소스 검색

Ticket #4711 - Providers for Automations.

AntonLV 2 년 전
부모
커밋
fc22dc58bd

+ 93 - 0
inc/classes/BxDolAIProvider.php

@@ -0,0 +1,93 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    UnaCore UNA Core
+ * @{
+ */
+
+class BxDolAIProvider extends BxDol
+{
+    protected $_iId;
+    protected $_sName;
+    protected $_sCaption;
+    protected $_sPrefix;
+    protected $_aOptions;
+
+    public function __construct($aProvider)
+    {
+        parent::__construct();
+
+        if(empty($aProvider) || !is_array($aProvider) || strcmp($aProvider['name'], $this->_sName) != 0)
+            $this->_log("Unexpected value provided for the credentials");
+
+        $this->_oDb = new BxDolAIQuery();
+
+        $this->_iId = (int)$aProvider['id'];
+        $this->_sName = $aProvider['name'];
+        $this->_sCaption = _t($aProvider['caption']);
+        $this->_sPrefix = $aProvider['option_prefix'];
+
+        $this->_aOptions = [];
+        if(!empty($aProvider['options']) && is_array($aProvider['options']))
+            $this->initOptions($aProvider['options']);
+    }
+
+    /**
+     * Get provider object instance by provider ID
+     * @param $sProvider provider name
+     * @return object instance or false on error
+     */
+    public static function getObjectInstance($iId)
+    {
+        $sPrefix = 'BxDolAIProvider!';
+
+        if(isset($GLOBALS['bxDolClasses'][$sPrefix . $iId]))
+            return $GLOBALS['bxDolClasses'][$sPrefix . $iId];
+
+        $aProvider = BxDolAIQuery::getProviderObject($iId);
+        if (!$aProvider || !is_array($aProvider))
+            return false;
+
+        $sClass = 'BxDolAIProvider';
+        if(!empty($aObject['class_name'])) {
+            $sClass = $aObject['class_name'];
+            if(!empty($aObject['class_file']))
+                require_once(BX_DIRECTORY_PATH_ROOT . $aObject['class_file']);
+        }
+
+        $o = new $sClass($aProvider);
+        return ($GLOBALS['bxDolClasses'][$sPrefix . $sObject] = $o);
+    }
+
+    public function initOptions($aOptions)
+    {
+    	$this->_aOptions = $aOptions;
+    }
+
+    public function getOption($sName)
+    {
+    	if(substr($sName, 0, strlen($this->_sPrefix)) != $this->_sPrefix)
+            $sName = $this->_sPrefix . $sName;
+
+        return isset($this->_aOptions[$sName]) ? $this->_aOptions[$sName]['value'] : '';
+    }
+
+    /**
+     * Internal methods.
+     */
+    protected function _call($sRequest, $aParams, $sMethod = 'post-json', $aHeaders = [])
+    {}
+
+    protected function _log($sMessage, $bUseLog = false)
+    {
+        if($bUseLog) {
+            //TODO: Use bx_log here.
+        }
+        else
+            throw new Exception($sMessage);
+
+        return false;
+    }    
+}

+ 90 - 0
inc/classes/BxDolAIProviderShopifyAdmin.php

@@ -0,0 +1,90 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    UnaCore UNA Core
+ * @{
+ */
+
+/*
+ * Login for Owner/Collaborator account:
+ * https://admin.shopify.com/store/your_shop/
+ * 
+ * Integration:
+ * 0. Custom apps creation guide (for a shop Owner/Collaborator, not a Partner):
+ * https://help.shopify.com/en/manual/apps/app-types/custom-apps
+ * 
+ * 1. Make authenticated requests to the REST Admin API:
+ * https://shopify.dev/docs/apps/auth/admin-app-access-tokens
+ * 
+ * 2. REST Admin API reference:
+ * https://shopify.dev/docs/api/admin-rest
+ * 
+ * 3. REST Admin API -> Product
+ * https://shopify.dev/docs/api/admin-rest/2023-10/resources/product
+ * 
+ * 4. REST Admin API -> Order
+ * https://shopify.dev/docs/api/admin-rest/2023-10/resources/order
+ * 
+ */
+class BxDolAIProviderShopifyAdmin extends BxDolAIProvider
+{
+    public static $NAME = 'shopify_admin';
+
+    protected $_sShopDomain;
+    protected $_sAccessToken;
+
+    protected $_sEndpoint;
+    protected $_sStorefront;
+
+    public function __construct($iProfile, $aSource)
+    {
+        $this->_sName = self::$NAME;
+
+        parent::__construct($iProfile, $aSource);
+
+        $this->_sShopDomain = $this->getOption('shop_domain');
+        $this->_sAccessToken = $this->getOption('access_token');
+
+        $this->_sEndpoint = "https://{$this->_sShopDomain}/admin/api/2023-10/";
+        $this->_sStorefront = "https://{$this->_sShopDomain}/";
+    }
+
+    public function getEntry($sId)
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        $sProduct = $this->_call('products/' . $sId . '.json', [
+            'fields' => 'id,title,handle,body_html,tags,variants',
+        ], 'get');
+        
+        if(empty($sProduct))
+            return [];
+
+        $aProduct = json_decode($sProduct, true);
+        if(empty($aProduct) || !is_array($aProduct) || empty($aProduct['product']))
+            return [];
+
+        return $aProduct['product'];
+    }
+
+    /**
+     * Internal methods.
+     */
+    protected function _call($sRequest, $aParams, $sMethod = 'post-json', $aHeaders = [])
+    {
+        $aHeaders[] = 'Content-Type: application/json';
+        if(!empty($this->_sAccessToken))
+            $aHeaders[] = 'X-Shopify-Access-Token: ' . $this->_sAccessToken;
+        else
+            $aHeaders[] = 'Authorization: Basic ' . base64_encode($this->_sApiKey . ':' . $this->_sApiSecretKey);
+
+        return bx_file_get_contents($this->_sEndpoint . $sRequest, $aParams, $sMethod, $aHeaders);
+    }
+    
+    protected function _dateI2S($iTimestamp)
+    {
+        return date("Y-m-d", $iTimestamp);
+    }
+}

+ 223 - 0
inc/classes/BxDolAIQuery.php

@@ -14,6 +14,36 @@ class BxDolAIQuery extends BxDolDb
         parent::__construct();
     }
 
+    static public function getProviderObject($iId)
+    {
+        $oDb = BxDolDb::getInstance();
+
+        $aProvider = $oDb->getRow("SELECT * FROM `sys_agents_providers` WHERE `id` = :id", ['id' => $iId]);
+        if(!$aProvider || !is_array($aProvider))
+            return false;
+
+        // get type
+        $aProviderType = $oDb->getRow("SELECT * FROM `sys_agents_provider_types` WHERE `id` = :id", ['id' => $aProvider['type_id']]);
+        if(!$aProviderType || !is_array($aProviderType))
+            return false;
+
+        $aProvider['type'] = $aProviderType;
+
+        // get options
+        $sQuery = "SELECT
+               `tpo`.`name` AS `name`,
+               `tpv`.`value` AS `value`
+            FROM `sys_agents_provider_options` AS `tpo`
+            LEFT JOIN `sys_agents_providers_values` AS `tpv` ON `tpo`.`id` = `tpv`.`option_id` AND `tpv`.`provider_id` = :provider_id
+            WHERE 1 ORDER BY `tpo`.`order`";
+
+        $aProvider['options'] = $this->getAllWithKey($sQuery, 'name', [
+            'provider_id' => $iId
+        ]);
+
+        return $aProvider;
+    }
+
     public function getModelsBy($aParams = [])
     {
         $aMethod = ['name' => 'getAll', 'params' => [0 => 'query']];
@@ -108,6 +138,19 @@ class BxDolAIQuery extends BxDolDb
                     $sWhereClause .= " AND `taa`.`active`=:active";
                 }
                 break;
+
+            case 'providers_by_id_pairs':
+                $aMethod['name'] = 'getPairs';
+                $aMethod['params'][1] = 'id';
+                $aMethod['params'][2] = 'provider_id';
+                $aMethod['params'][3] = [
+                    'id' => $aParams['id']
+                ];
+
+                $sSelectClause = "`tap`.`id`, `tap`.`provider_id`";
+                $sJoinClause = "INNER JOIN `sys_agents_automators_providers` AS `tap` ON `taa`.`id`=`tap`.`automator_id`";
+                $sWhereClause = " AND `taa`.`id`=:id";
+                break;
         }
 
         $aMethod['params'][0] = "SELECT " . $sSelectClause . "
@@ -124,7 +167,187 @@ class BxDolAIQuery extends BxDolDb
 
         return (int)$this->query("UPDATE `sys_agents_automators` SET " . $this->arrayToSQL($aSetClause) . " WHERE " . $this->arrayToSQL($aWhereClause)) > 0;
     }
+
+    public function insertAutomatorProvider($aParamsSet)
+    {
+        if(empty($aParamsSet))
+            return false;
+
+        return (int)$this->query("INSERT INTO `sys_agents_automators_providers` SET " . $this->arrayToSQL($aParamsSet)) > 0 ? (int)$this->lastId() : false;
+    }
+
+    public function updateAutomatorProvider($aParamsSet, $aParamsWhere)
+    {
+        if(empty($aParamsSet) || empty($aParamsWhere))
+            return false;
+
+        return $this->query("UPDATE `sys_agents_automators_providers` SET " . $this->arrayToSQL($aParamsSet) . " WHERE " . $this->arrayToSQL($aParamsWhere, " AND "));
+    }
+
+    public function deleteAutomatorProviders($aParamsWhere)
+    {
+        if(empty($aParamsWhere))
+            return false;
+
+        return (int)$this->query("DELETE FROM `sys_agents_automators_providers` WHERE " . $this->arrayToSQL($aParamsWhere)) > 0;
+    }
     
+    public function deleteAutomatorProvidersById($mixedId)
+    {
+        if(!is_array($mixedId))
+            $mixedId = [$mixedId];
+
+        return (int)$this->query("DELETE FROM `sys_agents_automators_providers` WHERE `id` IN (" . $this->implode_escape($mixedId) . ")") > 0;
+    }
+
+    public function getProviderTypesBy($aParams = [])
+    {
+        $aMethod = ['name' => 'getAll', 'params' => [0 => 'query']];
+    	$sWhereClause = "";
+
+        switch($aParams['sample']) {
+            case 'id':
+            	$aMethod['name'] = 'getRow';
+            	$aMethod['params'][1] = [
+                    'id' => $aParams['id']
+                ];
+
+                $sWhereClause .= " AND `id`=:id";
+                break;
+
+            case 'name':
+            	$aMethod['name'] = 'getRow';
+            	$aMethod['params'][1] = [
+                    'name' => $aParams['name']
+                ];
+
+                $sWhereClause .= " AND `name`=:name";
+                break;
+
+            case 'all_pairs':
+                $aMethod['name'] = 'getPairs';
+                $aMethod['params'][1] = 'id';
+                $aMethod['params'][2] = 'title';
+                break;
+        }
+
+        $aMethod['params'][0] = "SELECT * 
+            FROM `sys_agents_provider_types`
+            WHERE 1" . $sWhereClause;
+
+        return call_user_func_array([$this, $aMethod['name']], $aMethod['params']);
+    }
+
+    public function getProviderOptionsBy($aParams = [])
+    {
+        $aMethod = ['name' => 'getAll', 'params' => [0 => 'query']];
+    	$sWhereClause = "";
+
+        switch($aParams['sample']) {
+            case 'id':
+            	$aMethod['name'] = 'getRow';
+            	$aMethod['params'][1] = [
+                    'id' => $aParams['id']
+                ];
+
+                $sWhereClause .= " AND `id`=:id";
+                break;
+
+            case 'provider_type_id':
+            	$aMethod['params'][1] = [
+                    'provider_type_id' => $aParams['provider_type_id']
+                ];
+
+                $sWhereClause .= " AND `provider_type_id`=:provider_type_id";
+                break;
+        }
+
+        $aMethod['params'][0] = "SELECT * 
+            FROM `sys_agents_provider_options`
+            WHERE 1" . $sWhereClause;
+
+        return call_user_func_array([$this, $aMethod['name']], $aMethod['params']);
+    }
+
+    public function getProviderBy($aParams = [])
+    {
+    	$aMethod = ['name' => 'getAll', 'params' => [0 => 'query']];
+
+    	$sSelectClause = "`tp`.*";
+    	$sJoinClause = $sWhereClause = $sGroupClause = $sOrderClause = $sLimitClause = "";
+        switch($aParams['sample']) {
+            case 'id':
+            	$aMethod['name'] = 'getRow';
+            	$aMethod['params'][1] = [
+                    'id' => $aParams['id']
+                ];
+
+                $sWhereClause = " AND `tp`.`id`=:id";
+                break;
+
+            case 'options_by_id':
+                $aMethod['params'][1] = [
+                    'id' => $aParams['id']
+                ];
+
+                $sSelectClause = "`tpo`.`id`, `tpo`.`name`, `tpo`.`type`, `tpo`.`title`, `tpo`.`description`, `tpv`.`value`";
+                $sJoinClause = "INNER JOIN `sys_agents_providers_values` AS `tpv` ON `tp`.`id`=`tpv`.`provider_id` INNER JOIN `sys_agents_provider_options` AS `tpo` ON `tpv`.`option_id`=`tpo`.`id`";
+                $sWhereClause = " AND `tp`.`id`=:id";
+                break;
+            
+            case 'all_pairs':
+                $aMethod['name'] = 'getPairs';
+                $aMethod['params'][1] = 'id';
+                $aMethod['params'][2] = 'title';
+
+                if(isset($aParams['active'])) {
+                    $aMethod['params'][3] = [
+                        'active' => $aParams['active']
+                    ];
+
+                    $sWhereClause = " AND `tp`.`active`=:active";
+                }
+                break;
+        }
+
+        $sOrderClause = !empty($sOrderClause) ? "ORDER BY " . $sOrderClause : $sOrderClause;
+        $sLimitClause = !empty($sLimitClause) ? "LIMIT " . $sLimitClause : $sLimitClause;
+
+        $aMethod['params'][0] = "SELECT
+                " . $sSelectClause . "
+            FROM `sys_agents_providers` AS `tp` " . $sJoinClause . "
+            WHERE 1" . $sWhereClause . " " . $sGroupClause . " " . $sOrderClause . " " . $sLimitClause;
+
+        return call_user_func_array(array($this, $aMethod['name']), $aMethod['params']);
+    }
+
+    public function insertProviderValue($aParamsSet)
+    {
+        if(empty($aParamsSet))
+            return false;
+
+        return (int)$this->query("INSERT INTO `sys_agents_providers_values` SET " . $this->arrayToSQL($aParamsSet)) > 0 ? (int)$this->lastId() : false;
+    }
+
+    public function updateProviderValue($aParamsSet, $aParamsWhere)
+    {
+        if(empty($aParamsSet))
+            return false;
+
+        $sWhereClause = "1";
+        if(!empty($aParamsWhere) && is_array($aParamsWhere))
+            $sWhereClause = $this->arrayToSQL($aParamsWhere, ' AND ');
+
+        return $this->query("UPDATE `sys_agents_providers_values` SET " . $this->arrayToSQL($aParamsSet) . " WHERE " . $sWhereClause) !== false;
+    }
+
+    public function deleteProviderValues($aParamsWhere)
+    {
+        if(empty($aParamsWhere))
+            return false;
+
+        return (int)$this->query("DELETE FROM `sys_agents_providers_values` WHERE " . $this->arrayToSQL($aParamsWhere, ' AND ')) > 0;
+    }
 }
 
 /** @} */

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 0 - 0
install/sql/system.sql


+ 28 - 1
modules/boonex/english/data/langs/system/en.xml

@@ -1138,6 +1138,7 @@
     <string name="_adm_lmi_cpt_origins"><![CDATA[Origins]]></string>
     <string name="_adm_lmi_cpt_pre_lists"><![CDATA[Data Lists]]></string>
     <string name="_adm_lmi_cpt_pre_values"><![CDATA[Data Items]]></string>
+    <string name="_adm_lmi_cpt_providers"><![CDATA[Providers]]></string>
     <string name="_adm_lmi_cpt_popular"><![CDATA[Popular]]></string>
     <string name="_adm_lmi_cpt_purchases"><![CDATA[Purchases]]></string>
     <string name="_adm_lmi_cpt_pwa"><![CDATA[PWA]]></string>
@@ -2156,14 +2157,40 @@
         <string name="_sys_agents_automators_field_alert_unit"><![CDATA[Event Type]]></string>
         <string name="_sys_agents_automators_field_alert_action"><![CDATA[Event Action]]></string>
         <string name="_sys_agents_automators_field_scheduler_time"><![CDATA[Scheduler Time]]></string>
+        <string name="_sys_agents_automators_field_providers"><![CDATA[Providers]]></string>
+        <string name="_sys_agents_automators_field_providers_add"><![CDATA[Add]]></string>
         <string name="_sys_agents_automators_field_message"><![CDATA[Prompt]]></string>
         <string name="_sys_agents_automators_field_status_auto"><![CDATA[Auto]]></string>
         <string name="_sys_agents_automators_field_status_manual"><![CDATA[Manual]]></string>
         <string name="_sys_agents_automators_field_status_ready"><![CDATA[Ready]]></string>
         <string name="_sys_agents_automators_err_event_not_found"><![CDATA[Event isn't found, please rephrase your prompt.]]></string>
         <string name="_sys_agents_automators_err_cannot_get_code"><![CDATA[Can't generate code, please rephrase your prompt.]]></string>
+        <string name="_sys_agents_providers_txt_active"><![CDATA[Active]]></string>
+        <string name="_sys_agents_providers_txt_provider_title"><![CDATA[Title]]></string>
+        <string name="_sys_agents_providers_txt_provider_type"><![CDATA[Type]]></string>
+        <string name="_sys_agents_providers_txt_added"><![CDATA[Added]]></string>
+        <string name="_sys_agents_providers_btn_add"><![CDATA[Add Provider]]></string>
+        <string name="_sys_agents_providers_btn_info"><![CDATA[Info]]></string>
+        <string name="_sys_agents_providers_btn_edit"><![CDATA[Edit]]></string>
+        <string name="_sys_agents_providers_btn_delete"><![CDATA[Delete]]></string>
+        <string name="_sys_agents_providers_popup_add"><![CDATA[Add provider]]></string>
+        <string name="_sys_agents_providers_popup_edit"><![CDATA[Edit provider]]></string>
+        <string name="_sys_agents_providers_popup_view"><![CDATA[View provider]]></string>
+        <string name="_sys_agents_providers_field_type_id"><![CDATA[Type]]></string>
+        <string name="_sys_agents_providers_field_type_id_err"><![CDATA[Type is essential. Please select a value.]]></string>
+        <string name="_sys_agents_providers_field_title"><![CDATA[Title]]></string>        
+        <string name="_sys_agents_pvd_cpt_shopify_admin"><![CDATA[Shopify (Admin API)]]></string>
+        <string name="_sys_agents_pvd_opt_cpt_active"><![CDATA[Active]]></string>
+        <string name="_sys_agents_pvd_opt_dsc_active"><![CDATA[Activate(Deactivate) source]]></string>
+        <string name="_sys_agents_pvd_opt_cpt_shop_domain"><![CDATA[Shop domain]]></string>
+        <string name="_sys_agents_pvd_opt_dsc_shop_domain"><![CDATA[]]></string>
+        <string name="_sys_agents_pvd_opt_cpt_access_token"><![CDATA[Access token]]></string>
+        <string name="_sys_agents_pvd_opt_dsc_access_token"><![CDATA[]]></string>
+        <string name=""><![CDATA[]]></string>
+        <string name=""><![CDATA[]]></string>
+        <string name=""><![CDATA[]]></string>
+        <string name=""><![CDATA[]]></string>
         <string name=""><![CDATA[]]></string>
-        
 
   <string name="_sys_audit_content_info_popup_title"><![CDATA[Information]]></string>
   <string name="_sys_audit_action_edit_content"><![CDATA[Content edited]]></string>

+ 24 - 0
modules/boonex/russian/data/langs/system/ru.xml

@@ -1121,6 +1121,7 @@
 	<string name="_adm_lmi_cpt_menus"><![CDATA[Меню]]></string>
 	<string name="_adm_lmi_cpt_pre_lists"><![CDATA[Списки данных]]></string>
 	<string name="_adm_lmi_cpt_pre_values"><![CDATA[Элементы данных]]></string>
+        <string name="_adm_lmi_cpt_providers"><![CDATA[Поставщики]]></string>
 	<string name="_adm_lmi_cpt_popular"><![CDATA[Популярные]]></string>
 	<string name="_adm_lmi_cpt_purchases"><![CDATA[Покупки]]></string>
         <string name="_adm_lmi_cpt_pwa"><![CDATA[PWA]]></string>
@@ -2132,12 +2133,35 @@
         <string name="_sys_agents_automators_field_alert_unit"><![CDATA[Тип события]]></string>
         <string name="_sys_agents_automators_field_alert_action"><![CDATA[Действие события]]></string>
         <string name="_sys_agents_automators_field_scheduler_time"><![CDATA[Время для планировщика]]></string>
+        <string name="_sys_agents_automators_field_providers"><![CDATA[Поставщики]]></string>
+        <string name="_sys_agents_automators_field_providers_add"><![CDATA[Добавить]]></string>
         <string name="_sys_agents_automators_field_message"><![CDATA[Инструкции]]></string>
         <string name="_sys_agents_automators_field_status_auto"><![CDATA[Авто]]></string>
         <string name="_sys_agents_automators_field_status_manual"><![CDATA[Ручной]]></string>
         <string name="_sys_agents_automators_field_status_ready"><![CDATA[Готовый]]></string>
         <string name="_sys_agents_automators_err_event_not_found"><![CDATA[Событие не найдено. Перефразируйте запрос.]]></string>
         <string name="_sys_agents_automators_err_cannot_get_code"><![CDATA[Невозможно сгенерировать код. Перефразируйте запрос.]]></string>
+        <string name="_sys_agents_providers_txt_active"><![CDATA[Активный]]></string>
+        <string name="_sys_agents_providers_txt_provider_title"><![CDATA[Название]]></string>
+        <string name="_sys_agents_providers_txt_provider_type"><![CDATA[Тип]]></string>
+        <string name="_sys_agents_providers_txt_added"><![CDATA[Добавлено]]></string>
+        <string name="_sys_agents_providers_btn_add"><![CDATA[Добавить]]></string>
+        <string name="_sys_agents_providers_btn_info"><![CDATA[Инфо]]></string>
+        <string name="_sys_agents_providers_btn_edit"><![CDATA[Редактировать]]></string>
+        <string name="_sys_agents_providers_btn_delete"><![CDATA[Удалить]]></string>
+        <string name="_sys_agents_providers_popup_add"><![CDATA[Добавить поставщика]]></string>
+        <string name="_sys_agents_providers_popup_edit"><![CDATA[Редактировать поставщика]]></string>
+        <string name="_sys_agents_providers_popup_view"><![CDATA[Посмотреть поставщика]]></string>
+        <string name="_sys_agents_providers_field_type_id"><![CDATA[Тип]]></string>
+        <string name="_sys_agents_providers_field_type_id_err"><![CDATA[Тип имеет важное значение. Пожалуйста, выберите значение.]]></string>
+        <string name="_sys_agents_providers_field_title"><![CDATA[Название]]></string>
+        <string name="_sys_agents_pvd_cpt_shopify_admin"><![CDATA[Shopify (Admin API)]]></string>
+        <string name="_sys_agents_pvd_opt_cpt_active"><![CDATA[Активировать]]></string>
+        <string name="_sys_agents_pvd_opt_dsc_active"><![CDATA[Активировать(деактивировать) источник.]]></string>
+        <string name="_sys_agents_pvd_opt_cpt_shop_domain"><![CDATA[Домен магазина]]></string>
+        <string name="_sys_agents_pvd_opt_dsc_shop_domain"><![CDATA[]]></string>
+        <string name="_sys_agents_pvd_opt_cpt_access_token"><![CDATA[Токен доступа]]></string>
+        <string name="_sys_agents_pvd_opt_dsc_access_token"><![CDATA[]]></string>
         <string name=""><![CDATA[]]></string>
         <string name=""><![CDATA[]]></string>
         <string name=""><![CDATA[]]></string>

+ 1 - 0
studio/classes/BxDolStudioAgents.php

@@ -9,6 +9,7 @@
 
 define('BX_DOL_STUDIO_AGENTS_TYPE_SETTINGS', 'settings');
 define('BX_DOL_STUDIO_AGENTS_TYPE_AUTOMATORS', 'automators');
+define('BX_DOL_STUDIO_AGENTS_TYPE_PROVIDERS', 'providers');
 
 define('BX_DOL_STUDIO_AGENTS_TYPE_DEFAULT', BX_DOL_STUDIO_AGENTS_TYPE_SETTINGS);
 

+ 30 - 0
studio/classes/BxDolStudioAgentsProviders.php

@@ -0,0 +1,30 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    UnaStudio UNA Studio
+ * @{
+ */
+
+require_once(BX_DOL_DIR_STUDIO_INC . 'utils.inc.php');
+
+class BxDolStudioAgentsProviders extends BxTemplStudioGrid
+{
+    protected $_oDb;
+
+    protected $_iProfileIdAi;
+
+    public function __construct ($aOptions, $oTemplate = false)
+    {
+        parent::__construct ($aOptions, $oTemplate);
+
+        $this->_sDefaultSortingOrder = 'DESC';
+
+        $this->_oDb = new BxDolStudioAgentsQuery();
+
+        $this->_iProfileIdAi = BxDolAI::getInstance()->getProfileId();
+    }
+}
+
+/** @} */

+ 17 - 1
studio/js/agents.js

@@ -13,6 +13,7 @@ function BxDolStudioPageAgents(oOptions)
     this.sObjName = oOptions.sObjName == undefined ? 'oBxDolStudioPageAgents' : oOptions.sObjName;
 
     this.sActionUrlCmts = oOptions.sActionUrlCmts == undefined ? this.sActionUrl : oOptions.sActionUrlCmts;
+    this.sActionUrlGrid = oOptions.sActionUrlGrid == undefined ? this.sActionUrl : oOptions.sActionUrlGrid;
 
     /*
      * Note. Are needed for Grid and don't used for now.
@@ -26,7 +27,7 @@ function BxDolStudioPageAgents(oOptions)
 BxDolStudioPageAgents.prototype = Object.create(BxDolStudioPage.prototype);
 BxDolStudioPageAgents.prototype.constructor = BxDolStudioPageAgents;
 
-BxDolStudioPageAgents.prototype.onChangeType = function(oSelect) {
+BxDolStudioPageAgents.prototype.onChangeAutomatorType = function(oSelect) {
     var aHide = [];
     var aShow = [];
     switch($(oSelect).val()) {
@@ -79,6 +80,21 @@ BxDolStudioPageAgents.prototype.approveCode = function(oSource, iCmtId) {
     );
 };
 
+BxDolStudioPageAgents.prototype.providerAdd = function(oButton, sName) {
+    var oButton = $(oButton);
+
+    var oSubentry = oButton.parents('#bx-form-element-' + sName).find('.bx-form-input-provider:first').clone();
+    oSubentry.find("select").val('');
+    oSubentry.find("input[type = 'hidden']").remove();
+
+    oButton.parents('.bx-form-input-provider-add:first').before(oSubentry);
+};
+
+BxDolStudioPageAgents.prototype.providerDelete = function(oButton) {
+    $(oButton).parents('.bx-form-input-provider:first').remove();
+};
+
+
 BxDolStudioPageAgents.prototype._getDefaultData = function() {
     var oDate = new Date();
     return jQuery.extend({}, this._oRequestParams, {_t:oDate.getTime()});

+ 11 - 0
studio/template/agents_automator_form_providers.html

@@ -0,0 +1,11 @@
+<div class="bx-form-input-providers">
+    <bx_repeat:providers>
+        <div class="bx-form-input-provider bx-def-padding-thd-topbottom">
+            <div class="bx-form-input-provider-cell bx-fi-sc-txt">__input_select__</div>
+            <div class="bx-form-input-provider-cell bx-fi-sc-btn bx-def-padding-sec-left">
+                <a class="bx-btn" href="javascript:void(0)" onclick="javascript:__js_object__.providerDelete(this)"><bx_image_auto:times /></a>
+            </div>
+        </div>
+    </bx_repeat:providers>
+    <div class="bx-form-input-provider-add">__btn_add__</div>
+</div>

+ 19 - 0
studio/template/agents_provider_form.html

@@ -0,0 +1,19 @@
+<div class="bx-agents-provider-form">
+    <div class="bx-agents-provider-form-cnt">
+        __form__
+        <script language="javascript">
+            $(document).ready(function () {
+                $("#__form_id__").ajaxForm({ 
+                    dataType: "json",
+                    beforeSubmit: function (formData, jqForm, options) {
+                        bx_loading($("#__form_id__"), true);
+                    },
+                    success: function (data) {
+                        $(".bx-popup-applied:visible").dolPopupHide();
+                        glGrids.__object__.processJson(data, '__action__');
+                    }
+                });
+            });
+        </script>
+    </div>
+</div>

+ 26 - 0
studio/template/css/agents.css

@@ -15,4 +15,30 @@
     background-color: #1f2937;
 
     color: #e5e7eb;
+}
+
+/*-- Automators form: Providers --*/
+.bx-form-input-provider {
+    display: -webkit-flex;
+    display: flex;
+    -webkit-align-items: center;
+    align-items: center;
+}
+.bx-form-input-provider-cell.bx-fi-sc-txt {
+    -webkit-flex: 1 1 auto;
+    -ms-flex: 1 1 auto;
+    flex: 1 1 auto;
+}
+.bx-form-input-provider-cell.bx-fi-sc-btn {
+    -webkit-flex: 0 0 auto;
+    -ms-flex: 0 0 auto;
+    flex: 0 0 auto;
+}
+
+.bx-form-input-provider-add {
+    text-align: right;
+}
+.bx-form-input-provider-add .bx-form-input-button {
+    display: inline-block;
+    float: none;
 }

+ 14 - 0
studio/template/scripts/BxBaseStudioAgents.php

@@ -34,10 +34,12 @@ class BxBaseStudioAgents extends BxDolStudioAgents
         $this->aMenuItems = [
             BX_DOL_STUDIO_AGENTS_TYPE_SETTINGS => ['icon' => 'cogs'],
             BX_DOL_STUDIO_AGENTS_TYPE_AUTOMATORS => ['icon' => 'cogs'],
+            BX_DOL_STUDIO_AGENTS_TYPE_PROVIDERS => ['icon' => 'cogs'],
         ];
 
         $this->aGridObjects = [
             BX_DOL_STUDIO_AGENTS_TYPE_AUTOMATORS => 'sys_studio_agents_automators',
+            BX_DOL_STUDIO_AGENTS_TYPE_PROVIDERS => 'sys_studio_agents_providers',
         ];
     }
 
@@ -99,6 +101,18 @@ class BxBaseStudioAgents extends BxDolStudioAgents
         return $this->getGrid($this->aGridObjects[BX_DOL_STUDIO_AGENTS_TYPE_AUTOMATORS]);
     }
 
+    protected function getProviders()
+    {
+        $this->aPageJsOptions = array_merge($this->aPageJsOptions, [
+            'sPageUrl' => $this->sSubpageUrl . 'providers',
+            'sActionUrlGrid' => bx_append_url_params(BX_DOL_URL_ROOT . 'grid.php', [
+                'o' => 'sys_studio_agents_providers'
+            ])
+        ]);
+
+        return $this->getGrid($this->aGridObjects[BX_DOL_STUDIO_AGENTS_TYPE_PROVIDERS]);
+    }
+
     protected function getGrid($sObjectName)
     {
         $oGrid = BxDolGrid::getObjectInstance($sObjectName);

+ 117 - 3
studio/template/scripts/BxBaseStudioAgentsAutomators.php

@@ -113,6 +113,14 @@ class BxBaseStudioAgentsAutomators extends BxDolStudioAgentsAutomators
 
             if($bIsValid) {
                 if(($iId = $oForm->insert($aValsToAdd)) !== false) {
+                    $aProviders = $oForm->getCleanValue('providers');
+                    if(!empty($aProviders) && is_array($aProviders))
+                        foreach($aProviders as $iProviderId)
+                            $this->_oDb->insertAutomatorProvider([
+                                'automator_id' => $iId, 
+                                'provider_id' => $iProviderId
+                            ]);
+
                     if(($oCmts = BxDolCmts::getObjectInstance($this->_sCmts, $iId)) !== null) {
                         if($bMessage) {
                             $aResult = $oCmts->addAuto([
@@ -162,6 +170,7 @@ class BxBaseStudioAgentsAutomators extends BxDolStudioAgentsAutomators
 
         $iId = $this->_getId();
         $aAutomator = $this->_oDb->getAutomatorsBy(['sample' => 'id', 'id' => $iId]);
+        $aAutomator['providers'] = $this->_oDb->getAutomatorsBy(['sample' => 'providers_by_id_pairs', 'id' => $iId]);
 
         $aForm = $this->_getFormEdit($sAction, $aAutomator);
         $oForm = new BxTemplFormView($aForm);
@@ -169,7 +178,30 @@ class BxBaseStudioAgentsAutomators extends BxDolStudioAgentsAutomators
 
         if($oForm->isSubmittedAndValid()) {
             $aValsToAdd = [];
-            
+
+            $aProvidersIds = $oForm->getCleanValue('providers_ids');
+            $aProvidersValues = $oForm->getCleanValue('providers');
+
+            //--- Remove deleted
+            $this->_oDb->deleteAutomatorProvidersById(array_diff(array_keys($aAutomator['providers']), $aProvidersIds));
+
+            //--- Update existed
+            foreach($aProvidersIds as $iIndex => $iApId)
+                $this->_oDb->updateAutomatorProvider(['provider_id' => (int)$aProvidersValues[$iIndex]], ['id' => (int)$iApId]);
+
+
+            //--- Add new
+            $iProvidersIds = count($aProvidersIds);
+            $iProvidersValues = count($aProvidersValues);
+            if($iProvidersValues > $iProvidersIds) {
+                $aProvidersValues = array_slice($aProvidersValues, $iProvidersIds);
+                foreach($aProvidersValues as $iProvidersValue)
+                    $this->_oDb->insertAutomatorProvider([
+                        'automator_id' => $iId,
+                        'provider_id' => (int)$iProvidersValue,
+                    ]);
+            }
+
             $iProfileId = $oForm->getCleanValue('profile_id');
             if(empty($iProfileId)) {
                 $iProfileId = (int)getParam('sys_agents_profile');
@@ -183,7 +215,7 @@ class BxBaseStudioAgentsAutomators extends BxDolStudioAgentsAutomators
             if(!empty($sSchedulerTime))
                 $aValsToAdd['params'] = json_encode(['scheduler_time' => $sSchedulerTime]);
 
-            if($oForm->update($iId, $aValsToAdd))
+            if($oForm->update($iId, $aValsToAdd) !== false)
                 $aRes = ['grid' => $this->getCode(false), 'blink' => $iId];
             else
                 $aRes = ['msg' => _t('_sys_txt_error_occured')];
@@ -278,12 +310,22 @@ class BxBaseStudioAgentsAutomators extends BxDolStudioAgentsAutomators
     {
         return false;
     }
+    
+    protected function _delete ($mixedId)
+    {
+        $mixedResult = parent::_delete($mixedId);
+        if($mixedResult)
+            $this->_oDb->deleteAutomatorProviders(['automator_id' => (int)$mixedId]);
+
+        return $mixedResult;
+    }
 
     protected function _getFormEdit($sAction, $aAutomator = [])
     {
         $aForm = $this->_getForm($sAction, $aAutomator);
         $aForm['form_attrs']['action'] .= '&id=' . $aAutomator['id'];
 
+        unset($aForm['inputs']['type']);
         unset($aForm['inputs']['message']);
 
         return $aForm;
@@ -291,6 +333,8 @@ class BxBaseStudioAgentsAutomators extends BxDolStudioAgentsAutomators
 
     protected function _getForm($sAction, $aAutomator = [])
     {
+        $sJsObject = $this->getPageJsObject();
+
         $sType = isset($aAutomator['type']) ? $aAutomator['type'] : 'event';
 
         if(!empty($aAutomator['params']))
@@ -346,7 +390,7 @@ class BxBaseStudioAgentsAutomators extends BxDolStudioAgentsAutomators
                         'webhook' => _t('_sys_agents_automators_field_type_webhook'),
                     ],
                     'attrs' => [
-                        'onchange' => $this->getPageJsObject() . '.onChangeType(this)',
+                        'onchange' => $this->getPageJsObject() . '.onChangeAutomatorType(this)',
                     ],
                     'required' => '1',
                     'db' => [
@@ -386,6 +430,12 @@ class BxBaseStudioAgentsAutomators extends BxDolStudioAgentsAutomators
                         'style' => $sType != 'scheduler' ? 'display:none' : ''
                     ],
                 ],
+                'providers' => [
+                    'type' => 'custom',
+                    'name' => 'providers',
+                    'caption' => _t('_sys_agents_automators_field_providers'),
+                    'value' => '',
+                ],
                 'message' => [
                     'type' => 'textarea',
                     'name' => 'message',
@@ -408,6 +458,70 @@ class BxBaseStudioAgentsAutomators extends BxDolStudioAgentsAutomators
 
             ),
         );
+        
+        if($aForm['inputs']['providers']) {
+            $oForm = new BxTemplFormView([]);
+
+            $sProviders = 'providers';
+            $aProviders = array_map(function($sTitle) {
+                return _t($sTitle);
+            }, ['' => '_sys_please_select'] + $this->_oDb->getProviderBy(['sample' => 'all_pairs', 'active' => 1]));
+
+            $aTmplVarsProviders = array();
+            if(!empty($aAutomator['providers']) && is_array($aAutomator['providers'])) {
+                foreach($aAutomator['providers'] as $iApId => $iProviderId) {
+                    $aInputSelect = [
+                        'type' => 'select',
+                        'name' => 'providers[]',
+                        'values' => $aProviders,
+                        'value' => (int)$iProviderId,
+                        'attrs' => [
+                            'class' => 'bx-def-margin-sec-top-auto'
+                        ]
+                    ];
+                    $sInput = $oForm->genInput($aInputSelect);
+
+                    $aInputHidden = [
+                        'type' => 'hidden',
+                        'name' => 'providers_ids[]',
+                        'value' => (int)$iApId,
+                    ];
+                    $sInput .= $oForm->genInput($aInputHidden);
+
+                    $aTmplVarsProviders[] = ['js_object' => $sJsObject, 'input_select' => $sInput];
+                }
+            }
+            else  {
+                $aInputSelect = [
+                    'type' => 'select',
+                    'name' => 'providers[]',
+                    'values' => $aProviders,
+                    'value' => '',
+                    'attrs' => [
+                        'class' => 'bx-def-margin-sec-top-auto'
+                    ]
+                ];
+
+                $aTmplVarsProviders = [
+                    ['js_object' => $sJsObject, 'input_select' => $oForm->genInput($aInputSelect)],
+                ];
+            }
+        
+            $aInputButton = [
+                'type' => 'button',
+                'name' => 'providers_add',
+                'value' => _t('_sys_agents_automators_field_providers_add'),
+                'attrs' => [
+                    'class' => 'bx-def-margin-sec-top',
+                    'onclick' => $sJsObject . ".providerAdd(this, '" . $sProviders . "');"
+                ]
+            ];
+
+            $aForm['inputs']['providers']['content'] = $this->_oTemplate->parseHtmlByName('agents_automator_form_providers.html', [
+                'bx_repeat:providers' => $aTmplVarsProviders,
+                'btn_add' => $oForm->genInputButton($aInputButton)
+            ]);
+        }
 
         return $aForm;
     }

+ 309 - 0
studio/template/scripts/BxBaseStudioAgentsProviders.php

@@ -0,0 +1,309 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    UnaView UNA Studio Representation classes
+ * @ingroup     UnaStudio
+ * @{
+ */
+
+class BxBaseStudioAgentsProviders extends BxDolStudioAgentsProviders
+{
+    protected $_sUrlPage;
+
+    public function __construct ($aOptions, $oTemplate = false)
+    {
+        parent::__construct ($aOptions, $oTemplate);
+
+        $this->_sUrlPage = BX_DOL_URL_STUDIO . 'agents.php?page=providers';
+    }
+
+    public function getPageJsObject()
+    {
+        return 'oBxDolStudioPageAgents';
+    }
+
+    public function performActionAdd()
+    {
+        $sAction = 'add';
+
+        $aProvider = [];
+        if(($iTypeId = bx_get('type_id')) !== false && $iTypeId > 0) {
+            $aProvider = [
+                'type_id' => (int)$iTypeId,
+                'options' => $this->_oDb->getProviderOptionsBy(['sample' => 'provider_type_id', 'provider_type_id' => $iTypeId])
+            ];
+        }
+
+        $aForm = $this->_getForm($sAction, $aProvider);
+        $oForm = new BxTemplFormView($aForm);
+        $oForm->initChecker();
+
+        if($oForm->isSubmittedAndValid()) {
+            $aValsToAdd = ['profile_id' => bx_get_logged_profile_id(), 'added' => time(), 'active' => 1];
+
+            if(($iId = $oForm->insert($aValsToAdd)) !== false) {
+                if(!empty($aProvider['options']) && is_array($aProvider['options']))
+                    foreach($aProvider['options'] as $aOption)
+                        $this->_oDb->insertProviderValue([
+                            'provider_id' => $iId, 
+                            'option_id' => $aOption['id'],
+                            'value' => $oForm->getCleanValue($aOption['name'])
+                        ]);
+
+                $aRes = ['grid' => $this->getCode(false), 'blink' => $iId];
+            }
+            else
+                $aRes = ['msg' => _t('_sys_txt_error_occured')];
+
+            return echoJson($aRes);
+        }
+
+        $sFormId = $oForm->getId();
+        $sContent = BxTemplStudioFunctions::getInstance()->popupBox($sFormId . '_popup_' . $sAction, _t('_sys_agents_providers_popup_add'), $this->_oTemplate->parseHtmlByName('agents_provider_form.html', [
+            'form_id' => $sFormId,
+            'form' => $oForm->getCode(true),
+            'object' => $this->_sObject,
+            'action' => $sAction
+        ]));
+
+        return echoJson(['popup' => ['html' => $sContent, 'options' => ['closeOnOuterClick' => false]]]);
+    }
+
+    public function performActionEdit()
+    {
+        $sAction = 'edit';
+
+        $iId = $this->_getId();
+
+        $aProvider = $this->_oDb->getProviderBy(['sample' => 'id', 'id' => $iId]);
+        if(empty($aProvider) || !is_array($aProvider))
+            return echoJson([]);
+
+        $aProvider['options'] = $this->_oDb->getProviderBy(['sample' => 'options_by_id', 'id' => $iId]);
+
+        $aForm = $this->_getFormEdit($sAction, $aProvider);
+        $oForm = new BxTemplFormView($aForm);
+        $oForm->initChecker();
+
+        if($oForm->isSubmittedAndValid()) {
+            if($oForm->update($iId) === false)
+                return echoJson(['msg' => _t('_sys_txt_error_occured')]);
+
+            if(!empty($aProvider['options']) && is_array($aProvider['options']))
+                foreach($aProvider['options'] as $aOption)
+                    $this->_oDb->updateProviderValue([
+                        'value' => $oForm->getCleanValue($aOption['name'])
+                    ], [
+                        'provider_id' => $iId, 
+                        'option_id' => $aOption['id'],
+                    ]);
+
+            return echoJson(['grid' => $this->getCode(false), 'blink' => $iId]);
+        } 
+
+        $sFormId = $oForm->getId();
+        $sContent = BxTemplStudioFunctions::getInstance()->popupBox($sFormId . '_popup_' . $sAction, _t('_sys_agents_providers_popup_edit'), $this->_oTemplate->parseHtmlByName('agents_provider_form.html', [
+            'form_id' => $sFormId,
+            'form' => $oForm->getCode(true),
+            'object' => $this->_sObject,
+            'action' => $sAction
+        ]));
+
+        return echoJson(['popup' => ['html' => $sContent, 'options' => ['closeOnOuterClick' => false]]]);
+    }
+
+    public function performActionInfo()
+    {
+        $sAction = 'view';
+
+        $iId = $this->_getId();
+
+        $aProvider = $this->_oDb->getProviderBy(['sample' => 'id', 'id' => $iId]);
+        if(empty($aProvider) || !is_array($aProvider))
+            return echoJson([]);
+
+        $aProvider['options'] = $this->_oDb->getProviderBy(['sample' => 'options_by_id', 'id' => $iId]);
+
+        $aForm = $this->_getFormView($sAction, $aProvider);
+        $oForm = new BxTemplFormView($aForm);
+        $oForm->initChecker($aProvider);
+
+        $sFormId = $oForm->getId();
+        $sContent = BxTemplStudioFunctions::getInstance()->popupBox($sFormId . '_popup_' . $sAction, _t('_sys_agents_providers_popup_view'), $this->_oTemplate->parseHtmlByName('agents_provider_form.html', [
+            'form_id' => $oForm->getId(),
+            'form' => $oForm->getCode(true),
+            'object' => $this->_sObject,
+            'action' => $sAction
+        ]));
+
+        echoJson(['popup' => ['html' => $sContent, 'options' => ['closeOnOuterClick' => true, 'removeOnClose' => true]]]);
+    }
+
+    protected function _getCellAdded($mixedValue, $sKey, $aField, $aRow)
+    {
+        return parent::_getCellDefault(bx_time_js($mixedValue), $sKey, $aField, $aRow);
+    }
+
+    protected function _addJsCss()
+    {
+        parent::_addJsCss();
+
+        $this->_oTemplate->addJs(['jquery.form.min.js', 'agents_automators.js']);
+
+        $oForm = new BxTemplStudioFormView([]);
+        $oForm->addCssJs();
+    }
+    
+    protected function _isCheckboxDisabled($aRow)
+    {
+        return false;
+    }
+
+    protected function _getActionsDisabledBehavior($aRow)
+    {
+        return false;
+    }
+
+    protected function _delete ($mixedId)
+    {
+        $mixedResult = parent::_delete($mixedId);
+        if($mixedResult)
+            $this->_oDb->deleteProviderValues(['provider_id' => (int)$mixedId]);
+
+        return $mixedResult;
+    }
+
+    protected function _getFormView($sAction, $aProvider = [])
+    {
+        $aForm = $this->_getForm($sAction, $aProvider);
+        $aForm['params']['view_mode'] = 1;
+
+        return $aForm;
+    }
+    
+    protected function _getFormEdit($sAction, $aProvider = [])
+    {
+        $aForm = $this->_getForm($sAction, $aProvider);
+        $aForm['form_attrs']['action'] .= '&id=' . $aProvider['id'];
+
+        return $aForm;
+    }
+
+    protected function _getForm($sAction, $aProvider = [])
+    {
+        $bProvider = !empty($aProvider) && is_array($aProvider);
+
+        $aForm = [
+            'form_attrs' => [
+                'id' => 'bx_std_agents_providers_' . $sAction,
+                'action' => BX_DOL_URL_ROOT . 'grid.php?o=sys_studio_agents_providers&a=' . $sAction,
+                'method' => 'post',
+            ],
+            'params' => [
+                'db' => [
+                    'table' => 'sys_agents_providers',
+                    'key' => 'id',
+                    'submit_name' => 'do_submit',
+                ],
+            ],
+            'inputs' => [
+                'controls' => [
+                    'type' => 'input_set',
+                    0 => [
+                        'type' => 'submit',
+                        'name' => 'do_submit',
+                        'value' => _t('_sys_submit'),
+                    ],
+                    1 => [
+                        'type' => 'reset',
+                        'name' => 'close',
+                        'value' => _t('_sys_close'),
+                        'attrs' => ['class' => 'bx-def-margin-sec-left', 'onclick' => '$(\'.bx-popup-applied:visible\').dolPopupHide();'],
+                    ],
+                ],
+
+            ],
+        ];
+                    
+        if($sAction == 'add' && !$bProvider) {
+            $aForm['inputs'] = bx_array_insert_before([
+                'type_id' => [
+                    'type' => 'select',
+                    'name' => 'type_id',
+                    'caption' => _t('_sys_agents_providers_field_type_id'),
+                    'info' => '',
+                    'value' => isset($aProvider['type_id']) ? $aProvider['type_id'] : 0,
+                    'values' => array_map(function($sTitle) {
+                        return _t($sTitle);
+                    }, ['' => '_sys_please_select'] + $this->_oDb->getProviderTypesBy(['sample' => 'all_pairs'])),
+                    'required' => '1',
+                    'db' => [
+                        'pass' => 'Int',
+                    ]
+                ],
+            ], $aForm['inputs'], 'controls');
+
+            $aForm['inputs']['controls'][0] = array_merge($aForm['inputs']['controls'][0], [
+                'name' => 'do_select',
+                'value' => _t('_sys_select')
+            ]);
+        }
+        else {
+            $aInputsAdd = [
+                'type_id' => [
+                    'type' => 'hidden',
+                    'name' => 'type_id',
+                    'value' => isset($aProvider['type_id']) ? $aProvider['type_id'] : 0,
+                    'db' => [
+                        'pass' => 'Int',
+                    ]
+                ],
+                'title' => [
+                    'type' => 'text',
+                    'name' => 'title',
+                    'caption' => _t('_sys_agents_providers_field_title'),
+                    'value' => isset($aProvider['title']) ? $aProvider['title'] : '',
+                    'db' => [
+                        'pass' => 'Xss',
+                    ],
+                ],
+            ];
+
+            if(!empty($aProvider['options']) && is_array($aProvider['options']))
+                foreach($aProvider['options'] as $aOption)
+                    $aInputsAdd[$aOption['name']] = [
+                        'type' => $aOption['type'],
+                        'name' => $aOption['name'],
+                        'caption' => _t($aOption['title']),
+                        'info' => _t($aOption['description']),
+                        'value' => isset($aOption['value']) ? $aOption['value'] : '',
+                        'checker' => !empty($aOption['check_type']) ? [
+                            'func' => $aOption['check_type'],
+                            'params' => !empty($aOption['check_params']) ? unserialize($aOption['check_params']) : '',
+                            'error' => _t($aOption['check_error']),
+                        ] : null,
+                    ];
+
+            $aForm['inputs'] = bx_array_insert_before($aInputsAdd, $aForm['inputs'], 'controls');
+        }
+
+        return $aForm;
+    }
+    
+    protected function _getId()
+    {
+        $aIds = bx_get('ids');
+        if(!empty($aIds) && is_array($aIds))
+            return array_shift($aIds);
+
+        $iId = (int)bx_get('id');
+        if(!$iId)
+            return false;
+
+        return $iId;
+    }
+}
+
+/** @} */

+ 19 - 0
studio/template/scripts_templ/BxTemplStudioAgentsProviders.php

@@ -0,0 +1,19 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    UnaStudioView UNA Studio Representation classes
+ * @ingroup     UnaStudio
+ * @{
+ */
+
+class BxTemplStudioAgentsProviders extends BxBaseStudioAgentsProviders
+{
+    public function __construct ($aOptions, $oTemplate = false)
+    {
+        parent::__construct ($aOptions, $oTemplate);
+    }
+}
+
+/** @} */

+ 1 - 0
template/scripts/BxBasePage.php

@@ -500,6 +500,7 @@ class BxBasePage extends BxDolPage
 
         $bIsAvailable = $this->_isAvailablePage($this->_aObject);
         $bIsVisible = $this->_isVisiblePage($this->_aObject);
+        //TODO: If page isn't Available or isn't Visible then we should exit with related Error Codes immediately.
 
         $sMetaTitle = $this->_getPageMetaTitle();
         $sName = $this->_getPageTitle();

이 변경점에서 너무 많은 파일들이 변경되어 몇몇 파일들은 표시되지 않았습니다.