Проекты

CRM модули

Прокрутите вниз
На главную

Модуль для CRM

Технические условия для создания модулей. Прежде чем создавать модуль, ознакомьтесь с условиями:

ТЕЛКОМ разработчик
РАЗРАБОТЧИКАМ И ПРОГРАММИСТАМ

Технические условия
Разработка модуля CRM

TELCOM CRM имеет встроенную функцию создания модулей и интеграции дополнительных функций вместе с основными функциями TELCOM CRM.

Модули могут состоять из перехватчиков действий, фильтров, контроллеров, моделей, библиотек, языков, представлений, файлов конфигурации, помощников, а также могут иметь доступ к базовому коду TELCOM CRM.

Вот демо-модуль для большего понимания. Чтобы установить модуль, скачайте образец модуля.

Образец модуля
01.

Модули CRM TELCOM — это пакеты кода, которые поддерживают форму модульности кода, для расширения основных функций CRM.

Прежде чем создавать модуль, ознакомьтесь с условиями:

Обслуживание модулей: вы несете ответственность за поддержку разрабатываемых вами модулей. Когда в TELCOM CRM произойдут серьезные изменения , ваша задача — сделать их совместимыми с последней версией.

Безопасность модулей: При создании модулей убедитесь, что они полностью защищены, и используйте существующие функции и методы, существующие в PHP-фреймворке Codeigniter.

Наша поддержка вашего модуля: Мы не будем предлагать вам поддержку по созданию модулей. Если вам кажется, что что-то работает не так в CRM или это ошибка, отправьте эл. письмо в службу тех. поддержки. Мы проверим и исправим ошибки в будущих обновлениях CRM.

Продажа модулей в маркете TELCOM. Если вы хотите создавать модули и продавать их как автор на маркете TELCOM, вы можете это сделать абсолютно свободно. Но имейте в виду, что из-за нашего соглашения об эксклюзивности вы можете продавать модули только исключительно на маркете TELCOM. Вы можете быть как физ. лицо или юр. лицо. Публикация модуля под вашим аккаунтом в маркете TELCOM означает, что вы владеете всеми авторскими правами на модуль и код.

— Создайте модуль с уникальным именем папки.
— Создайте файл index.php в корневом каталоге папки модуля.
— Добавьте метаданные в файл index.php, как показано ниже:
<?php
//Prevent direct access
defined(‘PLUGINPATH’) or exit(‘No direct script access allowed’);
/*
Plugin Name: Your Module  Name
Plugin URL: https://telcom.pro/product-category/your_item
Description: Your module description
Version: 1.0
Requires at least: 3.6
Author: Author name
Author URL: https:// telcom.pro/user/author_url
*/
Примечание. Метаданные необходимо добавлять только в файл index.php.
Это индексируется в TELCOM CRM. Откройте «Настройки» > «Модули». Там вы можете установить и активировать этот модуль.
Вы также можете создать ZIP-файл с папкой вашего модуля и установить его из «Настройки» > «Модули».

Посетите официальную документацию CodeIgniter ( https://www.codeigniter.com/ ) для получения дополнительной информации.

Маршруты / Routes:

Укажите маршруты для обнаружения модуля в CRM.
<?php
namespace Config;
$routes = Services::routes();
$routes->get(‘my_plugin’, ‘My_Plugin::index’, [‘namespace’ => ‘My_Plugin\Controllers’]);
$routes->get(‘my_plugin/(:any)’, ‘My_Plugin::$1’, [‘namespace’ => ‘My_Plugin\Controllers’]);
$routes->post(‘my_plugin/(:any)’, ‘My_Plugin::$1’, [‘namespace’ => ‘My_Plugin\Controllers’]); //will be required if any data need to be posted

Контроллеры / Controllers:

<?php
namespace My_Plugin\Controllers;
use App\Controllers\Security_Controller; //access main app’s controller
class My_Plugin extends Security_Controller {
//your methods
}

Модели / Models:

<?php
namespace My_Plugin\Controllers;
use App\Models\Crud_model; //access main app’s models
class My_Plugin_Model extends Crud_model {
//your methods
}

Вызов модели / Calling the model:

$My_Plugin_Model = new \My_Plugin\Models\My_Plugin_Model();

Библиотеки / Libraries:

<?php
namespace My_Plugin\Libraries;
class My_Plugin_Library {
//your methods
}

Вызов библиотеки / Calling the library:

$my_plugin_library = new \My_Plugin\Libraries\My_Plugin_Library();

Языки / Languages:

Используйте тот же дизайн каталога для языков. Например: My_Plugin/Language/english/custom_lang.php и default_lang.php. Не забудьте добавить уникальный префикс к вашему языковому ключу. Вот пример:
?php
$lang[«my_plugin_show_staff_members»] = «Show staff members»;
Затем вы можете использовать CRM app_lang(«my_plugin_show_staff_members»); для получения значения языка. Добавьте все языковые каталоги, как в CRM, если вы хотите поддерживать все языки для вашего модуля.

Просмотры / Views:

$view_data[‘foo’] = «bar»;
//$this->template->rander() функция по умолчанию покажет вид с левым меню и верхней панелью.
return $this->template->rander(‘My_Plugin\Views\folder\index’, $view_data);
//$this->template->view() функция покажет только вид, но здесь вы получите информацию о пользователе для входа в систему в виде $login_user переменная, если существует какой-либо пользователь для входа в систему
return $this->template->view(‘My_Plugin\Views\folder\index’, $view_data);
//default view() function of CI
return view(‘My_Plugin\Views\folder\index’, $view_data);

Помощники / Helpers:

Добавьте вспомогательный файл в папку My_Plugin/Helpers (например, my_plugin_general_helper.php) и вызовите его следующим образом:
helper(«my_plugin_general_helper»);
ThirdParty : Загрузите сторонний файл следующим образом:
require_once(PLUGINPATH . «My_Plugin/ThirdParty/library_folder/vendor/autoload.php»);

Загрузка ресурсов / Loading assets:

<link rel=’stylesheet’ type=’text/css’ href='» . base_url(PLUGIN_URL_PATH . «My_Plugin/assets/css/my_plugin_styles.css») . «‘ />

Управление файлами / File management:

Следуйте тому же рабочему процессу, что и сейчас для управления файлами. Только измените целевой каталог на этот:
PLUGIN_URL_PATH. «My_Plugin/files/my_plugin_files/»

Вызовите эти функции в папке My_Plugin/файле index.php.

Зарегистрируйте установочный веб-хук.

Когда модуль собираются установить, эта функция будет активирована. Выполните необходимые запросы sql или проверить ключ лицензии здесь.
register_installation_hook(«My_Plugin», function ($item_purchase_code) {
//validate purchase code if you wish
if (!validate_purchase_code($item_purchase_code)) {
echo json_encode(array(«success» => false, ‘message’ => «Invalid purchase code»));
exit();
}
//run necessary sql queries
$db = db_connect(‘default’);
$db_prefix = get_db_prefix();
$db->query(«SET sql_mode = »»);
$db->query(«CREATE TABLE IF NOT EXISTS `» . $db_prefix . «plugin_table` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` TEXT CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL ,
`deleted` tinyint(1) NOT NULL DEFAULT ‘0’,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ;»);
});

Зарегистрируйте веб-хук удаления.

Когда модуль собираются удалить, эта функция будет активирована.
register_uninstallation_hook(«My_Plugin», function () {
//run something
});
Зарегистрируйте веб-хук активации. Когда модуль собираются активироваться, эта функция будет активирована.
register_activation_hook(«My_Plugin», function () {
//run something
});

Зарегистрируйте веб-хук деактивации.

Когда модуль собираются деактивироваться, эта функция будет активирована.
register_deactivation_hook(«My_Plugin», function () {
//run something
});

Зарегистрируйте веб-хук обновления.

Предоставьте информацию для обновления вашего модуля. Обратите внимание: если ваши обновления имеют какую-либо сопоставимость версий, проверьте это при обновлении.
register_update_hook(«My_Plugin», function () {
//show necessary information to update this plugin in the modal
});

Зарегистрируйте веб-хук вставки данных.

register_data_insert_hook(function ($data) {
//some data has been inserted
/*
the $data array has 3 items
id => inserted id
table => associated table with db prefix
table_without_prefix => associated table without db prefix
data => inserted data array
*/
});

Зарегистрируйте веб-хук обновления данных.

register_data_update_hook(function ($data) {
//some data has been updated
/*
the $data array has 3 items
id => updated id
table => associated table with db prefix
table_without_prefix => associated table without db prefix
*/
});

Зарегистрируйте веб-хук удаления данных.

register_data_delete_hook(function ($data) {
//some data has been deleted
/*
the $data array has 2 items
id => deleted id
table => associated table with db prefix
table_without_prefix => associated table without db prefix
*/
});

Вызовите эти веб-хуки в папке My_Plugin/файле index.php.

Внимание: когда вы используете функцию-перехватчик add_filter, всегда возвращайте первый параметр с его изменением или без его изменения в соответствии с потребностями.

Добавьте URL-адрес в CSRF, исключив URIS.
app_hooks()->add_filter(‘app_filter_app_csrf_exclude_uris’, function ($app_csrf_exclude_uris) {
if (!in_array(«plugin_controller.*+», $app_csrf_exclude_uris)) {
array_push($app_csrf_exclude_uris, «plugin_controller.*+»);
}

return $app_csrf_exclude_uris;
});

Выполните сценарий после запуска задания cron.
app_hooks()->add_action(‘app_hook_after_cron_run’, function() {
//run something
});

Добавьте виджет на дашборд.
app_hooks()->add_filter(‘app_filter_dashboard_widgets’, function ($default_widgets_array) {
array_push($default_widgets_array, array(
«widget» => «widget_name»,
«widget_view» => view(«My_Plugin\Views\widget»)
));

return $default_widgets_array;
});

Добавьте несколько ссылок на действия «Настройки» > «Модули таблицы».
app_hooks()->add_filter(‘app_filter_action_links_of_My_Plugin’, function ($action_links_array) {
$action_links_array = array(
anchor(get_uri(«my_plugin/settings»), «Settings»),
anchor(get_uri(«my_plugin/get_support»), «Supports»)
);

return $action_links_array;
});

Пользователь успешно вошел в систему/вошел пользователь, который собирается получить доступ в CRM. Это состояние права до этого.
app_hooks()->add_action(‘app_hook_before_app_access’, function ($data) {
$login_user_id = get_array_value($data, «login_user_id»); //logged in user id if it’s valid login
$redirect = get_array_value($data, «redirect»); //either it’ll redirect to signin page or not if there has invalid login

//perform something before accessing to the main app
});

Добавьте пункт меню для сотрудников.
app_hooks()->add_filter(‘app_filter_staff_left_menu’, function ($sidebar_menu) {
$sidebar_menu[«left_menu_item»] = array(
«name» => «item_name»,
«url» => «my_plugin/url»,
«class» => «feather-icon-class», //like book
«position» => 5 //will be on the position after 4th item
);

return $sidebar_menu;
});

Добавьте пункт меню для пользователей клиента.
app_hooks()->add_filter(‘app_filter_client_left_menu’, function ($sidebar_menu) {
$sidebar_menu[«left_menu_item»] = array(
«name» => «item_name»,
«url» => «my_plugin/url»,
«class» => «feather-icon-class», //like book
«position» => 5 //will be on the position after 4th item
);

return $sidebar_menu;
});

Создано новое уведомление. Сделайте что-нибудь после этого.
app_hooks()->add_action(‘app_hook_post_notification’, function ($notification_id) {
//do something
});

Создание уведомлений. Сначала добавьте настройку уведомления в таблицу Notification_settings при установке модуля.

Примечание. После деактивации вашего модуля настройки уведомлений по-прежнему будут отображаться в настройках уведомлений. По этой причине используйте register_deactivation_hook() и установите delete=1 и Register_activation_hook(), чтобы снова отменить его с помощью delete=0.
INSERT INTO `notification_settings` (`event`, `category`, `enable_email`, `enable_web`, `notify_to_team`, `notify_to_team_members`, `notify_to_terms`, `deleted`) VALUES
(‘your_notification_key’, ‘your_category’, 0, 0, », », », 0);

Также добавьте необходимое поле идентификатора в таблицу уведомлений.

Примечание. Добавьте префикс (plugin_) в свое поле и обратите внимание, что после деактивации вашего плагина уведомления по-прежнему будут отображаться в области уведомлений пользователя. По этой причине используйте register_deactivation_hook() и установите delete=1 и Register_activation_hook(), чтобы снова отменить его с помощью delete=0.

ALTER TABLE `notifications` ADD `plugin_your_item_id` INT(11) NOT NULL AFTER `deleted`;

Добавьте веб-хук категории настроек уведомлений.
app_hooks()->add_filter(‘app_filter_notification_category_suggestion’, function ($category_suggestions) {
$category_suggestions[] = array(«id» => «your_category», «text» => app_lang(«your_category»));

return $category_suggestions;
});

Добавьте веб-хук конфигурации уведомлений.
app_hooks()->add_filter(‘app_filter_notification_config’, function ($events_of_hook) {
$notification_link = function () {
return array(«url» => get_uri(«notification_link»));
};

$events_of_hook[«your_notification_key»] = array( //check …app/Helpers/notifications_helper.php > function get_notification_config() for better ideas
«notify_to» => array(«recipient»), //check available values below
«info» => $notification_link
);

return $events_of_hook;
});

Поддерживаемый массив notify_to:

array(«team_members», «team», «project_members», «client_primary_contact», «client_all_contacts», «task_assignee», «task_collaborators», «comment_creator», «cusomer_feedback_creator», «leave_applicant», «ticket_creator», «ticket_assignee», «estimate_request_assignee», «recipient», «mentioned_members», «owner», «client_assigned_contacts», «post_creator», «order_creator_contact»);

Подготовьте запрос на получение пользователей notify_to:

app_hooks()->add_filter(‘app_filter_create_notification_where_query’, function ($where_queries_from_hook, $data) {
//prepare WHERE query and return
//check …app/Models/Notifications_model.php > function create_notification() for better ideas

/*
Переменная $data имеет следующие ключевые значения:
«event» => Event key (your_notification_key).
«user_id» => Which user created the notification. If it’s 0, then it’s created by the app.
«options» => It contains another array of available notification item ids. Check …app/Models/Notifications_model.php > function create_notification() for better ideas.
«notify_to_terms» => Notify to terms array as selected in notification setting for this event. Like array(«team_members», «team», «project_members»).
*/

$where_queries_from_hook[] = «YOUR QUERIES»;
return $where_queries_from_hook;
});

Если вы хотите отображать дополнительную информацию вместе с уведомлением, вам придется добавить этот веб-хук:

//for web
app_hooks()->add_filter(‘app_filter_notification_description’, function ($notification_descriptions, $notification) {
$notification_descriptions[] = view(«your_notification_description», array(«notification» => $notification)), //check …app/Views/notifications/notification_description.php
return $notification_descriptions;
});

//for slack

app_hooks()->add_filter(‘app_filter_notification_description_for_slack’, function ($notification_descriptions, $notification) {
$notification_descriptions[] = view(«your_notification_description_for_slack», array(«notification» => $notification)) //check …app/Views/notifications/notification_description_for_slack.php
return $notification_descriptions;
});

Добавьте шаблоны электронной почты.
app_hooks()->add_filter(‘app_filter_email_templates’, function ($templates_array) {
$templates_array[«account»][«your_email_template»] = array(«USER_FIRST_NAME», «USER_LAST_NAME», «LOGO_URL», «SIGNATURE», «OR_ANY_VARIABLE_YOU_WANT_TO_ADD»);

return $templates_array;
});

Для этого также необходимо добавить этот шаблон электронной почты в таблицу email_templates при установке модуля.

INSERT INTO `email_templates` (`template_name`, `email_subject`, `default_message`, `custom_message`, `deleted`) VALUES (‘your_email_template’, ‘Email subject’, ‘CONTENT OF YOUR EMAIL TEMPLATE’, », ‘0’);

Настройте уведомление по электронной почте.

app_hooks()->add_filter(‘app_filter_send_email_notification’, function ($data) {
//available values in $data
//check …/app/Helpers/notifications_helper.php > function send_notification_emails() for better ideas
$notification_info = get_array_value($data, «notification»);
$parser_data = get_array_value($data, «parser_data»);
$user_language = get_array_value($data, «user_language»);

//check if it’s your plugin’s notification otherwise it’ll send for all notifications
if ($notification->event !== «your_notification_key») {
return $data;
}

$Email_templates_model = model(«App\Models\Email_templates_model»);
$email_template = $Email_templates_model->get_final_template(«your_email_template», true);

$parser_data[«ANY_VARIABLE»] = «value»;

$parser = \Config\Services::parser();
$message = get_array_value($email_template, «message_$user_language») ? get_array_value($email_template, «message_$user_language») : get_array_value($email_template, «message_default»);
$subject = get_array_value($email_template, «subject_$user_language») ? get_array_value($email_template, «subject_$user_language») : get_array_value($email_template, «subject_default»);
$message = $parser->setData($parser_data)->renderString($message); //modify email message
$subject = $parser->setData($parser_data)->renderString($subject); //modify email subject

//add attachment
//showing demo of sending an invoice pdf
$invoice_data = get_invoice_making_data(invoice_id);
$attachement_url = prepare_invoice_pdf($invoice_data, «send_email»);
$email_options[«attachments»] = array(array(«file_path» => $attachement_url));

$info_array = array(
«subject» => $subject,
«message» => $message,
«email_options» => $email_options,
«attachement_url» => $attachement_url,
);

return $info_array;
});

Добавьте способ оплаты в таблице «Настройки» > «Способы оплаты».
app_hooks()->add_filter(‘app_filter_payment_method_settings’, function($settings) {
$settings[«payment_method_name»] = array(
array(«name» => «pay_button_text», «text» => app_lang(«pay_button_text»), «type» => «text», «default» => «Payment Method»), //required
array(«name» => «payment_method_setting_text», «text» => «Payment method setting (Text)», «type» => «text», «default» => «»),
array(«name» => «payment_method_setting_boolean», «text» => «Payment method setting (Boolean)», «type» => «boolean», «default» => «0»),
array(«name» => «payment_method_setting_readonly», «text» => «Payment method setting (Readonly)», «type» => «readonly», «default» => «This is the readonly value»),
);

return $settings;
});

Для этого также необходимо добавить этот метод оплаты в таблицу Payment_methods при установке модуля.

INSERT INTO `payment_methods` (`title`, `type`, `description`, `online_payable`, `available_on_invoice`, `minimum_payment_amount`, `settings`, `deleted`) VALUES (‘Payment method name’, ‘payment_method_name’, ‘Payment method description’, 1, 0, 0, », 0);

Note: On deactivation of a payment method plugin, the payment method will still be shown in payment method settings. Because of this, use register_deactivation_hook() and set deleted=1 and register_activation_hook() to revert it again by deleted=0.

Показывать активированные способы оплаты в представлении счета.

app_hooks()->add_action(‘app_hook_invoice_payment_extension’, function($payment_method_variables) {
if (get_array_value($payment_method_variables, «method_type») === «my_payment_method») {
echo view(«My_Payment_Method\Views\index», $payment_method_variables);
}
});

Массив $pay_method_variables() имеет следующие ключевые значения:

method_type: текущий тип способа оплаты из доступных активированных способов оплаты.
payment_method: массив информации о способе оплаты.
balance_due: общий остаток по счету.
currency: Валюта для этого счета.
invoice_info: информационный объект счета.
invoice_id: идентификатор текущего счета.
contact_user_id: для какого контакта с клиентом был предоставлен общий доступ к этому счету. (Эта переменная будет доступна для общедоступных счетов)
verification_code: код для проверки того, является ли это действительным общедоступным счетом. (Эта переменная будет доступна для общедоступных счетов)

Добавьте вкладку ajax в несколько мест.
//add ajax tab in staff profile
app_hooks()->add_filter(‘app_filter_staff_profile_ajax_tab’, function ($hook_tabs, $user_id) {
$hook_tabs[] = array(
«title» => app_lang(«tab_title»),
«url» => get_uri(«my_plugin/my_tab»),
«target» => «my-plugin-my-tab»
);

return $hook_tabs;
});

Доступные веб-хуки для добавления вкладок ajax:
app_hooks()->add_filter(‘app_filter_client_details_ajax_tab’, ‘function_to_add_tab’); //parameter: $hook_tabs, $client_id
app_hooks()->add_filter(‘app_filter_client_profile_ajax_tab’, ‘function_to_add_tab’); //parameter: $hook_tabs, $client_contact_id
app_hooks()->add_filter(‘app_filter_lead_details_ajax_tab’, ‘function_to_add_tab’); //parameter: $hook_tabs, $lead_id
app_hooks()->add_filter(‘app_filter_lead_profile_ajax_tab’, ‘function_to_add_tab’); //parameter: $hook_tabs, $lead_contact_id
app_hooks()->add_filter(‘app_filter_integration_settings_tab’, ‘function_to_add_tab’); //parameter: $hook_tabs

Добавьте элемент в настройки.
app_hooks()->add_filter(‘app_filter_admin_settings_menu’, function($settings_menu) {
$settings_menu[«setup»][] = array(«name» => «my_plugin_setting», «url» => «my_plugin/setting»);
return $settings_menu;
});

Покажите что-нибудь в режиме входа.
app_hooks()->add_action(‘app_hook_signin_extension’, function() {
//show something
});

Покажите что-нибудь в режиме регистрации.
app_hooks()->add_action(‘app_hook_signup_extension’, function() {
//show something
});

Покажите что-нибудь в основном представлении макета страницы пользователю, вошедшему в систему.
app_hooks()->add_action(‘app_hook_layout_main_view_extension’, function() {
//show something
});

Включите что-нибудь в тег заголовка.
app_hooks()->add_action(‘app_hook_head_extension’, function() {
//include something
});

Покажите что-нибудь в верхней части панели управления, например оповещения об объявлениях.
app_hooks()->add_action(‘app_hook_dashboard_announcement_extension’, function() {
//show something
});

Пользователь вошел в систему.
app_hooks()->add_action(‘app_hook_after_signin’, function() {
//do something
});

Пользователь выходит из системы.
app_hooks()->add_action(‘app_hook_before_signout’, function() {
//do something
});

Добавьте опцию в настройки роли.
Показать роль в блоке <li></li>. Проверьте файл …/app/Views/roles/permissions.php, чтобы найти лучшие идеи. Вы получите значение разрешения с помощью ключа массива следующим образом: $your_permission = get_array_value($permissions, «your_permission»);
app_hooks()->add_action(‘app_hook_role_permissions_extension’, function () {
//show a role setting
});
Сохраните настройку роли.
app_hooks()->add_filter(‘app_filter_role_permissions_save_data’, function ($permissions) {
$request = \Config\Services::request();
$permissions[«your_permission»] = $request->getPost(‘your_permission’);

return $permissions;
});

Покажите что-нибудь на правой панели представления задач.
app_hooks()->add_action(‘app_hook_task_view_right_panel_extension’, function() {
//show something
});

Добавьте настройки в нескольких местах.

Добавить опцию в общих настройках.
app_hooks()->add_action(‘app_hook_general_settings_extension’, ‘function_to_add_setting’);
app_hooks()->add_action(‘app_hook_general_settings_save_data’, ‘function_to_save_setting’);

Добавьте опцию в настройки разрешений клиента.
app_hooks()->add_action(‘app_hook_client_permissions_extension’, ‘function_to_add_setting’);
app_hooks()->add_action(‘app_hook_client_permissions_save_data’, ‘function_to_save_setting’);

Добавьте опцию в настройки моих предпочтений участника команды.
app_hooks()->add_action(‘app_hook_team_members_my_preferences_extension’, ‘function_to_add_setting’);
app_hooks()->add_action(‘app_hook_team_members_my_preferences_save_data’, ‘function_to_save_setting’);

Добавьте опцию в настройки моих предпочтений клиента.
app_hooks()->add_action(‘app_hook_clients_my_preferences_extension’, ‘function_to_add_setting’);
app_hooks()->add_action(‘app_hook_clients_my_preferences_save_data’, ‘function_to_save_setting’);

Пример:

Показать опцию в общих настройках:

app_hooks()->add_action(‘app_hook_general_settings_extension’, function() {
//show settings
//show a setting block (<div class=»form-group»>)
//check …/app/Views/settings/general.php for better ideas
echo view(«My_Plugin\Views\setting»);
});

Сохранить настройку:

app_hooks()->add_action(‘app_hook_general_settings_save_data’, function () {
$request = \Config\Services::request();
$your_setting_value = $request->getPost(«your_setting»);

$Settings_model = model(«App\Models\Settings_model»);
$Settings_model->save_setting(«your_setting», $your_setting_value);
});

Добавьте вкладку ajax на страницу сведений о проекте.
app_hooks()->add_filter(‘app_filter_team_members_project_details_tab’, function ($project_tabs_of_hook_of_staff, $project_id = 0) {
$project_tabs_of_hook_of_staff[«my_tab_title_with_available_language_key_value»] = «my_plugin/my_tab_url»;
$project_tabs_of_hook_of_staff[«my_tab_another_title_with_available_language_key_value»] = «my_plugin/my_another_tab_url»;

return $project_tabs_of_hook_of_staff;
});

//available filter for clients

app_hooks()->add_filter(‘app_filter_clients_project_details_tab’, ‘function_to_add_tab’); //parameter: $project_tabs_of_hook_of_staff, $project_id

Добавьте индивидуальную интеграцию хранилища.

1. Сначала определите константу PLUGIN_CUSTOM_STORAGE для события pre_system.

Events::on(‘pre_system’, function () {
if (!defined(‘PLUGIN_CUSTOM_STORAGE’)) {
define(‘PLUGIN_CUSTOM_STORAGE’, TRUE);
}
});

2. При загрузке файла сначала загрузите его во временный каталог.

app_hooks()->add_action(‘app_hook_upload_file_to_temp’, function ($data) {
$temp_file = get_array_value($data, «temp_file»);
$file_name = get_array_value($data, «file_name»);

\Your_Storage_Integration\Libraries\Your_Storage_Integration::upload_file_to_temp($temp_file, $file_name);
//check upload_file_to_temp() function on …/app/Helpers/app_files_helper.php for better ideas
});

3. Переместите временный файл в постоянный каталог.

app_hooks()->add_filter(‘app_filter_move_temp_file’, function ($data) {
$related_to = get_array_value($data, «related_to»);
$file_name = get_array_value($data, «file_name»);
$new_filename = get_array_value($data, «new_filename»);
$file_content = get_array_value($data, «file_content»);
$source_path = get_array_value($data, «source_path»);
$target_path = get_array_value($data, «target_path»);
$direct_upload = get_array_value($data, «direct_upload»);

$files_data = \Your_Storage_Integration\Libraries\Your_Storage_Integration::move_temp_file($file_name, $new_filename); //use necessary parameters
//check move_temp_file() function on …/app/Helpers/app_files_helper.php for better ideas

return $files_data;
});

4. Загрузите файл, получив его содержимое.

app_hooks()->add_filter(‘app_filter_get_file_content’, function ($data) {
$file_info = get_array_value($data, «file_info»);

$file_id = get_array_value($file_info, «file_id»);
//you can use any key here instead of file_id which is needed to download the content
//but you should pass that key and value on app_filter_move_temp_file hook (on returning $files_data array)
//check download_app_files() function on …/app/Controllers/App_Controller.php for better ideas

return \Your_Storage_Integration\Libraries\Your_Storage_Integration::get_file_content($file_id);
});

5. Получите исходный URL-адрес файла для предварительного просмотра.

app_hooks()->add_filter(‘app_filter_get_source_url_of_file’, function ($data) {
//check get_source_url_of_file() function on …/app/Helpers/app_files_helper.php for better ideas
$file_info = get_array_value($data, «file_info»);

$file_id = get_array_value($file_info, «file_id»);
return \Your_Storage_Integration\Libraries\Your_Storage_Integration::get_source_url_of_file($file_id);
});

6. Удалить файл.

app_hooks()->add_action(‘app_hook_delete_app_file’, function ($file_info) {
//check delete_app_files() function on …/app/Helpers/app_files_helper.php for better ideas
$file_id = get_array_value($file_info, «file_id»);
\Your_Storage_Integration\Libraries\Your_Storage_Integration::delete_file($file_id);
});

7. Обработка вставленных изображений из контента.

app_hooks()->add_filter(‘app_filter_process_images_from_content’, function ($content) {
//sometimes you may need to update the source url of pasted images in rich text editor
return $updated_content;
}

Добавьте папку в массив допустимых папок Google Диска.
app_hooks()->add_filter(‘app_filter_add_folder_to_google_drive_valid_folders_array’, function ($folders_array) {
if (!in_array(«your_folder», $folders_array)) {
array_push($folders_array, «your_folder»);
}
return $folders_array;
});

Пожалуйста, следуйте этим рекомендациям при разработке плагина:

— Всегда добавляйте префикс к именам функций, именам классов и таблицам базы данных.
— Не загружайте ресурсы плагинов (например, CSS/JS) повсюду. Загружайте его только там, где это необходимо.
— Не вставляйте ничего в таблицу настроек для вашего плагина. Создайте свою собственную таблицу для хранения собственных настроек. Но вы всегда можете получить данные таблицы настроек.
— Чтобы запретить отображение списка каталогов, добавьте файл index.html во все подпапки вашего плагина. Вы можете использовать этот код:

<html>
<head>
<title>403 Forbidden</title>
</head>
<body>
<p>Directory access is forbidden.</p>
</body>
</html>