AntonLV 5 лет назад
Родитель
Сommit
32ae436671
100 измененных файлов с 14767 добавлено и 0 удалено
  1. 51 0
      modules/boonex/accounts/updates/12.0.3_12.0.4/install/config.php
  2. 13 0
      modules/boonex/accounts/updates/12.0.3_12.0.4/install/installer.php
  3. 18 0
      modules/boonex/accounts/updates/12.0.3_12.0.4/install/langs/en.xml
  4. 26 0
      modules/boonex/accounts/updates/12.0.3_12.0.4/install/sql/enable.sql
  5. 103 0
      modules/boonex/accounts/updates/12.0.3_12.0.4/source/classes/BxAccntConfig.php
  6. 35 0
      modules/boonex/accounts/updates/12.0.3_12.0.4/source/classes/BxAccntDb.php
  7. 731 0
      modules/boonex/accounts/updates/12.0.3_12.0.4/source/classes/BxAccntGridAdministration.php
  8. 160 0
      modules/boonex/accounts/updates/12.0.3_12.0.4/source/classes/BxAccntModule.php
  9. 88 0
      modules/boonex/accounts/updates/12.0.3_12.0.4/source/classes/BxAccntSearchResult.php
  10. 45 0
      modules/boonex/accounts/updates/12.0.3_12.0.4/source/classes/BxAccntStudioPage.php
  11. 71 0
      modules/boonex/accounts/updates/12.0.3_12.0.4/source/install/config.php
  12. 110 0
      modules/boonex/accounts/updates/12.0.3_12.0.4/source/install/langs/en.xml
  13. 31 0
      modules/boonex/accounts/updates/12.0.3_12.0.4/source/install/sql/disable.sql
  14. 105 0
      modules/boonex/accounts/updates/12.0.3_12.0.4/source/install/sql/enable.sql
  15. 51 0
      modules/boonex/acl/updates/12.0.1_12.0.2/install/config.php
  16. 13 0
      modules/boonex/acl/updates/12.0.1_12.0.2/install/installer.php
  17. 7 0
      modules/boonex/acl/updates/12.0.1_12.0.2/install/langs/en.xml
  18. 609 0
      modules/boonex/acl/updates/12.0.1_12.0.2/source/classes/BxAclModule.php
  19. 70 0
      modules/boonex/acl/updates/12.0.1_12.0.2/source/install/config.php
  20. 102 0
      modules/boonex/acl/updates/12.0.1_12.0.2/source/install/langs/en.xml
  21. 51 0
      modules/boonex/ads/updates/12.0.0_12.0.1/install/config.php
  22. 23 0
      modules/boonex/ads/updates/12.0.0_12.0.1/install/installer.php
  23. 4 0
      modules/boonex/ads/updates/12.0.0_12.0.1/install/langs/en.xml
  24. 2 0
      modules/boonex/ads/updates/12.0.0_12.0.1/install/sql/install.sql
  25. 150 0
      modules/boonex/ads/updates/12.0.0_12.0.1/source/install/config.php
  26. 402 0
      modules/boonex/ads/updates/12.0.0_12.0.1/source/install/langs/en.xml
  27. 746 0
      modules/boonex/ads/updates/12.0.0_12.0.1/source/install/sql/install.sql
  28. 51 0
      modules/boonex/albums/updates/12.0.3_12.0.4/install/config.php
  29. 23 0
      modules/boonex/albums/updates/12.0.3_12.0.4/install/installer.php
  30. 2 0
      modules/boonex/albums/updates/12.0.3_12.0.4/install/sql/install.sql
  31. 975 0
      modules/boonex/albums/updates/12.0.3_12.0.4/source/classes/BxAlbumsModule.php
  32. 413 0
      modules/boonex/albums/updates/12.0.3_12.0.4/source/classes/BxAlbumsTemplate.php
  33. 143 0
      modules/boonex/albums/updates/12.0.3_12.0.4/source/install/config.php
  34. 538 0
      modules/boonex/albums/updates/12.0.3_12.0.4/source/install/sql/install.sql
  35. 241 0
      modules/boonex/albums/updates/12.0.3_12.0.4/source/template/css/main.css
  36. 51 0
      modules/boonex/api/updates/12.0.1_12.0.2/install/config.php
  37. 13 0
      modules/boonex/api/updates/12.0.1_12.0.2/install/installer.php
  38. 4 0
      modules/boonex/api/updates/12.0.1_12.0.2/install/langs/en.xml
  39. 29 0
      modules/boonex/api/updates/12.0.1_12.0.2/source/classes/BxApiStudioPage.php
  40. 70 0
      modules/boonex/api/updates/12.0.1_12.0.2/source/install/config.php
  41. 16 0
      modules/boonex/api/updates/12.0.1_12.0.2/source/install/langs/en.xml
  42. 51 0
      modules/boonex/channels/updates/12.0.0_12.0.1/install/config.php
  43. 23 0
      modules/boonex/channels/updates/12.0.0_12.0.1/install/installer.php
  44. 6 0
      modules/boonex/channels/updates/12.0.0_12.0.1/install/langs/en.xml
  45. 7 0
      modules/boonex/channels/updates/12.0.0_12.0.1/install/sql/enable.sql
  46. 1 0
      modules/boonex/channels/updates/12.0.0_12.0.1/install/sql/install.sql
  47. 181 0
      modules/boonex/channels/updates/12.0.0_12.0.1/source/classes/BxCnlConfig.php
  48. 562 0
      modules/boonex/channels/updates/12.0.0_12.0.1/source/classes/BxCnlModule.php
  49. 153 0
      modules/boonex/channels/updates/12.0.0_12.0.1/source/install/config.php
  50. 242 0
      modules/boonex/channels/updates/12.0.0_12.0.1/source/install/langs/en.xml
  51. 414 0
      modules/boonex/channels/updates/12.0.0_12.0.1/source/install/sql/enable.sql
  52. 295 0
      modules/boonex/channels/updates/12.0.0_12.0.1/source/install/sql/install.sql
  53. 51 0
      modules/boonex/classes/updates/12.0.1_12.0.2/install/config.php
  54. 23 0
      modules/boonex/classes/updates/12.0.1_12.0.2/install/installer.php
  55. 2 0
      modules/boonex/classes/updates/12.0.1_12.0.2/install/sql/install.sql
  56. 152 0
      modules/boonex/classes/updates/12.0.1_12.0.2/source/install/config.php
  57. 641 0
      modules/boonex/classes/updates/12.0.1_12.0.2/source/install/sql/install.sql
  58. 51 0
      modules/boonex/convos/updates/12.0.2_12.0.3/install/config.php
  59. 13 0
      modules/boonex/convos/updates/12.0.2_12.0.3/install/installer.php
  60. 134 0
      modules/boonex/convos/updates/12.0.2_12.0.3/source/classes/BxCnvCmts.php
  61. 104 0
      modules/boonex/convos/updates/12.0.2_12.0.3/source/install/config.php
  62. 51 0
      modules/boonex/courses/updates/12.0.0_12.0.1/install/config.php
  63. 31 0
      modules/boonex/courses/updates/12.0.0_12.0.1/install/installer.php
  64. 79 0
      modules/boonex/courses/updates/12.0.0_12.0.1/install/langs/en.xml
  65. 129 0
      modules/boonex/courses/updates/12.0.0_12.0.1/install/sql/enable.sql
  66. 86 0
      modules/boonex/courses/updates/12.0.0_12.0.1/install/sql/install.sql
  67. 257 0
      modules/boonex/courses/updates/12.0.0_12.0.1/source/classes/BxCoursesConfig.php
  68. 22 0
      modules/boonex/courses/updates/12.0.0_12.0.1/source/classes/BxCoursesCronPruning.php
  69. 22 0
      modules/boonex/courses/updates/12.0.0_12.0.1/source/classes/BxCoursesFormPrice.php
  70. 22 0
      modules/boonex/courses/updates/12.0.0_12.0.1/source/classes/BxCoursesGridPricesManage.php
  71. 22 0
      modules/boonex/courses/updates/12.0.0_12.0.1/source/classes/BxCoursesGridPricesView.php
  72. 60 0
      modules/boonex/courses/updates/12.0.0_12.0.1/source/classes/BxCoursesMenuViewActionsAll.php
  73. 24 0
      modules/boonex/courses/updates/12.0.0_12.0.1/source/classes/BxCoursesPageListEntry.php
  74. 152 0
      modules/boonex/courses/updates/12.0.0_12.0.1/source/install/config.php
  75. 439 0
      modules/boonex/courses/updates/12.0.0_12.0.1/source/install/langs/en.xml
  76. 60 0
      modules/boonex/courses/updates/12.0.0_12.0.1/source/install/sql/disable.sql
  77. 643 0
      modules/boonex/courses/updates/12.0.0_12.0.1/source/install/sql/enable.sql
  78. 459 0
      modules/boonex/courses/updates/12.0.0_12.0.1/source/install/sql/install.sql
  79. 64 0
      modules/boonex/courses/updates/12.0.0_12.0.1/source/install/sql/uninstall.sql
  80. 59 0
      modules/boonex/courses/updates/12.0.0_12.0.1/source/js/prices.js
  81. 1 0
      modules/boonex/courses/updates/12.0.0_12.0.1/source/template/css/prices.css
  82. 1 0
      modules/boonex/courses/updates/12.0.0_12.0.1/source/template/favorite-list-info.html
  83. 1 0
      modules/boonex/courses/updates/12.0.0_12.0.1/source/template/favorite-lists.html
  84. 1 0
      modules/boonex/courses/updates/12.0.0_12.0.1/source/template/popup_price.html
  85. 51 0
      modules/boonex/credits/updates/12.0.0_12.0.1/install/config.php
  86. 13 0
      modules/boonex/credits/updates/12.0.0_12.0.1/install/installer.php
  87. 13 0
      modules/boonex/credits/updates/12.0.0_12.0.1/install/langs/en.xml
  88. 267 0
      modules/boonex/credits/updates/12.0.0_12.0.1/source/classes/BxCreditsConfig.php
  89. 110 0
      modules/boonex/credits/updates/12.0.0_12.0.1/source/classes/BxCreditsFormWithdraw.php
  90. 998 0
      modules/boonex/credits/updates/12.0.0_12.0.1/source/classes/BxCreditsModule.php
  91. 77 0
      modules/boonex/credits/updates/12.0.0_12.0.1/source/install/config.php
  92. 254 0
      modules/boonex/credits/updates/12.0.0_12.0.1/source/install/langs/en.xml
  93. 4 0
      modules/boonex/credits/updates/12.0.0_12.0.1/source/template/css/withdraw.css
  94. 51 0
      modules/boonex/developer/updates/12.0.0_12.0.1/install/config.php
  95. 13 0
      modules/boonex/developer/updates/12.0.0_12.0.1/install/installer.php
  96. 36 0
      modules/boonex/developer/updates/12.0.0_12.0.1/install/langs/en.xml
  97. 53 0
      modules/boonex/developer/updates/12.0.0_12.0.1/install/sql/install.sql
  98. 468 0
      modules/boonex/developer/updates/12.0.0_12.0.1/source/classes/BxDevBuilderPage.php
  99. 115 0
      modules/boonex/developer/updates/12.0.0_12.0.1/source/classes/BxDevConfig.php
  100. 67 0
      modules/boonex/developer/updates/12.0.0_12.0.1/source/classes/BxDevDb.php

+ 51 - 0
modules/boonex/accounts/updates/12.0.3_12.0.4/install/config.php

@@ -0,0 +1,51 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'title' => 'Accounts Manager',
+    'version_from' => '12.0.3',
+    'version_to' => '12.0.4',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '12.1.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/accounts/updates/update_12.0.3_12.0.4/',
+    'home_uri' => 'accounts_update_1203_1204',
+
+    'module_dir' => 'boonex/accounts/',
+    'module_uri' => 'accounts',
+
+    'db_prefix' => 'bx_accnt_',
+    'class_prefix' => 'BxAccnt',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_files' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Accounts',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

+ 13 - 0
modules/boonex/accounts/updates/12.0.3_12.0.4/install/installer.php

@@ -0,0 +1,13 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+class BxAccntUpdater extends BxDolStudioUpdater
+{
+    function __construct($aConfig)
+    {
+        parent::__construct($aConfig);
+    }
+}

+ 18 - 0
modules/boonex/accounts/updates/12.0.3_12.0.4/install/langs/en.xml

@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources name="en" flag="gb" title="English">
+	<string_add name="_bx_accounts_option_export_to"><![CDATA[Export to]]></string_add>
+    <string_add name="_bx_accounts_option_export_fields"><![CDATA[Export fields]]></string_add>
+	<string_add name="_bx_accnt_grid_action_title_adm_export"><![CDATA[Export]]></string_add>
+	<string_add name="_bx_accnt_txt_export_to_csv"><![CDATA[CSV]]></string_add>
+    <string_add name="_bx_accnt_txt_export_to_xml"><![CDATA[XML]]></string_add>
+    <string_add name="_bx_accnt_txt_field_name"><![CDATA[Name]]></string_add>
+    <string_add name="_bx_accnt_txt_field_email"><![CDATA[Email]]></string_add>
+    <string_add name="_bx_accnt_txt_field_email_confirmed"><![CDATA[Email Confirmed]]></string_add>
+    <string_add name="_bx_accnt_txt_field_phone"><![CDATA[Phone]]></string_add>
+    <string_add name="_bx_accnt_txt_field_receive_updates"><![CDATA[Receive Updates]]></string_add>
+    <string_add name="_bx_accnt_txt_field_receive_news"><![CDATA[Receive News]]></string_add>
+    <string_add name="_bx_accnt_txt_field_added"><![CDATA[Added]]></string_add>
+    <string_add name="_bx_accnt_txt_field_changed"><![CDATA[Changed]]></string_add>
+    <string_add name="_bx_accnt_txt_field_logged"><![CDATA[Logged]]></string_add>
+    <string_add name="_bx_accnt_txt_field_ip"><![CDATA[IP]]></string_add>
+</resources>

+ 26 - 0
modules/boonex/accounts/updates/12.0.3_12.0.4/install/sql/enable.sql

@@ -0,0 +1,26 @@
+SET @sName = 'bx_accounts';
+
+
+-- SETTINGS
+DELETE FROM `sys_options_types` WHERE `name`=@sName;
+SET @iTypeOrder = (SELECT MAX(`order`) FROM `sys_options_types` WHERE `group` = 'modules');
+INSERT INTO `sys_options_types`(`group`, `name`, `caption`, `icon`, `order`) VALUES 
+('modules', @sName, '_bx_accounts', 'bx_accounts@modules/boonex/accounts/|std-icon.svg', IF(ISNULL(@iTypeOrder), 1, @iTypeOrder + 1));
+SET @iTypeId = LAST_INSERT_ID();
+
+DELETE FROM `sys_options_categories` WHERE `name`=@sName;
+INSERT INTO `sys_options_categories` (`type_id`, `name`, `caption`, `order`)
+VALUES (@iTypeId, @sName, '_bx_accounts', 1);
+SET @iCategId = LAST_INSERT_ID();
+
+DELETE FROM `sys_options` WHERE `name` IN ('bx_accounts_export_to', 'bx_accounts_export_fields');
+INSERT INTO `sys_options` (`name`, `value`, `category_id`, `caption`, `type`, `check`, `check_params`, `check_error`, `extra`, `order`) VALUES
+('bx_accounts_export_to', 'csv', @iCategId, '_bx_accounts_option_export_to', 'select', '', '', '', 'a:2:{s:6:"module";s:11:"bx_accounts";s:6:"method";s:21:"get_options_export_to";}', 10),
+('bx_accounts_export_fields', 'name,email', @iCategId, '_bx_accounts_option_export_fields', 'list', '', '', '', 'a:2:{s:6:"module";s:11:"bx_accounts";s:6:"method";s:25:"get_options_export_fields";}', 20);
+
+
+-- GRIDS
+DELETE FROM `sys_grid_actions` WHERE `object`='bx_accounts_administration' AND `name`='export' AND `type` IN ('bulk', 'independent');
+INSERT INTO `sys_grid_actions` (`object`, `type`, `name`, `title`, `icon`, `icon_only`, `confirm`, `order`) VALUES
+('bx_accounts_administration', 'bulk', 'export', '_bx_accnt_grid_action_title_adm_export', '', 0, 0, 8),
+('bx_accounts_administration', 'independent', 'export', '_bx_accnt_grid_action_title_adm_export', 'download', 0, 0, 1);

+ 103 - 0
modules/boonex/accounts/updates/12.0.3_12.0.4/source/classes/BxAccntConfig.php

@@ -0,0 +1,103 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Accounts Accounts
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxAccntConfig extends BxBaseModGeneralConfig
+{
+    protected $_oDb;
+    protected $_aHtmlIds;
+
+    /**
+     * Constructor
+     */
+    public function __construct($aModule)
+    {
+        parent::__construct($aModule);
+
+        $this->CNF = array (
+            // some params
+            'PARAM_PROFILE_NAME_LENGTH_MAX' => 10,
+            'PARAM_EXPORT_TO' => 'bx_accounts_export_to',
+            'PARAM_EXPORT_FIELDS' => 'bx_accounts_export_fields',
+
+            // page URIs
+            'URL_MANAGE_ADMINISTRATION' => 'page.php?i=accounts-administration',
+
+            // objects
+            'OBJECT_STORAGE_FILES' => 'sys_files',
+            'OBJECT_FORM_ACCOUNT' => 'bx_accounts_account',
+            'OBJECT_FORM_ACCOUNT_DISPLAY_SETTINGS_EMAIL' => 'bx_accounts_account_settings_email',
+            'OBJECT_FORM_ACCOUNT_DISPLAY_CREATE' => 'bx_accounts_account_create',
+            'OBJECT_MENU_MANAGE_TOOLS' => 'bx_accounts_menu_manage_tools', //manage menu in content administration tools
+            'OBJECT_GRID_ADMINISTRATION' => 'bx_accounts_administration',
+            'OBJECT_GRID_MODERATION' => 'bx_accounts_moderation',
+
+                // some language keys
+            'T' => array (
+                'grid_action_err_delete' => '_bx_accnt_grid_action_err_delete',
+                'grid_action_err_perform' => '_bx_accnt_grid_action_err_perform',
+                'filter_item_active' => '_bx_accnt_grid_filter_item_title_adm_active',
+                'filter_item_operators' => '_bx_accnt_grid_filter_item_title_adm_operators',
+                'filter_item_pending' => '_bx_accnt_grid_filter_item_title_adm_pending',
+                'filter_item_suspended' => '_bx_accnt_grid_filter_item_title_adm_suspended',
+                'filter_item_unconfirmed' => '_bx_accnt_grid_filter_item_title_adm_unconfirmed',
+                'filter_item_locked' => '_bx_accnt_grid_filter_item_title_adm_locked',
+                'filter_item_without_profile' => '_bx_accnt_grid_filter_item_title_adm_without_profile',
+                'filter_item_select_one_filter1' => '_bx_accnt_grid_filter_item_title_adm_select_one_filter1',
+                'filter_item_select_one_filter2' => '_bx_accnt_grid_filter_item_title_adm_select_one_filter2',
+            )
+        );
+
+        $this->_aObjects = array(
+            'alert' => $this->_sName,
+        );
+
+        $this->_aJsClasses = array(
+            'main' => 'BxAccntMain',
+            'manage_tools' => 'BxAccntManageTools'
+        );
+
+        $this->_aJsObjects = array(
+            'main' => 'oBxAccntMain',
+            'manage_tools' => 'oBxAccntManageTools'
+        );
+
+        $this->_aGridObjects = array(
+            'moderation' => $this->CNF['OBJECT_GRID_MODERATION'],
+            'administration' => $this->CNF['OBJECT_GRID_ADMINISTRATION'],
+
+        );
+
+        $sHtmlPrefix = str_replace('_', '-', $this->_sName);
+        $this->_aHtmlIds = array(
+            'profile' => $sHtmlPrefix . '-profile-',
+            'profile_more_popup' => $sHtmlPrefix . '-profile-more-popup-',
+
+            'password_text' => $sHtmlPrefix . '-txt-password',
+            'password_button' => $sHtmlPrefix . '-btn-copy',
+            'password_popup' => $sHtmlPrefix . '-password-popup',
+        );
+    }
+
+    public function init(&$oDb)
+    {
+        $this->_oDb = &$oDb;
+    }
+
+    public function getHtmlIds($sKey = '')
+    {
+        if(empty($sKey))
+            return $this->_aHtmlIds;
+
+        return isset($this->_aHtmlIds[$sKey]) ? $this->_aHtmlIds[$sKey] : '';
+    }
+}
+
+/** @} */

+ 35 - 0
modules/boonex/accounts/updates/12.0.3_12.0.4/source/classes/BxAccntDb.php

@@ -0,0 +1,35 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Accounts Accounts
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxAccntDb extends BxBaseModGeneralDb
+{
+    function __construct(&$oConfig)
+    {
+        parent::__construct($oConfig);
+    }
+
+    public function getAccountFields()
+    {
+        return $this->getFields('sys_accounts');
+    }
+
+    public function getAccountIds()
+    {
+    	return $this->getColumn("SELECT `id` FROM `sys_accounts` WHERE 1", "id");
+    }
+
+    public function updateAccount($aSet, $aWhere)
+    {
+    	return (int)$this->query("UPDATE `sys_accounts` SET " . $this->arrayToSQL($aSet) . " WHERE " . $this->arrayToSQL($aWhere, ' AND ')) > 0;
+    }
+}
+
+/** @} */

+ 731 - 0
modules/boonex/accounts/updates/12.0.3_12.0.4/source/classes/BxAccntGridAdministration.php

@@ -0,0 +1,731 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Accounts Accounts
+ * @ingroup     UnaModules
+ * 
+ * @{
+ */
+
+class BxAccntGridAdministration extends BxBaseModProfileGridAdministration
+{
+    protected $_sFilter2Name;
+	protected $_sFilter2Value;
+	protected $_aFilter2Values;
+    
+    public function __construct ($aOptions, $oTemplate = false)
+    {
+    	$this->MODULE = 'bx_accounts';
+        parent::__construct ($aOptions, $oTemplate);
+
+        $CNF = &$this->_oModule->_oConfig->CNF;
+        $this->_aFilter1Values = array_merge($this->_aFilter1Values, array(
+            'unconfirmed' => $CNF['T']['filter_item_unconfirmed'],
+            'locked' => $CNF['T']['filter_item_locked'],
+            'without_profile' => $CNF['T']['filter_item_without_profile'],
+        ));
+
+        $this->_sFilter2Name = 'filter2';
+        $this->_aFilter2Values = array(
+            'operators' => $CNF['T']['filter_item_operators']
+        );
+
+        $sFilter2 = bx_get($this->_sFilter2Name);
+        if(!empty($sFilter2)) {
+            $this->_sFilter2Value = bx_process_input($sFilter2);
+            $this->_aQueryAppend[$this->_sFilter2Name] = $this->_sFilter2Value;
+        }
+    }
+
+    protected function _getDataSql($sFilter, $sOrderField, $sOrderDir, $iStart, $iPerPage)
+    {
+        if(strpos($sFilter, $this->_sParamsDivider) !== false)
+            list($this->_sFilter1Value, $this->_sFilter2Value, $sFilter) = explode($this->_sParamsDivider, $sFilter);
+
+    	if(!empty($this->_sFilter1Value))
+            switch($this->_sFilter1Value) {
+                case 'unconfirmed':
+                    $sCnfnType = getParam('sys_account_confirmation_type');
+                    switch($sCnfnType) {
+                        case 'email':
+                            $this->_aOptions['source'] .= " AND `ta`.`email_confirmed`='0'";
+                            break;
+                        case 'phone':
+                            $this->_aOptions['source'] .= " AND `ta`.`phone_confirmed`='0'";
+                            break;
+                        case 'email_and_phone':
+                            $this->_aOptions['source'] .= " AND (`ta`.`email_confirmed`='0' OR `ta`.`phone_confirmed`='0')";
+                            break;
+                    }
+                    break;
+
+                case 'locked':
+                    $this->_aOptions['source'] .= " AND `ta`.`locked` = 1";
+                    break;
+                
+                case 'without_profile':
+                    $this->_aOptions['source'] .= " AND `ta`.`id` NOT IN (SELECT `account_id` FROM `sys_profiles` WHERE `type` <> 'system')";
+                    break;
+
+                default:
+        	        $this->_aOptions['source'] .= $this->_oModule->_oDb->prepareAsString(" AND `tp`.`status`=?", $this->_sFilter1Value);
+            }
+
+        if(!empty($this->_sFilter2Value))
+        	$this->_aOptions['source'] .= $this->_oModule->_oDb->prepareAsString(" AND `ta`.`role` & " . BX_DOL_ROLE_ADMIN ." = " . BX_DOL_ROLE_ADMIN);
+
+        $this->_aOptions['source'] .= " AND `ta`.`email` <> '' ";
+        
+        return parent::_getDataSqlInner($sFilter, $sOrderField, $sOrderDir, $iStart, $iPerPage);
+    }
+    
+    protected function _getFilterControls()
+    {
+        parent::_getFilterControls();
+
+        return  $this->_getFilterSelectOne($this->_sFilter1Name, $this->_sFilter1Value, $this->_aFilter1Values) . $this->_getFilterSelectOne($this->_sFilter2Name, $this->_sFilter2Value, $this->_aFilter2Values) . $this->_getSearchInput();
+    }
+    
+    public function getCode($isDisplayHeader = true)
+    {
+        return $this->_oModule->_oTemplate->getJsCode('main', array(
+        	'aHtmlIds' => $this->_oModule->_oConfig->getHtmlIds()
+        )) . parent::getCode($isDisplayHeader);
+    }
+
+    public function performActionActivate()
+    {
+    	$this->_performActionEnable(true);
+    }
+
+	public function performActionSuspend()
+    {
+    	$this->_performActionEnable(false);
+    }
+
+    public function performActionEditEmail()
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        $aIds = bx_get('ids');
+        if(!$aIds || !is_array($aIds)) {
+            $iId = (int)bx_get('id');
+            if(!$iId)
+                return echoJson(array());
+
+            $aIds = array($iId);
+        }
+
+        $iId = $aIds[0];
+        $oAccount = BxDolAccount::getInstance($iId);
+        if(!$oAccount)
+            return echoJson(array());
+
+        $aAccount = $oAccount->getInfo();
+        $sAction = 'edit_email';
+
+        $oForm = BxDolForm::getObjectInstance($CNF['OBJECT_FORM_ACCOUNT'], $CNF['OBJECT_FORM_ACCOUNT_DISPLAY_SETTINGS_EMAIL']);
+        $oForm->aFormAttrs['action'] = BX_DOL_URL_ROOT . 'grid.php?o=' . $this->_sObject . '&a=' . $sAction . '&id=' . $iId;
+        $oForm->initChecker($aAccount);
+
+        if($oForm->isSubmittedAndValid()) {
+            $sEmail = $oForm->getCleanValue('email');
+            if(strcmp($aAccount['email'], $sEmail) !== 0 && BxDolAccountQuery::getInstance()->getIdByEmail($sEmail))
+                return echoJson(array('msg' => _t('_sys_form_account_input_email_uniq_error_loggedin')));
+
+            if($oForm->update($aAccount['id'])) {
+                bx_alert('account', 'edited', $aAccount['id'], BxDolAccount::getInstance()->id(), array('display' => $CNF['OBJECT_FORM_ACCOUNT_DISPLAY_SETTINGS_EMAIL']));
+
+                $aRes = array('grid' => $this->getCode(false), 'blink' => $iId);
+                
+                $oAccount->doAudit($iId, '_sys_audit_action_account_email_changed', array('old_email' => $oAccount->getEmail(), 'new_email' => $sEmail));
+            }
+            else
+                $aRes = array('msg' => _t('_sys_txt_error_account_update'));
+
+            echoJson($aRes);
+        }
+        else {
+            $sContent = BxTemplStudioFunctions::getInstance()->popupBox('bx-account-edit-email-popup', _t('_bx_accounts_form_display_account_settings_email_popup'), $this->_oModule->_oTemplate->parseHtmlByName('edit_email.html', array(
+                'form_id' => $oForm->id,
+                'form' => $oForm->getCode(true),
+                'object' => $this->_sObject,
+                'action' => $sAction
+            )));
+
+            echoJson(array('popup' => array('html' => $sContent, 'options' => array('closeOnOuterClick' => false))));
+        }
+    }
+    
+    public function performActionAdd()
+    {
+      
+        $CNF = &$this->_oModule->_oConfig->CNF;
+        $sAction = 'add';
+        $oForm = BxDolForm::getObjectInstance($CNF['OBJECT_FORM_ACCOUNT'], $CNF['OBJECT_FORM_ACCOUNT_DISPLAY_CREATE']);
+        $oForm->aFormAttrs['action'] = BX_DOL_URL_ROOT . 'grid.php?o=' . $this->_sObject . '&a=' . $sAction;
+        $oForm->initChecker();
+
+        if($oForm->isSubmittedAndValid()) {
+           
+            $iAccountId = $oForm->insert();
+            
+            if (!$iAccountId) {
+                $aRes = array('msg' => _t('_sys_txt_error_account_insert'));
+            }
+            else{
+                $aRes = array('grid' => $this->getCode(false), 'blink' => $iAccountId);
+                
+                $oBxTemplAccountForms = new BxTemplAccountForms();
+                
+                $iProfileId = $oBxTemplAccountForms->onAccountCreated($iAccountId, $oForm->isSetPendingApproval(), BX_PROFILE_ACTION_MANUAL, false);
+
+                // perform action
+                BxDolAccount::isAllowedCreate ($iProfileId, true);
+                
+                // check
+                $aModulesProfile = array(); 
+                $aModules = BxDolModuleQuery::getInstance()->getModulesBy(array('type' => 'modules', 'active' => 1));
+                foreach($aModules as $aModule) {
+                    $oModule = BxDolModule::getInstance($aModule['name']);
+                    if($oModule instanceof iBxDolProfileService && BxDolService::call($aModule['name'], 'act_as_profile') === true)
+                        $aModulesProfile[] = $aModule;
+                }
+
+                $sDefaultProfileType = getParam('sys_account_default_profile_type');
+                if(count($aModulesProfile) == 1)
+                    $sProfileModule = $aModulesProfile[0]['name'];
+                else if(!empty($sDefaultProfileType)) 
+                    $sProfileModule = $sDefaultProfileType;
+
+                if (getParam('sys_account_auto_profile_creation') && !empty($sProfileModule)) {
+                    $oAccount = BxDolAccount::getInstance($iAccountId);
+                    $aProfileInfo = BxDolService::call($sProfileModule, 'prepare_fields', array(array(
+                        'author' => $iProfileId,
+                        'name' => $oAccount->getDisplayName(),
+                    )));
+                    $a = BxDolService::call($sProfileModule, 'entity_add', array($iProfileId, $aProfileInfo));
+                    if (isset($a['content']['profile_id']) && (int)$a['content']['profile_id'] > 0){
+                        BxDolAcl::getInstance()->setMembership((int)$a['content']['profile_id'], MEMBERSHIP_ID_STANDARD);
+                    }
+                    echoJson($aRes);
+                }
+            }
+        }
+        else {
+            $sContent = BxTemplStudioFunctions::getInstance()->popupBox('bx-account-edit-email-popup', _t('_bx_accounts_form_display_account_create_popup'), $this->_oModule->_oTemplate->parseHtmlByName('create.html', array(
+                'form_id' => $oForm->id,
+                'form' => $oForm->getCode(true),
+                'object' => $this->_sObject,
+                'action' => $sAction
+            )));
+
+            echoJson(array('popup' => array('html' => $sContent, 'options' => array('closeOnOuterClick' => false))));
+        }
+    }
+
+    public function performActionExport()
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        $aFields = explode(',', getParam($CNF['PARAM_EXPORT_FIELDS']));
+        if(empty($aFields) || !is_array($aFields))
+            return echoJson(array());
+
+        
+        $aTitles = $aConverters = array();
+        foreach($aFields as $sField) {
+            $aTitles[$sField] = _t('_bx_accnt_txt_field_' . $sField);
+            
+            $sConverter = '_exportFieldConverter' . bx_gen_method_name($sField);
+            if(method_exists($this, $sConverter))
+                $aConverters[$sField] = $sConverter;
+        }
+
+        $sMethod = '_exportTo' . bx_gen_method_name(getParam($CNF['PARAM_EXPORT_TO']));
+        if(!method_exists($this, $sMethod))
+            return echoJson(array());
+
+        $aIds = bx_get('ids');
+        if(!$aIds || !is_array($aIds))
+            $aIds = $this->_oModule->_oDb->getAccountIds();
+
+        if(($aFile = $this->$sMethod($aIds, $aFields, $aTitles, $aConverters)) === false)
+            return echoJson(array());
+
+        list($sFilePath, $sFileUrl) = $aFile;
+
+        $oStorage = BxDolStorage::getObjectInstance($CNF['OBJECT_STORAGE_FILES']);
+        if($oStorage && ($iFileId = $oStorage->storeFileFromPath($sFilePath, true, bx_get_logged_profile_id())) !== false) {
+            $sFileUrl = $oStorage->getFileUrlById($iFileId);
+
+            @unlink($sFilePath);
+        }
+
+        return echoJson(array('redirect' => $sFileUrl));
+    }
+    
+    public function performActionConfirm()
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+    	$aIds = bx_get('ids');
+        if(!$aIds || !is_array($aIds))
+            return echoJson(array());
+
+        $oAccount = BxDolAccount::getInstance();
+
+        $iAffected = 0;
+        $aIdsAffected = array();
+        foreach($aIds as $iId){
+            if (BxDolAccount::isNeedConfirmEmail()) {
+                if($oAccount->updateEmailConfirmed(true, true, $iId)) {
+                    $aIdsAffected[] = $iId;
+                    $iAffected++;  
+                }
+            }
+
+            if (BxDolAccount::isNeedConfirmPhone()){
+                if($oAccount->updatePhoneConfirmed(true, $iId)) {
+                    $aIdsAffected[] = $iId;
+                    $iAffected++;  
+                }
+            }
+        }
+		echoJson($iAffected ? array('grid' => $this->getCode(false), 'blink' => $aIdsAffected) : array('msg' => _t($CNF['T']['grid_action_err_perform'])));
+    }
+    
+    public function performActionResendCemail()
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        $aIds = bx_get('ids');
+        if(!$aIds || !is_array($aIds))
+            return echoJson(array());
+
+        $oAccount = BxDolAccount::getInstance();
+
+        $iAffected = 0;
+        $aIdsAffected = array();
+        foreach($aIds as $iId)
+            if($oAccount->sendConfirmationEmail($iId)) {
+                $aIdsAffected[] = $iId;
+                $iAffected++;  
+            }
+
+        echoJson($iAffected ? array('grid' => $this->getCode(false), 'blink' => $aIdsAffected) : array('msg' => _t($CNF['T']['grid_action_err_perform'])));
+    }
+
+    public function performActionResetPassword()
+    {
+    	$aIds = bx_get('ids');
+        if(!$aIds || !is_array($aIds))
+            return echoJson(array());
+
+        $iId = $aIds[0];
+        $oAccount = BxDolAccount::getInstance($iId);
+        if(!$oAccount)
+            return echoJson(array());
+
+        $aRes = array();
+        $sPwd = genRndPwd();
+        if (BxDolAccount::getInstance()->updatePassword($sPwd, $iId)){
+            $sPopupId = $this->_oModule->_oConfig->getHtmlIds('password_popup');
+            $sPopupTitle = _t('_bx_accounts_form_display_account_settings_password_popup');
+            $sPopupContent = $this->_oModule->_oTemplate->parseHtmlByName('reset_password.html', array(
+                'js_object' => $this->_oModule->_oConfig->getJsObject('main'),
+                'html_id_text' => $this->_oModule->_oConfig->getHtmlIds('password_text'),
+                'html_id_button' => $this->_oModule->_oConfig->getHtmlIds('password_button'),
+                'password' => $sPwd,
+            ));
+
+            $aRes = array('popup' => BxTemplStudioFunctions::getInstance()->popupBox($sPopupId, $sPopupTitle, $sPopupContent));
+        }
+        else 
+            $aRes = array('msg' => _t('_bx_accnt_grid_action_err_perform'));
+
+        return echoJson($aRes);
+    }
+
+    public function performActionResendRemail()
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        $aIds = bx_get('ids');
+        if(!$aIds || !is_array($aIds))
+            return echoJson(array());
+
+        $oAccount = BxDolAccount::getInstance();
+
+        $iAffected = 0;
+        $aIdsAffected = array();
+        foreach($aIds as $iId)
+            if($oAccount->sendResetPasswordEmail($iId)) {
+                $aIdsAffected[] = $iId;
+                $iAffected++;  
+            }
+
+        echoJson($iAffected ? array('grid' => $this->getCode(false), 'blink' => $aIdsAffected) : array('msg' => _t($CNF['T']['grid_action_err_perform'])));
+    }
+
+    public function performActionUnlockAccount()
+    {
+    	$aIds = bx_get('ids');
+        if(!$aIds || !is_array($aIds)) {
+            echoJson(array());
+            return;
+        }
+
+        $oAccountQuery = BxDolAccountQuery::getInstance();
+        foreach($aIds as $iId) {
+            $oAccount = BxDolAccount::getInstance($iId);
+            if(!$oAccount)
+                continue;
+
+            if ($oAccount->isLocked()){
+                $oAccountQuery->unlockAccount($iId);
+            }
+            
+            $oAccount->doAudit($iId, '_sys_audit_action_account_unlock');
+        }
+
+        return echoJson(array('grid' => $this->getCode(false), 'blink' => $aIds));
+    }
+
+    public function performActionSetOperatorRole()
+    {
+    	$aIds = bx_get('ids');
+        if(!$aIds || !is_array($aIds))
+            return echoJson(array());
+        
+        $oUtils = BxDolStudioRolesUtils::getInstance();
+
+        $aRoles = $oUtils->getRoles();
+        if(empty($aRoles) || !is_array($aRoles))
+            return echoJson(array('msg' => _t('_sys_txt_error_occured')));
+
+        $iId = (int)array_shift($aIds);
+
+        $sPopupName = str_replace('_', '-', $this->MODULE) . '-set-role-popup';
+        $sPopupContent = $this->_oModule->_oTemplate->getPopupSetRole($aRoles, $iId, $oUtils->getRole($iId));
+
+        return echoJson(array('popup' => array(
+            'html' => BxTemplFunctions::getInstance()->transBox($sPopupName, $sPopupContent),
+            'options' => array(
+                'closeOnOuterClick' => true,
+                'removeOnClose' => true
+            )
+        )));
+    }
+
+    public function performActionSetOperatorRoleSubmit()
+    {
+        $aIds = bx_get('ids');
+        if(!$aIds || !is_array($aIds))
+            return echoJson(array());
+
+        $iId = (int)array_shift($aIds);
+        if(!$iId)
+            return echoJson(array('msg' => _t('_sys_txt_error_occured')));
+
+        if(!BxDolStudioRolesUtils::getInstance()->setRole($iId, bx_process_input(bx_get('role'), BX_DATA_INT)))
+            return echoJson(array('msg' => _t('_error occured')));
+
+        echoJson(array('grid' => $this->getCode(false), 'blink' => $iId));
+    }
+
+    public function performActionMakeOperator()
+    {
+    	$this->_performActionChangeRole(3);
+    }
+
+    public function performActionUnmakeOperator()
+    {
+    	$this->_performActionChangeRole(1);
+    }
+
+    protected function _performActionChangeRole($iRole)
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        $aIds = bx_get('ids');
+        if(!$aIds || !is_array($aIds))
+            return echoJson(array());
+
+        $oAccount = BxDolAccount::getInstance();
+        $oUtils = BxDolStudioRolesUtils::getInstance();
+
+        $iAffected = 0;
+        $aIdsAffected = array();
+        foreach($aIds as $iId) {
+            if(!$this->_oModule->_oDb->updateAccount(array('role' => $iRole), array('id' => $iId))) 
+                continue;
+
+            $oUtils->setRole($iId, $iRole == 3 ? BX_DOL_STUDIO_ROLE_OPERATOR : 0);
+
+            $oAccount->doAudit($iId, '_sys_audit_action_account_change_role_to_' . $iRole);
+
+            $aIdsAffected[] = $iId;
+            $iAffected++;
+        }
+
+        echoJson($iAffected ? array('grid' => $this->getCode(false), 'blink' => $aIdsAffected) : array('msg' => _t($CNF['T']['grid_action_err_perform'])));
+    }
+
+    protected function _performActionEnable($isChecked)
+    {
+    	$CNF = &$this->_oModule->_oConfig->CNF;
+
+    	$aIds = bx_get('ids');
+        if(!$aIds || !is_array($aIds)) {
+            echoJson(array());
+            return;
+        }
+        $iAffected = 0;
+        $aIdsAffected = array();
+        foreach($aIds as $iId)
+        	if($this->_enable($iId, $isChecked)) {
+        		$aIdsAffected[] = $iId;
+        		$iAffected++;
+                
+                $oAccount = BxDolAccount::getInstance($iId);
+                $oAccount->doAudit($iId, '_sys_audit_action_account_' . $isChecked ? 'activated' : 'suspended');
+        	}
+
+        echoJson($iAffected ? array('grid' => $this->getCode(false), 'blink' => $aIdsAffected) : array('msg' => _t($CNF['T']['grid_action_err_perform'])));
+    }
+
+    protected function _enable($mixedId, $isChecked)
+    {
+    	$oProfile = BxDolProfile::getInstanceAccountProfile($mixedId);
+    	if(!$oProfile)
+    	    return false;
+
+        $iAction = BX_PROFILE_ACTION_MANUAL;
+        $sMethod = $isChecked ? 'activate' : 'suspend';
+        if(!$oProfile->$sMethod($iAction, 0 ,false))
+            return false;
+
+        sendMailTemplate('t_ChangeStatusAccount' . ucfirst($sMethod), $oProfile->getAccountObject()->id(), $oProfile->id(), array(), BX_EMAIL_SYSTEM);
+        
+        $aProfiles = $oProfile->getAccountObject()->getProfiles();
+        foreach($aProfiles as $aProfile){
+            BxDolProfile::getInstance($aProfile['id'])->$sMethod($iAction, 0 ,false);
+        }
+        
+    	return true;
+    }
+
+    //--- Layout methods ---//
+    protected function _getActionEditEmail($sType, $sKey, $a, $isSmall = false, $isDisabled = false, $aRow = array())
+    {
+        return '';
+    }
+    
+    protected function _getCellEmailConfirmed($mixedValue, $sKey, $aField, $aRow)
+    {
+    	$mixedValue = (int)$mixedValue == 1 ? '_Yes' : '_No';
+        return parent::_getCellDefault(_t($mixedValue), $sKey, $aField, $aRow);
+    }
+
+    protected function _getActionResetPassword($sType, $sKey, $a, $isSmall = false, $isDisabled = false, $aRow = array())
+    {
+        return '';
+    }
+
+    protected function _getActionResendRemail($sType, $sKey, $a, $isSmall = false, $isDisabled = false, $aRow = array())
+    {
+        if($sType == 'single')
+            return '';
+
+        return parent::_getActionDefault ($sType, $sKey, $a, $isSmall, $isDisabled, $aRow);
+    }
+
+    protected function _getActionUnlockAccount($sType, $sKey, $a, $isSmall = false, $isDisabled = false, $aRow = array())
+    {
+        return '';
+    }
+
+    protected function _getCellName($mixedValue, $sKey, $aField, $aRow)
+    {
+        $oAccount = BxDolAccount::getInstance($aRow['id']);
+        if ($oAccount)
+            $s = ($aRow['locked'] == 1 ? $this->_oTemplate->parseIcon("lock col-red1") . ' ' : '') . $oAccount->getDisplayName();
+        return parent::_getCellDefault ($s, $sKey, $aField, $aRow);
+    }
+    
+	protected function _getCellProfiles($mixedValue, $sKey, $aField, $aRow)
+    {
+        $s = $this->_oModule->_oTemplate->getProfilesByAccount($aRow);
+
+        return parent::_getCellDefault ($s, $sKey, $aField, $aRow);
+    }
+
+    protected function _getCellLogged($mixedValue, $sKey, $aField, $aRow)
+    {
+        $mixedValue = !empty($mixedValue) ? bx_time_js($mixedValue) : _t('_sys_not_available');
+
+        return parent::_getCellDefault($mixedValue, $sKey, $aField, $aRow);
+    } 
+    
+    protected function _getCellAdded($mixedValue, $sKey, $aField, $aRow)
+    {
+        $mixedValue = !empty($mixedValue) ? bx_time_js($mixedValue) : _t('_sys_not_available');
+
+        return parent::_getCellDefault($mixedValue, $sKey, $aField, $aRow);
+    } 
+    
+    protected function _getCellIsConfirmed($mixedValue, $sKey, $aField, $aRow)
+    {
+        $oAccount = BxDolAccount::getInstance($aRow['id']);
+        $s = "";
+        if ($oAccount)
+            $s = $oAccount->getCurrentConfirmationStatusValue();
+        return parent::_getCellDefault(_t('_bx_accnt_grid_confirmation_status_' . $s), $sKey, $aField, $aRow);
+    }
+
+    protected function _isCheckboxDisabled($aRow)
+    {
+        return false;
+    }
+
+	protected function _getContentInfo($iId)
+    {
+    	return BxDolAccountQuery::getInstance()->getInfoById($iId);
+    }
+
+	protected function _doDelete($iId, $aParams = array())
+    {
+    	return BxDolAccount::getInstance($iId)->delete(isset($aParams['with_content']) && $aParams['with_content'] === true);
+    }
+    
+    
+
+    protected function _addJsCss()
+    {
+        parent::_addJsCss();
+        
+        $this->_oTemplate->addJs(array(
+            'main.css'
+        ));
+
+        $this->_oTemplate->addJs(array(
+        	'jquery.form.min.js',
+            'clipboard.min.js',
+            'main.js'
+        ));
+    }
+
+    protected function _isVisibleGrid($a)
+    {
+        if(isAdmin())
+            return true;
+        
+        return parent::_isVisibleGrid($a);
+    }
+
+    protected function _exportToCsv($aIds, $aFields, $aTitles, $aConverters)
+    {
+        $sFileDiv = ';';
+        $sFileName = 'accounts-' . date('Y.m.d') . '.csv';
+        $sFilePath = BX_DIRECTORY_PATH_TMP . $sFileName;
+        $oFileHandler = fopen($sFilePath, 'w');
+        if(!$oFileHandler)
+            return false;
+
+        fputcsv($oFileHandler, $aTitles, $sFileDiv);
+
+        $aFieldsFlip = array_flip($aFields);
+        $oAccountQuery = BxDolAccountQuery::getInstance();
+
+        foreach($aIds as $iId) {
+            $aAccount = $oAccountQuery->getInfoById($iId);
+            if(empty($aAccount) || !is_array($aAccount))
+                continue;
+            
+            $aConvert = array_intersect_key($aConverters, $aAccount);
+            foreach($aConvert as $sField => $sMethod)
+                $aAccount[$sField] = $this->$sMethod($aAccount[$sField]);
+
+            fputcsv($oFileHandler, array_intersect_key($aAccount, $aFieldsFlip), $sFileDiv);
+        }
+
+        fclose($oFileHandler);
+
+        return array($sFilePath, BX_DOL_URL_ROOT . 'tmp/' . $sFileName);
+    }
+
+    protected function _exportToXml($aIds, $aFields, $aTitles, $aConverters)
+    {
+        $sFileName = 'accounts-' . date('Y.m.d') . '.xml';
+        $sFilePath = BX_DIRECTORY_PATH_TMP . $sFileName;
+        $oFileHandler = fopen($sFilePath, 'w');
+        if(!$oFileHandler)
+            return false;
+
+        $aFieldsFlip = array_flip($aFields);
+        $oAccountQuery = BxDolAccountQuery::getInstance();
+
+        $oXML = xmlwriter_open_memory();
+        xmlwriter_set_indent($oXML, 1);
+        xmlwriter_set_indent_string($oXML, '  ');
+        
+        xmlwriter_start_document($oXML, '1.0', 'UTF-8');
+        xmlwriter_start_element($oXML, 'accounts');
+
+        foreach($aIds as $iId) {
+            $aAccount = $oAccountQuery->getInfoById($iId);
+            if(empty($aAccount) || !is_array($aAccount))
+                continue;
+
+            $aConvert = array_intersect_key($aConverters, $aAccount);
+            foreach($aConvert as $sField => $sMethod)
+                $aAccount[$sField] = $this->$sMethod($aAccount[$sField]);
+
+            xmlwriter_start_element($oXML, 'account');
+            $aAccountFields = array_intersect_key($aAccount, $aFieldsFlip);
+            foreach($aAccountFields as $sAccountField => $sAccountValue) {
+                xmlwriter_start_element($oXML, $sAccountField);
+                xmlwriter_write_cdata($oXML, $sAccountValue);
+                xmlwriter_end_element($oXML);
+            }
+            xmlwriter_end_element($oXML);
+        }
+
+        xmlwriter_end_document($oXML);
+
+        fwrite($oFileHandler, xmlwriter_output_memory($oXML));
+        fclose($oFileHandler);
+
+        return array($sFilePath, BX_DOL_URL_ROOT . 'tmp/' . $sFileName);
+    }
+
+    protected function _exportFieldConverterAdded($mixedValue)
+    {
+        return $this->__exportFieldConverterDate($mixedValue);
+    }
+
+    protected function _exportFieldConverterChanged($mixedValue)
+    {
+        return $this->__exportFieldConverterDate($mixedValue);
+    }
+
+    protected function _exportFieldConverterLogged($mixedValue)
+    {
+        return $this->__exportFieldConverterDateTime($mixedValue);
+    }
+
+    protected function __exportFieldConverterDate($mixedValue)
+    {
+        return date('Y.m.d', $mixedValue);
+    }
+
+    protected function __exportFieldConverterDateTime($mixedValue)
+    {
+        return date('Y.m.d H:i', $mixedValue);
+    }
+}
+
+/** @} */

+ 160 - 0
modules/boonex/accounts/updates/12.0.3_12.0.4/source/classes/BxAccntModule.php

@@ -0,0 +1,160 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Accounts Accounts
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxAccntModule extends BxBaseModGeneralModule
+{
+    /**
+     * Constructor
+     */
+    function __construct($aModule)
+    {
+        parent::__construct($aModule);
+
+        $this->_oConfig->init($this->_oDb);
+    }
+
+    public function serviceGetSafeServices()
+    {
+        return array ();
+    }
+
+    public function serviceGetOptionsExportTo()
+    {
+        return array(
+            'csv' => _t('_bx_accnt_txt_export_to_csv'),
+            'xml' => _t('_bx_accnt_txt_export_to_xml'),
+        );
+    }
+
+    public function serviceGetOptionsExportFields()
+    {
+        $aResult = array();
+
+        $aFields = $this->_oDb->getAccountFields();
+        if(empty($aFields['original']) || !is_array($aFields['original']))
+            return $aResult;
+
+        foreach($aFields['original'] as $sField) {
+            $sLangKey = '_bx_accnt_txt_field_' . $sField;
+            $sLangString = _t($sLangKey);
+            if(strcmp($sLangKey, $sLangString) == 0)
+                continue;
+
+            $aResult[] = array('key' => $sField, 'value' => $sLangString);
+        }
+
+        return $aResult;
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_accounts Accounts
+     * @subsection bx_accounts-other Other
+     * @subsubsection bx_accounts-get_menu_addon_manage_tools get_menu_addon_manage_tools
+     * 
+     * @code bx_srv('bx_accounts', 'get_menu_addon_manage_tools', [...]); @endcode
+     * 
+     * Get number of 'unconfirmed' accounts for User End -> Dasboard page -> Manage block.
+     *
+     * @return integer number of 'unconfirmed' accounts
+     * 
+     * @see BxAccntModule::serviceGetMenuAddonManageTools
+     */
+    /** 
+     * @ref bx_accounts-get_menu_addon_manage_tools "get_menu_addon_manage_tools"
+     */
+    public function serviceGetMenuAddonManageTools()
+    {
+        bx_import('SearchResult', $this->_aModule);
+        $sClass = $this->_aModule['class_prefix'] . 'SearchResult';
+        $o = new $sClass();
+        $o->unsetPaginate();
+        $iNumTotal = $o->getNum();
+        
+        $o->fillFilters(array(
+            'unconfirmed' => 1,
+            'non_robot' => 'Robot'
+        ));
+      
+        return array('counter1_value' => $o->getNum(),'counter3_value' => $iNumTotal, 'counter1_caption' => _t('_bx_accnt_menu_dashboard_manage_tools_addon_counter1_caption'));
+    }
+    
+    public function checkAllowedConfirm(&$aDataEntry, $isPerformAction = false)
+    {
+    	$bAdmin = isAdmin();
+    	if(!$bAdmin || BxDolAccount::getInstance($aDataEntry['id'])->isConfirmed())
+    		return _t('_sys_txt_access_denied');
+
+    	return CHECK_ACTION_RESULT_ALLOWED;
+    }
+
+    public function checkAllowedDelete(&$aDataEntry, $isPerformAction = false)
+    {
+    	if(isAdmin() && (int)$aDataEntry['id'] == getLoggedId())
+    		return _t('_sys_txt_access_denied');
+
+        // check ACL
+        $aCheck = checkActionModule($this->_iProfileId, 'delete account', 'system', $isPerformAction);
+        if($aCheck[CHECK_ACTION_RESULT] != CHECK_ACTION_RESULT_ALLOWED)
+            return $aCheck[CHECK_ACTION_MESSAGE];
+
+        return CHECK_ACTION_RESULT_ALLOWED;
+    }
+
+    public function checkAllowedSetOperatorRole(&$aDataEntry, $isPerformAction = false)
+    {
+    	$bAdmin = isAdmin();
+        $iAccountId = getLoggedId();
+    	if(!$bAdmin || !BxDolStudioRolesUtils::getInstance()->isActionAllowed(BX_SRA_MANAGE_ROLES, $iAccountId) || (int)$aDataEntry['id'] == $iAccountId)
+            return _t('_sys_txt_access_denied');
+
+    	return CHECK_ACTION_RESULT_ALLOWED;
+    }
+
+    public function checkAllowedMakeOperator(&$aDataEntry, $isPerformAction = false)
+    {
+    	$bAdmin = isAdmin();
+        $iAccountId = getLoggedId();
+    	if(!$bAdmin || !BxDolStudioRolesUtils::getInstance()->isActionAllowed(BX_SRA_MANAGE_ROLES, $iAccountId) || (int)$aDataEntry['id'] == $iAccountId || (int)$aDataEntry['role'] == 3)
+            return _t('_sys_txt_access_denied');
+
+    	return CHECK_ACTION_RESULT_ALLOWED;
+    }
+
+    public function checkAllowedUnmakeOperator(&$aDataEntry, $isPerformAction = false)
+    {
+    	$bAdmin = isAdmin();
+        $iAccountId = getLoggedId();
+    	if(!$bAdmin || !BxDolStudioRolesUtils::getInstance()->isActionAllowed(BX_SRA_MANAGE_ROLES, $iAccountId) || (int)$aDataEntry['id'] == $iAccountId || (int)$aDataEntry['role'] != 3)
+            return _t('_sys_txt_access_denied');
+
+    	return CHECK_ACTION_RESULT_ALLOWED;
+    }
+    
+    public function checkAllowedUnlockAccount(&$aDataEntry, $isPerformAction = false)
+    {
+    	if((int)$aDataEntry['locked'] != 1)
+    		return _t('_sys_txt_access_denied');
+
+    	return CHECK_ACTION_RESULT_ALLOWED;
+    }
+    
+    public function isAllowDeleteOrDisable($iActorProfileId, $iTargetProfileId)
+    {
+        if (BxDolAcl::getInstance()->isMemberLevelInSet(array(MEMBERSHIP_ID_MODERATOR), $iActorProfileId) && BxDolAcl::getInstance()->isMemberLevelInSet(array(MEMBERSHIP_ID_MODERATOR, MEMBERSHIP_ID_ADMINISTRATOR), $iTargetProfileId))
+            return false;
+        
+        return true;    
+    }
+    
+}
+
+/** @} */

+ 88 - 0
modules/boonex/accounts/updates/12.0.3_12.0.4/source/classes/BxAccntSearchResult.php

@@ -0,0 +1,88 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Accounts Accounts
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxAccntSearchResult extends BxBaseModGeneralSearchResult
+{
+    function __construct($sMode = '', $aParams = false)
+    {
+        parent::__construct($sMode, $aParams);
+
+        $aConfirmed = array();
+        $aUnConfirmed = array();
+        $sCnfnType = getParam('sys_account_confirmation_type');
+        switch($sCnfnType) {
+            case 'email':
+                $aConfirmed = array('value' => '', 'field' => 'email_confirmed', 'operator' => '=');
+                $aUnConfirmed = array('value' => '', 'field' => 'email_confirmed', 'operator' => '<>');
+                break;
+            case 'phone':
+                $aConfirmed = array('value' => '', 'field' => 'phone_confirmed', 'operator' => '=');
+                $aUnConfirmed = array('value' => '', 'field' => 'phone_confirmed', 'operator' => '<>');
+                break;
+            case 'email_and_phone':
+                $aConfirmed = array('value' => '', 'field' => 'phone_confirmed` * `email_confirmed', 'operator' => '=');
+                $aUnConfirmed = array('value' => '', 'field' => 'phone_confirmed` * `email_confirmed', 'operator' => '<>');
+                break;
+        }
+        
+        $this->aCurrent =  array(
+            'name' => 'bx_accounts',
+            'module_name' => 'bx_accounts',
+            'object_metatags' => '',
+            'title' => _t('_bx_accnt_page_title_browse'),
+            'table' => 'sys_accounts',
+            'tableSearch' => 'sys_accounts',
+            'ownFields' => array(),
+            'searchFields' => array('name', 'email'),
+            'restriction' => array(
+                'confirmed' => $aConfirmed,
+        		'unconfirmed' => $aUnConfirmed,
+                'non_robot' => array('value' => '', 'field' => 'name', 'operator' => '<>'),
+            ),
+            'join' => array (),
+            'paginate' => array('perPage' => 20, 'start' => 0),
+            'sorting' => 'none',
+            'rss' => array(
+                'title' => '',
+                'link' => '',
+                'image' => '',
+                'profile' => 0,
+                'fields' => array (
+                    'Guid' => 'link',
+                    'Link' => 'link',
+                    'Title' => 'fullname',
+                    'DateTimeUTS' => 'added',
+                    'Desc' => 'fullname',
+                    'Picture' => 'picture',
+                ),
+            ),
+            'ident' => 'id'
+        );
+
+        $this->sFilterName = 'bx_accounts_filter';
+        $this->oModule = $this->getMain();
+
+        switch ($sMode) {
+            case '': // search results
+                $this->sBrowseUrl = BX_DOL_SEARCH_KEYWORD_PAGE;
+                $this->aCurrent['title'] = _t('_bx_accnt');
+                unset($this->aCurrent['paginate']['perPage'], $this->aCurrent['rss']);
+                break;
+
+            default:
+                $this->isError = true;
+        }
+
+        parent::__construct();
+    }
+}
+
+/** @} */

+ 45 - 0
modules/boonex/accounts/updates/12.0.3_12.0.4/source/classes/BxAccntStudioPage.php

@@ -0,0 +1,45 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Accounts Accounts
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+define('BX_DOL_STUDIO_MOD_TYPE_MANAGE', 'manage');
+
+class BxAccntStudioPage extends BxTemplStudioModule
+{
+    protected $_sModule;
+    protected $_oModule;
+
+    function __construct($sModule, $mixedPageName, $sPage = "")
+    {
+        $this->_sModule = 'bx_accounts';
+    	$this->_oModule = BxDolModule::getInstance($this->_sModule);
+
+        parent::__construct($sModule, $mixedPageName, $sPage);
+
+        $this->aMenuItems[BX_DOL_STUDIO_MOD_TYPE_MANAGE] = array('name' => BX_DOL_STUDIO_MOD_TYPE_MANAGE, 'icon' => 'wrench', 'title' => '_bx_accnt_menu_item_title_manage');
+    }
+
+    protected function getManage()
+    {
+        $sType = 'administration';
+
+        $sGrid = $this->_oModule->_oConfig->getGridObject($sType);
+        $oGrid = BxDolGrid::getObjectInstance($sGrid, BxDolStudioTemplate::getInstance());
+        if(!$oGrid)
+            return '';
+
+        $this->_oModule->_oTemplate->addStudioCss(array('manage_tools.css', 'main.css'));
+        $this->_oModule->_oTemplate->addStudioJs(array('manage_tools.js', 'main.js'));
+        $this->_oModule->_oTemplate->addStudioJsTranslation(array('_sys_grid_search'));
+        return $this->_oModule->_oTemplate->getJsCode('manage_tools', array('sObjNameGrid' => $sGrid)) . $oGrid->getCode();
+    }
+}
+
+/** @} */

+ 71 - 0
modules/boonex/accounts/updates/12.0.3_12.0.4/source/install/config.php

@@ -0,0 +1,71 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Accounts Accounts
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_accounts',
+    'title' => 'Accounts Manager',
+    'note' => 'Accounts Manager module.',
+    'version' => '12.0.4',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '12.1.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/accounts/',
+    'home_uri' => 'accounts',
+
+    'db_prefix' => 'bx_accnt_',
+    'class_prefix' => 'BxAccnt',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Accounts',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'uninstall' => array (
+        'execute_sql' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'enable' => array(
+        'execute_sql' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable' => array (
+        'execute_sql' => 1,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Dependencies Section
+     */
+    'dependencies' => array(),
+
+);
+
+/** @} */

+ 110 - 0
modules/boonex/accounts/updates/12.0.3_12.0.4/source/install/langs/en.xml

@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources name="en" flag="gb" title="English">
+    <string name="_bx_accnt"><![CDATA[Accounts]]></string>
+    <string name="_bx_accounts"><![CDATA[Accounts]]></string>
+
+    <string name="_bx_accounts_option_export_to"><![CDATA[Export to]]></string>
+    <string name="_bx_accounts_option_export_fields"><![CDATA[Export fields]]></string>
+
+    <string name="_bx_accounts_form_display_account_settings_email_popup"><![CDATA[Edit Email]]></string>
+    <string name="_bx_accounts_form_display_account_create_popup"><![CDATA[Create new Account]]></string>
+    <string name="_bx_accounts_form_display_account_settings_password_popup"><![CDATA[Reset Password]]></string>
+
+    <string name="_bx_accnt_page_title_sys_manage_administration"><![CDATA[Manage All Accounts]]></string>
+    <string name="_bx_accnt_page_title_manage"><![CDATA[Manage Accounts]]></string>
+    <string name="_bx_accnt_page_title_browse"><![CDATA[Accounts]]></string>
+
+    <string name="_bx_accnt_page_block_title_system_manage_administration"><![CDATA[Manage All Accounts]]></string>
+    <string name="_bx_accnt_page_block_title_manage"><![CDATA[Manage Accounts]]></string>
+
+    <string name="_bx_accnt_menu_set_title_manage_tools"><![CDATA[Manage Tools Submenu]]></string>
+    <string name="_bx_accnt_menu_title_manage_tools"><![CDATA[Manage Tools Submenu]]></string>
+    <string name="_bx_accnt_menu_item_title_system_resend_cemail"><![CDATA[Resend Confirmation]]></string>
+    <string name="_bx_accnt_menu_item_title_resend_cemail"><![CDATA[Resend Confirmation]]></string>
+    <string name="_bx_accnt_menu_item_title_system_confirm"><![CDATA[Confirm]]></string>
+    <string name="_bx_accnt_menu_item_title_confirm"><![CDATA[Confirm]]></string>
+    <string name="_bx_accnt_menu_item_title_system_edit_email"><![CDATA[Edit Email]]></string>
+    <string name="_bx_accnt_menu_item_title_edit_email"><![CDATA[Edit Email]]></string>
+    <string name="_bx_accnt_menu_item_title_system_reset_password"><![CDATA[Reset Password]]></string>
+    <string name="_bx_accnt_menu_item_title_reset_password"><![CDATA[Reset Password]]></string>
+    <string name="_bx_accnt_menu_item_title_system_resend_remail"><![CDATA[Resend Reset Password]]></string>
+    <string name="_bx_accnt_menu_item_title_resend_remail"><![CDATA[Resend Reset Password]]></string>
+    <string name="_bx_accnt_menu_item_title_system_unlock_account"><![CDATA[Unlock]]></string>
+    <string name="_bx_accnt_menu_item_title_unlock_account"><![CDATA[Unlock]]></string>
+    <string name="_bx_accnt_menu_item_title_system_delete"><![CDATA[Delete]]></string>
+    <string name="_bx_accnt_menu_item_title_delete"><![CDATA[Delete]]></string>
+    <string name="_bx_accnt_menu_item_title_system_delete_with_content"><![CDATA[Delete With Content]]></string>
+    <string name="_bx_accnt_menu_item_title_delete_with_content"><![CDATA[Delete With Content]]></string>
+    <string name="_bx_accnt_menu_item_title_system_make_operator"><![CDATA[Make Operator]]></string>
+    <string name="_bx_accnt_menu_item_title_make_operator"><![CDATA[Make Operator]]></string>
+    <string name="_bx_accnt_menu_item_title_system_unmake_operator"><![CDATA[Unmake Operator]]></string>
+    <string name="_bx_accnt_menu_item_title_unmake_operator"><![CDATA[Unmake Operator]]></string>
+    <string name="_bx_accnt_menu_item_title_system_set_operator_role"><![CDATA[Set Operator Role]]></string>
+    <string name="_bx_accnt_menu_item_title_set_operator_role"><![CDATA[Set Operator Role]]></string>
+    <string name="_bx_accnt_menu_item_title_system_admt_accounts"><![CDATA[Accounts]]></string>
+    <string name="_bx_accnt_menu_item_title_admt_accounts"><![CDATA[Accounts]]></string>
+    <string name="_bx_accnt_menu_item_title_manage"><![CDATA[Manage]]></string>
+    <string name="_bx_accnt_menu_dashboard_manage_tools_addon_counter1_caption"><![CDATA[unconfirmed]]></string>
+
+    <string name="_bx_accnt_acl_action_edit_any_account"><![CDATA[Edit Any Account]]></string>
+
+    <string name="_bx_accnt_grid_filter_item_title_adm_select_one_filter1"><![CDATA[All Statuses]]></string>
+    <string name="_bx_accnt_grid_filter_item_title_adm_select_one_filter2"><![CDATA[All]]></string>
+    <string name="_bx_accnt_grid_filter_item_title_adm_active"><![CDATA[Active]]></string>
+    <string name="_bx_accnt_grid_filter_item_title_adm_operators"><![CDATA[Operators]]></string>
+    <string name="_bx_accnt_grid_filter_item_title_adm_pending"><![CDATA[Pending]]></string>
+    <string name="_bx_accnt_grid_filter_item_title_adm_suspended"><![CDATA[Suspended]]></string>    
+    <string name="_bx_accnt_grid_filter_item_title_adm_unconfirmed"><![CDATA[Unconfirmed]]></string>
+    <string name="_bx_accnt_grid_filter_item_title_adm_locked"><![CDATA[Locked]]></string>
+    <string name="_bx_accnt_grid_filter_item_title_adm_without_profile"><![CDATA[Without profile]]></string>
+    <string name="_bx_accnt_grid_column_title_adm_active"><![CDATA[Active]]></string>
+    <string name="_bx_accnt_grid_column_title_adm_name"><![CDATA[Name]]></string>
+    <string name="_bx_accnt_grid_column_title_adm_email"><![CDATA[Email]]></string>
+    <string name="_bx_accnt_grid_column_title_adm_ip"><![CDATA[IP]]></string>
+
+    <string name="_bx_accnt_grid_column_title_adm_is_confirmed"><![CDATA[Confirmed]]></string>
+    <string name="_bx_accnt_grid_column_title_adm_profiles"><![CDATA[Profiles]]></string>
+    <string name="_bx_accnt_grid_column_title_adm_logged"><![CDATA[Last Logged]]></string>
+    <string name="_bx_accnt_grid_column_title_adm_added"><![CDATA[Created]]></string>
+    <string name="_bx_accnt_grid_action_title_adm_activate"><![CDATA[Activate]]></string>
+    <string name="_bx_accnt_grid_action_title_adm_suspend"><![CDATA[Suspend]]></string>
+    <string name="_bx_accnt_grid_action_title_adm_confirm"><![CDATA[Confirm]]></string>
+    <string name="_bx_accnt_grid_action_title_adm_edit_email"><![CDATA[Edit Email]]></string>
+    <string name="_bx_accnt_grid_action_title_adm_export"><![CDATA[Export]]></string>
+    <string name="_bx_accnt_grid_action_title_adm_resend_cemail"><![CDATA[Resend Confirmation]]></string>
+    <string name="_bx_accnt_grid_action_title_adm_resend_remail"><![CDATA[Resend Reset Password]]></string>
+    <string name="_bx_accnt_grid_action_title_adm_reset_password"><![CDATA[Reset Password]]></string>
+    <string name="_bx_accnt_grid_action_title_adm_unlock_account"><![CDATA[Unlock]]></string>
+    <string name="_bx_accnt_grid_action_title_adm_delete"><![CDATA[Delete]]></string>
+    <string name="_bx_accnt_grid_action_title_adm_delete_with_content"><![CDATA[Delete With Content]]></string>
+    <string name="_bx_accnt_grid_action_title_adm_more_actions"><![CDATA[More Actions]]></string>
+    <string name="_bx_accnt_grid_action_title_adm_more_add"><![CDATA[Add new]]></string>
+    <string name="_bx_accnt_grid_action_err_delete"><![CDATA[Cannot delete the selected account(s).]]></string>
+    <string name="_bx_accnt_grid_action_err_perform"><![CDATA[Cannot perform the action for selected account(s).]]></string>
+    <string name="_bx_accnt_grid_action_unlock_successed"><![CDATA[Successfully unlocked]]></string>
+    <string name="_bx_accnt_grid_action_unlock_error"><![CDATA[Account is not blocked]]></string>
+    <string name="_bx_accnt_grid_confirmation_status_none"><![CDATA[No]]></string>
+    <string name="_bx_accnt_grid_confirmation_status_email"><![CDATA[Email]]></string>
+    <string name="_bx_accnt_grid_confirmation_status_phone"><![CDATA[Phone]]></string>
+    <string name="_bx_accnt_grid_confirmation_status_email_and_phone"><![CDATA[All]]></string>
+
+    <string name="_bx_accnt_form_login_input_caption_system_email_confirmed"><![CDATA[Email confirmed]]></string>
+    <string name="_bx_accnt_form_account_input_email_confirmed"><![CDATA[Email confirmed]]></string>
+ 
+    <string name="_bx_accnt_txt_more"><![CDATA[{0} more]]></string>
+    <string name="_bx_accnt_txt_see_more"><![CDATA[See more]]></string>
+    <string name="_bx_accnt_txt_copy_to_clipboard"><![CDATA[Copy to Clipboard]]></string>
+    <string name="_bx_accnt_txt_not_operator"><![CDATA[Not an Operator]]></string>
+    <string name="_bx_accnt_txt_export_to_csv"><![CDATA[CSV]]></string>
+    <string name="_bx_accnt_txt_export_to_xml"><![CDATA[XML]]></string>
+    <string name="_bx_accnt_txt_field_name"><![CDATA[Name]]></string>
+    <string name="_bx_accnt_txt_field_email"><![CDATA[Email]]></string>
+    <string name="_bx_accnt_txt_field_email_confirmed"><![CDATA[Email Confirmed]]></string>
+    <string name="_bx_accnt_txt_field_phone"><![CDATA[Phone]]></string>
+    <string name="_bx_accnt_txt_field_receive_updates"><![CDATA[Receive Updates]]></string>
+    <string name="_bx_accnt_txt_field_receive_news"><![CDATA[Receive News]]></string>
+    <string name="_bx_accnt_txt_field_added"><![CDATA[Added]]></string>
+    <string name="_bx_accnt_txt_field_changed"><![CDATA[Changed]]></string>
+    <string name="_bx_accnt_txt_field_logged"><![CDATA[Logged]]></string>
+    <string name="_bx_accnt_txt_field_ip"><![CDATA[IP]]></string>
+</resources>

+ 31 - 0
modules/boonex/accounts/updates/12.0.3_12.0.4/source/install/sql/disable.sql

@@ -0,0 +1,31 @@
+SET @sName = 'bx_accounts';
+
+
+-- SETTINGS
+SET @iTypeId = (SELECT `ID` FROM `sys_options_types` WHERE `name` = @sName LIMIT 1);
+SET @iCategId = (SELECT `ID` FROM `sys_options_categories` WHERE `type_id` = @iTypeId LIMIT 1);
+DELETE FROM `sys_options` WHERE `category_id` = @iCategId;
+DELETE FROM `sys_options_categories` WHERE `type_id` = @iTypeId;
+DELETE FROM `sys_options_types` WHERE `id` = @iTypeId;
+
+
+-- PAGES
+DELETE FROM `sys_objects_page` WHERE `module` = @sName;
+DELETE FROM `sys_pages_blocks` WHERE `module` = @sName;
+
+
+-- MENU
+DELETE FROM `sys_objects_menu` WHERE `module` = @sName;
+DELETE FROM `sys_menu_sets` WHERE `module` = @sName;
+DELETE FROM `sys_menu_items` WHERE `module` = @sName OR `set_name` IN('bx_accounts_menu_manage_tools');
+
+
+-- ACL
+DELETE `sys_acl_actions`, `sys_acl_matrix` FROM `sys_acl_actions`, `sys_acl_matrix` WHERE `sys_acl_matrix`.`IDAction` = `sys_acl_actions`.`ID` AND `sys_acl_actions`.`Module` = @sName;
+DELETE FROM `sys_acl_actions` WHERE `Module` = @sName;
+
+
+-- GRIDS
+DELETE FROM `sys_objects_grid` WHERE `object` IN ('bx_accounts_administration');
+DELETE FROM `sys_grid_fields` WHERE `object` IN ('bx_accounts_administration');
+DELETE FROM `sys_grid_actions` WHERE `object` IN ('bx_accounts_administration');

+ 105 - 0
modules/boonex/accounts/updates/12.0.3_12.0.4/source/install/sql/enable.sql

@@ -0,0 +1,105 @@
+SET @sName = 'bx_accounts';
+
+
+-- SETTINGS
+SET @iTypeOrder = (SELECT MAX(`order`) FROM `sys_options_types` WHERE `group` = 'modules');
+INSERT INTO `sys_options_types`(`group`, `name`, `caption`, `icon`, `order`) VALUES 
+('modules', @sName, '_bx_accounts', 'bx_accounts@modules/boonex/accounts/|std-icon.svg', IF(ISNULL(@iTypeOrder), 1, @iTypeOrder + 1));
+SET @iTypeId = LAST_INSERT_ID();
+
+INSERT INTO `sys_options_categories` (`type_id`, `name`, `caption`, `order`)
+VALUES (@iTypeId, @sName, '_bx_accounts', 1);
+SET @iCategId = LAST_INSERT_ID();
+
+INSERT INTO `sys_options` (`name`, `value`, `category_id`, `caption`, `type`, `check`, `check_error`, `extra`, `order`) VALUES
+('bx_accounts_export_to', 'csv', @iCategId, '_bx_accounts_option_export_to', 'select', '', '', 'a:2:{s:6:"module";s:11:"bx_accounts";s:6:"method";s:21:"get_options_export_to";}', 10),
+('bx_accounts_export_fields', 'name,email', @iCategId, '_bx_accounts_option_export_fields', 'list', '', '', 'a:2:{s:6:"module";s:11:"bx_accounts";s:6:"method";s:25:"get_options_export_fields";}', 20);
+
+
+-- PAGE: module administration
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_accounts_administration', '_bx_accnt_page_title_sys_manage_administration', '_bx_accnt_page_title_manage', @sName, 5, 192, 1, 'accounts-administration', 'page.php?i=accounts-administration', '', '', '', 0, 1, 0, '', '');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_accounts_administration', 1, @sName, '_bx_accnt_page_block_title_system_manage_administration', '_bx_accnt_page_block_title_manage', 11, 192, 'service', 'a:3:{s:6:\"module\";s:11:\"bx_accounts\";s:6:\"method\";s:12:\"manage_tools\";s:6:\"params\";a:1:{i:0;s:14:\"administration\";}}', 0, 1, 0);
+
+
+-- MENU: manage tools submenu
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_accounts_menu_manage_tools', '_bx_accnt_menu_title_manage_tools', 'bx_accounts_menu_manage_tools', @sName, 6, 0, 1, 'BxAccntMenuManageTools', 'modules/boonex/accounts/classes/BxAccntMenuManageTools.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_accounts_menu_manage_tools', @sName, '_bx_accnt_menu_set_title_manage_tools', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('bx_accounts_menu_manage_tools', @sName, 'edit-email', '_bx_accnt_menu_item_title_system_edit_email', '_bx_accnt_menu_item_title_edit_email', 'javascript:void(0)', 'javascript:{js_object}.onClickEditEmail({content_id}, this);', '_self', 'at', '', 192, 1, 0, 1),
+('bx_accounts_menu_manage_tools', @sName, 'resend-cemail', '_bx_accnt_menu_item_title_system_resend_cemail', '_bx_accnt_menu_item_title_resend_cemail', 'javascript:void(0)', 'javascript:{js_object}.onClickResendCemail({content_id}, this);', '_self', 'far envelope', '', 192, 1, 0, 2),
+('bx_accounts_menu_manage_tools', @sName, 'confirm', '_bx_accnt_menu_item_title_system_confirm', '_bx_accnt_menu_item_title_confirm', 'javascript:void(0)', 'javascript:{js_object}.onClickConfirm({content_id}, this);', '_self', 'fas check', '', 192, 1, 0, 3),
+('bx_accounts_menu_manage_tools', @sName, 'reset-password', '_bx_accnt_menu_item_title_system_reset_password', '_bx_accnt_menu_item_title_reset_password', 'javascript:void(0)', 'javascript:{js_object}.onClickResetPassword({content_id}, this);', '_self', 'eraser', '', 192, 1, 0, 4),
+('bx_accounts_menu_manage_tools', @sName, 'resend-remail', '_bx_accnt_menu_item_title_system_resend_remail', '_bx_accnt_menu_item_title_resend_remail', 'javascript:void(0)', 'javascript:{js_object}.onClickResendRemail({content_id}, this);', '_self', 'eraser', '', 192, 1, 0, 5),
+('bx_accounts_menu_manage_tools', @sName, 'unlock-account', '_bx_accnt_menu_item_title_system_unlock_account', '_bx_accnt_menu_item_title_unlock_account', 'javascript:void(0)', 'javascript:{js_object}.onClickUnlockAccount({content_id}, this);', '_self', 'unlock', '', 192, 1, 0, 6),
+('bx_accounts_menu_manage_tools', @sName, 'delete', '_bx_accnt_menu_item_title_system_delete', '_bx_accnt_menu_item_title_delete', 'javascript:void(0)', 'javascript:{js_object}.onClickDelete({content_id}, this);', '_self', 'far trash-alt', '', 192, 1, 0, 7),
+('bx_accounts_menu_manage_tools', @sName, 'delete-with-content', '_bx_accnt_menu_item_title_system_delete_with_content', '_bx_accnt_menu_item_title_delete_with_content', 'javascript:void(0)', 'javascript:{js_object}.onClickDeleteWithContent({content_id}, this);', '_self', 'far trash-alt', '', 192, 1, 0, 8),
+('bx_accounts_menu_manage_tools', @sName, 'make-operator', '_bx_accnt_menu_item_title_system_make_operator', '_bx_accnt_menu_item_title_make_operator', 'javascript:void(0)', 'javascript:{js_object}.onClickMakeOperator({content_id}, this);', '_self', 'wrench', '', 192, 0, 0, 9),
+('bx_accounts_menu_manage_tools', @sName, 'unmake-operator', '_bx_accnt_menu_item_title_system_unmake_operator', '_bx_accnt_menu_item_title_unmake_operator', 'javascript:void(0)', 'javascript:{js_object}.onClickUnmakeOperator({content_id}, this);', '_self', 'wrench', '', 192, 0, 0, 10),
+('bx_accounts_menu_manage_tools', @sName, 'set-operator-role', '_bx_accnt_menu_item_title_system_set_operator_role', '_bx_accnt_menu_item_title_set_operator_role', 'javascript:void(0)', 'javascript:{js_object}.onClickSetOperatorRole({content_id}, this);', '_self', 'wrench', '', 192, 1, 0, 11);
+
+-- MENU: dashboard manage tools
+SET @iManageMenuOrder = (SELECT IFNULL(MAX(`order`), 0) FROM `sys_menu_items` WHERE `set_name`='sys_account_dashboard_manage_tools' LIMIT 1);
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `addon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('sys_account_dashboard_manage_tools', @sName, 'accounts-administration', '_bx_accnt_menu_item_title_system_admt_accounts', '_bx_accnt_menu_item_title_admt_accounts', 'page.php?i=accounts-administration', '', '_self', 'at', 'a:2:{s:6:"module";s:11:"bx_accounts";s:6:"method";s:27:"get_menu_addon_manage_tools";}', '', 192, 1, 0, @iManageMenuOrder + 1);
+
+
+-- ACL
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+(@sName, 'edit any entry', NULL, '_bx_accnt_acl_action_edit_any_account', '', 1, 3);
+SET @iIdActionProfileEditAny = LAST_INSERT_ID();
+
+SET @iUnauthenticated = 1;
+SET @iAccount = 2;
+SET @iStandard = 3;
+SET @iUnconfirmed = 4;
+SET @iPending = 5;
+SET @iSuspended = 6;
+SET @iModerator = 7;
+SET @iAdministrator = 8;
+SET @iPremium = 9;
+
+INSERT INTO `sys_acl_matrix` (`IDLevel`, `IDAction`) VALUES
+
+-- edit any entry 
+(@iModerator, @iIdActionProfileEditAny),
+(@iAdministrator, @iIdActionProfileEditAny);
+
+
+-- GRIDS: administration
+INSERT INTO `sys_objects_grid` (`object`, `source_type`, `source`, `table`, `field_id`, `field_order`, `field_active`, `paginate_url`, `paginate_per_page`, `paginate_simple`, `paginate_get_start`, `paginate_get_per_page`, `filter_fields`, `filter_fields_translatable`, `filter_mode`, `sorting_fields`, `sorting_fields_translatable`, `visible_for_levels`, `show_total_count`, `override_class_name`, `override_class_file`) VALUES
+('bx_accounts_administration', 'Sql', 'SELECT `ta`.*, `tp`.`status` AS `status` FROM `sys_accounts` AS `ta` LEFT JOIN `sys_profiles` AS `tp` ON `ta`.`id`=`tp`.`account_id` AND `tp`.`type`=''system'' WHERE 1 ', 'sys_accounts', 'id', 'logged', 'status', '', 20, NULL, 'start', '', 'name,email,ip,phone', '', 'like', 'email_confirmed,logged,added', '', 192, 1, 'BxAccntGridAdministration', 'modules/boonex/accounts/classes/BxAccntGridAdministration.php');
+
+INSERT INTO `sys_grid_fields` (`object`, `name`, `title`, `width`, `translatable`, `chars_limit`, `params`, `order`) VALUES
+('bx_accounts_administration', 'checkbox', '_sys_select', '2%', 0, '', '', 1),
+('bx_accounts_administration', 'switcher', '_bx_accnt_grid_column_title_adm_active', '6%', 0, '', '', 2),
+('bx_accounts_administration', 'name', '_bx_accnt_grid_column_title_adm_name', '16%', 0, '16', '', 3),
+('bx_accounts_administration', 'email', '_bx_accnt_grid_column_title_adm_email', '22%', 0, '16', '', 4),
+('bx_accounts_administration', 'is_confirmed', '_bx_accnt_grid_column_title_adm_is_confirmed', '5%', 0, '', '', 5),
+('bx_accounts_administration', 'profiles', '_bx_accnt_grid_column_title_adm_profiles', '23%', 0, '', '', 6),
+('bx_accounts_administration', 'logged', '_bx_accnt_grid_column_title_adm_logged', '10%', 0, '15', '', 7),
+('bx_accounts_administration', 'added', '_bx_accnt_grid_column_title_adm_added', '10%', 0, '15', '', 8),
+('bx_accounts_administration', 'actions', '', '6%', 0, '', '', 9);
+
+INSERT INTO `sys_grid_actions` (`object`, `type`, `name`, `title`, `icon`, `icon_only`, `confirm`, `order`) VALUES
+('bx_accounts_administration', 'bulk', 'activate', '_bx_accnt_grid_action_title_adm_activate', '', 0, 0, 1),
+('bx_accounts_administration', 'bulk', 'suspend', '_bx_accnt_grid_action_title_adm_suspend', '', 0, 0, 2),
+('bx_accounts_administration', 'bulk', 'resend_cemail', '_bx_accnt_grid_action_title_adm_resend_cemail', '', 0, 0, 3),
+('bx_accounts_administration', 'bulk', 'resend_remail', '_bx_accnt_grid_action_title_adm_resend_remail', '', 0, 0, 4),
+('bx_accounts_administration', 'bulk', 'confirm', '_bx_accnt_grid_action_title_adm_confirm', '', 0, 0, 5),
+('bx_accounts_administration', 'bulk', 'delete', '_bx_accnt_grid_action_title_adm_delete', '', 0, 1, 6),
+('bx_accounts_administration', 'bulk', 'delete_with_content', '_bx_accnt_grid_action_title_adm_delete_with_content', '', 0, 1, 7),
+('bx_accounts_administration', 'bulk', 'export', '_bx_accnt_grid_action_title_adm_export', '', 0, 0, 8),
+('bx_accounts_administration', 'single', 'edit_email', '_bx_accnt_grid_action_title_adm_edit_email', '', 0, 0, 0),
+('bx_accounts_administration', 'single', 'reset_password', '_bx_accnt_grid_action_title_adm_reset_password', '', 0, 0, 0),
+('bx_accounts_administration', 'single', 'resend_remail', '_bx_accnt_grid_action_title_adm_resend_remail', '', 0, 0, 0),
+('bx_accounts_administration', 'single', 'unlock_account', '_bx_accnt_grid_action_title_adm_unlock_account', '', 0, 0, 0),
+('bx_accounts_administration', 'single', 'settings', '_bx_accnt_grid_action_title_adm_more_actions', 'cog', 1, 0, 2),
+('bx_accounts_administration', 'independent', 'add', '_bx_accnt_grid_action_title_adm_more_add', 'plus', 0, 0, 0),
+('bx_accounts_administration', 'independent', 'export', '_bx_accnt_grid_action_title_adm_export', 'download', 0, 0, 1);

+ 51 - 0
modules/boonex/acl/updates/12.0.1_12.0.2/install/config.php

@@ -0,0 +1,51 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'title' => 'Paid Levels',
+    'version_from' => '12.0.1',
+    'version_to' => '12.0.2',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '12.1.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/acl/updates/update_12.0.1_12.0.2/',
+    'home_uri' => 'acl_update_1201_1202',
+
+    'module_dir' => 'boonex/acl/',
+    'module_uri' => 'acl',
+
+    'db_prefix' => 'bx_acl_',
+    'class_prefix' => 'BxAcl',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 0,
+        'update_files' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 0,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Paid Levels',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

+ 13 - 0
modules/boonex/acl/updates/12.0.1_12.0.2/install/installer.php

@@ -0,0 +1,13 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+class BxAclUpdater extends BxDolStudioUpdater
+{
+    function __construct($aConfig)
+    {
+        parent::__construct($aConfig);
+    }
+}

+ 7 - 0
modules/boonex/acl/updates/12.0.1_12.0.2/install/langs/en.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources name="en" flag="gb" title="English">
+	<string_add name="_bx_acl_txt_cart_item_description"><![CDATA[Membership level on {0} site.]]></string_add>
+
+	<string_upd name="_bx_acl_grid_action_subscribe"><![CDATA[Subscribe]]></string_upd>
+	<string_upd name="_bx_acl_grid_action_subscribe_title"><![CDATA[Create a subscription with recurring billing]]></string_upd>
+</resources>

+ 609 - 0
modules/boonex/acl/updates/12.0.1_12.0.2/source/classes/BxAclModule.php

@@ -0,0 +1,609 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    PaidLevels Paid Levels
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+bx_import('BxDolAcl');
+
+define('BX_ACL_LICENSE_TYPE_SINGLE', 'single'); //--- one-time payment license
+define('BX_ACL_LICENSE_TYPE_RECURRING', 'recurring'); //--- recurring payment license
+
+class BxAclModule extends BxDolModule
+{
+    /**
+     * Constructor
+     */
+    function __construct($aModule)
+    {
+        parent::__construct($aModule);
+
+        $this->_oConfig->init($this->_oDb);
+    }
+
+    /**
+     * ACTION METHODS
+     */
+    public function actionCheckName()
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+    	$sName = bx_process_input(bx_get('name'));
+    	if(empty($sName))
+            return echoJson(array());
+
+        $sResult = '';
+
+        $iId = (int)bx_get('id');
+        if(!empty($iId)) {
+            $aPrice = $this->_oDb->getPrices(array('type' => 'by_id', 'value' => $iId)); 
+            if(strcmp($sName, $aPrice[$CNF['FIELD_NAME']]) == 0) 
+                $sResult = $sName;
+        }
+
+    	echoJson(array(
+            'name' => !empty($sResult) ? $sResult : $this->_oConfig->getPriceName($sName)
+    	));
+    }
+
+    /**
+     * SERVICE METHODS
+     */
+
+    public function serviceGetSafeServices()
+    {
+        return array (
+            'GetViewUrl' => '',
+            'GetBlockView' => '',
+            'GetMembershipActions' => '',
+        );
+    }
+
+	/**
+     * @page service Service Calls
+     * @section bx_acl Paid Levels
+     * @subsection bx_acl-other Other
+     * @subsubsection bx_acl-get_view_url get_view_url
+     * 
+     * @code bx_srv('bx_acl', 'get_view_url', [...]); @endcode
+     * 
+     * Get page URL with membership levels list.
+     *
+     * @return string with page URL.
+     * 
+     * @see BxAclModule::serviceGetViewUrl
+     */
+    /** 
+     * @ref bx_acl-get_view_url "get_view_url"
+     */
+	public function serviceGetViewUrl()
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+    	return  BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink($CNF['URL_VIEW']);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_acl Paid Levels
+     * @subsection bx_acl-page_blocks Page Blocks
+     * @subsubsection bx_acl-get_block_view get_block_view
+     * 
+     * @code bx_srv('bx_acl', 'get_block_view', [...]); @endcode
+     * 
+     * Get page block with a list of available ACL levels to purchase or get for Free. List is represented as table.
+     *
+     * @return HTML string with a list of ACL levels to display on the site, all necessary CSS and JS files are automatically added to the HEAD section of the site HTML. On error empty string is returned.
+     * 
+     * @see BxAclModule::serviceGetBlockView
+     */
+    /** 
+     * @ref bx_acl-get_block_view "get_block_view"
+     */
+	public function serviceGetBlockView()
+	{
+	    bx_require_authentication(false, false, $this->serviceGetViewUrl());
+
+		$sGrid = $this->_oConfig->getGridObject('view');
+		$oGrid = BxDolGrid::getObjectInstance($sGrid);
+        if(!$oGrid)
+            return '';
+
+        $this->_oTemplate->addCss(array('view.css'));
+		return array(
+            'content' => $oGrid->getCode()
+        );
+	}
+
+	/**
+     * @page service Service Calls
+     * @section bx_acl Paid Levels
+     * @subsection bx_acl-page_blocks Page Blocks
+     * @subsubsection bx_acl-get_membership_actions get_membership_actions
+     * 
+     * @code bx_srv('bx_acl', 'get_membership_actions', [...]); @endcode
+     * 
+     * Get page block with a list of current membership level's actions.
+     *
+     * @return HTML string with a list of actions to display on the site, all necessary CSS and JS files are automatically added to the HEAD section of the site HTML. On error empty string is returned.
+     * 
+     * @see BxAclModule::serviceGetMembershipActions
+     */
+    /** 
+     * @ref bx_acl-get_membership_actions "get_membership_actions"
+     */
+	public function serviceGetMembershipActions($iProfileId)
+	{
+		if($iProfileId != $this->getUserId())
+			return '';
+
+		return $this->_oTemplate->displayMembershipActions($iProfileId);
+	}
+
+	/**
+     * @page service Service Calls
+     * @section bx_acl Paid Levels
+     * @subsection bx_acl-payments Payments
+     * @subsubsection bx_acl-get_payment_data get_payment_data
+     * 
+     * @code bx_srv('bx_acl', 'get_payment_data', [...]); @endcode
+     * 
+     * Get an array with module's description. Is needed for payments processing module.
+     * 
+     * @return an array with module's description.
+     * 
+     * @see BxAclModule::serviceGetPaymentData
+     */
+    /** 
+     * @ref bx_acl-get_payment_data "get_payment_data"
+     */
+	public function serviceGetPaymentData()
+    {
+        return $this->_aModule;
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_acl Paid Levels
+     * @subsection bx_acl-payments Payments
+     * @subsubsection bx_acl-get_cart_item get_cart_item
+     * 
+     * @code bx_srv('bx_acl', 'get_cart_item', [...]); @endcode
+     * 
+     * Get an array with level's description. Is used in Shopping Cart in payments processing module.
+     * 
+     * @param $mixedItemId level's ID or Unique Name.
+     * @return an array with level's description. Empty array is returned if something is wrong.
+     * 
+     * @see BxAclModule::serviceGetCartItem
+     */
+    /** 
+     * @ref bx_acl-get_cart_item "get_cart_item"
+     */
+    public function serviceGetCartItem($mixedItemId)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        if(!$mixedItemId)
+            return array();
+
+        if(is_numeric($mixedItemId))
+            $aItem = $this->_oDb->getPrices(array('type' => 'by_id_full', 'value' => (int)$mixedItemId));
+        else 
+            $aItem = $this->_oDb->getPrices(array('type' => 'by_name_full', 'value' => $mixedItemId));
+
+        if(empty($aItem) || !is_array($aItem))
+            return array();
+
+        $sTitle = '';
+        if((int)$aItem['period'] == 0)
+            $sTitle = _t('_bx_acl_txt_cart_item_title_lifetime', _t($aItem['level_name']));
+        else
+            $sTitle = _t('_bx_acl_txt_cart_item_title', _t($aItem['level_name']), $aItem['period'], $aItem['period_unit']);
+
+        $sDescription = _t($aItem['level_description']);
+        if(empty($sDescription))
+            $sDescription = _t('_bx_acl_txt_cart_item_description', getParam('site_title'));
+
+        return array (
+            'id' => $aItem['id'],
+            'author_id' => $this->_oConfig->getOwner(),
+            'name' => $aItem['name'],
+            'title' => $sTitle,
+            'description' => $sDescription,
+            'url' => BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink($CNF['URL_VIEW']),
+            'price_single' => $aItem['price'],
+            'price_recurring' => $aItem['price'],
+            'period_recurring' => $aItem['period'],
+            'period_unit_recurring' => $aItem['period_unit'],
+            'trial_recurring' => $aItem['trial']
+        );
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_acl Paid Levels
+     * @subsection bx_acl-payments Payments
+     * @subsubsection bx_acl-get_cart_items get_cart_items
+     * 
+     * @code bx_srv('bx_acl', 'get_cart_items', [...]); @endcode
+     * 
+     * Get an array with levels' descriptions by seller. Is used in Manual Order Processing in payments processing module.
+     * 
+     * @param $iSellerId seller ID.
+     * @return an array with levels' descriptions. Empty array is returned if something is wrong or seller doesn't have any paid level.
+     * 
+     * @see BxAclModule::serviceGetCartItems
+     */
+    /** 
+     * @ref bx_acl-get_cart_items "get_cart_items"
+     */
+    public function serviceGetCartItems($iSellerId)
+    {
+    	$CNF = &$this->_oConfig->CNF;
+
+    	$iSellerIdSetting = $this->_oConfig->getOwner();
+    	if(empty($iSellerId) || ($iSellerId != $iSellerIdSetting && !isAdmin()))
+    	    return array();
+
+        $aItems = $this->_oDb->getPrices(array('type' => 'all_full'));
+        $sUrl = BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink($CNF['URL_VIEW']);
+
+        $aResult = array();
+        foreach($aItems as $aItem) {
+            $sTitle = '';
+            if((int)$aItem['period'] == 0)
+                $sTitle = _t('_bx_acl_txt_cart_item_title_lifetime', _t($aItem['level_name']));
+            else
+                $sTitle = _t('_bx_acl_txt_cart_item_title', _t($aItem['level_name']), $aItem['period'], $aItem['period_unit']);
+
+            $sDescription = _t($aItem['level_description']);
+            if(empty($sDescription))
+                $sDescription = _t('_bx_acl_txt_cart_item_description', getParam('site_title'));
+            
+            $aResult[] = array(
+                'id' => $aItem['id'],
+                'author_id' => $iSellerIdSetting,
+                'name' => $aItem['name'],
+                'title' => $sTitle,
+                'description' => $sDescription,
+                'url' => $sUrl,
+                'price_single' => $aItem['price'],
+                'price_recurring' => $aItem['price'],
+                'period_recurring' => $aItem['period'],
+                'period_unit_recurring' => $aItem['period_unit'],
+                'trial_recurring' => $aItem['trial']
+           );
+        }
+
+        return $aResult;
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_acl Paid Levels
+     * @subsection bx_acl-payments Payments
+     * @subsubsection bx_acl-register_cart_item register_cart_item
+     * 
+     * @code bx_srv('bx_acl', 'register_cart_item', [...]); @endcode
+     * 
+     * Register a processed single time payment inside the Paid Levels module. Is called with payment processing module after the payment was registered there.
+     * 
+     * @param $iClientId client ID.
+     * @param $iSellerId seller ID
+     * @param $iItemId item ID.
+     * @param $iItemCount the number of purchased items.
+     * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
+     * @param $sLicense license number genereted with payment processing module for internal usage
+     * @return an array with purchased prodict's description. Empty array is returned if something is wrong.
+     * 
+     * @see BxAclModule::serviceRegisterCartItem
+     */
+    /** 
+     * @ref bx_acl-register_cart_item "register_cart_item"
+     */
+    public function serviceRegisterCartItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense)
+    {
+        return $this->_serviceRegisterItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense, BX_ACL_LICENSE_TYPE_SINGLE);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_acl Paid Levels
+     * @subsection bx_acl-payments Payments
+     * @subsubsection bx_acl-register_subscription_item register_subscription_item
+     * 
+     * @code bx_srv('bx_acl', 'register_subscription_item', [...]); @endcode
+     * 
+     * Register a processed subscription (recurring payment) inside the Paid Levels module. Is called with payment processing module after the subscription was registered there.
+     * 
+     * @param $iClientId client ID.
+     * @param $iSellerId seller ID
+     * @param $iItemId item ID.
+     * @param $iItemCount the number of purchased items.
+     * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
+     * @param $sLicense license number genereted with payment processing module for internal usage
+     * @return an array with subscribed prodict's description. Empty array is returned if something is wrong.
+     * 
+     * @see BxAclModule::serviceRegisterSubscriptionItem
+     */
+    /** 
+     * @ref bx_acl-register_subscription_item "register_subscription_item"
+     */
+    public function serviceRegisterSubscriptionItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense)
+    {
+		return $this->_serviceRegisterItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense, BX_ACL_LICENSE_TYPE_RECURRING);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_acl Paid Levels
+     * @subsection bx_acl-payments Payments
+     * @subsubsection bx_acl-reregister_cart_item reregister_cart_item
+     * 
+     * @code bx_srv('bx_acl', 'reregister_cart_item', [...]); @endcode
+     * 
+     * Reregister a single time payment inside the Paid Levels module. Is called with payment processing module after the payment was reregistered there.
+     * 
+     * @param $iClientId client ID.
+     * @param $iSellerId seller ID
+     * @param $iItemIdOld old item ID.
+     * @param $iItemIdNew new item ID.
+     * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
+     * @return an array with purchased prodict's description. Empty array is returned if something is wrong.
+     * 
+     * @see BxAclModule::serviceReregisterCartItem
+     */
+    /** 
+     * @ref bx_acl-reregister_cart_item "reregister_cart_item"
+     */
+    public function serviceReregisterCartItem($iClientId, $iSellerId, $iItemIdOld, $iItemIdNew, $sOrder)
+    {
+        return $this->_serviceReregisterItem($iClientId, $iSellerId, $iItemIdOld, $iItemIdNew, $sOrder, BX_ACL_LICENSE_TYPE_SINGLE);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_acl Paid Levels
+     * @subsection bx_acl-payments Payments
+     * @subsubsection bx_acl-reregister_subscription_item reregister_subscription_item
+     * 
+     * @code bx_srv('bx_acl', 'reregister_subscription_item', [...]); @endcode
+     * 
+     * Reregister a subscription (recurring payment) inside the Paid Levels module. Is called with payment processing module after the subscription was reregistered there.
+     * 
+     * @param $iClientId client ID.
+     * @param $iSellerId seller ID
+     * @param $iItemIdOld old item ID.
+     * @param $iItemIdNew new item ID.
+     * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
+     * @return an array with subscribed prodict's description. Empty array is returned if something is wrong.
+     * 
+     * @see BxAclModule::serviceReregisterSubscriptionItem
+     */
+    /** 
+     * @ref bx_acl-reregister_subscription_item "reregister_subscription_item"
+     */
+    public function serviceReregisterSubscriptionItem($iClientId, $iSellerId, $iItemIdOld, $iItemIdNew, $sOrder)
+    {
+		return $this->_serviceReregisterItem($iClientId, $iSellerId, $iItemIdOld, $iItemIdNew, $sOrder, BX_ACL_LICENSE_TYPE_RECURRING);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_acl Paid Levels
+     * @subsection bx_acl-payments Payments
+     * @subsubsection bx_acl-unregister_cart_item unregister_cart_item
+     * 
+     * @code bx_srv('bx_acl', 'unregister_cart_item', [...]); @endcode
+     * 
+     * Unregister an earlier processed single time payment inside the Paid Levels module. Is called with payment processing module after the payment was unregistered there.
+     * 
+     * @param $iClientId client ID.
+     * @param $iSellerId seller ID
+     * @param $iItemId item ID.
+     * @param $iItemCount the number of purchased items.
+     * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
+     * @param $sLicense license number genereted with payment processing module for internal usage
+     * @return boolean value determining where the payment was unregistered or not.
+     * 
+     * @see BxAclModule::serviceUnregisterCartItem
+     */
+    /** 
+     * @ref bx_acl-unregister_cart_item "unregister_cart_item"
+     */
+    public function serviceUnregisterCartItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense)
+    {
+        return $this->_serviceUnregisterItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense, BX_ACL_LICENSE_TYPE_SINGLE);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_acl Paid Levels
+     * @subsection bx_acl-payments Payments
+     * @subsubsection bx_acl-unregister_subscription_item unregister_subscription_item
+     * 
+     * @code bx_srv('bx_acl', 'unregister_subscription_item', [...]); @endcode
+     * 
+     * Unregister an earlier processed subscription (recurring payment) inside the Paid Levels module. Is called with payment processing module after the subscription was unregistered there.
+     * 
+     * @param $iClientId client ID.
+     * @param $iSellerId seller ID
+     * @param $iItemId item ID.
+     * @param $iItemCount the number of purchased items.
+     * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
+     * @param $sLicense license number genereted with payment processing module for internal usage
+     * @return boolean value determining where the subscription was unregistered or not.
+     * 
+     * @see BxAclModule::serviceUnregisterSubscriptionItem
+     */
+    /** 
+     * @ref bx_acl-unregister_subscription_item "unregister_subscription_item"
+     */
+    public function serviceUnregisterSubscriptionItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense)
+    {
+    	return $this->_serviceUnregisterItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense, BX_ACL_LICENSE_TYPE_RECURRING); 
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_acl Paid Levels
+     * @subsection bx_acl-payments Payments
+     * @subsubsection bx_acl-cancel_subscription_item cancel_subscription_item
+     * 
+     * @code bx_srv('bx_acl', 'cancel_subscription_item', [...]); @endcode
+     * 
+     * Cancel an earlier processed subscription (recurring payment) inside the Paid Levels module. Is called with payment processing module after the subscription was canceled there.
+     * 
+     * @param $iClientId client ID.
+     * @param $iSellerId seller ID
+     * @param $iItemId item ID.
+     * @param $iItemCount the number of purchased items.
+     * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
+     * @return boolean value determining where the subscription was canceled or not.
+     * 
+     * @see BxAclModule::serviceCancelSubscriptionItem
+     */
+    /** 
+     * @ref bx_acl-cancel_subscription_item "cancel_subscription_item"
+     */
+    public function serviceCancelSubscriptionItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder)
+    {
+    	//TODO: Do something if it's necessary.
+    	return true;
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_acl Paid Levels
+     * @subsection bx_acl-other Other
+     * @subsubsection bx_acl-get_prices get_prices
+     * 
+     * @code bx_srv('bx_acl', 'get_prices', [...]); @endcode
+     * 
+     * Get array of available price options for membership levels
+     *
+     * @param $iLevelId membership level id
+     * @param $bFreeUnlimitedOnly get unlimited free pricing options only
+     * @return array of levels, or empty array of there are no any pricing options avaiulable
+     * 
+     * @see BxAclModule::serviceGetPrices
+     */
+    /** 
+     * @ref bx_acl-get_prices "get_prices"
+     */
+	public function serviceGetPrices($iLevelId = 0, $bFreeUnlimitedOnly = false)
+    {
+        $aParams = array(
+            'type' => $iLevelId ? 'by_level_id' : 'all_full',
+            'value' => $iLevelId,
+        );
+        $aPrices = $this->_oDb->getPrices($aParams, false);        
+
+        return array_filter($aPrices, function ($r) use ($bFreeUnlimitedOnly) {
+            return $bFreeUnlimitedOnly ? !$r['price'] && !$r['period'] : true;
+        });
+    }
+    
+    /**
+     * @page service Service Calls
+     * @section bx_acl Paid Levels
+     * @subsection bx_acl-other Other
+     * @subsubsection bx_acl-get_products_names get_products_names
+     * 
+     * @code bx_srv('bx_acl', 'get_products_names', [...]); @endcode
+     * 
+     * Get an array of products names.
+     * 
+     * @param $iVendorId return products of 1 vendor only
+     * @param $iLimit limit the result artay
+     * @return an array of products names
+     * 
+     * @see BxAclModule::serviceGetProductsNames
+     */
+    /** 
+     * @ref bx_acl-get_products_names "get_products_names"
+     */
+	public function serviceGetProductsNames($iVendorId = 0, $iLimit = 1000)
+    {
+    	return $this->_oDb->getProductsNames($iVendorId, $iLimit);
+    }
+
+    protected function _serviceRegisterItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense, $sType)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+    	$aItem = $this->serviceGetCartItem($iItemId);
+        if(empty($aItem) || !is_array($aItem))
+            return array();
+
+        $oAcl = BxDolAcl::getInstance();
+
+        $aItemInfo = $this->_oDb->getPrices(array('type' => 'by_id', 'value' => $iItemId));
+        $aMembershipInfo = $oAcl->getMemberMembershipInfo($iClientId);
+
+        $aPeriod = array('period' => (int)$aItemInfo['period'], 'period_unit' => $aItemInfo['period_unit']);
+        if($sType == BX_ACL_LICENSE_TYPE_RECURRING && (int)$aItemInfo['trial'] > 0 && (int)$aItemInfo['level_id'] != (int)$aMembershipInfo['id'])
+            $aPeriod = array('period' => (int)$aItemInfo['trial'], 'period_unit' => 'day', 'period_trial' => true);
+
+        $iReserve = (int)getParam($CNF['PARAM_RECURRING_RESERVE']);
+        if(!empty($iReserve))
+            $aPeriod['period_reserve'] = $iReserve;
+
+        if(!$oAcl->setMembership($iClientId, $aItemInfo['level_id'], $aPeriod, true, $sLicense))
+            return array();
+
+        return $aItem;
+    }
+
+    protected function _serviceReregisterItem($iClientId, $iSellerId, $iItemIdOld, $iItemIdNew, $sOrder, $sType)
+    {
+        $aItemNew = $this->serviceGetCartItem($iItemIdNew);
+        if(empty($aItemNew) || !is_array($aItemNew))
+			return array();
+
+        /*
+         * Note. Membership level cannot be reregistered immediately.
+         * it will be automatically changed in the end of current period.
+         */
+    	return $aItemNew;
+    }
+
+    protected function _serviceUnregisterItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense, $sType)
+    {
+    	$aItemInfo = $this->_oDb->getPrices(array('type' => 'by_id', 'value' => $iItemId));
+    	if(empty($aItemInfo) || !is_array($aItemInfo))
+			return false;
+
+    	return BxDolAcl::getInstance()->unsetMembership($iClientId, $aItemInfo['level_id'], $sLicense);
+    }
+
+    /**
+     * COMMON METHODS
+     */
+	public function getUserId()
+    {
+        return isLogged() ? bx_get_logged_profile_id() : 0;
+    }
+
+    public function getUserInfo($iUserId = 0)
+    {
+        $oProfile = BxDolProfile::getInstance($iUserId);
+        if (!$oProfile)
+            $oProfile = BxDolProfileUndefined::getInstance();
+
+        return array(
+            $oProfile->getDisplayName(),
+            $oProfile->getUrl(),
+            $oProfile->getThumb(),
+            $oProfile->getUnit()
+        );
+    }
+}
+
+/** @} */

+ 70 - 0
modules/boonex/acl/updates/12.0.1_12.0.2/source/install/config.php

@@ -0,0 +1,70 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    PaidLevels Paid Levels
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_acl',
+    'title' => 'Paid Levels',
+    'note' => 'Paid Levels module.',
+    'version' => '12.0.2',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '12.1.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/acl/',
+    'home_uri' => 'acl',
+
+    'db_prefix' => 'bx_acl_',
+    'class_prefix' => 'BxAcl',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Paid Levels',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'uninstall' => array (
+        'execute_sql' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'enable' => array(
+        'execute_sql' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable' => array (
+        'execute_sql' => 1,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Dependencies Section
+     */
+    'dependencies' => array(),
+);
+
+/** @} */

+ 102 - 0
modules/boonex/acl/updates/12.0.1_12.0.2/source/install/langs/en.xml

@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources name="en" flag="gb" title="English">
+	<string name="_bx_acl"><![CDATA[Paid Levels]]></string>
+
+
+        <!-- Option -->
+        <string name="_bx_acl_option_recurring_reserve"><![CDATA[Reserve (in days) to accept and process recurring payment notification]]></string>
+        <string name="_bx_acl_option_recurring_prioritize"><![CDATA[Prioritize recurring payments]]></string>
+
+
+	<!-- Pages -->
+	<string name="_bx_acl_page_title_sys_view"><![CDATA[Membership]]></string>
+	<string name="_bx_acl_page_title_view"><![CDATA[Membership]]></string>
+	<string name="_bx_acl_page_block_title_system_view"><![CDATA[Membership]]></string>
+	<string name="_bx_acl_page_block_title_view"><![CDATA[Membership]]></string>
+
+
+        <!-- Menus -->
+        <string name="_bx_acl_lmi_cpt_manage"><![CDATA[Manage]]></string>
+
+
+	<!-- Forms -->
+	<string name="_bx_acl_form_price"><![CDATA[Price]]></string>
+	<string name="_bx_acl_form_price_display_add"><![CDATA[Add]]></string>
+	<string name="_bx_acl_form_price_display_edit"><![CDATA[Edit]]></string>
+	<string name="_bx_acl_form_price_input_sys_id"><![CDATA[ID]]></string>
+	<string name="_bx_acl_form_price_input_sys_level_id"><![CDATA[Level ID]]></string>
+        <string name="_bx_acl_form_price_input_sys_name"><![CDATA[Name]]></string>
+	<string name="_bx_acl_form_price_input_name"><![CDATA[Name]]></string>
+	<string name="_bx_acl_form_price_input_inf_name"><![CDATA[Unique value which will be used in back end and API calls]]></string>
+        <string name="_bx_acl_form_price_input_err_name"><![CDATA[You need to enter a unique value here]]></string>
+	<string name="_bx_acl_form_price_input_sys_period"><![CDATA[Period]]></string>
+	<string name="_bx_acl_form_price_input_period"><![CDATA[Period]]></string>
+	<string name="_bx_acl_form_price_input_inf_period"><![CDATA[Use 0 for lifetime]]></string>
+	<string name="_bx_acl_form_price_input_sys_period_unit"><![CDATA[Period unit]]></string>
+	<string name="_bx_acl_form_price_input_period_unit"><![CDATA[Period unit]]></string>
+	<string name="_bx_acl_form_price_input_inf_period_unit"><![CDATA[Leave empty for lifetime level.]]></string>
+	<string name="_bx_acl_form_price_input_err_period_unit"><![CDATA[You need to select a period unit here.]]></string>
+	<string name="_bx_acl_form_price_input_sys_price"><![CDATA[Price]]></string>
+	<string name="_bx_acl_form_price_input_price"><![CDATA[Price]]></string>
+	<string name="_bx_acl_form_price_input_inf_price"><![CDATA[Use 0 or leave empty to create free level.]]></string>
+	<string name="_bx_acl_form_price_input_sys_trial"><![CDATA[Trial]]></string>
+    <string name="_bx_acl_form_price_input_trial"><![CDATA[Trial]]></string>
+    <string name="_bx_acl_form_price_input_inf_trial"><![CDATA[The number of days new customers should receive a free trial. Leave empty to disable trial period.]]></string>
+	<string name="_bx_acl_form_price_input_sys_do_submit"><![CDATA[Submit]]></string>
+	<string name="_bx_acl_form_price_input_do_submit"><![CDATA[Submit]]></string>
+	<string name="_bx_acl_form_price_input_sys_do_cancel"><![CDATA[Cancel]]></string>
+	<string name="_bx_acl_form_price_input_do_cancel"><![CDATA[Cancel]]></string>
+
+
+	<!-- Pre Lists -->
+	<string name="_bx_acl_pre_lists_period_units"><![CDATA[Billing Interval]]></string>
+	<string name="_bx_acl_pre_values_day"><![CDATA[day]]></string>
+	<string name="_bx_acl_pre_values_week"><![CDATA[week]]></string>
+	<string name="_bx_acl_pre_values_month"><![CDATA[month]]></string>
+	<string name="_bx_acl_pre_values_year"><![CDATA[year]]></string>
+
+
+	<!-- Grids -->
+	<string name="_bx_acl_grid_column_level_icon"><![CDATA[]]></string>
+	<string name="_bx_acl_grid_column_level_name"><![CDATA[Level]]></string>
+	<string name="_bx_acl_grid_column_name"><![CDATA[Name]]></string>
+	<string name="_bx_acl_grid_column_period"><![CDATA[Period]]></string>
+	<string name="_bx_acl_grid_column_price"><![CDATA[Price]]></string>
+	<string name="_bx_acl_grid_column_trial"><![CDATA[Trial]]></string>
+
+	<string name="_bx_acl_grid_action_add"><![CDATA[Add]]></string>
+	<string name="_bx_acl_grid_action_edit"><![CDATA[Edit]]></string>
+	<string name="_bx_acl_grid_action_delete"><![CDATA[Delete]]></string>
+	<string name="_bx_acl_grid_action_buy"><![CDATA[Buy]]></string>
+	<string name="_bx_acl_grid_action_buy_title"><![CDATA[One-time payment]]></string>
+	<string name="_bx_acl_grid_action_subscribe"><![CDATA[Subscribe]]></string>
+	<string name="_bx_acl_grid_action_subscribe_title"><![CDATA[Create a subscription with recurring billing]]></string>
+	<string name="_bx_acl_grid_action_choose"><![CDATA[Choose]]></string>
+    <string name="_bx_acl_grid_action_choose_title"><![CDATA[Switch to the level for free]]></string>
+
+	<string name="_bx_acl_popup_title_price_add"><![CDATA[Add Pricing Plan]]></string>
+	<string name="_bx_acl_popup_title_price_edit"><![CDATA[Edit Pricing Plan]]></string>
+
+
+	<!-- Menus -->
+	<string name="_bx_acl_menu_item_title_system_acl_view"><![CDATA[Membership]]></string>
+	<string name="_bx_acl_menu_item_title_acl_view"><![CDATA[Membership]]></string>
+
+
+	<!-- Common Texts -->
+	<string name="_bx_acl_msg_empty_owner"><![CDATA['Main seller' is empty. You need to mark some profile as 'Main seller' in Settings of currently active Payment app.]]></string>
+	<string name="_bx_acl_msg_performed"><![CDATA[The action was successfully performed.]]></string>
+	<string name="_bx_acl_err_price_duplicate"><![CDATA[Similar pricing plan is already exists.]]></string>
+	<string name="_bx_acl_err_cannot_perform"><![CDATA[An error appeared. Please report.]]></string>
+
+	<string name="_bx_acl_txt_select_level"><![CDATA[Select level...]]></string>
+	<string name="_bx_acl_txt_cart_item_title"><![CDATA[{0} ({1} {2})]]></string>
+        <string name="_bx_acl_txt_cart_item_title_lifetime"><![CDATA[{0} (lifetime)]]></string>
+        <string name="_bx_acl_txt_cart_item_description"><![CDATA[Membership level on {0} site.]]></string>
+	<string name="_bx_acl_txt_upgrade"><![CDATA[Upgrade]]></string>
+	<string name="_bx_acl_txt_manage"><![CDATA[Manage]]></string>
+	<string name="_bx_acl_txt_n_unit"><![CDATA[{0} ({1})]]></string>
+	<string name="_bx_acl_txt_none"><![CDATA[none]]></string>
+	<string name="_bx_acl_txt_free"><![CDATA[free]]></string>
+	<string name="_bx_acl_txt_lifetime"><![CDATA[lifetime]]></string>
+</resources>

+ 51 - 0
modules/boonex/ads/updates/12.0.0_12.0.1/install/config.php

@@ -0,0 +1,51 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'title' => 'Ads',
+    'version_from' => '12.0.0',
+    'version_to' => '12.0.1',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '12.1.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/ads/updates/update_12.0.0_12.0.1/',
+    'home_uri' => 'ads_update_1200_1201',
+
+    'module_dir' => 'boonex/ads/',
+    'module_uri' => 'ads',
+
+    'db_prefix' => 'bx_ads_',
+    'class_prefix' => 'BxAds',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_files' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Ads',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

+ 23 - 0
modules/boonex/ads/updates/12.0.0_12.0.1/install/installer.php

@@ -0,0 +1,23 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+class BxAdsUpdater extends BxDolStudioUpdater
+{
+    function __construct($aConfig)
+    {
+        parent::__construct($aConfig);
+    }
+
+    public function actionExecuteSql($sOperation)
+    {
+        if($sOperation == 'install') {
+            if(!$this->oDb->isFieldExists('bx_ads_videos', 'dimensions'))
+                $this->oDb->query("ALTER TABLE `bx_ads_videos` ADD `dimensions` varchar(12) NOT NULL AFTER `size`");
+        }
+
+        return parent::actionExecuteSql($sOperation);
+    }
+}

+ 4 - 0
modules/boonex/ads/updates/12.0.0_12.0.1/install/langs/en.xml

@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources name="en" flag="gb" title="English">
+	<string_add name="_bx_ads_alert_action_doInterest_personal"><![CDATA[Someone interested in your ad]]></string_add>
+</resources>

+ 2 - 0
modules/boonex/ads/updates/12.0.0_12.0.1/install/sql/install.sql

@@ -0,0 +1,2 @@
+-- STORAGES & TRANSCODERS
+UPDATE `sys_objects_storage` SET `params`='a:1:{s:6:"fields";a:1:{s:10:"dimensions";s:17:"getFileDimensions";}}' WHERE `object`='bx_ads_videos';

+ 150 - 0
modules/boonex/ads/updates/12.0.0_12.0.1/source/install/config.php

@@ -0,0 +1,150 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Ads Ads
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_ads',
+    'title' => 'Ads',
+    'note' => 'Ads module.',
+    'version' => '12.0.1',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '12.1.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/ads/',
+    'home_uri' => 'ads',
+
+    'db_prefix' => 'bx_ads_',
+    'class_prefix' => 'BxAds',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Ads',
+
+    /**
+     * List of page triggers.
+     */
+    'page_triggers' => array (
+    	'trigger_page_profile_view_entry',
+    ),
+    
+    /**
+     * Menu triggers.
+     */
+    'menu_triggers' => array(
+        'trigger_profile_view_submenu',
+        'trigger_group_view_submenu',
+    ),
+
+    /**
+     * Storage objects to automatically delete files from upon module uninstallation.
+     * Note. Don't add storage objects used in transcoder objects.
+     */
+    'storages' => array(
+        'bx_ads_covers',
+    	'bx_ads_photos',
+        'bx_ads_videos',
+        'bx_ads_files'
+    ),
+
+    /**
+     * Transcoders.
+     */
+    'transcoders' => array(
+        'bx_ads_preview',
+        'bx_ads_gallery',
+        'bx_ads_cover',
+
+        'bx_ads_preview_photos',
+        'bx_ads_gallery_photos', 
+
+        'bx_ads_videos_poster',
+        'bx_ads_videos_poster_preview',
+        'bx_ads_videos_mp4',
+        'bx_ads_videos_mp4_hd',
+
+        'bx_ads_preview_files',
+        'bx_ads_gallery_files'
+    ),
+
+    /**
+     * Extended Search Forms.
+     */
+    'esearches' => array(
+        'bx_ads',
+    	'bx_ads_cmts'
+    ),
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'uninstall' => array (
+    	'process_esearches' => 1,
+        'execute_sql' => 1,
+        'update_languages' => 1,
+        'update_relations' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'enable' => array(
+        'execute_sql' => 1,
+        'update_relations' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'enable_success' => array(
+        'process_menu_triggers' => 1,
+        'process_page_triggers' => 1,
+    	'process_esearches' => 1,
+        'register_transcoders' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable' => array (
+        'execute_sql' => 1,
+        'update_relations' => 1,
+        'unregister_transcoders' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable_failed' => array (
+        'register_transcoders' => 1,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Dependencies Section
+     */
+    'dependencies' => array(),
+
+    /**
+     * Relations Section
+     */
+    'relations' => array(
+    	'bx_timeline',
+    	'bx_notifications'
+    ),
+
+);
+
+/** @} */

+ 402 - 0
modules/boonex/ads/updates/12.0.0_12.0.1/source/install/langs/en.xml

@@ -0,0 +1,402 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources name="en" flag="gb" title="English">
+    <string name="_bx_ads"><![CDATA[Ads]]></string>
+    <string name="_bx_ads_cmts"><![CDATA[Ads' Comments]]></string>
+    <string name="_bx_ads_reactions"><![CDATA[Ads' Reactions]]></string>
+
+    <string name="_bx_ads_option_summary_chars"><![CDATA[Number of characters in auto-cropped ad summary]]></string>
+    <string name="_bx_ads_option_plain_summary_chars"><![CDATA[Number of characters in plain ad description when ad hasn't thumb]]></string>
+    <string name="_bx_ads_option_per_page_browse"><![CDATA[Number of items per page]]></string>
+    <string name="_bx_ads_option_per_page_profile"><![CDATA[Number of items on profile/group page]]></string>
+    <string name="_bx_ads_option_rss_num"><![CDATA[Number of items in RSS feed]]></string>
+    <string name="_bx_ads_option_searchable_fields"><![CDATA[Searchable fields for keyword search]]></string>
+    <string name="_bx_ads_option_lifetime"><![CDATA[Deactivate automatically after (in days)]]></string>
+    <string name="_bx_ads_option_internal_interested_notification"><![CDATA[Use internal notification about Interested action]]></string>
+
+    <string name="_bx_ads_form_category"><![CDATA[Category]]></string>
+    <string name="_bx_ads_form_category_display_add"><![CDATA[Add Category]]></string>
+    <string name="_bx_ads_form_category_display_edit"><![CDATA[Edit Category]]></string>
+    <string name="_bx_ads_form_category_display_delete"><![CDATA[Delete Category]]></string>
+    <string name="_bx_ads_form_category_input_sys_do_submit"><![CDATA[Submit]]></string>
+    <string name="_bx_ads_form_category_input_do_submit"><![CDATA[Submit]]></string>
+    <string name="_bx_ads_form_category_input_sys_do_cancel"><![CDATA[Cancel]]></string>
+    <string name="_bx_ads_form_category_input_do_cancel"><![CDATA[Cancel]]></string>
+    <string name="_bx_ads_form_category_input_sys_parent_id"><![CDATA[Parent]]></string>
+    <string name="_bx_ads_form_category_input_parent_id"><![CDATA[Parent category]]></string>
+    <string name="_bx_ads_form_category_input_parent_id_empty"><![CDATA[No parent]]></string>
+    <string name="_bx_ads_form_category_input_sys_title"><![CDATA[Title]]></string>
+    <string name="_bx_ads_form_category_input_title"><![CDATA[Title]]></string>
+    <string name="_bx_ads_form_category_input_title_err"><![CDATA[Title is essential. Please, fill in this field.]]></string>
+    <string name="_bx_ads_form_category_input_sys_text"><![CDATA[Text]]></string>
+    <string name="_bx_ads_form_category_input_text"><![CDATA[Text]]></string>
+    <string name="_bx_ads_form_category_input_sys_type"><![CDATA[Type]]></string>
+    <string name="_bx_ads_form_category_input_type"><![CDATA[Type]]></string>
+    <string name="_bx_ads_form_category_input_type_err"><![CDATA[Type is essential. Please, select a value for this field.]]></string>
+    <string name="_bx_ads_form_category_input_type_info"><![CDATA[Type determines a set of fields for entries in this category.]]></string>
+    <string name="_bx_ads_form_category_input_sys_type_clone"><![CDATA[Clone type]]></string>
+    <string name="_bx_ads_form_category_input_type_clone"><![CDATA[Clone type]]></string>
+    <string name="_bx_ads_form_category_input_sys_type_title"><![CDATA[Type title]]></string>
+    <string name="_bx_ads_form_category_input_type_title"><![CDATA[Type title]]></string>
+    <string name="_bx_ads_form_category_input_sys_icon"><![CDATA[Icon]]></string>
+    <string name="_bx_ads_form_category_input_icon"><![CDATA[Icon]]></string>
+    <string name="_bx_ads_form_category_input_sys_delete_confirm"><![CDATA[Delete confirmation]]></string>
+    <string name="_bx_ads_form_category_input_delete_confirm"><![CDATA[I am sure I want to delete this category]]></string>
+    <string name="_bx_ads_form_category_input_delete_confirm_info"><![CDATA[This action can not be undone]]></string>
+    <string name="_bx_ads_form_category_input_delete_confirm_error"><![CDATA[Please check this checkbox if you really want to delete the category]]></string>
+
+    <string name="_bx_ads_form_entry"><![CDATA[Ads]]></string>
+    <string name="_bx_ads_form_entry_display_add"><![CDATA[Add Ad]]></string>
+    <string name="_bx_ads_form_entry_display_delete"><![CDATA[Delete Ad]]></string>
+
+    <string name="_bx_ads_form_entry_price_display_add"><![CDATA[With Price: Add]]></string>
+    <string name="_bx_ads_form_entry_price_display_edit"><![CDATA[With Price: Edit]]></string>
+    <string name="_bx_ads_form_entry_price_display_view"><![CDATA[With Price: View]]></string>
+
+    <string name="_bx_ads_form_entry_price_year_display_add"><![CDATA[With Price and Year: Add]]></string>
+    <string name="_bx_ads_form_entry_price_year_display_edit"><![CDATA[With Price and Year: Edit]]></string>
+    <string name="_bx_ads_form_entry_price_year_display_view"><![CDATA[With Price and Year: View]]></string>
+
+    <string name="_bx_ads_form_entry_input_author"><![CDATA[Author]]></string>
+    <string name="_bx_ads_form_entry_input_sys_do_submit"><![CDATA[Submit]]></string>
+    <string name="_bx_ads_form_entry_input_do_submit"><![CDATA[Submit]]></string>
+    <string name="_bx_ads_form_entry_input_sys_title"><![CDATA[Title]]></string>
+    <string name="_bx_ads_form_entry_input_title"><![CDATA[Title]]></string>
+    <string name="_bx_ads_form_entry_input_title_err"><![CDATA[Title is essential. Please, fill in this field]]></string>
+    <string name="_bx_ads_form_entry_input_sys_price"><![CDATA[Price]]></string>
+    <string name="_bx_ads_form_entry_input_price"><![CDATA[Price]]></string>
+    <string name="_bx_ads_form_entry_input_sys_year"><![CDATA[Year]]></string>
+    <string name="_bx_ads_form_entry_input_year"><![CDATA[Year]]></string>
+    <string name="_bx_ads_form_entry_input_sys_category"><![CDATA[Category]]></string>
+    <string name="_bx_ads_form_entry_input_sys_category_view"><![CDATA[Category]]></string>
+    <string name="_bx_ads_form_entry_input_category_view"><![CDATA[Category]]></string>
+    <string name="_bx_ads_form_entry_input_sys_category_select"><![CDATA[Category]]></string>
+    <string name="_bx_ads_form_entry_input_category_select"><![CDATA[Category]]></string>
+    <string name="_bx_ads_form_entry_input_sys_text"><![CDATA[Text]]></string>
+    <string name="_bx_ads_form_entry_input_text"><![CDATA[Text]]></string>
+    <string name="_bx_ads_form_entry_input_text_err"><![CDATA[Text field can't be empty]]></string>
+    <string name="_bx_ads_form_entry_input_sys_delete_confirm"><![CDATA[Delete confirmation]]></string>
+    <string name="_bx_ads_form_entry_input_delete_confirm"><![CDATA[I am sure I want to delete this ad]]></string>
+    <string name="_bx_ads_form_entry_input_delete_confirm_info"><![CDATA[This action can not be undone]]></string>
+    <string name="_bx_ads_form_entry_input_delete_confirm_error"><![CDATA[Please check this checkbox if you really want to delete the ad]]></string>
+    <string name="_bx_ads_form_entry_input_sys_covers"><![CDATA[Header Image]]></string>
+    <string name="_bx_ads_form_entry_input_covers"><![CDATA[Header Image]]></string>
+    <string name="_bx_ads_form_entry_input_covers_uploader_simple_title"><![CDATA[Upload]]></string>
+    <string name="_bx_ads_form_entry_input_covers_uploader_html5_title"><![CDATA[Upload]]></string>
+    <string name="_bx_ads_form_entry_input_sys_pictures"><![CDATA[Images]]></string>
+    <string name="_bx_ads_form_entry_input_pictures"><![CDATA[]]></string>
+    <string name="_bx_ads_form_entry_input_sys_videos"><![CDATA[Videos]]></string>
+    <string name="_bx_ads_form_entry_input_videos"><![CDATA[]]></string>
+    <string name="_bx_ads_form_entry_input_sys_files"><![CDATA[Files]]></string>
+    <string name="_bx_ads_form_entry_input_files"><![CDATA[]]></string>
+    <string name="_bx_ads_form_entry_input_sys_polls"><![CDATA[Polls]]></string>
+    <string name="_bx_ads_form_entry_input_sys_allow_view_to"><![CDATA[Visibility]]></string>
+    <string name="_bx_ads_form_entry_input_allow_view_to"><![CDATA[Visibility]]></string>
+    <string name="_bx_ads_form_entry_input_sys_date_added"><![CDATA[Created]]></string>
+    <string name="_bx_ads_form_entry_input_date_added"><![CDATA[Created]]></string>
+    <string name="_bx_ads_form_entry_input_sys_date_changed"><![CDATA[Updated]]></string>
+    <string name="_bx_ads_form_entry_input_date_changed"><![CDATA[Updated]]></string>
+    <string name="_bx_ads_form_entry_input_sys_attachments"><![CDATA[Attachments]]></string>
+
+    <string name="_bx_ads_form_poll"><![CDATA[Polls]]></string>
+    <string name="_bx_ads_form_poll_display_add"><![CDATA[Add Poll]]></string>
+    <string name="_bx_ads_form_poll_input_sys_text"><![CDATA[Question]]></string>
+    <string name="_bx_ads_form_poll_input_text"><![CDATA[Question]]></string>
+    <string name="_bx_ads_form_poll_input_text_err"><![CDATA[Question is essential. Please, fill in this field]]></string>
+    <string name="_bx_ads_form_poll_input_sys_answers"><![CDATA[Answers]]></string>
+    <string name="_bx_ads_form_poll_input_answers"><![CDATA[Answers]]></string>
+    <string name="_bx_ads_form_poll_input_answers_err"><![CDATA[Poll should have at least 2 non-empty answers.]]></string>
+    <string name="_bx_ads_form_poll_input_answers_add"><![CDATA[Add More]]></string>
+    <string name="_bx_ads_form_poll_input_sys_do_submit"><![CDATA[Add]]></string>
+    <string name="_bx_ads_form_poll_input_do_submit"><![CDATA[Add]]></string>
+    <string name="_bx_ads_form_poll_input_do_cancel"><![CDATA[Close]]></string>
+
+    <string name="_bx_ads_acl_action_create_entry"><![CDATA[Create Ad]]></string>
+    <string name="_bx_ads_acl_action_delete_entry"><![CDATA[Delete Ad]]></string>
+    <string name="_bx_ads_acl_action_view_entry"><![CDATA[View Ad]]></string>
+    <string name="_bx_ads_acl_action_set_thumb"><![CDATA[Set Ad Header Image]]></string>
+    <string name="_bx_ads_acl_action_edit_any_entry"><![CDATA[Edit Any Ad]]></string>
+
+    <string name="_bx_ads_page_title_sys_create_entry"><![CDATA[New Ad]]></string>
+    <string name="_bx_ads_page_title_create_entry"><![CDATA[New Ad]]></string>
+    <string name="_bx_ads_page_block_title_create_entry"><![CDATA[New Ad]]></string>
+    <string name="_bx_ads_page_title_sys_edit_entry"><![CDATA[Edit]]></string>
+    <string name="_bx_ads_page_title_edit_entry"><![CDATA[Edit]]></string>
+    <string name="_bx_ads_page_block_title_edit_entry"><![CDATA[Edit]]></string>
+    <string name="_bx_ads_page_title_sys_delete_entry"><![CDATA[Delete]]></string>
+    <string name="_bx_ads_page_title_delete_entry"><![CDATA[Delete]]></string>
+    <string name="_bx_ads_page_block_title_delete_entry"><![CDATA[Delete]]></string>
+    <string name="_bx_ads_page_title_sys_view_entry"><![CDATA[View Ad]]></string>
+    <string name="_bx_ads_page_title_view_entry"><![CDATA[{title}]]></string>
+    <string name="_bx_ads_page_block_title_entry_breadcrumb"><![CDATA[Breadcrumb]]></string>
+    <string name="_bx_ads_page_block_title_entry_text"><![CDATA[Ad Text]]></string>
+    <string name="_bx_ads_page_title_browse"><![CDATA[Ads]]></string>
+    <string name="_bx_ads_page_title_search_results"><![CDATA[Ads matching "{0}"]]></string>
+    <string name="_bx_ads_page_title_browse_by_author"><![CDATA[Ads of {display_name}]]></string>
+    <string name="_bx_ads_page_title_browse_by_context"><![CDATA[Ads in {display_name}]]></string>
+    <string name="_bx_ads_page_title_browse_featured"><![CDATA[Featured Ads]]></string>
+    <string name="_bx_ads_page_title_browse_recent"><![CDATA[Latest Ads]]></string>
+    <string name="_bx_ads_page_title_browse_popular"><![CDATA[Popular Ads]]></string>
+    <string name="_bx_ads_page_title_browse_updated"><![CDATA[Updated Ads]]></string>
+    <string name="_bx_ads_page_title_browse_category"><![CDATA[Ads in {display_name}]]]]></string>
+    <string name="_bx_ads_page_title_sys_home"><![CDATA[Ads Home]]></string>
+    <string name="_bx_ads_page_title_home"><![CDATA[Ads]]></string>
+    <string name="_bx_ads_page_block_title_featured_entries_view_extended"><![CDATA[Featured Ads]]></string>
+    <string name="_bx_ads_page_block_title_recent_entries"><![CDATA[Latest Ads (Gallery View)]]></string>
+    <string name="_bx_ads_page_block_title_recent_entries_view_extended"><![CDATA[Latest Ads]]></string>
+    <string name="_bx_ads_page_block_title_recent_entries_view_full"><![CDATA[Latest Ads (Full View)]]></string>
+    <string name="_bx_ads_page_block_title_entry_social_sharing"><![CDATA[Share]]></string>
+    <string name="_bx_ads_page_block_title_entry_author"><![CDATA[Author]]></string>
+    <string name="_bx_ads_page_block_title_entry_actions"><![CDATA[Actions]]></string>
+    <string name="_bx_ads_page_block_title_entry_comments"><![CDATA[Comments]]></string>
+    <string name="_bx_ads_page_block_title_entry_comments_link"><![CDATA[Comments to <a href="{entry_link}">{title}</a>]]></string>
+    <string name="_bx_ads_page_block_title_entry_reviews"><![CDATA[Reviews]]></string>
+    <string name="_bx_ads_page_block_title_entry_reviews_link"><![CDATA[Reviews to <a href="{entry_link}">{title}</a>]]></string>
+    <string name="_bx_ads_page_block_title_entry_reviews_rating"><![CDATA[Rating]]></string>
+    <string name="_bx_ads_page_block_title_entry_location"><![CDATA[Location]]></string>
+    <string name="_bx_ads_page_block_title_entry_attachments"><![CDATA[Attachments]]></string>
+    <string name="_bx_ads_page_block_title_entry_polls"><![CDATA[Polls]]></string>
+    <string name="_bx_ads_page_block_title_entry_all_actions"><![CDATA[All Actions]]></string>
+    <string name="_bx_ads_page_title_sys_entries_popular"><![CDATA[Popular Ads]]></string>
+    <string name="_bx_ads_page_title_entries_popular"><![CDATA[Popular Ads]]></string>
+    <string name="_bx_ads_page_title_sys_entries_updated"><![CDATA[Updated Ads]]></string>
+    <string name="_bx_ads_page_title_entries_updated"><![CDATA[Updated Ads]]></string>
+    <string name="_bx_ads_page_title_sys_entries_search"><![CDATA[Search]]></string>
+    <string name="_bx_ads_page_title_entries_search"><![CDATA[Search]]></string>
+    <string name="_bx_ads_page_block_title_search_form"><![CDATA[Search Form]]></string>
+    <string name="_bx_ads_page_block_title_search_results"><![CDATA[Search Results]]></string>
+    <string name="_bx_ads_page_block_title_search_form_cmts"><![CDATA[Comments Search Form]]></string>
+    <string name="_bx_ads_page_block_title_search_results_cmts"><![CDATA[Comments Search Results]]></string>
+    <string name="_bx_ads_page_block_title_popular_entries"><![CDATA[Popular Ads]]></string>
+    <string name="_bx_ads_page_block_title_popular_entries_view_extended"><![CDATA[Popular Ads (Extended View)]]></string>
+    <string name="_bx_ads_page_block_title_popular_entries_view_full"><![CDATA[Popular Ads (Full View)]]></string>
+    <string name="_bx_ads_page_block_title_updated_entries"><![CDATA[Updated Ads]]></string>
+    <string name="_bx_ads_page_title_sys_view_entry_comments"><![CDATA[Ad Comments]]></string>
+    <string name="_bx_ads_page_title_view_entry_comments"><![CDATA[Comments to {title}]]></string>
+    <string name="_bx_ads_page_title_sys_entries_of_author"><![CDATA[Ads of author]]></string>
+    <string name="_bx_ads_page_title_entries_of_author"><![CDATA[Ads by {display_name}]]></string>
+    <string name="_bx_ads_page_title_sys_entries_in_context"><![CDATA[Ads in context]]></string>
+    <string name="_bx_ads_page_title_entries_in_context"><![CDATA[Ads in {display_name}]]></string>
+    <string name="_bx_ads_page_block_title_favorites_of_author"><![CDATA[Favorites by <a href="{profile_link}">{display_name}</a>]]></string>
+    <string name="_bx_ads_page_block_title_sys_favorites_of_author"><![CDATA[Favorites of author]]></string>
+    <string name="_bx_ads_page_block_title_entries_of_author"><![CDATA[Ads by <a href="{profile_link}">{display_name}</a>]]></string>
+    <string name="_bx_ads_page_block_title_sys_entries_of_author"><![CDATA[Ads of author]]></string>
+    <string name="_bx_ads_page_block_title_entries_in_context"><![CDATA[Ads in <a href="{profile_link}">{display_name}</a>]]></string>
+    <string name="_bx_ads_page_block_title_sys_entries_in_context"><![CDATA[Ads in context]]></string>
+    <string name="_bx_ads_page_block_title_entries_actions"><![CDATA[Ads actions]]></string>
+    <string name="_bx_ads_page_block_title_browse_cmts"><![CDATA[Ads' Comments]]></string>
+    <string name="_bx_ads_page_title_sys_manage"><![CDATA[Manage Own]]></string>
+    <string name="_bx_ads_page_title_sys_manage_administration"><![CDATA[Manage All]]></string>
+    <string name="_bx_ads_page_title_manage"><![CDATA[Manage]]></string>
+    <string name="_bx_ads_page_block_title_system_manage"><![CDATA[Manage Own]]></string>
+    <string name="_bx_ads_page_block_title_system_manage_administration"><![CDATA[Manage All]]></string>
+    <string name="_bx_ads_page_block_title_manage"><![CDATA[Manage]]></string>    
+    <string name="_bx_ads_page_block_title_popular_keywords"><![CDATA[Popular Hashtags]]></string>
+    <string name="_bx_ads_page_block_title_categories"><![CDATA[Ads Categories]]></string>
+    <string name="_bx_ads_page_block_title_entry_info"><![CDATA[Info]]></string>
+    <string name="_bx_ads_page_block_title_sys_my_entries"><![CDATA[User Ads]]></string>
+    <string name="_bx_ads_page_block_title_my_entries"><![CDATA[{display_name} Ads]]></string>
+    <string name="_bx_ads_page_block_title_sys_recent_entries_view_showcase"><![CDATA[Latest Ads (Showcase View)]]></string>
+    <string name="_bx_ads_page_block_title_recent_entries_view_showcase"><![CDATA[Latest Ads]]></string>
+    <string name="_bx_ads_page_block_title_sys_popular_entries_view_showcase"><![CDATA[Popular Ads (Showcase View)]]></string>
+    <string name="_bx_ads_page_block_title_popular_entries_view_showcase"><![CDATA[Popular Ads]]></string>
+    <string name="_bx_ads_page_block_title_sys_featured_entries_view_showcase"><![CDATA[Featured Ads (Showcase View)]]></string>
+    <string name="_bx_ads_page_block_title_featured_entries_view_showcase"><![CDATA[Featured Ads]]></string>
+    <string name="_bx_ads_page_block_title_sys_entry_context"><![CDATA[Posted in]]></string>
+    <string name="_bx_ads_page_block_title_entry_context"><![CDATA[Posted in]]></string>
+    <string name="_bx_ads_page_title_sys_entries_categories"><![CDATA[Ads Categories]]></string>
+    <string name="_bx_ads_page_title_entries_categories"><![CDATA[Ads Categories]]></string>
+    <string name="_bx_ads_page_block_title_entries_by_category"><![CDATA[Ads]]></string>
+    <string name="_bx_ads_page_block_title_entries_by_category_mask"><![CDATA[Ads in: {0}]]></string>
+
+    <string name="_bx_ads_menu_title_entry_attachments"><![CDATA[Form Attachments]]></string>
+    <string name="_bx_ads_menu_set_title_entry_attachments"><![CDATA[Form Attachments]]></string>
+    <string name="_bx_ads_menu_item_title_system_cpa_photo_simple"><![CDATA[Add Photo (simple)]]></string>
+    <string name="_bx_ads_menu_item_title_cpa_photo_simple"><![CDATA[Add Photo]]></string>
+    <string name="_bx_ads_menu_item_title_system_cpa_photo_html5"><![CDATA[Add Photo (html5)]]></string>
+    <string name="_bx_ads_menu_item_title_cpa_photo_html5"><![CDATA[Add Photos]]></string>
+    <string name="_bx_ads_menu_item_title_system_cpa_video_simple"><![CDATA[Add Video (simple)]]></string>
+    <string name="_bx_ads_menu_item_title_cpa_video_simple"><![CDATA[Add Video]]></string>
+    <string name="_bx_ads_menu_item_title_system_cpa_video_html5"><![CDATA[Add Video (html5)]]></string>
+    <string name="_bx_ads_menu_item_title_cpa_video_html5"><![CDATA[Add Videos]]></string>
+    <string name="_bx_ads_menu_item_title_system_cpa_video_record"><![CDATA[Record Video]]></string>
+    <string name="_bx_ads_menu_item_title_cpa_video_record"><![CDATA[Record Video]]></string>
+    <string name="_bx_ads_menu_item_title_system_cpa_file_simple"><![CDATA[Add File (simple)]]></string>
+    <string name="_bx_ads_menu_item_title_cpa_file_simple"><![CDATA[Add File]]></string>
+    <string name="_bx_ads_menu_item_title_system_cpa_file_html5"><![CDATA[Add File (html5)]]></string>
+    <string name="_bx_ads_menu_item_title_cpa_file_html5"><![CDATA[Add Files]]></string>
+    <string name="_bx_ads_menu_item_title_system_cpa_poll"><![CDATA[Add Poll]]></string>
+    <string name="_bx_ads_menu_item_title_cpa_poll"><![CDATA[Add Poll]]></string>
+
+    <string name="_bx_ads_menu_set_title_view_entry"><![CDATA[Ad Actions]]></string>
+    <string name="_bx_ads_menu_title_view_entry"><![CDATA[Ad Actions]]></string>
+    <string name="_bx_ads_menu_title_submenu"><![CDATA[Ads Submenu]]></string>
+    <string name="_bx_ads_menu_set_title_submenu"><![CDATA[Ads Submenu]]></string>
+    <string name="_bx_ads_menu_item_title_system_create_entry"><![CDATA[Ad]]></string>
+    <string name="_bx_ads_menu_item_title_create_entry"><![CDATA[Ad]]></string>
+    <string name="_bx_ads_menu_item_title_system_interested_entry"><![CDATA[Interested]]></string>
+    <string name="_bx_ads_menu_item_title_interested_entry"><![CDATA[I'm interested]]></string>
+    <string name="_bx_ads_menu_item_title_system_edit_entry"><![CDATA[Edit]]></string>
+    <string name="_bx_ads_menu_item_title_edit_entry"><![CDATA[Edit]]></string>
+    <string name="_bx_ads_menu_item_title_system_delete_entry"><![CDATA[Delete]]></string>
+    <string name="_bx_ads_menu_item_title_delete_entry"><![CDATA[Delete]]></string>
+    <string name="_bx_ads_menu_item_title_system_review_entry"><![CDATA[Review]]></string>
+    <string name="_bx_ads_menu_item_title_system_view_entry"><![CDATA[View Ad]]></string>
+    <string name="_bx_ads_menu_item_title_system_entries_home"><![CDATA[Ads]]></string>
+    <string name="_bx_ads_menu_item_title_entries_home"><![CDATA[Ads]]></string>
+    <string name="_bx_ads_menu_item_title_system_entries_public"><![CDATA[Latest]]></string>
+    <string name="_bx_ads_menu_item_title_entries_public"><![CDATA[Latest]]></string>
+    <string name="_bx_ads_menu_item_title_system_entries_manage"><![CDATA[Manage]]></string>
+    <string name="_bx_ads_menu_item_title_entries_manage"><![CDATA[Manage]]></string>
+    <string name="_bx_ads_menu_item_title_system_entries_popular"><![CDATA[Popular]]></string>
+    <string name="_bx_ads_menu_item_title_entries_popular"><![CDATA[Popular]]></string>
+    <string name="_bx_ads_menu_item_title_system_entries_search"><![CDATA[Search]]></string>
+    <string name="_bx_ads_menu_item_title_entries_search"><![CDATA[Search]]></string>
+    <string name="_bx_ads_menu_title_view_entry_submenu"><![CDATA[View Ad Submenu]]></string>
+    <string name="_bx_ads_menu_set_title_view_entry_submenu"><![CDATA[View Ad Submenu]]></string>
+    <string name="_bx_ads_menu_item_title_view_entry_submenu_entry"><![CDATA[Ad]]></string>
+    <string name="_bx_ads_menu_item_title_view_entry_submenu_comments"><![CDATA[Comments]]></string>
+    <string name="_bx_ads_menu_item_title_system_view_entry_comments"><![CDATA[Ad Comments]]></string>
+    <string name="_bx_ads_menu_item_title_system_view_entries_author"><![CDATA[Ads]]></string>
+    <string name="_bx_ads_menu_item_title_view_entries_author"><![CDATA[Ads]]></string>
+    <string name="_bx_ads_menu_item_title_system_view_entries_in_context"><![CDATA[Ads]]></string>
+    <string name="_bx_ads_menu_item_title_view_entries_in_context"><![CDATA[Ads]]></string>
+    <string name="_bx_ads_menu_title_entries_my"><![CDATA[My Ads Action Menu]]></string>
+    <string name="_bx_ads_menu_set_title_entries_my"><![CDATA[My Ads Menu]]></string>
+    <string name="_bx_ads_menu_item_title_system_manage_my_posts"><![CDATA[My ads]]></string>
+    <string name="_bx_ads_menu_item_title_manage_my_posts"><![CDATA[Ads]]></string>
+    <string name="_bx_ads_menu_set_title_manage_tools"><![CDATA[Manage Tools Submenu]]></string>
+    <string name="_bx_ads_menu_title_manage_tools"><![CDATA[Manage Tools Submenu]]></string>
+    <string name="_bx_ads_menu_item_title_system_manage_account"><![CDATA[Manage account]]></string>
+    <string name="_bx_ads_menu_item_title_manage_account"><![CDATA[Manage account]]></string>
+    <string name="_bx_ads_menu_item_title_system_admt_ads"><![CDATA[Ads]]></string>
+    <string name="_bx_ads_menu_item_title_admt_ads"><![CDATA[Ads]]></string>
+    <string name="_bx_ads_menu_item_title_manage_my"><![CDATA[My Ads]]></string>
+    <string name="_bx_ads_menu_item_title_manage_all"><![CDATA[All Ads]]></string>
+    <string name="_bx_ads_menu_item_title_categories"><![CDATA[Categories]]></string>
+    <string name="_bx_ads_menu_item_title_system_entries_categories"><![CDATA[Categories]]></string>
+    <string name="_bx_ads_menu_item_title_entries_categories"><![CDATA[Categories]]></string>
+    <string name="_bx_ads_menu_item_title_system_sm_price"><![CDATA[Price]]></string>
+    <string name="_bx_ads_menu_item_title_sm_price"><![CDATA[Price]]></string>
+
+    <string name="_bx_ads_grid_column_title_icon"><![CDATA[Icon]]></string>
+    <string name="_bx_ads_grid_column_title_title"><![CDATA[Title]]></string>
+    <string name="_bx_ads_grid_column_title_subcategories"><![CDATA[Subcategories]]></string>
+    <string name="_bx_ads_grid_column_value_subcategories"><![CDATA[{0} subcategories]]></string>
+    <string name="_bx_ads_grid_column_info_subcategories"><![CDATA[View subcategories]]></string>
+    <string name="_bx_ads_grid_action_title_add"><![CDATA[Add New]]></string>
+    <string name="_bx_ads_grid_action_title_back"><![CDATA[Back]]></string>
+    <string name="_bx_ads_grid_action_title_delete"><![CDATA[Delete]]></string>
+    <string name="_bx_ads_grid_popup_title_add"><![CDATA[Add New Category]]></string>
+    <string name="_bx_ads_grid_popup_title_edit"><![CDATA[Edit '{0}' Category]]></string>
+    <string name="_bx_ads_grid_action_err_add_category"><![CDATA[Cannot add a category.]]></string>
+    <string name="_bx_ads_grid_action_err_edit_category"><![CDATA[Cannot edit the category.]]></string>
+
+    <string name="_bx_ads_grid_filter_item_title_adm_select_one_filter1"><![CDATA[All Statuses]]></string>
+    <string name="_bx_ads_grid_filter_item_title_adm_active"><![CDATA[Active]]></string>
+    <string name="_bx_ads_grid_filter_item_title_adm_hidden"><![CDATA[Hidden]]></string>
+    <string name="_bx_ads_grid_column_title_adm_active"><![CDATA[Active]]></string>
+    <string name="_bx_ads_grid_column_title_adm_title"><![CDATA[Title]]></string>
+    <string name="_bx_ads_grid_column_title_adm_added"><![CDATA[Added]]></string>
+    <string name="_bx_ads_grid_column_title_adm_author"><![CDATA[Author]]></string>
+    <string name="_bx_ads_grid_action_title_adm_edit"><![CDATA[Edit]]></string>
+    <string name="_bx_ads_grid_action_title_adm_delete"><![CDATA[Delete]]></string>
+    <string name="_bx_ads_grid_action_title_adm_more_actions"><![CDATA[More Actions]]></string>
+    <string name="_bx_ads_grid_action_title_adm_audit_content"><![CDATA[Audit]]></string>
+    <string name="_bx_ads_grid_action_err_delete"><![CDATA[Cannot delete the selected ad(s).]]></string>
+    <string name="_bx_ads_grid_txt_account_manager"><![CDATA[Redirect to manage account.]]></string>
+
+    <string name="_bx_ads_chart_growth"><![CDATA[Ads: Growth]]></string>
+    <string name="_bx_ads_chart_growth_speed"><![CDATA[Ads: Growth Speed]]></string>
+
+    <string name="_bx_ads_search_extended"><![CDATA[Ads Search]]></string>
+    <string name="_bx_ads_search_extended_cmts"><![CDATA[Ads Comments Search]]></string>
+    <string name="_bx_ads_search_extended_reviews"><![CDATA[Ads Reviews Search]]></string>
+
+    <!-- Ctegories -->
+    <string name="_bx_ads_cat_type_price"><![CDATA[With price]]></string>
+    <string name="_bx_ads_cat_type_price_year"><![CDATA[With price and year]]></string>
+
+    <string name="_bx_ads_cat_title_job"><![CDATA[Jobs]]></string>
+    <string name="_bx_ads_cat_title_accounting_finance"><![CDATA[Accounting / finance jobs]]></string>
+    <string name="_bx_ads_cat_title_education_nonprofit"><![CDATA[Education / nonprofit jobs]]></string>
+    <string name="_bx_ads_cat_title_government_legal"><![CDATA[Government / legal jobs]]></string>
+    <string name="_bx_ads_cat_title_programming_web_design"><![CDATA[Programming / web design jobs]]></string>
+
+    <string name="_bx_ads_cat_title_music"><![CDATA[Music Exchange]]></string>
+    <string name="_bx_ads_cat_title_instrument_sale"><![CDATA[Music instruments for sale]]></string>
+    <string name="_bx_ads_cat_title_instrument_wanted"><![CDATA[Music instruments wanted]]></string>
+    
+    <string name="_bx_ads_cat_title_housing"><![CDATA[Housing & Rentals]]></string>
+    <string name="_bx_ads_cat_title_apartments_housing"><![CDATA[Apartments / housing]]></string>
+    <string name="_bx_ads_cat_title_office_commercial"><![CDATA[Office / commercial]]></string>
+    <string name="_bx_ads_cat_title_real_estate_sale"><![CDATA[Real estate for sale]]></string>
+    <string name="_bx_ads_cat_title_roommate"><![CDATA[Roommates]]></string>
+    <string name="_bx_ads_cat_title_temporary_rental"><![CDATA[Temporary rental]]></string>
+    
+    <string name="_bx_ads_cat_title_service"><![CDATA[Services]]></string>
+    <string name="_bx_ads_cat_title_automotive"><![CDATA[Automotive services]]></string>
+    <string name="_bx_ads_cat_title_educational"><![CDATA[Educational services]]></string>
+    <string name="_bx_ads_cat_title_financial"><![CDATA[Financial services]]></string>
+    <string name="_bx_ads_cat_title_labor_move"><![CDATA[Labor / move services]]></string>
+    <string name="_bx_ads_cat_title_legal"><![CDATA[Legal services]]></string>
+
+    <string name="_bx_ads_cat_title_casting"><![CDATA[Casting Calls]]></string>
+    <string name="_bx_ads_cat_title_acting"><![CDATA[Acting castings]]></string>
+    <string name="_bx_ads_cat_title_dance"><![CDATA[Dance castings]]></string>
+    <string name="_bx_ads_cat_title_modeling"><![CDATA[Modeling castings]]></string>
+    <string name="_bx_ads_cat_title_musician"><![CDATA[Musicians castings]]></string>
+    <string name="_bx_ads_cat_title_reality_show"><![CDATA[Reality shows castings]]></string>
+
+    <string name="_bx_ads_cat_title_personal"><![CDATA[Personals]]></string>
+    <string name="_bx_ads_cat_title_men_women"><![CDATA[Men seeking women]]></string>
+    <string name="_bx_ads_cat_title_women_men"><![CDATA[Women seeking men]]></string>
+    <string name="_bx_ads_cat_title_missed_connection"><![CDATA[Missed connections]]></string>
+
+    <string name="_bx_ads_cat_title_sale"><![CDATA[For Sale]]></string>
+    <string name="_bx_ads_cat_title_barter"><![CDATA[Barter]]></string>
+    <string name="_bx_ads_cat_title_clothing"><![CDATA[Sale clothing]]></string>
+    <string name="_bx_ads_cat_title_collectible"><![CDATA[Sale collectibles]]></string>
+
+    <string name="_bx_ads_cat_title_sale_car"><![CDATA[Cars For Sale]]></string>
+    <string name="_bx_ads_cat_title_auto_part"><![CDATA[Sale auto parts]]></string>
+    <string name="_bx_ads_cat_title_auto_truck"><![CDATA[Sale autos / trucks]]></string>
+    <string name="_bx_ads_cat_title_motorcycle"><![CDATA[Sale motorcycles]]></string>
+
+    <string name="_bx_ads_et_txt_name_interested"><![CDATA[I'm interested.]]></string>
+    <string name="_bx_ads_et_txt_subject_interested"><![CDATA[{viewer_name} is interested in your ad.]]></string>
+    <string name="_bx_ads_et_txt_body_interested"><![CDATA[{email_header}
+<p>Hello, {profile_name}.</p>
+<p><b><a href="{viewer_url}">{viewer_name}</a></b> is interested in your ad <b><a href="{ad_url}">{ad_name}</a></b>.</p>
+{email_footer}]]></string>
+
+    <string name="_bx_ads_txt_all_entries_in"><![CDATA[<a href="{0}">All Ads in {1} ({2})</a>]]></string>
+    <string name="_bx_ads_txt_all_entries_by"><![CDATA[{0} ads]]></string>
+    <string name="_bx_ads_txt_sample_single"><![CDATA[ad]]></string>
+    <string name="_bx_ads_txt_sample_single_with_article"><![CDATA[an ad]]></string>
+    <string name="_bx_ads_txt_sample_comment_single"><![CDATA[comment to ad]]></string>
+    <string name="_bx_ads_txt_sample_vote_single"><![CDATA[vote to ad]]></string>
+    <string name="_bx_ads_txt_sample_reaction_single"><![CDATA['{0}' reaction to ad]]></string>
+    <string name="_bx_ads_txt_sample_score_up_single"><![CDATA[score up vote to ad]]></string>
+    <string name="_bx_ads_txt_sample_score_down_single"><![CDATA[score down vote to ad]]></string>
+    <string name="_bx_ads_txt_sample_interest_single"><![CDATA[interested in ad]]></string>
+    <string name="_bx_ads_txt_display_title_add"><![CDATA[{0}: Add]]></string>
+    <string name="_bx_ads_txt_display_title_edit"><![CDATA[{0}: Edit]]></string>
+    <string name="_bx_ads_txt_display_title_view"><![CDATA[{0}: View]]></string>
+    <string name="_bx_ads_txt_processing_awaiting"><![CDATA[Ad will be published as soon as video is converted]]></string>
+    <string name="_bx_ads_txt_processing_failed"><![CDATA[Ad isn't published because video conversion failed, edit video to fix the issue.]]></string>
+    <string name="_bx_ads_txt_free"><![CDATA[Free]]></string>
+
+    <string name="_bx_ads_txt_msg_author_notified"><![CDATA[Advertiser was notified, that you're interested in his ad. Please wait.]]></string>
+    <string name="_bx_ads_txt_err_your_own"><![CDATA[You cannot do the action because it's your own ad.]]></string>
+    <string name="_bx_ads_txt_err_duplicate"><![CDATA[You already performed the action.]]></string>
+    <string name="_bx_ads_txt_err_cannot_perform_action"><![CDATA[Cannot perform action. Please report.]]></string>
+
+    <string name="_bx_ads_txt_poll_view_answers"><![CDATA[poll]]></string>
+    <string name="_bx_ads_txt_poll_view_results"><![CDATA[results]]></string>
+    <string name="_bx_ads_txt_poll_answer_vote_do_by"><![CDATA[Voted for]]></string>
+    <string name="_bx_ads_txt_poll_answer_vote_counter"><![CDATA[{0} votes]]></string>
+    <string name="_bx_ads_txt_poll_answer_vote_percent"><![CDATA[({0}%)]]></string>
+
+    <string name="_bx_ads_alert_action_doInterest_personal"><![CDATA[Someone interested in your ad]]></string>
+    <string name="_bx_ads_txt_ntfs_subobject_interested"><![CDATA[<b class="bx-ntfs-content-profile">{owner_name}</b> {subentry_sample} <b class="bx-ntfs-content-entry">{entry_caption}</b>]]></string>
+</resources>

+ 746 - 0
modules/boonex/ads/updates/12.0.0_12.0.1/source/install/sql/install.sql

@@ -0,0 +1,746 @@
+-- TABLE: entries
+CREATE TABLE IF NOT EXISTS `bx_ads_entries` (
+  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+  `author` int(11) NOT NULL,
+  `added` int(11) NOT NULL,
+  `changed` int(11) NOT NULL,
+  `category` int(11) NOT NULL,
+  `thumb` int(11) NOT NULL,
+  `title` varchar(255) NOT NULL,
+  `price` float NOT NULL,
+  `year` int(11) NOT NULL,
+  `text` mediumtext NOT NULL,
+  `labels` text NOT NULL,
+  `location` text NOT NULL,
+  `views` int(11) NOT NULL default '0',
+  `rate` float NOT NULL default '0',
+  `votes` int(11) NOT NULL default '0',
+  `rrate` float NOT NULL default '0',
+  `rvotes` int(11) NOT NULL default '0',
+  `score` int(11) NOT NULL default '0',
+  `sc_up` int(11) NOT NULL default '0',
+  `sc_down` int(11) NOT NULL default '0',
+  `favorites` int(11) NOT NULL default '0',
+  `comments` int(11) NOT NULL default '0',
+  `reviews` int(11) NOT NULL default '0',
+  `reviews_avg` float NOT NULL default '0',
+  `reports` int(11) NOT NULL default '0',
+  `featured` int(11) NOT NULL default '0',
+  `allow_view_to` varchar(16) NOT NULL DEFAULT '3',
+  `status` enum('active','awaiting','hidden') NOT NULL DEFAULT 'active',
+  `status_admin` enum('active','hidden') NOT NULL DEFAULT 'active',
+  PRIMARY KEY (`id`),
+  FULLTEXT KEY `title_text` (`title`,`text`)
+);
+
+-- TABLE: types of categories
+CREATE TABLE IF NOT EXISTS `bx_ads_categories_types` (
+  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
+  `name` varchar(64) NOT NULL DEFAULT '',
+  `title` varchar(255) NOT NULL DEFAULT '',
+  `display_add` varchar(255) NOT NULL DEFAULT '',
+  `display_edit` varchar(255) NOT NULL DEFAULT '',
+  `display_view` varchar(255) NOT NULL DEFAULT '',
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `name` (`name`)
+);
+
+INSERT INTO `bx_ads_categories_types` (`id`, `name`, `title`, `display_add`, `display_edit`, `display_view`) VALUES
+(1, 'price', '_bx_ads_cat_type_price', 'bx_ads_entry_price_add', 'bx_ads_entry_price_edit', 'bx_ads_entry_price_view'),
+(2, 'price_year', '_bx_ads_cat_type_price_year', 'bx_ads_entry_price_year_add', 'bx_ads_entry_price_year_edit', 'bx_ads_entry_price_year_view');
+
+-- TABLE: categories
+CREATE TABLE IF NOT EXISTS `bx_ads_categories` (
+  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
+  `parent_id` int(11) unsigned NOT NULL DEFAULT '0',
+  `level` tinyint(11) unsigned NOT NULL DEFAULT '0',
+  `type` int(11) NOT NULL DEFAULT '0',
+  `name` varchar(64) NOT NULL DEFAULT '',
+  `title` varchar(255) NOT NULL DEFAULT '',
+  `text` text NOT NULL,
+  `icon` varchar(255) NOT NULL DEFAULT '',
+  `items` int(11) NOT NULL DEFAULT '0',
+  `active` tinyint(4) NOT NULL DEFAULT '1',
+  `order` int(11) NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `name` (`name`),
+  FULLTEXT KEY `title_text` (`title`,`text`)
+);
+
+INSERT INTO `bx_ads_categories` (`parent_id`, `level`, `type`, `name`, `title`, `text`, `icon`, `active`, `order`) VALUES 
+(0, 0, 1, 'job', '_bx_ads_cat_title_job', '', 'user-md', 1, 1);
+SET @iParentId = LAST_INSERT_ID();
+
+INSERT INTO `bx_ads_categories` (`parent_id`, `level`, `type`, `name`, `title`, `text`, `icon`, `active`, `order`) VALUES 
+(@iParentId, 1, 1, 'job_finance', '_bx_ads_cat_title_accounting_finance', '', '', 1, 1),
+(@iParentId, 1, 1, 'job_education', '_bx_ads_cat_title_education_nonprofit', '', '', 1, 2),
+(@iParentId, 1, 1, 'job_legal', '_bx_ads_cat_title_government_legal', '', '', 1, 3),
+(@iParentId, 1, 1, 'job_programming', '_bx_ads_cat_title_programming_web_design', '', '', 1, 4);
+
+INSERT INTO `bx_ads_categories` (`parent_id`, `level`, `type`, `name`, `title`, `text`, `icon`, `active`, `order`) VALUES 
+(0, 0, 2, 'music', '_bx_ads_cat_title_music', '', 'music', 1, 2);
+SET @iParentId = LAST_INSERT_ID();
+
+INSERT INTO `bx_ads_categories` (`parent_id`, `level`, `type`, `name`, `title`, `text`, `icon`, `active`, `order`) VALUES 
+(@iParentId, 1, 2, 'music_isale', '_bx_ads_cat_title_instrument_sale', '', '', 1, 1),
+(@iParentId, 1, 2, 'music_iwanted', '_bx_ads_cat_title_instrument_wanted', '', '', 1, 2);
+
+INSERT INTO `bx_ads_categories` (`parent_id`, `level`, `type`, `name`, `title`, `text`, `icon`, `active`, `order`) VALUES 
+(0, 0, 1, 'housing', '_bx_ads_cat_title_housing', '', 'home', 1, 3);
+SET @iParentId = LAST_INSERT_ID();
+
+INSERT INTO `bx_ads_categories` (`parent_id`, `level`, `type`, `name`, `title`, `text`, `icon`, `active`, `order`) VALUES 
+(@iParentId, 1, 1, 'housing_apartments', '_bx_ads_cat_title_apartments_housing', '', '', 1, 1),
+(@iParentId, 1, 1, 'housing_office', '_bx_ads_cat_title_office_commercial', '', '', 1, 2),
+(@iParentId, 1, 1, 'housing_re_sale', '_bx_ads_cat_title_real_estate_sale', '', '', 1, 3),
+(@iParentId, 1, 1, 'housing_roommate', '_bx_ads_cat_title_roommate', '', '', 1, 4),
+(@iParentId, 1, 1, 'housing_temp_rental', '_bx_ads_cat_title_temporary_rental', '', '', 1, 5);
+
+INSERT INTO `bx_ads_categories` (`parent_id`, `level`, `type`, `name`, `title`, `text`, `icon`, `active`, `order`) VALUES 
+(0, 0, 1, 'service', '_bx_ads_cat_title_service', '', 'wrench', 1, 4);
+SET @iParentId = LAST_INSERT_ID();
+
+INSERT INTO `bx_ads_categories` (`parent_id`, `level`, `type`, `name`, `title`, `text`, `icon`, `active`, `order`) VALUES 
+(@iParentId, 1, 1, 'service_automotive', '_bx_ads_cat_title_automotive', '', '', 1, 1),
+(@iParentId, 1, 1, 'service_educational', '_bx_ads_cat_title_educational', '', '', 1, 2),
+(@iParentId, 1, 1, 'service_financial', '_bx_ads_cat_title_financial', '', '', 1, 3),
+(@iParentId, 1, 1, 'service_labor', '_bx_ads_cat_title_labor_move', '', '', 1, 4),
+(@iParentId, 1, 1, 'service_legal', '_bx_ads_cat_title_legal', '', '', 1, 5);
+
+INSERT INTO `bx_ads_categories` (`parent_id`, `level`, `type`, `name`, `title`, `text`, `icon`, `active`, `order`) VALUES 
+(0, 0, 1, 'casting', '_bx_ads_cat_title_casting', '', 'eye', 1, 5);
+SET @iParentId = LAST_INSERT_ID();
+
+INSERT INTO `bx_ads_categories` (`parent_id`, `level`, `type`, `name`, `title`, `text`, `icon`, `active`, `order`) VALUES 
+(@iParentId, 1, 1, 'casting_acting', '_bx_ads_cat_title_acting', '', '', 1, 1),
+(@iParentId, 1, 1, 'casting_dance', '_bx_ads_cat_title_dance', '', '', 1, 2),
+(@iParentId, 1, 1, 'casting_modeling', '_bx_ads_cat_title_modeling', '', '', 1, 3),
+(@iParentId, 1, 1, 'casting_musician', '_bx_ads_cat_title_musician', '', '', 1, 4),
+(@iParentId, 1, 1, 'casting_rshow', '_bx_ads_cat_title_reality_show', '', '', 1, 5);
+
+INSERT INTO `bx_ads_categories` (`parent_id`, `level`, `type`, `name`, `title`, `text`, `icon`, `active`, `order`) VALUES 
+(0, 0, 2, 'personal', '_bx_ads_cat_title_personal', '', 'user', 1, 6);
+SET @iParentId = LAST_INSERT_ID();
+
+INSERT INTO `bx_ads_categories` (`parent_id`, `level`, `type`, `name`, `title`, `text`, `icon`, `active`, `order`) VALUES 
+(@iParentId, 1, 2, 'personal_mw', '_bx_ads_cat_title_men_women', '', '', 1, 1),
+(@iParentId, 1, 2, 'personal_wm', '_bx_ads_cat_title_women_men', '', '', 1, 2),
+(@iParentId, 1, 2, 'personal_missed', '_bx_ads_cat_title_missed_connection', '', '', 1, 3);
+
+INSERT INTO `bx_ads_categories` (`parent_id`, `level`, `type`, `name`, `title`, `text`, `icon`, `active`, `order`) VALUES 
+(0, 0, 2, 'sale', '_bx_ads_cat_title_sale', '', 'shopping-cart', 1, 7);
+SET @iParentId = LAST_INSERT_ID();
+
+INSERT INTO `bx_ads_categories` (`parent_id`, `level`, `type`, `name`, `title`, `text`, `icon`, `active`, `order`) VALUES 
+(@iParentId, 1, 2, 'sale_barter', '_bx_ads_cat_title_barter', '', '', 1, 1),
+(@iParentId, 1, 2, 'sale_clothing', '_bx_ads_cat_title_clothing', '', '', 1, 1),
+(@iParentId, 1, 2, 'sale_collectible', '_bx_ads_cat_title_collectible', '', '', 1, 1);
+
+INSERT INTO `bx_ads_categories` (`parent_id`, `level`, `type`, `name`, `title`, `text`, `icon`, `active`, `order`) VALUES 
+(0, 0, 2, 'sale_car', '_bx_ads_cat_title_sale_car', '', 'truck', 1, 8);
+SET @iParentId = LAST_INSERT_ID();
+
+INSERT INTO `bx_ads_categories` (`parent_id`, `level`, `type`, `name`, `title`, `text`, `icon`, `active`, `order`) VALUES 
+(@iParentId, 1, 2, 'sale_car_part', '_bx_ads_cat_title_auto_part', '', '', 1, 1),
+(@iParentId, 1, 2, 'sale_car_auto', '_bx_ads_cat_title_auto_truck', '', '', 1, 2),
+(@iParentId, 1, 2, 'sale_car_motorcycle', '_bx_ads_cat_title_motorcycle', '', '', 1, 3);
+
+CREATE TABLE IF NOT EXISTS `bx_ads_interested_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `entry_id` int(11) NOT NULL default '0',
+  `profile_id` int(11) NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `interested` (`entry_id`, `profile_id`)
+);
+
+-- TABLE: storages & transcoders
+CREATE TABLE IF NOT EXISTS `bx_ads_covers` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `profile_id` int(10) unsigned NOT NULL,
+  `remote_id` varchar(128) NOT NULL,
+  `path` varchar(255) NOT NULL,
+  `file_name` varchar(255) NOT NULL,
+  `mime_type` varchar(128) NOT NULL,
+  `ext` varchar(32) NOT NULL,
+  `size` bigint(20) NOT NULL,
+  `added` int(11) NOT NULL,
+  `modified` int(11) NOT NULL,
+  `private` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `remote_id` (`remote_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_ads_files` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `profile_id` int(10) unsigned NOT NULL,
+  `remote_id` varchar(128) NOT NULL,
+  `path` varchar(255) NOT NULL,
+  `file_name` varchar(255) NOT NULL,
+  `mime_type` varchar(128) NOT NULL,
+  `ext` varchar(32) NOT NULL,
+  `size` bigint(20) NOT NULL,
+  `added` int(11) NOT NULL,
+  `modified` int(11) NOT NULL,
+  `private` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `remote_id` (`remote_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_ads_photos` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `profile_id` int(10) unsigned NOT NULL,
+  `remote_id` varchar(128) NOT NULL,
+  `path` varchar(255) NOT NULL,
+  `file_name` varchar(255) NOT NULL,
+  `mime_type` varchar(128) NOT NULL,
+  `ext` varchar(32) NOT NULL,
+  `size` bigint(20) NOT NULL,
+  `added` int(11) NOT NULL,
+  `modified` int(11) NOT NULL,
+  `private` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `remote_id` (`remote_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_ads_photos_resized` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `profile_id` int(10) unsigned NOT NULL,
+  `remote_id` varchar(128) NOT NULL,
+  `path` varchar(255) NOT NULL,
+  `file_name` varchar(255) NOT NULL,
+  `mime_type` varchar(128) NOT NULL,
+  `ext` varchar(32) NOT NULL,
+  `size` bigint(20) NOT NULL,
+  `added` int(11) NOT NULL,
+  `modified` int(11) NOT NULL,
+  `private` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `remote_id` (`remote_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_ads_videos` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `profile_id` int(10) unsigned NOT NULL,
+  `remote_id` varchar(128) NOT NULL,
+  `path` varchar(255) NOT NULL,
+  `file_name` varchar(255) NOT NULL,
+  `mime_type` varchar(128) NOT NULL,
+  `ext` varchar(32) NOT NULL,
+  `size` bigint(20) NOT NULL,
+  `dimensions` varchar(12) NOT NULL,
+  `added` int(11) NOT NULL,
+  `modified` int(11) NOT NULL,
+  `private` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `remote_id` (`remote_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_ads_videos_resized` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `profile_id` int(10) unsigned NOT NULL,
+  `remote_id` varchar(128) NOT NULL,
+  `path` varchar(255) NOT NULL,
+  `file_name` varchar(255) NOT NULL,
+  `mime_type` varchar(128) NOT NULL,
+  `ext` varchar(32) NOT NULL,
+  `size` bigint(20) NOT NULL,
+  `added` int(11) NOT NULL,
+  `modified` int(11) NOT NULL,
+  `private` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `remote_id` (`remote_id`)
+);
+
+-- TABLE: comments
+CREATE TABLE IF NOT EXISTS `bx_ads_cmts` (
+  `cmt_id` int(11) NOT NULL AUTO_INCREMENT,
+  `cmt_parent_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_vparent_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_object_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_author_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_level` int(11) NOT NULL DEFAULT '0',
+  `cmt_text` text NOT NULL,
+  `cmt_mood` tinyint(4) NOT NULL DEFAULT '0',
+  `cmt_rate` int(11) NOT NULL DEFAULT '0',
+  `cmt_rate_count` int(11) NOT NULL DEFAULT '0',
+  `cmt_time` int(11) unsigned NOT NULL DEFAULT '0',
+  `cmt_replies` int(11) NOT NULL DEFAULT '0',
+  `cmt_pinned` int(11) NOT NULL default '0',
+  PRIMARY KEY (`cmt_id`),
+  KEY `cmt_object_id` (`cmt_object_id`,`cmt_parent_id`),
+  FULLTEXT KEY `search_fields` (`cmt_text`)
+);
+
+-- TABLE: reviews
+CREATE TABLE IF NOT EXISTS `bx_ads_reviews` (
+  `cmt_id` int(11) NOT NULL AUTO_INCREMENT,
+  `cmt_parent_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_vparent_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_object_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_author_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_level` int(11) NOT NULL DEFAULT '0',
+  `cmt_text` text NOT NULL,
+  `cmt_mood` tinyint(4) NOT NULL DEFAULT '0',
+  `cmt_rate` int(11) NOT NULL DEFAULT '0',
+  `cmt_rate_count` int(11) NOT NULL DEFAULT '0',
+  `cmt_time` int(11) unsigned NOT NULL DEFAULT '0',
+  `cmt_replies` int(11) NOT NULL DEFAULT '0',
+  `cmt_pinned` int(11) NOT NULL default '0',
+  PRIMARY KEY (`cmt_id`),
+  KEY `cmt_object_id` (`cmt_object_id`,`cmt_parent_id`),
+  FULLTEXT KEY `search_fields` (`cmt_text`)
+);
+
+-- TABLE: votes
+CREATE TABLE IF NOT EXISTS `bx_ads_votes` (
+  `object_id` int(11) NOT NULL default '0',
+  `count` int(11) NOT NULL default '0',
+  `sum` int(11) NOT NULL default '0',
+  UNIQUE KEY `object_id` (`object_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_ads_votes_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `author_nip` int(11) unsigned NOT NULL default '0',
+  `value` tinyint(4) NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `vote` (`object_id`, `author_nip`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_ads_reactions` (
+  `object_id` int(11) NOT NULL default '0',
+  `reaction` varchar(32) NOT NULL default '',
+  `count` int(11) NOT NULL default '0',
+  `sum` int(11) NOT NULL default '0',
+  UNIQUE KEY `reaction` (`object_id`, `reaction`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_ads_reactions_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `author_nip` int(11) unsigned NOT NULL default '0',
+  `reaction` varchar(32) NOT NULL default '',
+  `value` tinyint(4) NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `vote` (`object_id`, `author_nip`)
+);
+
+-- TABLE: views
+CREATE TABLE IF NOT EXISTS `bx_ads_views_track` (
+  `object_id` int(11) NOT NULL default '0',
+  `viewer_id` int(11) NOT NULL default '0',
+  `viewer_nip` int(11) unsigned NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  KEY `id` (`object_id`,`viewer_id`,`viewer_nip`)
+);
+
+-- TABLE: metas
+CREATE TABLE IF NOT EXISTS `bx_ads_meta_keywords` (
+  `object_id` int(10) unsigned NOT NULL,
+  `keyword` varchar(255) NOT NULL,
+  KEY `object_id` (`object_id`),
+  KEY `keyword` (`keyword`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_ads_meta_mentions` (
+  `object_id` int(10) unsigned NOT NULL,
+  `profile_id` int(10) unsigned NOT NULL,
+  KEY `object_id` (`object_id`),
+  KEY `profile_id` (`profile_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_ads_meta_locations` (
+  `object_id` int(10) unsigned NOT NULL,
+  `lat` double NOT NULL,
+  `lng` double NOT NULL,
+  `country` varchar(2) NOT NULL,
+  `state` varchar(255) NOT NULL,
+  `city` varchar(255) NOT NULL,
+  `zip` varchar(255) NOT NULL,
+  `street` varchar(255) NOT NULL,
+  `street_number` varchar(255) NOT NULL,
+  PRIMARY KEY (`object_id`),
+  KEY `country_state_city` (`country`,`state`(8),`city`(8))
+);
+
+-- TABLE: reports
+CREATE TABLE IF NOT EXISTS `bx_ads_reports` (
+  `object_id` int(11) NOT NULL default '0',
+  `count` int(11) NOT NULL default '0',
+  UNIQUE KEY `object_id` (`object_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_ads_reports_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `author_nip` int(11) unsigned NOT NULL default '0',
+  `type` varchar(32) NOT NULL default '',
+  `text` text NOT NULL default '',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `report` (`object_id`, `author_nip`)
+);
+
+-- TABLE: favorites
+CREATE TABLE IF NOT EXISTS `bx_ads_favorites_track` (
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  KEY `id` (`object_id`,`author_id`)
+);
+
+-- TABLE: scores
+CREATE TABLE IF NOT EXISTS `bx_ads_scores` (
+  `object_id` int(11) NOT NULL default '0',
+  `count_up` int(11) NOT NULL default '0',
+  `count_down` int(11) NOT NULL default '0',
+  UNIQUE KEY `object_id` (`object_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_ads_scores_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `author_nip` int(11) unsigned NOT NULL default '0',
+  `type` varchar(8) NOT NULL default '',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `vote` (`object_id`, `author_nip`)
+);
+
+-- TABLE: polls
+CREATE TABLE IF NOT EXISTS `bx_ads_polls` (
+  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+  `author_id` int(11) NOT NULL default '0',
+  `content_id` int(11) NOT NULL default '0',
+  `text` text NOT NULL,
+  PRIMARY KEY (`id`),
+  FULLTEXT KEY `search_fields` (`text`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_ads_polls_answers` (
+  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+  `poll_id` int(11) unsigned NOT NULL default '0',
+  `title` varchar(255) NOT NULL,
+  `rate` float NOT NULL default '0',
+  `votes` int(11) NOT NULL default '0',
+  `order` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  FULLTEXT KEY `title` (`title`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_ads_polls_answers_votes` (
+  `object_id` int(11) NOT NULL default '0',
+  `count` int(11) NOT NULL default '0',
+  `sum` int(11) NOT NULL default '0',
+  UNIQUE KEY `object_id` (`object_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_ads_polls_answers_votes_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `author_nip` int(11) unsigned NOT NULL default '0',
+  `value` tinyint(4) NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `vote` (`object_id`, `author_nip`)
+);
+
+-- STORAGES & TRANSCODERS
+SET @sStorageEngine = (SELECT `value` FROM `sys_options` WHERE `name` = 'sys_storage_default');
+
+INSERT INTO `sys_objects_storage` (`object`, `engine`, `params`, `token_life`, `cache_control`, `levels`, `table_files`, `ext_mode`, `ext_allow`, `ext_deny`, `quota_size`, `current_size`, `quota_number`, `current_number`, `max_file_size`, `ts`) VALUES
+('bx_ads_covers', @sStorageEngine, '', 360, 2592000, 3, 'bx_ads_covers', 'allow-deny', 'jpg,jpeg,jpe,gif,png', '', 0, 0, 0, 0, 0, 0),
+
+('bx_ads_photos', @sStorageEngine, '', 360, 2592000, 3, 'bx_ads_photos', 'allow-deny', 'jpg,jpeg,jpe,gif,png', '', 0, 0, 0, 0, 0, 0),
+('bx_ads_photos_resized', @sStorageEngine, '', 360, 2592000, 3, 'bx_ads_photos_resized', 'allow-deny', 'jpg,jpeg,jpe,gif,png', '', 0, 0, 0, 0, 0, 0),
+
+('bx_ads_videos', @sStorageEngine, 'a:1:{s:6:"fields";a:1:{s:10:"dimensions";s:17:"getFileDimensions";}}', 360, 2592000, 3, 'bx_ads_videos', 'allow-deny', 'avi,flv,mpg,mpeg,wmv,mp4,m4v,mov,qt,divx,xvid,3gp,3g2,webm,mkv,ogv,ogg,rm,rmvb,asf,drc', '', 0, 0, 0, 0, 0, 0),
+('bx_ads_videos_resized', @sStorageEngine, '', 360, 2592000, 3, 'bx_ads_videos_resized', 'allow-deny', 'jpg,jpeg,jpe,gif,png,avi,flv,mpg,mpeg,wmv,mp4,m4v,mov,qt,divx,xvid,3gp,3g2,webm,mkv,ogv,ogg,rm,rmvb,asf,drc', '', 0, 0, 0, 0, 0, 0),
+
+('bx_ads_files', @sStorageEngine, '', 360, 2592000, 3, 'bx_ads_files', 'deny-allow', '', 'action,apk,app,bat,bin,cmd,com,command,cpl,csh,exe,gadget,inf,ins,inx,ipa,isu,job,jse,ksh,lnk,msc,msi,msp,mst,osx,out,paf,pif,prg,ps1,reg,rgs,run,sct,shb,shs,u3p,vb,vbe,vbs,vbscript,workflow,ws,wsf', 0, 0, 0, 0, 0, 0);
+
+INSERT INTO `sys_objects_transcoder` (`object`, `storage_object`, `source_type`, `source_params`, `private`, `atime_tracking`, `atime_pruning`, `ts`, `override_class_name`, `override_class_file`) VALUES 
+('bx_ads_preview', 'bx_ads_photos_resized', 'Storage', 'a:1:{s:6:"object";s:13:"bx_ads_covers";}', 'no', '1', '2592000', '0', '', ''),
+('bx_ads_gallery', 'bx_ads_photos_resized', 'Storage', 'a:1:{s:6:"object";s:13:"bx_ads_covers";}', 'no', '1', '2592000', '0', '', ''),
+('bx_ads_cover', 'bx_ads_photos_resized', 'Storage', 'a:1:{s:6:"object";s:13:"bx_ads_covers";}', 'no', '1', '2592000', '0', '', ''),
+
+('bx_ads_preview_photos', 'bx_ads_photos_resized', 'Storage', 'a:1:{s:6:"object";s:13:"bx_ads_photos";}', 'no', '1', '2592000', '0', '', ''),
+('bx_ads_gallery_photos', 'bx_ads_photos_resized', 'Storage', 'a:1:{s:6:"object";s:13:"bx_ads_photos";}', 'no', '1', '2592000', '0', '', ''),
+
+('bx_ads_videos_poster', 'bx_ads_videos_resized', 'Storage', 'a:1:{s:6:"object";s:13:"bx_ads_videos";}', 'no', '0', '0', '0', 'BxDolTranscoderVideo', ''),
+('bx_ads_videos_poster_preview', 'bx_ads_videos_resized', 'Storage', 'a:1:{s:6:"object";s:13:"bx_ads_videos";}', 'no', '0', '0', '0', 'BxDolTranscoderVideo', ''),
+('bx_ads_videos_mp4', 'bx_ads_videos_resized', 'Storage', 'a:1:{s:6:"object";s:13:"bx_ads_videos";}', 'no', '0', '0', '0', 'BxDolTranscoderVideo', ''),
+('bx_ads_videos_mp4_hd', 'bx_ads_videos_resized', 'Storage', 'a:1:{s:6:"object";s:13:"bx_ads_videos";}', 'no', '0', '0', '0', 'BxDolTranscoderVideo', ''),
+
+('bx_ads_preview_files', 'bx_ads_photos_resized', 'Storage', 'a:1:{s:6:"object";s:12:"bx_ads_files";}', 'no', '1', '2592000', '0', '', ''),
+('bx_ads_gallery_files', 'bx_ads_photos_resized', 'Storage', 'a:1:{s:6:"object";s:12:"bx_ads_files";}', 'no', '1', '2592000', '0', '', '');
+
+INSERT INTO `sys_transcoder_filters` (`transcoder_object`, `filter`, `filter_params`, `order`) VALUES 
+('bx_ads_preview', 'Resize', 'a:3:{s:1:"w";s:3:"300";s:1:"h";s:3:"200";s:11:"crop_resize";s:1:"1";}', '0'),
+('bx_ads_gallery', 'Resize', 'a:1:{s:1:"w";s:3:"500";}', '0'),
+('bx_ads_cover', 'Resize', 'a:1:{s:1:"w";s:4:"2000";}', '0'),
+
+('bx_ads_preview_photos', 'Resize', 'a:3:{s:1:"w";s:3:"300";s:1:"h";s:3:"200";s:11:"crop_resize";s:1:"1";}', '0'),
+('bx_ads_gallery_photos', 'Resize', 'a:4:{s:1:"w";s:3:"600";s:1:"h";s:3:"600";s:13:"square_resize";s:1:"1";s:10:"force_type";s:3:"jpg";}', '0'),
+
+('bx_ads_videos_poster_preview', 'Resize', 'a:3:{s:1:"w";s:3:"300";s:1:"h";s:3:"200";s:13:"square_resize";s:1:"1";}', 10),
+('bx_ads_videos_poster_preview', 'Poster', 'a:2:{s:1:"h";s:3:"480";s:10:"force_type";s:3:"jpg";}', 0),
+('bx_ads_videos_poster', 'Poster', 'a:2:{s:1:"h";s:3:"318";s:10:"force_type";s:3:"jpg";}', 0),
+('bx_ads_videos_mp4', 'Mp4', 'a:2:{s:1:"h";s:3:"318";s:10:"force_type";s:3:"mp4";}', 0),
+('bx_ads_videos_mp4_hd', 'Mp4', 'a:3:{s:1:"h";s:3:"720";s:13:"video_bitrate";s:4:"1536";s:10:"force_type";s:3:"mp4";}', 0),
+
+('bx_ads_preview_files', 'Resize', 'a:3:{s:1:"w";s:3:"300";s:1:"h";s:3:"200";s:11:"crop_resize";s:1:"1";}', '0'),
+('bx_ads_gallery_files', 'Resize', 'a:4:{s:1:"w";s:3:"600";s:1:"h";s:3:"600";s:13:"square_resize";s:1:"1";s:10:"force_type";s:3:"jpg";}', '0');
+
+
+-- FORMS: category
+INSERT INTO `sys_objects_form`(`object`, `module`, `title`, `action`, `form_attrs`, `table`, `key`, `uri`, `uri_title`, `submit_name`, `params`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_ads_category', 'bx_ads', '_bx_ads_form_category', '', 'a:1:{s:7:"enctype";s:19:"multipart/form-data";}', 'bx_ads_categories', 'id', '', '', 'a:1:{i:0;s:9:"do_submit";}', '', 0, 1, 'BxAdsFormCategory', 'modules/boonex/ads/classes/BxAdsFormCategory.php');
+
+INSERT INTO `sys_form_displays`(`object`, `display_name`, `module`, `view_mode`, `title`) VALUES 
+('bx_ads_category', 'bx_ads_category_add', 'bx_ads', 0, '_bx_ads_form_category_display_add'),
+('bx_ads_category', 'bx_ads_category_delete', 'bx_ads', 0, '_bx_ads_form_category_display_delete'),
+('bx_ads_category', 'bx_ads_category_edit', 'bx_ads', 0, '_bx_ads_form_category_display_edit');
+
+INSERT INTO `sys_form_inputs`(`object`, `module`, `name`, `value`, `values`, `checked`, `type`, `caption_system`, `caption`, `info`, `required`, `collapsed`, `html`, `attrs`, `attrs_tr`, `attrs_wrapper`, `checker_func`, `checker_params`, `checker_error`, `db_pass`, `db_params`, `editable`, `deletable`) VALUES 
+('bx_ads_category', 'bx_ads', 'delete_confirm', 1, '', 0, 'checkbox', '_bx_ads_form_category_input_sys_delete_confirm', '_bx_ads_form_category_input_delete_confirm', '_bx_ads_form_category_input_delete_confirm_info', 1, 0, 0, '', '', '', 'Avail', '', '_bx_ads_form_category_input_delete_confirm_error', '', '', 1, 0),
+('bx_ads_category', 'bx_ads', 'parent_id', '', '', 0, 'select', '_bx_ads_form_category_input_sys_parent_id', '_bx_ads_form_category_input_parent_id', '', 0, 0, 0, '', '', '', '', '', '', 'Int', '', 1, 0),
+('bx_ads_category', 'bx_ads', 'title', '', '', 0, 'text_translatable', '_bx_ads_form_category_input_sys_title', '_bx_ads_form_category_input_title', '', 1, 0, 0, '', '', '', 'AvailTranslatable', 'a:1:{i:0;s:5:"title";}', '_bx_ads_form_category_input_title_err', 'Xss', '', 1, 0),
+('bx_ads_category', 'bx_ads', 'text', '', '', 0, 'textarea_translatable', '_bx_ads_form_category_input_sys_text', '_bx_ads_form_category_input_text', '', 0, 0, 2, '', '', '', '', '', '', 'XssHtml', '', 1, 0),
+('bx_ads_category', 'bx_ads', 'type', '', '', 0, 'select', '_bx_ads_form_category_input_sys_type', '_bx_ads_form_category_input_type', '_bx_ads_form_category_input_type_info', 1, 0, 0, '', '', '', 'Avail', '', '_bx_ads_form_category_input_type_err', 'Int', '', 0, 0),
+('bx_ads_category', 'bx_ads', 'type_clone', 'on', '', 0, 'switcher', '_bx_ads_form_category_input_sys_type_clone', '_bx_ads_form_category_input_type_clone', '', 0, 0, 0, 'a:1:{s:8:"onchange";s:33:"oBxAdsStudio.onChangeClone(this);";}', '', '', '', '', '', '', '', 0, 0),
+('bx_ads_category', 'bx_ads', 'type_title', '', '', 0, 'text_translatable', '_bx_ads_form_category_input_sys_type_title', '_bx_ads_form_category_input_type_title', '', 0, 0, 0, 'a:1:{s:8:"disabled";s:8:"disabled";}', 'a:1:{s:5:"style";s:13:"display:none;";}', '', '', '', '', '', '', 0, 0),
+('bx_ads_category', 'bx_ads', 'icon', '', '', 0, 'text', '_bx_ads_form_category_input_sys_icon', '_bx_ads_form_category_input_icon', '', 0, 0, 0, '', '', '', '', '', '', 'Xss', '', 1, 0),
+('bx_ads_category', 'bx_ads', 'controls', '', 'do_submit,do_cancel', 0, 'input_set', '', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
+('bx_ads_category', 'bx_ads', 'do_submit', '_bx_ads_form_category_input_do_submit', '', 0, 'submit', '_bx_ads_form_category_input_sys_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_ads_category', 'bx_ads', 'do_cancel', '_bx_ads_form_category_input_do_cancel', '', 0, 'button', '_bx_ads_form_category_input_sys_do_cancel', '', '', 0, 0, 0, 'a:2:{s:7:"onclick";s:45:"$(''.bx-popup-applied:visible'').dolPopupHide()";s:5:"class";s:22:"bx-def-margin-sec-left";}', '', '', '', '', '', '', '', 1, 0);
+
+INSERT INTO `sys_form_display_inputs`(`display_name`, `input_name`, `visible_for_levels`, `active`, `order`) VALUES 
+('bx_ads_category_add', 'parent_id', 2147483647, 1, 1),
+('bx_ads_category_add', 'type', 2147483647, 1, 2),
+('bx_ads_category_add', 'type_clone', 2147483647, 1, 3),
+('bx_ads_category_add', 'type_title', 2147483647, 1, 4),
+('bx_ads_category_add', 'title', 2147483647, 1, 5),
+('bx_ads_category_add', 'text', 2147483647, 1, 6),
+('bx_ads_category_add', 'icon', 2147483647, 1, 7),
+('bx_ads_category_add', 'controls', 2147483647, 1, 8),
+('bx_ads_category_add', 'do_submit', 2147483647, 1, 9),
+('bx_ads_category_add', 'do_cancel', 2147483647, 1, 10),
+
+('bx_ads_category_delete', 'delete_confirm', 2147483647, 1, 1),
+('bx_ads_category_delete', 'do_submit', 2147483647, 1, 2),
+
+('bx_ads_category_edit', 'parent_id', 2147483647, 1, 1),
+('bx_ads_category_edit', 'title', 2147483647, 1, 2),
+('bx_ads_category_edit', 'text', 2147483647, 1, 3),
+('bx_ads_category_edit', 'icon', 2147483647, 1, 4),
+('bx_ads_category_edit', 'controls', 2147483647, 1, 5),
+('bx_ads_category_edit', 'do_submit', 2147483647, 1, 6),
+('bx_ads_category_edit', 'do_cancel', 2147483647, 1, 7);
+
+
+-- FORMS: entry (ad)
+INSERT INTO `sys_objects_form`(`object`, `module`, `title`, `action`, `form_attrs`, `table`, `key`, `uri`, `uri_title`, `submit_name`, `params`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_ads', 'bx_ads', '_bx_ads_form_entry', '', 'a:1:{s:7:"enctype";s:19:"multipart/form-data";}', 'bx_ads_entries', 'id', '', '', 'a:1:{i:0;s:9:"do_submit";}', '', 0, 1, 'BxAdsFormEntry', 'modules/boonex/ads/classes/BxAdsFormEntry.php');
+
+INSERT INTO `sys_form_displays`(`object`, `display_name`, `module`, `view_mode`, `title`) VALUES 
+('bx_ads', 'bx_ads_entry_add', 'bx_ads', 0, '_bx_ads_form_entry_display_add'),
+('bx_ads', 'bx_ads_entry_delete', 'bx_ads', 0, '_bx_ads_form_entry_display_delete'),
+
+('bx_ads', 'bx_ads_entry_price_add', 'bx_ads', 0, '_bx_ads_form_entry_price_display_add'),
+('bx_ads', 'bx_ads_entry_price_edit', 'bx_ads', 0, '_bx_ads_form_entry_price_display_edit'),
+('bx_ads', 'bx_ads_entry_price_view', 'bx_ads', 1, '_bx_ads_form_entry_price_display_view'),
+
+('bx_ads', 'bx_ads_entry_price_year_add', 'bx_ads', 0, '_bx_ads_form_entry_price_year_display_add'),
+('bx_ads', 'bx_ads_entry_price_year_edit', 'bx_ads', 0, '_bx_ads_form_entry_price_year_display_edit'),
+('bx_ads', 'bx_ads_entry_price_year_view', 'bx_ads', 1, '_bx_ads_form_entry_price_year_display_view');
+
+INSERT INTO `sys_form_inputs`(`object`, `module`, `name`, `value`, `values`, `checked`, `type`, `caption_system`, `caption`, `info`, `required`, `collapsed`, `html`, `attrs`, `attrs_tr`, `attrs_wrapper`, `checker_func`, `checker_params`, `checker_error`, `db_pass`, `db_params`, `editable`, `deletable`) VALUES 
+('bx_ads', 'bx_ads', 'allow_view_to', '', '', 0, 'custom', '_bx_ads_form_entry_input_sys_allow_view_to', '_bx_ads_form_entry_input_allow_view_to', '', 1, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_ads', 'bx_ads', 'delete_confirm', 1, '', 0, 'checkbox', '_bx_ads_form_entry_input_sys_delete_confirm', '_bx_ads_form_entry_input_delete_confirm', '_bx_ads_form_entry_input_delete_confirm_info', 1, 0, 0, '', '', '', 'Avail', '', '_bx_ads_form_entry_input_delete_confirm_error', '', '', 1, 0),
+('bx_ads', 'bx_ads', 'do_submit', '_bx_ads_form_entry_input_do_submit', '', 0, 'submit', '_bx_ads_form_entry_input_sys_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_ads', 'bx_ads', 'location', '', '', 0, 'location', '_sys_form_input_sys_location', '_sys_form_input_location', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_ads', 'bx_ads', 'covers', 'a:1:{i:0;s:12:"bx_ads_html5";}', 'a:2:{s:13:"bx_ads_simple";s:26:"_sys_uploader_simple_title";s:12:"bx_ads_html5";s:25:"_sys_uploader_html5_title";}', 0, 'files', '_bx_ads_form_entry_input_sys_covers', '_bx_ads_form_entry_input_covers', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_ads', 'bx_ads', 'pictures', 'a:1:{i:0;s:19:"bx_ads_photos_html5";}', 'a:2:{s:20:"bx_ads_photos_simple";s:26:"_sys_uploader_simple_title";s:19:"bx_ads_photos_html5";s:25:"_sys_uploader_html5_title";}', 0, 'files', '_bx_ads_form_entry_input_sys_pictures', '_bx_ads_form_entry_input_pictures', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_ads', 'bx_ads', 'videos', 'a:2:{i:0;s:19:"bx_ads_videos_html5";i:1;s:26:"bx_ads_videos_record_video";}', 'a:3:{s:20:"bx_ads_videos_simple";s:26:"_sys_uploader_simple_title";s:19:"bx_ads_videos_html5";s:25:"_sys_uploader_html5_title";s:26:"bx_ads_videos_record_video";s:32:"_sys_uploader_record_video_title";}', 0, 'files', '_bx_ads_form_entry_input_sys_videos', '_bx_ads_form_entry_input_videos', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_ads', 'bx_ads', 'files', 'a:1:{i:0;s:18:"bx_ads_files_html5";}', 'a:2:{s:19:"bx_ads_files_simple";s:26:"_sys_uploader_simple_title";s:18:"bx_ads_files_html5";s:25:"_sys_uploader_html5_title";}', 0, 'files', '_bx_ads_form_entry_input_sys_files', '_bx_ads_form_entry_input_files', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_ads', 'bx_ads', 'polls', '', '', 0, 'custom', '_bx_ads_form_entry_input_sys_polls', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_ads', 'bx_ads', 'text', '', '', 0, 'textarea', '_bx_ads_form_entry_input_sys_text', '_bx_ads_form_entry_input_text', '', 1, 0, 2, '', '', '', 'Avail', '', '_bx_ads_form_entry_input_text_err', 'XssHtml', '', 1, 0),
+('bx_ads', 'bx_ads', 'title', '', '', 0, 'text', '_bx_ads_form_entry_input_sys_title', '_bx_ads_form_entry_input_title', '', 1, 0, 0, '', '', '', 'Avail', '', '_bx_ads_form_entry_input_title_err', 'Xss', '', 1, 0),
+('bx_ads', 'bx_ads', 'price', '', '', 0, 'text', '_bx_ads_form_entry_input_sys_price', '_bx_ads_form_entry_input_price', '', 0, 0, 0, '', '', '', '', '', '', 'Xss', '', 1, 0),
+('bx_ads', 'bx_ads', 'year', '', '', 0, 'text', '_bx_ads_form_entry_input_sys_year', '_bx_ads_form_entry_input_year', '', 0, 0, 0, '', '', '', '', '', '', 'Xss', '', 1, 0),
+('bx_ads', 'bx_ads', 'category', '', '', 0, 'hidden', '_bx_ads_form_entry_input_sys_category', '', '', 0, 0, 0, '', '', '', '', '', '', 'Int', '', 0, 0),
+('bx_ads', 'bx_ads', 'category_view', '', '', 0, 'text', '_bx_ads_form_entry_input_sys_category_view', '_bx_ads_form_entry_input_category_view', '', 0, 0, 0, 'a:1:{s:8:"disabled";s:8:"disabled";}', '', '', '', '', '', '', '', 1, 0),
+('bx_ads', 'bx_ads', 'category_select', '', '', 0, 'select', '_bx_ads_form_entry_input_sys_category_select', '_bx_ads_form_entry_input_category_select', '', 1, 0, 0, 'a:1:{s:8:"onchange";s:35:"oBxAdsEntry.onChangeCategory(this);";}', '', '', '', '', '', '', '', 0, 0),
+('bx_ads', 'bx_ads', 'added', '', '', 0, 'datetime', '_bx_ads_form_entry_input_sys_date_added', '_bx_ads_form_entry_input_date_added', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_ads', 'bx_ads', 'changed', '', '', 0, 'datetime', '_bx_ads_form_entry_input_sys_date_changed', '_bx_ads_form_entry_input_date_changed', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_ads', 'bx_ads', 'attachments', '', '', 0, 'custom', '_bx_ads_form_entry_input_sys_attachments', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_ads', 'bx_ads', 'labels', '', '', 0, 'custom', '_sys_form_input_sys_labels', '_sys_form_input_labels', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0);
+
+INSERT INTO `sys_form_display_inputs`(`display_name`, `input_name`, `visible_for_levels`, `active`, `order`) VALUES 
+('bx_ads_entry_add', 'category_select', 2147483647, 1, 1),
+
+('bx_ads_entry_delete', 'delete_confirm', 2147483647, 1, 1),
+('bx_ads_entry_delete', 'do_submit', 2147483647, 1, 2),
+
+('bx_ads_entry_price_add', 'category', 2147483647, 1, 1),
+('bx_ads_entry_price_add', 'category_view', 2147483647, 1, 2),
+('bx_ads_entry_price_add', 'title', 2147483647, 1, 3),
+('bx_ads_entry_price_add', 'price', 2147483647, 1, 4),
+('bx_ads_entry_price_add', 'text', 2147483647, 1, 5),
+('bx_ads_entry_price_add', 'attachments', 2147483647, 1, 6),
+('bx_ads_entry_price_add', 'pictures', 2147483647, 1, 7),
+('bx_ads_entry_price_add', 'videos', 2147483647, 1, 8),
+('bx_ads_entry_price_add', 'files', 2147483647, 1, 9),
+('bx_ads_entry_price_add', 'polls', 2147483647, 1, 10),
+('bx_ads_entry_price_add', 'covers', 2147483647, 1, 11),
+('bx_ads_entry_price_add', 'allow_view_to', 2147483647, 1, 12),
+('bx_ads_entry_price_add', 'location', 2147483647, 1, 13),
+('bx_ads_entry_price_add', 'do_submit', 2147483647, 1, 14),
+
+('bx_ads_entry_price_edit', 'category_view', 2147483647, 1, 1),
+('bx_ads_entry_price_edit', 'title', 2147483647, 1, 2),
+('bx_ads_entry_price_edit', 'price', 2147483647, 1, 3),
+('bx_ads_entry_price_edit', 'text', 2147483647, 1, 4),
+('bx_ads_entry_price_edit', 'attachments', 2147483647, 1, 5),
+('bx_ads_entry_price_edit', 'pictures', 2147483647, 1, 6),
+('bx_ads_entry_price_edit', 'videos', 2147483647, 1, 7),
+('bx_ads_entry_price_edit', 'files', 2147483647, 1, 8),
+('bx_ads_entry_price_edit', 'polls', 2147483647, 1, 9),
+('bx_ads_entry_price_edit', 'covers', 2147483647, 1, 10),
+('bx_ads_entry_price_edit', 'allow_view_to', 2147483647, 1, 11),
+('bx_ads_entry_price_edit', 'location', 2147483647, 1, 12),
+('bx_ads_entry_price_edit', 'do_submit', 2147483647, 1, 13),
+
+('bx_ads_entry_price_view', 'category_view', 2147483647, 1, 1),
+('bx_ads_entry_price_view', 'price', 2147483647, 1, 2),
+('bx_ads_entry_price_view', 'added', 2147483647, 1, 3),
+('bx_ads_entry_price_view', 'changed', 2147483647, 1, 4),
+
+('bx_ads_entry_price_year_add', 'category', 2147483647, 1, 1),
+('bx_ads_entry_price_year_add', 'category_view', 2147483647, 1, 2),
+('bx_ads_entry_price_year_add', 'title', 2147483647, 1, 3),
+('bx_ads_entry_price_year_add', 'price', 2147483647, 1, 4),
+('bx_ads_entry_price_year_add', 'year', 2147483647, 1, 5),
+('bx_ads_entry_price_year_add', 'text', 2147483647, 1, 6),
+('bx_ads_entry_price_year_add', 'attachments', 2147483647, 1, 7),
+('bx_ads_entry_price_year_add', 'pictures', 2147483647, 1, 8),
+('bx_ads_entry_price_year_add', 'videos', 2147483647, 1, 9),
+('bx_ads_entry_price_year_add', 'files', 2147483647, 1, 10),
+('bx_ads_entry_price_year_add', 'polls', 2147483647, 1, 11),
+('bx_ads_entry_price_year_add', 'covers', 2147483647, 1, 12),
+('bx_ads_entry_price_year_add', 'allow_view_to', 2147483647, 1, 13),
+('bx_ads_entry_price_year_add', 'location', 2147483647, 1, 14),
+('bx_ads_entry_price_year_add', 'do_submit', 2147483647, 1, 15),
+
+('bx_ads_entry_price_year_edit', 'category_view', 2147483647, 1, 1),
+('bx_ads_entry_price_year_edit', 'title', 2147483647, 1, 2),
+('bx_ads_entry_price_year_edit', 'price', 2147483647, 1, 3),
+('bx_ads_entry_price_year_edit', 'year', 2147483647, 1, 4),
+('bx_ads_entry_price_year_edit', 'text', 2147483647, 1, 5),
+('bx_ads_entry_price_year_edit', 'attachments', 2147483647, 1, 6),
+('bx_ads_entry_price_year_edit', 'pictures', 2147483647, 1, 7),
+('bx_ads_entry_price_year_edit', 'videos', 2147483647, 1, 8),
+('bx_ads_entry_price_year_edit', 'files', 2147483647, 1, 9),
+('bx_ads_entry_price_year_edit', 'polls', 2147483647, 1, 10),
+('bx_ads_entry_price_year_edit', 'covers', 2147483647, 1, 11),
+('bx_ads_entry_price_year_edit', 'allow_view_to', 2147483647, 1, 12),
+('bx_ads_entry_price_year_edit', 'location', 2147483647, 1, 13),
+('bx_ads_entry_price_year_edit', 'do_submit', 2147483647, 1, 14),
+
+('bx_ads_entry_price_year_view', 'category_view', 2147483647, 1, 1),
+('bx_ads_entry_price_year_view', 'price', 2147483647, 1, 2),
+('bx_ads_entry_price_year_view', 'year', 2147483647, 1, 3),
+('bx_ads_entry_price_year_view', 'added', 2147483647, 1, 4),
+('bx_ads_entry_price_year_view', 'changed', 2147483647, 1, 5);
+
+-- FORMS: poll
+INSERT INTO `sys_objects_form` (`object`, `module`, `title`, `action`, `form_attrs`, `submit_name`, `table`, `key`, `uri`, `uri_title`, `params`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES
+('bx_ads_poll', 'bx_ads', '_bx_ads_form_poll', '', '', 'do_submit', 'bx_ads_polls', 'id', '', '', 'a:1:{s:14:"checker_helper";s:26:"BxAdsFormPollCheckerHelper";}', 0, 1, 'BxAdsFormPoll', 'modules/boonex/ads/classes/BxAdsFormPoll.php');
+
+INSERT INTO `sys_form_displays` (`display_name`, `module`, `object`, `title`, `view_mode`) VALUES
+('bx_ads_poll_add', 'bx_ads', 'bx_ads_poll', '_bx_ads_form_poll_display_add', 0);
+
+INSERT INTO `sys_form_inputs` (`object`, `module`, `name`, `value`, `values`, `checked`, `type`, `caption_system`, `caption`, `info`, `required`, `collapsed`, `html`, `attrs`, `attrs_tr`, `attrs_wrapper`, `checker_func`, `checker_params`, `checker_error`, `db_pass`, `db_params`, `editable`, `deletable`) VALUES
+('bx_ads_poll', 'bx_ads', 'text', '', '', 0, 'text', '_bx_ads_form_poll_input_sys_text', '_bx_ads_form_poll_input_text', '', 1, 0, 0, '', '', '', 'Avail', '', '_bx_ads_form_poll_input_text_err', 'Xss', '', 1, 0),
+('bx_ads_poll', 'bx_ads', 'answers', '', '', 0, 'custom', '_bx_ads_form_poll_input_sys_answers', '_bx_ads_form_poll_input_answers', '', 1, 0, 0, '', '', '', 'AvailAnswers', '', '_bx_ads_form_poll_input_answers_err', '', '', 1, 0),
+('bx_ads_poll', 'bx_ads', 'controls', '', 'do_submit,do_cancel', 0, 'input_set', '', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
+('bx_ads_poll', 'bx_ads', 'do_submit', '_bx_ads_form_poll_input_do_submit', '', 0, 'submit', '_bx_ads_form_poll_input_sys_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
+('bx_ads_poll', 'bx_ads', 'do_cancel', '_bx_ads_form_poll_input_do_cancel', '', 0, 'button', '_bx_ads_form_poll_input_do_cancel', '', '', 0, 0, 0, 'a:2:{s:7:"onclick";s:45:"$(''.bx-popup-applied:visible'').dolPopupHide()";s:5:"class";s:22:"bx-def-margin-sec-left";}', '', '', '', '', '', '', '', 0, 0);
+
+INSERT INTO `sys_form_display_inputs` (`display_name`, `input_name`, `visible_for_levels`, `active`, `order`) VALUES
+('bx_ads_poll_add', 'text', 2147483647, 1, 1),
+('bx_ads_poll_add', 'answers', 2147483647, 1, 2),
+('bx_ads_poll_add', 'controls', 2147483647, 1, 3),
+('bx_ads_poll_add', 'do_submit', 2147483647, 1, 4),
+('bx_ads_poll_add', 'do_cancel', 2147483647, 1, 5);
+
+
+-- COMMENTS
+INSERT INTO `sys_objects_cmts` (`Name`, `Module`, `Table`, `CharsPostMin`, `CharsPostMax`, `CharsDisplayMax`, `Html`, `PerView`, `PerViewReplies`, `BrowseType`, `IsBrowseSwitch`, `PostFormPosition`, `NumberOfLevels`, `IsDisplaySwitch`, `IsRatable`, `ViewingThreshold`, `IsOn`, `RootStylePrefix`, `BaseUrl`, `ObjectVote`, `TriggerTable`, `TriggerFieldId`, `TriggerFieldAuthor`, `TriggerFieldTitle`, `TriggerFieldComments`, `ClassName`, `ClassFile`) VALUES
+('bx_ads', 'bx_ads', 'bx_ads_cmts', 1, 5000, 1000, 3, 5, 3, 'tail', 1, 'bottom', 1, 1, 1, -3, 1, 'cmt', 'page.php?i=view-ad&id={object_id}', '', 'bx_ads_entries', 'id', 'author', 'title', 'comments', '', ''),
+('bx_ads_reviews', 'bx_ads', 'bx_ads_reviews', 1, 5000, 1000, 3, 5, 3, 'tail', 1, 'bottom', 1, 0, 1, -3, 1, 'cmt', 'page.php?i=view-ad&id={object_id}', '', 'bx_ads_entries', 'id', 'author', 'title', 'reviews', 'BxTemplCmtsReviews', '');
+
+-- VOTES
+INSERT INTO `sys_objects_vote` (`Name`, `TableMain`, `TableTrack`, `PostTimeout`, `MinValue`, `MaxValue`, `IsUndo`, `IsOn`, `TriggerTable`, `TriggerFieldId`, `TriggerFieldAuthor`, `TriggerFieldRate`, `TriggerFieldRateCount`, `ClassName`, `ClassFile`) VALUES 
+('bx_ads', 'bx_ads_votes', 'bx_ads_votes_track', '604800', '1', '1', '0', '1', 'bx_ads_entries', 'id', 'author', 'rate', 'votes', '', ''),
+('bx_ads_reactions', 'bx_ads_reactions', 'bx_ads_reactions_track', '604800', '1', '1', '1', '1', 'bx_ads_entries', 'id', 'author', 'rrate', 'rvotes', 'BxTemplVoteReactions', ''),
+('bx_ads_poll_answers', 'bx_ads_polls_answers_votes', 'bx_ads_polls_answers_votes_track', '604800', '1', '1', '0', '1', 'bx_ads_polls_answers', 'id', 'author_id', 'rate', 'votes', 'BxAdsVotePollAnswers', 'modules/boonex/ads/classes/BxAdsVotePollAnswers.php');
+
+-- SCORES
+INSERT INTO `sys_objects_score` (`name`, `module`, `table_main`, `table_track`, `post_timeout`, `is_on`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_score`, `trigger_field_cup`, `trigger_field_cdown`, `class_name`, `class_file`) VALUES 
+('bx_ads', 'bx_ads', 'bx_ads_scores', 'bx_ads_scores_track', '604800', '0', 'bx_ads_entries', 'id', 'author', 'score', 'sc_up', 'sc_down', '', '');
+
+-- REPORTS
+INSERT INTO `sys_objects_report` (`name`, `module`, `table_main`, `table_track`, `is_on`, `base_url`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_count`, `class_name`, `class_file`) VALUES 
+('bx_ads', 'bx_ads', 'bx_ads_reports', 'bx_ads_reports_track', '1', 'page.php?i=view-ad&id={object_id}', 'bx_ads_entries', 'id', 'author', 'reports', '', '');
+
+-- VIEWS
+INSERT INTO `sys_objects_view` (`name`, `table_track`, `period`, `is_on`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_count`, `class_name`, `class_file`) VALUES 
+('bx_ads', 'bx_ads_views_track', '86400', '1', 'bx_ads_entries', 'id', 'author', 'views', '', '');
+
+-- FAFORITES
+INSERT INTO `sys_objects_favorite` (`name`, `table_track`, `is_on`, `is_undo`, `is_public`, `base_url`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_count`, `class_name`, `class_file`) VALUES 
+('bx_ads', 'bx_ads_favorites_track', '1', '1', '1', 'page.php?i=view-ad&id={object_id}', 'bx_ads_entries', 'id', 'author', 'favorites', '', '');
+
+-- FEATURED
+INSERT INTO `sys_objects_feature` (`name`, `module`, `is_on`, `is_undo`, `base_url`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_flag`, `class_name`, `class_file`) VALUES 
+('bx_ads', 'bx_ads', '1', '1', 'page.php?i=view-ad&id={object_id}', 'bx_ads_entries', 'id', 'author', 'featured', '', '');
+
+-- CONTENT INFO
+INSERT INTO `sys_objects_content_info` (`name`, `title`, `alert_unit`, `alert_action_add`, `alert_action_update`, `alert_action_delete`, `class_name`, `class_file`) VALUES
+('bx_ads', '_bx_ads', 'bx_ads', 'added', 'edited', 'deleted', '', ''),
+('bx_ads_cmts', '_bx_ads_cmts', 'bx_ads', 'commentPost', 'commentUpdated', 'commentRemoved', 'BxDolContentInfoCmts', ''),
+('bx_ads_reviews', '_bx_ads_reviews', 'bx_ads_reviews', 'commentPost', 'commentUpdated', 'commentRemoved', 'BxDolContentInfoCmts', '');
+
+INSERT INTO `sys_content_info_grids` (`object`, `grid_object`, `grid_field_id`, `condition`, `selection`) VALUES
+('bx_ads', 'bx_ads_administration', 'id', '', ''),
+('bx_ads', 'bx_ads_common', 'id', '', '');
+
+-- SEARCH EXTENDED
+INSERT INTO `sys_objects_search_extended` (`object`, `object_content_info`, `module`, `title`, `active`, `class_name`, `class_file`) VALUES
+('bx_ads', 'bx_ads', 'bx_ads', '_bx_ads_search_extended', 1, '', ''),
+('bx_ads_cmts', 'bx_ads_cmts', 'bx_ads', '_bx_ads_search_extended_cmts', 1, 'BxTemplSearchExtendedCmts', ''),
+('bx_ads_reviews', 'bx_ads_reviews', 'bx_ads', '_bx_ads_search_extended_reviews', 1, 'BxTemplSearchExtendedCmts', '');
+
+-- STUDIO: page & widget
+INSERT INTO `sys_std_pages`(`index`, `name`, `header`, `caption`, `icon`) VALUES
+(3, 'bx_ads', '_bx_ads', '_bx_ads', 'bx_ads@modules/boonex/ads/|std-icon.svg');
+SET @iPageId = LAST_INSERT_ID();
+
+SET @iParentPageId = (SELECT `id` FROM `sys_std_pages` WHERE `name` = 'home');
+SET @iParentPageOrder = (SELECT MAX(`order`) FROM `sys_std_pages_widgets` WHERE `page_id` = @iParentPageId);
+INSERT INTO `sys_std_widgets` (`page_id`, `module`, `type`, `url`, `click`, `icon`, `caption`, `cnt_notices`, `cnt_actions`) VALUES
+(@iPageId, 'bx_ads', 'content', '{url_studio}module.php?name=bx_ads', '', 'bx_ads@modules/boonex/ads/|std-icon.svg', '_bx_ads', '', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:11:"get_actions";s:6:"params";a:0:{}s:5:"class";s:18:"TemplStudioModules";}');
+INSERT INTO `sys_std_pages_widgets` (`page_id`, `widget_id`, `order`) VALUES
+(@iParentPageId, LAST_INSERT_ID(), IF(ISNULL(@iParentPageOrder), 1, @iParentPageOrder + 1));
+

+ 51 - 0
modules/boonex/albums/updates/12.0.3_12.0.4/install/config.php

@@ -0,0 +1,51 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'title' => 'Albums',
+    'version_from' => '12.0.3',
+    'version_to' => '12.0.4',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '12.1.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/albums/updates/update_12.0.3_12.0.4/',
+    'home_uri' => 'albums_update_1203_1204',
+
+    'module_dir' => 'boonex/albums/',
+    'module_uri' => 'albums',
+
+    'db_prefix' => 'bx_albums_',
+    'class_prefix' => 'BxAlbums',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_files' => 1,
+        'update_languages' => 0,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Albums',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

+ 23 - 0
modules/boonex/albums/updates/12.0.3_12.0.4/install/installer.php

@@ -0,0 +1,23 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+class BxAlbumsUpdater extends BxDolStudioUpdater
+{
+    function __construct($aConfig)
+    {
+        parent::__construct($aConfig);
+    }
+
+    public function actionExecuteSql($sOperation)
+    {
+        if($sOperation == 'install') {
+            if(!$this->oDb->isFieldExists('bx_albums_files', 'dimensions'))
+                $this->oDb->query("ALTER TABLE `bx_albums_files` ADD `dimensions` varchar(12) NOT NULL AFTER `size`");
+        }
+
+        return parent::actionExecuteSql($sOperation);
+    }
+}

+ 2 - 0
modules/boonex/albums/updates/12.0.3_12.0.4/install/sql/install.sql

@@ -0,0 +1,2 @@
+-- STORAGES & TRANSCODERS
+UPDATE `sys_objects_storage` SET `params`='a:1:{s:6:"fields";a:1:{s:10:"dimensions";s:17:"getFileDimensions";}}' WHERE `object`='bx_albums_files';

+ 975 - 0
modules/boonex/albums/updates/12.0.3_12.0.4/source/classes/BxAlbumsModule.php

@@ -0,0 +1,975 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Albums Albums
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+bx_import('BxDolAcl');
+
+/**
+ * Albums module
+ */
+class BxAlbumsModule extends BxBaseModTextModule
+{
+    protected $_aContexts = array('popular', 'public', 'author');
+
+    function __construct(&$aModule)
+    {
+        parent::__construct($aModule);
+    }
+
+    public function serviceGetSafeServices()
+    {
+        $a = parent::serviceGetSafeServices();
+        return array_merge($a, array (
+            'EntityAddFiles' => '',
+            'MediaComments' => '',
+            'BrowseRecentMedia' => '',
+            'BrowseFeaturedMedia' => '',
+            'BrowsePopularMedia' => '',
+            'BrowseTopMedia' => '',
+            'BrowseFavoriteMedia' => '',
+        ));
+    }
+
+    /**
+     * Entry actions and social sharing block
+     */
+    public function serviceEntityAllActions ($mixedContent = false, $aParams = array())
+    {
+        if(!empty($mixedContent)) {
+            if(!is_array($mixedContent))
+               $mixedContent = array((int)$mixedContent, array());
+        }
+        else {
+            $mixedContent = $this->_getContent();
+            if($mixedContent === false)
+                return false;
+        }
+        
+        list($iContentId, $aContentInfo) = $mixedContent;
+
+        $aMedias = $this->_oDb->getMediaListByContentId($iContentId);
+        if(!empty($aMedias) && is_array($aMedias)) {
+            $aMedia = array_shift($aMedias);
+            if(!empty($aMedia['file_id']))
+                $aParams = array_merge(array(
+                    'entry_thumb' => $aMedia['file_id']
+                ), $aParams);
+        }
+
+        return parent::serviceEntityAllActions(array($iContentId, $aContentInfo), $aParams);
+    }
+    
+    /**
+     * @page service Service Calls
+     * @section bx_albums Albums
+     * @subsection bx_albums-forms Forms
+     * @subsubsection bx_albums-entity_add_files entity_add_files
+     * 
+     * @code bx_srv('bx_albums', 'entity_add_files', [...]); @endcode
+     * 
+     * Display form for adding media to the album.
+     * @param $iContentId album content id where media will be added, if it's not provided then it's determined from 'id' GET variable
+     * @return HTML string with form, all necessary CSS and JS files are automatically added to the HEAD section of the site HTML. On error false or empty string is returned.
+     * 
+     * @see BxAlbumsModule::serviceEntityAddFiles
+     */
+    /** 
+     * @ref bx_albums-entity_add_files "entity_add_files"
+     */
+    public function serviceEntityAddFiles ($iContentId = 0)
+    {
+        return $this->_serviceEntityForm ('editDataForm', $iContentId, 'bx_albums_entry_add_images');
+    }
+
+    /**
+     * Delete file and album association, also file views, votes, comments, meta data are also deleted
+     * @param $iFileId file ID
+     * @return true on success of false on error
+     */ 
+    public function serviceDeleteFileAssociations($iFileId)
+    {        
+        $CNF = &$this->_oConfig->CNF;
+
+        if (!($aMediaInfo = $this->_oDb->getMediaInfoSimpleByFileId($iFileId))) // file is already deleted
+            return true; 
+    
+        if (!$this->_oDb->deassociateFileWithContent(0, $iFileId))
+            return false;
+
+        $aContentInfo = $this->_oDb->getContentInfoById($aMediaInfo['content_id']);
+        $iSender = isLogged() ? bx_get_logged_profile_id() : $aMediaInfo['author'];
+        $iAuthor = isset($aContentInfo[$CNF['FIELD_AUTHOR']]) ? $aContentInfo[$CNF['FIELD_AUTHOR']] : $aMediaInfo['author'];
+        bx_alert($this->getName(), 'media_deleted', $aMediaInfo['content_id'], $iSender, array(
+            'object_author_id' => $iAuthor,
+
+            'subobject_id' => $aMediaInfo['id'],
+
+            'media_id' => $aMediaInfo['id'], 
+            'media_info' => $aMediaInfo,
+        ));
+
+        bx_alert($this->getName() . '_media', 'deleted', $aMediaInfo['id'], $iSender, array(
+            'object_id' => $aMediaInfo['content_id'],
+            'object_author_id' => $iAuthor,
+
+            'media_info' => $aMediaInfo,
+        ));        
+
+        if (!empty($CNF['OBJECT_VIEWS_MEDIA'])) {
+            $o = BxDolView::getObjectInstance($CNF['OBJECT_VIEWS_MEDIA'], $aMediaInfo['id']);
+            if ($o) $o->onObjectDelete();
+        }
+
+        if (!empty($CNF['OBJECT_VOTES_MEDIA'])) {
+            $o = BxDolVote::getObjectInstance($CNF['OBJECT_VOTES_MEDIA'], $aMediaInfo['id']);
+            if ($o) $o->onObjectDelete();
+        }
+
+        if (!empty($CNF['OBJECT_SCORES_MEDIA'])) {
+            $o = BxDolScore::getObjectInstance($CNF['OBJECT_SCORES_MEDIA'], $aMediaInfo['id']);
+            if ($o) $o->onObjectDelete();
+        }
+
+        if (!empty($CNF['OBJECT_COMMENTS_MEDIA'])) {
+            $o = BxDolCmts::getObjectInstance($CNF['OBJECT_COMMENTS_MEDIA'], $aMediaInfo['id']);
+            if ($o) $o->onObjectDelete();
+        }
+
+        if (!empty($CNF['OBJECT_METATAGS_MEDIA'])) {
+            $oMetatags = BxDolMetatags::getObjectInstance($CNF['OBJECT_METATAGS_MEDIA']);
+            $oMetatags->onDeleteContent($aMediaInfo['id']);
+        }
+
+        if (!empty($CNF['OBJECT_METATAGS_MEDIA_CAMERA'])) {
+            $oMetatags = BxDolMetatags::getObjectInstance($CNF['OBJECT_METATAGS_MEDIA_CAMERA']);
+            $oMetatags->onDeleteContent($aMediaInfo['id']);
+        }
+
+        return true;
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_albums Albums
+     * @subsection bx_albums-page_blocks Page Blocks
+     * @subsubsection bx_albums-media_comments media_comments
+     * 
+     * @code bx_srv('bx_albums', 'media_comments', [...]); @endcode
+     * 
+     * Display media comments block.
+     * @param $iMediaId media ID, if it's omitted then it's taken from 'id' GET variable.
+     * @return HTML string with comments. On error false or empty string is returned.
+     * 
+     * @see BxAlbumsModule::serviceMediaComments
+     */
+    /** 
+     * @ref bx_albums-media_comments "media_comments"
+     */
+    public function serviceMediaComments ($iMediaId = 0)
+    {
+        return $this->_entityComments($this->_oConfig->CNF['OBJECT_COMMENTS_MEDIA'], $iMediaId);
+    }
+
+    /**
+     * Display media author block.
+     * @param $iMediaId media ID, if it's omitted then it's taken from 'id' GET variable.
+     * @return HTML string with block content. On error false or empty string is returned.
+     */
+    public function serviceMediaAuthor ($iMediaId = 0)
+    {
+        return $this->_serviceTemplateFunc ('mediaAuthor', $iMediaId, 'getMediaInfoById');
+    }
+
+    /**
+     * Entry actions and social sharing block
+     */
+    public function serviceMediaAllActions ($mixedContent = false, $aParams = array())
+    {
+        $iMediaId = 0;
+        $aMediaInfo = array();
+
+        $bContent = !empty($mixedContent);
+        if($bContent && is_array($mixedContent))
+            list($iMediaId, $aMediaInfo) = $mixedContent;
+        else {
+            if($bContent)
+                $iMediaId = (int)$mixedContent;
+            else
+                $iMediaId = bx_process_input(bx_get('id'), BX_DATA_INT);
+
+            if(!$iMediaId)
+                return false;
+
+            $aMediaInfo = $this->_oDb->getMediaInfoById($iMediaId);
+        }
+
+        if(!$iMediaId || !$aMediaInfo)
+            return false;
+
+        $CNF = &$this->_oConfig->CNF;
+
+        return parent::serviceEntityAllActions (array($iMediaId, $aMediaInfo), array_merge(array(
+            'object_menu' => $CNF['OBJECT_MENU_ACTIONS_VIEW_MEDIA_ALL'],
+            'object_transcoder' => $CNF['OBJECT_IMAGES_TRANSCODER_BIG'],
+            'entry_url' => BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink('page.php?i=' . $CNF['URI_VIEW_MEDIA'] . '&id=' . $iMediaId),
+            'entry_title' => $aMediaInfo['title'],
+            'entry_thumb' => $aMediaInfo['file_id']
+        ), $aParams));
+    }
+
+    /**
+     * Entry actions block
+     */
+    public function serviceMediaActions ($iContentId = 0)
+    {
+        $iContentId = $this->_getContent($iContentId, false);
+        if($iContentId === false)
+            return false;
+
+        $oMenu = BxTemplMenu::getObjectInstance($this->_oConfig->CNF['OBJECT_MENU_ACTIONS_VIEW_MEDIA']);
+        return $oMenu ? $oMenu->getCode() : false;
+    }
+
+    /**
+     * Display media social sharing buttons block.
+     * @param $iMediaId media ID, if it's omitted then it's taken from 'id' GET variable.
+     * @return HTML string with block content. On error false or empty string is returned.
+     */
+    public function serviceMediaSocialSharing ($iMediaId = 0)
+    {
+        if(!$iMediaId)
+            $iMediaId = bx_process_input(bx_get('id'), BX_DATA_INT);
+        if(!$iMediaId)
+            return false;
+
+        $aMediaInfo = $this->_oDb->getMediaInfoById($iMediaId);
+        if(!$aMediaInfo)
+            return false;
+
+        $CNF = &$this->_oConfig->CNF;
+
+        return $this->serviceEntitySocialSharing(array($iMediaId, $aMediaInfo), array(
+            'uri' => $CNF['URI_VIEW_MEDIA'],
+            'title' => $aMediaInfo['title'],
+            'id_thumb' => $aMediaInfo['file_id'],
+            'object_transcoder' => $CNF['OBJECT_IMAGES_TRANSCODER_BIG']
+        ));
+    }
+
+    /**
+     * Display media preview block.
+     * @param $iMediaId media ID, if it's omitted then it's taken from 'id' GET variable.
+     * @param $mixedContext current context to navigate to next and previous file, possible values: popular, public, author. If omitted then value from 'context' GTE variable is taken. Default context is 'album' - when nothin is specified.
+     * @param $aParams array of additional params. 
+     * @return HTML string with block content. On error false or empty string is returned.
+     */
+    public function serviceMediaView ($iMediaId = 0, $mixedContext = false, $aParams = array())
+    {
+        if(!$iMediaId)
+            $iMediaId = bx_process_input(bx_get('id'), BX_DATA_INT);
+        if(!$iMediaId)
+            return false;
+
+        if(!$mixedContext) {
+            $mixedContext = bx_process_input(bx_get('context'));
+            if(!in_array($mixedContext, $this->_aContexts)) // when no context specified, it is assumed that it is an album context
+                $mixedContext = bx_process_input($mixedContext, BX_DATA_INT); // numeric context is reserved for future use
+        }
+        $aParams['context'] = $mixedContext;
+
+        $iAutoplay = 0;
+        if(!isset($aParams['autoplay']) && ($iAutoplay = bx_get('autoplay')) !== false)
+            $aParams['autoplay'] = (int)$iAutoplay;
+
+        return $this->_oTemplate->entryMediaView ($iMediaId, $aParams);
+    }
+
+    public function checkAllowedSetThumb ($iContentId = 0)
+    {
+        return CHECK_ACTION_RESULT_NOT_ALLOWED;
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_albums Albums
+     * @subsection bx_albums-browse Browse
+     * @subsubsection bx_albums-browse_recent_media browse_recent_media
+     * 
+     * @code bx_srv('bx_albums', 'browse_recent_media', [...]); @endcode
+     * 
+     * Display block for browsing recently uploaded media files.
+     * @param $sUnitView unit view mode: gallery
+     * @param $bDisplayEmptyMsg display 'empty' message when nothing to browse, or return empty string.
+     * @param $bAjaxPaginate use AJAX or regular paginate.
+     * @return HTML string with block content. On error false or empty string is returned.
+     * 
+     * @see BxAlbumsModule::serviceBrowseRecentMedia
+     */
+    /** 
+     * @ref bx_albums-browse_recent_media "browse_recent_media"
+     */
+    public function serviceBrowseRecentMedia ($sUnitView = false, $bDisplayEmptyMsg = true, $bAjaxPaginate = true)
+    {
+        return $this->_serviceBrowse ('recent', array('unit_view' => $sUnitView), BX_DB_PADDING_DEF, $bDisplayEmptyMsg, $bAjaxPaginate, 'SearchResultMedia');
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_albums Albums
+     * @subsection bx_albums-browse Browse
+     * @subsubsection bx_albums-browse_featured_media browse_featured_media
+     * 
+     * @code bx_srv('bx_albums', 'browse_featured_media', [...]); @endcode
+     * 
+     * Display featured media. 
+     * @param $sUnitView unit view mode: gallery
+     * @param $bDisplayEmptyMsg display 'empty' message when nothing to browse, or return empty string.
+     * @param $bAjaxPaginate use AJAX or regular paginate.
+     * @return HTML string with block content. On error false or empty string is returned.
+     * 
+     * @see BxAlbumsModule::serviceBrowseFeaturedMedia
+     */
+    /** 
+     * @ref bx_albums-browse_featured_media "browse_featured_media"
+     */
+    public function serviceBrowseFeaturedMedia ($sUnitView = false, $bDisplayEmptyMsg = false, $bAjaxPaginate = true)
+    {
+        return $this->_serviceBrowse ('featured', array('unit_view' => $sUnitView), BX_DB_PADDING_DEF, $bDisplayEmptyMsg, $bAjaxPaginate, 'SearchResultMedia');
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_albums Albums
+     * @subsection bx_albums-browse Browse
+     * @subsubsection bx_albums-browse_popular_media browse_popular_media
+     * 
+     * @code bx_srv('bx_albums', 'browse_popular_media', [...]); @endcode
+     * 
+     * Display popular media.
+     * @param $sUnitView unit view mode: gallery
+     * @param $bDisplayEmptyMsg display 'empty' message when nothing to browse, or return empty string.
+     * @param $bAjaxPaginate use AJAX or regular paginate.
+     * @return HTML string with block content. On error false or empty string is returned.
+     * 
+     * @see BxAlbumsModule::serviceBrowsePopularMedia
+     */
+    /** 
+     * @ref bx_albums-browse_popular_media "browse_popular_media"
+     */
+    public function serviceBrowsePopularMedia ($sUnitView = false, $bDisplayEmptyMsg = true, $bAjaxPaginate = true)
+    {
+        return $this->_serviceBrowse ('popular', array('unit_view' => $sUnitView), BX_DB_PADDING_DEF, $bDisplayEmptyMsg, $bAjaxPaginate, 'SearchResultMedia');
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_albums Albums
+     * @subsection bx_albums-browse Browse
+     * @subsubsection bx_albums-browse_top_media browse_top_media
+     * 
+     * @code bx_srv('bx_albums', 'browse_top_media', [...]); @endcode
+     * 
+     * Display top media.
+     * @param $sUnitView unit view mode: gallery
+     * @param $bDisplayEmptyMsg display 'empty' message when nothing to browse, or return empty string.
+     * @param $bAjaxPaginate use AJAX or regular paginate.
+     * @return HTML string with block content. On error false or empty string is returned.
+     * 
+     * @see BxAlbumsModule::serviceBrowseTopMedia
+     */
+    /** 
+     * @ref bx_albums-browse_top_media "browse_top_media"
+     */
+    public function serviceBrowseTopMedia ($sUnitView = false, $bDisplayEmptyMsg = true, $bAjaxPaginate = true)
+    {
+        return $this->_serviceBrowse ('top', array('unit_view' => $sUnitView), BX_DB_PADDING_DEF, $bDisplayEmptyMsg, $bAjaxPaginate, 'SearchResultMedia');
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_albums Albums
+     * @subsection bx_albums-browse Browse
+     * @subsubsection bx_albums-browse_favorite_media browse_favorite_media
+     * 
+     * @code bx_srv('bx_albums', 'browse_favorite_media', [...]); @endcode
+     * 
+     * Display favorite media for particular profile. 
+     * @param $iProfileId profile ID, if omitted then 'profile_id' GET variable is used 
+     * @param $aParams additional params for browsing such as 'unit_view'
+     * 
+     * @see BxAlbumsModule::serviceBrowseFavoriteMedia
+     */
+    /** 
+     * @ref bx_albums-browse_favorite_media "browse_favorite_media"
+     */
+    public function serviceBrowseFavoriteMedia ($iProfileId = 0, $aParams = array())
+    {
+        $oProfile = null;
+        if((int)$iProfileId)
+            $oProfile = BxDolProfile::getInstance($iProfileId);
+        if(!$oProfile && bx_get('profile_id') !== false)
+            $oProfile = BxDolProfile:: getInstance(bx_process_input(bx_get('profile_id'), BX_DATA_INT));
+        if(!$oProfile)
+            $oProfile = BxDolProfile::getInstance();
+        if(!$oProfile)
+            return '';
+
+        $bEmptyMessage = false;
+        if(isset($aParams['empty_message'])) {
+            $bEmptyMessage = (bool)$aParams['empty_message'];
+            unset($aParams['empty_message']);
+        }
+
+        return $this->_serviceBrowse ('favorite', array_merge(array('user' => $oProfile->id()), $aParams), BX_DB_PADDING_DEF, $bEmptyMessage, true, 'SearchResultMedia');
+    }
+
+    public function serviceGetTimelineData()
+    {
+    	$sModule = $this->_aModule['name'];
+
+        $aResult = parent::serviceGetTimelineData();
+        $aResult['handlers'] = array_merge($aResult['handlers'], array(
+            array('group' => $sModule . '_object_media', 'type' => 'insert', 'alert_unit' => $sModule, 'alert_action' => 'medias_added', 'module_name' => $sModule, 'module_method' => 'get_timeline_media', 'module_class' => 'Module',  'groupable' => 0, 'group_by' => ''),
+        ));
+        $aResult['alerts'] = array_merge($aResult['alerts'], array(
+            array('unit' => $sModule, 'action' => 'medias_added')
+        ));
+
+        return $aResult;
+    }
+
+    public function serviceGetTimelineMedia($aEvent, $aBrowseParams = array())
+    {
+        if(empty($aEvent['content']))
+            return false;
+
+        $aEvent['content'] = unserialize($aEvent['content']);
+        if(empty($aEvent['content']['medias_added']) || !is_array($aEvent['content']['medias_added']))
+            return false;
+
+        $iContentId = (int)$aEvent['object_id'];
+        $aContentInfo = $this->_oDb->getContentInfoById($iContentId);
+        if(empty($aContentInfo) || !is_array($aContentInfo))
+            return false;
+
+        $CNF = &$this->_oConfig->CNF;
+        
+        //--- Views
+        $oViews = isset($CNF['OBJECT_VIEWS']) ? BxDolView::getObjectInstance($CNF['OBJECT_VIEWS'], $iContentId) : null;
+
+        $aViews = array();
+        if ($oViews && $oViews->isEnabled())
+            $aViews = array(
+                'system' => $CNF['OBJECT_VIEWS'],
+                'object_id' => $iContentId,
+                'count' => $aContentInfo['views']
+            );
+
+        //--- Votes
+        $oVotes = isset($CNF['OBJECT_VOTES']) ? BxDolVote::getObjectInstance($CNF['OBJECT_VOTES'], $iContentId) : null;
+
+        $aVotes = array();
+        if ($oVotes && $oVotes->isEnabled())
+            $aVotes = array(
+                'system' => $CNF['OBJECT_VOTES'],
+                'object_id' => $iContentId,
+                'count' => $aContentInfo['votes']
+            );
+
+        //--- Scores
+        $oScores = isset($CNF['OBJECT_SCORES']) ? BxDolScore::getObjectInstance($CNF['OBJECT_SCORES'], $iContentId) : null;
+
+        $aScores = array();
+        if ($oScores && $oScores->isEnabled())
+            $aScores = array(
+                'system' => $CNF['OBJECT_SCORES'],
+                'object_id' => $iContentId,
+                'score' => $aContentInfo['score']
+            );
+
+        //--- Reports
+        $oReports = isset($CNF['OBJECT_REPORTS']) ? BxDolReport::getObjectInstance($CNF['OBJECT_REPORTS'], $aEvent['object_id']) : null;
+
+        $aReports = array();
+        if ($oReports && $oReports->isEnabled())
+            $aReports = array(
+                'system' => $CNF['OBJECT_REPORTS'],
+                'object_id' => $iContentId,
+                'count' => $aContentInfo['reports']
+            );
+
+        //--- Comments
+        $oCmts = isset($CNF['OBJECT_COMMENTS']) ? BxDolCmts::getObjectInstance($CNF['OBJECT_COMMENTS'], $iContentId) : null;
+
+        $aComments = array();
+        if($oCmts && $oCmts->isEnabled())
+            $aComments = array(
+                'system' => $CNF['OBJECT_COMMENTS'],
+                'object_id' => $iContentId,
+                'count' => $aContentInfo['comments']
+            );
+
+        //--- Title & Description
+        $sTitle = isset($CNF['FIELD_TITLE']) && isset($aContentInfo[$CNF['FIELD_TITLE']]) ? $aContentInfo[$CNF['FIELD_TITLE']] : (isset($CNF['FIELD_TEXT']) && isset($aContentInfo[$CNF['FIELD_TEXT']]) ? strmaxtextlen($aContentInfo[$CNF['FIELD_TEXT']], 20, '...') : '');
+
+        return array(
+            '_cache' => true,
+            'owner_id' => $aEvent['owner_id'],
+            'object_owner_id' => $aContentInfo['author'],
+            'icon' => !empty($CNF['ICON']) ? $CNF['ICON'] : '',
+            'sample' => isset($CNF['T']['txt_sample_single_with_article']) ? $CNF['T']['txt_sample_single_with_article'] : $CNF['T']['txt_sample_single'],
+            'sample_wo_article' => $CNF['T']['txt_sample_single'],
+    	    'sample_action' => $CNF['T']['txt_sample_action_changed'],
+            'url' => BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink('page.php?i=' . $CNF['URI_VIEW_ENTRY'] . '&id=' . $iContentId),
+            'content' => $this->_getContentForTimelineMedia($aEvent, $aContentInfo, $aBrowseParams), //a string to display or array to parse default template before displaying.
+            'date' => $aContentInfo[$CNF['FIELD_ADDED']],
+            'views' => $aViews,
+            'votes' => $aVotes,
+            'scores' => $aScores,
+            'reports' => $aReports,
+            'comments' => $aComments,
+            'title' => $sTitle, //may be empty.
+            'description' => '' //may be empty.
+        );
+    }
+
+    public function serviceGetNotificationsData()
+    {
+        $sModule = $this->_aModule['name'];
+
+        $sEventPrivacy = $sModule . '_allow_view_event_to';
+        if(BxDolPrivacy::getObjectInstance($sEventPrivacy) === false)
+                $sEventPrivacy = '';
+
+        $aResult = parent::serviceGetNotificationsData();
+        $aResult['handlers'] = array_merge($aResult['handlers'], array(
+            array('group' => $sModule . '_object_media', 'type' => 'insert', 'alert_unit' => $sModule, 'alert_action' => 'medias_added', 'module_name' => $sModule, 'module_method' => 'get_notifications_media', 'module_class' => 'Module', 'module_event_privacy' => $sEventPrivacy),
+            array('group' => $sModule . '_object_media', 'type' => 'delete', 'alert_unit' => $sModule, 'alert_action' => 'media_deleted'),
+
+            array('group' => $sModule . '_comment_media', 'type' => 'insert', 'alert_unit' => $sModule . '_media', 'alert_action' => 'commentPost', 'module_name' => $sModule, 'module_method' => 'get_notifications_comment_media', 'module_class' => 'Module', 'module_event_privacy' => $sEventPrivacy),
+            array('group' => $sModule . '_comment_media', 'type' => 'delete', 'alert_unit' => $sModule . '_media', 'alert_action' => 'commentRemoved'),
+
+            array('group' => $sModule . '_vote_media', 'type' => 'insert', 'alert_unit' => $sModule . '_media', 'alert_action' => 'doVote', 'module_name' => $sModule, 'module_method' => 'get_notifications_vote_media', 'module_class' => 'Module', 'module_event_privacy' => $sEventPrivacy),
+            array('group' => $sModule . '_vote_media', 'type' => 'delete', 'alert_unit' => $sModule . '_media', 'alert_action' => 'undoVote'),
+            
+            array('group' => $sModule . '_score_up_media', 'type' => 'insert', 'alert_unit' => $sModule . '_media', 'alert_action' => 'doVoteUp', 'module_name' => $sModule, 'module_method' => 'get_notifications_score_up_media', 'module_class' => 'Module', 'module_event_privacy' => $sEventPrivacy),
+
+            array('group' => $sModule . '_score_down_media', 'type' => 'insert', 'alert_unit' => $sModule . '_media', 'alert_action' => 'doVoteDown', 'module_name' => $sModule, 'module_method' => 'get_notifications_score_down_media', 'module_class' => 'Module', 'module_event_privacy' => $sEventPrivacy),
+        ));
+
+        $aResult['settings'] = array_merge($aResult['settings'], array(
+            array('group' => 'content', 'unit' => $sModule, 'action' => 'medias_added', 'types' => array('follow_member', 'follow_context')),
+            array('group' => 'comment', 'unit' => $sModule . '_media', 'action' => 'commentPost', 'types' => array('personal', 'follow_member', 'follow_context')),
+            array('group' => 'vote', 'unit' => $sModule . '_media', 'action' => 'doVote', 'types' => array('personal', 'follow_member', 'follow_context')),
+            array('group' => 'score_up', 'unit' => $sModule . '_media', 'action' => 'doVoteUp', 'types' => array('personal', 'follow_member', 'follow_context')),
+            array('group' => 'score_down', 'unit' => $sModule . '_media', 'action' => 'doVoteDown', 'types' => array('personal', 'follow_member', 'follow_context'))
+        ));
+
+        $aResult['alerts'] = array_merge($aResult['alerts'], array(
+            array('unit' => $sModule, 'action' => 'medias_added'),
+            array('unit' => $sModule, 'action' => 'media_deleted'),
+
+            array('unit' => $sModule . '_media', 'action' => 'commentPost'),
+            array('unit' => $sModule . '_media', 'action' => 'commentRemoved'),
+
+            array('unit' => $sModule . '_media', 'action' => 'doVote'),
+            array('unit' => $sModule . '_media', 'action' => 'undoVote'),
+
+            array('unit' => $sModule . '_media', 'action' => 'doVoteUp'),
+            array('unit' => $sModule . '_media', 'action' => 'doVoteDown'),
+        ));
+
+        return $aResult; 
+    }
+
+    public function serviceGetNotificationsMedia($aEvent)
+    {
+    	$CNF = &$this->_oConfig->CNF;
+
+        $iContentId = (int)$aEvent['object_id'];
+        $aContentInfo = $this->_oDb->getContentInfoById($iContentId);
+        if(empty($aContentInfo) || !is_array($aContentInfo))
+            return array();
+
+    	$iMediaId = (int)$aEvent['subobject_id'];
+    	$aMediaInfo = $this->_oDb->getMediaInfoById($iMediaId);
+        if(empty($aMediaInfo) || !is_array($aMediaInfo))
+            return array();
+
+        $oPermalinks = BxDolPermalinks::getInstance();
+        $sEntryUrl = BX_DOL_URL_ROOT . $oPermalinks->permalink('page.php?i=' . $CNF['URI_VIEW_ENTRY'] . '&id=' . $iContentId);
+        $sSubentryUrl = BX_DOL_URL_ROOT . $oPermalinks->permalink('page.php?i=' . $CNF['URI_VIEW_MEDIA'] . '&id=' . $iMediaId);
+        $sEntryCaption = isset($aMediaInfo['title']) ? $aMediaInfo['title'] : _t('_bx_albums_media');
+
+        return array(
+            'entry_sample' => $CNF['T']['txt_sample_single'],
+            'entry_url' => $sEntryUrl,
+            'entry_caption' => $sEntryCaption,
+            'entry_author' => $aMediaInfo['author'],
+            'subentry_sample' => $CNF['T']['txt_media_single'],
+            'subentry_url' => $sSubentryUrl,
+            'lang_key' => '', //may be empty or not specified. In this case the default one from Notification module will be used.
+        );
+    }
+
+    public function serviceGetNotificationsCommentMedia($aEvent)
+    {
+    	$CNF = &$this->_oConfig->CNF;
+
+    	$iMediaId = (int)$aEvent['object_id'];
+    	$aMediaInfo = $this->_oDb->getMediaInfoById($iMediaId);
+        if(empty($aMediaInfo) || !is_array($aMediaInfo))
+            return array();
+
+        $oComment = BxDolCmts::getObjectInstance($CNF['OBJECT_COMMENTS_MEDIA'], $iMediaId);
+        if(!$oComment || !$oComment->isEnabled())
+            return array();
+
+        $sEntryUrl = BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink('page.php?i=' . $CNF['URI_VIEW_MEDIA'] . '&id=' . $aMediaInfo['id']);
+        $sEntryCaption = isset($aMediaInfo['title']) ? $aMediaInfo['title'] : _t('_bx_albums_media');
+
+        return array(
+            'entry_sample' => $CNF['T']['txt_media_single'],
+            'entry_url' => $sEntryUrl,
+            'entry_caption' => $sEntryCaption,
+            'entry_author' => $aMediaInfo['author'],
+            'subentry_sample' => $CNF['T']['txt_media_comment_single'],
+            'subentry_url' => $oComment->getViewUrl((int)$aEvent['subobject_id']),
+            'lang_key' => '', //may be empty or not specified. In this case the default one from Notification module will be used.
+        );
+    }
+
+    public function serviceGetNotificationsVoteMedia($aEvent)
+    {
+    	$CNF = &$this->_oConfig->CNF;
+
+    	$iMediaId = (int)$aEvent['object_id'];
+    	$aMediaInfo = $this->_oDb->getMediaInfoById($iMediaId);
+        if(empty($aMediaInfo) || !is_array($aMediaInfo))
+            return array();
+
+        $oVote = BxDolVote::getObjectInstance($CNF['OBJECT_VOTES_MEDIA'], $iMediaId);
+        if(!$oVote || !$oVote->isEnabled())
+            return array();
+
+        $sEntryUrl = BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink('page.php?i=' . $CNF['URI_VIEW_MEDIA'] . '&id=' . $aMediaInfo['id']);
+        $sEntryCaption = isset($aMediaInfo['title']) ? $aMediaInfo['title'] : _t('_bx_albums_media');
+
+        return array(
+            'entry_sample' => $CNF['T']['txt_media_single'],
+            'entry_url' => $sEntryUrl,
+            'entry_caption' => $sEntryCaption,
+            'entry_author' => $aMediaInfo['author'],
+            'subentry_sample' => $CNF['T']['txt_media_vote_single'],
+            'subentry_url' => '',
+            'lang_key' => '', //may be empty or not specified. In this case the default one from Notification module will be used.
+        );
+    }
+
+    public function serviceGetNotificationsScoreUpMedia($aEvent)
+    {
+    	return $this->_serviceGetNotificationsScoreMedia('up', $aEvent);
+    }
+
+    public function serviceGetNotificationsScoreDownMedia($aEvent)
+    {
+    	return $this->_serviceGetNotificationsScoreMedia('down', $aEvent);
+    }
+
+    protected function _serviceGetNotificationsScoreMedia($sType, $aEvent)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+    	$iMediaId = (int)$aEvent['object_id'];
+    	$aMediaInfo = $this->_oDb->getMediaInfoById($iMediaId);
+        if(empty($aMediaInfo) || !is_array($aMediaInfo))
+            return array();
+
+        $oVote = BxDolScore::getObjectInstance($CNF['OBJECT_SCORES_MEDIA'], $iMediaId);
+        if(!$oVote || !$oVote->isEnabled())
+            return array();
+
+        $sEntryUrl = BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink('page.php?i=' . $CNF['URI_VIEW_MEDIA'] . '&id=' . $aMediaInfo['id']);
+        $sEntryCaption = isset($aMediaInfo['title']) ? $aMediaInfo['title'] : _t('_bx_albums_media');
+
+        return array(
+            'entry_sample' => $CNF['T']['txt_media_single'],
+            'entry_url' => $sEntryUrl,
+            'entry_caption' => $sEntryCaption,
+            'entry_author' => $aMediaInfo['author'],
+            'subentry_sample' => $CNF['T']['txt_media_score_' . $sType . '_single'],
+            'subentry_url' => '',
+            'lang_key' => '', //may be empty or not specified. In this case the default one from Notification module will be used.
+        );
+    }
+
+    public function actionEditMedia($iMediaId)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $iMediaId = (int)$iMediaId;
+    	$aMediaInfo = $this->_oDb->getMediaInfoById($iMediaId);
+
+        $oForm = BxDolForm::getObjectInstance($CNF['OBJECT_FORM_MEDIA'], $CNF['OBJECT_FORM_MEDIA_DISPLAY_EDIT']);
+        $oForm->aFormAttrs['action'] = BX_DOL_URL_ROOT . $this->_oConfig->getBaseUri() . 'edit_media/' . $iMediaId;
+        $oForm->initChecker($aMediaInfo);
+
+        if($oForm->isSubmittedAndValid()) {
+            if($oForm->update($iMediaId) !== false)
+                $aRes = array('reload' => 1);
+            else
+                $aRes = array('msg' => _t('_bx_albums_txt_err_cannot_perform_action'));
+
+            return echoJson($aRes);
+        }
+
+        $sContent = BxTemplStudioFunctions::getInstance()->transBox('bx-albums-edit-media-popup', $this->_oTemplate->parseHtmlByName('media-edit.html', array(
+            'form_id' => $oForm->aFormAttrs['id'],
+            'form' => $oForm->getCode(true)
+        )));
+
+        echoJson(array('popup' => array('html' => $sContent, 'options' => array('closeOnOuterClick' => false))));
+    }
+
+    public function actionGetSiblingMedia($iMediaId, $mixedContext)
+    {
+        $aSiblings = false;
+        $sErrorMsg = false;
+        if (!($aMediaInfo = $this->_oDb->getMediaInfoById((int)$iMediaId))) 
+            $sErrorMsg = _t('_sys_txt_error_occured');
+
+        if (empty($sErrorMsg) && !($aContentInfo = $this->_oDb->getContentInfoById($aMediaInfo['content_id'])))
+            $sErrorMsg = _t('_sys_txt_error_occured');
+
+        if (empty($sErrorMsg) && (CHECK_ACTION_RESULT_ALLOWED !== ($sMsg = $this->checkAllowedView($aContentInfo))))
+            $sErrorMsg = $sMsg;
+
+        if (empty($sErrorMsg)) {
+            $aSiblings = array (
+                'next' => $this->_oTemplate->getNextPrevMedia($aMediaInfo, true, $mixedContext),
+                'prev' => $this->_oTemplate->getNextPrevMedia($aMediaInfo, false, $mixedContext),
+            );
+        }
+    
+        $a = $sErrorMsg ? array('error' => $sErrorMsg) : array('next' => $aSiblings['next'], 'prev' => $aSiblings['prev']);
+
+        $s = json_encode($a);
+
+        header('Content-type: text/html; charset=utf-8');
+        echo $s;
+    }
+
+    public function actionRssMedia ()
+    {
+        $aArgs = func_get_args();
+        $this->_rss($aArgs, 'SearchResultMedia');
+    }
+
+    public function getMediaDuration($aMediaInfo) 
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        if(empty($aMediaInfo) || !is_array($aMediaInfo))
+            return 0;
+
+        $sField = 'duration';
+        if(!empty($aMediaInfo[$sField]))
+            return (int)$aMediaInfo[$sField];
+
+        $iMedia = $aMediaInfo['id'];
+        $sMedia = BxDolTranscoderImage::getObjectInstance($CNF['OBJECT_VIDEOS_TRANSCODERS']['mp4'])->getFileUrl($iMedia);
+        if(empty($sMedia))
+            return 0;
+
+        $iDuration = (int)BxDolTranscoderVideo::getDuration($sMedia);
+        if(!empty($iDuration))
+            $this->_oDb->updateMedia(array($sField => $iDuration), array('id' => $iMedia));
+
+        return $iDuration;
+    }
+
+    protected function _buildRssParams($sMode, $aArgs)
+    {        
+        if ($aParams = parent::_buildRssParams($sMode, $aArgs))
+            return $aParams;
+
+        $sMode = bx_process_input($sMode);
+        switch ($sMode) {
+            case 'album':
+                $aParams = array('album_id' => isset($aArgs[0]) ? (int)$aArgs[0] : '');
+                break;
+        }
+
+        return $aParams;
+    }
+
+    protected function _getImagesForTimelinePostAttach($aEvent, $aContentInfo, $sUrl, $aBrowseParams = array())
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        if(empty($CNF['OBJECT_IMAGES_TRANSCODER_PREVIEW']) || empty($CNF['OBJECT_TRANSCODER_COVER']))
+            return array();
+
+        $aMediaList = $this->_oDb->getMediaListByContentId($aContentInfo[$CNF['FIELD_ID']]);
+        if(empty($aMediaList) || !is_array($aMediaList))
+            return array();
+
+        $oStorage = BxDolStorage::getObjectInstance($CNF['OBJECT_STORAGE']);
+        $oTcPoster = BxDolTranscoderVideo::getObjectInstance($CNF['OBJECT_VIDEOS_TRANSCODERS']['poster']);
+        $oTranscoder = BxDolTranscoderImage::getObjectInstance($CNF['OBJECT_IMAGES_TRANSCODER_PREVIEW']);
+        $oTranscoderCover = BxDolTranscoderImage::getObjectInstance($CNF['OBJECT_TRANSCODER_COVER']);
+        if(!$oTranscoder || !$oTranscoderCover)
+            return array();
+
+        $aOutput = array();
+        foreach ($aMediaList as $aMedia) {
+            $aFileInfo = $oStorage->getFile($aMedia['file_id']);
+
+            $bVideo = $oTcPoster && strncmp('video/', $aFileInfo['mime_type'], 6) === 0 && $oTcPoster->isMimeTypeSupported($aFileInfo['mime_type']);
+            if($bVideo)
+                continue;
+
+            $aOutput[$aMedia['id']] = array (
+                'id' => $aMedia['id'],
+                'url' => $this->_oTemplate->getViewMediaUrl($CNF, $aMedia['id']), 
+                'src' => $oTranscoder->getFileUrl($aMedia['file_id']),
+                'src_orig' => $oTranscoderCover->getFileUrl($aMedia['file_id'])
+            );
+        }
+
+        if(empty($aOutput))
+            return array();
+
+        $iSlice = 4;
+        $iTotal = count($aOutput);
+        return array(
+            'total' => $iTotal,
+            'items' => $iTotal > $iSlice ? array_slice($aOutput, 0, $iSlice) : $aOutput
+        );
+    }
+
+    protected function _getVideosForTimelinePostAttach($aEvent, $aContentInfo, $sUrl, $aBrowseParams = array())
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        if(empty($CNF['OBJECT_VIDEOS_TRANSCODERS']))
+            return array();
+
+        $aMediaList = $this->_oDb->getMediaListByContentId($aContentInfo[$CNF['FIELD_ID']]);
+        if(empty($aMediaList) || !is_array($aMediaList))
+            return array();
+
+        $oStorage = BxDolStorage::getObjectInstance($CNF['OBJECT_STORAGE']);
+        $oTcPoster = BxDolTranscoderVideo::getObjectInstance($CNF['OBJECT_VIDEOS_TRANSCODERS']['poster']);
+        $oTcMp4 = BxDolTranscoderVideo::getObjectInstance($CNF['OBJECT_VIDEOS_TRANSCODERS']['mp4']);
+        $oTcMp4Hd = BxDolTranscoderVideo::getObjectInstance($CNF['OBJECT_VIDEOS_TRANSCODERS']['mp4_hd']);
+        if(!$oTcPoster || !$oTcMp4 || !$oTcMp4Hd)
+            return array();
+
+        $aOutput = array();
+        foreach($aMediaList as $k => $aMedia) {
+            $aFileInfo = $oStorage->getFile($aMedia['file_id']);
+
+            $bVideo = $oTcPoster && strncmp('video/', $aFileInfo['mime_type'], 6) === 0 && $oTcPoster->isMimeTypeSupported($aFileInfo['mime_type']);
+            if(!$bVideo)
+                continue;
+
+            $sVideoUrl = $oStorage->getFileUrlById($aMedia['file_id']);
+            $aVideoFile = $oStorage->getFile($aMedia['file_id']);
+
+            $sVideoUrlHd = '';
+            if (!empty($aVideoFile['dimensions']) && $oTcMp4Hd->isProcessHD($aVideoFile['dimensions']))
+                $sVideoUrlHd = $oTcMp4Hd->getFileUrl($aMedia['file_id']);
+
+            $aOutput[$aMedia['id']] = array(
+                'id' => $aMedia['id'],
+                'src_poster' => $oTcPoster->getFileUrl($aMedia['file_id']),
+                'src_mp4' => $oTcMp4->getFileUrl($aMedia['file_id']),
+                'src_mp4_hd' => $sVideoUrlHd,
+                'duration' => $aFileInfo['duration'],
+            );
+        }
+
+        if(empty($aOutput))
+            return array();
+
+        $iSlice = 4;
+        $iTotal = count($aOutput);
+        return array(
+            'total' => $iTotal,
+            'items' => $iTotal > $iSlice ? array_slice($aOutput, 0, $iSlice) : $aOutput
+        );
+    }
+
+    protected function _getContentForTimelineMedia($aEvent, $aContentInfo, $aBrowseParams = array())
+    {
+    	$CNF = &$this->_oConfig->CNF;
+
+        $sUrl = BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink('page.php?i=' . $CNF['URI_VIEW_ENTRY'] . '&id=' . $aContentInfo[$CNF['FIELD_ID']]);
+        $sTitle = isset($CNF['FIELD_TITLE']) && isset($aContentInfo[$CNF['FIELD_TITLE']]) ? $aContentInfo[$CNF['FIELD_TITLE']] : (isset($CNF['FIELD_TEXT']) && isset($aContentInfo[$CNF['FIELD_TEXT']]) ? strmaxtextlen($aContentInfo[$CNF['FIELD_TEXT']], 20, '...') : '');
+
+        $oStorage = BxDolStorage::getObjectInstance($CNF['OBJECT_STORAGE']);
+        $oTcPoster = BxDolTranscoderVideo::getObjectInstance($CNF['OBJECT_VIDEOS_TRANSCODERS']['poster']);
+        $oTcMp4 = BxDolTranscoderVideo::getObjectInstance($CNF['OBJECT_VIDEOS_TRANSCODERS']['mp4']);
+        $oTcMp4Hd = BxDolTranscoderVideo::getObjectInstance($CNF['OBJECT_VIDEOS_TRANSCODERS']['mp4_hd']);
+        $oTranscoder = BxDolTranscoderImage::getObjectInstance($CNF['OBJECT_IMAGES_TRANSCODER_PREVIEW']);
+        $oTranscoderCover = BxDolTranscoderImage::getObjectInstance($CNF['OBJECT_TRANSCODER_COVER']);
+
+    	//--- Image(s) and Video(s)
+        $aImages = $aVideos = array();
+        foreach($aEvent['content']['medias_added'] as $iMediaId) {
+            $aMediaInfo = $this->_oDb->getMediaInfoById($iMediaId);
+            if(empty($aMediaInfo) || !is_array($aMediaInfo))
+                continue;
+
+            $aFileInfo = $oStorage->getFile($aMediaInfo['file_id']);
+            $bVideo = $oTcPoster && strncmp('video/', $aFileInfo['mime_type'], 6) === 0 && $oTcPoster->isMimeTypeSupported($aFileInfo['mime_type']);
+            if($bVideo)
+                $aVideos[$iMediaId] = array(
+                    'id' => $aMediaInfo['id'],
+                    'src_poster' => $oTcPoster->getFileUrl($aMediaInfo['file_id']),
+                    'src_mp4' => $oTcMp4->getFileUrl($aMediaInfo['file_id']),
+                    'src_mp4_hd' => $oTcMp4Hd->getFileUrl($aMediaInfo['file_id']),
+                    'duration' => $aFileInfo['duration'],
+                );
+            else
+                $aImages[$iMediaId] = array(
+                    'id' => $aMediaInfo['id'],
+                    'url' => $this->_oTemplate->getViewMediaUrl($CNF, $aMediaInfo['id']), 
+                    'src' => $oTranscoder->getFileUrl($aMediaInfo['file_id']),
+                    'src_orig' => $oTranscoderCover->getFileUrl($aMediaInfo['file_id'])
+                );
+        }
+
+    	return array(
+            'sample' => isset($CNF['T']['txt_sample_single_with_article']) ? $CNF['T']['txt_sample_single_with_article'] : $CNF['T']['txt_sample_single'],
+            'sample_wo_article' => $CNF['T']['txt_sample_single'],
+            'sample_action' => isset($CNF['T']['txt_sample_action_changed']),
+            'url' => $sUrl,
+            'title' => $sTitle,
+            'text' => '',
+            'images_attach' => $aImages,
+            'videos_attach' => $aVideos
+        );
+    }
+
+    protected function _getImagesForTimelineMedia($aEvent, $aMediaInfo, $sUrl, $aBrowseParams = array())
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $aImages = array();
+
+        
+
+        return $aImages;
+    }
+}
+
+/** @} */

+ 413 - 0
modules/boonex/albums/updates/12.0.3_12.0.4/source/classes/BxAlbumsTemplate.php

@@ -0,0 +1,413 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Albums Albums
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+/*
+ * Module representation.
+ */
+class BxAlbumsTemplate extends BxBaseModTextTemplate
+{
+    /**
+     * Constructor
+     */
+    function __construct(&$oConfig, &$oDb)
+    {
+        $this->MODULE = 'bx_albums';
+        parent::__construct($oConfig, $oDb);
+
+        $this->addCss(array(BX_DIRECTORY_PATH_PLUGINS_PUBLIC . 'flickity/|flickity.css'));
+        $this->addJs(array('flickity/flickity.pkgd.min.js', 'main.js'));
+    }
+
+    function unit ($aData, $isCheckPrivateContent = true, $sTemplateName = 'unit.html', $aParams = array())
+    {
+        if ('unit_media.html' == $sTemplateName || 'unit_media_live_search.html' == $sTemplateName || 'unit_showcase.html' == $sTemplateName)
+            return $this->unitMedia($aData, $isCheckPrivateContent, $sTemplateName, $aParams);
+
+        $oModule = BxDolModule::getInstance($this->MODULE);
+        $CNF = &$oModule->_oConfig->CNF;
+
+        if ($s = $this->checkPrivacy ($aData, $isCheckPrivateContent, $oModule))
+            return $s;
+
+        // get entry url        
+        $sUrl = BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink('page.php?i=' . $CNF['URI_VIEW_ENTRY'] . '&id=' . $aData[$CNF['FIELD_ID']]);
+
+        $oProfile = BxDolProfile::getInstance($aData[$CNF['FIELD_AUTHOR']]);
+        if (!$oProfile) 
+            $oProfile = BxDolProfileUndefined::getInstance();
+
+        $oStorage = BxDolStorage::getObjectInstance($CNF['OBJECT_STORAGE']);
+        $oTranscoder = BxDolTranscoderImage::getObjectInstance($CNF['OBJECT_TRANSCODER_BROWSE']);
+        $oTranscoderPoster = $CNF['OBJECT_VIDEOS_TRANSCODERS'] ? BxDolTranscoderImage::getObjectInstance($CNF['OBJECT_VIDEOS_TRANSCODERS']['poster']) : false;
+
+        $aBrowseUnits = array ();
+        $aMediaList = $oModule->_oDb->getMediaListByContentId($aData[$CNF['FIELD_ID']], getParam('bx_albums_album_browsing_unit'));
+        foreach ($aMediaList as $k => $a) {
+            $aFileInfo = $oStorage->getFile($a['file_id']);
+
+            $bVideo = $oTranscoderPoster && strncmp('video/', $aFileInfo['mime_type'], 6) === 0 && $oTranscoderPoster->isMimeTypeSupported($aFileInfo['mime_type']);            
+            $iVideoDuration = $bVideo ? $oModule->getMediaDuration($aFileInfo) : 0;
+
+            $aBrowseUnits[] = array (
+                'img_url' => $oTranscoder->getFileUrl($a['file_id']),
+                'url' => $this->getViewMediaUrl($CNF, $a['id']),
+                'title_attr' => bx_html_attribute($a['title']),
+                'bx_if:show_play' => array(
+                    'condition' => $bVideo,
+                    'content' => array()
+                ),
+                'bx_if:show_duration' => array(
+                    'condition' => $iVideoDuration > 0,
+                    'content' => array(
+                        'duration' => _t_format_duration($iVideoDuration)
+                    )
+                )
+
+            );
+        }
+
+        // get summary
+        $sLinkMore = ' <a title="' . bx_html_attribute(_t('_sys_read_more', $aData[$CNF['FIELD_TITLE']])) . '" href="' . $sUrl . '"><i class="sys-icon ellipsis-h"></i></a>';
+        $sSummary = strmaxtextlen($aData[$CNF['FIELD_TEXT']], (int)getParam($CNF['PARAM_CHARS_SUMMARY']), $sLinkMore);
+        $sSummaryPlain = BxTemplFunctions::getInstance()->getStringWithLimitedLength(strip_tags($sSummary), (int)getParam($CNF['PARAM_CHARS_SUMMARY_PLAIN']));
+
+        $sMeta = '';
+        if(!empty($CNF['OBJECT_MENU_SNIPPET_META'])) {
+            $oMenuMeta = BxDolMenu::getObjectInstance($CNF['OBJECT_MENU_SNIPPET_META'], $this);
+            if($oMenuMeta) {
+                $oMenuMeta->setContentId($aData[$CNF['FIELD_ID']]);
+                $aTmplVarsMeta = array(
+                    'meta' => $oMenuMeta->getCode()
+                );
+            }
+        }
+
+        // generate html
+        $aVars = array (
+            'id' => $aData[$CNF['FIELD_ID']],
+            'content_url' => $sUrl,
+            'title' => bx_process_output($aData[$CNF['FIELD_TITLE']]),
+        	'summary' => $sSummary,
+            'author' => $oProfile->getDisplayName(),
+            'author_url' => $oProfile->getUrl(),
+            'entry_posting_date' => bx_time_js($aData[$CNF['FIELD_ADDED']], BX_FORMAT_DATE),
+            'module_name' => _t($CNF['T']['txt_sample_single']),
+            'ts' => $aData[$CNF['FIELD_ADDED']],
+        	'bx_if:meta' => array(
+                'condition' => !empty($aTmplVarsMeta),
+                'content' => $aTmplVarsMeta
+            ),
+            'bx_repeat:browse' => $aBrowseUnits,
+            'bx_if:thumb' => array (
+                'condition' => $aBrowseUnits,
+                'content' => array (
+                    'title' => bx_process_output($aData[$CNF['FIELD_TITLE']]),
+                    'summary_attr' => '',
+                    'content_url' => $sUrl,
+                    'thumb_url' => $aBrowseUnits ? $aBrowseUnits[0]['img_url'] : '',
+                    'gallery_url' => '',
+                    'strecher' => '',
+                ),
+            ),
+            'bx_if:no_thumb' => array (
+                'condition' => !$aBrowseUnits,
+                'content' => array (
+                    'content_url' => $sUrl,
+                    'summary_plain' => '',
+                    'strecher' => '',
+                ),
+            ),
+
+        );
+
+        return $this->parseHtmlByName($sTemplateName, $aVars);
+    }
+
+    function unitMedia ($aData, $isCheckPrivateContent = true, $sTemplateName = 'unit.html', $aParams = array())
+    {
+        $oModule = BxDolModule::getInstance($this->MODULE);
+        $CNF = &$oModule->_oConfig->CNF;
+
+        if (!($aMediaInfo = $oModule->_oDb->getMediaInfoById($aData['id'])))
+            return '';
+
+        $oStorage = BxDolStorage::getObjectInstance($CNF['OBJECT_STORAGE']);
+        if (!($aFile = $oStorage->getFile($aMediaInfo['file_id'])))
+            return '';
+
+        $aVars = $this->mediaVars($aMediaInfo, $CNF['OBJECT_IMAGES_TRANSCODER_PREVIEW'], $CNF['OBJECT_VIDEOS_TRANSCODERS']['poster_preview'], $aParams);
+
+        $aVarsTmp = $aVars['bx_if:image']['condition'] ? $aVars['bx_if:image']['content'] : $aVars['bx_if:video']['content'];
+
+        $aVars = array_merge($aVars, array (
+            'class' => $this->_getUnitClass($aData, $sTemplateName),
+            'module_name' => _t($CNF['T']['txt_media_single']),
+            'content_url' => $aVars['url'],
+            'ts' => $aFile['added'],
+            'actions' => $oModule->serviceMediaAllActions(array($aData['id'], $aMediaInfo), array(
+                'object_menu' => $CNF['OBJECT_MENU_ACTIONS_VIEW_MEDIA_UNIT']
+            )),
+            'bx_if:thumb' => array (
+                'condition' => isset($aData['file_id']) && $aData['file_id'],
+                'content' => array (
+                    'title' => bx_process_output($aData['title']),
+                    'summary_attr' => '',
+                    'content_url' => $aVarsTmp['url'],
+                    'thumb_url' => $aVarsTmp['url_img'],
+                    'gallery_url' => '',
+                    'strecher' => '',
+                ),
+            ),
+            'bx_if:no_thumb' => array (
+                'condition' => false,
+                'content' => array (),
+            ),
+        ));
+
+        return $this->parseHtmlByName($sTemplateName, $aVars);
+    }
+
+    public function entryText ($aData, $sTemplateName = 'entry-text.html')
+    {
+        $CNF = &$this->getModule()->_oConfig->CNF;
+
+        $aVars = $this->getTmplVarsText($aData);
+        if(empty($aVars[$CNF['FIELD_TITLE']]) && empty($aVars[$CNF['FIELD_TEXT']]))
+            return false;
+
+        return $this->parseHtmlByName($sTemplateName, $aVars);
+    }
+
+    function entryMediaView ($iMediaId, $aParams = array())
+    {
+        $oModule = BxDolModule::getInstance($this->MODULE);
+        $CNF = &$oModule->_oConfig->CNF;
+
+        if (!($aMediaInfo = $oModule->_oDb->getMediaInfoById($iMediaId)))
+            return '';
+
+        if (!($aAlbumInfo = $oModule->_oDb->getContentInfoById($aMediaInfo['content_id'])))
+            return '';        
+
+        $sUrlAlbum = BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink('page.php?i=' . $CNF['URI_VIEW_ENTRY'] . '&id=' . $aAlbumInfo[$CNF['FIELD_ID']]);
+
+        $iProfileId = $aAlbumInfo[$CNF['FIELD_AUTHOR']];
+        $oProfile = BxDolProfile::getInstance($iProfileId);
+        if (!$oProfile) 
+            $oProfile = BxDolProfileUndefined::getInstance();
+
+        $aVars = array(
+            'album' => _t('_bx_albums_txt_media_album_link', $sUrlAlbum,  bx_process_output($aAlbumInfo[$CNF['FIELD_TITLE']]), $oProfile->getUrl(), $oProfile->getDisplayName()),
+            'js_code' => $this->getJsCode('main')
+        );
+
+        $mixedContext = isset($aParams['context']) ? $aParams['context'] : false;
+
+        $aNextPrev = array (
+            'next' => $this->getNextPrevMedia($aMediaInfo, true, $mixedContext),
+            'prev' => $this->getNextPrevMedia($aMediaInfo, false, $mixedContext),
+        );
+
+        foreach ($aNextPrev as $k => $a) {
+            $aVars['bx_if:' . $k] = array (
+                'condition' => $a,
+                'content' => $a,
+            );
+            $aVars['bx_if:' . $k . '-na'] = array (
+                'condition' => !$a,
+                'content' => array(),
+            );
+        }
+
+        $aVars = array_merge($aVars, $this->mediaVars($aMediaInfo, $CNF['OBJECT_IMAGES_TRANSCODER_BIG'], $CNF['OBJECT_VIDEOS_TRANSCODERS']['poster'], $aParams));
+
+        return $this->parseHtmlByName('media-view.html', $aVars);
+    }
+
+    protected function mediaVars ($aMediaInfo, $sImageTranscoder = false, $sVideoPosterTranscoder = false, $aParams = array())
+    {
+        $oModule = BxDolModule::getInstance($this->MODULE);
+        $CNF = &$oModule->_oConfig->CNF;
+
+        $oStorage = BxDolStorage::getObjectInstance($CNF['OBJECT_STORAGE']);
+        $oTranscoder = BxDolTranscoderImage::getObjectInstance($sImageTranscoder);
+        $aTranscodersVideo = false;
+
+        if ($CNF['OBJECT_VIDEOS_TRANSCODERS'])
+            $aTranscodersVideo = array (
+                'poster' => BxDolTranscoderImage::getObjectInstance($sVideoPosterTranscoder),
+                'mp4' => BxDolTranscoderImage::getObjectInstance($CNF['OBJECT_VIDEOS_TRANSCODERS']['mp4']),
+                'mp4_hd' => BxDolTranscoderImage::getObjectInstance($CNF['OBJECT_VIDEOS_TRANSCODERS']['mp4_hd']),
+            );
+        
+        $aFileInfo = $oStorage->getFile ($aMediaInfo['file_id']);
+        if (!$aFileInfo)
+            return '';
+
+        $isImage = 0 === strncmp('image/', $aFileInfo['mime_type'], 6) && $oTranscoder->isMimeTypeSupported($aFileInfo['mime_type']); // preview for images, transcoder object for preview must be defined
+        $isVideo = $aTranscodersVideo && (0 === strncmp('video/', $aFileInfo['mime_type'], 6)) && $aTranscodersVideo['poster']->isMimeTypeSupported($aFileInfo['mime_type']); // preview for videos, transcoder object for video must be defined
+
+        $sMediaTitle = $this->getMediaTitle($aMediaInfo);
+        $sMediaTitleAttr = bx_html_attribute($sMediaTitle);
+        $mixedContext = isset($aParams['context']) ? $aParams['context'] : '';
+        $sUrl = $this->getViewMediaUrl($CNF, $aMediaInfo['id'], $mixedContext);
+
+        $aTmplVarsImage = array();
+        if($isImage) {
+            $aSize = $aMediaInfo['data'] ? explode('x', $aMediaInfo['data']) : array(0, 0);
+
+            $aTmplVarsImage = array (
+                'title_attr' => $sMediaTitleAttr,
+                'title' => $sMediaTitle,
+                'url' => $sUrl,
+                'url_img' => $oTranscoder ? $oTranscoder->getFileUrl($aFileInfo['id']) : $oStorage->getFileUrlById($aFileInfo['id']),
+                'media_id' => $aMediaInfo['id'],
+                'w' => $aSize[0],
+                'h' => $aSize[1],
+                'context' => $mixedContext,
+            );
+        }
+
+        $aTmplVarsVideo = array();
+        if($isVideo) {
+            $mixedAttrs = false;
+            if(!empty($aParams['autoplay']))
+                $mixedAttrs = array('autoplay' => 'autoplay');
+
+            $iVideoDuration = $oModule->getMediaDuration($aFileInfo);
+            $sVideoDuration = _t_format_duration($iVideoDuration);
+
+            $sVideoUrl = $oStorage->getFileUrlById($aMediaInfo['file_id']);
+            $aVideoFile = $oStorage->getFile($aMediaInfo['file_id']);
+
+            $sVideoUrlHd = '';
+            if (!empty($aVideoFile['dimensions']) && $aTranscodersVideo['mp4_hd']->isProcessHD($aVideoFile['dimensions']))
+                $sVideoUrlHd = $aTranscodersVideo['mp4_hd']->getFileUrl($aMediaInfo['file_id']);
+
+            $aTmplVarsVideo = array (
+                'title_attr' => $sMediaTitleAttr,
+                'title' => $sMediaTitle,
+                'url' => bx_append_url_params($sUrl, array('autoplay' => 1)),
+                'url_img' => $isVideo ? $aTranscodersVideo['poster']->getFileUrl($aMediaInfo['file_id']) : '',
+                'video' => $isVideo && $aTranscodersVideo ? BxTemplFunctions::getInstance()->videoPlayer(
+                    $aTranscodersVideo['poster']->getFileUrl($aMediaInfo['file_id']), 
+                    $aTranscodersVideo['mp4']->getFileUrl($aMediaInfo['file_id']), 
+                    $sVideoUrlHd, $mixedAttrs, 'max-height:' . $CNF['OBJECT_VIDEO_TRANSCODER_HEIGHT']
+                ) : '',
+                'duration' => $sVideoDuration,
+                'bx_if:show_duration' => array(
+                    'condition' => $iVideoDuration > 0,
+                    'content' => array(
+                        'duration' => $sVideoDuration
+                    )
+                )
+            );
+        }
+
+        $aVars = array(
+            'bx_if:image' => array (
+                'condition' => $isImage,
+                'content' => $aTmplVarsImage,
+            ),
+            'bx_if:video' => array (
+                'condition' => $isVideo,
+                'content' => $aTmplVarsVideo,
+            ),
+            'title_attr' => $sMediaTitleAttr,
+            'title' => $sMediaTitle,
+            'url' => $sUrl,
+        );
+
+        return $aVars;
+    }
+
+    public function getViewMediaUrl($CNF, $iMediaId, $sContext = '')
+    {
+        return BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink('page.php?i=' . $CNF['URI_VIEW_MEDIA'] . '&id=' . $iMediaId . (!empty($sContext) ? '&context=' . $sContext : ''));
+    }
+
+    public function getNextPrevMedia($aMediaInfo, $isNext, $sContext, $aParamsSearchResult = array())
+    {
+        if (!$sContext) {
+            $sContext = 'album';
+            $aParamsSearchResult = array('album_id' => $aMediaInfo['content_id']);
+        }
+
+        $oModule = BxDolModule::getInstance($this->MODULE);
+        $CNF = &$oModule->_oConfig->CNF;
+
+        bx_import('SearchResultMedia', $oModule->_aModule);
+        $sClass = $oModule->_aModule['class_prefix'] . 'SearchResultMedia';
+        $o = new $sClass($sContext, $aParamsSearchResult);
+        if ($o->isError)
+            return false;
+
+        $o->setUnitParams(array('context' => $sContext));
+
+        $a = $o->getNextPrevItem($aMediaInfo, $isNext);
+    
+        if ($a) {
+
+            $aVars = $this->mediaVars($a, $CNF['OBJECT_IMAGES_TRANSCODER_BIG'], $CNF['OBJECT_VIDEOS_TRANSCODERS']['poster'], array('context' => $sContext));
+            $aMedia = $aVars['bx_if:image']['condition'] ? $aVars['bx_if:image']['content'] : $aVars['bx_if:video']['content'];
+
+            $a['url'] = $aMedia['url'];
+            $a['url_img'] = $aMedia['url_img'];
+            $a['title_attr'] = $aMedia['title_attr'];
+            $a['title_js_string'] = bx_js_string($aMedia['title']);
+            $a['w'] = $aVars['bx_if:image']['condition'] ? $aVars['bx_if:image']['content']['w'] : 0;
+            $a['h'] = $aVars['bx_if:image']['condition'] ? $aVars['bx_if:image']['content']['h'] : 0;
+            $a['html'] = $aVars['bx_if:video']['condition'] ? '<div class="pswp__video">' . $aVars['bx_if:video']['content']['video'] . '</div>': 0;
+        }
+
+        return $a;
+    }
+
+    function entryAttachments ($aData, $aParams = array())
+    {
+        $oModule = BxDolModule::getInstance($this->MODULE);
+        $CNF = &$oModule->_oConfig->CNF;
+
+        return $oModule->_serviceBrowse ('album', array('unit_view' => 'gallery', 'album_id' => $aData[$CNF['FIELD_ID']], 'author' => $aData[$CNF['FIELD_AUTHOR']]), BX_DB_PADDING_DEF, true, true, 'SearchResultMedia');
+    }
+
+    function mediaAuthor ($aMediaInfo, $iProfileId = false, $sFuncAuthorDesc = '', $sTemplateName = '') 
+    {
+        $oModule = BxDolModule::getInstance($this->MODULE);
+        $CNF = &$oModule->_oConfig->CNF;
+
+        if (!($aAlbumInfo = $oModule->_oDb->getContentInfoById($aMediaInfo['content_id'])))
+            return '';
+
+        return $this->entryAuthor ($aMediaInfo, $aAlbumInfo[$CNF['FIELD_AUTHOR']]);
+    }
+
+    function getMediaTitle ($aMediaInfo)
+    {
+        $oModule = BxDolModule::getInstance($this->MODULE);
+        $CNF = &$oModule->_oConfig->CNF;
+
+        if(!empty($aMediaInfo['title'])) {
+            $sText = bx_process_output($aMediaInfo['title']);
+            if(!empty($CNF['OBJECT_METATAGS_MEDIA'])) {
+                $oMetatags = BxDolMetatags::getObjectInstance($CNF['OBJECT_METATAGS_MEDIA']);
+                if($oMetatags && $oMetatags->keywordsIsEnabled())
+                    $sText = $oMetatags->keywordsParse($aMediaInfo['id'], $sText);
+            }
+        }
+        else 
+            $sText = _t('_bx_albums_txt_media_title_empty');
+
+        return $sText;
+    }
+}
+
+/** @} */

+ 143 - 0
modules/boonex/albums/updates/12.0.3_12.0.4/source/install/config.php

@@ -0,0 +1,143 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Albums Albums
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_albums',
+    'title' => 'Albums',
+    'note' => 'Photos & videos',
+    'version' => '12.0.4',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '12.1.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/albums/',
+    'home_uri' => 'albums',
+
+    'db_prefix' => 'bx_albums_',
+    'class_prefix' => 'BxAlbums',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Albums',
+
+    /**
+     * List of page triggers.
+     */
+    'page_triggers' => array (
+    	'trigger_page_profile_view_entry',
+    ),
+
+    /**
+     * Menu triggers.
+     */
+    'menu_triggers' => array(
+    	'trigger_profile_view_submenu',
+        'trigger_group_view_submenu',
+    ),
+
+	/**
+     * Storage objects to automatically delete files from upon module uninstallation.
+     * Note. Don't add storage objects used in transcoder objects.
+     */
+    'storages' => array(
+    	'bx_albums_files'
+    ),
+
+    /**
+     * Transcoders.
+     */
+    'transcoders' => array(
+        'bx_albums_preview',
+        'bx_albums_browse',
+        'bx_albums_big',
+        'bx_albums_video_poster_browse',
+        'bx_albums_video_poster_preview',
+        'bx_albums_video_poster_big',
+        'bx_albums_video_mp4',
+        'bx_albums_video_mp4_hd',
+    ),
+
+    /**
+     * Extended Search Forms.
+     */
+    'esearches' => array(
+        'bx_albums',
+    	'bx_albums_media',
+    	'bx_albums_cmts',
+        'bx_albums_media_cmts'
+    ),
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'uninstall' => array (
+    	'process_esearches' => 1,
+        'execute_sql' => 1,
+        'update_languages' => 1,
+    	'update_relations' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'enable' => array(
+        'execute_sql' => 1,
+    	'update_relations' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'enable_success' => array(
+        'process_menu_triggers' => 1,
+        'process_page_triggers' => 1,
+    	'process_esearches' => 1,
+    	'register_transcoders' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable' => array (
+        'execute_sql' => 1,
+    	'update_relations' => 1,
+    	'unregister_transcoders' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable_failed' => array (
+    	'register_transcoders' => 1,
+    	'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Dependencies Section
+     */
+    'dependencies' => array(),
+
+    /**
+     * Connections Section
+     */
+    'relations' => array(
+    	'bx_timeline',
+    	'bx_notifications'
+    ),
+
+);
+
+/** @} */

+ 538 - 0
modules/boonex/albums/updates/12.0.3_12.0.4/source/install/sql/install.sql

@@ -0,0 +1,538 @@
+
+SET @sStorageEngine = (SELECT `value` FROM `sys_options` WHERE `name` = 'sys_storage_default');
+
+-- TABLE: entries
+CREATE TABLE IF NOT EXISTS `bx_albums_albums` (
+  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+  `author` int(10) unsigned NOT NULL,
+  `added` int(11) NOT NULL,
+  `changed` int(11) NOT NULL,
+  `thumb` int(11) NOT NULL,
+  `title` varchar(255) NOT NULL,
+  `text` text NOT NULL,
+  `labels` text NOT NULL,
+  `location` text NOT NULL,
+  `views` int(11) NOT NULL default '0',
+  `rate` float NOT NULL default '0',
+  `votes` int(11) NOT NULL default '0',
+  `rrate` float NOT NULL default '0',
+  `rvotes` int(11) NOT NULL default '0',
+  `score` int(11) NOT NULL default '0',
+  `sc_up` int(11) NOT NULL default '0',
+  `sc_down` int(11) NOT NULL default '0',
+  `favorites` int(11) NOT NULL default '0',
+  `comments` int(11) NOT NULL default '0',
+  `reports` int(11) NOT NULL default '0',
+  `featured` int(11) NOT NULL default '0',
+  `allow_view_to` varchar(16) NOT NULL DEFAULT '3',
+  `status` enum('active','awaiting','failed','hidden') NOT NULL DEFAULT 'active',
+  `status_admin` enum('active','hidden') NOT NULL DEFAULT 'active',
+  PRIMARY KEY (`id`),
+  FULLTEXT KEY `title_text` (`title`,`text`)
+);
+
+-- TABLE: storages & transcoders
+CREATE TABLE IF NOT EXISTS `bx_albums_files` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `profile_id` int(10) unsigned NOT NULL,
+  `remote_id` varchar(128) NOT NULL,
+  `path` varchar(255) NOT NULL,
+  `file_name` varchar(255) NOT NULL,
+  `mime_type` varchar(128) NOT NULL,
+  `ext` varchar(32) NOT NULL,
+  `size` bigint(20) NOT NULL,
+  `dimensions` varchar(12) NOT NULL,
+  `duration` int(11) NOT NULL,
+  `added` int(11) NOT NULL,
+  `modified` int(11) NOT NULL,
+  `private` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `remote_id` (`remote_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_albums_photos_resized` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `profile_id` int(10) unsigned NOT NULL,
+  `remote_id` varchar(128) NOT NULL,
+  `path` varchar(255) NOT NULL,
+  `file_name` varchar(255) NOT NULL,
+  `mime_type` varchar(128) NOT NULL,
+  `ext` varchar(32) NOT NULL,
+  `size` bigint(20) NOT NULL,
+  `added` int(11) NOT NULL,
+  `modified` int(11) NOT NULL,
+  `private` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `remote_id` (`remote_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_albums_files2albums` (
+  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+  `content_id` int(10) unsigned NOT NULL,
+  `file_id` int(11) NOT NULL,
+  `author` int(10) unsigned NOT NULL,
+  `title` varchar(255) NOT NULL,
+  `views` int(11) NOT NULL,
+  `rate` float NOT NULL,
+  `votes` int(11) NOT NULL,
+  `score` int(11) NOT NULL default '0',
+  `sc_up` int(11) NOT NULL default '0',
+  `sc_down` int(11) NOT NULL default '0',
+  `favorites` int(11) NOT NULL default '0',
+  `comments` int(11) NOT NULL,
+  `featured` int(11) NOT NULL default '0',
+  `data` text NOT NULL,
+  `exif` text NOT NULL,
+  `order` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `file_content` (`file_id`,`content_id`),
+  KEY `content_id` (`content_id`),
+  FULLTEXT KEY `search_fields` (`title`)
+);
+
+-- TABLE: comments
+CREATE TABLE IF NOT EXISTS `bx_albums_cmts` (
+  `cmt_id` int(11) NOT NULL AUTO_INCREMENT,
+  `cmt_parent_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_vparent_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_object_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_author_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_level` int(11) NOT NULL DEFAULT '0',
+  `cmt_text` text NOT NULL,
+  `cmt_mood` tinyint(4) NOT NULL DEFAULT '0',
+  `cmt_rate` int(11) NOT NULL DEFAULT '0',
+  `cmt_rate_count` int(11) NOT NULL DEFAULT '0',
+  `cmt_time` int(11) unsigned NOT NULL DEFAULT '0',
+  `cmt_replies` int(11) NOT NULL DEFAULT '0',
+  `cmt_pinned` int(11) NOT NULL default '0',
+  PRIMARY KEY (`cmt_id`),
+  KEY `cmt_object_id` (`cmt_object_id`,`cmt_parent_id`),
+  FULLTEXT KEY `search_fields` (`cmt_text`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_albums_cmts_notes` (
+  `cmt_id` int(11) NOT NULL AUTO_INCREMENT,
+  `cmt_parent_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_vparent_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_object_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_author_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_level` int(11) NOT NULL DEFAULT '0',
+  `cmt_text` text NOT NULL,
+  `cmt_mood` tinyint(4) NOT NULL DEFAULT '0',
+  `cmt_rate` int(11) NOT NULL DEFAULT '0',
+  `cmt_rate_count` int(11) NOT NULL DEFAULT '0',
+  `cmt_time` int(11) unsigned NOT NULL DEFAULT '0',
+  `cmt_replies` int(11) NOT NULL DEFAULT '0',
+  `cmt_pinned` int(11) NOT NULL default '0',
+  PRIMARY KEY (`cmt_id`),
+  KEY `cmt_object_id` (`cmt_object_id`,`cmt_parent_id`),
+  FULLTEXT KEY `search_fields` (`cmt_text`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_albums_cmts_media` (
+  `cmt_id` int(11) NOT NULL AUTO_INCREMENT,
+  `cmt_parent_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_vparent_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_object_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_author_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_level` int(11) NOT NULL DEFAULT '0',
+  `cmt_text` text NOT NULL,
+  `cmt_mood` tinyint(4) NOT NULL DEFAULT '0',
+  `cmt_rate` int(11) NOT NULL DEFAULT '0',
+  `cmt_rate_count` int(11) NOT NULL DEFAULT '0',
+  `cmt_time` int(11) unsigned NOT NULL DEFAULT '0',
+  `cmt_replies` int(11) NOT NULL DEFAULT '0',
+  `cmt_pinned` int(11) NOT NULL default '0',
+  PRIMARY KEY (`cmt_id`),
+  KEY `cmt_object_id` (`cmt_object_id`,`cmt_parent_id`),
+  FULLTEXT KEY `search_fields` (`cmt_text`)
+);
+
+-- TABLE: votes
+CREATE TABLE IF NOT EXISTS `bx_albums_votes` (
+  `object_id` int(11) NOT NULL default '0',
+  `count` int(11) NOT NULL default '0',
+  `sum` int(11) NOT NULL default '0',
+  UNIQUE KEY `object_id` (`object_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_albums_votes_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `author_nip` int(11) unsigned NOT NULL default '0',
+  `value` tinyint(4) NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `vote` (`object_id`, `author_nip`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_albums_votes_media` (
+  `object_id` int(11) NOT NULL default '0',
+  `count` int(11) NOT NULL default '0',
+  `sum` int(11) NOT NULL default '0',
+  UNIQUE KEY `object_id` (`object_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_albums_votes_media_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `author_nip` int(11) unsigned NOT NULL default '0',
+  `value` tinyint(4) NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `vote` (`object_id`, `author_nip`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_albums_reactions` (
+  `object_id` int(11) NOT NULL default '0',
+  `reaction` varchar(32) NOT NULL default '',
+  `count` int(11) NOT NULL default '0',
+  `sum` int(11) NOT NULL default '0',
+  UNIQUE KEY `reaction` (`object_id`, `reaction`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_albums_reactions_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `author_nip` int(11) unsigned NOT NULL default '0',
+  `reaction` varchar(32) NOT NULL default '',
+  `value` tinyint(4) NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `vote` (`object_id`, `author_nip`)
+);
+
+-- TABLE: views
+CREATE TABLE `bx_albums_views_track` (
+  `object_id` int(11) NOT NULL default '0',
+  `viewer_id` int(11) NOT NULL default '0',
+  `viewer_nip` int(11) unsigned NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  KEY `id` (`object_id`,`viewer_id`,`viewer_nip`)
+);
+
+CREATE TABLE `bx_albums_views_media_track` (
+  `object_id` int(11) NOT NULL default '0',
+  `viewer_id` int(11) NOT NULL default '0',
+  `viewer_nip` int(11) unsigned NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  KEY `id` (`object_id`,`viewer_id`,`viewer_nip`)
+);
+
+-- TABLE: metas
+CREATE TABLE `bx_albums_meta_keywords` (
+  `object_id` int(10) unsigned NOT NULL,
+  `keyword` varchar(255) NOT NULL,
+  KEY `object_id` (`object_id`),
+  KEY `keyword` (`keyword`)
+);
+
+CREATE TABLE `bx_albums_meta_keywords_media` (
+  `object_id` int(10) unsigned NOT NULL,
+  `keyword` varchar(255) NOT NULL,
+  KEY `object_id` (`object_id`),
+  KEY `keyword` (`keyword`)
+);
+
+CREATE TABLE `bx_albums_meta_keywords_media_camera` (
+  `object_id` int(10) unsigned NOT NULL,
+  `keyword` varchar(255) NOT NULL,
+  KEY `object_id` (`object_id`),
+  KEY `keyword` (`keyword`)
+);
+
+CREATE TABLE `bx_albums_meta_locations` (
+  `object_id` int(10) unsigned NOT NULL,
+  `lat` double NOT NULL,
+  `lng` double NOT NULL,
+  `country` varchar(2) NOT NULL,
+  `state` varchar(255) NOT NULL,
+  `city` varchar(255) NOT NULL,
+  `zip` varchar(255) NOT NULL,
+  `street` varchar(255) NOT NULL,
+  `street_number` varchar(255) NOT NULL,
+  PRIMARY KEY (`object_id`),
+  KEY `country_state_city` (`country`,`state`(8),`city`(8))
+);
+
+CREATE TABLE `bx_albums_meta_mentions` (
+  `object_id` int(10) unsigned NOT NULL,
+  `profile_id` int(10) unsigned NOT NULL,
+  KEY `object_id` (`object_id`),
+  KEY `profile_id` (`profile_id`)
+);
+
+-- TABLE: reports
+CREATE TABLE IF NOT EXISTS `bx_albums_reports` (
+  `object_id` int(11) NOT NULL default '0',
+  `count` int(11) NOT NULL default '0',
+  UNIQUE KEY `object_id` (`object_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_albums_reports_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `author_nip` int(11) unsigned NOT NULL default '0',
+  `type` varchar(32) NOT NULL default '',
+  `text` text NOT NULL default '',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `report` (`object_id`, `author_nip`)
+);
+
+-- TABLE: favorites
+CREATE TABLE `bx_albums_favorites_track` (
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `list_id` int(11) NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  KEY `id` (`object_id`,`author_id`)
+);
+
+CREATE TABLE `bx_albums_favorites_media_track` (
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  KEY `id` (`object_id`,`author_id`)
+);
+
+CREATE TABLE `bx_albums_favorites_lists` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `title` varchar(255) NOT NULL,
+  `author_id` int(11) NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  `allow_view_favorite_list_to` varchar(16) NOT NULL DEFAULT '3',
+   PRIMARY KEY (`id`)
+);
+
+-- TABLE: scores
+CREATE TABLE IF NOT EXISTS `bx_albums_scores` (
+  `object_id` int(11) NOT NULL default '0',
+  `count_up` int(11) NOT NULL default '0',
+  `count_down` int(11) NOT NULL default '0',
+  UNIQUE KEY `object_id` (`object_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_albums_scores_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `author_nip` int(11) unsigned NOT NULL default '0',
+  `type` varchar(8) NOT NULL default '',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `vote` (`object_id`, `author_nip`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_albums_scores_media` (
+  `object_id` int(11) NOT NULL default '0',
+  `count_up` int(11) NOT NULL default '0',
+  `count_down` int(11) NOT NULL default '0',
+  UNIQUE KEY `object_id` (`object_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_albums_scores_media_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `author_nip` int(11) unsigned NOT NULL default '0',
+  `type` varchar(8) NOT NULL default '',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `vote` (`object_id`, `author_nip`)
+);
+
+
+-- STORAGES & TRANSCODERS
+INSERT INTO `sys_objects_storage` (`object`, `engine`, `params`, `token_life`, `cache_control`, `levels`, `table_files`, `ext_mode`, `ext_allow`, `ext_deny`, `quota_size`, `current_size`, `quota_number`, `current_number`, `max_file_size`, `ts`) VALUES
+('bx_albums_files', @sStorageEngine, 'a:1:{s:6:"fields";a:1:{s:10:"dimensions";s:17:"getFileDimensions";}}', 360, 2592000, 3, 'bx_albums_files', 'allow-deny', 'jpg,jpeg,jpe,gif,png,avi,flv,mpg,mpeg,wmv,mp4,m4v,mov,qt,divx,xvid,3gp,3g2,webm,mkv,ogv,ogg,rm,rmvb,asf,drc', '', 0, 0, 0, 0, 0, 0),
+('bx_albums_photos_resized', @sStorageEngine, '', 360, 2592000, 3, 'bx_albums_photos_resized', 'allow-deny', 'jpg,jpeg,jpe,gif,png,avi,flv,mpg,mpeg,wmv,mp4,m4v,mov,qt,divx,xvid,3gp,3g2,webm,mkv,ogv,ogg,rm,rmvb,asf,drc', '', 0, 0, 0, 0, 0, 0);
+
+INSERT INTO `sys_objects_transcoder` (`object`, `storage_object`, `source_type`, `source_params`, `private`, `atime_tracking`, `atime_pruning`, `ts`, `override_class_name`, `override_class_file`) VALUES
+('bx_albums_preview', 'bx_albums_photos_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_albums_files";}', 'no', '1', '2592000', '0', '', ''),
+('bx_albums_browse', 'bx_albums_photos_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_albums_files";}', 'no', '1', '2592000', '0', '', ''),
+('bx_albums_big', 'bx_albums_photos_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_albums_files";}', 'no', '1', '2592000', '0', '', ''),
+('bx_albums_video_poster_browse', 'bx_albums_photos_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_albums_files";}', 'no', 0, 0, 0, 'BxDolTranscoderVideo', ''),
+('bx_albums_video_poster_preview', 'bx_albums_photos_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_albums_files";}', 'no', 0, 0, 0, 'BxDolTranscoderVideo', ''),
+('bx_albums_video_poster_big', 'bx_albums_photos_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_albums_files";}', 'no', 0, 0, 0, 'BxDolTranscoderVideo', ''),
+('bx_albums_video_mp4', 'bx_albums_photos_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_albums_files";}', 'no', 0, 0, 0, 'BxDolTranscoderVideo', ''),
+('bx_albums_video_mp4_hd', 'bx_albums_photos_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_albums_files";}', 'no', 0, 0, 0, 'BxDolTranscoderVideo', ''),
+('bx_albums_proxy_preview', 'bx_albums_photos_resized', 'Proxy', 'a:4:{s:6:"object";s:15:"bx_albums_files";s:5:"image";s:17:"bx_albums_preview";s:12:"video_poster";s:30:"bx_albums_video_poster_preview";s:5:"video";a:4:{i:0;s:19:"bx_albums_video_mp4";i:1;s:22:"bx_albums_video_mp4_hd";i:2;s:29:"bx_albums_video_poster_browse";i:3;s:26:"bx_albums_video_poster_big";}}', 'no', 0, 0, 0, 'BxDolTranscoderProxy', ''),
+('bx_albums_proxy_browse', 'bx_albums_photos_resized', 'Proxy', 'a:4:{s:6:"object";s:15:"bx_albums_files";s:5:"image";s:16:"bx_albums_browse";s:12:"video_poster";s:29:"bx_albums_video_poster_browse";s:5:"video";a:2:{i:0;s:19:"bx_albums_video_mp4";i:1;s:22:"bx_albums_video_mp4_hd";}}', 'no', 0, 0, 0, 'BxDolTranscoderProxy', ''),
+('bx_albums_proxy_cover', 'bx_albums_photos_resized', 'Proxy', 'a:4:{s:6:"object";s:15:"bx_albums_files";s:5:"image";s:13:"bx_albums_big";s:12:"video_poster";s:26:"bx_albums_video_poster_big";s:5:"video";a:2:{i:0;s:19:"bx_albums_video_mp4";i:1;s:22:"bx_albums_video_mp4_hd";}}', 'no', 0, 0, 0, 'BxDolTranscoderProxy', '');
+
+INSERT INTO `sys_transcoder_filters` (`transcoder_object`, `filter`, `filter_params`, `order`) VALUES 
+('bx_albums_preview', 'Resize', 'a:3:{s:1:"w";s:3:"300";s:1:"h";s:3:"300";s:13:"square_resize";s:1:"1";}', '0'),
+('bx_albums_browse', 'Resize', 'a:1:{s:1:"h";s:3:"180";}', '0'),
+('bx_albums_big', 'Resize', 'a:2:{s:1:"w";s:4:"1280";s:1:"h";s:4:"1280";}', '0'),
+('bx_albums_video_poster_browse', 'Poster', 'a:2:{s:1:"h";s:3:"180";s:10:"force_type";s:3:"jpg";}', 0),
+('bx_albums_video_poster_preview', 'Poster', 'a:2:{s:1:"h";s:3:"480";s:10:"force_type";s:3:"jpg";}', 0),
+('bx_albums_video_poster_preview', 'Resize', 'a:3:{s:1:"w";s:3:"300";s:1:"h";s:3:"300";s:13:"square_resize";s:1:"1";}', 10),
+('bx_albums_video_poster_big', 'Poster', 'a:2:{s:1:"h";s:3:"480";s:10:"force_type";s:3:"jpg";}', 0),
+('bx_albums_video_mp4', 'Mp4', 'a:2:{s:1:"h";s:3:"480";s:10:"force_type";s:3:"mp4";}', 0),
+('bx_albums_video_mp4_hd', 'Mp4', 'a:3:{s:1:"h";s:3:"720";s:13:"video_bitrate";s:4:"1536";s:10:"force_type";s:3:"mp4";}', 0);
+
+
+-- FORMS
+INSERT INTO `sys_objects_form`(`object`, `module`, `title`, `action`, `form_attrs`, `table`, `key`, `uri`, `uri_title`, `submit_name`, `params`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_albums', 'bx_albums', '_bx_albums_form_entry', '', 'a:1:{s:7:\"enctype\";s:19:\"multipart/form-data\";}', 'bx_albums_albums', 'id', '', '', 'do_submit', '', 0, 1, 'BxAlbumsFormEntry', 'modules/boonex/albums/classes/BxAlbumsFormEntry.php');
+
+INSERT INTO `sys_form_displays`(`object`, `display_name`, `module`, `view_mode`, `title`) VALUES 
+('bx_albums', 'bx_albums_entry_add', 'bx_albums', 0, '_bx_albums_form_entry_display_add'),
+('bx_albums', 'bx_albums_entry_edit', 'bx_albums', 0, '_bx_albums_form_entry_display_edit'),
+('bx_albums', 'bx_albums_entry_add_images', 'bx_albums', 0, '_bx_albums_form_entry_display_add_images'),
+('bx_albums', 'bx_albums_entry_delete', 'bx_albums', 0, '_bx_albums_form_entry_display_delete'),
+('bx_albums', 'bx_albums_entry_view', 'bx_albums', 1, '_bx_albums_form_entry_display_view');
+
+INSERT INTO `sys_form_inputs`(`object`, `module`, `name`, `value`, `values`, `checked`, `type`, `caption_system`, `caption`, `info`, `required`, `collapsed`, `html`, `attrs`, `attrs_tr`, `attrs_wrapper`, `checker_func`, `checker_params`, `checker_error`, `db_pass`, `db_params`, `editable`, `deletable`) VALUES 
+('bx_albums', 'bx_albums', 'delete_confirm', 1, '', 0, 'checkbox', '_bx_albums_form_entry_input_sys_delete_confirm', '_bx_albums_form_entry_input_delete_confirm', '_bx_albums_form_entry_input_delete_confirm_info', 1, 0, 0, '', '', '', 'Avail', '', '_bx_albums_form_entry_input_delete_confirm_error', '', '', 1, 0),
+('bx_albums', 'bx_albums', 'do_submit', '_bx_albums_form_entry_input_do_submit', '', 0, 'submit', '_bx_albums_form_entry_input_sys_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_albums', 'bx_albums', 'title', '', '', 0, 'text', '_bx_albums_form_entry_input_sys_title', '_bx_albums_form_entry_input_title', '', 1, 0, 0, '', '', '', 'avail', '', '_bx_albums_form_entry_input_title_err', 'Xss', '', 1, 0),
+('bx_albums', 'bx_albums', 'text', '', '', 0, 'textarea', '_bx_albums_form_entry_input_sys_text', '_bx_albums_form_entry_input_text', '', 0, 0, 2, '', '', '', '', '', '', 'XssHtml', '', 1, 0),
+('bx_albums', 'bx_albums', 'pictures', 'a:2:{i:0;s:15:"bx_albums_html5";i:1;s:22:"bx_albums_record_video";}', 'a:4:{s:16:"bx_albums_simple";s:26:"_sys_uploader_simple_title";s:15:"bx_albums_html5";s:25:"_sys_uploader_html5_title";s:22:"bx_albums_record_video";s:32:"_sys_uploader_record_video_title";s:14:"bx_albums_crop";s:24:"_sys_uploader_crop_title";}', 0, 'files', '_bx_albums_form_entry_input_sys_pictures', '_bx_albums_form_entry_input_pictures', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_albums', 'bx_albums', 'allow_view_to', '', '', 0, 'custom', '_bx_albums_form_entry_input_sys_allow_view_to', '_bx_albums_form_entry_input_allow_view_to', '', 1, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_albums', 'bx_albums', 'location', '', '', 0, 'location', '_sys_form_input_sys_location', '_sys_form_input_location', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_albums', 'bx_albums', 'added', '', '', 0, 'datetime', '_bx_albums_form_entry_input_sys_date_added', '_bx_albums_form_entry_input_date_added', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_albums', 'bx_albums', 'changed', '', '', 0, 'datetime', '_bx_albums_form_entry_input_sys_date_changed', '_bx_albums_form_entry_input_date_changed', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_albums', 'bx_albums', 'labels', '', '', 0, 'custom', '_sys_form_input_sys_labels', '_sys_form_input_labels', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0);
+
+INSERT INTO `sys_form_display_inputs` (`display_name`, `input_name`, `visible_for_levels`, `active`, `order`) VALUES
+('bx_albums_entry_add', 'delete_confirm', 2147483647, 0, 1),
+('bx_albums_entry_add', 'title', 2147483647, 1, 2),
+('bx_albums_entry_add', 'text', 2147483647, 1, 3),
+('bx_albums_entry_add', 'pictures', 2147483647, 1, 4),
+('bx_albums_entry_add', 'allow_view_to', 2147483647, 1, 5),
+('bx_albums_entry_add', 'location', 2147483647, 1, 6),
+('bx_albums_entry_add', 'do_submit', 2147483647, 1, 7),
+
+('bx_albums_entry_edit', 'delete_confirm', 2147483647, 0, 1),
+('bx_albums_entry_edit', 'title', 2147483647, 1, 2),
+('bx_albums_entry_edit', 'text', 2147483647, 1, 3),
+('bx_albums_entry_edit', 'pictures', 2147483647, 1, 4),
+('bx_albums_entry_edit', 'allow_view_to', 2147483647, 1, 5),
+('bx_albums_entry_edit', 'location', 2147483647, 1, 6),
+('bx_albums_entry_edit', 'do_submit', 2147483647, 1, 7),
+
+('bx_albums_entry_add_images', 'delete_confirm', 2147483647, 0, 1),
+('bx_albums_entry_add_images', 'title', 2147483647, 0, 2),
+('bx_albums_entry_add_images', 'text', 2147483647, 0, 3),
+('bx_albums_entry_add_images', 'allow_view_to', 2147483647, 0, 4),
+('bx_albums_entry_add_images', 'location', 2147483647, 0, 5),
+('bx_albums_entry_add_images', 'pictures', 2147483647, 1, 6),
+('bx_albums_entry_add_images', 'do_submit', 2147483647, 1, 7),
+
+('bx_albums_entry_view', 'delete_confirm', 2147483647, 0, 0),
+('bx_albums_entry_view', 'allow_view_to', 2147483647, 0, 0),
+('bx_albums_entry_view', 'do_submit', 2147483647, 0, 0),
+('bx_albums_entry_view', 'text', 2147483647, 0, 0),
+('bx_albums_entry_view', 'title', 2147483647, 0, 0),
+('bx_albums_entry_view', 'pictures', 2147483647, 0, 0),
+('bx_albums_entry_view', 'added', 2147483647, 1, 1),
+('bx_albums_entry_view', 'changed', 2147483647, 1, 2),
+
+('bx_albums_entry_delete', 'delete_confirm', 2147483647, 1, 1),
+('bx_albums_entry_delete', 'do_submit', 2147483647, 1, 2),
+('bx_albums_entry_delete', 'allow_view_to', 2147483647, 0, 0),
+('bx_albums_entry_delete', 'pictures', 2147483647, 0, 0),
+('bx_albums_entry_delete', 'text', 2147483647, 0, 0),
+('bx_albums_entry_delete', 'title', 2147483647, 0, 0);
+
+INSERT INTO `sys_objects_form`(`object`, `module`, `title`, `action`, `form_attrs`, `table`, `key`, `uri`, `uri_title`, `submit_name`, `params`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_albums_media', 'bx_albums', '_bx_albums_form_media', '', 'a:1:{s:7:\"enctype\";s:19:\"multipart/form-data\";}', 'bx_albums_files2albums', 'id', '', '', 'do_submit', '', 0, 1, '', '');
+
+INSERT INTO `sys_form_displays`(`object`, `display_name`, `module`, `view_mode`, `title`) VALUES 
+('bx_albums_media', 'bx_albums_media_edit', 'bx_albums', 0, '_bx_albums_form_media_display_edit');
+
+INSERT INTO `sys_form_inputs`(`object`, `module`, `name`, `value`, `values`, `checked`, `type`, `caption_system`, `caption`, `info`, `required`, `collapsed`, `html`, `attrs`, `attrs_tr`, `attrs_wrapper`, `checker_func`, `checker_params`, `checker_error`, `db_pass`, `db_params`, `editable`, `deletable`) VALUES 
+('bx_albums_media', 'bx_albums', 'title', '', '', 0, 'text', '_bx_albums_form_media_input_sys_title', '_bx_albums_form_media_input_title', '', 0, 0, 0, '', '', '', '', '', '', 'Xss', '', 1, 0),
+('bx_albums_media', 'bx_albums', 'controls', '', 'do_submit,do_cancel', 0, 'input_set', '', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
+('bx_albums_media', 'bx_albums', 'do_submit', '_bx_albums_form_media_input_do_submit', '', 0, 'submit', '_bx_albums_form_media_input_sys_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_albums_media', 'bx_albums', 'do_cancel', '_bx_albums_form_media_input_do_cancel', '', 0, 'button', '_bx_albums_form_media_input_sys_do_cancel', '', '', 0, 0, 0, 'a:2:{s:7:"onclick";s:45:"$(''.bx-popup-applied:visible'').dolPopupHide()";s:5:"class";s:22:"bx-def-margin-sec-left";}', '', '', '', '', '', '', '', 0, 0);
+
+INSERT INTO `sys_form_display_inputs` (`display_name`, `input_name`, `visible_for_levels`, `active`, `order`) VALUES
+('bx_albums_media_edit', 'title', 2147483647, 1, 1),
+('bx_albums_media_edit', 'controls', 2147483647, 1, 2),
+('bx_albums_media_edit', 'do_submit', 2147483647, 1, 3),
+('bx_albums_media_edit', 'do_cancel', 2147483647, 1, 4);
+
+
+-- COMMENTS
+INSERT INTO `sys_objects_cmts` (`Name`, `Module`, `Table`, `CharsPostMin`, `CharsPostMax`, `CharsDisplayMax`, `Html`, `PerView`, `PerViewReplies`, `BrowseType`, `IsBrowseSwitch`, `PostFormPosition`, `NumberOfLevels`, `IsDisplaySwitch`, `IsRatable`, `ViewingThreshold`, `IsOn`, `RootStylePrefix`, `BaseUrl`, `ObjectVote`, `TriggerTable`, `TriggerFieldId`, `TriggerFieldAuthor`, `TriggerFieldTitle`, `TriggerFieldComments`, `ClassName`, `ClassFile`) VALUES
+('bx_albums', 'bx_albums', 'bx_albums_cmts', 1, 5000, 1000, 3, 5, 3, 'tail', 1, 'bottom', 1, 1, 1, -3, 1, 'cmt', 'page.php?i=view-album&id={object_id}', '', 'bx_albums_albums', 'id', 'author', 'title', 'comments', '', ''),
+('bx_albums_notes', 'bx_albums', 'bx_albums_cmts_notes', 1, 5000, 1000, 0, 5, 3, 'tail', 1, 'bottom', 1, 1, 1, -3, 1, 'cmt', 'page.php?i=view-post&id={object_id}', '', 'bx_albums_albums', 'id', 'author', 'title', 'comments', 'BxTemplCmtsNotes', ''),
+('bx_albums_media', 'bx_albums', 'bx_albums_cmts_media', 1, 5000, 1000, 3, 5, 3, 'tail', 1, 'bottom', 1, 1, 1, -3, 1, 'cmt', 'page.php?i=view-album-media&id={object_id}', '', 'bx_albums_files2albums', 'id', 'author', 'title', 'comments', 'BxAlbumsCmtsMedia', 'modules/boonex/albums/classes/BxAlbumsCmtsMedia.php');
+
+
+-- VOTES
+INSERT INTO `sys_objects_vote` (`Name`, `TableMain`, `TableTrack`, `PostTimeout`, `MinValue`, `MaxValue`, `IsUndo`, `IsOn`, `TriggerTable`, `TriggerFieldId`, `TriggerFieldAuthor`, `TriggerFieldRate`, `TriggerFieldRateCount`, `ClassName`, `ClassFile`) VALUES 
+('bx_albums', 'bx_albums_votes', 'bx_albums_votes_track', '604800', '1', '1', '0', '1', 'bx_albums_albums', 'id', 'author', 'rate', 'votes', '', ''),
+('bx_albums_media', 'bx_albums_votes_media', 'bx_albums_votes_media_track', '604800', '1', '1', '0', '1', 'bx_albums_files2albums', 'id', 'author', 'rate', 'votes', '', ''),
+
+('bx_albums_reactions', 'bx_albums_reactions', 'bx_albums_reactions_track', '604800', '1', '1', '1', '1', 'bx_albums_albums', 'id', 'author', 'rrate', 'rvotes', 'BxTemplVoteReactions', '');
+
+
+-- SCORES
+INSERT INTO `sys_objects_score` (`name`, `module`, `table_main`, `table_track`, `post_timeout`, `is_on`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_score`, `trigger_field_cup`, `trigger_field_cdown`, `class_name`, `class_file`) VALUES 
+('bx_albums', 'bx_albums', 'bx_albums_scores', 'bx_albums_scores_track', '604800', '0', 'bx_albums_albums', 'id', 'author', 'score', 'sc_up', 'sc_down', '', ''),
+('bx_albums_media', 'bx_albums', 'bx_albums_scores_media', 'bx_albums_scores_media_track', '604800', '0', 'bx_albums_files2albums', 'id', 'author', 'score', 'sc_up', 'sc_down', '', '');
+
+
+-- REPORTS
+INSERT INTO `sys_objects_report` (`name`, `module`, `table_main`, `table_track`, `is_on`, `base_url`, `object_comment`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_count`, `class_name`, `class_file`) VALUES 
+('bx_albums', 'bx_albums', 'bx_albums_reports', 'bx_albums_reports_track', '1', 'page.php?i=view-album&id={object_id}', 'bx_albums_notes', 'bx_albums_albums', 'id', 'author', 'reports', '', '');
+
+
+-- VIEWS
+INSERT INTO `sys_objects_view` (`name`, `table_track`, `period`, `is_on`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_count`, `class_name`, `class_file`) VALUES 
+('bx_albums', 'bx_albums_views_track', '86400', '1', 'bx_albums_albums', 'id', '', 'views', '', ''),
+('bx_albums_media', 'bx_albums_views_media_track', '86400', '1', 'bx_albums_files2albums', 'id', 'author', 'views', '', '');
+
+
+-- FAFORITES
+INSERT INTO `sys_objects_favorite` (`name`, `table_track`, `table_lists`, `is_on`, `is_undo`, `is_public`, `base_url`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_count`, `class_name`, `class_file`) VALUES 
+('bx_albums', 'bx_albums_favorites_track', 'bx_albums_favorites_lists', '1', '1', '1', 'page.php?i=view-album&id={object_id}', 'bx_albums_albums', 'id', 'author', 'favorites', '', ''),
+('bx_albums_media', 'bx_albums_favorites_media_track', '', '1', '1', '1', 'page.php?i=view-album-media&id={object_id}', 'bx_albums_files2albums', 'id', 'author', 'favorites', '', '');
+
+
+-- FEATURED
+INSERT INTO `sys_objects_feature` (`name`, `module`, `is_on`, `is_undo`, `base_url`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_flag`, `class_name`, `class_file`) VALUES 
+('bx_albums', 'bx_albums', '1', '1', 'page.php?i=view-album&id={object_id}', 'bx_albums_albums', 'id', 'author', 'featured', '', ''),
+('bx_albums_media', 'bx_albums', '1', '1', 'page.php?i=view-album-media&id={object_id}', 'bx_albums_files2albums', 'id', '', 'featured', '', '');
+
+
+-- CONTENT INFO
+INSERT INTO `sys_objects_content_info` (`name`, `title`, `alert_unit`, `alert_action_add`, `alert_action_update`, `alert_action_delete`, `class_name`, `class_file`) VALUES
+('bx_albums', '_bx_albums', 'bx_albums', 'added', 'edited', 'deleted', '', ''),
+('bx_albums_media', '_bx_albums_media', 'bx_albums', 'media_added', '', 'media_deleted', 'BxAlbumsContentInfoMedia', 'modules/boonex/albums/classes/BxAlbumsContentInfoMedia.php'),
+('bx_albums_cmts', '_bx_albums_cmts', 'bx_albums', 'commentPost', 'commentUpdated', 'commentRemoved', 'BxDolContentInfoCmts', ''),
+('bx_albums_media_cmts', '_bx_albums_media_cmts', 'bx_albums_media', 'commentPost', 'commentUpdated', 'commentRemoved', 'BxDolContentInfoCmts', '');
+
+INSERT INTO `sys_content_info_grids` (`object`, `grid_object`, `grid_field_id`, `condition`, `selection`) VALUES
+('bx_albums', 'bx_albums_administration', 'id', '', ''),
+('bx_albums', 'bx_albums_common', 'id', '', '');
+
+
+-- SEARCH EXTENDED
+INSERT INTO `sys_objects_search_extended` (`object`, `object_content_info`, `module`, `title`, `active`, `class_name`, `class_file`) VALUES
+('bx_albums', 'bx_albums', 'bx_albums', '_bx_albums_search_extended', 1, '', ''),
+('bx_albums_media', 'bx_albums_media', 'bx_albums', '_bx_albums_search_extended_media', 1, '', ''),
+('bx_albums_cmts', 'bx_albums_cmts', 'bx_albums', '_bx_albums_search_extended_cmts', 1, 'BxTemplSearchExtendedCmts', ''),
+('bx_albums_media_cmts', 'bx_albums_media_cmts', 'bx_albums', '_bx_albums_search_extended_media_cmts', 1, 'BxTemplSearchExtendedCmts', '');
+
+
+-- STUDIO: page & widget
+INSERT INTO `sys_std_pages`(`index`, `name`, `header`, `caption`, `icon`) VALUES
+(3, 'bx_albums', '_bx_albums', '_bx_albums', 'bx_albums@modules/boonex/albums/|std-icon.svg');
+SET @iPageId = LAST_INSERT_ID();
+
+SET @iParentPageId = (SELECT `id` FROM `sys_std_pages` WHERE `name` = 'home');
+SET @iParentPageOrder = (SELECT MAX(`order`) FROM `sys_std_pages_widgets` WHERE `page_id` = @iParentPageId);
+INSERT INTO `sys_std_widgets` (`page_id`, `module`, `type`, `url`, `click`, `icon`, `caption`, `cnt_notices`, `cnt_actions`) VALUES
+(@iPageId, 'bx_albums', 'content', '{url_studio}module.php?name=bx_albums', '', 'bx_albums@modules/boonex/albums/|std-icon.svg', '_bx_albums', '', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:11:"get_actions";s:6:"params";a:0:{}s:5:"class";s:18:"TemplStudioModules";}');
+INSERT INTO `sys_std_pages_widgets` (`page_id`, `widget_id`, `order`) VALUES
+(@iParentPageId, LAST_INSERT_ID(), IF(ISNULL(@iParentPageOrder), 1, @iParentPageOrder + 1));
+

+ 241 - 0
modules/boonex/albums/updates/12.0.3_12.0.4/source/template/css/main.css

@@ -0,0 +1,241 @@
+
+@import url(../../../../base/text/template/css/main.css);
+
+
+/* flexbox */
+.bx-albums-medias-wrapper {
+    display: -webkit-box;
+    display: -webkit-flex;
+    display: -ms-flexbox;
+    display: flex;
+
+    /* makes all items on a row equal height */
+    -webkit-box-align: stretch;
+    -webkit-align-items: stretch;
+    -ms-flex-align: stretch;
+    align-items: stretch;
+
+    /* wrap onto the next line rather than stretching or shrinking */
+    -webkit-flex-wrap: wrap;
+    -ms-flex-wrap: wrap;
+    flex-wrap: wrap;
+
+    /* tells flexbox to start items from the left */
+    -webkit-box-pack: start;
+    -ms-flex-pack: start;
+    plex-pack: start;
+    -webkit-justify-content: flex-start;
+    justify-content: flex-start;
+}
+
+.bx-albums-medias-wrapper .bx-albums-media-wrapper {
+    -webkit-box-flex: 0;
+
+    -webkit-flex: 0 0 100%;
+    -ms-flex: 0 0 100%;
+    flex: 0 0 100%;
+
+    max-width: 100%;
+}
+
+.bx-albums-media-wrapper .bx-albums-unit-size {
+    width: 100%;
+    height: auto;
+    min-height: 10rem;
+    object-fit: cover;
+}
+	
+/* MEDIA: phone2 */
+
+.bx-media-phone2 .bx-layout-column-half .bx-albums-medias-wrapper .bx-albums-media-wrapper,
+.bx-media-phone2 .bx-layout-column-thin .bx-albums-medias-wrapper .bx-albums-media-wrapper {
+    -webkit-flex: 0 0 49.8%;
+    -ms-flex: 0 0 49.8%;
+    flex: 0 0 49.8%;
+    
+    max-width: 49.8%;
+}
+
+/* MEDIA: tablet2 */
+
+.bx-media-tablet2 #sys_search_results .bx-albums-medias-wrapper .bx-albums-media-wrapper,
+.bx-media-tablet2 .bx-layout-column-wide .bx-albums-medias-wrapper .bx-albums-media-wrapper,
+.bx-media-tablet2 .bx-layout-column-fullwidth .bx-albums-medias-wrapper .bx-albums-media-wrapper {
+    -webkit-flex: 0 0 49.8%;
+    -ms-flex: 0 0 49.8%;
+    flex: 0 0 49.8%;
+    
+    max-width: 49.8%;
+}
+
+.bx-media-tablet2 .bx-layout-column-wide .bx-albums-medias-wrapper .bx-albums-media-wrapper .bx-albums-unit-size {
+    width: 100%;
+    height: auto;
+}
+
+.bx-media-tablet2 #sys_search_results .bx-albums-medias-wrapper .bx-albums-media-wrapper .bx-albums-unit-size,
+.bx-media-tablet2 .bx-layout-column-fullwidth .bx-albums-medias-wrapper .bx-albums-media-wrapper .bx-albums-unit-size {
+    height: 18.0rem;
+}
+
+/* MEDIA: desktop */
+
+.bx-media-desktop .bx-layout-column-wide .bx-albums-medias-wrapper .bx-albums-media-wrapper {
+    -webkit-flex: 0 0 49.8%;
+    -ms-flex: 0 0 49.8%;
+    flex: 0 0 49.8%;
+    
+    max-width: 49.8%;
+}
+
+.bx-media-desktop .bx-layout-column-wide .bx-albums-medias-wrapper .bx-albums-media-wrapper .bx-albums-unit-size {
+    width: 100%;
+    height: auto;
+}
+    
+.bx-media-desktop #sys_search_results .bx-albums-medias-wrapper .bx-albums-media-wrapper,
+.bx-media-desktop .bx-layout-column-fullwidth .bx-albums-medias-wrapper .bx-albums-media-wrapper {
+    -webkit-flex: 0 0 33.25%;
+    -ms-flex: 0 0 33.25%;
+    flex: 0 0 33.25%;
+    
+    max-width: 33.25%;
+}
+
+.bx-media-desktop #sys_search_results .bx-albums-medias-wrapper .bx-albums-media-wrapper .bx-albums-unit-size,
+.bx-media-desktop .bx-layout-column-half .bx-albums-medias-wrapper .bx-albums-media-wrapper .bx-albums-unit-size,
+.bx-media-desktop .bx-layout-column-fullwidth .bx-albums-medias-wrapper .bx-albums-media-wrapper .bx-albums-unit-size {
+    height: 18.0rem;
+}
+
+.bx-search-result-block .bx-base-text-unit-gallery-wrapper {
+	display: block;
+}
+.bx-search-result-block.bx-base-text-unit-gallery-wrapper .bx-base-text-unit.bx-base-text-unit-gallery {
+	display: inline-block;
+}
+
+.bx-albums-media-thumb {
+    position: relative;    
+}
+.bx-albums-media-thumb a {
+    position: relative;
+    display: -webkit-flex;
+    display: flex;
+    -webkit-justify-content: center;
+    justify-content: center;
+    -webkit-align-items: center;
+    align-items: center;
+}
+.bx-albums-media-play {
+    position: absolute;
+
+    width: 3rem;
+    height: 3rem;
+
+    background-color: rgba(255, 255, 255, 0.3);
+
+    text-align: center;
+    line-height: 3rem;
+    font-size: 1.5rem;
+}
+.bx-albums-media-duration {
+    position: absolute;
+    right: 10px;
+    bottom: 10px;
+
+    background-color: rgba(255, 255, 255, 0.9);
+}
+.bx-albums-media-caption {
+    white-space:nowrap;
+    overflow:hidden;
+    text-overflow:ellipsis;
+}
+.bx-albums-media-actions {
+    text-align: center;
+}
+.bx-base-text-unit-ext .bx-albums-unit-text-cont {
+    text-align: left;
+}
+.bx-albums-unit-images {
+    white-space:nowrap;
+    width:100%;
+    overflow: hidden;
+}
+
+.bx-albums-unit-image {
+    display: inline-block;
+    margin-right: 0.125rem;
+}
+
+.bx-albums-unit-image,
+.bx-albums-unit-image img {
+    height: 11.25rem;
+}
+.bx-albums-unit-image {
+    display: -webkit-inline-flex;
+    display: inline-flex;
+    -webkit-justify-content: center;
+    justify-content: center;
+    -webkit-align-items: center;
+    align-items: center;
+}
+.bx-base-text-unit-gallery .bx-albums-unit-images-cont {
+    padding: 0.125rem 0.125rem 0 0.125rem;
+}
+.bx-base-text-unit-gallery .bx-albums-unit-text-cont {
+    line-height: 150%;
+}
+.bx-base-text-unit-gallery .bx-albums-unit-text-cont .bx-base-text-unit-title {
+    text-align: left;
+}
+
+.bx-albums-media-file {
+    text-align: center;    
+}
+
+.bx-albums-media-file img,
+.bx-albums-media-file video {
+    max-width:100%;
+}
+
+.bx-albums-media-title {
+    position:relative;
+    padding-right:6rem;
+}
+
+.bx-albums-media-title h1, 
+.bx-albums-media-title h2, 
+.bx-albums-media-title p {
+    margin:0;
+}
+
+.bx-albums-media-controls {
+    position:absolute;
+    top:0;
+    right:0;
+}
+
+.pswp__caption .pswp__caption__center {
+    text-align: center;
+}
+
+.pswp__video {
+    position:absolute;
+    text-align: center;
+    top:0;
+    bottom:0;
+    left:0;
+    right:0;
+}
+
+.pswp__video:before {
+  content: "";
+  display: inline-block;
+  vertical-align: middle;
+  height: 100%;
+}
+
+.pswp__video video {
+    vertical-align: middle;    
+}

+ 51 - 0
modules/boonex/api/updates/12.0.1_12.0.2/install/config.php

@@ -0,0 +1,51 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'title' => 'API',
+    'version_from' => '12.0.1',
+    'version_to' => '12.0.2',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '12.1.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/api/updates/update_12.0.1_12.0.2/',
+    'home_uri' => 'api_update_1201_1202',
+
+    'module_dir' => 'boonex/api/',
+    'module_uri' => 'api',
+
+    'db_prefix' => 'bx_api_',
+    'class_prefix' => 'BxApi',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 0,
+        'update_files' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 0,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'API',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

+ 13 - 0
modules/boonex/api/updates/12.0.1_12.0.2/install/installer.php

@@ -0,0 +1,13 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+class BxApiUpdater extends BxDolStudioUpdater
+{
+    function __construct($aConfig)
+    {
+        parent::__construct($aConfig);
+    }
+}

+ 4 - 0
modules/boonex/api/updates/12.0.1_12.0.2/install/langs/en.xml

@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources name="en" flag="gb" title="English">
+    <string_add name="_bx_api_help"><![CDATA[This module doesn't provide any functionality to the end user, instead it provides additional API endpoints. It works oly with OAuth2 module.]]></string_add>
+</resources>

+ 29 - 0
modules/boonex/api/updates/12.0.1_12.0.2/source/classes/BxApiStudioPage.php

@@ -0,0 +1,29 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    API API to the UNA backend
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxApiStudioPage extends BxTemplStudioModule
+{
+    function __construct($sModule, $mixedPageName, $sPage = "")
+    {
+        parent::__construct($sModule, $mixedPageName, $sPage);
+
+        $this->aMenuItems = array(
+            'settings' => array('name' => 'settings', 'icon' => 'cogs', 'title' => '_adm_txt_show_help'),
+        );
+    }
+
+    function getSettings ()
+    {
+        return _t('_bx_api_help');
+    }
+}
+
+/** @} */

+ 70 - 0
modules/boonex/api/updates/12.0.1_12.0.2/source/install/config.php

@@ -0,0 +1,70 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    API API to the UNA backend
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_api',
+    'title' => 'API',
+    'note' => 'API for backend.',
+    'version' => '12.0.2',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '12.1.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/api/',
+    'home_uri' => 'api',
+
+    'db_prefix' => 'bx_api_',
+    'class_prefix' => 'BxApi',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'API',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_languages' => 1,
+    ),
+    'uninstall' => array (
+        'execute_sql' => 1,
+        'update_languages' => 1,
+    ),
+    'enable' => array(
+        'execute_sql' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable' => array(
+        'execute_sql' => 1,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Dependencies Section
+     */
+    'dependencies' => array(
+        'oauth2' => 'BoonEx OAuth2 Server Module'
+    ),
+);
+
+/** @} */

+ 16 - 0
modules/boonex/api/updates/12.0.1_12.0.2/source/install/langs/en.xml

@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources name="en" flag="gb" title="English">
+    <string name="_sys_module_api"><![CDATA[API]]></string>
+    <string name="_bx_api"><![CDATA[API]]></string>
+    <string name="_bx_api_help"><![CDATA[This module doesn't provide any functionality to the end user, instead it provides additional API endpoints. It works oly with OAuth2 module.]]></string>
+
+    <!-- EMAIL TEMPLATES -->
+    <string name="_bx_api_et_txt_name_password_reset"><![CDATA[New password message]]></string>
+    <string name="_bx_api_et_txt_subject_password_reset"><![CDATA[Your new password]]></string>
+    <string name="_bx_api_et_txt_body_password_reset"><![CDATA[{email_header}
+<p>Your new password is:</p>
+<p> </p>
+<p><b>{password}</b></p>
+<p> </p>
+{email_footer}]]></string>
+</resources>

+ 51 - 0
modules/boonex/channels/updates/12.0.0_12.0.1/install/config.php

@@ -0,0 +1,51 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'title' => 'Channels',
+    'version_from' => '12.0.0',
+    'version_to' => '12.0.1',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '12.1.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/channels/updates/update_12.0.0_12.0.1/',
+    'home_uri' => 'channels_update_1200_1201',
+
+    'module_dir' => 'boonex/channels/',
+    'module_uri' => 'channels',
+
+    'db_prefix' => 'bx_cnl_',
+    'class_prefix' => 'BxCnl',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_files' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Channels',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

+ 23 - 0
modules/boonex/channels/updates/12.0.0_12.0.1/install/installer.php

@@ -0,0 +1,23 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+class BxCnlUpdater extends BxDolStudioUpdater
+{
+    function __construct($aConfig)
+    {
+        parent::__construct($aConfig);
+    }
+
+    public function actionExecuteSql($sOperation)
+    {
+        if($sOperation == 'install') {
+            if(!$this->oDb->isFieldExists('bx_cnl_data', 'status'))
+                $this->oDb->query("ALTER TABLE `bx_cnl_data` ADD `status` enum('active','awaiting','hidden') NOT NULL DEFAULT 'active' AFTER `allow_view_to`");
+        }
+
+        return parent::actionExecuteSql($sOperation);
+    }
+}

+ 6 - 0
modules/boonex/channels/updates/12.0.0_12.0.1/install/langs/en.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources name="en" flag="gb" title="English">
+	<string_add name="_bx_channels_acl_action_create_channel_auto_info"><![CDATA[Automatically create new channel when new hashtag is mentioned by anyone with this level]]></string_add>
+	<string_add name="_bx_channels_page_block_title_system_profile_subscribed_me"><![CDATA[Followers]]></string_add>
+	<string_add name="_bx_channels_page_block_title_profile_subscribed_me"><![CDATA[Followers]]></string_add>
+</resources>

+ 7 - 0
modules/boonex/channels/updates/12.0.0_12.0.1/install/sql/enable.sql

@@ -0,0 +1,7 @@
+-- PAGES
+DELETE FROM `sys_pages_blocks` WHERE `object`='bx_channels_view_profile' AND `title`='_bx_channels_page_block_title_profile_subscribed_me';
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `text`, `text_updated`, `deletable`, `copyable`, `active`, `order`) VALUES
+('bx_channels_view_profile', 4, 'bx_channels', '', '_bx_channels_page_block_title_profile_subscribed_me', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:11:\"bx_channels\";s:6:\"method\";s:21:\"profile_subscribed_me\";}', '', 0, 0, 1, 1, 0);
+
+-- ACL
+UPDATE `sys_acl_actions` SET `Desc`='_bx_channels_acl_action_create_channel_auto_info' WHERE `Module`='bx_channels' AND `Name`='create channel auto';

+ 1 - 0
modules/boonex/channels/updates/12.0.0_12.0.1/install/sql/install.sql

@@ -0,0 +1 @@
+SET @sName = 'bx_channels';

+ 181 - 0
modules/boonex/channels/updates/12.0.0_12.0.1/source/classes/BxCnlConfig.php

@@ -0,0 +1,181 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defdroup    Channels Channels
+ * @indroup     UnaModules
+ *
+ * @{
+ */
+
+class BxCnlConfig extends BxBaseModGroupsConfig
+{
+    function __construct($aModule)
+    {
+        parent::__construct($aModule);
+
+        $this->_aMenuItems2MethodsActions = array_merge($this->_aMenuItems2MethodsActions, array(
+            'view-channel-profile' => 'checkAllowedView',
+            'edit-channel-profile' => 'checkAllowedEdit',
+            'edit-channel-cover' => 'checkAllowedChangeCover',
+            'invite-to-channel' => 'checkAllowedInvite',
+            'delete-channel-profile' => 'checkAllowedDelete',
+        ));
+
+        $this->CNF = array (
+
+            // module icon
+            'ICON' => 'hashtag col-red2',
+
+            // database tables
+            'TABLE_ENTRIES' => $aModule['db_prefix'] . 'data',
+            'TABLE_ENTRIES_FULLTEXT' => 'search_fields',
+            'TABLE_CONTENT' => $aModule['db_prefix'] . 'content',
+
+            // database fields
+            'FIELD_ID' => 'id',
+            'FIELD_AUTHOR' => 'author',
+            'FIELD_ADDED' => 'added',
+            'FIELD_CHANGED' => 'changed',
+            'FIELD_NAME' => 'channel_name',
+            'FIELD_TITLE' => 'channel_name',
+            'FIELD_PICTURE' => 'picture',
+            'FIELD_COVER' => 'cover',
+            'FIELD_ALLOW_VIEW_TO' => 'allow_view_to',
+            'FIELD_VIEWS' => 'views',
+            'FIELD_COMMENTS' => 'comments',
+            'FIELD_STATUS' => 'status',
+            'FIELDS_QUICK_SEARCH' => array('channel_name'),
+            'FIELDS_WITH_KEYWORDS' => 'auto', // can be 'auto', array of fields or comma separated string of field names, works only when OBJECT_METATAGS is specified
+
+            // page URIs
+            'URI_VIEW_ENTRY' => 'view-channel-profile',
+            'URI_EDIT_ENTRY' => 'edit-channel-profile',
+            'URI_EDIT_COVER' => 'edit-channel-cover',
+            'URI_JOINED_ENTRIES' => 'channels-author',
+
+            'URL_HOME' => 'page.php?i=channels-home',
+            'URL_MANAGE_COMMON' => 'page.php?i=channels-manage',
+            'URL_MANAGE_ADMINISTRATION' => 'page.php?i=channels-administration',
+
+            'PARAM_DEFAULT_AUTHOR' => 'bx_channels_default_author',
+            'PARAM_NUM_RSS' => 'bx_channels_num_rss',
+          
+            'PARAM_SEARCHABLE_FIELDS' => 'bx_channels_searchable_fields',
+            'PARAM_PER_PAGE_BROWSE_SHOWCASE' => 'bx_channels_per_page_browse_showcase',
+            'PARAM_PER_PAGE_BROWSE_RECOMMENDED' => 'bx_channels_per_page_browse_recommended',
+
+            // objects
+            'OBJECT_STORAGE' => 'bx_channels_pics',
+            'OBJECT_STORAGE_COVER' => 'bx_channels_pics',
+            'OBJECT_IMAGES_TRANSCODER_THUMB' => 'bx_channels_thumb',
+            'OBJECT_IMAGES_TRANSCODER_ICON' => 'bx_channels_icon',
+            'OBJECT_IMAGES_TRANSCODER_AVATAR' => 'bx_channels_avatar',
+            'OBJECT_IMAGES_TRANSCODER_AVATAR_BIG' => 'bx_channels_avatar_big',
+            'OBJECT_IMAGES_TRANSCODER_PICTURE' => 'bx_channels_picture',
+            'OBJECT_IMAGES_TRANSCODER_COVER' => 'bx_channels_cover',
+            'OBJECT_IMAGES_TRANSCODER_COVER_THUMB' => 'bx_channels_cover_thumb',
+            'OBJECT_IMAGES_TRANSCODER_GALLERY' => 'bx_channels_gallery',
+            'OBJECT_VIEWS' => 'bx_channels',
+            'OBJECT_VOTES' => 'bx_channels',
+            'OBJECT_SCORES' => 'bx_channels',
+            'OBJECT_FAVORITES' => 'bx_channels',
+            'OBJECT_FEATURED' => 'bx_channels',
+            'OBJECT_COMMENTS' => 'bx_channels',
+            'OBJECT_REPORTS' => 'bx_channels',
+            'OBJECT_METATAGS' => 'bx_channels',
+            'OBJECT_FORM_ENTRY' => 'bx_channel',
+            'OBJECT_FORM_ENTRY_DISPLAY_VIEW' => 'bx_channel_view',
+            'OBJECT_FORM_ENTRY_DISPLAY_VIEW_FULL' => 'bx_channel_view_full', // for "info" tab on view channel page
+            'OBJECT_FORM_ENTRY_DISPLAY_ADD' => 'bx_channel_add',
+            'OBJECT_FORM_ENTRY_DISPLAY_EDIT' => 'bx_channel_edit',
+            'OBJECT_FORM_ENTRY_DISPLAY_EDIT_COVER' => 'bx_channel_edit_cover',
+            'OBJECT_FORM_ENTRY_DISPLAY_DELETE' => 'bx_channel_delete',
+            'OBJECT_MENU_ACTIONS_VIEW_ENTRY' => 'bx_channels_view_actions', // actions menu on view entry page
+            'OBJECT_MENU_ACTIONS_VIEW_ENTRY_MORE' => 'bx_channels_view_actions_more', // actions menu on view entry page for "more" popup
+            'OBJECT_MENU_ACTIONS_VIEW_ENTRY_ALL' => 'bx_channels_view_actions_all', // all actions menu on view entry page
+            'OBJECT_MENU_ACTIONS_MY_ENTRIES' => 'bx_channels_my', // actions menu on profile entries page
+            'OBJECT_MENU_SUBMENU' => 'bx_channels_submenu', // main module submenu
+            'OBJECT_MENU_SUBMENU_VIEW_ENTRY' => '',  // view entry submenu
+            'OBJECT_MENU_SUBMENU_VIEW_ENTRY_COVER' => '',  // view entry submenu displayed in cover
+            'OBJECT_MENU_SUBMENU_VIEW_ENTRY_MAIN_SELECTION' => 'channels-home', // first item in view entry submenu from main module submenu
+            'OBJECT_MENU_SNIPPET_META' => 'bx_channels_snippet_meta', // menu for snippet meta info
+            'OBJECT_MENU_MANAGE_TOOLS' => 'bx_channels_menu_manage_tools', //manage menu in content administration tools
+            'OBJECT_PAGE_VIEW_ENTRY' => 'bx_channels_view_profile',
+            'OBJECT_PAGE_VIEW_ENTRY_CLOSED' => 'bx_channels_view_profile_closed',
+            'OBJECT_PRIVACY_VIEW' => 'bx_channels_allow_view_to',
+            'OBJECT_PRIVACY_VIEW_NOTIFICATION_EVENT' => 'bx_channels_allow_view_notification_to',
+            'OBJECT_GRID_ADMINISTRATION' => 'bx_channels_administration',
+            'OBJECT_UPLOADERS_COVER' => array('bx_channels_cover_crop'),
+            'OBJECT_UPLOADERS_PICTURE' => array('bx_channels_picture_crop'),
+      
+
+            'TRIGGER_MENU_PROFILE_VIEW_SUBMENU' => 'trigger_group_view_submenu',
+            'TRIGGER_MENU_PROFILE_SNIPPET_META' => 'trigger_group_snippet_meta',
+            'TRIGGER_MENU_PROFILE_VIEW_ACTIONS' => 'trigger_group_view_actions',
+            'TRIGGER_PAGE_VIEW_ENTRY' => 'trigger_page_group_view_entry',
+
+            // menu items which visibility depends on custom visibility checking
+            'MENU_ITEM_TO_METHOD' => array (
+                'bx_channels_view_actions' => $this->_aMenuItems2MethodsActions,
+                'bx_channels_view_actions_more' => $this->_aMenuItems2MethodsActions,
+            ),
+
+            // informer messages
+            'INFORMERS' => array (
+                'status' => array (
+                    'name' => 'bx-channels-status-not-active',
+                    'map' => array (
+                        BX_PROFILE_STATUS_PENDING => '_bx_channels_txt_account_pending',
+                        BX_PROFILE_STATUS_SUSPENDED => '_bx_channels_txt_account_suspended',
+                    ),
+                ),
+            ),
+
+            // some language keys
+            'T' => array (
+                'txt_sample_single' => '_bx_channels_txt_sample_single',
+                'txt_sample_single_with_article' => '_bx_channels_txt_sample_single_with_article',
+                'txt_sample_comment_single' => '_bx_channels_txt_sample_comment_single',
+                'txt_sample_vote_single' => '_bx_channels_txt_sample_vote_single',
+                'txt_sample_score_up_single' => '_bx_channels_txt_sample_score_up_single',
+                'txt_sample_score_down_single' => '_bx_channels_txt_sample_score_down_single',
+                'txt_private_group' => '_bx_channels_txt_private_channel',
+                'txt_ntfs_timeline_post_common' => '_bx_channels_txt_ntfs_timeline_post_common',
+                'form_field_author' => '_bx_channels_form_entry_input_author',
+                'menu_item_title_befriend_sent' => '_bx_channels_menu_item_title_befriend_sent',
+                'menu_item_title_unfriend_cancel_request' => '_bx_channels_menu_item_title_unfriend_cancel_request',
+                'menu_item_title_befriend_confirm' => '_bx_channels_menu_item_title_befriend_confirm',
+                'menu_item_title_unfriend_reject_request' => '_bx_channels_menu_item_title_unfriend_reject_request',
+                'menu_item_title_befriend' => '_bx_channels_menu_item_title_befriend',
+                'menu_item_title_unfriend' => '_bx_channels_menu_item_title_unfriend',
+                'grid_action_err_delete' => '_bx_channels_grid_action_err_delete',
+                'grid_txt_account_manager' => '_bx_channels_grid_txt_account_manager',
+                'filter_item_active' => '_bx_channels_grid_filter_item_title_adm_active',
+                'filter_item_pending' => '_bx_channels_grid_filter_item_title_adm_pending',
+                'filter_item_suspended' => '_bx_channels_grid_filter_item_title_adm_suspended',
+                'filter_item_select_one_filter1' => '_bx_channels_grid_filter_item_title_adm_select_one_filter1',
+                'menu_item_manage_my' => '_bx_channels_menu_item_title_manage_my',
+                'menu_item_manage_all' => '_bx_channels_menu_item_title_manage_all',
+                'txt_all_entries_by_author' => '_bx_channels_page_title_browse_by_author'
+            ),
+
+        );
+
+        $this->_aJsClasses = array(
+            'manage_tools' => 'BxCnlManageTools'
+        );
+
+        $this->_aJsObjects = array(
+            'manage_tools' => 'oBxCnlManageTools'
+        );
+
+        $this->_aGridObjects = array(
+            'administration' => $this->CNF['OBJECT_GRID_ADMINISTRATION']
+        );
+    }
+
+}
+
+/** @} */

+ 562 - 0
modules/boonex/channels/updates/12.0.0_12.0.1/source/classes/BxCnlModule.php

@@ -0,0 +1,562 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defdroup    Channels Channels
+ * @indroup     UnaModules
+ *
+ * @{
+ */
+
+/**
+ * Channels profiles module.
+ */
+
+class BxCnlModule extends BxBaseModGroupsModule
+{
+    function __construct(&$aModule)
+    {
+        parent::__construct($aModule);
+    }
+
+    public function _modGroupsCheckAllowedSubscribeAdd(&$aDataEntry, $isPerformAction = false)
+    {
+        return parent::_modProfileCheckAllowedSubscribeAdd($aDataEntry, $isPerformAction);
+    }
+
+    /**
+     * Process Hash Tag
+     * 
+     * @param string $sHashtag - hashtag to be processed.
+     * @param string $sModuleName - module name.
+     * @param integer $iContentId - ID of the content which has the hashtag.
+     * @param integer $iAuthorId - action's author id.
+     */
+    function processHashtag($sHashtag, $sModuleName, $iContentId, $iAuthorId)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        /*
+         * Note! For now metatag object name is used here as module name, because usually it's equal to module's name. This should be changed in Ticket #1596
+         * For now if module cannot be created then a channel for such tag shouldn't be created too.
+         */
+
+        $oModule = BxDolModule::getInstance($sModuleName);
+        if(empty($oModule) && $sModuleName != 'sys_cmts')
+            return;
+
+        /*
+         * Use content's author profile when Author ID wasn't provided. 
+         * Usually it happens when tags were processed with cron.
+         */
+        if(empty($iAuthorId))
+            $iAuthorId = BxDolService::call($sModuleName, 'get_author', array($iContentId));
+
+        $aCheck = checkActionModule($this->_iProfileId, 'create channel auto', $this->getName(), false);
+        $mixedCnlId = $this->_oDb->getChannelIdByName($sHashtag);
+        if(empty($mixedCnlId) && ($aCheck[CHECK_ACTION_RESULT] == CHECK_ACTION_RESULT_ALLOWED)) {
+            $iProfileId = (int)$this->_oDb->getParam($CNF['PARAM_DEFAULT_AUTHOR']);
+            if(empty($iProfileId)) {
+                $aOperators = BxDolAccountQuery::getInstance()->getOperators();
+                if(count($aOperators) > 0)
+                    $iProfileId = BxDolProfile::getInstanceByAccount(array_shift($aOperators))->id();
+            }
+
+            $aContent = $this->serviceEntityAdd($iProfileId, array($CNF['FIELD_NAME'] => $sHashtag));
+            checkActionModule($this->_iProfileId, 'create channel auto', $this->getName(), true);
+            if(isset($aContent['content']) && isset($aContent['content']['id']))
+                $mixedCnlId = $aContent['content']['id'];
+        }
+
+        if(empty($mixedCnlId) || (int)$this->_oDb->checkContentInChannel($iContentId, $mixedCnlId, $sModuleName, $iAuthorId) != 0)
+            return;
+
+        $iId = (int)$this->_oDb->addContentToChannel($iContentId, $mixedCnlId, $sModuleName, $iAuthorId);
+        if($iId == 0)
+            return;
+
+        $oCnlProfile = BxDolProfile::getInstanceByContentAndType($mixedCnlId, $this->_oConfig->getName());
+        if(!$oCnlProfile)
+            return;
+
+        $iCnlProfileId = $oCnlProfile->id();
+
+        bx_alert($this->_aModule['name'], 'hashtag_added', $iId, $iCnlProfileId, array(
+            'object_author_id' => $iAuthorId, 
+            'privacy_view' => -$iCnlProfileId,
+
+            'timeline_group' => array(
+                'by' => $sModuleName . '_' . $iAuthorId . '_' . $iContentId,
+                'field' => 'owner_id'
+            )
+        ));
+        $aParams = array(
+            'object_author_id' => $iAuthorId, 
+            'privacy_view' => -$iCnlProfileId, 
+            'subobject_id' => $iId,
+			'content_module' => $sModuleName,
+            'content_id' => $iContentId,
+            'content_author_id' => $iAuthorId
+        );
+        bx_alert('system', 'prepare_alert_params', 0, 0, array('unit'=> $this->_aModule['name'], 'action' => 'hashtag_added_notif', 'object_id' => $mixedCnlId, 'sender_id' => $iCnlProfileId, 'extras' => &$aParams));
+        bx_alert($this->_aModule['name'], 'hashtag_added_notif', $mixedCnlId, $iCnlProfileId, $aParams);
+    }
+    
+    function removeContentFromChannel($iContentId, $sModuleName)
+    {
+        $oDolProfileQuery = BxDolProfileQuery::getInstance();
+        
+        $aData = $this->_oDb->getDataByContent($iContentId, $sModuleName);
+        foreach ($aData as $aRow) {
+            $iProfileInfo = $oDolProfileQuery->getProfileByContentAndType($aRow['cnl_id'], $this->_aModule['name']);
+            if(is_array($iProfileInfo)){
+                bx_alert($this->_aModule['name'], 'hashtag_deleted', $aRow['id'], $iProfileInfo['id']);
+                bx_alert($this->_aModule['name'], 'hashtag_deleted_notif', $aRow['cnl_id'], $iProfileInfo['id'], array('subobject_id' => $aRow['id']));
+            }
+        }
+        
+        return $this->_oDb->removeContentFromChannel($iContentId, $sModuleName);
+    }
+
+    public function serviceGetSafeServices()
+    {
+        $a = parent::serviceGetSafeServices();
+        unset($a['GetCreatePostForm']);
+        unset($a['EntityCreate']);
+        return array_merge($a, array (
+            'EntityBreadcrumb' => '',
+            'EntityParent' => '',
+            'EntityChilds' => '',
+            'SearchResultByHashtag' => '',
+        ));
+    }
+
+    public function serviceGetWidgetNotices()
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $iResult = 0;
+        if(empty($this->_oDb->getParam($CNF['PARAM_DEFAULT_AUTHOR'])))
+            $iResult += 1;
+
+        return $iResult;
+    }
+
+    public function serviceGetOptionsDefaultAuthor()
+    {
+        $aResult = array(
+            array('key' => '', 'value' => _t('_Select_one'))
+        );
+
+        $aAccountsIds = BxDolAccountQuery::getInstance()->getOperators();
+        foreach($aAccountsIds as $iAccountId) {
+            $aProfilesIds = BxDolAccount::getInstance($iAccountId)->getProfilesIds();
+            foreach($aProfilesIds as $iProfileId)
+                $aResult[] = array(
+                    'key' => $iProfileId,
+                    'value' => BxDolProfile::getInstance($iProfileId)->getDisplayName()
+                );
+        }
+
+        return $aResult;
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_channels Channels
+     * @subsection bx_channels-page_blocks Page Blocks
+     * @subsubsection bx_channels-entity_breadcrumb entity_breadcrumb
+     * 
+     * @code bx_srv('bx_channels', 'entity_breadcrumb', [...]); @endcode
+     * 
+     * Display channel breadcrumb
+     * @param $iContentId channel content ID
+     * 
+     * @see BxCnlModule::serviceEntityBreadcrumb
+     */
+    /** 
+     * @ref bx_channels-entity_breadcrumb "entity_breadcrumb"
+     */
+    public function serviceEntityBreadcrumb($iContentId = 0)
+    {
+    	if(!$iContentId)
+            $iContentId = bx_process_input(bx_get('id'), BX_DATA_INT);
+        if(!$iContentId)
+            return false;
+
+        $aContentInfo = $this->_oDb->getContentInfoById($iContentId);
+        if(!$aContentInfo)
+            return false;
+
+        return $this->_oTemplate->entryBreadcrumb($aContentInfo);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_channels Channels
+     * @subsection bx_channels-page_blocks Page Blocks
+     * @subsubsection bx_channels-entity_parent entity_parent
+     * 
+     * @code bx_srv('bx_channels', 'entity_parent', [...]); @endcode
+     * 
+     * Display block with parent channel
+     * @param $iContentId channel content ID
+     * @param $sTemplateName html template name
+     * 
+     * @see BxCnlModule::serviceEntityParent
+     */
+    /** 
+     * @ref bx_channels-entity_parent "entity_parent"
+     */
+    public function serviceEntityParent($iContentId = 0, $sTemplateName = '')
+    {
+        return $this->_serviceTemplateFuncEx('entryParent', $iContentId, array('template_name' =>$sTemplateName));
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_channels Channels
+     * @subsection bx_channels-page_blocks Page Blocks
+     * @subsubsection bx_channels-entity_childs entity_childs
+     * 
+     * @code bx_srv('bx_channels', 'entity_childs', [...]); @endcode
+     * 
+     * Display block with child channels
+     * @param $iContentId channel content ID
+     * @param $sTemplateName html template name
+     * 
+     * @see BxCnlModule::serviceEntityChilds
+     */
+    /** 
+     * @ref bx_channels-entity_childs "entity_childs"
+     */
+    public function serviceEntityChilds($iContentId = 0, $sTemplateName = '')
+    {
+        return $this->_serviceTemplateFuncEx('entryChilds', $iContentId, array('template_name' =>$sTemplateName));
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_channels Channels
+     * @subsection bx_channels-page_blocks Page Blocks
+     * @subsubsection bx_channels-search_result_by_hashtag search_result_by_hashtag
+     * 
+     * @code bx_srv('bx_channels', 'search_result_by_hashtag', [...]); @endcode
+     * 
+     * Display search results by hashtag for particular channel
+     * @param $iContentId channel content ID
+     * 
+     * @see BxCnlModule::serviceSearchResultByHashtag
+     */
+    /** 
+     * @ref bx_channels-search_result_by_hashtag "search_result_by_hashtag"
+     */
+    public function serviceSearchResultByHashtag($iContentId = 0)
+    {
+        $CNF = &$this->_oConfig->CNF;
+        
+        $oSearch = new BxTemplSearch();
+        $oSearch->setLiveSearch(0);
+        $oSearch->setMetaType('keyword');
+        $aContentInfo = $this->_oDb->getContentInfoById(bx_get('id'));
+        $_GET['keyword'] = $aContentInfo[$CNF['FIELD_NAME']];
+        $sCode = $oSearch->response();
+        if (!$sCode)
+            $sCode = $oSearch->getEmptyResult();
+        
+        return $sCode;
+    }
+    
+    /**
+     * Data for Timeline module
+     */
+    public function serviceGetTimelineData()
+    {
+        $sModule = $this->_aModule['name'];
+
+        return array(
+            'handlers' => array(
+                array('group' => $sModule . '_hastag', 'type' => 'insert', 'alert_unit' => $sModule, 'alert_action' => 'hashtag_added', 'module_name' => $sModule, 'module_method' => 'get_timeline_post_hashtag', 'module_class' => 'Module',  'groupable' => 0, 'group_by' => ''),
+                array('group' => $sModule . '_hastag', 'type' => 'delete', 'alert_unit' => $sModule, 'alert_action' => 'hashtag_deleted')
+            ),
+            'alerts' => array(
+                array('unit' => $sModule, 'action' => 'hashtag_added'),
+                array('unit' => $sModule, 'action' => 'hashtag_deleted')
+            )
+        );
+    }
+
+    public function serviceGetTimelinePostAllowedView ($aEvent)
+    {
+        $sError = _t('_sys_txt_access_denied');
+
+        if(empty($aEvent) || !is_array($aEvent))
+            return $sError;
+
+        $aEventContent = $this->_oDb->getContentById($aEvent['object_id']);
+        
+        if ($aEventContent['module_name'] == 'sys_cmts')
+            return CHECK_ACTION_RESULT_ALLOWED;
+            
+        if(empty($aEventContent) || !is_array($aEventContent))
+            return $sError;
+
+        if(!BxDolRequest::serviceExists($aEventContent['module_name'], 'get_timeline_post_allowed_view'))
+            return $sError;
+
+        return BxDolService::call($aEventContent['module_name'], 'get_timeline_post_allowed_view', array(array('id' => $aEvent['id'], 'owner_id' => $aEventContent['author_id'], 'object_id' => $aEventContent['content_id'])));
+    }
+
+    public function serviceGetTimelinePostHashtag($aEvent, $aBrowseParams = array())
+    {
+        if(empty($aEvent) || !is_array($aEvent))
+            return false;
+        
+        $aEventContent = $this->_oDb->getContentById($aEvent['object_id']);
+        if(empty($aEventContent) || !is_array($aEventContent))
+            return false;
+       
+        $sModule = $aEventContent['module_name'];
+        $sClass = 'Module';
+        if($sModule == 'sys_cmts'){
+            $sClass = 'TemplCmtsServices';
+            $sModule = 'system';
+        }
+        
+        if(!BxDolRequest::serviceExists($sModule, 'get_timeline_post', $sClass))
+            return false;
+        /**
+         * Prepare fake event array (only mandatory parameters) to get
+         * necessary data (related to an 'original' event with hashtag/label) 
+         * from associated content module.
+         */
+        $iOwnerId = (int)$aEventContent['author_id'];
+        $iContentId = (int)$aEventContent['content_id'];
+        $mixedObjectPrivacyView = BX_DOL_PG_ALL;
+        if(BxDolRequest::serviceExists($sModule, 'get_privacy_view')) {
+            $mixedAllowViewTo = BxDolService::call($sModule, 'get_privacy_view', array($iContentId));
+            if($mixedAllowViewTo !== false)
+                $mixedObjectPrivacyView = $mixedAllowViewTo;
+            if(is_numeric($mixedAllowViewTo) && (int)$mixedAllowViewTo < 0)
+                $iOwnerId = abs($mixedAllowViewTo);
+        }
+        $aResult = BxDolService::call($sModule, 'get_timeline_post', array(array(
+            'owner_id' => $iOwnerId,
+            'object_id' => $iContentId,
+            'object_privacy_view' => $mixedObjectPrivacyView
+        ), $aBrowseParams), $sClass);
+
+        if(empty($aResult) || !is_array($aResult))
+            return $aResult;
+        
+        /**
+         * Note. The context shouldn't be changed therefore 
+         * use input event's context (owner_id) in returned results.
+         */
+        return array_merge($aResult, array(
+            'owner_id' => $aEvent['owner_id']
+        ));
+    }
+    
+    /**
+     * Data for Notifications module
+     */
+    public function serviceGetNotificationsData()
+    {      
+        $a = parent::serviceGetNotificationsData();
+
+        $sModule = $this->_aModule['name'];
+
+        $a['handlers'][] = array('group' => $sModule . '_hastag_notif', 'type' => 'insert', 'alert_unit' => $sModule, 'alert_action' => 'hashtag_added_notif', 'module_name' => $sModule, 'module_method' => 'get_notifications_post_hashtag', 'module_class' => 'Module');
+        $a['handlers'][] = array('group' => $sModule . '_hastag_notif', 'type' => 'delete', 'alert_unit' => $sModule, 'alert_action' => 'hashtag_deleted_notif');
+
+        $a['settings'][] = array('group' => 'hastag', 'unit' => $sModule, 'action' => 'hashtag_added_notif', 'types' => array('follow_context'));
+
+        $a['alerts'][] = array('unit' => $sModule, 'action' => 'hashtag_added_notif');
+        $a['alerts'][] = array('unit' => $sModule, 'action' => 'hashtag_deleted_notif');
+
+        return $a;
+    }
+
+    public function serviceGetNotificationsPostHashtag($aEvent)
+    {
+        if(empty($aEvent) || !is_array($aEvent))
+            return '';
+
+        $aContentEvent = $this->_oDb->getContentById($aEvent['subobject_id']);
+        if(empty($aContentEvent) || !is_array($aContentEvent))
+            return '';
+
+        $oModule = BxDolModule::getInstance($aContentEvent['module_name']);
+        if ($oModule) {
+            if (isset($oModule->_oConfig->CNF['OBJECT_PRIVACY_VIEW'])){
+                $oPrivacy = BxDolPrivacy::getObjectInstance($oModule->_oConfig->CNF['OBJECT_PRIVACY_VIEW']);
+                if (!$oPrivacy->check($aContentEvent['content_id']))
+                    return '';
+            }
+
+            $aRv = $oModule->serviceGetNotificationsPost(array(
+                'object_id' => $aContentEvent['content_id']
+            ));
+
+            $aRv['lang_key'] = '_bx_channels_ntfs_txt_subobject_added';
+            if(method_exists($oModule, 'serviceActAsProfile') && $oModule->serviceActAsProfile())
+                $aRv['lang_key'] = '_bx_channels_ntfs_txt_subobject_added_profile';
+
+            $aRv['entry_url'] = $this->serviceGetLink($aContentEvent['cnl_id']);
+            return $aRv;
+        }
+
+        return '';
+    }
+    
+    public function serviceBrowseByLevel ($iLevelId = 0, $bDisplayEmptyMsg = false)
+    {
+        return $this->_serviceBrowse ('level', array('level' => $iLevelId), BX_DB_PADDING_DEF, $bDisplayEmptyMsg);
+    }
+    
+    public function serviceBrowseAuthor($iProfileId = 0, $aParams = array())
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        if(empty($iProfileId))
+            $iProfileId = bx_get_logged_profile_id();
+
+        $sResult = isset($aParams['empty_message']) && (bool)$aParams['empty_message'] === true ? MsgBox(_t('_Empty')) : '';
+
+        $oConnection = BxDolConnection::getObjectInstance('sys_profiles_subscriptions');
+        $aProfile = $oConnection->getConnectedContent($iProfileId);
+        $aVars = array();
+        foreach ($aProfile as $iProfileId) {
+            $oProfile = BxDolProfile::getInstance($iProfileId);
+            if (!$oProfile || $oProfile->getModule() != $this->getName())
+                continue;
+
+            $iContentId = $oProfile->getContentId();
+            $aContentInfo = $this->_oDb->getContentInfoById($iContentId);
+            if (isset($aContentInfo[$CNF['FIELD_NAME']]))
+                array_push($aVars, array('title' => $aContentInfo[$CNF['FIELD_NAME']], 'link' => BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink('page.php?i=' . $CNF['URI_VIEW_ENTRY'] . '&id=' . $iContentId)));
+        }
+
+        if(empty($aVars) || !is_array($aVars))
+            return $sResult;
+
+        return $this->_oTemplate->parseHtmlByName('my_channels.html', array(
+            'bx_if:show_list' => array(
+                'condition' => count($aVars) > 0,
+                'content' => array(
+                    'bx_repeat:items' => $aVars
+                )
+            )
+        ));
+    }
+    
+    public function serviceDeleteProfileFromFansAndAdmins ($iProfileId)
+    {
+        return true;
+    }
+
+    public function serviceGetFollowingChannelsNames($iProfileId)
+    {
+        if (!($oConn = BxDolConnection::getObjectInstance('sys_profiles_subscriptions')))
+            return array();
+
+        if (!($aIds = $oConn->getConnectedContent($iProfileId)))
+            return array();
+
+        $a = array();
+        foreach ($aIds as $iId) {
+            if (!($oProfile = BxDolProfile::getInstance($iId)))
+                continue;
+            if ($oProfile->getModule() != $this->getName())
+                continue;
+            $a[] = $oProfile->getDisplayName();
+        }
+        return $a;
+    }
+
+    public function checkAllowedCompose(&$aDataEntry, $isPerformAction = false)
+    {
+        return _t('_sys_txt_access_denied');
+    }
+
+    public function checkAllowedContact($aDataEntry, $isPerformAction = false)
+    {
+        return _t('_sys_txt_access_denied');
+    }
+
+    public function followLabels($sModule, $iContentId)
+    {
+        if (!getParam('bx_channels_labels_autofollow'))
+            return;
+        
+        if (!($oModuleProfiles = BxDolModule::getInstance($sModule)))
+            return;
+
+        if (!($aContentInfo = $oModuleProfiles->_oDb->getContentInfoById($iContentId)) || !($oProfile = BxDolProfile::getInstanceByContentAndType($iContentId, $sModule)))
+            return;
+
+        $CNF = &$oModuleProfiles->_oConfig->CNF;
+        
+        if (!$oModuleProfiles->serviceActAsProfile() || !isset($CNF['FIELD_LABELS']) || empty($aContentInfo[$CNF['FIELD_ID']]))
+            return;
+
+        if (!($oMetatags = BxDolMetatags::getObjectInstance($CNF['OBJECT_METATAGS'])) || !$oMetatags->keywordsIsEnabled() || !($aLabels = $oMetatags->keywordsGet($aContentInfo[$CNF['FIELD_ID']])))
+            return;
+
+        if (!($oConn = BxDolConnection::getObjectInstance('sys_profiles_subscriptions')))
+            return;
+
+        foreach ($aLabels as $sLabel) {
+
+            if (!($iContentIdChannel = $this->_oDb->getChannelIdByName($sLabel)))
+                continue;
+
+            if (!($oProfileChannel = BxDolProfile::getInstanceByContentAndType($iContentIdChannel, 'bx_channels')))
+                continue;
+
+            $oConn->addConnection($oProfile->id(), $oProfileChannel->id());
+        }
+    }
+
+    /** Returns profile's subscribed channels  React Jot
+     *
+     * @param int $iProfileId
+     * @param array $aParams
+     * @return array
+     */
+
+    public function serviceBrowseAuthorChannels($iProfileId = 0, $aParams = array())
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        if(empty($iProfileId))
+            $iProfileId = bx_get_logged_profile_id();
+
+        $oConnection = BxDolConnection::getObjectInstance('sys_profiles_subscriptions');
+        $aProfile = $oConnection->getConnectedContent($iProfileId);
+        $aVars = array();
+        foreach ($aProfile as $iProfileId) {
+            $oProfile = BxDolProfile::getInstance($iProfileId);
+            if (!$oProfile || $oProfile->getModule() != $this->getName())
+                continue;
+
+            $iContentId = $oProfile->getContentId();
+            $aContentInfo = $this->_oDb->getContentInfoById($iContentId);
+
+            if (isset($aContentInfo[$CNF['FIELD_NAME']]))
+                array_push($aVars, array(
+                    'title' => $aContentInfo[$CNF['FIELD_NAME']],
+                    'link' => BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink('page.php?i=' . $CNF['URI_VIEW_ENTRY'] . '&id=' . $iContentId),
+                    'followers' => $oConnection -> getConnectedInitiatorsCount($iProfileId),
+                    'id' => $iProfileId,
+                    'icon' => $oProfile -> getThumb()
+                ));
+        }
+
+        return $aVars;
+    }
+}
+
+/** @} */

+ 153 - 0
modules/boonex/channels/updates/12.0.0_12.0.1/source/install/config.php

@@ -0,0 +1,153 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defdroup    Channels Channels
+ * @indroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_channels',
+    'title' => 'Channels',
+    'note' => 'Channels functionality.',
+    'version' => '12.0.1',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '12.1.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use channels in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/channels/',
+    'home_uri' => 'channels',
+
+    'db_prefix' => 'bx_cnl_',
+    'class_prefix' => 'BxCnl',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Channels',
+
+    /**
+     * Connections.
+     */
+    'connections' => array(
+        'sys_profiles_friends' => array ('type' => 'profiles'),
+        'sys_profiles_subscriptions' => array ('type' => 'profiles'),
+    ),
+
+    /**
+     * Menu triggers.
+     */
+    'menu_triggers' => array(
+        'trigger_profile_view_submenu',
+        'trigger_group_view_submenu',
+        'trigger_group_snippet_meta',
+        'trigger_group_view_actions',
+    ),
+
+    /**
+     * Page triggers.
+     */
+    'page_triggers' => array (
+        'trigger_page_profile_view_entry',
+        'trigger_page_group_view_entry',
+    ),
+
+    /**
+     * Storage objects to automatically delete files from upon module uninstallation.
+     * Note. Don't add storage objects used in transcoder objects.
+     */
+    'storages' => array(
+        'bx_channels_pics'
+    ),
+
+    /**
+     * Transcoders.
+     */
+    'transcoders' => array(
+        'bx_channels_icon',
+        'bx_channels_thumb',
+        'bx_channels_avatar',
+        'bx_channels_avatar_big',
+        'bx_channels_picture',
+        'bx_channels_cover',
+        'bx_channels_cover_thumb',
+        'bx_channels_gallery'
+    ),
+
+    /**
+     * Extended Search Forms.
+     */
+    'esearches' => array(
+        'bx_channels',
+        'bx_channels_cmts',
+    ),
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'uninstall' => array (
+        'process_esearches' => 1,
+        'execute_sql' => 1,
+        'update_languages' => 1,
+        'process_connections' => 1,
+        'process_deleted_profiles' => 1,
+        'update_relations' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'enable' => array(
+        'execute_sql' => 1,
+        'update_relations' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'enable_success' => array(
+        'process_menu_triggers' => 1,
+        'process_page_triggers' => 1,
+        'process_esearches' => 1,
+        'register_transcoders' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable' => array (
+        'execute_sql' => 1,
+        'unregister_transcoders' => 1,
+        'update_relations' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable_failed' => array (
+        'register_transcoders' => 1,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Dependencies Section
+     */
+    'dependencies' => array(),
+
+    /**
+     * Connections Section
+     */
+    'relations' => array(
+        'bx_timeline',
+        'bx_notifications',
+    ),
+);
+
+/** @} */

+ 242 - 0
modules/boonex/channels/updates/12.0.0_12.0.1/source/install/langs/en.xml

@@ -0,0 +1,242 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources name="en" flag="gb" title="English">
+    <string name="_bx_channels"><![CDATA[Channels]]></string>
+    <string name="_bx_channels_cmts"><![CDATA[Channels' Comments]]></string>
+
+    <string name="_bx_channels_option_default_author"><![CDATA[Default author for automatically created channels]]></string>
+    <string name="_bx_channels_option_num_connections_quick"><![CDATA[Number of items in friends block]]></string>
+    <string name="_bx_channels_option_per_page_browse"><![CDATA[Number of items per page]]></string>
+    <string name="_bx_channels_option_num_rss"><![CDATA[Number of items in RSS feed]]></string>
+    <string name="_bx_channels_option_searchable_fields"><![CDATA[Searchable fields]]></string>
+    <string name="_bx_channels_option_labels_autofollow"><![CDATA[Auto-follow channels when used as labels in profiles]]></string>
+
+	<string name="_bx_channels_form_profile"><![CDATA[Channels]]></string>
+	<string name="_bx_channels_form_profile_display_add"><![CDATA[Add Channel]]></string>
+	<string name="_bx_channels_form_profile_display_edit"><![CDATA[Edit Channel]]></string>
+	<string name="_bx_channels_form_profile_display_edit_cover"><![CDATA[Edit Cover]]></string>
+	<string name="_bx_channels_form_profile_display_delete"><![CDATA[Delete Channel]]></string>
+	<string name="_bx_channels_form_profile_display_view"><![CDATA[View Channel]]></string>
+	<string name="_bx_channels_form_profile_display_view_full"><![CDATA[Full View Channel]]></string>
+	<string name="_bx_channels_form_profile_display_invite"><![CDATA[Invite to Channel]]></string>
+	<string name="_bx_channels_form_entry_input_author"><![CDATA[Author]]></string>
+	<string name="_bx_channels_form_profile_input_sys_do_submit"><![CDATA[Submit]]></string>
+	<string name="_bx_channels_form_profile_input_sys_allow_view_to"><![CDATA[Privacy]]></string>
+	<string name="_bx_channels_form_profile_input_allow_view_to"><![CDATA[Privacy]]></string>
+	<string name="_bx_channels_form_profile_input_allow_view_to_desc"><![CDATA[Closed - anyone can find the channel and see who's in it, only members can see posts. Secret - only members can find the channel and see posts.]]></string>
+	<string name="_bx_channels_form_profile_input_sys_initial_members"><![CDATA[Invite Members]]></string>
+	<string name="_bx_channels_form_profile_input_initial_members"><![CDATA[Invite Members]]></string>
+  	<string name="_bx_channels_form_profile_input_sys_channel_name"><![CDATA[Channel Name]]></string>
+	<string name="_bx_channels_form_profile_input_channel_name"><![CDATA[Channel Name]]></string>
+	<string name="_bx_channels_form_profile_input_channel_name_err"><![CDATA[Please, fill in this field. Channel name must be unique.]]></string>
+	<string name="_bx_channels_form_profile_input_sys_picture"><![CDATA[Channel Picture]]></string>
+	<string name="_bx_channels_form_profile_input_picture"><![CDATA[Upload New Channel Picture]]></string>
+	<string name="_bx_channels_form_profile_input_picture_err"><![CDATA[Channel picture is mandatory.]]></string>
+	<string name="_bx_channels_form_profile_input_sys_cover"><![CDATA[Cover Picture]]></string>
+	<string name="_bx_channels_form_profile_input_cover"><![CDATA[Upload New Cover Picture]]></string>
+	<string name="_bx_channels_form_profile_input_sys_delete_confirm"><![CDATA[Delete confirmation]]></string>
+	<string name="_bx_channels_form_profile_input_delete_confirm"><![CDATA[I am sure I want to delete this channel]]></string>
+	<string name="_bx_channels_form_profile_input_delete_confirm_info"><![CDATA[This action can not be undone.]]></string>
+	<string name="_bx_channels_form_profile_input_delete_confirm_error"><![CDATA[Please check this checkbox if you really want to delete channel.]]></string>
+	
+	<string name="_bx_channels_acl_action_delete_profile"><![CDATA[Delete Channel]]></string>
+	<string name="_bx_channels_acl_action_view_profile"><![CDATA[View Channel]]></string>
+	<string name="_bx_channels_acl_action_edit_any_profile"><![CDATA[Edit Any Channel]]></string>
+  <string name="_bx_channels_acl_action_create_channel_auto"><![CDATA[Create Channel Auto]]></string>
+  <string name="_bx_channels_acl_action_create_channel_auto_info"><![CDATA[Automatically create new channel when new hashtag is mentioned by anyone with this level]]></string>
+ 
+  <string name="_bx_channels_page_title_sys_edit_profile"><![CDATA[Edit Channel]]></string>
+	<string name="_bx_channels_page_title_edit_profile"><![CDATA[Edit Channel]]></string>
+	<string name="_bx_channels_page_title_sys_edit_profile_cover"><![CDATA[Edit Channel Cover]]></string>
+	<string name="_bx_channels_page_title_edit_profile_cover"><![CDATA[Edit Cover]]></string>
+	<string name="_bx_channels_page_title_sys_delete_profile"><![CDATA[Delete Channel]]></string>
+	<string name="_bx_channels_page_title_delete_profile"><![CDATA[Delete Channel]]></string>
+	<string name="_bx_channels_page_title_sys_view_profile_closed"><![CDATA[View Closed Channel]]></string>
+	<string name="_bx_channels_page_title_sys_view_profile"><![CDATA[View Channel]]></string>
+	<string name="_bx_channels_page_title_view_profile"><![CDATA[{display_name}]]></string>
+	<string name="_bx_channels_page_title_browse"><![CDATA[Channels]]></string>
+	<string name="_bx_channels_page_title_browse_by_author"><![CDATA[Channels of {display_name}]]></string>
+	<string name="_bx_channels_page_title_browse_featured"><![CDATA[Featured Channels]]></string>
+	<string name="_bx_channels_page_title_browse_top"><![CDATA[Top Channels]]></string>
+	<string name="_bx_channels_page_title_browse_recent"><![CDATA[New Channels]]></string>
+	<string name="_bx_channels_page_title_browse_connections"><![CDATA[{0} connections]]></string>
+	<string name="_bx_channels_page_title_browse_connections_mutual"><![CDATA[{0} and {1} mutual connections]]></string>
+	<string name="_bx_channels_page_title_sys_profile_friends"><![CDATA[Friends]]></string>
+	<string name="_bx_channels_page_title_profile_friends"><![CDATA[Friends]]></string>
+	<string name="_bx_channels_page_title_sys_profile_comments"><![CDATA[Comments]]></string>
+	<string name="_bx_channels_page_title_profile_comments"><![CDATA[Comments]]></string>
+	<string name="_bx_channels_page_title_sys_profile_info"><![CDATA[Channel Info]]></string>
+	<string name="_bx_channels_page_title_profile_info"><![CDATA[Info about {display_name}]]></string>
+	<string name="_bx_channels_page_title_sys_recent"><![CDATA[New Channels]]></string>
+	<string name="_bx_channels_page_title_recent"><![CDATA[New Channels]]></string>
+	<string name="_bx_channels_page_title_sys_manage"><![CDATA[Manage Own Channels]]></string>
+	<string name="_bx_channels_page_title_sys_manage_administration"><![CDATA[Manage All Channels]]></string>
+	<string name="_bx_channels_page_title_manage"><![CDATA[Manage Channels]]></string>
+	<string name="_bx_channels_page_title_sys_top"><![CDATA[Top Channels]]></string>
+	<string name="_bx_channels_page_title_top"><![CDATA[Top Channels]]></string>
+	<string name="_bx_channels_page_title_sys_entries_search"><![CDATA[Search]]></string>
+	<string name="_bx_channels_page_title_entries_search"><![CDATA[Search]]></string>
+  <string name="_bx_channels_page_title_sys_entries_toplevel"><![CDATA[Top level]]></string>
+  <string name="_bx_channels_page_title_entries_toplevel"><![CDATA[Top level]]></string>
+  <string name="_bx_channels_page_title_sys_entries_of_author"><![CDATA[Сhannels of author]]></string>
+  <string name="_bx_channels_page_title_entries_of_author"><![CDATA[Сhannels by {display_name}]]></string>
+
+  <string name="_bx_channels_page_block_title_system_profile_subscribed_me"><![CDATA[Followers]]></string>
+  <string name="_bx_channels_page_block_title_profile_subscribed_me"><![CDATA[Followers]]></string>
+  <string name="_bx_channels_page_block_title_sys_entries_actions"><![CDATA[Channels actions]]></string>
+	<string name="_bx_channels_page_block_title_entries_actions"><![CDATA[Channels actions]]></string>
+	<string name="_bx_channels_page_block_title_sys_entries_of_author"><![CDATA[Followed Сhannels]]></string>
+	<string name="_bx_channels_page_block_title_entries_of_author"><![CDATA[Followed Сhannels]]></string>
+	<string name="_bx_channels_page_block_title_favorites_of_author"><![CDATA[Favorite Channels]]></string>
+	<string name="_bx_channels_page_block_title_sys_favorites_of_author"><![CDATA[Favorite Channels]]></string>
+	<string name="_bx_channels_page_block_title_edit_profile"><![CDATA[Edit Channel]]></string>
+	<string name="_bx_channels_page_block_title_edit_profile_cover"><![CDATA[Edit Cover]]></string>
+	<string name="_bx_channels_page_block_title_delete_profile"><![CDATA[Delete Channel]]></string>
+	<string name="_bx_channels_page_block_title_profile_info_link"><![CDATA[About <a href="{profile_link}">{display_name}</a>]]></string>
+	<string name="_bx_channels_page_block_title_profile_info"><![CDATA[Info]]></string>
+	<string name="_bx_channels_page_block_title_system_profile_info"><![CDATA[Info]]></string>
+	<string name="_bx_channels_page_block_title_profile_description"><![CDATA[Description]]></string>
+	<string name="_bx_channels_page_block_title_profile_friends_link"><![CDATA[Friends of <a href="{profile_link}">{display_name}</a>]]></string>
+	<string name="_bx_channels_page_block_title_profile_friends"><![CDATA[Friends]]></string>
+	<string name="_bx_channels_page_block_title_system_profile_friends"><![CDATA[Friends]]></string>
+	<string name="_bx_channels_page_block_title_admins"><![CDATA[Administrators]]></string>
+	<string name="_bx_channels_page_block_title_profile_comments"><![CDATA[Comments]]></string>
+	<string name="_bx_channels_page_block_title_profile_comments_link"><![CDATA[Comments to <a href="{entry_link}">{title}</a>]]></string>
+	<string name="_bx_channels_page_block_title_profile_actions"><![CDATA[Actions]]></string>
+	<string name="_bx_channels_page_block_title_featured_profiles"><![CDATA[Featured Channels]]></string>
+	<string name="_bx_channels_page_block_title_latest_profiles"><![CDATA[New Channels]]></string>
+	<string name="_bx_channels_page_block_title_system_manage"><![CDATA[Manage Own Channels]]></string>
+	<string name="_bx_channels_page_block_title_system_manage_administration"><![CDATA[Manage All Channels]]></string>
+	<string name="_bx_channels_page_block_title_manage"><![CDATA[Manage Channels]]></string>
+	<string name="_bx_channels_page_block_title_top_profiles"><![CDATA[Top Channels]]></string>
+        <string name="_bx_channels_page_block_title_entry_all_actions"><![CDATA[All Actions]]></string>
+	<string name="_bx_channels_page_block_title_entry_social_sharing"><![CDATA[Share]]></string>
+        <string name="_bx_channels_page_block_title_entry_breadcrumb"><![CDATA[Breadcrumb]]></string>
+        <string name="_bx_channels_page_block_title_entry_parent"><![CDATA[Parent Channel]]></string>
+        <string name="_bx_channels_page_block_title_entry_childs"><![CDATA[Child Channels]]></string>
+	<string name="_bx_channels_page_block_title_search_form"><![CDATA[Search Form]]></string>
+  <string name="_bx_channels_page_block_title_toplevel"><![CDATA[Top level]]></string>
+        <string name="_bx_channels_page_block_title_entries_my"><![CDATA[My Followed Channels]]></string>
+        <string name="_bx_channels_page_trigger_block_title_entries_my"><![CDATA[My Followed Channels]]></string>
+        <string name="_bx_channels_page_block_title_search_results"><![CDATA[Search Results]]></string>
+        <string name="_bx_channels_page_block_title_search_results_by_hashtag"><![CDATA[Search Results By Hashtag]]></string>
+	<string name="_bx_channels_page_block_title_search_form_cmts"><![CDATA[Comments Search Form]]></string>
+	<string name="_bx_channels_page_block_title_search_results_cmts"><![CDATA[Comments Search Results]]></string>
+	<string name="_bx_channels_page_block_title_sys_featured_entries_view_showcase"><![CDATA[Featured Channels (Showcase View)]]></string>
+	<string name="_bx_channels_page_block_title_featured_entries_view_showcase"><![CDATA[Featured Channels]]></string>
+	<string name="_bx_channels_page_block_title_sys_recommended_entries_view_showcase"><![CDATA[Recommended Channels (Showcase View)]]></string>
+	<string name="_bx_channels_page_block_title_recommended_entries_view_showcase"><![CDATA[Recommended Channels]]></string>
+
+	<string name="_bx_channels_menu_title_submenu"><![CDATA[Channels Submenu]]></string>
+	<string name="_bx_channels_menu_set_title_submenu"><![CDATA[Channels Submenu]]></string>
+	<string name="_bx_channels_menu_set_title_view_profile_actions"><![CDATA[Channel Actions]]></string>
+	<string name="_bx_channels_menu_title_view_profile_actions"><![CDATA[Channel Actions]]></string>
+	<string name="_bx_channels_menu_set_title_view_profile_actions_more"><![CDATA[Channel More Actions]]></string>
+	<string name="_bx_channels_menu_title_view_profile_actions_more"><![CDATA[Channel More Actions]]></string>
+	<string name="_bx_channels_menu_set_title_view_profile_submenu"><![CDATA[View Channel Submenu]]></string>
+	<string name="_bx_channels_menu_title_entries_my"><![CDATA[Profile Channels Action Menu]]></string>
+	<string name="_bx_channels_menu_set_title_entries_my"><![CDATA[Profile Channels Menu]]></string>
+	<string name="_bx_channels_menu_set_title_manage_tools"><![CDATA[Manage Tools Submenu]]></string>
+	<string name="_bx_channels_menu_title_manage_tools"><![CDATA[Manage Tools Submenu]]></string>
+	<string name="_bx_channels_menu_item_title_system_delete"><![CDATA[Delete]]></string>
+	<string name="_bx_channels_menu_item_title_delete"><![CDATA[Delete]]></string>
+	<string name="_bx_channels_menu_item_title_system_delete_with_content"><![CDATA[Delete With Content]]></string>
+	<string name="_bx_channels_menu_item_title_delete_with_content"><![CDATA[Delete With Content]]></string>
+	<string name="_bx_channels_menu_item_title_system_edit_cover"><![CDATA[Edit Cover]]></string>
+	<string name="_bx_channels_menu_item_title_edit_cover"><![CDATA[Edit Cover]]></string>
+	<string name="_bx_channels_menu_item_title_system_edit_profile"><![CDATA[Edit Channel]]></string>
+	<string name="_bx_channels_menu_item_title_edit_profile"><![CDATA[Edit Channel]]></string>
+	<string name="_bx_channels_menu_item_title_system_delete_profile"><![CDATA[Delete Channel]]></string>
+	<string name="_bx_channels_menu_item_title_delete_profile"><![CDATA[Delete Channel]]></string>
+	<string name="_bx_channels_menu_item_title_system_delete_account"><![CDATA[Delete Account]]></string>
+	<string name="_bx_channels_menu_item_title_delete_account"><![CDATA[Delete Account]]></string>
+	<string name="_bx_channels_menu_item_title_system_profile_type"><![CDATA[Channel]]></string>
+	<string name="_bx_channels_menu_item_title_profile_type"><![CDATA[Channel]]></string>
+	<string name="_bx_channels_menu_item_title_system_view_profile_friends"><![CDATA[Friends]]></string>
+	<string name="_bx_channels_menu_item_title_view_profile_friends"><![CDATA[Friends]]></string>
+	<string name="_bx_channels_menu_item_title_system_view_profile_comments"><![CDATA[Comments]]></string>
+	<string name="_bx_channels_menu_item_title_view_profile_comments"><![CDATA[Comments]]></string>
+	<string name="_bx_channels_menu_item_title_system_view_profile_info"><![CDATA[Info]]></string>
+	<string name="_bx_channels_menu_item_title_view_profile_info"><![CDATA[Info]]></string>
+	<string name="_bx_channels_menu_item_title_system_view_profile_view"><![CDATA[Channel]]></string>
+	<string name="_bx_channels_menu_item_title_view_profile_view"><![CDATA[Channel]]></string>
+        <string name="_bx_channels_menu_item_title_system_view_profile_more_auto"><![CDATA[More]]></string>
+        <string name="_bx_channels_menu_item_title_view_profile_more_auto"><![CDATA[More]]></string>
+	<string name="_bx_channels_menu_item_title_system_invite"><![CDATA[Invite]]></string>
+	<string name="_bx_channels_menu_item_title_invite"><![CDATA[Invite]]></string>
+	
+	<string name="_bx_channels_menu_item_title_system_befriend"><![CDATA[Add friend]]></string>
+	<string name="_bx_channels_menu_item_title_befriend"><![CDATA[Add friend]]></string>
+	<string name="_bx_channels_menu_item_title_befriend_sent"><![CDATA[Add friend (requested)]]></string>
+	<string name="_bx_channels_menu_item_title_befriend_confirm"><![CDATA[Accept friend request]]></string>
+	<string name="_bx_channels_menu_item_title_system_unfriend"><![CDATA[Unfriend]]></string>
+	<string name="_bx_channels_menu_item_title_unfriend"><![CDATA[Unfriend]]></string>
+	<string name="_bx_channels_menu_item_title_unfriend_cancel_request"><![CDATA[Cancel friend request]]></string>
+	<string name="_bx_channels_menu_item_title_unfriend_reject_request"><![CDATA[Reject friend request]]></string>
+	
+	<string name="_bx_channels_menu_item_title_system_subscribe"><![CDATA[Follow]]></string>
+	<string name="_bx_channels_menu_item_title_subscribe"><![CDATA[Follow]]></string>
+	<string name="_bx_channels_menu_item_title_system_unsubscribe"><![CDATA[Unfollow]]></string>
+	<string name="_bx_channels_menu_item_title_unsubscribe"><![CDATA[Unfollow]]></string>
+	<string name="_bx_channels_menu_item_title_system_more_actions"><![CDATA[More Actions]]></string>
+	<string name="_bx_channels_menu_item_title_more_actions"><![CDATA[]]></string>
+	<string name="_bx_channels_menu_item_title_system_friends"><![CDATA[Friends]]></string>
+	<string name="_bx_channels_menu_item_title_friends"><![CDATA[Friends]]></string>
+	<string name="_bx_channels_menu_item_title_system_manage_my_channels"><![CDATA[My channels]]></string>
+	<string name="_bx_channels_menu_item_title_manage_my_channels"><![CDATA[{addon} channels]]></string>
+	<string name="_bx_channels_menu_item_title_system_entries_recent"><![CDATA[New]]></string>
+	<string name="_bx_channels_menu_item_title_entries_recent"><![CDATA[New]]></string>
+	<string name="_bx_channels_menu_item_title_system_entries_search"><![CDATA[Search]]></string>
+	<string name="_bx_channels_menu_item_title_entries_search"><![CDATA[Search]]></string>
+  <string name="_bx_channels_menu_item_title_system_entries_toplevel"><![CDATA[Top level]]></string>
+  <string name="_bx_channels_menu_item_title_entries_toplevel"><![CDATA[Top level]]></string>
+        <string name="_bx_channels_menu_item_title_system_entries_manage"><![CDATA[Manage]]></string>
+	<string name="_bx_channels_menu_item_title_entries_manage"><![CDATA[Manage]]></string>
+	<string name="_bx_channels_menu_item_title_system_entries_home"><![CDATA[Channels]]></string>
+	<string name="_bx_channels_menu_item_title_entries_home"><![CDATA[Channels]]></string>
+	<string name="_bx_channels_menu_item_title_system_admt_channels"><![CDATA[Channels]]></string>
+	<string name="_bx_channels_menu_item_title_admt_channels"><![CDATA[Channels]]></string>
+	<string name="_bx_channels_menu_item_title_manage_my"><![CDATA[My Channels]]></string>
+	<string name="_bx_channels_menu_item_title_manage_all"><![CDATA[All Channels]]></string>
+	<string name="_bx_channels_menu_item_title_system_entries_top"><![CDATA[Top]]></string>
+	<string name="_bx_channels_menu_item_title_entries_top"><![CDATA[Top]]></string>
+        <string name="_bx_channels_menu_item_title_system_view_entries_author"><![CDATA[Channels]]></string>
+        <string name="_bx_channels_menu_item_title_view_entries_author"><![CDATA[Channels]]></string>
+
+	<string name="_bx_channels_grid_filter_item_title_adm_select_one_filter1"><![CDATA[All Statuses]]></string>
+	<string name="_bx_channels_grid_filter_item_title_adm_active"><![CDATA[Active]]></string>
+	<string name="_bx_channels_grid_filter_item_title_adm_pending"><![CDATA[Pending]]></string>
+	<string name="_bx_channels_grid_filter_item_title_adm_suspended"><![CDATA[Suspended]]></string>
+	<string name="_bx_channels_grid_column_title_adm_active"><![CDATA[Active]]></string>
+	<string name="_bx_channels_grid_column_title_adm_name"><![CDATA[Name]]></string>
+	<string name="_bx_channels_grid_column_title_adm_added"><![CDATA[Created]]></string>
+	<string name="_bx_channels_grid_column_title_adm_account"><![CDATA[Account]]></string>
+	<string name="_bx_channels_grid_action_title_adm_delete"><![CDATA[Delete]]></string>
+	<string name="_bx_channels_grid_action_title_adm_delete_with_content"><![CDATA[Delete With Content]]></string>
+	<string name="_bx_channels_grid_action_title_adm_more_actions"><![CDATA[More Actions]]></string>
+  <string name="_bx_channels_grid_action_title_adm_audit_context"><![CDATA[Audit actions in context]]></string>
+  <string name="_bx_channels_grid_action_title_adm_audit_content"><![CDATA[Audit actions with content]]></string>
+	<string name="_bx_channels_grid_action_err_delete"><![CDATA[Cannot delete the selected channel(s).]]></string>
+	<string name="_bx_channels_grid_txt_account_manager"><![CDATA[Redirect to manage account.]]></string>
+	
+	<string name="_bx_channels_chart_growth"><![CDATA[Channels: Growth]]></string>
+	<string name="_bx_channels_chart_growth_speed"><![CDATA[Channels: Growth Speed]]></string>
+	
+	<string name="_bx_channels_search_extended"><![CDATA[Channels Search]]></string>
+	<string name="_bx_channels_search_extended_cmts"><![CDATA[Channels Comments Search]]></string>
+
+	<string name="_bx_channels_txt_account_pending"><![CDATA[This channel is pending approval, please wait until it is activated.]]></string>
+	<string name="_bx_channels_txt_account_suspended"><![CDATA[This channel is suspended.]]></string>
+	<string name="_bx_channels_txt_sample_single"><![CDATA[channel]]></string>
+	<string name="_bx_channels_txt_sample_single_with_article"><![CDATA[a channel]]></string>
+	<string name="_bx_channels_txt_sample_comment_single"><![CDATA[comment to channel]]></string>
+	<string name="_bx_channels_txt_sample_vote_single"><![CDATA[vote to channel]]></string>
+        <string name="_bx_channels_txt_sample_score_up_single"><![CDATA[score up vote to channel]]></string>
+        <string name="_bx_channels_txt_sample_score_down_single"><![CDATA[score down vote to channel]]></string>
+        <string name="_bx_channels_msg_empty_author"><![CDATA['Default author for automatically created channels' is empty. You need to select some profile in this setting.]]></string>
+
+    <string name="_bx_channels_txt_ntfs_timeline_post_common"><![CDATA[New post <b class="bx-ntfs-content-entry">{subentry_sample}</b> in <b class="bx-ntfs-content-profile">{owner_name}</b> channel timeline]]></string>
+    <string name="_bx_channels_ntfs_txt_subobject_added"><![CDATA[New content <b class="bx-ntfs-content-entry">{entry_caption}</b> in <b class="bx-ntfs-content-profile">{owner_name}</b> channel]]></string>
+    <string name="_bx_channels_ntfs_txt_subobject_added_profile"><![CDATA[<b class="bx-ntfs-content-entry">{entry_caption}</b> was added to <b class="bx-ntfs-content-profile">{owner_name}</b> channel]]></string>
+    <string name="_bx_channels_alert_action_hashtag_added"><![CDATA[New hashtags]]></string>
+    <string name="_bx_channels_alert_action_hashtag_added_notif_follow_context"><![CDATA[New hashtags]]></string>
+</resources>

+ 414 - 0
modules/boonex/channels/updates/12.0.0_12.0.1/source/install/sql/enable.sql

@@ -0,0 +1,414 @@
+
+-- SETTINGS
+
+SET @iTypeOrder = (SELECT MAX(`order`) FROM `sys_options_types` WHERE `group` = 'modules');
+INSERT INTO `sys_options_types`(`group`, `name`, `caption`, `icon`, `order`) VALUES 
+('modules', 'bx_channels', '_bx_channels', 'bx_channels@modules/boonex/channels/|std-icon.svg', IF(ISNULL(@iTypeOrder), 1, @iTypeOrder + 1));
+SET @iTypeId = LAST_INSERT_ID();
+
+INSERT INTO `sys_options_categories` (`type_id`, `name`, `caption`, `order`)
+VALUES (@iTypeId, 'bx_channels', '_bx_channels', 1);
+SET @iCategId = LAST_INSERT_ID();
+
+INSERT INTO `sys_options` (`name`, `value`, `category_id`, `caption`, `type`, `extra`, `check`, `check_params`, `check_error`, `order`) VALUES
+('bx_channels_default_author', '', @iCategId, '_bx_channels_option_default_author', 'select', 'a:2:{s:6:"module";s:11:"bx_channels";s:6:"method";s:26:"get_options_default_author";}', '', '', '', 1),
+('bx_channels_num_connections_quick', '6', @iCategId, '_bx_channels_option_num_connections_quick', 'digit', '', '', '', '', 10),
+('bx_channels_per_page_browse', '24', @iCategId, '_bx_channels_option_per_page_browse', 'digit', '', '', '', '', 11),
+('bx_channels_num_rss', '10', @iCategId, '_bx_channels_option_num_rss', 'digit', '', '', '', '', 12),
+('bx_channels_per_page_browse_showcase', '32', @iCategId, '_sys_option_per_page_browse_showcase', 'digit', '', '', '', '', 15),
+('bx_channels_per_page_browse_recommended', '10', @iCategId, '_sys_option_per_page_browse_recommended', 'digit', '', '', '', '', 16),
+('bx_channels_searchable_fields', 'channel_name', @iCategId, '_bx_channels_option_searchable_fields', 'list', 'a:2:{s:6:"module";s:11:"bx_channels";s:6:"method";s:21:"get_searchable_fields";}', '', '', '', 30),
+('bx_channels_labels_autofollow', 'on', @iCategId, '_bx_channels_option_labels_autofollow', 'checkbox', '', '', '', '', 40);
+
+
+-- PAGES
+
+-- PAGE: view profile
+
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_channels_view_profile', 'view-channel-profile', '_bx_channels_page_title_sys_view_profile', '_bx_channels_page_title_view_profile', 'bx_channels', 10, 2147483647, 1, 'page.php?i=view-channel-profile', '', '', '', 0, 1, 0, 'BxCnlPageEntry', 'modules/boonex/channels/classes/BxCnlPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES
+('bx_channels_view_profile', 1, 'bx_channels', '', '_bx_channels_page_block_title_entry_social_sharing', 13, 2147483647, 'service', 'a:2:{s:6:\"module\";s:11:\"bx_channels\";s:6:\"method\";s:21:\"entity_social_sharing\";}', 0, 0, 0, 0),
+('bx_channels_view_profile', 1, 'bx_channels', '', '_bx_channels_page_block_title_entry_all_actions', 13, 2147483647, 'service', 'a:2:{s:6:\"module\";s:11:\"bx_channels\";s:6:\"method\";s:18:\"entity_all_actions\";}', 0, 0, 0, 0),
+('bx_channels_view_profile', 1, 'bx_channels', '', '_bx_channels_page_block_title_entry_breadcrumb', 13, 2147483647, 'service', 'a:2:{s:6:"module";s:11:"bx_channels";s:6:"method";s:17:"entity_breadcrumb";}', 0, 0, 1, 1),
+('bx_channels_view_profile', 2, 'bx_channels', '', '_bx_channels_page_block_title_entry_parent', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:11:"bx_channels";s:6:"method";s:13:"entity_parent";}', 0, 0, 1, 1),
+('bx_channels_view_profile', 3, 'bx_channels', '', '_bx_channels_page_block_title_entry_childs', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:11:"bx_channels";s:6:"method";s:13:"entity_childs";}', 0, 0, 1, 1),
+('bx_channels_view_profile', 4, 'bx_channels', '', '_bx_channels_page_block_title_search_results_by_hashtag', 0, 2147483647, 'service', 'a:2:{s:6:\"module\";s:11:\"bx_channels\";s:6:\"method\";s:24:\"search_result_by_hashtag\";}', 0, 0, 0, 0),
+('bx_channels_view_profile', 4, 'bx_channels', '', '_bx_channels_page_block_title_profile_comments', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:11:\"bx_channels\";s:6:\"method\";s:15:\"entity_comments\";}', 0, 0, 0, 1),
+('bx_channels_view_profile', 4, 'bx_channels', '', '_bx_channels_page_block_title_profile_subscribed_me', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:11:\"bx_channels\";s:6:\"method\";s:21:\"profile_subscribed_me\";}', 0, 1, 1, 0);
+
+-- PAGE: view closed profile 
+
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_channels_view_profile_closed', 'view-channel-profile-closed', '_bx_channels_page_title_sys_view_profile_closed', '_bx_channels_page_title_view_profile', 'bx_channels', 10, 2147483647, 1, 'page.php?i=view-channel-profile', '', '', '', 0, 1, 0, 'BxCnlPageEntry', 'modules/boonex/channels/classes/BxCnlPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_channels_view_profile_closed', 2, 'bx_channels', '', '_bx_channels_page_block_title_profile_info', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:11:\"bx_channels\";s:6:\"method\";s:11:\"entity_info\";}', 0, 0, 1, 0);
+
+-- PAGE: edit profile
+
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_channels_edit_profile', 'edit-channel-profile', '_bx_channels_page_title_sys_edit_profile', '_bx_channels_page_title_edit_profile', 'bx_channels', 5, 2147483647, 1, 'page.php?i=edit-channel-profile', '', '', '', 0, 1, 0, 'BxCnlPageEntry', 'modules/boonex/channels/classes/BxCnlPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_channels_edit_profile', 1, 'bx_channels', '_bx_channels_page_block_title_edit_profile', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:11:\"bx_channels\";s:6:\"method\";s:11:\"entity_edit\";}', 0, 0, 0);
+
+-- PAGE: edit profile cover
+
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_channels_edit_profile_cover', 'edit-channel-cover', '_bx_channels_page_title_sys_edit_profile_cover', '_bx_channels_page_title_edit_profile_cover', 'bx_channels', 5, 2147483647, 1, 'page.php?i=edit-channel-cover', '', '', '', 0, 1, 0, 'BxCnlPageEntry', 'modules/boonex/channels/classes/BxCnlPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_channels_edit_profile_cover', 1, 'bx_channels', '_bx_channels_page_block_title_edit_profile_cover', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:11:\"bx_channels\";s:6:\"method\";s:17:\"entity_edit_cover\";}', 0, 0, 0);
+
+-- PAGE: delete profile
+
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_channels_delete_profile', 'delete-channel-profile', '_bx_channels_page_title_sys_delete_profile', '_bx_channels_page_title_delete_profile', 'bx_channels', 5, 2147483647, 1, 'page.php?i=delete-channel-profile', '', '', '', 0, 1, 0, 'BxCnlPageEntry', 'modules/boonex/channels/classes/BxCnlPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_channels_delete_profile', 1, 'bx_channels', '_bx_channels_page_block_title_delete_profile', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:11:\"bx_channels\";s:6:\"method\";s:13:\"entity_delete\";}', 0, 0, 0);
+
+-- PAGE: view entry comments
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_channels_profile_comments', '_bx_channels_page_title_sys_profile_comments', '_bx_channels_page_title_profile_comments', 'bx_channels', 5, 2147483647, 1, 'channel-profile-comments', '', '', '', '', 0, 1, 0, 'BxCnlPageEntry', 'modules/boonex/channels/classes/BxCnlPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_channels_profile_comments', 1, 'bx_channels', '_bx_channels_page_block_title_profile_comments', '_bx_channels_page_block_title_profile_comments_link', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:11:\"bx_channels\";s:6:\"method\";s:15:\"entity_comments\";}', 0, 0, 0, 1);
+
+-- PAGE: entries of author
+
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_channels_author', 'channels-author', '_bx_channels_page_title_sys_entries_of_author', '_bx_channels_page_title_entries_of_author', 'bx_channels', 5, 2147483647, 1, '', '', '', '', 0, 1, 0, 'BxCnlPageAuthor', 'modules/boonex/channels/classes/BxCnlPageAuthor.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_channels_author', 1, 'bx_channels', '_bx_channels_page_block_title_sys_favorites_of_author', '_bx_channels_page_block_title_favorites_of_author', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:11:"bx_channels";s:6:"method";s:15:"browse_favorite";s:6:"params";a:1:{i:0;s:12:"{profile_id}";}}', 0, 1, 1, 1),
+('bx_channels_author', 1, 'bx_channels', '_bx_channels_page_block_title_sys_entries_of_author', '_bx_channels_page_block_title_entries_of_author', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:11:"bx_channels";s:6:"method";s:13:"browse_author";s:6:"params";a:2:{i:0;s:12:"{profile_id}";i:1;a:1:{s:13:"empty_message";b:1;}}}}', 0, 0, 1, 2);
+
+-- PAGE: module home
+
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_channels_home', '_bx_channels_page_title_sys_recent', '_bx_channels_page_title_recent', 'bx_channels', 5, 2147483647, 1, 'channels-home', 'page.php?i=channels-home', '', '', '', 0, 1, 0, 'BxCnlPageBrowse', 'modules/boonex/channels/classes/BxCnlPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES
+('bx_channels_home', 1, 'bx_channels', '_bx_channels_page_block_title_featured_profiles', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:11:"bx_channels";s:6:"method";s:15:"browse_featured";s:6:"params";a:1:{i:0;s:7:"gallery";}}', 0, 1, 1, 0),
+('bx_channels_home', 1, 'bx_channels', '_bx_channels_page_block_title_latest_profiles', 11, 2147483647, 'service', 'a:3:{s:6:\"module\";s:11:\"bx_channels\";s:6:\"method\";s:22:\"browse_recent_profiles\";s:6:"params";a:1:{i:0;b:1;}}', 0, 1, 1, 1),
+('bx_channels_home', 1, 'bx_channels', '_bx_channels_page_block_title_entries_my', 11, 2147483646, 'service', 'a:2:{s:6:"module";s:11:"bx_channels";s:6:"method";s:13:"browse_author";}',  0, 1, 0, 0);
+
+-- PAGE: top profiles
+
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_channels_top', '_bx_channels_page_title_sys_top', '_bx_channels_page_title_top', 'bx_channels', 5, 2147483647, 1, 'channels-top', 'page.php?i=channels-top', '', '', '', 0, 1, 0, 'BxCnlPageBrowse', 'modules/boonex/channels/classes/BxCnlPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_channels_top', 1, 'bx_channels', '_bx_channels_page_block_title_top_profiles', 11, 2147483647, 'service', 'a:3:{s:6:\"module\";s:11:\"bx_channels\";s:6:\"method\";s:19:\"browse_top_profiles\";s:6:"params";a:1:{i:0;b:1;}}', 0, 1, 0);
+
+-- PAGE: top level entries
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_channels_toplevel', '_bx_channels_page_title_sys_entries_toplevel', '_bx_channels_page_title_entries_toplevel', 'bx_channels', 5, 2147483647, 1, 'channels-toplevel', 'page.php?i=toplevel', '', '', '', 0, 1, 0, 'BxCnlPageBrowse', 'modules/boonex/channels/classes/BxCnlPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_channels_toplevel', 1, 'bx_channels', '_bx_channels_page_block_title_toplevel', 11, 2147483647, 'service', 'a:3:{s:6:\"module\";s:11:\"bx_channels\";s:6:\"method\";s:15:\"browse_by_level\";s:6:"params";a:2:{i:0;i:0;i:1;b:1;}}', 0, 1, 1, 1);
+
+-- PAGE: search for entries
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_channels_search', '_bx_channels_page_title_sys_entries_search', '_bx_channels_page_title_entries_search', 'bx_channels', 5, 2147483647, 1, 'channels-search', 'page.php?i=channels-search', '', '', '', 0, 1, 0, 'BxCnlPageBrowse', 'modules/boonex/channels/classes/BxCnlPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_channels_search', 1, 'bx_channels', '_bx_channels_page_block_title_search_form', 11, 2147483647, 'service', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:8:"get_form";s:6:"params";a:1:{i:0;a:1:{s:6:"object";s:11:"bx_channels";}}s:5:"class";s:27:"TemplSearchExtendedServices";}', 0, 1, 1, 1),
+('bx_channels_search', 1, 'bx_channels', '_bx_channels_page_block_title_search_results', 11, 2147483647, 'service', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:11:"get_results";s:6:"params";a:1:{i:0;a:2:{s:6:"object";s:11:"bx_channels";s:10:"show_empty";b:1;}}s:5:"class";s:27:"TemplSearchExtendedServices";}', 0, 1, 1, 2),
+('bx_channels_search', 1, 'bx_channels', '_bx_channels_page_block_title_search_form_cmts', 11, 2147483647, 'service', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:8:"get_form";s:6:"params";a:1:{i:0;a:1:{s:6:"object";s:16:"bx_channels_cmts";}}s:5:"class";s:27:"TemplSearchExtendedServices";}', 0, 1, 0, 3),
+('bx_channels_search', 1, 'bx_channels', '_bx_channels_page_block_title_search_results_cmts', 11, 2147483647, 'service', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:11:"get_results";s:6:"params";a:1:{i:0;a:2:{s:6:"object";s:16:"bx_channels_cmts";s:10:"show_empty";b:1;}}s:5:"class";s:27:"TemplSearchExtendedServices";}', 0, 1, 0, 4);
+
+-- PAGE: module manage all
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_channels_administration', '_bx_channels_page_title_sys_manage_administration', '_bx_channels_page_title_manage', 'bx_channels', 5, 128, 1, 'channels-administration', 'page.php?i=channels-administration', '', '', '', 0, 1, 0, 'BxCnlPageBrowse', 'modules/boonex/channels/classes/BxCnlPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_channels_administration', 1, 'bx_channels', '_bx_channels_page_block_title_system_manage_administration', '_bx_channels_page_block_title_manage', 11, 192, 'service', 'a:3:{s:6:\"module\";s:11:\"bx_channels\";s:6:\"method\";s:12:\"manage_tools\";s:6:\"params\";a:1:{i:0;s:14:\"administration\";}}', 0, 1, 0);
+
+
+-- PAGE: add block to homepage
+SET @iBlockOrder = (SELECT `order` FROM `sys_pages_blocks` WHERE `object` = 'sys_home' AND `cell_id` = 1 ORDER BY `order` DESC LIMIT 1);
+INSERT INTO `sys_pages_blocks` (`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES
+('sys_home', 1, 'bx_channels', '', '_bx_channels_page_block_title_latest_profiles', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:11:"bx_channels";s:6:"method";s:22:"browse_recent_profiles";}', 1, 0, 0, IFNULL(@iBlockOrder, 0) + 1),
+('sys_home', 1, 'bx_channels', '_bx_channels_page_block_title_sys_recommended_entries_view_showcase', '_bx_channels_page_block_title_recommended_entries_view_showcase', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:11:"bx_channels";s:6:"method";s:18:"browse_recommended";}', 1, 0, 0, IFNULL(@iBlockOrder, 0) + 2);
+-- PAGE: service blocks
+SET @iBlockOrder = (SELECT `order` FROM `sys_pages_blocks` WHERE `object` = '' AND `cell_id` = 0 ORDER BY `order` DESC LIMIT 1);
+INSERT INTO `sys_pages_blocks` (`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES
+('', 0, 'bx_channels', '_bx_channels_page_block_title_sys_featured_entries_view_showcase', '_bx_channels_page_block_title_featured_entries_view_showcase', 11, 2147483647, 'service', 'a:3:{s:6:\"module\";s:11:\"bx_channels\";s:6:\"method\";s:15:\"browse_featured\";s:6:\"params\";a:3:{s:9:\"unit_view\";s:8:\"showcase\";s:13:\"empty_message\";b:0;s:13:\"ajax_paginate\";b:0;}}', 0, 1, 1, IFNULL(@iBlockOrder, 0) + 1),
+('', 0, 'bx_channels', '_bx_channels_page_block_title_sys_recommended_entries_view_showcase', '_bx_channels_page_block_title_recommended_entries_view_showcase', 11, 2147483647, 'service', 'a:3:{s:6:\"module\";s:11:\"bx_channels\";s:6:\"method\";s:18:\"browse_recommended\";s:6:\"params\";a:3:{s:9:\"unit_view\";s:8:\"showcase\";s:13:\"empty_message\";b:0;s:13:\"ajax_paginate\";b:0;}}', 0, 1, 1, IFNULL(@iBlockOrder, 0) + 2);
+
+-- PAGES: add page block to profiles modules (trigger* page objects are processed separately upon modules enable/disable)
+SET @iPBCellProfile = 3;
+INSERT INTO `sys_pages_blocks` (`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES
+('trigger_page_profile_view_entry', @iPBCellProfile, 'bx_channels', '_bx_channels_page_trigger_block_title_entries_my', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:11:"bx_channels";s:6:"method";s:13:"browse_author";s:6:"params";a:2:{i:0;s:12:"{profile_id}";i:1;a:1:{s:13:"empty_message";b:0;}}}', 0, 0, 0);
+
+
+-- MENU
+
+-- MENU: add to site menu
+
+SET @iSiteMenuOrder = (SELECT `order` FROM `sys_menu_items` WHERE `set_name` = 'sys_site' AND `active` = 1 AND `order` < 9999 ORDER BY `order` DESC LIMIT 1);
+INSERT INTO `sys_menu_items` (`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('sys_site', 'bx_channels', 'channels-home', '_bx_channels_menu_item_title_system_entries_home', '_bx_channels_menu_item_title_entries_home', 'page.php?i=channels-home', '', '', 'hashtag col-red2', 'bx_channels_submenu', 2147483647, 1, 1, IFNULL(@iSiteMenuOrder, 0) + 1);
+
+-- MENU: add to homepage menu
+
+SET @iHomepageMenuOrder = (SELECT `order` FROM `sys_menu_items` WHERE `set_name` = 'sys_homepage' AND `active` = 1 ORDER BY `order` DESC LIMIT 1);
+INSERT INTO `sys_menu_items` (`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('sys_homepage', 'bx_channels', 'channels-home', '_bx_channels_menu_item_title_system_entries_home', '_bx_channels_menu_item_title_entries_home', 'page.php?i=channels-home', '', '', 'hashtag col-red2', 'bx_channels_submenu', 2147483647, 1, 1, IFNULL(@iHomepageMenuOrder, 0) + 1);
+
+-- MENU: view actions
+
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_channels_view_actions', '_bx_channels_menu_title_view_profile_actions', 'bx_channels_view_actions', 'bx_channels', 9, 0, 1, 'BxCnlMenuViewActions', 'modules/boonex/channels/classes/BxCnlMenuViewActions.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_channels_view_actions', 'bx_channels', '_bx_channels_menu_set_title_view_profile_actions', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `submenu_popup`, `visible_for_levels`, `active`, `copyable`, `editable`, `order`) VALUES 
+('bx_channels_view_actions', 'bx_channels', 'profile-subscribe-add', '_bx_channels_menu_item_title_system_subscribe', '_bx_channels_menu_item_title_subscribe', 'javascript:void(0)', 'bx_conn_action(this, \'sys_profiles_subscriptions\', \'add\', \'{profile_id}\')', '', 'check', '', 0, 2147483647, 1, 0, 1, 20),
+('bx_channels_view_actions', 'bx_channels', 'profile-actions-more', '_bx_channels_menu_item_title_system_more_actions', '_bx_channels_menu_item_title_more_actions', 'javascript:void(0)', 'bx_menu_popup(''bx_channels_view_actions_more'', this, {}, {profile_id:{profile_id}});', '', 'cog', 'bx_channels_view_actions_more', 1, 2147483647, 1, 0, 1, 9999);
+
+-- MENU: view actions more
+
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_channels_view_actions_more', '_bx_channels_menu_title_view_profile_actions_more', 'bx_channels_view_actions_more', 'bx_channels', 6, 0, 1, 'BxCnlMenuViewActions', 'modules/boonex/channels/classes/BxCnlMenuViewActions.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_channels_view_actions_more', 'bx_channels', '_bx_channels_menu_set_title_view_profile_actions_more', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('bx_channels_view_actions_more', 'bx_channels', 'profile-subscribe-remove', '_bx_channels_menu_item_title_system_unsubscribe', '_bx_channels_menu_item_title_unsubscribe', 'javascript:void(0)', 'bx_conn_action(this, \'sys_profiles_subscriptions\', \'remove\', \'{profile_id}\')', '', 'check', '', 2147483647, 1, 0, 20),
+('bx_channels_view_actions_more', 'bx_channels', 'edit-channel-cover', '_bx_channels_menu_item_title_system_edit_cover', '_bx_channels_menu_item_title_edit_cover', 'page.php?i=edit-channel-cover&id={content_id}', '', '', 'pencil-alt', '', 2147483647, 1, 0, 30),
+('bx_channels_view_actions_more', 'bx_channels', 'edit-channel-profile', '_bx_channels_menu_item_title_system_edit_profile', '_bx_channels_menu_item_title_edit_profile', 'page.php?i=edit-channel-profile&id={content_id}', '', '', 'pencil-alt', '', 2147483647, 0, 0, 40),
+('bx_channels_view_actions_more', 'bx_channels', 'delete-channel-profile', '_bx_channels_menu_item_title_system_delete_profile', '_bx_channels_menu_item_title_delete_profile', 'page.php?i=delete-channel-profile&id={content_id}', '', '', 'remove', '', 2147483647, 1, 0, 50);
+
+-- MENU: all actions menu for view entry 
+
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_channels_view_actions_all', '_sys_menu_title_view_actions', 'bx_channels_view_actions_all', 'bx_channels', 15, 0, 1, 'BxCnlMenuViewActionsAll', 'modules/boonex/channels/classes/BxCnlMenuViewActionsAll.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_channels_view_actions_all', 'bx_channels', '_sys_menu_set_title_view_actions', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `addon`, `submenu_object`, `submenu_popup`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('bx_channels_view_actions_all', 'bx_channels', 'profile-subscribe-add', '_bx_channels_menu_item_title_system_subscribe', '', '', '', '', '', '', '', 0, 2147483647, 1, 0, 10),
+('bx_channels_view_actions_all', 'bx_channels', 'profile-subscribe-remove', '_bx_channels_menu_item_title_system_unsubscribe', '', '', '', '', '', '', '', 0, 2147483647, 1, 0, 20),
+('bx_channels_view_actions_all', 'bx_channels', 'comment', '_sys_menu_item_title_system_va_comment', '', '', '', '', '', '', '', 0, 2147483647, 0, 0, 200),
+('bx_channels_view_actions_all', 'bx_channels', 'view', '_sys_menu_item_title_system_va_view', '', '', '', '', '', '', '', 0, 2147483647, 1, 0, 210),
+('bx_channels_view_actions_all', 'bx_channels', 'vote', '_sys_menu_item_title_system_va_vote', '', '', '', '', '', '', '', 0, 2147483647, 1, 0, 220),
+('bx_channels_view_actions_all', 'bx_channels', 'score', '_sys_menu_item_title_system_va_score', '', '', '', '', '', '', '', 0, 2147483647, 1, 0, 230),
+('bx_channels_view_actions_all', 'bx_channels', 'favorite', '_sys_menu_item_title_system_va_favorite', '', '', '', '', '', '', '', 0, 2147483647, 1, 0, 240),
+('bx_channels_view_actions_all', 'bx_channels', 'feature', '_sys_menu_item_title_system_va_feature', '', '', '', '', '', '', '', 0, 2147483647, 1, 0, 250),
+('bx_channels_view_actions_all', 'bx_channels', 'report', '_sys_menu_item_title_system_va_report', '', '', '', '', '', '', '', 0, 2147483647, 1, 0, 260),
+('bx_channels_view_actions_all', 'bx_channels', 'social-sharing-facebook', '_sys_menu_item_title_system_social_sharing_facebook', '', '', '', '', '', '', '', 0, 2147483647, 1, 0, 300),
+('bx_channels_view_actions_all', 'bx_channels', 'social-sharing-twitter', '_sys_menu_item_title_system_social_sharing_twitter', '', '', '', '', '', '', '', 0, 2147483647, 1, 0, 320),
+('bx_channels_view_actions_all', 'bx_channels', 'social-sharing-pinterest', '_sys_menu_item_title_system_social_sharing_pinterest', '', '', '', '', '', '', '', 0, 2147483647, 1, 0, 330),
+('bx_channels_view_actions_all', 'bx_channels', 'edit-channel-cover', '_bx_channels_menu_item_title_system_edit_cover', '', '', '', '', '', '', '', 0, 2147483647, 1, 0, 400),
+('bx_channels_view_actions_all', 'bx_channels', 'edit-channel-profile', '_bx_channels_menu_item_title_system_edit_profile', '', '', '', '', '', '', '', 0, 2147483647, 0, 0, 410),
+('bx_channels_view_actions_all', 'bx_channels', 'delete-channel-profile', '_bx_channels_menu_item_title_system_delete_profile', '', '', '', '', '', '', '', 0, 2147483647, 1, 0, 420),
+('bx_channels_view_actions_all', 'bx_channels', 'more-auto', '_sys_menu_item_title_system_va_more_auto', '_sys_menu_item_title_va_more_auto', 'javascript:void(0)', '', '', 'ellipsis-v', '', '', 0, 2147483647, 1, 0, 9999);
+
+-- MENU: actions menu for my entries
+
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_channels_my', '_bx_channels_menu_title_entries_my', 'bx_channels_my', 'bx_channels', 9, 0, 1, 'BxCnlMenu', 'modules/boonex/channels/classes/BxCnlMenu.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_channels_my', 'bx_channels', '_bx_channels_menu_set_title_entries_my', 0);
+
+-- MENU: module sub-menu
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_channels_submenu', '_bx_channels_menu_title_submenu', 'bx_channels_submenu', 'bx_channels', 8, 0, 1, '', '');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_channels_submenu', 'bx_channels', '_bx_channels_menu_set_title_submenu', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('bx_channels_submenu', 'bx_channels', 'channels-home', '_bx_channels_menu_item_title_system_entries_recent', '_bx_channels_menu_item_title_entries_recent', 'page.php?i=channels-home', '', '', '', '', 2147483647, 1, 1, 1),
+('bx_channels_submenu', 'bx_channels', 'channels-top', '_bx_channels_menu_item_title_system_entries_top', '_bx_channels_menu_item_title_entries_top', 'page.php?i=channels-top', '', '', '', '', 2147483647, 1, 1, 2),
+('bx_channels_submenu', 'bx_channels', 'channels-toplevel', '_bx_channels_menu_item_title_system_entries_toplevel', '_bx_channels_menu_item_title_entries_toplevel', 'page.php?i=channels-toplevel', '', '', '', '', 2147483647, 1, 1, 3),
+('bx_channels_submenu', 'bx_channels', 'channels-search', '_bx_channels_menu_item_title_system_entries_search', '_bx_channels_menu_item_title_entries_search', 'page.php?i=channels-search', '', '', '', '', 2147483647, 1, 1, 4);
+-- MENU: custom menu for snippet meta info
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_channels_snippet_meta', '_sys_menu_title_snippet_meta', 'bx_channels_snippet_meta', 'bx_channels', 15, 0, 1, 'BxCnlMenuSnippetMeta', 'modules/boonex/channels/classes/BxCnlMenuSnippetMeta.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_channels_snippet_meta', 'bx_channels', '_sys_menu_set_title_snippet_meta', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `editable`, `order`) VALUES
+('bx_channels_snippet_meta', 'bx_channels', 'date', '_sys_menu_item_title_system_sm_date', '_sys_menu_item_title_sm_date', '', '', '', '', '', 2147483647, 0, 0, 1, 1),
+('bx_channels_snippet_meta', 'bx_channels', 'tags', '_sys_menu_item_title_system_sm_tags', '_sys_menu_item_title_sm_tags', '', '', '', '', '', 2147483647, 0, 0, 1, 2),
+('bx_channels_snippet_meta', 'bx_channels', 'views', '_sys_menu_item_title_system_sm_views', '_sys_menu_item_title_sm_views', '', '', '', '', '', 2147483647, 0, 0, 1, 3),
+('bx_channels_snippet_meta', 'bx_channels', 'comments', '_sys_menu_item_title_system_sm_comments', '_sys_menu_item_title_sm_comments', '', '', '', '', '', 2147483647, 0, 0, 1, 4),
+('bx_channels_snippet_meta', 'bx_channels', 'members', '_sys_menu_item_title_system_sm_members', '_sys_menu_item_title_sm_members', '', '', '', '', '', 2147483647, 1, 0, 1, 5),
+('bx_channels_snippet_meta', 'bx_channels', 'subscribers', '_sys_menu_item_title_system_sm_subscribers', '_sys_menu_item_title_sm_subscribers', '', '', '', '', '', 2147483647, 1, 0, 1, 6),
+('bx_channels_snippet_meta', 'bx_channels', 'nl', '_sys_menu_item_title_system_sm_nl', '_sys_menu_item_title_sm_nl', '', '', '', '', '', 2147483647, 1, 0, 1, 7),
+('bx_channels_snippet_meta', 'bx_channels', 'subscribe', '_sys_menu_item_title_system_sm_subscribe', '_sys_menu_item_title_sm_subscribe', '', '', '', '', '', 2147483647, 1, 0, 1, 8),
+('bx_channels_snippet_meta', 'bx_channels', 'unsubscribe', '_sys_menu_item_title_system_sm_unsubscribe', '_sys_menu_item_title_sm_unsubscribe', '', '', '', '', '', 2147483647, 1, 0, 1, 9);
+
+-- MENU: manage tools submenu
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_channels_menu_manage_tools', '_bx_channels_menu_title_manage_tools', 'bx_channels_menu_manage_tools', 'bx_channels', 6, 0, 1, 'BxCnlMenuManageTools', 'modules/boonex/channels/classes/BxCnlMenuManageTools.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_channels_menu_manage_tools', 'bx_channels', '_bx_channels_menu_set_title_manage_tools', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('bx_channels_menu_manage_tools', 'bx_channels', 'delete', '_bx_channels_menu_item_title_system_delete', '_bx_channels_menu_item_title_delete', 'javascript:void(0)', 'javascript:{js_object}.onClickDelete({content_id});', '_self', 'far trash-alt', '', 2147483647, 1, 0, 1),
+('bx_channels_menu_manage_tools', 'bx_channels', 'delete-with-content', '_bx_channels_menu_item_title_system_delete_with_content', '_bx_channels_menu_item_title_delete_with_content', 'javascript:void(0)', 'javascript:{js_object}.onClickDeleteWithContent({content_id});', '_self', 'far trash-alt', '', 2147483647, 1, 0, 2);
+
+-- MENU: dashboard manage tools
+SET @iManageMenuOrder = (SELECT IFNULL(MAX(`order`), 0) FROM `sys_menu_items` WHERE `set_name`='sys_account_dashboard_manage_tools' LIMIT 1);
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `addon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('sys_account_dashboard_manage_tools', 'bx_channels', 'channels-administration', '_bx_channels_menu_item_title_system_admt_channels', '_bx_channels_menu_item_title_admt_channels', 'page.php?i=channels-administration', '', '_self', 'hashtag', 'a:2:{s:6:"module";s:11:"bx_channels";s:6:"method";s:27:"get_menu_addon_manage_tools";}', '', 128, 1, 0, @iManageMenuOrder + 1);
+
+-- MENU: add menu item to profiles modules (trigger* menu sets are processed separately upon modules enable/disable)
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('trigger_profile_view_submenu', 'bx_channels', 'channels-author', '_bx_channels_menu_item_title_system_view_entries_author', '_bx_channels_menu_item_title_view_entries_author', 'page.php?i=channels-author&profile_id={profile_id}', '', '', 'hashtag col-red2', '', 2147483647, 1, 0, 0);
+
+
+-- ACL
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_channels', 'delete entry', NULL, '_bx_channels_acl_action_delete_profile', '', 1, 1);
+SET @iIdActionProfileDelete = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_channels', 'view entry', NULL, '_bx_channels_acl_action_view_profile', '', 1, 0);
+SET @iIdActionProfileView = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_channels', 'edit any entry', NULL, '_bx_channels_acl_action_edit_any_profile', '', 1, 3);
+SET @iIdActionProfileEditAny = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_channels', 'create channel auto', NULL, '_bx_channels_acl_action_create_channel_auto', '_bx_channels_acl_action_create_channel_auto_info', 1, 1);
+
+SET @iIdActionCreateChannelAuto = LAST_INSERT_ID();
+
+SET @iUnauthenticated = 1;
+SET @iAccount = 2;
+SET @iStandard = 3;
+SET @iUnconfirmed = 4;
+SET @iPending = 5;
+SET @iSuspended = 6;
+SET @iModerator = 7;
+SET @iAdministrator = 8;
+SET @iPremium = 9;
+
+INSERT INTO `sys_acl_matrix` (`IDLevel`, `IDAction`) VALUES
+
+-- profile delete
+(@iAdministrator, @iIdActionProfileDelete),
+
+-- profile view
+(@iUnauthenticated, @iIdActionProfileView),
+(@iAccount, @iIdActionProfileView),
+(@iStandard, @iIdActionProfileView),
+(@iUnconfirmed, @iIdActionProfileView),
+(@iPending, @iIdActionProfileView),
+(@iModerator, @iIdActionProfileView),
+(@iAdministrator, @iIdActionProfileView),
+(@iPremium, @iIdActionProfileView),
+
+-- any profile edit
+(@iModerator, @iIdActionProfileEditAny),
+(@iAdministrator, @iIdActionProfileEditAny),
+
+-- create channel auto
+(@iAccount, @iIdActionCreateChannelAuto),
+(@iStandard, @iIdActionCreateChannelAuto),
+(@iUnconfirmed, @iIdActionCreateChannelAuto),
+(@iPending, @iIdActionCreateChannelAuto),
+(@iModerator, @iIdActionCreateChannelAuto),
+(@iAdministrator, @iIdActionCreateChannelAuto),
+(@iPremium, @iIdActionCreateChannelAuto);
+
+
+-- METATAGS
+INSERT INTO `sys_objects_metatags` (`object`, `table_keywords`, `table_locations`, `table_mentions`, `override_class_name`, `override_class_file`) VALUES
+('bx_channels', 'bx_cnl_meta_keywords', '', 'bx_cnl_meta_mentions', '', '');
+
+-- SEARCH
+SET @iSearchOrder = (SELECT IFNULL(MAX(`Order`), 0) FROM `sys_objects_search`);
+INSERT INTO `sys_objects_search` (`ObjectName`, `Title`, `Order`, `ClassName`, `ClassPath`) VALUES
+('bx_channels', '_bx_channels', @iSearchOrder + 1, 'BxCnlSearchResult', 'modules/boonex/channels/classes/BxCnlSearchResult.php');
+
+-- STATS
+SET @iMaxOrderStats = (SELECT IFNULL(MAX(`order`), 0) FROM `sys_statistics`);
+INSERT INTO `sys_statistics` (`module`, `name`, `title`, `link`, `icon`, `query`, `order`) VALUES 
+('bx_channels', 'bx_channels', '_bx_channels', 'page.php?i=channels-home', 'hashtag col-red2', 'SELECT COUNT(*) FROM `bx_cnl_data` AS `td` LEFT JOIN `sys_profiles` AS `tp` ON `td`.`id` = `tp`.`content_id` AND `tp`.`type`=''bx_channels'' WHERE 1 AND `tp`.`status`=''active''', @iMaxOrderStats + 1);
+
+-- CHARTS
+SET @iMaxOrderCharts = (SELECT IFNULL(MAX(`order`), 0) FROM `sys_objects_chart`);
+INSERT INTO `sys_objects_chart` (`object`, `title`, `table`, `field_date_ts`, `field_date_dt`, `field_status`, `query`, `active`, `order`, `class_name`, `class_file`) VALUES
+('bx_channels_growth', '_bx_channels_chart_growth', 'bx_cnl_data', 'added', '', '', 'SELECT {field_date_formatted} AS `period`, COUNT(*) AS {object} FROM {table} LEFT JOIN `sys_profiles` AS `tp` ON {table}.`id` = `tp`.`content_id` AND `tp`.`type`=''bx_channels'' WHERE 1 AND `tp`.`status`=''active'' {where_inteval} GROUP BY `period` ORDER BY {table}.{field_date} ASC', 1, @iMaxOrderCharts + 1, 'BxDolChartGrowth', ''),
+('bx_channels_growth_speed', '_bx_channels_chart_growth_speed', 'bx_cnl_data', 'added', '', '', 'SELECT {field_date_formatted} AS `period`, COUNT(*) AS {object} FROM {table} LEFT JOIN `sys_profiles` AS `tp` ON {table}.`id` = `tp`.`content_id` AND `tp`.`type`=''bx_channels'' WHERE 1 AND `tp`.`status`=''active'' {where_inteval} GROUP BY `period` ORDER BY {table}.{field_date} ASC', 1, @iMaxOrderCharts + 2, 'BxDolChartGrowthSpeed', '');
+
+-- GRIDS: administration
+
+INSERT INTO `sys_objects_grid` (`object`, `source_type`, `source`, `table`, `field_id`, `field_order`, `field_active`, `paginate_url`, `paginate_per_page`, `paginate_simple`, `paginate_get_start`, `paginate_get_per_page`, `filter_fields`, `filter_fields_translatable`, `filter_mode`, `sorting_fields`, `sorting_fields_translatable`, `visible_for_levels`, `override_class_name`, `override_class_file`) VALUES
+('bx_channels_administration', 'Sql', 'SELECT `td`.*, `td`.`channel_name` AS `name`, `ta`.`email` AS `account`, `td`.`added` AS `added_ts`, `tp`.`status` AS `status` FROM `bx_cnl_data` AS `td` LEFT JOIN `sys_profiles` AS `tp` ON `td`.`id`=`tp`.`content_id` AND `tp`.`type`=''bx_channels'' LEFT JOIN `sys_accounts` AS `ta` ON `tp`.`account_id`=`ta`.`id` WHERE 1 ', 'bx_cnl_data', 'id', 'added', 'status', '', 20, NULL, 'start', '', 'channel_name', '', 'like', 'reports', '', 192, 'BxCnlGridAdministration', 'modules/boonex/channels/classes/BxCnlGridAdministration.php');
+
+INSERT INTO `sys_grid_fields` (`object`, `name`, `title`, `width`, `translatable`, `chars_limit`, `params`, `order`) VALUES
+('bx_channels_administration', 'checkbox', '_sys_select', '2%', 0, '', '', 1),
+('bx_channels_administration', 'switcher', '_bx_channels_grid_column_title_adm_active', '8%', 0, '', '', 2),
+('bx_channels_administration', 'reports', '_sys_txt_reports_title', '5%', 0, '', '', 3),
+('bx_channels_administration', 'name', '_bx_channels_grid_column_title_adm_name', '45%', 0, '', '', 4),
+('bx_channels_administration', 'added_ts', '_bx_channels_grid_column_title_adm_added', '20%', 1, '25', '', 5),
+('bx_channels_administration', 'actions', '', '20%', 0, '', '', 6);
+
+INSERT INTO `sys_grid_actions` (`object`, `type`, `name`, `title`, `icon`, `icon_only`, `confirm`, `order`) VALUES
+('bx_channels_administration', 'bulk', 'delete', '_bx_channels_grid_action_title_adm_delete', '', 0, 1, 2),
+('bx_channels_administration', 'bulk', 'delete_with_content', '_bx_channels_grid_action_title_adm_delete_with_content', '', 0, 1, 3),
+('bx_channels_administration', 'single', 'settings', '_bx_channels_grid_action_title_adm_more_actions', 'cog', 1, 0, 2),
+('bx_channels_administration', 'single', 'audit_content', '_bx_channels_grid_action_title_adm_audit_content', 'search', 1, 0, 3),
+('bx_channels_administration', 'single', 'audit_profile', '_bx_channels_grid_action_title_adm_audit_context', 'search-location', 1, 0, 4);
+
+
+-- ALERTS
+
+INSERT INTO `sys_alerts_handlers` (`name`, `class`, `file`, `service_call`) VALUES 
+('bx_channels', 'BxCnlAlertsResponse', 'modules/boonex/channels/classes/BxCnlAlertsResponse.php', '');
+SET @iHandler := LAST_INSERT_ID();
+
+INSERT INTO `sys_alerts` (`unit`, `action`, `handler_id`) VALUES
+('system', 'save_setting', @iHandler),
+('bx_timeline', 'post_common', @iHandler),
+('bx_channels_pics', 'file_deleted', @iHandler),
+('profile', 'delete', @iHandler),
+('bx_channels', 'timeline_view', @iHandler),
+('bx_channels', 'timeline_post', @iHandler),
+('bx_channels', 'timeline_delete', @iHandler),
+('bx_channels', 'timeline_comment', @iHandler),
+('bx_channels', 'timeline_vote', @iHandler),
+('bx_channels', 'timeline_score', @iHandler),
+('bx_channels', 'timeline_report', @iHandler),
+('bx_channels', 'timeline_repost', @iHandler),
+('bx_channels', 'timeline_pin', @iHandler),
+('bx_channels', 'timeline_promote', @iHandler),
+('bx_persons', 'added', @iHandler),
+('bx_persons', 'edited', @iHandler),
+('bx_organizations', 'added', @iHandler),
+('bx_organizations', 'edited', @iHandler),
+('meta_keyword', 'added', @iHandler),
+('meta_keyword', 'url', @iHandler),
+('meta_keyword', 'deleted', @iHandler);
+
+
+-- PRIVACY 
+
+INSERT INTO `sys_objects_privacy` (`object`, `module`, `action`, `title`, `default_group`, `spaces`, `table`, `table_field_id`, `table_field_author`, `override_class_name`, `override_class_file`) VALUES
+('bx_channels_allow_view_to', 'bx_channels', 'view', '_bx_channels_form_profile_input_allow_view_to', '3', '', 'bx_cnl_data', 'id', 'author', 'BxCnlPrivacy', 'modules/boonex/channels/classes/BxCnlPrivacy.php'),
+('bx_channels_allow_view_notification_to', 'bx_channels', 'view_event', '_bx_channels_form_profile_input_allow_view_notification_to', '3', '', 'bx_notifications_events', 'id', 'object_owner_id', 'BxCnlPrivacyNotifications', 'modules/boonex/channels/classes/BxCnlPrivacyNotifications.php');
+
+
+-- UPLOADERS
+
+INSERT INTO `sys_objects_uploader` (`object`, `active`, `override_class_name`, `override_class_file`) VALUES
+('bx_channels_cover_crop', 1, 'BxCnlUploaderCoverCrop', 'modules/boonex/channels/classes/BxCnlUploaderCoverCrop.php'),
+('bx_channels_picture_crop', 1, 'BxCnlUploaderPictureCrop', 'modules/boonex/channels/classes/BxCnlUploaderPictureCrop.php');

+ 295 - 0
modules/boonex/channels/updates/12.0.0_12.0.1/source/install/sql/install.sql

@@ -0,0 +1,295 @@
+SET @sStorageEngine = (SELECT `value` FROM `sys_options` WHERE `name` = 'sys_storage_default');
+
+-- TABLE: PROFILES
+CREATE TABLE IF NOT EXISTS `bx_cnl_data` (
+  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+  `author` int(10) unsigned NOT NULL,
+  `added` int(11) NOT NULL,
+  `changed` int(11) NOT NULL,
+  `picture` int(11) NOT NULL,
+  `cover` int(11) NOT NULL,
+  `channel_name` varchar(191) NOT NULL,
+  `views` int(11) NOT NULL default '0',
+  `rate` float NOT NULL default '0',
+  `votes` int(11) NOT NULL default '0',
+  `score` int(11) NOT NULL default '0',
+  `sc_up` int(11) NOT NULL default '0',
+  `sc_down` int(11) NOT NULL default '0',
+  `favorites` int(11) NOT NULL default '0',
+  `comments` int(11) NOT NULL default '0',
+  `reports` int(11) NOT NULL default '0',
+  `featured` int(11) NOT NULL default '0',
+  `allow_view_to` varchar(255) DEFAULT '3',
+  `status` enum('active','awaiting','hidden') NOT NULL DEFAULT 'active',
+  PRIMARY KEY (`id`),
+  UNIQUE INDEX channel_name (`channel_name`),
+  FULLTEXT KEY `search_fields` (`channel_name`)
+);
+
+-- TABLE: items
+CREATE TABLE IF NOT EXISTS `bx_cnl_content` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `content_id` int(11) NOT NULL,
+  `cnl_id` int(11) NOT NULL,
+  `author_id` int(11) NOT NULL,
+  `module_name` varchar(19) NOT NULL,
+  PRIMARY KEY (`id`)
+);
+
+-- TABLE: STORAGES & TRANSCODERS
+CREATE TABLE `bx_cnl_pics` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `profile_id` int(10) unsigned NOT NULL,
+  `remote_id` varchar(128) NOT NULL,
+  `path` varchar(255) NOT NULL,
+  `file_name` varchar(255) NOT NULL,
+  `mime_type` varchar(128) NOT NULL,
+  `ext` varchar(32) NOT NULL,
+  `size` bigint(20) NOT NULL,
+  `added` int(11) NOT NULL,
+  `modified` int(11) NOT NULL,
+  `private` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `remote_id` (`remote_id`)
+);
+
+CREATE TABLE `bx_cnl_pics_resized` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `profile_id` int(10) unsigned NOT NULL,
+  `remote_id` varchar(128) NOT NULL,
+  `path` varchar(255) NOT NULL,
+  `file_name` varchar(255) NOT NULL,
+  `mime_type` varchar(128) NOT NULL,
+  `ext` varchar(32) NOT NULL,
+  `size` bigint(20) NOT NULL,
+  `added` int(11) NOT NULL,
+  `modified` int(11) NOT NULL,
+  `private` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `remote_id` (`remote_id`)
+);
+
+-- TABLE: comments
+CREATE TABLE IF NOT EXISTS `bx_cnl_cmts` (
+  `cmt_id` int(11) NOT NULL AUTO_INCREMENT,
+  `cmt_parent_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_vparent_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_object_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_author_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_level` int(11) NOT NULL DEFAULT '0',
+  `cmt_text` text NOT NULL,
+  `cmt_mood` tinyint(4) NOT NULL DEFAULT '0',
+  `cmt_rate` int(11) NOT NULL DEFAULT '0',
+  `cmt_rate_count` int(11) NOT NULL DEFAULT '0',
+  `cmt_time` int(11) unsigned NOT NULL DEFAULT '0',
+  `cmt_replies` int(11) NOT NULL DEFAULT '0',
+  `cmt_pinned` int(11) NOT NULL default '0',
+  PRIMARY KEY (`cmt_id`),
+  KEY `cmt_object_id` (`cmt_object_id`,`cmt_parent_id`),
+  FULLTEXT KEY `search_fields` (`cmt_text`)
+);
+
+-- TABLE: VIEWS
+CREATE TABLE `bx_cnl_views_track` (
+  `object_id` int(11) NOT NULL default '0',
+  `viewer_id` int(11) NOT NULL default '0',
+  `viewer_nip` int(11) unsigned NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  KEY `id` (`object_id`,`viewer_id`,`viewer_nip`)
+);
+
+-- TABLE: VOTES
+CREATE TABLE IF NOT EXISTS `bx_cnl_votes` (
+  `object_id` int(11) NOT NULL default '0',
+  `count` int(11) NOT NULL default '0',
+  `sum` int(11) NOT NULL default '0',
+  UNIQUE KEY `object_id` (`object_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_cnl_votes_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `author_nip` int(11) unsigned NOT NULL default '0',
+  `value` tinyint(4) NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `vote` (`object_id`, `author_nip`)
+);
+
+-- TABLE: REPORTS
+CREATE TABLE IF NOT EXISTS `bx_cnl_reports` (
+  `object_id` int(11) NOT NULL default '0',
+  `count` int(11) NOT NULL default '0',
+  UNIQUE KEY `object_id` (`object_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_cnl_reports_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `author_nip` int(11) unsigned NOT NULL default '0',
+  `type` varchar(32) NOT NULL default '',
+  `text` text NOT NULL default '',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `report` (`object_id`, `author_nip`)
+);
+
+-- TABLE: metas
+CREATE TABLE `bx_cnl_meta_keywords` (
+  `object_id` int(10) unsigned NOT NULL,
+  `keyword` varchar(255) NOT NULL,
+  KEY `object_id` (`object_id`),
+  KEY `keyword` (`keyword`)
+);
+
+CREATE TABLE `bx_cnl_meta_mentions` (
+  `object_id` int(10) unsigned NOT NULL,
+  `profile_id` int(10) unsigned NOT NULL,
+  KEY `object_id` (`object_id`),
+  KEY `profile_id` (`profile_id`)
+);
+
+
+-- TABLE: favorites
+CREATE TABLE `bx_cnl_favorites_track` (
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  KEY `id` (`object_id`,`author_id`)
+);
+
+-- TABLE: scores
+CREATE TABLE IF NOT EXISTS `bx_cnl_scores` (
+  `object_id` int(11) NOT NULL default '0',
+  `count_up` int(11) NOT NULL default '0',
+  `count_down` int(11) NOT NULL default '0',
+  UNIQUE KEY `object_id` (`object_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_cnl_scores_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `author_nip` int(11) unsigned NOT NULL default '0',
+  `type` varchar(8) NOT NULL default '',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `vote` (`object_id`, `author_nip`)
+);
+
+
+-- STORAGES & TRANSCODERS
+INSERT INTO `sys_objects_storage` (`object`, `engine`, `params`, `token_life`, `cache_control`, `levels`, `table_files`, `ext_mode`, `ext_allow`, `ext_deny`, `quota_size`, `current_size`, `quota_number`, `current_number`, `max_file_size`, `ts`) VALUES
+('bx_channels_pics', @sStorageEngine, '', 360, 2592000, 3, 'bx_cnl_pics', 'allow-deny', 'jpg,jpeg,jpe,gif,png', '', 0, 0, 0, 0, 0, 0),
+('bx_channels_pics_resized', @sStorageEngine, '', 360, 2592000, 3, 'bx_cnl_pics_resized', 'allow-deny', 'jpg,jpeg,jpe,gif,png', '', 0, 0, 0, 0, 0, 0);
+
+INSERT INTO `sys_objects_transcoder` (`object`, `storage_object`, `source_type`, `source_params`, `private`, `atime_tracking`, `atime_pruning`, `ts`) VALUES 
+('bx_channels_icon', 'bx_channels_pics_resized', 'Storage', 'a:1:{s:6:"object";s:16:"bx_channels_pics";}', 'no', '1', '2592000', '0'),
+('bx_channels_thumb', 'bx_channels_pics_resized', 'Storage', 'a:1:{s:6:"object";s:16:"bx_channels_pics";}', 'no', '1', '2592000', '0'),
+('bx_channels_avatar', 'bx_channels_pics_resized', 'Storage', 'a:1:{s:6:"object";s:16:"bx_channels_pics";}', 'no', '1', '2592000', '0'),
+('bx_channels_avatar_big', 'bx_channels_pics_resized', 'Storage', 'a:1:{s:6:"object";s:16:"bx_channels_pics";}', 'no', '1', '2592000', '0'),
+('bx_channels_picture', 'bx_channels_pics_resized', 'Storage', 'a:1:{s:6:"object";s:16:"bx_channels_pics";}', 'no', '1', '2592000', '0'),
+('bx_channels_cover', 'bx_channels_pics_resized', 'Storage', 'a:1:{s:6:"object";s:16:"bx_channels_pics";}', 'no', '1', '2592000', '0'),
+('bx_channels_cover_thumb', 'bx_channels_pics_resized', 'Storage', 'a:1:{s:6:"object";s:16:"bx_channels_pics";}', 'no', '1', '2592000', '0'),
+('bx_channels_gallery', 'bx_channels_pics_resized', 'Storage', 'a:1:{s:6:"object";s:16:"bx_channels_pics";}', 'no', '1', '2592000', '0');
+
+INSERT INTO `sys_transcoder_filters` (`transcoder_object`, `filter`, `filter_params`, `order`) VALUES 
+('bx_channels_icon', 'Resize', 'a:3:{s:1:"w";s:2:"30";s:1:"h";s:2:"30";s:13:"square_resize";s:1:"1";}', '0'),
+('bx_channels_thumb', 'Resize', 'a:3:{s:1:"w";s:2:"50";s:1:"h";s:2:"50";s:13:"square_resize";s:1:"1";}', '0'),
+('bx_channels_avatar', 'Resize', 'a:3:{s:1:"w";s:3:"100";s:1:"h";s:3:"100";s:13:"square_resize";s:1:"1";}', '0'),
+('bx_channels_avatar_big', 'Resize', 'a:3:{s:1:"w";s:3:"200";s:1:"h";s:3:"200";s:13:"square_resize";s:1:"1";}', '0'),
+('bx_channels_picture', 'Resize', 'a:3:{s:1:"w";s:4:"1024";s:1:"h";s:4:"1024";s:13:"square_resize";s:1:"0";}', '0'),
+('bx_channels_cover', 'Resize', 'a:1:{s:1:"w";s:4:"2000";}', '0'),
+('bx_channels_cover_thumb', 'Resize', 'a:3:{s:1:"w";s:2:"48";s:1:"h";s:2:"48";s:13:"square_resize";s:1:"1";}', '0'),
+('bx_channels_gallery', 'Resize', 'a:1:{s:1:"w";s:3:"500";}', '0');
+
+-- FORMS
+INSERT INTO `sys_objects_form`(`object`, `module`, `title`, `action`, `form_attrs`, `table`, `key`, `uri`, `uri_title`, `submit_name`, `params`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_channel', 'bx_channels', '_bx_channels_form_profile', '', 'a:1:{s:7:\"enctype\";s:19:\"multipart/form-data\";}', 'bx_cnl_data', 'id', '', '', 'do_submit', '', 0, 1, 'BxCnlFormEntry', 'modules/boonex/channels/classes/BxCnlFormEntry.php');
+
+INSERT INTO `sys_form_displays`(`object`, `display_name`, `module`, `view_mode`, `title`) VALUES 
+('bx_channel', 'bx_channel_add', 'bx_channels', 0, '_bx_channels_form_profile_display_add'),
+('bx_channel', 'bx_channel_delete', 'bx_channels', 0, '_bx_channels_form_profile_display_delete'),
+('bx_channel', 'bx_channel_edit', 'bx_channels', 0, '_bx_channels_form_profile_display_edit'),
+('bx_channel', 'bx_channel_edit_cover', 'bx_channels', 0, '_bx_channels_form_profile_display_edit_cover'),
+('bx_channel', 'bx_channel_view', 'bx_channels', 1, '_bx_channels_form_profile_display_view'),
+('bx_channel', 'bx_channel_view_full', 'bx_channels', 1, '_bx_channels_form_profile_display_view_full');
+
+INSERT INTO `sys_form_inputs`(`object`, `module`, `name`, `value`, `values`, `checked`, `type`, `caption_system`, `caption`, `info`, `required`, `collapsed`, `html`, `attrs`, `attrs_tr`, `attrs_wrapper`, `checker_func`, `checker_params`, `checker_error`, `db_pass`, `db_params`, `editable`, `deletable`) VALUES 
+('bx_channel', 'bx_channels', 'delete_confirm', 1, '', 0, 'checkbox', '_bx_channels_form_profile_input_sys_delete_confirm', '_bx_channels_form_profile_input_delete_confirm', '_bx_channels_form_profile_input_delete_confirm_info', 1, 0, 0, '', '', '', 'avail', '', '_bx_channels_form_profile_input_delete_confirm_error', '', '', 1, 0),
+('bx_channel', 'bx_channels', 'do_submit', '_sys_form_account_input_submit', '', 0, 'submit', '_bx_channels_form_profile_input_sys_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_channel', 'bx_channels', 'channel_name', '', '', 0, 'text', '_bx_channels_form_profile_input_sys_channel_name', '_bx_channels_form_profile_input_channel_name', '', 1, 0, 0, '', '', '', 'avail', '', '_bx_channels_form_profile_input_channel_name_err', 'Xss', '', 1, 0),
+('bx_channel', 'bx_channels', 'cover', 'a:1:{i:0;s:22:"bx_channels_cover_crop";}', 'a:1:{s:22:"bx_channels_cover_crop";s:24:"_sys_uploader_crop_title";}', 0, 'files', '_bx_channels_form_profile_input_sys_cover', '_bx_channels_form_profile_input_cover', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_channel', 'bx_channels', 'picture', 'a:1:{i:0;s:24:"bx_channels_picture_crop";}', 'a:1:{s:24:"bx_channels_picture_crop";s:24:"_sys_uploader_crop_title";}', 0, 'files', '_bx_channels_form_profile_input_sys_picture', '_bx_channels_form_profile_input_picture', '', 0, 0, 0, '', '', '', '', '', '_bx_channels_form_profile_input_picture_err', '', '', 1, 0);
+
+INSERT INTO `sys_form_display_inputs`(`display_name`, `input_name`, `visible_for_levels`, `active`, `order`) VALUES 
+('bx_channel_add', 'channel_name', 2147483647, 1, 1),
+('bx_channel_add', 'do_submit', 2147483647, 1, 2),
+
+('bx_channel_delete', 'delete_confirm', 2147483647, 1, 0),
+('bx_channel_delete', 'do_submit', 2147483647, 1, 1),
+
+('bx_channel_edit', 'channel_name', 2147483647, 1, 1),
+('bx_channel_edit', 'do_submit', 2147483647, 1, 2),
+
+('bx_channel_edit_cover', 'cover', 2147483647, 1, 1),
+('bx_channel_edit_cover', 'do_submit', 2147483647, 1, 2),
+
+('bx_channel_view', 'channel_name', 2147483647, 1, 1),
+
+('bx_channel_view_full', 'channel_name', 2147483647, 1, 1);
+
+-- COMMENTS
+INSERT INTO `sys_objects_cmts` (`Name`, `Module`, `Table`, `CharsPostMin`, `CharsPostMax`, `CharsDisplayMax`, `Html`, `PerView`, `PerViewReplies`, `BrowseType`, `IsBrowseSwitch`, `PostFormPosition`, `NumberOfLevels`, `IsDisplaySwitch`, `IsRatable`, `ViewingThreshold`, `IsOn`, `RootStylePrefix`, `BaseUrl`, `ObjectVote`, `TriggerTable`, `TriggerFieldId`, `TriggerFieldAuthor`, `TriggerFieldTitle`, `TriggerFieldComments`, `ClassName`, `ClassFile`) VALUES
+('bx_channels', 'bx_channels', 'bx_cnl_cmts', 1, 5000, 1000, 3, 5, 3, 'tail', 1, 'bottom', 1, 1, 1, -3, 1, 'cmt', 'page.php?i=view-channel-profile&id={object_id}', '', 'bx_cnl_data', 'id', 'author', 'channel_name', 'comments', '', '');
+
+-- VIEWS
+INSERT INTO `sys_objects_view` (`name`, `table_track`, `period`, `is_on`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_count`, `class_name`, `class_file`) VALUES 
+('bx_channels', 'bx_cnl_views_track', '86400', '1', 'bx_cnl_data', 'id', 'author', 'views', '', '');
+
+-- VOTES
+INSERT INTO `sys_objects_vote` (`Name`, `TableMain`, `TableTrack`, `PostTimeout`, `MinValue`, `MaxValue`, `IsUndo`, `IsOn`, `TriggerTable`, `TriggerFieldId`, `TriggerFieldAuthor`, `TriggerFieldRate`, `TriggerFieldRateCount`, `ClassName`, `ClassFile`) VALUES 
+('bx_channels', 'bx_cnl_votes', 'bx_cnl_votes_track', '604800', '1', '1', '0', '1', 'bx_cnl_data', 'id', 'author', 'rate', 'votes', '', '');
+
+-- SCORES
+INSERT INTO `sys_objects_score` (`name`, `module`, `table_main`, `table_track`, `post_timeout`, `is_on`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_score`, `trigger_field_cup`, `trigger_field_cdown`, `class_name`, `class_file`) VALUES 
+('bx_channels', 'bx_channels', 'bx_cnl_scores', 'bx_cnl_scores_track', '604800', '0', 'bx_cnl_data', 'id', 'author', 'score', 'sc_up', 'sc_down', '', '');
+
+-- REPORTS
+INSERT INTO `sys_objects_report` (`name`, `module`, `table_main`, `table_track`, `is_on`, `base_url`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_count`, `class_name`, `class_file`) VALUES 
+('bx_channels', 'bx_channels', 'bx_cnl_reports', 'bx_cnl_reports_track', '1', 'page.php?i=view-channel-profile&id={object_id}', 'bx_cnl_data', 'id', 'author', 'reports', '', '');
+
+-- FAFORITES
+INSERT INTO `sys_objects_favorite` (`name`, `table_track`, `is_on`, `is_undo`, `is_public`, `base_url`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_count`, `class_name`, `class_file`) VALUES 
+('bx_channels', 'bx_cnl_favorites_track', '1', '1', '1', 'page.php?i=view-channel-profile&id={object_id}', 'bx_cnl_data', 'id', 'author', 'favorites', '', '');
+
+-- FEATURED
+INSERT INTO `sys_objects_feature` (`name`, `module`, `is_on`, `is_undo`, `base_url`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_flag`, `class_name`, `class_file`) VALUES 
+('bx_channels', 'bx_channels', '1', '1', 'page.php?i=view-channel-profile&id={object_id}', 'bx_cnl_data', 'id', 'author', 'featured', '', '');
+
+-- CONTENT INFO
+INSERT INTO `sys_objects_content_info` (`name`, `title`, `alert_unit`, `alert_action_add`, `alert_action_update`, `alert_action_delete`, `class_name`, `class_file`) VALUES
+('bx_channels', '_bx_channels', 'bx_channels', 'added', 'edited', 'deleted', '', ''),
+('bx_channels_cmts', '_bx_channels_cmts', 'bx_channels', 'commentPost', 'commentUpdated', 'commentRemoved', 'BxDolContentInfoCmts', '');
+
+INSERT INTO `sys_content_info_grids` (`object`, `grid_object`, `grid_field_id`, `condition`, `selection`) VALUES
+('bx_channels', 'bx_channels_administration', 'td`.`id', '', '');
+
+-- SEARCH EXTENDED
+INSERT INTO `sys_objects_search_extended` (`object`, `object_content_info`, `module`, `title`, `active`, `class_name`, `class_file`) VALUES
+('bx_channels', 'bx_channels', 'bx_channels', '_bx_channels_search_extended', 1, '', ''),
+('bx_channels_cmts', 'bx_channels_cmts', 'bx_channels', '_bx_channels_search_extended_cmts', 1, 'BxTemplSearchExtendedCmts', '');
+
+-- STUDIO PAGE & WIDGET
+INSERT INTO `sys_std_pages`(`index`, `name`, `header`, `caption`, `icon`) VALUES
+(3, 'bx_channels', '_bx_channels', '_bx_channels', 'bx_channels@modules/boonex/channels/|std-icon.svg');
+SET @iPageId = LAST_INSERT_ID();
+
+SET @iParentPageId = (SELECT `id` FROM `sys_std_pages` WHERE `name` = 'home');
+SET @iParentPageOrder = (SELECT MAX(`order`) FROM `sys_std_pages_widgets` WHERE `page_id` = @iParentPageId);
+INSERT INTO `sys_std_widgets` (`page_id`, `module`, `type`, `url`, `click`, `icon`, `caption`, `cnt_notices`, `cnt_actions`) VALUES
+(@iPageId, 'bx_channels', 'extensions', '{url_studio}module.php?name=bx_channels', '', 'bx_channels@modules/boonex/channels/|std-icon.svg', '_bx_channels', 'a:4:{s:6:"module";s:11:"bx_channels";s:6:"method";s:18:"get_widget_notices";s:6:"params";a:0:{}s:5:"class";s:6:"Module";}', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:11:"get_actions";s:6:"params";a:0:{}s:5:"class";s:18:"TemplStudioModules";}');
+INSERT INTO `sys_std_pages_widgets` (`page_id`, `widget_id`, `order`) VALUES
+(@iParentPageId, LAST_INSERT_ID(), IF(ISNULL(@iParentPageOrder), 1, @iParentPageOrder + 1));

+ 51 - 0
modules/boonex/classes/updates/12.0.1_12.0.2/install/config.php

@@ -0,0 +1,51 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'title' => 'Classes',
+    'version_from' => '12.0.1',
+    'version_to' => '12.0.2',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '12.1.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/classes/updates/update_12.0.1_12.0.2/',
+    'home_uri' => 'classes_update_1201_1202',
+
+    'module_dir' => 'boonex/classes/',
+    'module_uri' => 'classes',
+
+    'db_prefix' => 'bx_classes_',
+    'class_prefix' => 'BxClss',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_files' => 1,
+        'update_languages' => 0,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Classes',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

+ 23 - 0
modules/boonex/classes/updates/12.0.1_12.0.2/install/installer.php

@@ -0,0 +1,23 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+class BxClssUpdater extends BxDolStudioUpdater
+{
+    function __construct($aConfig)
+    {
+        parent::__construct($aConfig);
+    }
+
+    public function actionExecuteSql($sOperation)
+    {
+        if($sOperation == 'install') {
+            if(!$this->oDb->isFieldExists('bx_classes_videos', 'dimensions'))
+                $this->oDb->query("ALTER TABLE `bx_classes_videos` ADD `dimensions` varchar(12) NOT NULL AFTER `size`");
+        }
+
+        return parent::actionExecuteSql($sOperation);
+    }
+}

+ 2 - 0
modules/boonex/classes/updates/12.0.1_12.0.2/install/sql/install.sql

@@ -0,0 +1,2 @@
+-- STORAGES & TRANSCODERS
+UPDATE `sys_objects_storage` SET `params`='a:1:{s:6:"fields";a:1:{s:10:"dimensions";s:17:"getFileDimensions";}}' WHERE `object`='bx_classes_videos';

+ 152 - 0
modules/boonex/classes/updates/12.0.1_12.0.2/source/install/config.php

@@ -0,0 +1,152 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Classes Classes
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_classes',
+    'title' => 'Classes',
+    'note' => 'Classes module.',
+    'version' => '12.0.2',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '12.1.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/classes/',
+    'home_uri' => 'classes',
+
+    'db_prefix' => 'bx_classes_',
+    'class_prefix' => 'BxClss',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Classes',
+
+    /**
+     * List of page triggers.
+     */
+    'page_triggers' => array (
+    	'trigger_page_group_view_entry',
+    ),
+    
+    /**
+     * Menu triggers.
+     */
+    'menu_triggers' => array(
+        'trigger_group_view_submenu',
+    ),
+
+    /**
+     * Storage objects to automatically delete files from upon module uninstallation.
+     * Note. Don't add storage objects used in transcoder objects.
+     */
+    'storages' => array(
+        'bx_classes_covers',
+    	'bx_classes_photos',
+        'bx_classes_videos',
+        'bx_classes_sounds',
+        'bx_classes_files'
+    ),
+
+    /**
+     * Transcoders.
+     */
+    'transcoders' => array(
+        'bx_classes_preview',
+        'bx_classes_gallery',
+        'bx_classes_cover',
+
+        'bx_classes_preview_photos',
+        'bx_classes_gallery_photos', 
+
+        'bx_classes_videos_poster',
+        'bx_classes_videos_poster_preview',
+        'bx_classes_videos_mp4',
+        'bx_classes_videos_mp4_hd',
+
+        'bx_classes_sounds_mp3',
+
+        'bx_classes_preview_files',
+        'bx_classes_gallery_files'
+    ),
+
+    /**
+     * Extended Search Forms.
+     */
+    'esearches' => array(
+        'bx_classes',
+    	'bx_classes_cmts'
+    ),
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'uninstall' => array (
+    	'process_esearches' => 1,
+        'execute_sql' => 1,
+        'update_languages' => 1,
+        'update_relations' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'enable' => array(
+        'execute_sql' => 1,
+        'update_relations' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'enable_success' => array(
+        'process_menu_triggers' => 1,
+        'process_page_triggers' => 1,
+    	'process_esearches' => 1,
+        'register_transcoders' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable' => array (
+        'execute_sql' => 1,
+        'update_relations' => 1,
+        'unregister_transcoders' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable_failed' => array (
+        'register_transcoders' => 1,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Dependencies Section
+     */
+    'dependencies' => array(),
+
+    /**
+     * Relations Section
+     */
+    'relations' => array(
+    	'bx_timeline',
+    	'bx_notifications'
+    ),
+
+);
+
+/** @} */

+ 641 - 0
modules/boonex/classes/updates/12.0.1_12.0.2/source/install/sql/install.sql

@@ -0,0 +1,641 @@
+-- TABLE: entries
+CREATE TABLE IF NOT EXISTS `bx_classes_classes` (
+  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+  `author` int(11) NOT NULL,
+  `added` int(11) NOT NULL,
+  `changed` int(11) NOT NULL,  
+  `published` int(11) NOT NULL,
+  `module_id` int(10) unsigned NOT NULL,
+  `order` int(11) NOT NULL,
+  `start_date` int(11) NOT NULL,
+  `end_date` int(11) NOT NULL,
+  `thumb` int(11) NOT NULL,
+  `title` varchar(255) NOT NULL,
+  `avail` int(11) NOT NULL,
+  `cmts` int(11) NOT NULL,
+  `completed_when` int(11) NOT NULL,
+  `text` mediumtext NOT NULL,
+  `labels` text NOT NULL,
+  `location` text NOT NULL,
+  `views` int(11) NOT NULL default '0',
+  `rate` float NOT NULL default '0',
+  `votes` int(11) NOT NULL default '0',
+  `rrate` float NOT NULL default '0',
+  `rvotes` int(11) NOT NULL default '0',
+  `score` int(11) NOT NULL default '0',
+  `sc_up` int(11) NOT NULL default '0',
+  `sc_down` int(11) NOT NULL default '0',
+  `favorites` int(11) NOT NULL default '0',
+  `comments` int(11) NOT NULL default '0',
+  `reports` int(11) NOT NULL default '0',
+  `featured` int(11) NOT NULL default '0',
+  `allow_view_to` varchar(16) NOT NULL DEFAULT '3',
+  `status` enum('active','awaiting','failed','hidden') NOT NULL DEFAULT 'active',
+  `status_admin` enum('active','hidden') NOT NULL DEFAULT 'active',
+  PRIMARY KEY (`id`),
+  FULLTEXT KEY `title_text` (`title`,`text`)
+);
+
+-- TABLE: modules
+CREATE TABLE IF NOT EXISTS `bx_classes_modules` (
+  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+  `profile_id` int(10) unsigned NOT NULL,
+  `module_title` varchar(255) NOT NULL,
+  `author` int(11) NOT NULL,
+  `added` int(11) NOT NULL,
+  `changed` int(11) NOT NULL,
+  `order` int(11) NOT NULL,
+  PRIMARY KEY (`id`)
+);
+
+-- TABLE: status
+CREATE TABLE IF NOT EXISTS `bx_classes_statuses` (
+  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+  `class_id` int(10) unsigned NOT NULL,
+  `student_profile_id` int(11) NOT NULL,
+  `viewed` int(11) NOT NULL,
+  `replied` int(11) NOT NULL,
+  `completed` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE `class_student` (`class_id`,`student_profile_id`)
+);
+
+-- TABLE: storages & transcoders
+CREATE TABLE IF NOT EXISTS `bx_classes_covers` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `profile_id` int(10) unsigned NOT NULL,
+  `remote_id` varchar(128) NOT NULL,
+  `path` varchar(255) NOT NULL,
+  `file_name` varchar(255) NOT NULL,
+  `mime_type` varchar(128) NOT NULL,
+  `ext` varchar(32) NOT NULL,
+  `size` bigint(20) NOT NULL,
+  `added` int(11) NOT NULL,
+  `modified` int(11) NOT NULL,
+  `private` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `remote_id` (`remote_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_classes_files` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `profile_id` int(10) unsigned NOT NULL,
+  `remote_id` varchar(128) NOT NULL,
+  `path` varchar(255) NOT NULL,
+  `file_name` varchar(255) NOT NULL,
+  `mime_type` varchar(128) NOT NULL,
+  `ext` varchar(32) NOT NULL,
+  `size` bigint(20) NOT NULL,
+  `added` int(11) NOT NULL,
+  `modified` int(11) NOT NULL,
+  `private` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `remote_id` (`remote_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_classes_photos` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `profile_id` int(10) unsigned NOT NULL,
+  `remote_id` varchar(128) NOT NULL,
+  `path` varchar(255) NOT NULL,
+  `file_name` varchar(255) NOT NULL,
+  `mime_type` varchar(128) NOT NULL,
+  `ext` varchar(32) NOT NULL,
+  `size` bigint(20) NOT NULL,
+  `added` int(11) NOT NULL,
+  `modified` int(11) NOT NULL,
+  `private` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `remote_id` (`remote_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_classes_photos_resized` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `profile_id` int(10) unsigned NOT NULL,
+  `remote_id` varchar(128) NOT NULL,
+  `path` varchar(255) NOT NULL,
+  `file_name` varchar(255) NOT NULL,
+  `mime_type` varchar(128) NOT NULL,
+  `ext` varchar(32) NOT NULL,
+  `size` bigint(20) NOT NULL,
+  `added` int(11) NOT NULL,
+  `modified` int(11) NOT NULL,
+  `private` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `remote_id` (`remote_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_classes_videos` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `profile_id` int(10) unsigned NOT NULL,
+  `remote_id` varchar(128) NOT NULL,
+  `path` varchar(255) NOT NULL,
+  `file_name` varchar(255) NOT NULL,
+  `mime_type` varchar(128) NOT NULL,
+  `ext` varchar(32) NOT NULL,
+  `size` bigint(20) NOT NULL,
+  `dimensions` varchar(12) NOT NULL,
+  `added` int(11) NOT NULL,
+  `modified` int(11) NOT NULL,
+  `private` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `remote_id` (`remote_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_classes_videos_resized` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `profile_id` int(10) unsigned NOT NULL,
+  `remote_id` varchar(128) NOT NULL,
+  `path` varchar(255) NOT NULL,
+  `file_name` varchar(255) NOT NULL,
+  `mime_type` varchar(128) NOT NULL,
+  `ext` varchar(32) NOT NULL,
+  `size` bigint(20) NOT NULL,
+  `added` int(11) NOT NULL,
+  `modified` int(11) NOT NULL,
+  `private` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `remote_id` (`remote_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_classes_sounds` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `profile_id` int(10) unsigned NOT NULL,
+  `remote_id` varchar(128) NOT NULL,
+  `path` varchar(255) NOT NULL,
+  `file_name` varchar(255) NOT NULL,
+  `mime_type` varchar(128) NOT NULL,
+  `ext` varchar(32) NOT NULL,
+  `size` bigint(20) NOT NULL,
+  `added` int(11) NOT NULL,
+  `modified` int(11) NOT NULL,
+  `private` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `remote_id` (`remote_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_classes_sounds_resized` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `profile_id` int(10) unsigned NOT NULL,
+  `remote_id` varchar(128) NOT NULL,
+  `path` varchar(255) NOT NULL,
+  `file_name` varchar(255) NOT NULL,
+  `mime_type` varchar(128) NOT NULL,
+  `ext` varchar(32) NOT NULL,
+  `size` bigint(20) NOT NULL,
+  `added` int(11) NOT NULL,
+  `modified` int(11) NOT NULL,
+  `private` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `remote_id` (`remote_id`)
+);
+
+-- TABLE: comments
+CREATE TABLE IF NOT EXISTS `bx_classes_cmts` (
+  `cmt_id` int(11) NOT NULL AUTO_INCREMENT,
+  `cmt_parent_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_vparent_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_object_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_author_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_level` int(11) NOT NULL DEFAULT '0',
+  `cmt_text` text NOT NULL,
+  `cmt_mood` tinyint(4) NOT NULL DEFAULT '0',
+  `cmt_rate` int(11) NOT NULL DEFAULT '0',
+  `cmt_rate_count` int(11) NOT NULL DEFAULT '0',
+  `cmt_time` int(11) unsigned NOT NULL DEFAULT '0',
+  `cmt_replies` int(11) NOT NULL DEFAULT '0',
+  `cmt_pinned` int(11) NOT NULL default '0',
+  PRIMARY KEY (`cmt_id`),
+  KEY `cmt_object_id` (`cmt_object_id`,`cmt_parent_id`),
+  FULLTEXT KEY `search_fields` (`cmt_text`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_classes_cmts_notes` (
+  `cmt_id` int(11) NOT NULL AUTO_INCREMENT,
+  `cmt_parent_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_vparent_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_object_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_author_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_level` int(11) NOT NULL DEFAULT '0',
+  `cmt_text` text NOT NULL,
+  `cmt_mood` tinyint(4) NOT NULL DEFAULT '0',
+  `cmt_rate` int(11) NOT NULL DEFAULT '0',
+  `cmt_rate_count` int(11) NOT NULL DEFAULT '0',
+  `cmt_time` int(11) unsigned NOT NULL DEFAULT '0',
+  `cmt_replies` int(11) NOT NULL DEFAULT '0',
+  `cmt_pinned` int(11) NOT NULL default '0',
+  PRIMARY KEY (`cmt_id`),
+  KEY `cmt_object_id` (`cmt_object_id`,`cmt_parent_id`),
+  FULLTEXT KEY `search_fields` (`cmt_text`)
+);
+
+-- TABLE: votes
+CREATE TABLE IF NOT EXISTS `bx_classes_votes` (
+  `object_id` int(11) NOT NULL default '0',
+  `count` int(11) NOT NULL default '0',
+  `sum` int(11) NOT NULL default '0',
+  UNIQUE KEY `object_id` (`object_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_classes_votes_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `author_nip` int(11) unsigned NOT NULL default '0',
+  `value` tinyint(4) NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `vote` (`object_id`, `author_nip`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_classes_reactions` (
+  `object_id` int(11) NOT NULL default '0',
+  `reaction` varchar(32) NOT NULL default '',
+  `count` int(11) NOT NULL default '0',
+  `sum` int(11) NOT NULL default '0',
+  UNIQUE KEY `reaction` (`object_id`, `reaction`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_classes_reactions_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `author_nip` int(11) unsigned NOT NULL default '0',
+  `reaction` varchar(32) NOT NULL default '',
+  `value` tinyint(4) NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `vote` (`object_id`, `author_nip`)
+);
+
+-- TABLE: views
+CREATE TABLE `bx_classes_views_track` (
+  `object_id` int(11) NOT NULL default '0',
+  `viewer_id` int(11) NOT NULL default '0',
+  `viewer_nip` int(11) unsigned NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  KEY `id` (`object_id`,`viewer_id`,`viewer_nip`)
+);
+
+-- TABLE: metas
+CREATE TABLE `bx_classes_meta_keywords` (
+  `object_id` int(10) unsigned NOT NULL,
+  `keyword` varchar(255) NOT NULL,
+  KEY `object_id` (`object_id`),
+  KEY `keyword` (`keyword`)
+);
+
+CREATE TABLE `bx_classes_meta_mentions` (
+  `object_id` int(10) unsigned NOT NULL,
+  `profile_id` int(10) unsigned NOT NULL,
+  KEY `object_id` (`object_id`),
+  KEY `profile_id` (`profile_id`)
+);
+
+CREATE TABLE `bx_classes_meta_locations` (
+  `object_id` int(10) unsigned NOT NULL,
+  `lat` double NOT NULL,
+  `lng` double NOT NULL,
+  `country` varchar(2) NOT NULL,
+  `state` varchar(255) NOT NULL,
+  `city` varchar(255) NOT NULL,
+  `zip` varchar(255) NOT NULL,
+  `street` varchar(255) NOT NULL,
+  `street_number` varchar(255) NOT NULL,
+  PRIMARY KEY (`object_id`),
+  KEY `country_state_city` (`country`,`state`(8),`city`(8))
+);
+
+-- TABLE: reports
+CREATE TABLE IF NOT EXISTS `bx_classes_reports` (
+  `object_id` int(11) NOT NULL default '0',
+  `count` int(11) NOT NULL default '0',
+  UNIQUE KEY `object_id` (`object_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_classes_reports_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `author_nip` int(11) unsigned NOT NULL default '0',
+  `type` varchar(32) NOT NULL default '',
+  `text` text NOT NULL default '',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `report` (`object_id`, `author_nip`)
+);
+
+-- TABLE: favorites
+CREATE TABLE `bx_classes_favorites_track` (
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  KEY `id` (`object_id`,`author_id`)
+);
+
+-- TABLE: scores
+CREATE TABLE IF NOT EXISTS `bx_classes_scores` (
+  `object_id` int(11) NOT NULL default '0',
+  `count_up` int(11) NOT NULL default '0',
+  `count_down` int(11) NOT NULL default '0',
+  UNIQUE KEY `object_id` (`object_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_classes_scores_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `author_nip` int(11) unsigned NOT NULL default '0',
+  `type` varchar(8) NOT NULL default '',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `vote` (`object_id`, `author_nip`)
+);
+
+-- TABLE: polls
+CREATE TABLE IF NOT EXISTS `bx_classes_polls` (
+  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+  `author_id` int(11) NOT NULL default '0',
+  `content_id` int(11) NOT NULL default '0',
+  `text` text NOT NULL,
+  PRIMARY KEY (`id`),
+  KEY `content_id` (`content_id`),
+  FULLTEXT KEY `search_fields` (`text`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_classes_polls_answers` (
+  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+  `poll_id` int(11) unsigned NOT NULL default '0',
+  `title` varchar(255) NOT NULL,
+  `rate` float NOT NULL default '0',
+  `votes` int(11) NOT NULL default '0',
+  `order` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `poll_id` (`poll_id`),
+  FULLTEXT KEY `title` (`title`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_classes_polls_answers_votes` (
+  `object_id` int(11) NOT NULL default '0',
+  `count` int(11) NOT NULL default '0',
+  `sum` int(11) NOT NULL default '0',
+  UNIQUE KEY `object_id` (`object_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_classes_polls_answers_votes_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `author_nip` int(11) unsigned NOT NULL default '0',
+  `value` tinyint(4) NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `vote` (`object_id`, `author_nip`)
+);
+
+-- STORAGES & TRANSCODERS
+SET @sStorageEngine = (SELECT `value` FROM `sys_options` WHERE `name` = 'sys_storage_default');
+
+INSERT INTO `sys_objects_storage` (`object`, `engine`, `params`, `token_life`, `cache_control`, `levels`, `table_files`, `ext_mode`, `ext_allow`, `ext_deny`, `quota_size`, `current_size`, `quota_number`, `current_number`, `max_file_size`, `ts`) VALUES
+('bx_classes_covers', @sStorageEngine, '', 360, 2592000, 3, 'bx_classes_covers', 'allow-deny', 'jpg,jpeg,jpe,gif,png', '', 0, 0, 0, 0, 0, 0),
+
+('bx_classes_photos', @sStorageEngine, '', 360, 2592000, 3, 'bx_classes_photos', 'allow-deny', 'jpg,jpeg,jpe,gif,png', '', 0, 0, 0, 0, 0, 0),
+('bx_classes_photos_resized', @sStorageEngine, '', 360, 2592000, 3, 'bx_classes_photos_resized', 'allow-deny', 'jpg,jpeg,jpe,gif,png', '', 0, 0, 0, 0, 0, 0),
+
+('bx_classes_videos', @sStorageEngine, 'a:1:{s:6:"fields";a:1:{s:10:"dimensions";s:17:"getFileDimensions";}}', 360, 2592000, 3, 'bx_classes_videos', 'allow-deny', 'avi,flv,mpg,mpeg,wmv,mp4,m4v,mov,qt,divx,xvid,3gp,3g2,webm,mkv,ogv,ogg,rm,rmvb,asf,drc', '', 0, 0, 0, 0, 0, 0),
+('bx_classes_videos_resized', @sStorageEngine, '', 360, 2592000, 3, 'bx_classes_videos_resized', 'allow-deny', 'jpg,jpeg,jpe,gif,png,avi,flv,mpg,mpeg,wmv,mp4,m4v,mov,qt,divx,xvid,3gp,3g2,webm,mkv,ogv,ogg,rm,rmvb,asf,drc', '', 0, 0, 0, 0, 0, 0),
+
+('bx_classes_sounds', @sStorageEngine, '', 360, 2592000, 3, 'bx_classes_sounds', 'allow-deny', 'mp3,m4a,m4b,wma,wav,3gp', '', 0, 0, 0, 0, 0, 0),
+('bx_classes_sounds_resized', @sStorageEngine, '', 360, 2592000, 3, 'bx_classes_sounds_resized', 'allow-deny', 'mp3,m4a,m4b,wma,wav,3gp', '', 0, 0, 0, 0, 0, 0),
+
+('bx_classes_files', @sStorageEngine, '', 360, 2592000, 3, 'bx_classes_files', 'deny-allow', '', 'action,apk,app,bat,bin,cmd,com,command,cpl,csh,exe,gadget,inf,ins,inx,ipa,isu,job,jse,ksh,lnk,msc,msi,msp,mst,osx,out,paf,pif,prg,ps1,reg,rgs,run,sct,shb,shs,u3p,vb,vbe,vbs,vbscript,workflow,ws,wsf', 0, 0, 0, 0, 0, 0);
+
+INSERT INTO `sys_objects_transcoder` (`object`, `storage_object`, `source_type`, `source_params`, `private`, `atime_tracking`, `atime_pruning`, `ts`, `override_class_name`, `override_class_file`) VALUES 
+('bx_classes_preview', 'bx_classes_photos_resized', 'Storage', 'a:1:{s:6:"object";s:17:"bx_classes_covers";}', 'no', '1', '2592000', '0', '', ''),
+('bx_classes_gallery', 'bx_classes_photos_resized', 'Storage', 'a:1:{s:6:"object";s:17:"bx_classes_covers";}', 'no', '1', '2592000', '0', '', ''),
+('bx_classes_cover', 'bx_classes_photos_resized', 'Storage', 'a:1:{s:6:"object";s:17:"bx_classes_covers";}', 'no', '1', '2592000', '0', '', ''),
+
+('bx_classes_preview_photos', 'bx_classes_photos_resized', 'Storage', 'a:1:{s:6:"object";s:17:"bx_classes_photos";}', 'no', '1', '2592000', '0', '', ''),
+('bx_classes_gallery_photos', 'bx_classes_photos_resized', 'Storage', 'a:1:{s:6:"object";s:17:"bx_classes_photos";}', 'no', '1', '2592000', '0', '', ''),
+
+('bx_classes_videos_poster', 'bx_classes_videos_resized', 'Storage', 'a:1:{s:6:"object";s:17:"bx_classes_videos";}', 'no', '0', '0', '0', 'BxDolTranscoderVideo', ''),
+('bx_classes_videos_poster_preview', 'bx_classes_videos_resized', 'Storage', 'a:1:{s:6:"object";s:17:"bx_classes_videos";}', 'no', '0', '0', '0', 'BxDolTranscoderVideo', ''),
+('bx_classes_videos_mp4', 'bx_classes_videos_resized', 'Storage', 'a:1:{s:6:"object";s:17:"bx_classes_videos";}', 'no', '0', '0', '0', 'BxDolTranscoderVideo', ''),
+('bx_classes_videos_mp4_hd', 'bx_classes_videos_resized', 'Storage', 'a:1:{s:6:"object";s:17:"bx_classes_videos";}', 'no', '0', '0', '0', 'BxDolTranscoderVideo', ''),
+
+('bx_classes_sounds_mp3', 'bx_classes_sounds_resized', 'Storage', 'a:1:{s:6:"object";s:17:"bx_classes_sounds";}', 'no', '0', '0', '0', 'BxDolTranscoderAudio', ''),
+
+('bx_classes_preview_files', 'bx_classes_photos_resized', 'Storage', 'a:1:{s:6:"object";s:16:"bx_classes_files";}', 'no', '1', '2592000', '0', '', ''),
+('bx_classes_gallery_files', 'bx_classes_photos_resized', 'Storage', 'a:1:{s:6:"object";s:16:"bx_classes_files";}', 'no', '1', '2592000', '0', '', '');
+
+INSERT INTO `sys_transcoder_filters` (`transcoder_object`, `filter`, `filter_params`, `order`) VALUES 
+('bx_classes_preview', 'Resize', 'a:3:{s:1:"w";s:3:"300";s:1:"h";s:3:"200";s:11:"crop_resize";s:1:"1";}', '0'),
+('bx_classes_gallery', 'Resize', 'a:1:{s:1:"w";s:3:"500";}', '0'),
+('bx_classes_cover', 'Resize', 'a:1:{s:1:"w";s:4:"2000";}', '0'),
+
+('bx_classes_preview_photos', 'Resize', 'a:3:{s:1:"w";s:3:"300";s:1:"h";s:3:"200";s:11:"crop_resize";s:1:"1";}', '0'),
+('bx_classes_gallery_photos', 'Resize', 'a:1:{s:1:"w";s:4:"2000";}', '0'),
+
+('bx_classes_videos_poster_preview', 'Resize', 'a:3:{s:1:"w";s:3:"300";s:1:"h";s:3:"200";s:13:"square_resize";s:1:"1";}', 10),
+('bx_classes_videos_poster_preview', 'Poster', 'a:2:{s:1:"h";s:3:"480";s:10:"force_type";s:3:"jpg";}', 0),
+('bx_classes_videos_poster', 'Poster', 'a:2:{s:1:"h";s:3:"318";s:10:"force_type";s:3:"jpg";}', 0),
+('bx_classes_videos_mp4', 'Mp4', 'a:2:{s:1:"h";s:3:"318";s:10:"force_type";s:3:"mp4";}', 0),
+('bx_classes_videos_mp4_hd', 'Mp4', 'a:3:{s:1:"h";s:3:"720";s:13:"video_bitrate";s:4:"1536";s:10:"force_type";s:3:"mp4";}', 0),
+
+('bx_classes_sounds_mp3', 'Mp3', 'a:0:{}', 0),
+
+('bx_classes_preview_files', 'Resize', 'a:3:{s:1:"w";s:3:"300";s:1:"h";s:3:"200";s:11:"crop_resize";s:1:"1";}', '0'),
+('bx_classes_gallery_files', 'Resize', 'a:1:{s:1:"w";s:3:"500";}', '0');
+
+
+-- FORMS: entry (post)
+INSERT INTO `sys_objects_form`(`object`, `module`, `title`, `action`, `form_attrs`, `table`, `key`, `uri`, `uri_title`, `submit_name`, `params`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_classes', 'bx_classes', '_bx_classes_form_entry', '', 'a:1:{s:7:"enctype";s:19:"multipart/form-data";}', 'bx_classes_classes', 'id', '', '', 'a:2:{i:0;s:9:"do_submit";i:1;s:10:"do_publish";}', '', 0, 1, 'BxClssFormEntry', 'modules/boonex/classes/classes/BxClssFormEntry.php');
+
+INSERT INTO `sys_form_displays`(`object`, `display_name`, `module`, `view_mode`, `title`) VALUES 
+('bx_classes', 'bx_classes_entry_add', 'bx_classes', 0, '_bx_classes_form_entry_display_add'),
+('bx_classes', 'bx_classes_entry_delete', 'bx_classes', 0, '_bx_classes_form_entry_display_delete'),
+('bx_classes', 'bx_classes_entry_edit', 'bx_classes', 0, '_bx_classes_form_entry_display_edit'),
+('bx_classes', 'bx_classes_entry_view', 'bx_classes', 1, '_bx_classes_form_entry_display_view');
+
+INSERT INTO `sys_form_inputs`(`object`, `module`, `name`, `value`, `values`, `checked`, `type`, `caption_system`, `caption`, `info`, `required`, `collapsed`, `html`, `attrs`, `attrs_tr`, `attrs_wrapper`, `checker_func`, `checker_params`, `checker_error`, `db_pass`, `db_params`, `editable`, `deletable`) VALUES 
+('bx_classes', 'bx_classes', 'allow_view_to', '', '', 0, 'custom', '_bx_classes_form_entry_input_sys_allow_view_to', '_bx_classes_form_entry_input_allow_view_to', '', 1, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_classes', 'bx_classes', 'delete_confirm', 1, '', 0, 'checkbox', '_bx_classes_form_entry_input_sys_delete_confirm', '_bx_classes_form_entry_input_delete_confirm', '_bx_classes_form_entry_input_delete_confirm_info', 1, 0, 0, '', '', '', 'Avail', '', '_bx_classes_form_entry_input_delete_confirm_error', '', '', 1, 0),
+('bx_classes', 'bx_classes', 'do_publish', '_bx_classes_form_entry_input_do_publish', '', 0, 'submit', '_bx_classes_form_entry_input_sys_do_publish', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_classes', 'bx_classes', 'do_submit', '_bx_classes_form_entry_input_do_submit', '', 0, 'submit', '_bx_classes_form_entry_input_sys_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_classes', 'bx_classes', 'location', '', '', 0, 'location', '_sys_form_input_sys_location', '_sys_form_input_location', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_classes', 'bx_classes', 'covers', 'a:1:{i:0;s:16:"bx_classes_html5";}', 'a:2:{s:17:"bx_classes_simple";s:26:"_sys_uploader_simple_title";s:16:"bx_classes_html5";s:25:"_sys_uploader_html5_title";}', 0, 'files', '_bx_classes_form_entry_input_sys_covers', '_bx_classes_form_entry_input_covers', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_classes', 'bx_classes', 'pictures', 'a:1:{i:0;s:23:"bx_classes_photos_html5";}', 'a:2:{s:24:"bx_classes_photos_simple";s:26:"_sys_uploader_simple_title";s:23:"bx_classes_photos_html5";s:25:"_sys_uploader_html5_title";}', 0, 'files', '_bx_classes_form_entry_input_sys_pictures', '_bx_classes_form_entry_input_pictures', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_classes', 'bx_classes', 'videos', 'a:2:{i:0;s:23:"bx_classes_videos_html5";i:1;s:30:"bx_classes_videos_record_video";}', 'a:3:{s:24:"bx_classes_videos_simple";s:26:"_sys_uploader_simple_title";s:23:"bx_classes_videos_html5";s:25:"_sys_uploader_html5_title";s:30:"bx_classes_videos_record_video";s:32:"_sys_uploader_record_video_title";}', 0, 'files', '_bx_classes_form_entry_input_sys_videos', '_bx_classes_form_entry_input_videos', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_classes', 'bx_classes', 'sounds', 'a:1:{i:0;s:23:"bx_classes_sounds_html5";}', 'a:2:{s:24:"bx_classes_sounds_simple";s:26:"_sys_uploader_simple_title";s:23:"bx_classes_sounds_html5";s:25:"_sys_uploader_html5_title";}', 0, 'files', '_bx_classes_form_entry_input_sys_sounds', '_bx_classes_form_entry_input_sounds', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_classes', 'bx_classes', 'files', 'a:1:{i:0;s:22:"bx_classes_files_html5";}', 'a:2:{s:23:"bx_classes_files_simple";s:26:"_sys_uploader_simple_title";s:22:"bx_classes_files_html5";s:25:"_sys_uploader_html5_title";}', 0, 'files', '_bx_classes_form_entry_input_sys_files', '_bx_classes_form_entry_input_files', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_classes', 'bx_classes', 'polls', '', '', 0, 'custom', '_bx_classes_form_entry_input_sys_polls', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_classes', 'bx_classes', 'text', '', '', 0, 'textarea', '_bx_classes_form_entry_input_sys_text', '_bx_classes_form_entry_input_text', '', 1, 0, 2, '', '', '', 'Avail', '', '_bx_classes_form_entry_input_text_err', 'XssHtml', '', 1, 0),
+('bx_classes', 'bx_classes', 'title', '', '', 0, 'text', '_bx_classes_form_entry_input_sys_title', '_bx_classes_form_entry_input_title', '', 1, 0, 0, '', '', '', 'Avail', '', '_bx_classes_form_entry_input_title_err', 'Xss', '', 1, 0),
+('bx_classes', 'bx_classes', 'avail', '', '#!bx_classes_avail', 0, 'select', '', '_bx_classes_form_entry_input_avail', '', 1, 0, 0, '', '', '', '', '', '', 'Int', '', 1, 0),
+('bx_classes', 'bx_classes', 'cmts', '2', '#!bx_classes_cmts', 0, 'select', '', '_bx_classes_form_entry_input_cmts', '', 1, 0, 0, '', '', '', '', '', '', 'Int', '', 1, 0),
+('bx_classes', 'bx_classes', 'completed_when', '', '#!bx_classes_completed_when', 0, 'select', '', '_bx_classes_form_entry_input_completed_when', '', 1, 0, 0, '', '', '', '', '', '', 'Int', '', 1, 0),
+('bx_classes', 'bx_classes', 'module_id', '', '', 0, 'select', '', '_bx_classes_form_entry_input_module', '', 1, 0, 0, '', '', '', '', '', '', 'Int', '', 1, 0),
+('bx_classes', 'bx_classes', 'added', '', '', 0, 'datetime', '_bx_classes_form_entry_input_sys_date_added', '_bx_classes_form_entry_input_date_added', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_classes', 'bx_classes', 'changed', '', '', 0, 'datetime', '_bx_classes_form_entry_input_sys_date_changed', '_bx_classes_form_entry_input_date_changed', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_classes', 'bx_classes', 'start_date', '', '', 0, 'datetime', '', '_bx_classes_form_entry_input_date_start_date', '', 0, 0, 0, '', '', '', '', '', '', 'DateTimeUtc', '', 1, 0),
+('bx_classes', 'bx_classes', 'end_date', '', '', 0, 'datetime', '', '_bx_classes_form_entry_input_date_end_date', '', 0, 0, 0, '', '', '', '', '', '', 'DateTimeUtc', '', 1, 0),
+('bx_classes', 'bx_classes', 'attachments', '', '', 0, 'custom', '_bx_classes_form_entry_input_sys_attachments', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_classes', 'bx_classes', 'labels', '', '', 0, 'custom', '_sys_form_input_sys_labels', '_sys_form_input_labels', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_classes', 'bx_classes', 'anonymous', '', '', 0, 'switcher', '_sys_form_input_sys_anonymous', '_sys_form_input_anonymous', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0);
+
+
+
+INSERT INTO `sys_form_display_inputs`(`display_name`, `input_name`, `visible_for_levels`, `active`, `order`) VALUES 
+('bx_classes_entry_add', 'covers', 2147483647, 1, 1),
+('bx_classes_entry_add', 'module_id', 2147483647, 1, 2),
+('bx_classes_entry_add', 'title', 2147483647, 1, 3),
+('bx_classes_entry_add', 'text', 2147483647, 1, 4),
+('bx_classes_entry_add', 'attachments', 2147483647, 1, 5),
+('bx_classes_entry_add', 'pictures', 2147483647, 1, 6),
+('bx_classes_entry_add', 'videos', 2147483647, 1, 7),
+('bx_classes_entry_add', 'sounds', 2147483647, 1, 8),
+('bx_classes_entry_add', 'files', 2147483647, 1, 9),
+('bx_classes_entry_add', 'polls', 2147483647, 1, 10),
+('bx_classes_entry_add', 'start_date', 2147483647, 1, 11),
+('bx_classes_entry_add', 'end_date', 2147483647, 1, 12),
+('bx_classes_entry_add', 'completed_when', 2147483647, 1, 13),
+('bx_classes_entry_add', 'avail', 2147483647, 1, 14),
+('bx_classes_entry_add', 'cmts', 2147483647, 1, 15),
+('bx_classes_entry_add', 'allow_view_to', 2147483647, 1, 16),
+('bx_classes_entry_add', 'do_publish', 2147483647, 1, 17),
+
+('bx_classes_entry_delete', 'delete_confirm', 2147483647, 1, 1),
+('bx_classes_entry_delete', 'do_submit', 2147483647, 1, 2),
+
+('bx_classes_entry_edit', 'covers', 2147483647, 1, 1),
+('bx_classes_entry_edit', 'module_id', 2147483647, 1, 2),
+('bx_classes_entry_edit', 'title', 2147483647, 1, 3),
+('bx_classes_entry_edit', 'text', 2147483647, 1, 4),
+('bx_classes_entry_edit', 'attachments', 2147483647, 1, 5),
+('bx_classes_entry_edit', 'pictures', 2147483647, 1, 6),
+('bx_classes_entry_edit', 'videos', 2147483647, 1, 7),
+('bx_classes_entry_edit', 'sounds', 2147483647, 1, 8),
+('bx_classes_entry_edit', 'files', 2147483647, 1, 9),
+('bx_classes_entry_edit', 'polls', 2147483647, 1, 10),
+('bx_classes_entry_edit', 'start_date', 2147483647, 1, 11),
+('bx_classes_entry_edit', 'end_date', 2147483647, 1, 12),
+('bx_classes_entry_edit', 'completed_when', 2147483647, 1, 13),
+('bx_classes_entry_edit', 'avail', 2147483647, 1, 14),
+('bx_classes_entry_edit', 'cmts', 2147483647, 1, 15),
+('bx_classes_entry_edit', 'allow_view_to', 2147483647, 1, 16),
+('bx_classes_entry_edit', 'do_submit', 2147483647, 1, 17),
+
+('bx_classes_entry_view', 'module_id', 2147483647, 1, 1),
+('bx_classes_entry_view', 'completed_when', 2147483647, 1, 2),
+('bx_classes_entry_view', 'added', 2147483647, 1, 3),
+('bx_classes_entry_view', 'changed', 2147483647, 1, 4),
+('bx_classes_entry_view', 'start_date', 2147483647, 1, 5),
+('bx_classes_entry_view', 'end_date', 2147483647, 1, 6);
+
+-- FORMS: poll
+INSERT INTO `sys_objects_form` (`object`, `module`, `title`, `action`, `form_attrs`, `submit_name`, `table`, `key`, `uri`, `uri_title`, `params`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES
+('bx_classes_poll', 'bx_classes', '_bx_classes_form_poll', '', '', 'do_submit', 'bx_classes_polls', 'id', '', '', 'a:1:{s:14:"checker_helper";s:27:"BxClssFormPollCheckerHelper";}', 0, 1, 'BxClssFormPoll', 'modules/boonex/classes/classes/BxClssFormPoll.php');
+
+INSERT INTO `sys_form_displays` (`display_name`, `module`, `object`, `title`, `view_mode`) VALUES
+('bx_classes_poll_add', 'bx_classes', 'bx_classes_poll', '_bx_classes_form_poll_display_add', 0);
+
+INSERT INTO `sys_form_inputs` (`object`, `module`, `name`, `value`, `values`, `checked`, `type`, `caption_system`, `caption`, `info`, `required`, `collapsed`, `html`, `attrs`, `attrs_tr`, `attrs_wrapper`, `checker_func`, `checker_params`, `checker_error`, `db_pass`, `db_params`, `editable`, `deletable`) VALUES
+('bx_classes_poll', 'bx_classes', 'text', '', '', 0, 'text', '_bx_classes_form_poll_input_sys_text', '_bx_classes_form_poll_input_text', '', 1, 0, 0, '', '', '', 'Avail', '', '_bx_classes_form_poll_input_text_err', 'Xss', '', 1, 0),
+('bx_classes_poll', 'bx_classes', 'answers', '', '', 0, 'custom', '_bx_classes_form_poll_input_sys_answers', '_bx_classes_form_poll_input_answers', '', 1, 0, 0, '', '', '', 'AvailAnswers', '', '_bx_classes_form_poll_input_answers_err', '', '', 1, 0),
+('bx_classes_poll', 'bx_classes', 'controls', '', 'do_submit,do_cancel', 0, 'input_set', '', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
+('bx_classes_poll', 'bx_classes', 'do_submit', '_bx_classes_form_poll_input_do_submit', '', 0, 'submit', '_bx_classes_form_poll_input_sys_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
+('bx_classes_poll', 'bx_classes', 'do_cancel', '_bx_classes_form_poll_input_do_cancel', '', 0, 'button', '_bx_classes_form_poll_input_do_cancel', '', '', 0, 0, 0, 'a:2:{s:7:"onclick";s:45:"$(''.bx-popup-applied:visible'').dolPopupHide()";s:5:"class";s:22:"bx-def-margin-sec-left";}', '', '', '', '', '', '', '', 0, 0);
+
+INSERT INTO `sys_form_display_inputs` (`display_name`, `input_name`, `visible_for_levels`, `active`, `order`) VALUES
+('bx_classes_poll_add', 'text', 2147483647, 1, 1),
+('bx_classes_poll_add', 'answers', 2147483647, 1, 2),
+('bx_classes_poll_add', 'controls', 2147483647, 1, 3),
+('bx_classes_poll_add', 'do_submit', 2147483647, 1, 4),
+('bx_classes_poll_add', 'do_cancel', 2147483647, 1, 5);
+
+-- PRE-VALUES
+
+INSERT INTO `sys_form_pre_lists`(`key`, `title`, `module`, `use_for_sets`) VALUES
+('bx_classes_avail', '_bx_classes_pre_lists_availability', 'bx_classes', '0');
+
+INSERT INTO `sys_form_pre_values`(`Key`, `Value`, `Order`, `LKey`, `LKey2`) VALUES
+('bx_classes_avail', '1', 1, '_bx_classes_avail_always', ''),
+('bx_classes_avail', '2', 2, '_bx_classes_avail_prev_class_completed', ''),
+('bx_classes_avail', '3', 3, '_bx_classes_avail_after_start_date', ''),
+('bx_classes_avail', '4', 4, '_bx_classes_avail_after_start_date_prev_class_completed', ''),
+('bx_classes_avail', '5', 5, '_bx_classes_avail_between_start_end_dates', ''),
+('bx_classes_avail', '6', 6, '_bx_classes_avail_between_start_end_dates_prev_completed', '');
+
+INSERT INTO `sys_form_pre_lists`(`key`, `title`, `module`, `use_for_sets`) VALUES
+('bx_classes_cmts', '_bx_classes_pre_lists_cmts', 'bx_classes', '0');
+
+INSERT INTO `sys_form_pre_values`(`Key`, `Value`, `Order`, `LKey`, `LKey2`) VALUES
+('bx_classes_cmts', '1', 1, '_bx_classes_cmts_disabled', ''),
+('bx_classes_cmts', '2', 2, '_bx_classes_cmts_all_shown', '');
+
+
+INSERT INTO `sys_form_pre_lists`(`key`, `title`, `module`, `use_for_sets`) VALUES
+('bx_classes_completed_when', '_bx_classes_pre_lists_completed_when', 'bx_classes', '0');
+
+INSERT INTO `sys_form_pre_values`(`Key`, `Value`, `Order`, `LKey`, `LKey2`) VALUES
+('bx_classes_completed_when', '1', 1, '_bx_classes_completed_when_viewed', ''),
+('bx_classes_completed_when', '2', 2, '_bx_classes_completed_when_replied', '');
+
+-- COMMENTS
+INSERT INTO `sys_objects_cmts` (`Name`, `Module`, `Table`, `CharsPostMin`, `CharsPostMax`, `CharsDisplayMax`, `Html`, `PerView`, `PerViewReplies`, `BrowseType`, `IsBrowseSwitch`, `PostFormPosition`, `NumberOfLevels`, `IsDisplaySwitch`, `IsRatable`, `ViewingThreshold`, `IsOn`, `RootStylePrefix`, `BaseUrl`, `ObjectVote`, `TriggerTable`, `TriggerFieldId`, `TriggerFieldAuthor`, `TriggerFieldTitle`, `TriggerFieldComments`, `ClassName`, `ClassFile`) VALUES
+('bx_classes', 'bx_classes', 'bx_classes_cmts', 1, 5000, 1000, 3, 5, 3, 'tail', 1, 'bottom', 1, 1, 1, -3, 1, 'cmt', 'page.php?i=view-class&id={object_id}', '', 'bx_classes_classes', 'id', 'author', 'title', 'comments', '', ''),
+('bx_classes_notes', 'bx_classes', 'bx_classes_cmts_notes', 1, 5000, 1000, 0, 5, 3, 'tail', 1, 'bottom', 1, 1, 1, -3, 1, 'cmt', 'page.php?i=view-class&id={object_id}', '', 'bx_classes_classes', 'id', 'author', 'title', 'comments', 'BxTemplCmtsNotes', '');
+
+-- VOTES
+INSERT INTO `sys_objects_vote` (`Name`, `TableMain`, `TableTrack`, `PostTimeout`, `MinValue`, `MaxValue`, `IsUndo`, `IsOn`, `TriggerTable`, `TriggerFieldId`, `TriggerFieldAuthor`, `TriggerFieldRate`, `TriggerFieldRateCount`, `ClassName`, `ClassFile`) VALUES 
+('bx_classes', 'bx_classes_votes', 'bx_classes_votes_track', '604800', '1', '1', '0', '1', 'bx_classes_classes', 'id', 'author', 'rate', 'votes', '', ''),
+('bx_classes_reactions', 'bx_classes_reactions', 'bx_classes_reactions_track', '604800', '1', '1', '1', '1', 'bx_classes_classes', 'id', 'author', 'rrate', 'rvotes', 'BxTemplVoteReactions', ''),
+('bx_classes_poll_answers', 'bx_classes_polls_answers_votes', 'bx_classes_polls_answers_votes_track', '604800', '1', '1', '0', '1', 'bx_classes_polls_answers', 'id', 'author_id', 'rate', 'votes', 'BxClssVotePollAnswers', 'modules/boonex/classes/classes/BxClssVotePollAnswers.php');
+
+-- SCORES
+INSERT INTO `sys_objects_score` (`name`, `module`, `table_main`, `table_track`, `post_timeout`, `is_on`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_score`, `trigger_field_cup`, `trigger_field_cdown`, `class_name`, `class_file`) VALUES 
+('bx_classes', 'bx_classes', 'bx_classes_scores', 'bx_classes_scores_track', '604800', '0', 'bx_classes_classes', 'id', 'author', 'score', 'sc_up', 'sc_down', '', '');
+
+-- REPORTS
+INSERT INTO `sys_objects_report` (`name`, `module`, `table_main`, `table_track`, `is_on`, `base_url`, `object_comment`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_count`, `class_name`, `class_file`) VALUES 
+('bx_classes', 'bx_classes', 'bx_classes_reports', 'bx_classes_reports_track', '1', 'page.php?i=view-class&id={object_id}', 'bx_classes_notes', 'bx_classes_classes', 'id', 'author', 'reports', '', '');
+
+-- VIEWS
+INSERT INTO `sys_objects_view` (`name`, `table_track`, `period`, `is_on`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_count`, `class_name`, `class_file`) VALUES 
+('bx_classes', 'bx_classes_views_track', '86400', '1', 'bx_classes_classes', 'id', 'author', 'views', '', '');
+
+-- FAFORITES
+INSERT INTO `sys_objects_favorite` (`name`, `table_track`, `is_on`, `is_undo`, `is_public`, `base_url`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_count`, `class_name`, `class_file`) VALUES 
+('bx_classes', 'bx_classes_favorites_track', '1', '1', '1', 'page.php?i=view-class&id={object_id}', 'bx_classes_classes', 'id', 'author', 'favorites', '', '');
+
+-- FEATURED
+INSERT INTO `sys_objects_feature` (`name`, `module`, `is_on`, `is_undo`, `base_url`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_flag`, `class_name`, `class_file`) VALUES 
+('bx_classes', 'bx_classes', '1', '1', 'page.php?i=view-class&id={object_id}', 'bx_classes_classes', 'id', 'author', 'featured', '', '');
+
+-- CONTENT INFO
+INSERT INTO `sys_objects_content_info` (`name`, `title`, `alert_unit`, `alert_action_add`, `alert_action_update`, `alert_action_delete`, `class_name`, `class_file`) VALUES
+('bx_classes', '_bx_classes', 'bx_classes', 'added', 'edited', 'deleted', '', ''),
+('bx_classes_cmts', '_bx_classes_cmts', 'bx_classes', 'commentPost', 'commentUpdated', 'commentRemoved', 'BxDolContentInfoCmts', '');
+
+INSERT INTO `sys_content_info_grids` (`object`, `grid_object`, `grid_field_id`, `condition`, `selection`) VALUES
+('bx_classes', 'bx_classes_administration', 'id', '', ''),
+('bx_classes', 'bx_classes_common', 'id', '', '');
+
+-- SEARCH EXTENDED
+INSERT INTO `sys_objects_search_extended` (`object`, `object_content_info`, `module`, `title`, `active`, `class_name`, `class_file`) VALUES
+('bx_classes', 'bx_classes', 'bx_classes', '_bx_classes_search_extended', 1, '', ''),
+('bx_classes_cmts', 'bx_classes_cmts', 'bx_classes', '_bx_classes_search_extended_cmts', 1, 'BxTemplSearchExtendedCmts', '');
+
+-- STUDIO: page & widget
+INSERT INTO `sys_std_pages`(`index`, `name`, `header`, `caption`, `icon`) VALUES
+(3, 'bx_classes', '_bx_classes', '_bx_classes', 'bx_classes@modules/boonex/classes/|std-icon.svg');
+SET @iPageId = LAST_INSERT_ID();
+
+SET @iParentPageId = (SELECT `id` FROM `sys_std_pages` WHERE `name` = 'home');
+SET @iParentPageOrder = (SELECT MAX(`order`) FROM `sys_std_pages_widgets` WHERE `page_id` = @iParentPageId);
+INSERT INTO `sys_std_widgets` (`page_id`, `module`, `type`, `url`, `click`, `icon`, `caption`, `cnt_notices`, `cnt_actions`) VALUES
+(@iPageId, 'bx_classes', 'content', '{url_studio}module.php?name=bx_classes', '', 'bx_classes@modules/boonex/classes/|std-icon.svg', '_bx_classes', '', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:11:"get_actions";s:6:"params";a:0:{}s:5:"class";s:18:"TemplStudioModules";}');
+INSERT INTO `sys_std_pages_widgets` (`page_id`, `widget_id`, `order`) VALUES
+(@iParentPageId, LAST_INSERT_ID(), IF(ISNULL(@iParentPageOrder), 1, @iParentPageOrder + 1));
+

+ 51 - 0
modules/boonex/convos/updates/12.0.2_12.0.3/install/config.php

@@ -0,0 +1,51 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'title' => 'Conversations',
+    'version_from' => '12.0.2',
+    'version_to' => '12.0.3',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '12.1.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/convos/updates/update_12.0.2_12.0.3/',
+    'home_uri' => 'convos_update_1202_1203',
+
+    'module_dir' => 'boonex/convos/',
+    'module_uri' => 'convos',
+
+    'db_prefix' => 'bx_convos_',
+    'class_prefix' => 'BxCnv',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 0,
+        'update_files' => 1,
+        'update_languages' => 0,
+        'clear_db_cache' => 0,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Conversations',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

+ 13 - 0
modules/boonex/convos/updates/12.0.2_12.0.3/install/installer.php

@@ -0,0 +1,13 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+class BxCnvUpdater extends BxDolStudioUpdater
+{
+    function __construct($aConfig)
+    {
+        parent::__construct($aConfig);
+    }
+}

+ 134 - 0
modules/boonex/convos/updates/12.0.2_12.0.3/source/classes/BxCnvCmts.php

@@ -0,0 +1,134 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Convos Convos
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxCnvCmts extends BxTemplCmts
+{
+    protected $_sModule;
+    protected $_oModule;
+
+    /**
+     * Silent Mode for Notification based modules.
+     */
+    protected $_iSilentMode;
+
+    function __construct($sSystem, $iId, $iInit = true, $oTemplate = false)
+    {
+        $this->_sModule = 'bx_convos';
+        $this->_oModule = BxDolModule::getInstance($this->_sModule);
+
+        parent::__construct($sSystem, $iId, $iInit, $oTemplate);
+
+        $this->_iSilentMode = 21; //--- Absolute for Timeline module only.
+
+        $this->_aT = array_merge($this->_aT, array(
+            'txt_min_form_placeholder' => '_bx_cnv_txt_min_form_placeholder'
+        ));
+    }
+
+    public function getObjectTitle ($iObjectId = 0)
+    {
+    	$sResult = parent::getObjectTitle($iObjectId);
+    	if(!empty($sResult))
+    		return strmaxtextlen($sResult, 20, '...');
+
+        return $sResult;
+    }
+
+    public function addCssJs()
+    {
+        parent::addCssJs();
+
+        $this->_oModule->_oTemplate->addCss(array('cmts.css'));
+    }
+
+    /**
+     * Comments are enabled for collaborators only
+     */
+    public function isEnabled ()
+    {
+        if (!parent::isEnabled ())
+            return false;
+
+        if (!$this->_oModule->_oDb->getContentInfoById((int)$this->getId()))
+            return false;
+
+        $aCollaborators = $this->_oModule->_oDb->getCollaborators((int)$this->getId());
+        if (!isset($aCollaborators[bx_get_logged_profile_id()]))
+            return false;
+
+        return true;
+    }
+
+    public function isRemoveAllowed ($aCmt, $isPerformAction = false)
+    {
+        if (isAdmin())
+            return true;
+
+        return false;
+    }
+
+    public function msgErrRemoveAllowed ()
+    {
+        return _t('_sys_txt_access_denied');
+    }
+
+    public function isEditAllowed ($aCmt, $isPerformAction = false)
+    {
+        return $this->isRemoveAllowed ($aCmt, $isPerformAction);
+    }
+
+    public function msgErrEditAllowed ()
+    {
+        return $this->msgErrRemoveAllowed ();
+    }
+
+    public function getCommentsBlock($aBp = array(), $aDp = array())
+    {
+        $mixedBlock = parent::getCommentsBlock($aBp, $aDp);
+        if (is_array($mixedBlock) && isset($mixedBlock['title']))
+            $mixedBlock['title'] = _t('_bx_cnv_page_block_title_entry_comments', $this->getCommentsCount());
+
+        return $mixedBlock;
+    }
+
+    public function getCommentBlock($iCmtId = 0, $aBp = array(), $aDp = array())
+    {
+        if(!$this->isEnabled())
+            return '';
+
+        return parent::getCommentBlock($iCmtId, $aBp, $aDp);
+    }
+
+    protected function _getFormObject($sAction = BX_CMT_ACTION_POST)
+    {
+        $oForm = parent::_getFormObject($sAction);
+        $oForm->aInputs['cmt_submit']['value'] = _t('_sys_send');
+        return $oForm;
+    }
+
+    protected function _prepareAlertParams($aCmt)
+    {
+        $aParams = parent::_prepareAlertParams($aCmt);
+        $aParams['silent_mode'] = $this->_iSilentMode;
+
+        return $aParams;
+    }
+
+    protected function _prepareAlertParamsReply($aCmt, $aCmtPrnt)
+    {
+        $aParams = parent::_prepareAlertParamsReply($aCmt, $aCmtPrnt);
+        $aParams['silent_mode'] = $this->_iSilentMode;
+
+        return $aParams;
+    }
+}
+
+/** @} */

+ 104 - 0
modules/boonex/convos/updates/12.0.2_12.0.3/source/install/config.php

@@ -0,0 +1,104 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Convos Convos
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_convos',
+    'title' => 'Conversations',
+    'note' => 'Conversations module.',
+    'version' => '12.0.3',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '12.1.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/convos/',
+    'home_uri' => 'convos',
+
+    'db_prefix' => 'bx_convos_',
+    'class_prefix' => 'BxCnv',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Conversations',
+
+    /**
+     * Menu triggers.
+     */
+    'menu_triggers' => array(
+        'trigger_profile_view_actions',
+        'trigger_group_view_actions',
+    ),
+
+	/**
+     * Storage objects to automatically delete files from upon module uninstallation.
+     * Note. Don't add storage objects used in transcoder objects.
+     */
+    'storages' => array(
+    	'bx_convos_files'
+    ),
+
+	/**
+     * Transcoders.
+     */
+    'transcoders' => array(
+		'bx_convos_preview'
+    ),
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'uninstall' => array (
+        'execute_sql' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'enable' => array(
+        'execute_sql' => 1,
+        'clear_db_cache' => 1,
+    ),
+	'enable_success' => array(
+    	'process_menu_triggers' => 1,
+    	'register_transcoders' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable' => array (
+        'execute_sql' => 1,
+    	'unregister_transcoders' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable_failed' => array (
+    	'register_transcoders' => 1,
+    	'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Dependencies Section
+     */
+    'dependencies' => array(),
+);
+
+/** @} */

+ 51 - 0
modules/boonex/courses/updates/12.0.0_12.0.1/install/config.php

@@ -0,0 +1,51 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'title' => 'Courses',
+    'version_from' => '12.0.0',
+    'version_to' => '12.0.1',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '12.1.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/courses/updates/update_12.0.0_12.0.1/',
+    'home_uri' => 'courses_update_1200_1201',
+
+    'module_dir' => 'boonex/courses/',
+    'module_uri' => 'courses',
+
+    'db_prefix' => 'bx_courses_',
+    'class_prefix' => 'BxCourses',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_files' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Courses',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

+ 31 - 0
modules/boonex/courses/updates/12.0.0_12.0.1/install/installer.php

@@ -0,0 +1,31 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+class BxCoursesUpdater extends BxDolStudioUpdater
+{
+    function __construct($aConfig)
+    {
+        parent::__construct($aConfig);
+    }
+
+    public function actionExecuteSql($sOperation)
+    {
+        if($sOperation == 'install') {
+            if(!$this->oDb->isFieldExists('bx_courses_data', 'status'))
+                $this->oDb->query("ALTER TABLE `bx_courses_data` ADD `status` enum('active','awaiting','hidden') NOT NULL DEFAULT 'active' AFTER `allow_post_to`");
+
+            if(!$this->oDb->isFieldExists('bx_courses_admins', 'order'))
+                $this->oDb->query("ALTER TABLE `bx_courses_admins` ADD `order` varchar(32) NOT NULL default '' AFTER `role`");
+            if(!$this->oDb->isFieldExists('bx_courses_admins', 'expired'))
+                $this->oDb->query("ALTER TABLE `bx_courses_admins` ADD `expired` int(11) unsigned NOT NULL default '0' AFTER `added`");
+
+            if(!$this->oDb->isFieldExists('bx_courses_favorites_track', 'list_id'))
+                $this->oDb->query("ALTER TABLE `bx_courses_favorites_track` ADD `list_id` int(11) NOT NULL default '0' AFTER `author_id`");
+        }
+
+        return parent::actionExecuteSql($sOperation);
+    }
+}

+ 79 - 0
modules/boonex/courses/updates/12.0.0_12.0.1/install/langs/en.xml

@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources name="en" flag="gb" title="English">
+    <string_add name="_bx_courses_option_per_page_for_favorites_lists"><![CDATA[Number of favorite lists per page]]></string_add>
+	<string_add name="_bx_courses_form_profile_input_allow_view_favorite_list"><![CDATA[Visibility]]></string_add>
+	<string_add name="_bx_courses_form_price"><![CDATA[Price]]></string_add>
+	<string_add name="_bx_courses_form_price_display_add"><![CDATA[Add]]></string_add>
+	<string_add name="_bx_courses_form_price_display_edit"><![CDATA[Edit]]></string_add>
+	<string_add name="_bx_courses_form_price_input_sys_id"><![CDATA[ID]]></string_add>
+	<string_add name="_bx_courses_form_price_input_sys_role_id"><![CDATA[Role ID]]></string_add>
+	<string_add name="_bx_courses_form_price_input_sys_name"><![CDATA[Name]]></string_add>
+	<string_add name="_bx_courses_form_price_input_name"><![CDATA[Name]]></string_add>
+	<string_add name="_bx_courses_form_price_input_inf_name"><![CDATA[Unique value which will be used in back end and API calls]]></string_add>
+	<string_add name="_bx_courses_form_price_input_err_name"><![CDATA[You need to enter a unique value here]]></string_add>
+	<string_add name="_bx_courses_form_price_input_sys_period"><![CDATA[Period]]></string_add>
+	<string_add name="_bx_courses_form_price_input_period"><![CDATA[Period]]></string_add>
+	<string_add name="_bx_courses_form_price_input_inf_period"><![CDATA[Use 0 for lifetime]]></string_add>
+	<string_add name="_bx_courses_form_price_input_sys_period_unit"><![CDATA[Period unit]]></string_add>
+	<string_add name="_bx_courses_form_price_input_period_unit"><![CDATA[Period unit]]></string_add>
+	<string_add name="_bx_courses_form_price_input_inf_period_unit"><![CDATA[Leave empty for lifetime level.]]></string_add>
+	<string_add name="_bx_courses_form_price_input_err_period_unit"><![CDATA[You need to select a period unit here.]]></string_add>
+	<string_add name="_bx_courses_form_price_input_sys_price"><![CDATA[Price]]></string_add>
+	<string_add name="_bx_courses_form_price_input_price"><![CDATA[Price]]></string_add>
+	<string_add name="_bx_courses_form_price_input_inf_price"><![CDATA[Use 0 or leave empty to create free level.]]></string_add>
+	<string_add name="_bx_courses_form_price_input_sys_do_submit"><![CDATA[Submit]]></string_add>
+	<string_add name="_bx_courses_form_price_input_do_submit"><![CDATA[Submit]]></string_add>
+	<string_add name="_bx_courses_form_price_input_sys_do_cancel"><![CDATA[Cancel]]></string_add>
+	<string_add name="_bx_courses_form_price_input_do_cancel"><![CDATA[Cancel]]></string_add>
+	<string_add name="_bx_courses_acl_action_use_paid_join"><![CDATA[Use paid join]]></string_add>
+	<string_add name="_bx_courses_acl_action_delete_any_profile"><![CDATA[Delete Any Course]]></string_add>
+	<string_add name="_bx_courses_page_title_sys_join_profile"><![CDATA[Join Course]]></string_add>
+	<string_add name="_bx_courses_page_title_join_profile"><![CDATA[Join Course]]></string_add>
+	<string_add name="_bx_courses_page_block_title_entry_reports"><![CDATA[Reports]]></string_add>
+	<string_add name="_bx_courses_page_title_sys_profile_pricing"><![CDATA[Pricing]]></string_add>
+	<string_add name="_bx_courses_page_title_profile_pricing"><![CDATA[Pricing]]></string_add>
+	<string_add name="_bx_courses_page_title_sys_entries_favorites"><![CDATA[Favorives Courses]]></string_add>
+	<string_add name="_bx_courses_page_title_entries_favorites"><![CDATA[Favorives Courses]]></string_add>
+	<string_add name="_bx_courses_page_block_title_favorites_entries"><![CDATA["{title}" List]]></string_add>
+	<string_add name="_bx_courses_page_block_title_favorites_entries_info"><![CDATA[Info]]></string_add>
+	<string_add name="_bx_courses_page_block_title_favorites_entries_actions"><![CDATA[Favorites List Actions]]></string_add>
+	<string_add name="_bx_courses_page_block_title_join_profile"><![CDATA[Join Course]]></string_add>
+	<string_add name="_bx_courses_page_block_title_system_profile_pricing"><![CDATA[Pricing]]></string_add>
+	<string_add name="_bx_courses_page_block_title_profile_pricing"><![CDATA[Pricing]]></string_add>
+	<string_add name="_bx_courses_page_block_title_profile_pricing_link"><![CDATA[Pricing of <a href="{profile_link}">{display_name}</a>]]></string_add>
+	<string_add name="_bx_courses_menu_item_title_system_edit_pricing"><![CDATA[Edit Pricing]]></string_add>
+	<string_add name="_bx_courses_menu_item_title_edit_pricing"><![CDATA[Edit Pricing]]></string_add>
+	<string_add name="_bx_courses_menu_item_title_system_pay_and_join"><![CDATA[Pay & Join]]></string_add>
+	<string_add name="_bx_courses_menu_item_title_pay_and_join"><![CDATA[Pay & Join]]></string_add>
+	<string_add name="_bx_courses_grid_column_title_name"><![CDATA[Name]]></string_add>
+	<string_add name="_bx_courses_grid_column_title_role_id"><![CDATA[Role]]></string_add>
+	<string_add name="_bx_courses_grid_column_title_period"><![CDATA[Period]]></string_add>
+	<string_add name="_bx_courses_grid_column_title_price"><![CDATA[Price]]></string_add>
+	<string_add name="_bx_courses_grid_action_title_add"><![CDATA[Add]]></string_add>
+	<string_add name="_bx_courses_grid_action_title_edit"><![CDATA[Edit]]></string_add>
+	<string_add name="_bx_courses_grid_action_title_delete"><![CDATA[Delete]]></string_add>
+	<string_add name="_bx_courses_grid_action_title_buy"><![CDATA[Buy]]></string_add>
+	<string_add name="_bx_courses_grid_action_title_buy_title"><![CDATA[One-time payment]]></string_add>
+	<string_add name="_bx_courses_grid_action_title_subscribe"><![CDATA[Subscribe]]></string_add>
+	<string_add name="_bx_courses_grid_action_title_subscribe_title"><![CDATA[Create a subscription with recurring billing]]></string_add>
+	<string_add name="_bx_courses_grid_action_title_choose"><![CDATA[Choose]]></string_add>
+	<string_add name="_bx_courses_grid_action_title_choose_title"><![CDATA[Switch to the level for free]]></string_add>
+	<string_add name="_bx_courses_popup_title_price_add"><![CDATA[Add Pricing Plan]]></string_add>
+	<string_add name="_bx_courses_popup_title_price_edit"><![CDATA[Edit Pricing Plan]]></string_add>
+	<string_add name="_bx_courses_txt_role_added"><![CDATA[Added]]></string_add>
+	<string_add name="_bx_courses_txt_role_expired"><![CDATA[Expires]]></string_add>
+	<string_add name="_bx_courses_txt_n_unit"><![CDATA[{0} ({1})]]></string_add>
+	<string_add name="_bx_courses_txt_cart_item_title"><![CDATA[{0}: {1} ({2} {3})]]></string_add>
+	<string_add name="_bx_courses_msg_performed"><![CDATA[The action was successfully performed.]]></string_add>
+	<string_add name="_bx_courses_err_price_duplicate"><![CDATA[Similar pricing plan is already exists.]]></string_add>
+	<string_add name="_bx_courses_err_cannot_perform"><![CDATA[An error appeared. Please report.]]></string_add>
+	<string_add name="_bx_courses_pre_lists_period_units"><![CDATA[Billing Interval]]></string_add>
+	<string_add name="_bx_courses_period_unit_day"><![CDATA[day]]></string_add>
+	<string_add name="_bx_courses_period_unit_week"><![CDATA[week]]></string_add>
+	<string_add name="_bx_courses_period_unit_month"><![CDATA[month]]></string_add>
+	<string_add name="_bx_courses_period_unit_year"><![CDATA[year]]></string_add>
+
+	<string_del name="_bx_courses_acl_action_edit_any_profile"><![CDATA[Edit Any Course]]></string_del>
+	<string_del name="_bx_courses_txt_to_admins"><![CDATA[To Instructors]]></string_del>
+	<string_del name="_bx_courses_txt_from_admins"><![CDATA[From Instructors]]></string_del>
+</resources>

+ 129 - 0
modules/boonex/courses/updates/12.0.0_12.0.1/install/sql/enable.sql

@@ -0,0 +1,129 @@
+-- SETTINGS
+SET @iCategId = (SELECT `id` FROM `sys_options_categories` WHERE `name`='bx_courses' LIMIT 1);
+
+DELETE FROM `sys_options` WHERE `name`='bx_courses_per_page_for_favorites_lists';
+INSERT INTO `sys_options` (`name`, `value`, `category_id`, `caption`, `type`, `extra`, `check`, `check_params`, `check_error`, `order`) VALUES
+('bx_courses_per_page_for_favorites_lists', '5', @iCategId, '_bx_courses_option_per_page_for_favorites_lists', 'digit', '', '', '', '', 17);
+
+-- PAGES
+DELETE FROM `sys_objects_page` WHERE `object`='bx_courses_join_profile';
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_courses_join_profile', 'join-course-profile', '_bx_courses_page_title_sys_join_profile', '_bx_courses_page_title_join_profile', 'bx_courses', 5, 2147483647, 1, 'page.php?i=join-course-profile', '', '', '', 0, 1, 0, 'BxCoursesPageEntry', 'modules/boonex/courses/classes/BxCoursesPageEntry.php');
+
+DELETE FROM `sys_pages_blocks` WHERE `object`='bx_courses_join_profile';
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_courses_join_profile', 1, 'bx_courses', '', '_bx_courses_page_block_title_join_profile', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:10:"bx_courses";s:6:"method";s:11:"entity_join";s:6:"params";a:1:{i:0;s:12:"{profile_id}";}}', 0, 0, 0);
+
+DELETE FROM `sys_objects_page` WHERE `object`='bx_courses_profile_pricing';
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_courses_profile_pricing', 'edit-course-pricing', '_bx_courses_page_title_sys_profile_pricing', '_bx_courses_page_title_profile_pricing', 'bx_courses', 5, 2147483647, 1, 'page.php?i=edit-course-pricing', '', '', '', 0, 1, 0, 'BxCoursesPageEntry', 'modules/boonex/courses/classes/BxCoursesPageEntry.php');
+
+DELETE FROM `sys_pages_blocks` WHERE `object`='bx_courses_profile_pricing';
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_courses_profile_pricing', 1, 'bx_courses', '_bx_courses_page_block_title_system_profile_pricing', '_bx_courses_page_block_title_profile_pricing_link', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:10:"bx_courses";s:6:"method";s:14:"entity_pricing";s:6:"params";a:1:{i:0;s:12:"{profile_id}";}}', 0, 0, 1, 1);
+
+DELETE FROM `sys_objects_page` WHERE `object`='bx_courses_favorites';
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_courses_favorites', '_bx_courses_page_title_sys_entries_favorites', '_bx_courses_page_title_entries_favorites', 'bx_courses', 12, 2147483647, 1, 'courses-favorites', 'page.php?i=courses-favorites', '', '', '', 0, 1, 0, 'BxCoursesPageListEntry', 'modules/boonex/courses/classes/BxCoursesPageListEntry.php');
+
+DELETE FROM `sys_pages_blocks` WHERE `object`='bx_courses_favorites';
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_courses_favorites', 2, 'bx_courses', '', '_bx_courses_page_block_title_favorites_entries', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:10:"bx_courses";s:6:"method";s:15:"browse_favorite";s:6:"params";a:2:{s:10:"profile_id";s:12:"{profile_id}";s:6:"params";a:3:{s:9:"unit_view";s:7:"gallery";s:13:"empty_message";b:0;s:13:"ajax_paginate";b:0;}}}', 0, 1, 1),
+('bx_courses_favorites', 3, 'bx_courses', '', '_bx_courses_page_block_title_favorites_entries_info', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:10:"bx_courses";s:6:"method";s:19:"favorites_list_info";}', 0, 0, 0),
+('bx_courses_favorites', 3, 'bx_courses', '', '_bx_courses_page_block_title_favorites_entries_actions', 13, 2147483647, 'service', 'a:2:{s:6:"module";s:10:"bx_courses";s:6:"method";s:22:"favorites_list_actions";}', 0, 0, 1);
+
+
+-- MENUS
+DELETE FROM `sys_menu_items` WHERE `set_name`='bx_courses_view_actions' AND `name`='join-course-profile';
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `addon`, `markers`, `submenu_object`, `submenu_popup`, `visible_for_levels`, `visibility_custom`, `active`, `copyable`, `editable`, `order`) VALUES 
+('bx_courses_view_actions', 'bx_courses', 'join-course-profile', '_bx_courses_menu_item_title_system_pay_and_join', '_bx_courses_menu_item_title_pay_and_join', 'page.php?i=join-course-profile&profile_id={profile_id}', '', '', 'sign-in-alt', '', '', '', 0, 2147483647, 'a:3:{s:6:"module";s:10:"bx_courses";s:6:"method";s:22:"is_paid_join_avaliable";s:6:"params";a:1:{i:0;s:12:"{profile_id}";}}', 1, 0, 0, 5);
+
+DELETE FROM `sys_menu_items` WHERE `set_name`='bx_courses_view_actions_more' AND `name`='edit-course-pricing';
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `addon`, `markers`, `submenu_object`, `visible_for_levels`, `visibility_custom`, `active`, `copyable`, `order`) VALUES 
+('bx_courses_view_actions_more', 'bx_courses', 'edit-course-pricing', '_bx_courses_menu_item_title_system_edit_pricing', '_bx_courses_menu_item_title_edit_pricing', 'page.php?i=edit-course-pricing&profile_id={profile_id}', '', '', 'money-check-alt', '', '', '', 2147483647, 'a:3:{s:6:"module";s:10:"bx_courses";s:6:"method";s:20:"is_pricing_avaliable";s:6:"params";a:1:{i:0;s:12:"{profile_id}";}}', 1, 0, 41);
+
+DELETE FROM `sys_menu_items` WHERE `set_name`='bx_courses_view_actions_all' AND `name` IN ('join-course-profile', 'edit-course-pricing');
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `addon`, `markers`, `submenu_object`, `submenu_popup`, `visible_for_levels`, `visibility_custom`, `active`, `copyable`, `order`) VALUES 
+('bx_courses_view_actions_all', 'bx_courses', 'join-course-profile', '_bx_courses_menu_item_title_system_pay_and_join', '', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 5),
+('bx_courses_view_actions_all', 'bx_courses', 'edit-course-pricing', '_bx_courses_menu_item_title_system_edit_pricing', '', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 415);
+
+DELETE FROM `sys_menu_items` WHERE `set_name`='bx_courses_snippet_meta' AND `name`='join-paid';
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `addon`, `markers`, `submenu_object`, `visible_for_levels`, `visibility_custom`, `active`, `copyable`, `editable`, `order`) VALUES
+('bx_courses_snippet_meta', 'bx_courses', 'join-paid', '_sys_menu_item_title_system_sm_join_paid', '_sys_menu_item_title_sm_join_paid', '', '', '', '', '', '', '', 2147483647, 'a:3:{s:6:"module";s:10:"bx_courses";s:6:"method";s:33:"is_paid_join_avaliable_by_content";s:6:"params";a:1:{i:0;s:12:"{content_id}";}}', 1, 0, 1, 9);
+
+
+-- ACL
+SET @iIdActionUsePaidJoin = (SELECT `ID` FROM `sys_acl_actions` WHERE `Module`='bx_courses' AND `Name`='use paid join' LIMIT 1);
+DELETE FROM `sys_acl_actions` WHERE `ID`=@iIdActionUsePaidJoin;
+DELETE FROM `sys_acl_matrix` WHERE `IDAction`=@iIdActionUsePaidJoin;
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_courses', 'use paid join', NULL, '_bx_courses_acl_action_use_paid_join', '', 1, 1);
+SET @iIdActionUsePaidJoin = LAST_INSERT_ID();
+
+SET @iUnauthenticated = 1;
+SET @iAccount = 2;
+SET @iStandard = 3;
+SET @iUnconfirmed = 4;
+SET @iPending = 5;
+SET @iSuspended = 6;
+SET @iModerator = 7;
+SET @iAdministrator = 8;
+SET @iPremium = 9;
+
+INSERT INTO `sys_acl_matrix` (`IDLevel`, `IDAction`) VALUES
+(@iStandard, @iIdActionUsePaidJoin),
+(@iModerator, @iIdActionUsePaidJoin),
+(@iAdministrator, @iIdActionUsePaidJoin),
+(@iPremium, @iIdActionUsePaidJoin);
+
+
+-- GRID
+DELETE FROM `sys_grid_fields` WHERE `object`='bx_courses_fans' AND `name` IN ('role_added', 'role_expired');
+INSERT INTO `sys_grid_fields` (`object`, `name`, `title`, `width`, `params`, `order`) VALUES
+('bx_courses_fans', 'role_added', '_bx_courses_txt_role_added', '10%', '', 16),
+('bx_courses_fans', 'role_expired', '_bx_courses_txt_role_expired', '10%', '', 17);
+
+UPDATE `sys_grid_fields` SET `width`='20%' WHERE `object`='bx_courses_fans' AND `name`='actions';
+
+DELETE FROM `sys_objects_grid` WHERE `object` IN ('bx_courses_prices_manage', 'bx_courses_prices_view');
+INSERT INTO `sys_objects_grid` (`object`, `source_type`, `source`, `table`, `field_id`, `field_order`, `field_active`, `paginate_url`, `paginate_per_page`, `paginate_simple`, `paginate_get_start`, `paginate_get_per_page`, `filter_fields`, `filter_fields_translatable`, `filter_mode`, `sorting_fields`, `sorting_fields_translatable`, `visible_for_levels`, `override_class_name`, `override_class_file`) VALUES
+('bx_courses_prices_manage', 'Sql', 'SELECT * FROM `bx_courses_prices` WHERE 1 ', 'bx_courses_prices', 'id', 'order', '', '', 100, NULL, 'start', '', 'period,period_unit,price', '', 'like', '', '', 2147483647, 'BxCoursesGridPricesManage', 'modules/boonex/courses/classes/BxCoursesGridPricesManage.php'),
+('bx_courses_prices_view', 'Sql', 'SELECT * FROM `bx_courses_prices` WHERE 1 ', 'bx_courses_prices', 'id', 'order', '', '', 100, NULL, 'start', '', 'period,period_unit,price', '', 'like', '', '', 2147483647, 'BxCoursesGridPricesView', 'modules/boonex/courses/classes/BxCoursesGridPricesView.php');
+
+DELETE FROM `sys_grid_fields` WHERE `object` IN ('bx_courses_prices_manage', 'bx_courses_prices_view');
+INSERT INTO `sys_grid_fields` (`object`, `name`, `title`, `width`, `translatable`, `chars_limit`, `params`, `order`) VALUES
+('bx_courses_prices_manage', 'checkbox', '_sys_select', '1%', 0, 0, '', 1),
+('bx_courses_prices_manage', 'order', '', '1%', 0, 0, '', 2),
+('bx_courses_prices_manage', 'name', '_bx_courses_grid_column_title_name', '38%', 0, 32, '', 3),
+('bx_courses_prices_manage', 'price', '_bx_courses_grid_column_title_price', '20%', 0, 16, '', 4),
+('bx_courses_prices_manage', 'period', '_bx_courses_grid_column_title_period', '20%', 0, 16, '', 5),
+('bx_courses_prices_manage', 'actions', '', '20%', 0, 0, '', 6),
+
+('bx_courses_prices_view', 'role_id', '_bx_courses_grid_column_title_role_id', '40%', 0, 32, '', 1),
+('bx_courses_prices_view', 'price', '_bx_courses_grid_column_title_price', '20%', 0, 16, '', 2),
+('bx_courses_prices_view', 'period', '_bx_courses_grid_column_title_period', '20%', 0, 16, '', 3),
+('bx_courses_prices_view', 'actions', '', '20%', 0, 0, '', 4);
+
+DELETE FROM `sys_grid_actions` WHERE `object` IN ('bx_courses_prices_manage', 'bx_courses_prices_view');
+INSERT INTO `sys_grid_actions` (`object`, `type`, `name`, `title`, `icon`, `icon_only`, `confirm`, `order`) VALUES
+('bx_courses_prices_manage', 'independent', 'add', '_bx_courses_grid_action_title_add', '', 0, 0, 1),
+('bx_courses_prices_manage', 'single', 'edit', '_bx_courses_grid_action_title_edit', 'pencil-alt', 1, 0, 1),
+('bx_courses_prices_manage', 'single', 'delete', '_bx_courses_grid_action_title_delete', 'remove', 1, 1, 2),
+('bx_courses_prices_manage', 'bulk', 'delete', '_bx_courses_grid_action_title_delete', '', 0, 1, 1),
+
+('bx_courses_prices_view', 'single', 'buy', '_bx_courses_grid_action_title_buy', 'cart-plus', 0, 0, 1),
+('bx_courses_prices_view', 'single', 'subscribe', '_bx_courses_grid_action_title_subscribe', 'credit-card', 0, 0, 2),
+('bx_courses_prices_view', 'single', 'choose', '_bx_courses_grid_action_title_choose', 'far check-square', 0, 0, 3);
+
+
+-- PRIVACY
+DELETE FROM `sys_objects_privacy` WHERE `object`='bx_courses_allow_view_favorite_list';
+INSERT INTO `sys_objects_privacy` (`object`, `module`, `action`, `title`, `default_group`, `spaces`, `table`, `table_field_id`, `table_field_author`, `override_class_name`, `override_class_file`) VALUES
+('bx_courses_allow_view_favorite_list', 'bx_courses', 'view_favorite_list', '_bx_courses_form_profile_input_allow_view_favorite_list', '3', '', 'bx_courses_favorites_lists', 'id', 'author_id', 'BxCoursesPrivacy', 'modules/boonex/courses/classes/BxCoursesPrivacy.php');
+
+
+-- CRON
+DELETE FROM `sys_cron_jobs` WHERE `name`='bx_courses_pruning';
+INSERT INTO `sys_cron_jobs` (`name`, `time`, `class`, `file`, `service_call`) VALUES
+('bx_courses_pruning', '0 0 * * *', 'BxCoursesCronPruning', 'modules/boonex/courses/classes/BxCoursesCronPruning.php', '');

+ 86 - 0
modules/boonex/courses/updates/12.0.0_12.0.1/install/sql/install.sql

@@ -0,0 +1,86 @@
+-- TABLES
+CREATE TABLE IF NOT EXISTS `bx_courses_favorites_lists` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `title` varchar(255) NOT NULL,
+  `author_id` int(11) NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  `allow_view_favorite_list_to` varchar(16) NOT NULL DEFAULT '3',
+   PRIMARY KEY (`id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_courses_prices` (
+  `id` int(11) NOT NULL auto_increment,
+  `profile_id` int(11) NOT NULL default '0',
+  `role_id` int(11) unsigned NOT NULL default '0',
+  `name` varchar(128) NOT NULL default '',
+  `period` int(11) unsigned NOT NULL default '1',
+  `period_unit` varchar(32) NOT NULL default '',
+  `price` float unsigned NOT NULL default '1',
+  `order` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `name` (`name`),
+  UNIQUE KEY `type` (`profile_id`, `role_id`,`period`, `period_unit`)
+);
+
+
+-- FORMS
+DELETE FROM `sys_objects_form` WHERE `object`='bx_courses_price';
+INSERT INTO `sys_objects_form` (`object`, `module`, `title`, `action`, `form_attrs`, `submit_name`, `table`, `key`, `uri`, `uri_title`, `params`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES
+('bx_courses_price', 'bx_courses', '_bx_courses_form_price', '', '', 'do_submit', 'bx_courses_prices', 'id', '', '', '', 0, 1, 'BxCoursesFormPrice', 'modules/boonex/courses/classes/BxCoursesFormPrice.php');
+
+DELETE FROM `sys_form_displays` WHERE `object`='bx_courses_price';
+INSERT INTO `sys_form_displays` (`display_name`, `module`, `object`, `title`, `view_mode`) VALUES
+('bx_courses_price_add', 'bx_courses', 'bx_courses_price', '_bx_courses_form_price_display_add', 0),
+('bx_courses_price_edit', 'bx_courses', 'bx_courses_price', '_bx_courses_form_price_display_edit', 0);
+
+DELETE FROM `sys_form_inputs` WHERE `object`='bx_courses_price';
+INSERT INTO `sys_form_inputs` (`object`, `module`, `name`, `value`, `values`, `checked`, `type`, `caption_system`, `caption`, `info`, `required`, `collapsed`, `html`, `attrs`, `attrs_tr`, `attrs_wrapper`, `checker_func`, `checker_params`, `checker_error`, `db_pass`, `db_params`, `editable`, `deletable`) VALUES
+('bx_courses_price', 'bx_courses', 'id', '', '', 0, 'hidden', '_bx_courses_form_price_input_sys_id', '', '', 1, 0, 0, '', '', '', '', '', '', 'Int', '', 1, 0),
+('bx_courses_price', 'bx_courses', 'role_id', '', '', 0, 'hidden', '_bx_courses_form_price_input_sys_role_id', '', '', 1, 0, 0, '', '', '', '', '', '', 'Int', '', 1, 0),
+('bx_courses_price', 'bx_courses', 'name', '', '', 0, 'text', '_bx_courses_form_price_input_sys_name', '_bx_courses_form_price_input_name', '_bx_courses_form_price_input_inf_name', 1, 0, 0, '', '', '', 'Avail', '', '_bx_courses_form_price_input_err_name', 'Xss', '', 1, 0),
+('bx_courses_price', 'bx_courses', 'period', '', '', 0, 'text', '_bx_courses_form_price_input_sys_period', '_bx_courses_form_price_input_period', '_bx_courses_form_price_input_inf_period', 1, 0, 0, '', '', '', '', '', '', 'Int', '', 1, 0),
+('bx_courses_price', 'bx_courses', 'period_unit', '', '#!bx_courses_period_units', 0, 'select', '_bx_courses_form_price_input_sys_period_unit', '_bx_courses_form_price_input_period_unit', '_bx_courses_form_price_input_inf_period_unit', 1, 0, 0, '', '', '', '', '', '', 'Xss', '', 1, 0),
+('bx_courses_price', 'bx_courses', 'price', '', '', 0, 'text', '_bx_courses_form_price_input_sys_price', '_bx_courses_form_price_input_price', '_bx_courses_form_price_input_inf_price', 1, 0, 0, '', '', '', '', '', '', 'Float', '', 1, 0),
+('bx_courses_price', 'bx_courses', 'controls', '', 'do_submit,do_cancel', 0, 'input_set', '', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_courses_price', 'bx_courses', 'do_submit', '_bx_courses_form_price_input_do_submit', '', 0, 'submit', '_bx_courses_form_price_input_sys_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_courses_price', 'bx_courses', 'do_cancel', '_bx_courses_form_price_input_do_cancel', '', 0, 'button', '_bx_courses_form_price_input_sys_do_cancel', '', '', 0, 0, 0, 'a:2:{s:7:"onclick";s:45:"$(''.bx-popup-applied:visible'').dolPopupHide()";s:5:"class";s:22:"bx-def-margin-sec-left";}', '', '', '', '', '', '', '', 1, 0);
+
+DELETE FROM `sys_form_display_inputs` WHERE `display_name` IN ('bx_courses_price_add', 'bx_courses_price_edit');
+INSERT INTO `sys_form_display_inputs` (`display_name`, `input_name`, `visible_for_levels`, `active`, `order`) VALUES
+('bx_courses_price_add', 'id', 2147483647, 0, 1),
+('bx_courses_price_add', 'role_id', 2147483647, 1, 2),
+('bx_courses_price_add', 'name', 2147483647, 1, 3),
+('bx_courses_price_add', 'price', 2147483647, 1, 4),
+('bx_courses_price_add', 'period', 2147483647, 1, 5),
+('bx_courses_price_add', 'period_unit', 2147483647, 1, 6),
+('bx_courses_price_add', 'controls', 2147483647, 1, 7),
+('bx_courses_price_add', 'do_submit', 2147483647, 1, 8),
+('bx_courses_price_add', 'do_cancel', 2147483647, 1, 9),
+
+('bx_courses_price_edit', 'id', 2147483647, 1, 1),
+('bx_courses_price_edit', 'role_id', 2147483647, 1, 2),
+('bx_courses_price_edit', 'name', 2147483647, 1, 3),
+('bx_courses_price_edit', 'price', 2147483647, 1, 4),
+('bx_courses_price_edit', 'period', 2147483647, 1, 5),
+('bx_courses_price_edit', 'period_unit', 2147483647, 1, 6),
+('bx_courses_price_edit', 'controls', 2147483647, 1, 7),
+('bx_courses_price_edit', 'do_submit', 2147483647, 1, 8),
+('bx_courses_price_edit', 'do_cancel', 2147483647, 1, 9);
+
+
+-- PRE-VALUES
+DELETE FROM `sys_form_pre_lists` WHERE `key`='bx_courses_period_units';
+INSERT INTO `sys_form_pre_lists`(`key`, `title`, `module`, `use_for_sets`) VALUES
+('bx_courses_period_units', '_bx_courses_pre_lists_period_units', 'bx_courses', '0');
+
+DELETE FROM `sys_form_pre_values` WHERE `Key`='bx_courses_period_units';
+INSERT INTO `sys_form_pre_values`(`Key`, `Value`, `Order`, `LKey`, `LKey2`, `Data`) VALUES
+('bx_courses_period_units', '', 0, '_sys_please_select', '', ''),
+('bx_courses_period_units', 'day', 1, '_bx_courses_period_unit_day', '', ''),
+('bx_courses_period_units', 'week', 2, '_bx_courses_period_unit_week', '', ''),
+('bx_courses_period_units', 'month', 3, '_bx_courses_period_unit_month', '', ''),
+('bx_courses_period_units', 'year', 4, '_bx_courses_period_unit_year', '', '');
+
+
+-- FAFORITES
+UPDATE `sys_objects_favorite` SET `table_lists`='bx_courses_favorites_lists' WHERE `name`='bx_courses';

+ 257 - 0
modules/boonex/courses/updates/12.0.0_12.0.1/source/classes/BxCoursesConfig.php

@@ -0,0 +1,257 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Courses Courses
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxCoursesConfig extends BxBaseModGroupsConfig
+{
+    function __construct($aModule)
+    {
+        parent::__construct($aModule);
+
+        $this->_aMenuItems2MethodsActions = array_merge($this->_aMenuItems2MethodsActions, array(
+            'view-course-profile' => 'checkAllowedView',
+            'edit-course-profile' => 'checkAllowedEdit',
+            'edit-course-cover' => 'checkAllowedChangeCover',
+            'invite-to-course' => 'checkAllowedInvite',
+            'delete-course-profile' => 'checkAllowedDelete'
+        ));
+
+        $this->CNF = array (
+
+            // module icon
+            'ICON' => 'book-reader col-blue3-dark',
+
+            // database tables
+            'TABLE_ENTRIES' => $aModule['db_prefix'] . 'data',
+            'TABLE_ENTRIES_FULLTEXT' => 'search_fields',
+            'TABLE_ADMINS' => $aModule['db_prefix'] . 'admins',
+            'TABLE_INVITES' => $aModule['db_prefix'] . 'invites',
+            'TABLE_PRICES' => $aModule['db_prefix'] . 'prices',
+
+            // database fields
+            'FIELD_ID' => 'id',
+            'FIELD_AUTHOR' => 'author',
+            'FIELD_ADDED' => 'added',
+            'FIELD_CHANGED' => 'changed',
+            'FIELD_NAME' => 'name',
+            'FIELD_TITLE' => 'name',
+            'FIELD_TEXT' => 'desc',
+            'FIELD_PICTURE' => 'picture',
+            'FIELD_COVER' => 'cover',
+            'FIELD_JOIN_CONFIRMATION' => 'join_confirmation',
+            'FIELD_ALLOW_VIEW_TO' => 'allow_view_to',
+            'FIELD_ALLOW_POST_TO' => 'allow_post_to',
+            'FIELD_VIEWS' => 'views',
+            'FIELD_STATUS' => 'status',
+            'FIELD_COMMENTS' => 'comments',
+            'FIELDS_QUICK_SEARCH' => array('name'),
+            'FIELD_LOCATION' => 'location',
+            'FIELD_LOCATION_PREFIX' => 'location',
+            'FIELD_LABELS' => 'labels',
+            'FIELDS_WITH_KEYWORDS' => 'auto', // can be 'auto', array of fields or comma separated string of field names, works only when OBJECT_METATAGS is specified
+
+            'FIELD_PRICE_ROLE_ID' => 'role_id',
+            'FIELD_PRICE_NAME' => 'name',
+
+            // page URIs
+            'URI_VIEW_ENTRY' => 'view-course-profile',
+            'URI_EDIT_ENTRY' => 'edit-course-profile',
+            'URI_EDIT_COVER' => 'edit-course-cover',
+            'URI_JOIN_ENTRY' => 'join-course-profile',
+            'URI_JOINED_ENTRIES' => 'joined-courses',
+            'URI_MANAGE_COMMON' => 'courses-manage',
+            'URI_FAVORITES_LIST' => 'courses-favorites',
+
+            'URL_HOME' => 'page.php?i=courses-home',
+            'URL_ENTRY_FANS' => 'page.php?i=course-fans',
+            'URL_MANAGE_COMMON' => 'page.php?i=courses-manage',
+            'URL_MANAGE_ADMINISTRATION' => 'page.php?i=courses-administration',
+
+            'PARAM_NUM_RSS' => 'bx_courses_num_rss',
+            'PARAM_NUM_CONNECTIONS_QUICK' => 'bx_courses_num_connections_quick',
+
+            'PARAM_SEARCHABLE_FIELDS' => 'bx_courses_searchable_fields',
+            'PARAM_PER_PAGE_BROWSE_SHOWCASE' => 'bx_courses_per_page_browse_showcase',
+            'PARAM_PER_PAGE_BROWSE_RECOMMENDED' => 'bx_courses_per_page_browse_recommended',
+
+            'PARAM_MMODE' => 'bx_courses_members_mode',
+            'PARAM_PAID_JOIN_ENABLED' => true,
+            'PARAM_RECURRING_RESERVE' => 3, // 3 days for recurring payment to be registered
+            'PARAM_PER_PAGE_FOR_FAVORITES_LISTS' => 'bx_courses_per_page_for_favorites_lists',
+            'PARAM_USE_IN' => 'bx_courses_internal_notifications',
+
+            // objects
+            'OBJECT_STORAGE' => 'bx_courses_pics',
+            'OBJECT_STORAGE_COVER' => 'bx_courses_pics',
+            'OBJECT_IMAGES_TRANSCODER_THUMB' => 'bx_courses_thumb',
+            'OBJECT_IMAGES_TRANSCODER_ICON' => 'bx_courses_icon',
+            'OBJECT_IMAGES_TRANSCODER_AVATAR' => 'bx_courses_avatar',
+            'OBJECT_IMAGES_TRANSCODER_AVATAR_BIG' => 'bx_courses_avatar_big',
+            'OBJECT_IMAGES_TRANSCODER_PICTURE' => 'bx_courses_picture',
+            'OBJECT_IMAGES_TRANSCODER_COVER' => 'bx_courses_cover',
+            'OBJECT_IMAGES_TRANSCODER_COVER_THUMB' => 'bx_courses_cover_thumb',
+            'OBJECT_IMAGES_TRANSCODER_GALLERY' => 'bx_courses_gallery',
+            'OBJECT_VIEWS' => 'bx_courses',
+            'OBJECT_VOTES' => 'bx_courses',
+            'OBJECT_SCORES' => 'bx_courses',
+            'OBJECT_FAVORITES' => 'bx_courses',
+            'OBJECT_FEATURED' => 'bx_courses',
+            'OBJECT_COMMENTS' => 'bx_courses',
+            'OBJECT_REPORTS' => 'bx_courses',
+            'OBJECT_METATAGS' => 'bx_courses',
+            'OBJECT_FORM_ENTRY' => 'bx_course',
+            'OBJECT_FORM_ENTRY_DISPLAY_VIEW' => 'bx_course_view',
+            'OBJECT_FORM_ENTRY_DISPLAY_VIEW_FULL' => 'bx_course_view_full', // for "info" tab on view course page
+            'OBJECT_FORM_ENTRY_DISPLAY_ADD' => 'bx_course_add',
+            'OBJECT_FORM_ENTRY_DISPLAY_EDIT' => 'bx_course_edit',
+            'OBJECT_FORM_ENTRY_DISPLAY_EDIT_COVER' => 'bx_course_edit_cover',
+            'OBJECT_FORM_ENTRY_DISPLAY_DELETE' => 'bx_course_delete',
+            'OBJECT_FORM_ENTRY_DISPLAY_INVITE' => 'bx_course_invite',
+            'OBJECT_FORM_PRICE' => 'bx_courses_price',
+            'OBJECT_FORM_PRICE_DISPLAY_ADD' => 'bx_courses_price_add',
+            'OBJECT_FORM_PRICE_DISPLAY_EDIT' => 'bx_courses_price_edit',
+            'OBJECT_MENU_ACTIONS_VIEW_ENTRY' => 'bx_courses_view_actions', // actions menu on view entry page
+            'OBJECT_MENU_ACTIONS_VIEW_ENTRY_MORE' => 'bx_courses_view_actions_more', // actions menu on view entry page for "more" popup
+            'OBJECT_MENU_ACTIONS_VIEW_ENTRY_ALL' => 'bx_courses_view_actions_all', // all actions menu on view entry page
+            'OBJECT_MENU_ACTIONS_MY_ENTRIES' => 'bx_courses_my', // actions menu on profile entries page
+            'OBJECT_MENU_SUBMENU' => 'bx_courses_submenu', // main module submenu
+            'OBJECT_MENU_SUBMENU_VIEW_ENTRY' => 'bx_courses_view_submenu',  // view entry submenu
+            'OBJECT_MENU_SUBMENU_VIEW_ENTRY_COVER' => 'bx_courses_view_submenu_cover',  // view entry submenu displayed in cover
+            'OBJECT_MENU_SUBMENU_VIEW_ENTRY_MAIN_SELECTION' => 'courses-home', // first item in view entry submenu from main module submenu
+            'OBJECT_MENU_SNIPPET_META' => 'bx_courses_snippet_meta', // menu for snippet meta info
+            'OBJECT_MENU_MANAGE_TOOLS' => 'bx_courses_menu_manage_tools', //manage menu in content administration tools
+            'OBJECT_PAGE_VIEW_ENTRY' => 'bx_courses_view_profile',
+            'OBJECT_PAGE_VIEW_ENTRY_CLOSED' => 'bx_courses_view_profile_closed',
+            'OBJECT_PRIVACY_VIEW' => 'bx_courses_allow_view_to',
+            'OBJECT_PRIVACY_LIST_VIEW' => 'bx_courses_allow_view_favorite_list',
+            'OBJECT_PRIVACY_VIEW_NOTIFICATION_EVENT' => 'bx_courses_allow_view_notification_to',
+            'OBJECT_PRIVACY_POST' => 'bx_courses_allow_post_to',
+            'OBJECT_GRID_ADMINISTRATION' => 'bx_courses_administration',
+            'OBJECT_GRID_COMMON' => 'bx_courses_common',
+            'OBJECT_GRID_CONNECTIONS' => 'bx_courses_fans',
+            'OBJECT_GRID_INVITES' => 'bx_courses_invites',
+            'OBJECT_GRID_PRICES_MANAGE' => 'bx_courses_prices_manage',
+            'OBJECT_GRID_PRICES_VIEW' => 'bx_courses_prices_view',
+            'OBJECT_CONNECTIONS' => 'bx_courses_fans',
+            'OBJECT_UPLOADERS_COVER' => array('bx_courses_cover_crop'),
+            'OBJECT_UPLOADERS_PICTURE' => array('bx_courses_picture_crop'),
+            'OBJECT_PRE_LIST_ROLES' => 'bx_courses_roles',
+            'OBJECT_PRE_LIST_PERIOD_UNITS' => 'bx_courses_period_units',
+
+            'BADGES_AVALIABLE' => true,
+            
+            'INVITES_KEYS_LIFETIME' => 86400,
+
+            'EMAIL_INVITATION' => 'bx_courses_invitation',
+            'EMAIL_JOIN_REQUEST' => 'bx_courses_join_request',
+            'EMAIL_JOIN_CONFIRM' => 'bx_courses_join_confirm',
+            'EMAIL_FAN_BECOME_ADMIN' => 'bx_courses_fan_become_admin',
+            'EMAIL_ADMIN_BECOME_FAN' => 'bx_courses_admin_become_fan',
+            'EMAIL_FAN_REMOVE' => 'bx_courses_fan_remove',
+            'EMAIL_FAN_SET_ROLE' => 'bx_courses_set_role',
+            'EMAIL_JOIN_REJECT' => 'bx_courses_join_reject',
+
+            'TRIGGER_MENU_PROFILE_VIEW_SUBMENU' => 'trigger_group_view_submenu',
+            'TRIGGER_MENU_PROFILE_SNIPPET_META' => 'trigger_group_snippet_meta',
+            'TRIGGER_MENU_PROFILE_VIEW_ACTIONS' => 'trigger_group_view_actions',
+            'TRIGGER_PAGE_VIEW_ENTRY' => 'trigger_page_group_view_entry',
+
+            // menu items which visibility depends on custom visibility checking
+            'MENU_ITEM_TO_METHOD' => array (
+                'bx_courses_view_actions' => $this->_aMenuItems2MethodsActions,
+                'bx_courses_view_actions_more' => $this->_aMenuItems2MethodsActions,
+                'bx_courses_view_actions_all' => $this->_aMenuItems2MethodsActions,
+            ),
+
+            // informer messages
+            'INFORMERS' => array (
+                'status' => array (
+                    'name' => 'bx-courses-status-not-active',
+                    'map' => array (
+                        BX_PROFILE_STATUS_PENDING => '_bx_courses_txt_account_pending',
+                        BX_PROFILE_STATUS_SUSPENDED => '_bx_courses_txt_account_suspended',
+                    ),
+                ),
+            ),
+
+            // some language keys
+            'T' => array (
+                'txt_sample_single' => '_bx_courses_txt_sample_single',
+                'txt_sample_single_with_article' => '_bx_courses_txt_sample_single_with_article',
+                'txt_sample_comment_single' => '_bx_courses_txt_sample_comment_single',
+                'txt_sample_vote_single' => '_bx_courses_txt_sample_vote_single',
+                'txt_sample_score_up_single' => '_bx_courses_txt_sample_score_up_single',
+                'txt_sample_score_down_single' => '_bx_courses_txt_sample_score_down_single',
+                'txt_private_group' => '_bx_courses_txt_private_entry',
+                'txt_N_fans' => '_bx_courses_txt_N_fans',
+                'txt_ntfs_join_invitation' => '_bx_courses_txt_ntfs_join_invitation',
+                'txt_ntfs_join_request' => '_bx_courses_txt_ntfs_join_request',
+                'txt_ntfs_fan_added' => '_bx_courses_txt_ntfs_fan_added',
+                'txt_ntfs_timeline_post_common' => '_bx_courses_txt_ntfs_timeline_post_common',
+                'option_members_mode_multi_roles' => '_bx_courses_option_members_mode_multi_roles',
+                'form_field_author' => '_bx_courses_form_entry_input_author',
+                'menu_item_title_befriend_sent' => '_bx_courses_menu_item_title_befriend_sent',
+                'menu_item_title_unfriend_cancel_request' => '_bx_courses_menu_item_title_unfriend_cancel_request',
+                'menu_item_title_befriend_confirm' => '_bx_courses_menu_item_title_befriend_confirm',
+                'menu_item_title_unfriend_reject_request' => '_bx_courses_menu_item_title_unfriend_reject_request',
+                'menu_item_title_befriend' => '_bx_courses_menu_item_title_befriend',
+                'menu_item_title_unfriend' => '_bx_courses_menu_item_title_unfriend',
+                'grid_action_err_delete' => '_bx_courses_grid_action_err_delete',
+                'grid_txt_account_manager' => '_bx_courses_grid_txt_account_manager',
+                'filter_item_active' => '_bx_courses_grid_filter_item_title_adm_active',
+                'filter_item_pending' => '_bx_courses_grid_filter_item_title_adm_pending',
+                'filter_item_suspended' => '_bx_courses_grid_filter_item_title_adm_suspended',
+                'filter_item_select_one_filter1' => '_bx_courses_grid_filter_item_title_adm_select_one_filter1',
+                'menu_item_manage_my' => '_bx_courses_menu_item_title_manage_my',
+                'menu_item_manage_all' => '_bx_courses_menu_item_title_manage_all',
+                'menu_item_title_become_fan_sent' => '_bx_courses_menu_item_title_become_fan_sent',
+                'menu_item_title_leave_group_cancel_request' => '_bx_courses_menu_item_title_leave_entry_cancel_request',
+                'menu_item_title_become_fan' => '_bx_courses_menu_item_title_become_fan',
+                'menu_item_title_leave_group' => '_bx_courses_menu_item_title_leave_entry',
+                'txt_all_entries_by_author' => '_bx_courses_page_title_browse_by_author',
+                'txt_invitation_popup_title' => '_bx_courses_txt_invite_popup_title',
+                'txt_invitation_popup_text' => '_bx_courses_txt_invite_popup_text',
+                'txt_invitation_popup_accept_button' => '_bx_courses_txt_invite_popup_button_accept',
+                'txt_invitation_popup_decline_button' => '_bx_courses_txt_invite_popup_button_decline',
+                'txt_invitation_popup_error_invitation_absent' => '_bx_courses_txt_invite_popup_error_invitation_absent',
+                'txt_invitation_popup_error_wrong_user' => '_bx_courses_txt_invite_popup_error_invitation_wrong_user',
+                'txt_n_unit' => '_bx_courses_txt_n_unit',
+                'txt_buy_title' => '_bx_courses_grid_action_title_buy_title',
+                'txt_cart_item_title' => '_bx_courses_txt_cart_item_title',
+                'txt_subscribe_title' => '_bx_courses_grid_action_title_subscribe_title',
+                'msg_performed' => '_bx_courses_msg_performed',
+                'err_cannot_perform' => '_bx_courses_err_cannot_perform',
+            ),
+
+        );
+
+        $this->_aJsClasses = array(
+            'main' => 'BxCoursesMain',
+            'manage_tools' => 'BxCoursesManageTools',
+            'invite_popup' => 'BxCoursesInvitePopup',
+            'prices' => 'BxCoursesPrices'
+        );
+
+        $this->_aJsObjects = array(
+            'main' => 'oBxCoursesMain',
+            'manage_tools' => 'oBxCoursesManageTools',
+            'invite_popup' => 'oBxCoursesInvitePopup',
+            'prices' => 'oBxCoursesPrices'
+        );
+
+        $this->_aGridObjects = array(
+            'common' => $this->CNF['OBJECT_GRID_COMMON'],
+            'administration' => $this->CNF['OBJECT_GRID_ADMINISTRATION'],
+        );
+    }
+
+}
+
+/** @} */

+ 22 - 0
modules/boonex/courses/updates/12.0.0_12.0.1/source/classes/BxCoursesCronPruning.php

@@ -0,0 +1,22 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Courses Courses
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxCoursesCronPruning extends BxBaseModCoursesCronPruning
+{
+    public function __construct()
+    {
+        $this->_sModule = 'bx_courses';
+
+        parent::__construct();
+    }
+}
+
+/** @} */

+ 22 - 0
modules/boonex/courses/updates/12.0.0_12.0.1/source/classes/BxCoursesFormPrice.php

@@ -0,0 +1,22 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Courses Courses
+ * @ingroup     UnaModules
+ * 
+ * @{
+ */
+
+class BxCoursesFormPrice extends BxBaseModGroupsFormPrice
+{
+    public function __construct($aInfo, $oTemplate = false)
+    {
+        $this->_sModule = 'bx_courses';
+
+        parent::__construct($aInfo, $oTemplate);
+    }
+}
+
+/** @} */

+ 22 - 0
modules/boonex/courses/updates/12.0.0_12.0.1/source/classes/BxCoursesGridPricesManage.php

@@ -0,0 +1,22 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Courses Courses
+ * @ingroup     UnaModules
+ * 
+ * @{
+ */
+
+class BxCoursesGridPricesManage extends BxBaseModGroupsGridPricesManage
+{
+    public function __construct ($aOptions, $oTemplate = false)
+    {
+        $this->_sModule = 'bx_courses';
+
+        parent::__construct ($aOptions, $oTemplate);
+    }
+}
+
+/** @} */

+ 22 - 0
modules/boonex/courses/updates/12.0.0_12.0.1/source/classes/BxCoursesGridPricesView.php

@@ -0,0 +1,22 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Courses Courses
+ * @ingroup     UnaModules
+ * 
+ * @{
+ */
+
+class BxCoursesGridPricesView extends BxBaseModGroupsGridPricesView
+{
+    public function __construct ($aOptions, $oTemplate = false)
+    {
+        $this->_sModule = 'bx_courses';
+
+        parent::__construct ($aOptions, $oTemplate);
+    }
+}
+
+/** @} */

+ 60 - 0
modules/boonex/courses/updates/12.0.0_12.0.1/source/classes/BxCoursesMenuViewActionsAll.php

@@ -0,0 +1,60 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Courses Courses
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+/**
+ * View entry all actions menu
+ */
+class BxCoursesMenuViewActionsAll extends BxBaseModGroupsMenuViewActionsAll
+{
+    public function __construct($aObject, $oTemplate = false)
+    {
+        $this->_sModule = 'bx_courses';
+
+        parent::__construct($aObject, $oTemplate);
+    }
+
+    protected function _getMenuItemJoinCourseProfile($aItem)
+    {
+        return $this->_getMenuItemByNameActions($aItem);
+    }
+
+    protected function _getMenuItemEditCourseCover($aItem)
+    {
+        return $this->_getMenuItemByNameActionsMore($aItem);
+    }
+
+    protected function _getMenuItemEditCourseProfile($aItem)
+    {
+        return $this->_getMenuItemByNameActionsMore($aItem);
+    }
+
+    protected function _getMenuItemEditCoursePricing($aItem)
+    {
+        return $this->_getMenuItemByNameActionsMore($aItem);
+    }
+
+    protected function _getMenuItemInviteToCourse($aItem)
+    {
+        return $this->_getMenuItemByNameActionsMore($aItem);
+    }
+
+    protected function _getMenuItemDeleteCourseProfile($aItem)
+    {
+        return $this->_getMenuItemByNameActionsMore($aItem);
+    }
+    
+    protected function _getMenuItemProfileSetBadges($aItem)
+    {
+        return $this->_getMenuItemByNameActions($aItem);
+    }
+}
+
+/** @} */

+ 24 - 0
modules/boonex/courses/updates/12.0.0_12.0.1/source/classes/BxCoursesPageListEntry.php

@@ -0,0 +1,24 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Courses Courses
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+/**
+ * List entry page
+ */
+class BxCoursesPageListEntry extends BxBaseModGroupsPageListEntry
+{    
+    public function __construct($aObject, $oTemplate = false)
+    {
+        $this->MODULE = 'bx_courses';
+        parent::__construct($aObject, $oTemplate);
+    }
+}
+
+/** @} */

+ 152 - 0
modules/boonex/courses/updates/12.0.0_12.0.1/source/install/config.php

@@ -0,0 +1,152 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Courses Courses
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_courses',
+    'title' => 'Courses',
+    'note' => 'Basic course profiles functionality.',
+    'version' => '12.0.1',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '12.1.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/courses/',
+    'home_uri' => 'courses',
+
+    'db_prefix' => 'bx_courses_',
+    'class_prefix' => 'BxCourses',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Courses',
+
+    /**
+     * Connections.
+     */
+    'connections' => array(
+        'sys_profiles_friends' => array ('type' => 'profiles'),
+        'sys_profiles_subscriptions' => array ('type' => 'profiles'),
+    ),
+
+    /**
+     * Menu triggers.
+     */
+    'menu_triggers' => array(
+    	'trigger_profile_view_submenu',
+        'trigger_group_view_submenu',
+        'trigger_group_snippet_meta',
+        'trigger_group_view_actions',
+    ),
+
+    /**
+     * Page triggers.
+     */
+    'page_triggers' => array (
+    	'trigger_page_group_view_entry', 
+    ),
+
+	/**
+     * Storage objects to automatically delete files from upon module uninstallation.
+     * Note. Don't add storage objects used in transcoder objects.
+     */
+    'storages' => array(
+    	'bx_courses_pics'
+    ),
+
+	/**
+     * Transcoders.
+     */
+    'transcoders' => array(
+    	'bx_courses_icon', 
+    	'bx_courses_thumb', 
+    	'bx_courses_avatar', 
+        'bx_courses_avatar_big', 
+    	'bx_courses_picture', 
+    	'bx_courses_cover', 
+    	'bx_courses_cover_thumb',
+        'bx_courses_gallery'
+    ),
+
+    /**
+     * Extended Search Forms.
+     */
+    'esearches' => array(
+        'bx_courses',
+    	'bx_courses_cmts',
+    ),
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'uninstall' => array (
+    	'process_esearches' => 1,
+        'execute_sql' => 1,
+        'update_languages' => 1,
+    	'process_connections' => 1,
+        'process_deleted_profiles' => 1,
+    	'update_relations' => 1,        
+        'clear_db_cache' => 1,
+    ),
+    'enable' => array(
+        'execute_sql' => 1,
+    	'update_relations' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'enable_success' => array(
+    	'process_menu_triggers' => 1,
+    	'process_page_triggers' => 1,
+    	'process_esearches' => 1,
+    	'register_transcoders' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable' => array (
+        'execute_sql' => 1,
+        'unregister_transcoders' => 1,
+        'update_relations' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable_failed' => array (
+    	'register_transcoders' => 1,
+    	'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Dependencies Section
+     */
+    'dependencies' => array(),
+
+    /**
+     * Connections Section
+     */
+    'relations' => array(
+        'bx_timeline',
+        'bx_notifications',
+    ),
+);
+
+/** @} */

+ 439 - 0
modules/boonex/courses/updates/12.0.0_12.0.1/source/install/langs/en.xml

@@ -0,0 +1,439 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources name="en" flag="gb" title="English">
+    <string name="_bx_courses"><![CDATA[Courses]]></string>
+    <string name="_bx_courses_cmts"><![CDATA[Courses' Comments]]></string>
+
+    <string name="_bx_courses_option_num_connections_quick"><![CDATA[Number of items in friends block]]></string>
+    <string name="_bx_courses_option_per_page_browse"><![CDATA[Number of items per page]]></string>
+    <string name="_bx_courses_option_num_rss"><![CDATA[Number of items in RSS feed]]></string>
+    <string name="_bx_courses_option_searchable_fields"><![CDATA[Searchable fields]]></string>
+    <string name="_bx_courses_option_members_mode"><![CDATA[Special mode for course members]]></string>
+    <string name="_bx_courses_option_members_mode_multi_roles"><![CDATA[Multi Roles]]></string>
+    <string name="_bx_courses_option_per_page_for_favorites_lists"><![CDATA[Number of favorite lists per page]]></string>
+    <string name="_bx_courses_option_internal_notifications"><![CDATA[Use internal notifications]]></string>
+
+    <string name="_bx_courses_form_profile"><![CDATA[Courses]]></string>
+    <string name="_bx_courses_form_profile_display_add"><![CDATA[Add Course]]></string>
+    <string name="_bx_courses_form_profile_display_edit"><![CDATA[Edit Course]]></string>
+    <string name="_bx_courses_form_profile_display_edit_cover"><![CDATA[Edit Cover]]></string>
+    <string name="_bx_courses_form_profile_display_delete"><![CDATA[Delete Course]]></string>
+    <string name="_bx_courses_form_profile_display_view"><![CDATA[View Course]]></string>
+    <string name="_bx_courses_form_profile_display_view_full"><![CDATA[Full View Course]]></string>
+    <string name="_bx_courses_form_profile_display_invite"><![CDATA[Invite to Course]]></string>
+    <string name="_bx_courses_form_entry_input_author"><![CDATA[Author]]></string>
+    <string name="_bx_courses_form_profile_input_sys_do_submit"><![CDATA[Submit]]></string>
+    <string name="_bx_courses_form_profile_input_sys_join_confirm"><![CDATA[Join confirmation]]></string>
+    <string name="_bx_courses_form_profile_input_join_confirm"><![CDATA[Join confirmation]]></string>
+    <string name="_bx_courses_form_profile_input_sys_allow_view_to"><![CDATA[Visible to]]></string>
+    <string name="_bx_courses_form_profile_input_allow_view_to"><![CDATA[Visible to]]></string>
+    <string name="_bx_courses_form_profile_input_allow_view_favorite_list"><![CDATA[Visibility]]></string>
+    <string name="_bx_courses_form_profile_input_allow_view_to_desc"><![CDATA[Closed - anyone can find the course and see who's in it, only students can see posts. Secret - only students can find the course and see posts.]]></string>
+    <string name="_bx_courses_form_profile_input_sys_allow_post_to"><![CDATA[Who can post]]></string>
+    <string name="_bx_courses_form_profile_input_allow_post_to"><![CDATA[Who can post]]></string>
+    <string name="_bx_courses_form_profile_input_sys_initial_members"><![CDATA[Invite Students]]></string>
+    <string name="_bx_courses_form_profile_input_initial_members"><![CDATA[Invite Students]]></string>
+    <string name="_bx_courses_form_profile_input_sys_name"><![CDATA[Name]]></string>
+    <string name="_bx_courses_form_profile_input_name"><![CDATA[Name]]></string>
+    <string name="_bx_courses_form_profile_input_name_err"><![CDATA[This information is essential. Please, fill in this field.]]></string>
+    <string name="_bx_courses_form_profile_input_sys_desc"><![CDATA[Description]]></string>
+    <string name="_bx_courses_form_profile_input_desc"><![CDATA[Description]]></string>
+    <string name="_bx_courses_form_profile_input_sys_cat"><![CDATA[Category]]></string>
+    <string name="_bx_courses_form_profile_input_cat"><![CDATA[Category]]></string>
+    <string name="_bx_courses_form_profile_input_cat_err"><![CDATA[Category field is mandatory]]></string>
+    <string name="_bx_courses_form_profile_input_sys_picture"><![CDATA[Course Picture]]></string>
+    <string name="_bx_courses_form_profile_input_picture"><![CDATA[Upload New Course Picture]]></string>
+    <string name="_bx_courses_form_profile_input_picture_err"><![CDATA[Course picture is mandatory.]]></string>
+    <string name="_bx_courses_form_profile_input_sys_cover"><![CDATA[Cover Picture]]></string>
+    <string name="_bx_courses_form_profile_input_cover"><![CDATA[Upload New Cover Picture]]></string>
+    <string name="_bx_courses_form_profile_input_sys_delete_confirm"><![CDATA[Delete confirmation]]></string>
+    <string name="_bx_courses_form_profile_input_delete_confirm"><![CDATA[I am sure I want to delete this course]]></string>
+    <string name="_bx_courses_form_profile_input_delete_confirm_info"><![CDATA[This action can not be undone.]]></string>
+    <string name="_bx_courses_form_profile_input_delete_confirm_error"><![CDATA[Please check this checkbox if you really want to delete course.]]></string>
+
+    <string name="_bx_courses_form_price"><![CDATA[Price]]></string>
+    <string name="_bx_courses_form_price_display_add"><![CDATA[Add]]></string>
+    <string name="_bx_courses_form_price_display_edit"><![CDATA[Edit]]></string>
+    <string name="_bx_courses_form_price_input_sys_id"><![CDATA[ID]]></string>
+    <string name="_bx_courses_form_price_input_sys_role_id"><![CDATA[Role ID]]></string>
+    <string name="_bx_courses_form_price_input_sys_name"><![CDATA[Name]]></string>
+    <string name="_bx_courses_form_price_input_name"><![CDATA[Name]]></string>
+    <string name="_bx_courses_form_price_input_inf_name"><![CDATA[Unique value which will be used in back end and API calls]]></string>
+    <string name="_bx_courses_form_price_input_err_name"><![CDATA[You need to enter a unique value here]]></string>
+    <string name="_bx_courses_form_price_input_sys_period"><![CDATA[Period]]></string>
+    <string name="_bx_courses_form_price_input_period"><![CDATA[Period]]></string>
+    <string name="_bx_courses_form_price_input_inf_period"><![CDATA[Use 0 for lifetime]]></string>
+    <string name="_bx_courses_form_price_input_sys_period_unit"><![CDATA[Period unit]]></string>
+    <string name="_bx_courses_form_price_input_period_unit"><![CDATA[Period unit]]></string>
+    <string name="_bx_courses_form_price_input_inf_period_unit"><![CDATA[Leave empty for lifetime level.]]></string>
+    <string name="_bx_courses_form_price_input_err_period_unit"><![CDATA[You need to select a period unit here.]]></string>
+    <string name="_bx_courses_form_price_input_sys_price"><![CDATA[Price]]></string>
+    <string name="_bx_courses_form_price_input_price"><![CDATA[Price]]></string>
+    <string name="_bx_courses_form_price_input_inf_price"><![CDATA[Use 0 or leave empty to create free level.]]></string>
+    <string name="_bx_courses_form_price_input_sys_do_submit"><![CDATA[Submit]]></string>
+    <string name="_bx_courses_form_price_input_do_submit"><![CDATA[Submit]]></string>
+    <string name="_bx_courses_form_price_input_sys_do_cancel"><![CDATA[Cancel]]></string>
+    <string name="_bx_courses_form_price_input_do_cancel"><![CDATA[Cancel]]></string>
+
+    <string name="_bx_courses_acl_action_create_profile"><![CDATA[Create Course]]></string>
+    <string name="_bx_courses_acl_action_use_paid_join"><![CDATA[Use paid join]]></string>
+    <string name="_bx_courses_acl_action_delete_profile"><![CDATA[Delete Course]]></string>
+    <string name="_bx_courses_acl_action_view_profile"><![CDATA[View Course]]></string>
+    <string name="_bx_courses_acl_action_delete_any_profile"><![CDATA[Delete Any Course]]></string>
+    <string name="_bx_courses_acl_action_delete_invites"><![CDATA[Delete Invites]]></string>
+
+    <string name="_bx_courses_page_title_sys_joined_entries"><![CDATA[Profile Courses]]></string>
+    <string name="_bx_courses_page_title_joined_entries"><![CDATA[Profile Courses]]></string>
+    <string name="_bx_courses_page_title_sys_create_profile"><![CDATA[Create Course]]></string>
+    <string name="_bx_courses_page_title_create_profile"><![CDATA[Create Course]]></string>
+    <string name="_bx_courses_page_title_sys_edit_profile"><![CDATA[Edit Course]]></string>
+    <string name="_bx_courses_page_title_edit_profile"><![CDATA[Edit Course]]></string>
+    <string name="_bx_courses_page_title_sys_edit_profile_cover"><![CDATA[Edit Course Cover]]></string>
+    <string name="_bx_courses_page_title_edit_profile_cover"><![CDATA[Edit Cover]]></string>
+    <string name="_bx_courses_page_title_sys_delete_profile"><![CDATA[Delete Course]]></string>
+    <string name="_bx_courses_page_title_delete_profile"><![CDATA[Delete Course]]></string>
+    <string name="_bx_courses_page_title_sys_join_profile"><![CDATA[Join Course]]></string>
+    <string name="_bx_courses_page_title_join_profile"><![CDATA[Join Course]]></string>
+    <string name="_bx_courses_page_title_sys_view_profile_closed"><![CDATA[View Closed Course]]></string>
+    <string name="_bx_courses_page_title_sys_view_profile"><![CDATA[View Course]]></string>
+    <string name="_bx_courses_page_title_view_profile"><![CDATA[{display_name}]]></string>
+    <string name="_bx_courses_page_title_browse"><![CDATA[Courses]]></string>
+    <string name="_bx_courses_page_title_browse_by_author"><![CDATA[Courses of {display_name}]]></string>
+    <string name="_bx_courses_page_title_browse_featured"><![CDATA[Featured Courses]]></string>
+    <string name="_bx_courses_page_title_browse_top"><![CDATA[Top Courses]]></string>
+    <string name="_bx_courses_page_title_browse_recent"><![CDATA[New Courses]]></string>
+    <string name="_bx_courses_page_title_browse_connections"><![CDATA[{0} connections]]></string>
+    <string name="_bx_courses_page_title_browse_connections_mutual"><![CDATA[{0} and {1} mutual connections]]></string>
+    <string name="_bx_courses_page_title_sys_profile_friends"><![CDATA[Friends]]></string>
+    <string name="_bx_courses_page_title_profile_friends"><![CDATA[Friends]]></string>
+    <string name="_bx_courses_page_title_sys_entry_fans"><![CDATA[Students]]></string>
+    <string name="_bx_courses_page_title_entry_fans"><![CDATA[Students]]></string>
+    <string name="_bx_courses_page_title_sys_profile_comments"><![CDATA[Comments]]></string>
+    <string name="_bx_courses_page_title_profile_comments"><![CDATA[Comments]]></string>
+    <string name="_bx_courses_page_block_title_entry_reports"><![CDATA[Reports]]></string>
+    <string name="_bx_courses_page_title_sys_profile_info"><![CDATA[Course Info]]></string>
+    <string name="_bx_courses_page_title_profile_info"><![CDATA[Info about {display_name}]]></string>
+    <string name="_bx_courses_page_title_sys_profile_pricing"><![CDATA[Pricing]]></string>
+    <string name="_bx_courses_page_title_profile_pricing"><![CDATA[Pricing]]></string>
+    <string name="_bx_courses_page_title_sys_recent"><![CDATA[New Courses]]></string>
+    <string name="_bx_courses_page_title_recent"><![CDATA[New Courses]]></string>
+    <string name="_bx_courses_page_title_sys_manage"><![CDATA[Manage Own Courses]]></string>
+    <string name="_bx_courses_page_title_sys_manage_administration"><![CDATA[Manage All Courses]]></string>
+    <string name="_bx_courses_page_title_manage"><![CDATA[Manage Courses]]></string>
+    <string name="_bx_courses_page_title_sys_top"><![CDATA[Top Courses]]></string>
+    <string name="_bx_courses_page_title_top"><![CDATA[Top Courses]]></string>
+    <string name="_bx_courses_page_title_sys_joined"><![CDATA[Attended  Courses]]></string>
+    <string name="_bx_courses_page_title_joined"><![CDATA[Attended Courses]]></string>
+    <string name="_bx_courses_page_title_sys_invite_to_course"><![CDATA[Invite Students to the Course]]></string>
+    <string name="_bx_courses_page_title_invite_to_course"><![CDATA[Invite Students to the Course]]></string>
+    <string name="_bx_courses_page_title_sys_entries_search"><![CDATA[Search]]></string>
+    <string name="_bx_courses_page_title_entries_search"><![CDATA[Search]]></string>
+    <string name="_bx_courses_page_title_sys_entries_favorites"><![CDATA[Favorives Courses]]></string>
+    <string name="_bx_courses_page_title_entries_favorites"><![CDATA[Favorives Courses]]></string>
+
+    <string name="_bx_courses_page_block_title_sys_entries_actions"><![CDATA[Courses actions]]></string>
+    <string name="_bx_courses_page_block_title_entries_actions"><![CDATA[Courses actions]]></string>
+    <string name="_bx_courses_page_block_title_favorites_entries"><![CDATA["{title}" List]]></string>
+    <string name="_bx_courses_page_block_title_favorites_entries_info"><![CDATA[Info]]></string>
+    <string name="_bx_courses_page_block_title_favorites_entries_actions"><![CDATA[Favorites List Actions]]></string>
+    <string name="_bx_courses_page_block_title_sys_entries_of_author"><![CDATA[Courses of author]]></string>
+    <string name="_bx_courses_page_block_title_entries_of_author"><![CDATA[Courses by {display_name}]]></string>
+    <string name="_bx_courses_page_block_title_favorites_of_author"><![CDATA[Favorite Courses]]></string>
+    <string name="_bx_courses_page_block_title_sys_favorites_of_author"><![CDATA[Favorite Courses]]></string>
+    <string name="_bx_courses_page_block_title_sys_joined_entries"><![CDATA[Attended Courses]]></string>
+    <string name="_bx_courses_page_block_title_joined_entries"><![CDATA[Attended Courses]]></string>
+    <string name="_bx_courses_page_block_title_create_profile"><![CDATA[Create Course]]></string>
+    <string name="_bx_courses_page_block_title_edit_profile"><![CDATA[Edit Course]]></string>
+    <string name="_bx_courses_page_block_title_edit_profile_cover"><![CDATA[Edit Cover]]></string>
+    <string name="_bx_courses_page_block_title_delete_profile"><![CDATA[Delete Course]]></string>
+    <string name="_bx_courses_page_block_title_join_profile"><![CDATA[Join Course]]></string>
+    <string name="_bx_courses_page_block_title_profile_info_link"><![CDATA[About <a href="{profile_link}">{display_name}</a>]]></string>
+    <string name="_bx_courses_page_block_title_profile_info"><![CDATA[Info]]></string>
+    <string name="_bx_courses_page_block_title_system_profile_info"><![CDATA[Info]]></string>
+    <string name="_bx_courses_page_block_title_system_profile_pricing"><![CDATA[Pricing]]></string>
+    <string name="_bx_courses_page_block_title_profile_pricing"><![CDATA[Pricing]]></string>
+    <string name="_bx_courses_page_block_title_profile_pricing_link"><![CDATA[Pricing of <a href="{profile_link}">{display_name}</a>]]></string>
+    <string name="_bx_courses_page_block_title_profile_description"><![CDATA[Description]]></string>
+    <string name="_bx_courses_page_block_title_profile_friends_link"><![CDATA[Friends of <a href="{profile_link}">{display_name}</a>]]></string>
+    <string name="_bx_courses_page_block_title_profile_friends"><![CDATA[Friends]]></string>
+    <string name="_bx_courses_page_block_title_system_profile_friends"><![CDATA[Friends]]></string>
+    <string name="_bx_courses_page_block_title_admins"><![CDATA[Instructors]]></string>
+    <string name="_bx_courses_page_block_title_fans_link"><![CDATA[Students of <a href="{profile_link}">{display_name}</a>]]></string>
+    <string name="_bx_courses_page_block_title_fans"><![CDATA[Students]]></string>
+    <string name="_bx_courses_page_block_title_system_fans"><![CDATA[Students]]></string>
+    <string name="_bx_courses_page_block_title_fans_invites"><![CDATA[Invites]]></string>
+    <string name="_bx_courses_page_block_title_system_invites"><![CDATA[Invites]]></string>
+    <string name="_bx_courses_page_block_title_profile_location"><![CDATA[Location]]></string>
+    <string name="_bx_courses_page_block_title_profile_comments"><![CDATA[Comments]]></string>
+    <string name="_bx_courses_page_block_title_profile_comments_link"><![CDATA[Comments to <a href="{entry_link}">{title}</a>]]></string>
+    <string name="_bx_courses_page_block_title_profile_actions"><![CDATA[Actions]]></string>
+    <string name="_bx_courses_page_block_title_featured_profiles"><![CDATA[Featured Courses]]></string>
+    <string name="_bx_courses_page_block_title_latest_profiles"><![CDATA[New Courses]]></string>
+    <string name="_bx_courses_page_block_title_system_manage"><![CDATA[Manage Own Courses]]></string>
+    <string name="_bx_courses_page_block_title_system_manage_administration"><![CDATA[Manage All Courses]]></string>
+    <string name="_bx_courses_page_block_title_manage"><![CDATA[Manage Courses]]></string>
+    <string name="_bx_courses_page_block_title_top_profiles"><![CDATA[Top Courses]]></string>
+    <string name="_bx_courses_page_block_title_joined_profiles"><![CDATA[Attended Courses]]></string>
+    <string name="_bx_courses_page_block_title_entry_all_actions"><![CDATA[All Actions]]></string>
+    <string name="_bx_courses_page_block_title_entry_social_sharing"><![CDATA[Share]]></string>
+    <string name="_bx_courses_page_block_title_categories"><![CDATA[Courses Categories]]></string>
+    <string name="_bx_courses_page_block_title_invite_to_course"><![CDATA[Invite Students to the Course]]></string>
+    <string name="_bx_courses_page_block_title_search_form"><![CDATA[Search Form]]></string>
+    <string name="_bx_courses_page_block_title_search_results"><![CDATA[Search Results]]></string>
+    <string name="_bx_courses_page_block_title_search_form_cmts"><![CDATA[Comments Search Form]]></string>
+    <string name="_bx_courses_page_block_title_search_results_cmts"><![CDATA[Comments Search Results]]></string>
+    <string name="_bx_courses_page_block_title_sys_featured_entries_view_showcase"><![CDATA[Featured Courses (Showcase View)]]></string>
+    <string name="_bx_courses_page_block_title_featured_entries_view_showcase"><![CDATA[Featured Courses]]></string>
+    <string name="_bx_courses_page_block_title_sys_recommended_entries_view_showcase"><![CDATA[Recommended Courses (Showcase View)]]></string>
+    <string name="_bx_courses_page_block_title_recommended_entries_view_showcase"><![CDATA[Recommended Courses]]></string>
+    <string name="_bx_courses_page_block_title_sys_labels_tree"><![CDATA[Labels tree]]></string>
+    <string name="_bx_courses_page_block_title_labels_tree"><![CDATA[Labels tree]]></string>
+    <string name="_bx_courses_page_block_title_sys_browse_by_label"><![CDATA[Browse by label]]></string>
+    <string name="_bx_courses_page_block_title_browse_by_label"><![CDATA[Browse by label]]></string>
+    <string name="_bx_courses_page_block_title_sys_labels_breadcrumbs"><![CDATA[Labels breadcrumbs]]></string>
+    <string name="_bx_courses_page_block_title_labels_breadcrumbs"><![CDATA[Labels breadcrumbs]]></string>
+
+
+    <string name="_bx_courses_menu_title_submenu"><![CDATA[Courses Submenu]]></string>
+    <string name="_bx_courses_menu_set_title_submenu"><![CDATA[Courses Submenu]]></string>
+    <string name="_bx_courses_menu_set_title_view_profile_actions"><![CDATA[Course Actions]]></string>
+    <string name="_bx_courses_menu_title_view_profile_actions"><![CDATA[Course Actions]]></string>
+    <string name="_bx_courses_menu_set_title_view_profile_actions_more"><![CDATA[Course More Actions]]></string>
+    <string name="_bx_courses_menu_title_view_profile_actions_more"><![CDATA[Course More Actions]]></string>
+    <string name="_bx_courses_menu_set_title_view_profile_submenu"><![CDATA[View Course Submenu]]></string>
+    <string name="_bx_courses_menu_title_view_profile_submenu"><![CDATA[View Course Submenu]]></string>
+    <string name="_bx_courses_menu_title_view_profile_submenu_cover"><![CDATA[Course Cover Submenu]]></string>
+    <string name="_bx_courses_menu_title_entries_my"><![CDATA[Profile Courses Action Menu]]></string>
+    <string name="_bx_courses_menu_set_title_entries_my"><![CDATA[Profile Courses Menu]]></string>
+    <string name="_bx_courses_menu_set_title_manage_tools"><![CDATA[Manage Tools Submenu]]></string>
+    <string name="_bx_courses_menu_title_manage_tools"><![CDATA[Manage Tools Submenu]]></string>
+    <string name="_bx_courses_menu_item_title_system_delete"><![CDATA[Delete]]></string>
+    <string name="_bx_courses_menu_item_title_delete"><![CDATA[Delete]]></string>
+    <string name="_bx_courses_menu_item_title_system_delete_with_content"><![CDATA[Delete With Content]]></string>
+    <string name="_bx_courses_menu_item_title_delete_with_content"><![CDATA[Delete With Content]]></string>
+    <string name="_bx_courses_menu_item_title_system_clear_reports"><![CDATA[Clear reports]]></string>
+    <string name="_bx_courses_menu_item_title_clear_reports"><![CDATA[Clear reports]]></string>
+    <string name="_bx_courses_menu_item_title_system_edit_cover"><![CDATA[Edit Cover]]></string>
+    <string name="_bx_courses_menu_item_title_edit_cover"><![CDATA[Edit Cover]]></string>
+    <string name="_bx_courses_menu_item_title_system_edit_pricing"><![CDATA[Edit Pricing]]></string>
+    <string name="_bx_courses_menu_item_title_edit_pricing"><![CDATA[Edit Pricing]]></string>
+    <string name="_bx_courses_menu_item_title_system_edit_profile"><![CDATA[Edit Course]]></string>
+    <string name="_bx_courses_menu_item_title_edit_profile"><![CDATA[Edit Course]]></string>
+    <string name="_bx_courses_menu_item_title_system_delete_profile"><![CDATA[Delete Course]]></string>
+    <string name="_bx_courses_menu_item_title_delete_profile"><![CDATA[Delete Course]]></string>
+    <string name="_bx_courses_menu_item_title_system_delete_account"><![CDATA[Delete Account]]></string>
+    <string name="_bx_courses_menu_item_title_delete_account"><![CDATA[Delete Account]]></string>
+    <string name="_bx_courses_menu_item_title_system_profile_type"><![CDATA[Course]]></string>
+    <string name="_bx_courses_menu_item_title_profile_type"><![CDATA[Course]]></string>
+    <string name="_bx_courses_menu_item_title_system_create_profile"><![CDATA[Course]]></string>
+    <string name="_bx_courses_menu_item_title_create_profile"><![CDATA[Course]]></string>
+    <string name="_bx_courses_menu_item_title_system_view_profile_friends"><![CDATA[Friends]]></string>
+    <string name="_bx_courses_menu_item_title_view_profile_friends"><![CDATA[Friends]]></string>
+    <string name="_bx_courses_menu_item_title_system_view_joined_entries"><![CDATA[Courses]]></string>
+    <string name="_bx_courses_menu_item_title_view_joined_entries"><![CDATA[Courses]]></string>
+    <string name="_bx_courses_menu_item_title_system_view_fans"><![CDATA[Students]]></string>
+    <string name="_bx_courses_menu_item_title_view_fans"><![CDATA[Students]]></string>
+    <string name="_bx_courses_menu_item_title_system_view_profile_comments"><![CDATA[Comments]]></string>
+    <string name="_bx_courses_menu_item_title_view_profile_comments"><![CDATA[Comments]]></string>
+    <string name="_bx_courses_menu_item_title_system_view_profile_info"><![CDATA[Info]]></string>
+    <string name="_bx_courses_menu_item_title_view_profile_info"><![CDATA[Info]]></string>
+    <string name="_bx_courses_menu_item_title_system_view_profile_view"><![CDATA[Course]]></string>
+    <string name="_bx_courses_menu_item_title_view_profile_view"><![CDATA[Course]]></string>
+    <string name="_bx_courses_menu_item_title_system_view_profile_more_auto"><![CDATA[More]]></string>
+    <string name="_bx_courses_menu_item_title_view_profile_more_auto"><![CDATA[More]]></string>
+    <string name="_bx_courses_menu_item_title_system_invite"><![CDATA[Invite]]></string>
+    <string name="_bx_courses_menu_item_title_invite"><![CDATA[Invite]]></string>
+
+    <string name="_bx_courses_menu_item_title_system_befriend"><![CDATA[Add friend]]></string>
+    <string name="_bx_courses_menu_item_title_befriend"><![CDATA[Add friend]]></string>
+    <string name="_bx_courses_menu_item_title_befriend_sent"><![CDATA[Add friend (requested)]]></string>
+    <string name="_bx_courses_menu_item_title_befriend_confirm"><![CDATA[Accept friend request]]></string>
+    <string name="_bx_courses_menu_item_title_system_unfriend"><![CDATA[Unfriend]]></string>
+    <string name="_bx_courses_menu_item_title_unfriend"><![CDATA[Unfriend]]></string>
+    <string name="_bx_courses_menu_item_title_unfriend_cancel_request"><![CDATA[Cancel friend request]]></string>
+    <string name="_bx_courses_menu_item_title_unfriend_reject_request"><![CDATA[Reject friend request]]></string>
+
+    <string name="_bx_courses_menu_item_title_system_become_fan"><![CDATA[Attend Course]]></string>
+    <string name="_bx_courses_menu_item_title_become_fan"><![CDATA[Attend Course]]></string>
+    <string name="_bx_courses_menu_item_title_become_fan_sent"><![CDATA[Attend Course (requested)]]></string>
+    <string name="_bx_courses_menu_item_title_become_fan_confirm"><![CDATA[Accept Request]]></string>
+    <string name="_bx_courses_menu_item_title_system_leave_entry"><![CDATA[Leave Course]]></string>
+    <string name="_bx_courses_menu_item_title_leave_entry"><![CDATA[Leave Course]]></string>
+    <string name="_bx_courses_menu_item_title_leave_entry_cancel_request"><![CDATA[Cancel Request]]></string>
+    <string name="_bx_courses_menu_item_title_leave_entry_reject_request"><![CDATA[Reject Request]]></string>
+
+    <string name="_bx_courses_menu_item_title_system_pay_and_join"><![CDATA[Pay & Join]]></string>
+    <string name="_bx_courses_menu_item_title_pay_and_join"><![CDATA[Pay & Join]]></string>
+
+    <string name="_bx_courses_menu_item_title_system_subscribe"><![CDATA[Follow]]></string>
+    <string name="_bx_courses_menu_item_title_subscribe"><![CDATA[Follow]]></string>
+    <string name="_bx_courses_menu_item_title_system_unsubscribe"><![CDATA[Unfollow]]></string>
+    <string name="_bx_courses_menu_item_title_unsubscribe"><![CDATA[Unfollow]]></string>
+    <string name="_bx_courses_menu_item_title_system_more_actions"><![CDATA[More Actions]]></string>
+    <string name="_bx_courses_menu_item_title_more_actions"><![CDATA[]]></string>
+    <string name="_bx_courses_menu_item_title_system_friends"><![CDATA[Friends]]></string>
+    <string name="_bx_courses_menu_item_title_friends"><![CDATA[Friends]]></string>
+    <string name="_bx_courses_menu_item_title_system_manage_my_entries"><![CDATA[My courses]]></string>
+    <string name="_bx_courses_menu_item_title_manage_my_entries"><![CDATA[Courses]]></string>
+    <string name="_bx_courses_menu_item_title_system_entries_recent"><![CDATA[New]]></string>
+    <string name="_bx_courses_menu_item_title_entries_recent"><![CDATA[New]]></string>
+    <string name="_bx_courses_menu_item_title_system_entries_search"><![CDATA[Search]]></string>
+    <string name="_bx_courses_menu_item_title_entries_search"><![CDATA[Search]]></string>
+    <string name="_bx_courses_menu_item_title_system_entries_joined"><![CDATA[Attended]]></string>
+    <string name="_bx_courses_menu_item_title_entries_joined"><![CDATA[Attended]]></string>
+    <string name="_bx_courses_menu_item_title_system_entries_manage"><![CDATA[Manage]]></string>
+    <string name="_bx_courses_menu_item_title_entries_manage"><![CDATA[Manage]]></string>
+    <string name="_bx_courses_menu_item_title_system_entries_home"><![CDATA[Courses]]></string>
+    <string name="_bx_courses_menu_item_title_entries_home"><![CDATA[Courses]]></string>
+    <string name="_bx_courses_menu_item_title_system_admt_entries"><![CDATA[Courses]]></string>
+    <string name="_bx_courses_menu_item_title_admt_entries"><![CDATA[Courses]]></string>
+    <string name="_bx_courses_menu_item_title_manage_my"><![CDATA[My Courses]]></string>
+    <string name="_bx_courses_menu_item_title_manage_all"><![CDATA[All Courses]]></string>
+    <string name="_bx_courses_menu_item_title_system_entries_top"><![CDATA[Top]]></string>
+    <string name="_bx_courses_menu_item_title_entries_top"><![CDATA[Top]]></string>
+    <string name="_bx_courses_menu_item_title_system_sm_privacy"><![CDATA[Privacy]]></string>
+    <string name="_bx_courses_menu_item_title_sm_privacy"><![CDATA[Privacy]]></string>
+    <string name="_bx_courses_menu_item_title_system_sm_members"><![CDATA[Students]]></string>
+    <string name="_bx_courses_menu_item_title_sm_members"><![CDATA[{0} students]]></string>
+    <string name="_bx_courses_menu_item_title_system_sm_join"><![CDATA[Attend]]></string>
+    <string name="_bx_courses_menu_item_title_sm_join"><![CDATA[Attend]]></string>
+    <string name="_bx_courses_menu_item_title_sm_join_confirm"><![CDATA[Accept attend request]]></string>
+    <string name="_bx_courses_menu_item_title_sm_leave"><![CDATA[Leave]]></string>
+    <string name="_bx_courses_menu_item_title_sm_leave_reject"><![CDATA[Reject attend request]]></string>
+    <string name="_bx_courses_menu_item_title_sm_leave_cancel"><![CDATA[Cancel attend request]]></string>
+
+    <string name="_bx_courses_grid_filter_item_title_adm_select_one_filter1"><![CDATA[All Statuses]]></string>
+    <string name="_bx_courses_grid_filter_item_title_adm_active"><![CDATA[Active]]></string>
+    <string name="_bx_courses_grid_filter_item_title_adm_pending"><![CDATA[Pending]]></string>
+    <string name="_bx_courses_grid_filter_item_title_adm_suspended"><![CDATA[Suspended]]></string>
+    <string name="_bx_courses_grid_column_title_adm_active"><![CDATA[Active]]></string>
+    <string name="_bx_courses_grid_column_title_adm_name"><![CDATA[Name]]></string>
+    <string name="_bx_courses_grid_column_title_adm_added"><![CDATA[Created]]></string>
+    <string name="_bx_courses_grid_column_title_adm_account"><![CDATA[Account]]></string>
+    <string name="_bx_courses_grid_action_title_adm_audit_context"><![CDATA[Audit actions in context]]></string>
+    <string name="_bx_courses_grid_action_title_adm_audit_content"><![CDATA[Audit actions with context]]></string>
+    <string name="_bx_courses_grid_action_title_adm_clear_reports"><![CDATA[Сlear reports]]></string>
+    <string name="_bx_courses_grid_action_title_adm_delete"><![CDATA[Delete]]></string>
+    <string name="_bx_courses_grid_action_title_adm_delete_with_content"><![CDATA[Delete With Content]]></string>
+    <string name="_bx_courses_grid_action_title_adm_more_actions"><![CDATA[More Actions]]></string>
+    <string name="_bx_courses_grid_action_err_delete"><![CDATA[Cannot delete the selected course(s).]]></string>
+    <string name="_bx_courses_grid_txt_account_manager"><![CDATA[Redirect to manage account.]]></string>
+
+    <string name="_bx_courses_grid_column_title_name"><![CDATA[Name]]></string>
+    <string name="_bx_courses_grid_column_title_role_id"><![CDATA[Role]]></string>
+    <string name="_bx_courses_grid_column_title_period"><![CDATA[Period]]></string>
+    <string name="_bx_courses_grid_column_title_price"><![CDATA[Price]]></string>
+    <string name="_bx_courses_grid_action_title_add"><![CDATA[Add]]></string>
+    <string name="_bx_courses_grid_action_title_edit"><![CDATA[Edit]]></string>
+    <string name="_bx_courses_grid_action_title_delete"><![CDATA[Delete]]></string>
+    <string name="_bx_courses_grid_action_title_buy"><![CDATA[Buy]]></string>
+    <string name="_bx_courses_grid_action_title_buy_title"><![CDATA[One-time payment]]></string>
+    <string name="_bx_courses_grid_action_title_subscribe"><![CDATA[Subscribe]]></string>
+    <string name="_bx_courses_grid_action_title_subscribe_title"><![CDATA[Create a subscription with recurring billing]]></string>
+    <string name="_bx_courses_grid_action_title_choose"><![CDATA[Choose]]></string>
+    <string name="_bx_courses_grid_action_title_choose_title"><![CDATA[Switch to the level for free]]></string>
+    <string name="_bx_courses_popup_title_price_add"><![CDATA[Add Pricing Plan]]></string>
+    <string name="_bx_courses_popup_title_price_edit"><![CDATA[Edit Pricing Plan]]></string>
+
+    <string name="_bx_courses_chart_growth"><![CDATA[Courses: Growth]]></string>
+    <string name="_bx_courses_chart_growth_speed"><![CDATA[Courses: Growth Speed]]></string>
+
+    <string name="_bx_courses_search_extended"><![CDATA[Courses Search]]></string>
+    <string name="_bx_courses_search_extended_cmts"><![CDATA[Courses Comments Search]]></string>
+
+    <string name="_bx_courses_txt_account_pending"><![CDATA[This course is pending approval, please wait until it is activated.]]></string>
+    <string name="_bx_courses_txt_account_suspended"><![CDATA[This course is suspended.]]></string>
+    <string name="_bx_courses_txt_N_fans"><![CDATA[{0} students]]></string>
+    <string name="_bx_courses_txt_role"><![CDATA[Role]]></string>
+    <string name="_bx_courses_txt_role_added"><![CDATA[Added]]></string>
+    <string name="_bx_courses_txt_role_expired"><![CDATA[Expires]]></string>
+    <string name="_bx_courses_txt_sample_single"><![CDATA[course]]></string>
+    <string name="_bx_courses_txt_sample_single_with_article"><![CDATA[a course]]></string>
+    <string name="_bx_courses_txt_sample_comment_single"><![CDATA[comment to course]]></string>
+    <string name="_bx_courses_txt_sample_vote_single"><![CDATA[vote to course]]></string>
+    <string name="_bx_courses_txt_sample_score_up_single"><![CDATA[score up vote to course]]></string>
+    <string name="_bx_courses_txt_sample_score_down_single"><![CDATA[score down vote to course]]></string>
+    <string name="_bx_courses_txt_set_role"><![CDATA[Set Role]]></string>
+    <string name="_bx_courses_txt_private_entry"><![CDATA[Private course]]></string>
+    <string name="_bx_courses_txt_invite_popup_text"><![CDATA[You have been invited to a course. Click the button below to accept the invitation.]]></string>
+    <string name="_bx_courses_txt_invite_popup_title"><![CDATA[Invitation to a course]]></string>
+    <string name="_bx_courses_txt_invite_popup_button_accept"><![CDATA[Accept]]></string>
+    <string name="_bx_courses_txt_invite_popup_button_decline"><![CDATA[Decline]]></string>
+    <string name="_bx_courses_txt_invite_popup_error_invitation_absent"><![CDATA[Sorry, an error has occurred. You can not join this course. The invitation is expired or deleted.]]></string>
+    <string name="_bx_courses_txt_invite_popup_error_invitation_wrong_user"><![CDATA[Sorry, an error has occurred. You can not join this course. This invitation cannot be used by you.]]></string>
+    <string name="_bx_courses_txt_n_unit"><![CDATA[{0} ({1})]]></string>
+    <string name="_bx_courses_txt_cart_item_title"><![CDATA[{0}: {1} ({2} {3})]]></string>
+
+    <string name="_bx_courses_msg_performed"><![CDATA[The action was successfully performed.]]></string>
+    <string name="_bx_courses_err_price_duplicate"><![CDATA[Similar pricing plan is already exists.]]></string>
+    <string name="_bx_courses_err_cannot_perform"><![CDATA[An error appeared. Please report.]]></string>
+
+    <string name="_bx_courses_alert_action_fan_added"><![CDATA[member joined]]></string>
+    <string name="_bx_courses_txt_ntfs_fan_added"><![CDATA[Course <b class="bx-ntfs-content-profile">{owner_name}</b> has got a member <b class="bx-ntfs-content-entry">{subentry_sample}</b>]]></string>
+    <string name="_bx_courses_alert_action_join_invitation_notif"><![CDATA[join invitation]]></string>
+    <string name="_bx_courses_alert_action_join_request"><![CDATA[join request]]></string>
+    <string name="_bx_courses_txt_ntfs_join_invitation"><![CDATA[<b class="bx-ntfs-content-profile">{owner_name}</b> course's representative invites <b class="bx-ntfs-content-entry">{subentry_sample}</b> to join course]]></string>
+    <string name="_bx_courses_txt_ntfs_join_request"><![CDATA[Course <b class="bx-ntfs-content-profile">{owner_name}</b> has a join request from <b class="bx-ntfs-content-entry">{subentry_sample}</b>]]></string>
+    <string name="_bx_courses_txt_ntfs_timeline_post_common"><![CDATA[New post <b class="bx-ntfs-content-entry">{subentry_sample}</b> in <b class="bx-ntfs-content-profile">{owner_name}</b> course timeline]]></string>
+
+    <string name="_bx_courses_pre_lists_cats"><![CDATA[Course categories]]></string>
+    <string name="_bx_courses_cat_General"><![CDATA[General]]></string>
+
+    <string name="_bx_courses_pre_lists_roles"><![CDATA[Course roles]]></string>
+    <string name="_bx_courses_role_regular"><![CDATA[Student]]></string>
+    <string name="_bx_courses_role_administrator"><![CDATA[Instructor]]></string>
+    <string name="_bx_courses_role_moderator"><![CDATA[Assistant]]></string>
+
+    <string name="_bx_courses_pre_lists_period_units"><![CDATA[Billing Interval]]></string>
+    <string name="_bx_courses_period_unit_day"><![CDATA[day]]></string>
+    <string name="_bx_courses_period_unit_week"><![CDATA[week]]></string>
+    <string name="_bx_courses_period_unit_month"><![CDATA[month]]></string>
+    <string name="_bx_courses_period_unit_year"><![CDATA[year]]></string>
+
+    <string name="_bx_courses_email_join_request"><![CDATA[Course join request]]></string>
+    <string name="_bx_courses_email_join_request_subject"><![CDATA[Request to join your course]]></string>
+    <string name="_bx_courses_email_join_request_body"><![CDATA[{email_header}
+<p>New request to join <a href="{EntryUrl}">{EntryTitle}</a> course from <a href="{NewMemberUrl}">{NewMemberDisplayName}</a></p>
+{email_footer}]]></string>
+
+    <string name="_bx_courses_email_join_reject"><![CDATA[Course join request was rejected]]></string>
+    <string name="_bx_courses_email_join_reject_subject"><![CDATA[Request to join a course was rejected]]></string>
+    <string name="_bx_courses_email_join_reject_body"><![CDATA[{email_header}
+<p>Your request to join <a href="{EntryUrl}">{EntryTitle}</a> course was rejected by course admin.</p>
+{email_footer}]]></string>
+
+    <string name="_bx_courses_email_join_confirm"><![CDATA[Course join request was confirmed]]></string>
+    <string name="_bx_courses_email_join_confirm_subject"><![CDATA[Your request to join a course was confirmed]]></string>
+    <string name="_bx_courses_email_join_confirm_body"><![CDATA[{email_header}
+<p>Your request to join <a href="{EntryUrl}">{EntryTitle}</a> course was confirmed by the course admin.</p>
+{email_footer}]]></string>
+
+    <string name="_bx_courses_email_fan_remove"><![CDATA[Profile was removed from course fans]]></string>
+    <string name="_bx_courses_email_fan_remove_subject"><![CDATA[Your profile was removed from the course]]></string>
+    <string name="_bx_courses_email_fan_remove_body"><![CDATA[{email_header}
+<p>Your profile was removed from <a href="{EntryUrl}">{EntryTitle}</a> course by the course admin.</p>
+{email_footer}]]></string>
+
+    <string name="_bx_courses_email_fan_become_admin"><![CDATA[Course instructor status was granted]]></string>
+    <string name="_bx_courses_email_fan_become_admin_subject"><![CDATA[You are a course instructor now]]></string>
+    <string name="_bx_courses_email_fan_become_admin_body"><![CDATA[{email_header}
+<p>You are an instructor of <a href="{EntryUrl}">{EntryTitle}</a> course now.</p>
+{email_footer}]]></string>
+
+    <string name="_bx_courses_email_admin_become_fan"><![CDATA[Course instructor status was revoked]]></string>
+    <string name="_bx_courses_email_admin_become_fan_subject"><![CDATA[Your course instructor status was revoked]]></string>
+    <string name="_bx_courses_email_admin_become_fan_body"><![CDATA[{email_header}
+<p>Your instructor status was revoked from <a href="{EntryUrl}">{EntryTitle}</a> course.</p>
+{email_footer}]]></string>
+
+    <string name="_bx_courses_email_invitation"><![CDATA[Invitation to course]]></string>
+    <string name="_bx_courses_email_invitation_subject"><![CDATA[Invitation to "{EntryTitle}" course]]></string>
+    <string name="_bx_courses_email_invitation_body"><![CDATA[{email_header}
+<p><a href="{InviterUrl}">{InviterDisplayName}</a> invited you to <a href="{EntryUrl}">{EntryTitle} course</a>.</p>
+{email_footer}]]></string>
+
+    <string name="_bx_courses_email_set_role"><![CDATA[Course member status was changed]]></string>
+    <string name="_bx_courses_email_set_role_subject"><![CDATA[Your course status was changed]]></string>
+    <string name="_bx_courses_email_set_role_body"><![CDATA[{email_header}
+<p>Your status in <a href="{EntryUrl}">{EntryTitle}</a> course was changed to <b>{Role}</b>.</p>
+{email_footer}]]></string>
+</resources>

+ 60 - 0
modules/boonex/courses/updates/12.0.0_12.0.1/source/install/sql/disable.sql

@@ -0,0 +1,60 @@
+
+-- SETTINGS
+SET @iTypeId = (SELECT `ID` FROM `sys_options_types` WHERE `name` = 'bx_courses' LIMIT 1);
+SET @iCategId = (SELECT `ID` FROM `sys_options_categories` WHERE `type_id` = @iTypeId LIMIT 1);
+DELETE FROM `sys_options` WHERE `category_id` = @iCategId;
+DELETE FROM `sys_options_categories` WHERE `type_id` = @iTypeId;
+DELETE FROM `sys_options_types` WHERE `id` = @iTypeId;
+
+-- PAGES
+DELETE FROM `sys_objects_page` WHERE `module` = 'bx_courses';
+DELETE FROM `sys_pages_blocks` WHERE `module` = 'bx_courses' OR `object` IN('bx_courses_create_profile', 'bx_courses_delete_profile', 'bx_courses_join_profile', 'bx_courses_edit_profile', 'bx_courses_edit_profile_cover', 'bx_courses_invite', 'bx_courses_view_profile', 'bx_courses_view_profile_closed', 'bx_courses_profile_info', 'bx_courses_profile_pricing', 'bx_courses_profile_comments', 'bx_courses_home', 'bx_courses_fans', 'bx_courses_joined', 'bx_courses_favorites', 'bx_courses_top', 'bx_courses_search', 'bx_courses_manage', 'bx_courses_administration');
+
+-- MENU
+DELETE FROM `sys_objects_menu` WHERE `module` = 'bx_courses';
+DELETE FROM `sys_menu_sets` WHERE `module` = 'bx_courses';
+DELETE FROM `sys_menu_items` WHERE `module` = 'bx_courses' OR `set_name` IN('bx_courses_view_submenu', 'bx_courses_submenu', 'bx_courses_view_actions', 'bx_courses_view_actions_more', 'bx_courses_view_actions_all', 'bx_courses_my', 'bx_courses_snippet_meta', 'bx_courses_menu_manage_tools');
+
+-- ACL
+DELETE `sys_acl_actions`, `sys_acl_matrix` FROM `sys_acl_actions`, `sys_acl_matrix` WHERE `sys_acl_matrix`.`IDAction` = `sys_acl_actions`.`ID` AND `sys_acl_actions`.`Module` = 'bx_courses';
+DELETE FROM `sys_acl_actions` WHERE `Module` = 'bx_courses';
+
+-- METATAGS
+DELETE FROM `sys_objects_metatags` WHERE `object` = 'bx_courses';
+
+-- CATEGORY
+DELETE FROM `sys_objects_category` WHERE `object` = 'bx_courses_cats';
+
+-- SEARCH
+DELETE FROM `sys_objects_search` WHERE `ObjectName` = 'bx_courses';
+
+-- CONNECTIONS
+DELETE FROM `sys_objects_connection` WHERE `object` = 'bx_courses_fans';
+
+-- STATS
+DELETE FROM `sys_statistics` WHERE `name` LIKE 'bx_courses%';
+
+-- CHARTS
+DELETE FROM `sys_objects_chart` WHERE `object` LIKE 'bx_courses%';
+
+-- GRIDS
+DELETE FROM `sys_objects_grid` WHERE `object` IN ('bx_courses_administration', 'bx_courses_moderation', 'bx_courses_common', 'bx_courses_fans', 'bx_courses_invites', 'bx_courses_prices_manage', 'bx_courses_prices_view');
+DELETE FROM `sys_grid_fields` WHERE `object` IN ('bx_courses_administration', 'bx_courses_moderation', 'bx_courses_common', 'bx_courses_fans', 'bx_courses_invites', 'bx_courses_prices_manage', 'bx_courses_prices_view');
+DELETE FROM `sys_grid_actions` WHERE `object` IN ('bx_courses_administration', 'bx_courses_moderation', 'bx_courses_common', 'bx_courses_fans', 'bx_courses_invites', 'bx_courses_prices_manage', 'bx_courses_prices_view');
+
+-- ALERTS
+SET @iHandler := (SELECT `id` FROM `sys_alerts_handlers` WHERE `name` = 'bx_courses' LIMIT 1);
+DELETE FROM `sys_alerts` WHERE `handler_id` = @iHandler;
+DELETE FROM `sys_alerts_handlers` WHERE `id` = @iHandler;
+
+-- PRIVACY 
+DELETE FROM `sys_objects_privacy` WHERE `object` IN ('bx_courses_allow_view_to', 'bx_courses_allow_view_notification_to', 'bx_courses_allow_post_to', 'bx_courses_allow_view_favorite_list');
+
+-- EMAIL TEMPLATES
+DELETE FROM `sys_email_templates` WHERE `Module` = 'bx_courses';
+
+-- UPLOADERS
+DELETE FROM `sys_objects_uploader` WHERE `object` IN ('bx_courses_cover_crop', 'bx_courses_picture_crop');
+
+-- CRON
+DELETE FROM `sys_cron_jobs` WHERE `name` IN ('bx_courses_pruning');

+ 643 - 0
modules/boonex/courses/updates/12.0.0_12.0.1/source/install/sql/enable.sql

@@ -0,0 +1,643 @@
+
+-- SETTINGS
+
+SET @iTypeOrder = (SELECT MAX(`order`) FROM `sys_options_types` WHERE `group` = 'modules');
+INSERT INTO `sys_options_types`(`group`, `name`, `caption`, `icon`, `order`) VALUES 
+('modules', 'bx_courses', '_bx_courses', 'bx_courses@modules/boonex/courses/|std-icon.svg', IF(ISNULL(@iTypeOrder), 1, @iTypeOrder + 1));
+SET @iTypeId = LAST_INSERT_ID();
+
+INSERT INTO `sys_options_categories` (`type_id`, `name`, `caption`, `order`)
+VALUES (@iTypeId, 'bx_courses', '_bx_courses', 1);
+SET @iCategId = LAST_INSERT_ID();
+
+INSERT INTO `sys_options` (`name`, `value`, `category_id`, `caption`, `type`, `extra`, `check`, `check_error`, `order`) VALUES
+('bx_courses_num_connections_quick', '6', @iCategId, '_bx_courses_option_num_connections_quick', 'digit', '', '', '', 10),
+('bx_courses_per_page_browse', '24', @iCategId, '_bx_courses_option_per_page_browse', 'digit', '', '', '', 11),
+('bx_courses_num_rss', '10', @iCategId, '_bx_courses_option_num_rss', 'digit', '', '', '', 12),
+('bx_courses_per_page_browse_showcase', '32', @iCategId, '_sys_option_per_page_browse_showcase', 'digit', '', '', '', 15),
+('bx_courses_per_page_browse_recommended', '10', @iCategId, '_sys_option_per_page_browse_recommended', 'digit', '', '', '', 16),
+('bx_courses_per_page_for_favorites_lists', '5', @iCategId, '_bx_courses_option_per_page_for_favorites_lists', 'digit', '', '', '', 17),
+('bx_courses_searchable_fields', 'name,desc', @iCategId, '_bx_courses_option_searchable_fields', 'list', 'a:2:{s:6:"module";s:10:"bx_courses";s:6:"method";s:21:"get_searchable_fields";}', '', '', 30),
+('bx_courses_members_mode', '', @iCategId, '_bx_courses_option_members_mode', 'select', 'a:2:{s:6:"module";s:10:"bx_courses";s:6:"method";s:24:"get_options_members_mode";}', '', '', 40), 
+('bx_courses_internal_notifications', '', @iCategId, '_bx_courses_option_internal_notifications', 'checkbox', '', '', '', 50);
+
+-- PAGES
+
+-- PAGE: create profile
+
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_courses_create_profile', 'create-course-profile', '_bx_courses_page_title_sys_create_profile', '_bx_courses_page_title_create_profile', 'bx_courses', 5, 2147483647, 1, 'page.php?i=create-course-profile', '', '', '', 0, 1, 0, '', '');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_courses_create_profile', 1, 'bx_courses', '_bx_courses_page_block_title_create_profile', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:10:"bx_courses";s:6:"method";s:13:"entity_create";}', 0, 1, 1);
+
+-- PAGE: view profile
+
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_courses_view_profile', 'view-course-profile', '_bx_courses_page_title_sys_view_profile', '_bx_courses_page_title_view_profile', 'bx_courses', 12, 2147483647, 1, 'page.php?i=view-course-profile', '', '', '', 0, 1, 0, 'BxCoursesPageEntry', 'modules/boonex/courses/classes/BxCoursesPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES
+('bx_courses_view_profile', 1, 'bx_courses', '', '_bx_courses_page_block_title_entry_social_sharing', 13, 2147483647, 'service', 'a:2:{s:6:"module";s:10:"bx_courses";s:6:"method";s:21:"entity_social_sharing";}', 0, 0, 0, 0),
+('bx_courses_view_profile', 1, 'bx_courses', '', '_bx_courses_page_block_title_entry_all_actions', 13, 2147483647, 'service', 'a:2:{s:6:"module";s:10:"bx_courses";s:6:"method";s:18:"entity_all_actions";}', 0, 0, 0, 0),
+('bx_courses_view_profile', 2, 'bx_courses', '', '_bx_courses_page_block_title_profile_description', 13, 2147483647, 'service', 'a:2:{s:6:"module";s:10:"bx_courses";s:6:"method";s:17:"entity_text_block";}', 0, 0, 1, 0),
+('bx_courses_view_profile', 3, 'bx_courses', '', '_bx_courses_page_block_title_profile_location', 13, 2147483647, 'service', 'a:2:{s:6:"module";s:10:"bx_courses";s:6:"method";s:15:"entity_location";}', 0, 0, 0, 0),
+('bx_courses_view_profile', 3, 'bx_courses', '', '_bx_courses_page_block_title_profile_info', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:10:"bx_courses";s:6:"method";s:11:"entity_info";}', 0, 0, 1, 0),
+('bx_courses_view_profile', 3, 'bx_courses', '', '_bx_courses_page_block_title_admins', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:10:"bx_courses";s:6:"method";s:6:"admins";}', 0, 0, 1, 1),
+('bx_courses_view_profile', 3, 'bx_courses', '', '_bx_courses_page_block_title_fans', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:10:"bx_courses";s:6:"method";s:19:"fans_without_admins";}', 0, 0, 1, 2),
+('bx_courses_view_profile', 3, 'bx_courses', '', '_bx_courses_page_block_title_profile_location', 3, 2147483647, 'service', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:13:"locations_map";s:6:"params";a:2:{i:0;s:10:"bx_courses";i:1;s:12:"{content_id}";}s:5:"class";s:20:"TemplServiceMetatags";}', 0, 0, 1, 3),
+('bx_courses_view_profile', 4, 'bx_courses', '', '_bx_courses_page_block_title_profile_comments', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:10:"bx_courses";s:6:"method";s:15:"entity_comments";}', 0, 0, 0, 0);
+
+-- PAGE: view closed profile 
+
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_courses_view_profile_closed', 'view-course-profile-closed', '_bx_courses_page_title_sys_view_profile_closed', '_bx_courses_page_title_view_profile', 'bx_courses', 10, 2147483647, 1, 'page.php?i=view-course-profile', '', '', '', 0, 1, 0, 'BxCoursesPageEntry', 'modules/boonex/courses/classes/BxCoursesPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_courses_view_profile_closed', 2, 'bx_courses', '', '_bx_courses_page_block_title_profile_info', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:10:"bx_courses";s:6:"method";s:11:"entity_info";}', 0, 0, 1, 0),
+('bx_courses_view_profile_closed', 3, 'bx_courses', '', '_bx_courses_page_block_title_fans', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:10:"bx_courses";s:6:"method";s:4:"fans";}', 0, 0, 1, 0);
+
+-- PAGE: edit profile
+
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_courses_edit_profile', 'edit-course-profile', '_bx_courses_page_title_sys_edit_profile', '_bx_courses_page_title_edit_profile', 'bx_courses', 5, 2147483647, 1, 'page.php?i=edit-course-profile', '', '', '', 0, 1, 0, 'BxCoursesPageEntry', 'modules/boonex/courses/classes/BxCoursesPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_courses_edit_profile', 1, 'bx_courses', '_bx_courses_page_block_title_edit_profile', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:10:"bx_courses";s:6:"method";s:11:"entity_edit";}', 0, 0, 0);
+
+-- PAGE: edit profile cover
+
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_courses_edit_profile_cover', 'edit-course-cover', '_bx_courses_page_title_sys_edit_profile_cover', '_bx_courses_page_title_edit_profile_cover', 'bx_courses', 5, 2147483647, 1, 'page.php?i=edit-course-cover', '', '', '', 0, 1, 0, 'BxCoursesPageEntry', 'modules/boonex/courses/classes/BxCoursesPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_courses_edit_profile_cover', 1, 'bx_courses', '_bx_courses_page_block_title_edit_profile_cover', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:10:"bx_courses";s:6:"method";s:17:"entity_edit_cover";}', 0, 0, 0);
+
+-- PAGE: invite members
+
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_courses_invite', 'invite-to-course', '_bx_courses_page_title_sys_invite_to_course', '_bx_courses_page_title_invite_to_course', 'bx_courses', 5, 2147483647, 1, 'page.php?i=invite-to-course', '', '', '', 0, 1, 0, 'BxCoursesPageEntry', 'modules/boonex/courses/classes/BxCoursesPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_courses_invite', 1, 'bx_courses', '_bx_courses_page_block_title_invite_to_course', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:10:"bx_courses";s:6:"method";s:13:"entity_invite";}', 0, 0, 0);
+
+-- PAGE: delete profile
+
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_courses_delete_profile', 'delete-course-profile', '_bx_courses_page_title_sys_delete_profile', '_bx_courses_page_title_delete_profile', 'bx_courses', 5, 2147483647, 1, 'page.php?i=delete-course-profile', '', '', '', 0, 1, 0, 'BxCoursesPageEntry', 'modules/boonex/courses/classes/BxCoursesPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_courses_delete_profile', 1, 'bx_courses', '_bx_courses_page_block_title_delete_profile', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:10:"bx_courses";s:6:"method";s:13:"entity_delete";}', 0, 0, 0);
+
+-- PAGE: join profile
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_courses_join_profile', 'join-course-profile', '_bx_courses_page_title_sys_join_profile', '_bx_courses_page_title_join_profile', 'bx_courses', 5, 2147483647, 1, 'page.php?i=join-course-profile', '', '', '', 0, 1, 0, 'BxCoursesPageEntry', 'modules/boonex/courses/classes/BxCoursesPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_courses_join_profile', 1, 'bx_courses', '_bx_courses_page_block_title_join_profile', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:10:"bx_courses";s:6:"method";s:11:"entity_join";s:6:"params";a:1:{i:0;s:12:"{profile_id}";}}', 0, 0, 0);
+
+-- PAGE: profile info
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_courses_profile_info', 'course-profile-info', '_bx_courses_page_title_sys_profile_info', '_bx_courses_page_title_profile_info', 'bx_courses', 5, 2147483647, 1, 'page.php?i=course-profile-info', '', '', '', 0, 1, 0, 'BxCoursesPageEntry', 'modules/boonex/courses/classes/BxCoursesPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_courses_profile_info', 1, 'bx_courses', '_bx_courses_page_block_title_system_profile_info', '_bx_courses_page_block_title_profile_info_link', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:10:"bx_courses";s:6:"method";s:16:"entity_info_full";}', 0, 0, 1, 1),
+('bx_courses_profile_info', 1, 'bx_courses', '', '_bx_courses_page_block_title_profile_description', 13, 2147483647, 'service', 'a:2:{s:6:"module";s:10:"bx_courses";s:6:"method";s:17:"entity_text_block";}', 0, 0, 1, 2);
+
+-- PAGE: manage profile pricing
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_courses_profile_pricing', 'edit-course-pricing', '_bx_courses_page_title_sys_profile_pricing', '_bx_courses_page_title_profile_pricing', 'bx_courses', 5, 2147483647, 1, 'page.php?i=edit-course-pricing', '', '', '', 0, 1, 0, 'BxCoursesPageEntry', 'modules/boonex/courses/classes/BxCoursesPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_courses_profile_pricing', 1, 'bx_courses', '_bx_courses_page_block_title_system_profile_pricing', '_bx_courses_page_block_title_profile_pricing_link', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:10:"bx_courses";s:6:"method";s:14:"entity_pricing";s:6:"params";a:1:{i:0;s:12:"{profile_id}";}}', 0, 0, 1, 1);
+
+-- PAGE: course fans
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_courses_fans', 'course-fans', '_bx_courses_page_title_sys_entry_fans', '_bx_courses_page_title_entry_fans', 'bx_courses', 5, 2147483647, 1, 'page.php?i=course-fans', '', '', '', 0, 1, 0, 'BxCoursesPageEntry', 'modules/boonex/courses/classes/BxCoursesPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_courses_fans', 1, 'bx_courses', '_bx_courses_page_block_title_system_fans', '_bx_courses_page_block_title_fans_link', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:10:"bx_courses";s:6:"method";s:10:"fans_table";}', 0, 0, 1, 1),
+('bx_courses_fans', 1, 'bx_courses', '_bx_courses_page_block_title_system_invites', '_bx_courses_page_block_title_fans_invites', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:10:"bx_courses";s:6:"method";s:13:"invites_table";}', 0, 0, 1, 1);
+
+-- PAGE: view entry comments
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_courses_profile_comments', '_bx_courses_page_title_sys_profile_comments', '_bx_courses_page_title_profile_comments', 'bx_courses', 5, 2147483647, 1, 'course-profile-comments', '', '', '', '', 0, 1, 0, 'BxCoursesPageEntry', 'modules/boonex/courses/classes/BxCoursesPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_courses_profile_comments', 1, 'bx_courses', '_bx_courses_page_block_title_profile_comments', '_bx_courses_page_block_title_profile_comments_link', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:10:"bx_courses";s:6:"method";s:15:"entity_comments";}', 0, 0, 0, 1);
+
+-- PAGE: module home
+
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_courses_home', '_bx_courses_page_title_sys_recent', '_bx_courses_page_title_recent', 'bx_courses', 5, 2147483647, 1, 'courses-home', 'page.php?i=courses-home', '', '', '', 0, 1, 0, 'BxCoursesPageBrowse', 'modules/boonex/courses/classes/BxCoursesPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES
+('bx_courses_home', 1, 'bx_courses', '_bx_courses_page_block_title_featured_profiles', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:10:"bx_courses";s:6:"method";s:15:"browse_featured";s:6:"params";a:1:{i:0;s:7:"gallery";}}', 0, 1, 0),
+('bx_courses_home', 1, 'bx_courses', '_bx_courses_page_block_title_latest_profiles', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:10:"bx_courses";s:6:"method";s:22:"browse_recent_profiles";s:6:"params";a:1:{i:0;b:1;}}', 0, 1, 1);
+
+-- PAGE: top profiles
+
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_courses_top', '_bx_courses_page_title_sys_top', '_bx_courses_page_title_top', 'bx_courses', 5, 2147483647, 1, 'courses-top', 'page.php?i=courses-top', '', '', '', 0, 1, 0, 'BxCoursesPageBrowse', 'modules/boonex/courses/classes/BxCoursesPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_courses_top', 1, 'bx_courses', '_bx_courses_page_block_title_top_profiles', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:10:"bx_courses";s:6:"method";s:19:"browse_top_profiles";s:6:"params";a:1:{i:0;b:1;}}', 0, 1, 0);
+
+-- PAGE: search for entries
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_courses_search', '_bx_courses_page_title_sys_entries_search', '_bx_courses_page_title_entries_search', 'bx_courses', 5, 2147483647, 1, 'courses-search', 'page.php?i=courses-search', '', '', '', 0, 1, 0, 'BxCoursesPageBrowse', 'modules/boonex/courses/classes/BxCoursesPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_courses_search', 1, 'bx_courses', '_bx_courses_page_block_title_search_form', 11, 2147483647, 'service', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:8:"get_form";s:6:"params";a:1:{i:0;a:1:{s:6:"object";s:10:"bx_courses";}}s:5:"class";s:27:"TemplSearchExtendedServices";}', 0, 1, 1, 1),
+('bx_courses_search', 1, 'bx_courses', '_bx_courses_page_block_title_search_results', 11, 2147483647, 'service', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:11:"get_results";s:6:"params";a:1:{i:0;a:2:{s:6:"object";s:10:"bx_courses";s:10:"show_empty";b:1;}}s:5:"class";s:27:"TemplSearchExtendedServices";}', 0, 1, 1, 2),
+('bx_courses_search', 1, 'bx_courses', '_bx_courses_page_block_title_search_form_cmts', 11, 2147483647, 'service', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:8:"get_form";s:6:"params";a:1:{i:0;a:1:{s:6:"object";s:15:"bx_courses_cmts";}}s:5:"class";s:27:"TemplSearchExtendedServices";}', 0, 1, 0, 3),
+('bx_courses_search', 1, 'bx_courses', '_bx_courses_page_block_title_search_results_cmts', 11, 2147483647, 'service', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:11:"get_results";s:6:"params";a:1:{i:0;a:2:{s:6:"object";s:15:"bx_courses_cmts";s:10:"show_empty";b:1;}}s:5:"class";s:27:"TemplSearchExtendedServices";}', 0, 1, 0, 4);
+
+-- PAGE: joined profiles
+
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_joined_courses', '_bx_courses_page_title_sys_joined', '_bx_courses_page_title_joined', 'bx_courses', 5, 2147483647, 1, 'courses-joined', 'page.php?i=courses-joined', '', '', '', 0, 1, 0, 'BxCoursesPageBrowse', 'modules/boonex/courses/classes/BxCoursesPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_joined_courses', 1, 'bx_courses', '_bx_courses_page_block_title_joined_entries', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:10:"bx_courses";s:6:"method";s:21:"browse_joined_entries";s:6:"params";a:2:{i:0;s:12:"{profile_id}";i:1;b:1;}}', 0, 1, 0);
+
+-- PAGE: module manage own
+
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_courses_manage', '_bx_courses_page_title_sys_manage', '_bx_courses_page_title_manage', 'bx_courses', 5, 2147483647, 1, 'courses-manage', 'page.php?i=courses-manage', '', '', '', 0, 1, 0, 'BxCoursesPageBrowse', 'modules/boonex/courses/classes/BxCoursesPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_courses_manage', 1, 'bx_courses', '_bx_courses_page_block_title_system_manage', '_bx_courses_page_block_title_manage', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:10:"bx_courses";s:6:"method";s:12:"manage_tools";}}', 0, 1, 0);
+
+-- PAGE: module manage all
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_courses_administration', '_bx_courses_page_title_sys_manage_administration', '_bx_courses_page_title_manage', 'bx_courses', 5, 192, 1, 'courses-administration', 'page.php?i=courses-administration', '', '', '', 0, 1, 0, 'BxCoursesPageBrowse', 'modules/boonex/courses/classes/BxCoursesPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_courses_administration', 1, 'bx_courses', '_bx_courses_page_block_title_system_manage_administration', '_bx_courses_page_block_title_manage', 11, 192, 'service', 'a:3:{s:6:"module";s:10:"bx_courses";s:6:"method";s:12:"manage_tools";s:6:"params";a:1:{i:0;s:14:"administration";}}', 0, 1, 0);
+
+-- PAGE: user's courses
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_courses_joined', 'joined-courses', '_bx_courses_page_title_sys_joined_entries', '_bx_courses_page_title_joined_entries', 'bx_courses', 5, 2147483647, 1, '', '', '', '', 0, 1, 0, 'BxCoursesPageJoinedEntries', 'modules/boonex/courses/classes/BxCoursesPageJoinedEntries.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES
+('bx_courses_joined', 1, 'bx_courses', '_bx_courses_page_block_title_sys_entries_actions', '_bx_courses_page_block_title_entries_actions', 13, 2147483647, 'service', 'a:2:{s:6:"module";s:10:"bx_courses";s:6:"method";s:18:"my_entries_actions";}', 0, 0, 1, 1),
+('bx_courses_joined', 1, 'bx_courses', '_bx_courses_page_block_title_sys_entries_of_author', '_bx_courses_page_block_title_entries_of_author', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:10:"bx_courses";s:6:"method";s:22:"browse_created_entries";}', 0, 0, 0, 2),
+('bx_courses_joined', 1, 'bx_courses', '_bx_courses_page_block_title_sys_favorites_of_author', '_bx_courses_page_block_title_favorites_of_author', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:10:"bx_courses";s:6:"method";s:15:"browse_favorite";s:6:"params";a:1:{i:0;s:12:"{profile_id}";}}', 0, 1, 1, 3),
+('bx_courses_joined', 1, 'bx_courses', '_bx_courses_page_block_title_sys_joined_entries', '_bx_courses_page_block_title_joined_entries', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:10:"bx_courses";s:6:"method";s:21:"browse_joined_entries";s:6:"params";a:2:{i:0;i:0;i:1;b:1;}}', 0, 0, 1, 4);
+
+-- PAGE: favorites by list
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_courses_favorites', '_bx_courses_page_title_sys_entries_favorites', '_bx_courses_page_title_entries_favorites', 'bx_courses', 12, 2147483647, 1, 'courses-favorites', 'page.php?i=courses-favorites', '', '', '', 0, 1, 0, 'BxCoursesPageListEntry', 'modules/boonex/courses/classes/BxCoursesPageListEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_courses_favorites', 2, 'bx_courses', '_bx_courses_page_block_title_favorites_entries', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:10:"bx_courses";s:6:"method";s:15:"browse_favorite";s:6:"params";a:2:{s:10:"profile_id";s:12:"{profile_id}";s:6:"params";a:3:{s:9:"unit_view";s:7:"gallery";s:13:"empty_message";b:0;s:13:"ajax_paginate";b:0;}}}', 0, 1, 1),
+('bx_courses_favorites', 3, 'bx_courses', '_bx_courses_page_block_title_favorites_entries_info', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:10:"bx_courses";s:6:"method";s:19:"favorites_list_info";}', 0, 0, 0),
+('bx_courses_favorites', 3, 'bx_courses', '_bx_courses_page_block_title_favorites_entries_actions', 13, 2147483647, 'service', 'a:2:{s:6:"module";s:10:"bx_courses";s:6:"method";s:22:"favorites_list_actions";}', 0, 0, 1);
+
+
+-- PAGE: add block to homepage
+SET @iBlockOrder = (SELECT `order` FROM `sys_pages_blocks` WHERE `object` = 'sys_home' AND `cell_id` = 1 ORDER BY `order` DESC LIMIT 1);
+INSERT INTO `sys_pages_blocks` (`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES
+('sys_home', 1, 'bx_courses', '', '_bx_courses_page_block_title_latest_profiles', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:10:"bx_courses";s:6:"method";s:22:"browse_recent_profiles";}', 1, 0, 0, IFNULL(@iBlockOrder, 0) + 1),
+('sys_home', 1, 'bx_courses', '_bx_courses_page_block_title_sys_recommended_entries_view_showcase', '_bx_courses_page_block_title_recommended_entries_view_showcase', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:10:"bx_courses";s:6:"method";s:18:"browse_recommended";}', 1, 0, 0, IFNULL(@iBlockOrder, 0) + 2);
+-- PAGE: service blocks
+SET @iBlockOrder = (SELECT `order` FROM `sys_pages_blocks` WHERE `object` = '' AND `cell_id` = 0 ORDER BY `order` DESC LIMIT 1);
+INSERT INTO `sys_pages_blocks` (`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES
+('', 0, 'bx_courses', '', '_bx_courses_page_block_title_categories', 11, 2147483647, 'service', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:15:"categories_list";s:6:"params";a:2:{i:0;s:15:"bx_courses_cats";i:1;a:2:{s:10:"show_empty";b:1;s:21:"show_empty_categories";b:1;}}s:5:"class";s:20:"TemplServiceCategory";}', 1, 1, 1, IFNULL(@iBlockOrder, 0) + 1),
+('', 0, 'bx_courses', '_bx_courses_page_block_title_sys_featured_entries_view_showcase', '_bx_courses_page_block_title_featured_entries_view_showcase', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:10:"bx_courses";s:6:"method";s:15:"browse_featured";s:6:"params";a:3:{s:9:"unit_view";s:8:"showcase";s:13:"empty_message";b:0;s:13:"ajax_paginate";b:0;}}', 0, 1, 1, IFNULL(@iBlockOrder, 0) + 2),
+('', 0, 'bx_courses', '_bx_courses_page_block_title_sys_recommended_entries_view_showcase', '_bx_courses_page_block_title_recommended_entries_view_showcase', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:10:"bx_courses";s:6:"method";s:18:"browse_recommended";s:6:"params";a:3:{s:9:"unit_view";s:8:"showcase";s:13:"empty_message";b:0;s:13:"ajax_paginate";b:0;}}', 0, 1, 1, IFNULL(@iBlockOrder, 0) + 3),
+('', 0, 'bx_courses', '_bx_courses_page_block_title_sys_labels_tree', '_bx_courses_page_block_title_labels_tree', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:10:"bx_courses";s:6:"method";s:15:"get_lables_tree";}', 0, 1, 1, IFNULL(@iBlockOrder, 0) + 4),
+('', 0, 'bx_courses', '_bx_courses_page_block_title_sys_browse_by_label', '_bx_courses_page_block_title_browse_by_label', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:10:"bx_courses";s:6:"method";s:15:"browse_by_label";}', 0, 1, 1, IFNULL(@iBlockOrder, 0) + 5),
+('', 0, 'bx_courses', '_bx_courses_page_block_title_sys_labels_breadcrumbs', '_bx_courses_page_block_title_labels_breadcrumbs', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:10:"bx_courses";s:6:"method";s:22:"get_lables_breadcrumbs";}', 0, 1, 1, IFNULL(@iBlockOrder, 0) + 6);
+-- MENU
+
+-- MENU: add to site menu
+
+SET @iSiteMenuOrder = (SELECT `order` FROM `sys_menu_items` WHERE `set_name` = 'sys_site' AND `active` = 1 AND `order` < 9999 ORDER BY `order` DESC LIMIT 1);
+INSERT INTO `sys_menu_items` (`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('sys_site', 'bx_courses', 'courses-home', '_bx_courses_menu_item_title_system_entries_home', '_bx_courses_menu_item_title_entries_home', 'page.php?i=courses-home', '', '', 'book-reader col-blue3-dark', 'bx_courses_submenu', 2147483647, 1, 1, IFNULL(@iSiteMenuOrder, 0) + 1);
+
+-- MENU: add to homepage menu
+
+SET @iHomepageMenuOrder = (SELECT `order` FROM `sys_menu_items` WHERE `set_name` = 'sys_homepage' AND `active` = 1 ORDER BY `order` DESC LIMIT 1);
+INSERT INTO `sys_menu_items` (`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('sys_homepage', 'bx_courses', 'courses-home', '_bx_courses_menu_item_title_system_entries_home', '_bx_courses_menu_item_title_entries_home', 'page.php?i=courses-home', '', '', 'book-reader col-blue3-dark', 'bx_courses_submenu', 2147483647, 1, 1, IFNULL(@iHomepageMenuOrder, 0) + 1);
+
+-- MENU: add to "add content" menu
+
+SET @iAddMenuOrder = (SELECT `order` FROM `sys_menu_items` WHERE `set_name` = 'sys_add_content_links' AND `active` = 1 ORDER BY `order` DESC LIMIT 1);
+INSERT INTO `sys_menu_items` (`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('sys_add_content_links', 'bx_courses', 'create-course-profile', '_bx_courses_menu_item_title_system_create_profile', '_bx_courses_menu_item_title_create_profile', 'page.php?i=create-course-profile', '', '', 'book-reader col-blue3-dark', '', 2147483647, 1, 1, IFNULL(@iAddMenuOrder, 0) + 1);
+
+-- MENU: view actions
+
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_courses_view_actions', '_bx_courses_menu_title_view_profile_actions', 'bx_courses_view_actions', 'bx_courses', 9, 0, 1, 'BxCoursesMenuViewActions', 'modules/boonex/courses/classes/BxCoursesMenuViewActions.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_courses_view_actions', 'bx_courses', '_bx_courses_menu_set_title_view_profile_actions', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `submenu_popup`, `visible_for_levels`, `visibility_custom`, `active`, `copyable`, `editable`, `order`) VALUES 
+('bx_courses_view_actions', 'bx_courses', 'join-course-profile', '_bx_courses_menu_item_title_system_pay_and_join', '_bx_courses_menu_item_title_pay_and_join', 'page.php?i=join-course-profile&profile_id={profile_id}', '', '', 'sign-in-alt', '', 0, 2147483647, 'a:3:{s:6:"module";s:10:"bx_courses";s:6:"method";s:22:"is_paid_join_avaliable";s:6:"params";a:1:{i:0;s:12:"{profile_id}";}}', 1, 0, 0, 5),
+('bx_courses_view_actions', 'bx_courses', 'profile-fan-add', '_bx_courses_menu_item_title_system_become_fan', '{title_add_fan}', 'javascript:void(0)', 'bx_conn_action(this, \'bx_courses_fans\', \'add\', \'{profile_id}\')', '', 'sign-in-alt', '', 0, 2147483647, '', 1, 0, 0, 5),
+('bx_courses_view_actions', 'bx_courses', 'profile-subscribe-add', '_bx_courses_menu_item_title_system_subscribe', '_bx_courses_menu_item_title_subscribe', 'javascript:void(0)', 'bx_conn_action(this, \'sys_profiles_subscriptions\', \'add\', \'{profile_id}\')', '', 'check', '', 0, 2147483647, '', 1, 0, 1, 20),
+('bx_courses_view_actions', 'bx_courses', 'profile-set-badges', '_sys_menu_item_title_system_set_badges', '_sys_menu_item_title_set_badges', 'javascript:void(0)', 'bx_menu_popup(''sys_set_badges'', window, {}, {module: ''bx_courses'', content_id: {content_id}});', '', 'check-circle', '', 0, 192, 'a:2:{s:6:"module";s:10:"bx_courses";s:6:"method";s:19:"is_badges_avaliable";}', 1, 0, 1, 30),
+('bx_courses_view_actions', 'bx_courses', 'profile-actions-more', '_bx_courses_menu_item_title_system_more_actions', '_bx_courses_menu_item_title_more_actions', 'javascript:void(0)', 'bx_menu_popup(''bx_courses_view_actions_more'', this, {}, {profile_id:{profile_id}});', '', 'cog', 'bx_courses_view_actions_more', 1, 2147483647, '', 1, 0, 1, 9999);
+
+-- MENU: view actions more
+
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_courses_view_actions_more', '_bx_courses_menu_title_view_profile_actions_more', 'bx_courses_view_actions_more', 'bx_courses', 6, 0, 1, 'BxCoursesMenuViewActions', 'modules/boonex/courses/classes/BxCoursesMenuViewActions.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_courses_view_actions_more', 'bx_courses', '_bx_courses_menu_set_title_view_profile_actions_more', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `visibility_custom`, `active`, `copyable`, `order`) VALUES 
+('bx_courses_view_actions_more', 'bx_courses', 'profile-fan-remove', '_bx_courses_menu_item_title_system_leave_entry', '{title_remove_fan}', 'javascript:void(0)', 'bx_conn_action(this, \'bx_courses_fans\', \'remove\', \'{profile_id}\')', '', 'sign-out-alt', '', 2147483647, '', 1, 0, 10),
+('bx_courses_view_actions_more', 'bx_courses', 'profile-subscribe-remove', '_bx_courses_menu_item_title_system_unsubscribe', '_bx_courses_menu_item_title_unsubscribe', 'javascript:void(0)', 'bx_conn_action(this, \'sys_profiles_subscriptions\', \'remove\', \'{profile_id}\')', '', 'check', '', 2147483647, '', 1, 0, 20),
+('bx_courses_view_actions_more', 'bx_courses', 'edit-course-cover', '_bx_courses_menu_item_title_system_edit_cover', '_bx_courses_menu_item_title_edit_cover', 'page.php?i=edit-course-cover&id={content_id}', '', '', 'edit', '', 2147483647, '', 1, 0, 30),
+('bx_courses_view_actions_more', 'bx_courses', 'edit-course-profile', '_bx_courses_menu_item_title_system_edit_profile', '_bx_courses_menu_item_title_edit_profile', 'page.php?i=edit-course-profile&id={content_id}', '', '', 'pencil-alt', '', 2147483647, '', 1, 0, 40),
+('bx_courses_view_actions_more', 'bx_courses', 'edit-course-pricing', '_bx_courses_menu_item_title_system_edit_pricing', '_bx_courses_menu_item_title_edit_pricing', 'page.php?i=edit-course-pricing&profile_id={profile_id}', '', '', 'money-check-alt', '', 2147483647, 'a:3:{s:6:"module";s:10:"bx_courses";s:6:"method";s:20:"is_pricing_avaliable";s:6:"params";a:1:{i:0;s:12:"{profile_id}";}}', 1, 0, 41),
+('bx_courses_view_actions_more', 'bx_courses', 'invite-to-course', '_bx_courses_menu_item_title_system_invite', '_bx_courses_menu_item_title_invite', 'page.php?i=invite-to-course&id={content_id}', '', '', 'user-friends', '', 2147483647, '', 1, 0, 42),
+('bx_courses_view_actions_more', 'bx_courses', 'delete-course-profile', '_bx_courses_menu_item_title_system_delete_profile', '_bx_courses_menu_item_title_delete_profile', 'page.php?i=delete-course-profile&id={content_id}', '', '', 'remove', '', 2147483647, '', 1, 0, 50);
+
+-- MENU: all actions menu for view entry 
+
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_courses_view_actions_all', '_sys_menu_title_view_actions', 'bx_courses_view_actions_all', 'bx_courses', 15, 0, 1, 'BxCoursesMenuViewActionsAll', 'modules/boonex/courses/classes/BxCoursesMenuViewActionsAll.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_courses_view_actions_all', 'bx_courses', '_sys_menu_set_title_view_actions', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `addon`, `submenu_object`, `submenu_popup`, `visible_for_levels`, `visibility_custom`, `active`, `copyable`, `order`) VALUES 
+('bx_courses_view_actions_all', 'bx_courses', 'join-course-profile', '_bx_courses_menu_item_title_system_pay_and_join', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 5),
+('bx_courses_view_actions_all', 'bx_courses', 'profile-fan-add', '_bx_courses_menu_item_title_system_become_fan', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 10),
+('bx_courses_view_actions_all', 'bx_courses', 'profile-fan-remove', '_bx_courses_menu_item_title_system_leave_entry', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 20),
+('bx_courses_view_actions_all', 'bx_courses', 'profile-subscribe-add', '_bx_courses_menu_item_title_system_subscribe', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 30),
+('bx_courses_view_actions_all', 'bx_courses', 'profile-subscribe-remove', '_bx_courses_menu_item_title_system_unsubscribe', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 40),
+('bx_courses_view_actions_all', 'bx_courses', 'profile-set-badges', '_sys_menu_item_title_system_set_badges', '', '', '', '', '', '', '', 0, 192, 'a:2:{s:6:"module";s:10:"bx_courses";s:6:"method";s:19:"is_badges_avaliable";}', 1, 0, 50),
+('bx_courses_view_actions_all', 'bx_courses', 'comment', '_sys_menu_item_title_system_va_comment', '', '', '', '', '', '', '', 0, 2147483647, '', 0, 0, 200),
+('bx_courses_view_actions_all', 'bx_courses', 'view', '_sys_menu_item_title_system_va_view', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 210),
+('bx_courses_view_actions_all', 'bx_courses', 'vote', '_sys_menu_item_title_system_va_vote', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 220),
+('bx_courses_view_actions_all', 'bx_courses', 'score', '_sys_menu_item_title_system_va_score', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 230),
+('bx_courses_view_actions_all', 'bx_courses', 'favorite', '_sys_menu_item_title_system_va_favorite', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 240),
+('bx_courses_view_actions_all', 'bx_courses', 'feature', '_sys_menu_item_title_system_va_feature', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 250),
+('bx_courses_view_actions_all', 'bx_courses', 'repost', '_sys_menu_item_title_system_va_repost', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 260),
+('bx_courses_view_actions_all', 'bx_courses', 'report', '_sys_menu_item_title_system_va_report', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 270),
+('bx_courses_view_actions_all', 'bx_courses', 'social-sharing-facebook', '_sys_menu_item_title_system_social_sharing_facebook', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 300),
+('bx_courses_view_actions_all', 'bx_courses', 'social-sharing-twitter', '_sys_menu_item_title_system_social_sharing_twitter', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 320),
+('bx_courses_view_actions_all', 'bx_courses', 'social-sharing-pinterest', '_sys_menu_item_title_system_social_sharing_pinterest', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 330),
+('bx_courses_view_actions_all', 'bx_courses', 'edit-course-cover', '_bx_courses_menu_item_title_system_edit_cover', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 400),
+('bx_courses_view_actions_all', 'bx_courses', 'edit-course-profile', '_bx_courses_menu_item_title_system_edit_profile', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 410),
+('bx_courses_view_actions_all', 'bx_courses', 'edit-course-pricing', '_bx_courses_menu_item_title_system_edit_pricing', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 415),
+('bx_courses_view_actions_all', 'bx_courses', 'invite-to-course', '_bx_courses_menu_item_title_system_invite', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 420),
+('bx_courses_view_actions_all', 'bx_courses', 'delete-course-profile', '_bx_courses_menu_item_title_system_delete_profile', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 430),
+('bx_courses_view_actions_all', 'bx_courses', 'more-auto', '_sys_menu_item_title_system_va_more_auto', '_sys_menu_item_title_va_more_auto', 'javascript:void(0)', '', '', 'ellipsis-v', '', '', 0, 2147483647, '', 1, 0, 9999);
+
+-- MENU: actions menu for my entries
+
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_courses_my', '_bx_courses_menu_title_entries_my', 'bx_courses_my', 'bx_courses', 9, 0, 1, 'BxCoursesMenu', 'modules/boonex/courses/classes/BxCoursesMenu.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_courses_my', 'bx_courses', '_bx_courses_menu_set_title_entries_my', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('bx_courses_my', 'bx_courses', 'create-course-profile', '_bx_courses_menu_item_title_system_create_profile', '_bx_courses_menu_item_title_create_profile', 'page.php?i=create-course-profile', '', '', 'plus', '', 2147483647, 1, 0, 0);
+
+-- MENU: module sub-menu
+
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_courses_submenu', '_bx_courses_menu_title_submenu', 'bx_courses_submenu', 'bx_courses', 8, 0, 1, '', '');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_courses_submenu', 'bx_courses', '_bx_courses_menu_set_title_submenu', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('bx_courses_submenu', 'bx_courses', 'courses-home', '_bx_courses_menu_item_title_system_entries_recent', '_bx_courses_menu_item_title_entries_recent', 'page.php?i=courses-home', '', '', '', '', 2147483647, 1, 1, 1),
+('bx_courses_submenu', 'bx_courses', 'courses-top', '_bx_courses_menu_item_title_system_entries_top', '_bx_courses_menu_item_title_entries_top', 'page.php?i=courses-top', '', '', '', '', 2147483647, 1, 1, 2),
+('bx_courses_submenu', 'bx_courses', 'courses-search', '_bx_courses_menu_item_title_system_entries_search', '_bx_courses_menu_item_title_entries_search', 'page.php?i=courses-search', '', '', '', '', 2147483647, 1, 1, 3),
+('bx_courses_submenu', 'bx_courses', 'courses-joined', '_bx_courses_menu_item_title_system_entries_joined', '_bx_courses_menu_item_title_entries_joined', 'page.php?i=courses-joined', '', '', '', '', 2147483647, 1, 1, 4),
+('bx_courses_submenu', 'bx_courses', 'courses-manage', '_bx_courses_menu_item_title_system_entries_manage', '_bx_courses_menu_item_title_entries_manage', 'page.php?i=courses-manage', '', '', '', '', 2147483646, 1, 1, 5);
+
+-- MENU: view submenu
+
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_courses_view_submenu', '_bx_courses_menu_title_view_profile_submenu', 'bx_courses_view_submenu', 'bx_courses', 18, 0, 1, 'BxCoursesMenuView', 'modules/boonex/courses/classes/BxCoursesMenuView.php'),
+('bx_courses_view_submenu_cover', '_bx_courses_menu_title_view_profile_submenu_cover', 'bx_courses_view_submenu', 'bx_courses', 7, 0, 1, 'BxCoursesMenuView', 'modules/boonex/courses/classes/BxCoursesMenuView.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_courses_view_submenu', 'bx_courses', '_bx_courses_menu_set_title_view_profile_submenu', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `addon`, `submenu_object`, `submenu_popup`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('bx_courses_view_submenu', 'bx_courses', 'view-course-profile', '_bx_courses_menu_item_title_system_view_profile_view', '_bx_courses_menu_item_title_view_profile_view', 'page.php?i=view-course-profile&id={content_id}', '', '', 'book-reader col-blue3-dark', '', '', 0, 2147483647, 1, 0, 1),
+('bx_courses_view_submenu', 'bx_courses', 'course-profile-info', '_bx_courses_menu_item_title_system_view_profile_info', '_bx_courses_menu_item_title_view_profile_info', 'page.php?i=course-profile-info&id={content_id}', '', '', 'info-circle col-gray', '', '', 0, 2147483647, 1, 0, 2),
+('bx_courses_view_submenu', 'bx_courses', 'course-profile-comments', '_bx_courses_menu_item_title_system_view_profile_comments', '_bx_courses_menu_item_title_view_profile_comments', 'page.php?i=course-profile-comments&id={content_id}', '', '', '', '', '', 0, 2147483647, 0, 0, 3),
+('bx_courses_view_submenu', 'bx_courses', 'course-fans', '_bx_courses_menu_item_title_system_view_fans', '_bx_courses_menu_item_title_view_fans', 'page.php?i=course-fans&profile_id={profile_id}', '', '', 'users col-blue3', '', '', 0, 2147483647, 1, 0, 4),
+('bx_courses_view_submenu', 'bx_courses', 'more-auto', '_bx_courses_menu_item_title_system_view_profile_more_auto', '_bx_courses_menu_item_title_view_profile_more_auto', 'javascript:void(0)', '', '', 'ellipsis-v', '', '', 0, 2147483647, 1, 0, 9999);
+
+-- MENU: custom menu for snippet meta info
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_courses_snippet_meta', '_sys_menu_title_snippet_meta', 'bx_courses_snippet_meta', 'bx_courses', 15, 0, 1, 'BxCoursesMenuSnippetMeta', 'modules/boonex/courses/classes/BxCoursesMenuSnippetMeta.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_courses_snippet_meta', 'bx_courses', '_sys_menu_set_title_snippet_meta', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `visibility_custom`, `active`, `copyable`, `editable`, `order`) VALUES
+('bx_courses_snippet_meta', 'bx_courses', 'privacy', '_bx_courses_menu_item_title_system_sm_privacy', '_bx_courses_menu_item_title_sm_privacy', '', '', '', '', '', 2147483647, '', 1, 0, 1, 1),
+('bx_courses_snippet_meta', 'bx_courses', 'date', '_sys_menu_item_title_system_sm_date', '_sys_menu_item_title_sm_date', '', '', '', '', '', 2147483647, '', 0, 0, 1, 2),
+('bx_courses_snippet_meta', 'bx_courses', 'tags', '_sys_menu_item_title_system_sm_tags', '_sys_menu_item_title_sm_tags', '', '', '', '', '', 2147483647, '', 0, 0, 1, 3),
+('bx_courses_snippet_meta', 'bx_courses', 'views', '_sys_menu_item_title_system_sm_views', '_sys_menu_item_title_sm_views', '', '', '', '', '', 2147483647, '', 0, 0, 1, 4),
+('bx_courses_snippet_meta', 'bx_courses', 'comments', '_sys_menu_item_title_system_sm_comments', '_sys_menu_item_title_sm_comments', '', '', '', '', '', 2147483647, '', 0, 0, 1, 5),
+('bx_courses_snippet_meta', 'bx_courses', 'members', '_bx_courses_menu_item_title_system_sm_members', '_bx_courses_menu_item_title_sm_members', '', '', '', '', '', 2147483647, '', 1, 0, 1, 6),
+('bx_courses_snippet_meta', 'bx_courses', 'subscribers', '_sys_menu_item_title_system_sm_subscribers', '_sys_menu_item_title_sm_subscribers', '', '', '', '', '', 2147483647, '', 0, 0, 1, 7),
+('bx_courses_snippet_meta', 'bx_courses', 'nl', '_sys_menu_item_title_system_sm_nl', '_sys_menu_item_title_sm_nl', '', '', '', '', '', 2147483647, '', 1, 0, 1, 8),
+('bx_courses_snippet_meta', 'bx_courses', 'join-paid', '_sys_menu_item_title_system_sm_join_paid', '_sys_menu_item_title_sm_join_paid', '', '', '', '', '', 2147483647, 'a:3:{s:6:"module";s:10:"bx_courses";s:6:"method";s:33:"is_paid_join_avaliable_by_content";s:6:"params";a:1:{i:0;s:12:"{content_id}";}}', 1, 0, 1, 9),
+('bx_courses_snippet_meta', 'bx_courses', 'join', '_bx_courses_menu_item_title_system_sm_join', '_bx_courses_menu_item_title_sm_join', '', '', '', '', '', 2147483647, 'a:3:{s:6:"module";s:10:"bx_courses";s:6:"method";s:33:"is_free_join_avaliable_by_content";s:6:"params";a:1:{i:0;s:12:"{content_id}";}}', 1, 0, 1, 10),
+('bx_courses_snippet_meta', 'bx_courses', 'leave', '_sys_menu_item_title_system_sm_leave', '_sys_menu_item_title_sm_leave', '', '', '', '', '', 2147483647, '', 0, 0, 1, 11),
+('bx_courses_snippet_meta', 'bx_courses', 'subscribe', '_sys_menu_item_title_system_sm_subscribe', '_sys_menu_item_title_sm_subscribe', '', '', '', '', '', 2147483647, '', 0, 0, 1, 12),
+('bx_courses_snippet_meta', 'bx_courses', 'unsubscribe', '_sys_menu_item_title_system_sm_unsubscribe', '_sys_menu_item_title_sm_unsubscribe', '', '', '', '', '', 2147483647, '', 0, 0, 1, 13);
+
+-- MENU: profile stats
+SET @iNotifMenuOrder = (SELECT IFNULL(MAX(`order`), 0) FROM `sys_menu_items` WHERE `set_name` = 'sys_profile_stats' AND `active` = 1 LIMIT 1);
+INSERT INTO `sys_menu_items` (`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `addon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES
+('sys_profile_stats', 'bx_courses', 'profile-stats-manage-courses', '_bx_courses_menu_item_title_system_manage_my_entries', '_bx_courses_menu_item_title_manage_my_entries', 'page.php?i=courses-manage', '', '_self', 'book-reader col-blue3-dark', 'a:2:{s:6:"module";s:10:"bx_courses";s:6:"method";s:41:"get_menu_addon_manage_tools_profile_stats";}', '', 2147483646, 1, 0, @iNotifMenuOrder + 2);
+
+-- MENU: manage tools submenu
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_courses_menu_manage_tools', '_bx_courses_menu_title_manage_tools', 'bx_courses_menu_manage_tools', 'bx_courses', 6, 0, 1, 'BxCoursesMenuManageTools', 'modules/boonex/courses/classes/BxCoursesMenuManageTools.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_courses_menu_manage_tools', 'bx_courses', '_bx_courses_menu_set_title_manage_tools', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('bx_courses_menu_manage_tools', 'bx_courses', 'delete', '_bx_courses_menu_item_title_system_delete', '_bx_courses_menu_item_title_delete', 'javascript:void(0)', 'javascript:{js_object}.onClickDelete({content_id});', '_self', 'far trash-alt', '', 2147483647, 1, 0, 1),
+('bx_courses_menu_manage_tools', 'bx_courses', 'delete-with-content', '_bx_courses_menu_item_title_system_delete_with_content', '_bx_courses_menu_item_title_delete_with_content', 'javascript:void(0)', 'javascript:{js_object}.onClickDeleteWithContent({content_id});', '_self', 'far trash-alt', '', 2147483647, 1, 0, 2),
+('bx_courses_menu_manage_tools', 'bx_courses', 'clear-reports', '_bx_courses_menu_item_title_system_clear_reports', '_bx_courses_menu_item_title_clear_reports', 'javascript:void(0)', 'javascript:{js_object}.onClickClearReports({content_id});', '_self', 'eraser', '', 2147483647, 1, 0, 3);
+
+-- MENU: dashboard manage tools
+SET @iManageMenuOrder = (SELECT IFNULL(MAX(`order`), 0) FROM `sys_menu_items` WHERE `set_name`='sys_account_dashboard_manage_tools' LIMIT 1);
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `addon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('sys_account_dashboard_manage_tools', 'bx_courses', 'courses-administration', '_bx_courses_menu_item_title_system_admt_entries', '_bx_courses_menu_item_title_admt_entries', 'page.php?i=courses-administration', '', '_self', 'users', 'a:2:{s:6:"module";s:10:"bx_courses";s:6:"method";s:27:"get_menu_addon_manage_tools";}', '', 192, 1, 0, @iManageMenuOrder + 1);
+
+-- MENU: add menu item to profiles modules (trigger* menu sets are processed separately upon modules enable/disable)
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('trigger_profile_view_submenu', 'bx_courses', 'joined-courses', '_bx_courses_menu_item_title_system_view_joined_entries', '_bx_courses_menu_item_title_view_joined_entries', 'page.php?i=joined-courses&profile_id={profile_id}', '', '', 'book-reader col-blue3-dark', '', 2147483647, 1, 0, 0);
+
+-- ACL
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_courses', 'create entry', NULL, '_bx_courses_acl_action_create_profile', '', 1, 1);
+SET @iIdActionProfileCreate = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_courses', 'use paid join', NULL, '_bx_courses_acl_action_use_paid_join', '', 1, 1);
+SET @iIdActionUsePaidJoin = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_courses', 'delete entry', NULL, '_bx_courses_acl_action_delete_profile', '', 1, 1);
+SET @iIdActionProfileDelete = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_courses', 'view entry', NULL, '_bx_courses_acl_action_view_profile', '', 1, 0);
+SET @iIdActionProfileView = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_courses', 'edit any entry', NULL, '_bx_courses_acl_action_edit_any_profile', '', 1, 3);
+SET @iIdActionProfileEditAny = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_courses', 'delete invites', NULL, '_bx_courses_acl_action_delete_invites', '', 1, 3);
+SET @iIdActionProfileDeleteInvites = LAST_INSERT_ID();
+
+SET @iUnauthenticated = 1;
+SET @iAccount = 2;
+SET @iStandard = 3;
+SET @iUnconfirmed = 4;
+SET @iPending = 5;
+SET @iSuspended = 6;
+SET @iModerator = 7;
+SET @iAdministrator = 8;
+SET @iPremium = 9;
+
+INSERT INTO `sys_acl_matrix` (`IDLevel`, `IDAction`) VALUES
+
+-- profile create
+(@iAccount, @iIdActionProfileCreate),
+(@iStandard, @iIdActionProfileCreate),
+(@iUnconfirmed, @iIdActionProfileCreate),
+(@iPending, @iIdActionProfileCreate),
+(@iModerator, @iIdActionProfileCreate),
+(@iAdministrator, @iIdActionProfileCreate),
+(@iPremium, @iIdActionProfileCreate),
+
+-- use paid join
+(@iStandard, @iIdActionUsePaidJoin),
+(@iModerator, @iIdActionUsePaidJoin),
+(@iAdministrator, @iIdActionUsePaidJoin),
+(@iPremium, @iIdActionUsePaidJoin),
+
+-- profile delete
+(@iAccount, @iIdActionProfileDelete),
+(@iStandard, @iIdActionProfileDelete),
+(@iUnconfirmed, @iIdActionProfileDelete),
+(@iPending, @iIdActionProfileDelete),
+(@iModerator, @iIdActionProfileDelete),
+(@iAdministrator, @iIdActionProfileDelete),
+(@iPremium, @iIdActionProfileDelete),
+
+-- profile view
+(@iUnauthenticated, @iIdActionProfileView),
+(@iAccount, @iIdActionProfileView),
+(@iStandard, @iIdActionProfileView),
+(@iUnconfirmed, @iIdActionProfileView),
+(@iPending, @iIdActionProfileView),
+(@iModerator, @iIdActionProfileView),
+(@iAdministrator, @iIdActionProfileView),
+(@iPremium, @iIdActionProfileView),
+
+-- any profile edit
+(@iModerator, @iIdActionProfileEditAny),
+(@iAdministrator, @iIdActionProfileEditAny),
+
+-- any invites edit
+(@iModerator, @iIdActionProfileDeleteInvites),
+(@iAdministrator, @iIdActionProfileDeleteInvites);
+
+
+-- METATAGS
+INSERT INTO `sys_objects_metatags` (`object`, `table_keywords`, `table_locations`, `table_mentions`, `override_class_name`, `override_class_file`) VALUES
+('bx_courses', 'bx_courses_meta_keywords', 'bx_courses_meta_locations', 'bx_courses_meta_mentions', '', '');
+
+-- CATEGORY
+INSERT INTO `sys_objects_category` (`object`, `search_object`, `form_object`, `list_name`, `table`, `field`, `join`, `where`, `override_class_name`, `override_class_file`) VALUES
+('bx_courses_cats', 'bx_courses', 'bx_course', 'bx_courses_cats', 'bx_courses_data', 'cat', 'INNER JOIN `sys_profiles` ON (`sys_profiles`.`content_id` = `bx_courses_data`.`id` AND `sys_profiles`.`type` = ''bx_courses'')', 'AND `sys_profiles`.`status` = ''active''', '', '');
+
+-- SEARCH
+SET @iSearchOrder = (SELECT IFNULL(MAX(`Order`), 0) FROM `sys_objects_search`);
+INSERT INTO `sys_objects_search` (`ObjectName`, `Title`, `Order`, `ClassName`, `ClassPath`) VALUES
+('bx_courses', '_bx_courses', @iSearchOrder + 1, 'BxCoursesSearchResult', 'modules/boonex/courses/classes/BxCoursesSearchResult.php');
+
+-- CONNECTIONS
+INSERT INTO `sys_objects_connection` (`object`, `table`, `type`, `override_class_name`, `override_class_file`) VALUES
+('bx_courses_fans', 'bx_courses_fans', 'mutual', '', '');
+
+-- STATS
+SET @iMaxOrderStats = (SELECT IFNULL(MAX(`order`), 0) FROM `sys_statistics`);
+INSERT INTO `sys_statistics` (`module`, `name`, `title`, `link`, `icon`, `query`, `order`) VALUES 
+('bx_courses', 'bx_courses', '_bx_courses', 'page.php?i=courses-home', 'book-reader col-blue3-dark', 'SELECT COUNT(*) FROM `bx_courses_data` AS `td` LEFT JOIN `sys_profiles` AS `tp` ON `td`.`id` = `tp`.`content_id` AND `tp`.`type`=''bx_courses'' WHERE 1 AND `tp`.`status`=''active''', @iMaxOrderStats + 1);
+
+-- CHARTS
+SET @iMaxOrderCharts = (SELECT IFNULL(MAX(`order`), 0) FROM `sys_objects_chart`);
+INSERT INTO `sys_objects_chart` (`object`, `title`, `table`, `field_date_ts`, `field_date_dt`, `field_status`, `query`, `active`, `order`, `class_name`, `class_file`) VALUES
+('bx_courses_growth', '_bx_courses_chart_growth', 'bx_courses_data', 'added', '', '', 'SELECT {field_date_formatted} AS `period`, COUNT(*) AS {object} FROM {table} LEFT JOIN `sys_profiles` AS `tp` ON {table}.`id` = `tp`.`content_id` AND `tp`.`type`=''bx_courses'' WHERE 1 AND `tp`.`status`=''active'' {where_inteval} GROUP BY `period` ORDER BY {table}.{field_date} ASC', 1, @iMaxOrderCharts + 1, 'BxDolChartGrowth', ''),
+('bx_courses_growth_speed', '_bx_courses_chart_growth_speed', 'bx_courses_data', 'added', '', '', 'SELECT {field_date_formatted} AS `period`, COUNT(*) AS {object} FROM {table} LEFT JOIN `sys_profiles` AS `tp` ON {table}.`id` = `tp`.`content_id` AND `tp`.`type`=''bx_courses'' WHERE 1 AND `tp`.`status`=''active'' {where_inteval} GROUP BY `period` ORDER BY {table}.{field_date} ASC', 1, @iMaxOrderCharts + 2, 'BxDolChartGrowthSpeed', '');
+
+-- GRID: connections
+INSERT INTO `sys_objects_grid` (`object`, `source_type`, `source`, `table`, `field_id`, `field_order`, `field_active`, `paginate_url`, `paginate_per_page`, `paginate_simple`, `paginate_get_start`, `paginate_get_per_page`, `filter_fields`, `filter_fields_translatable`, `filter_mode`, `sorting_fields`, `sorting_fields_translatable`, `visible_for_levels`, `responsive`, `override_class_name`, `override_class_file`) VALUES
+('bx_courses_fans', 'Sql', 'SELECT `p`.`id`, `c`.`added`, `c`.`mutual` FROM `sys_profiles` AS `p` INNER JOIN `sys_accounts` AS `a` ON (`a`.`id` = `p`.`account_id`) {join_connections}', 'sys_profiles', 'id', 'c`.`added', '', '', 10, NULL, 'start', '', 'name,email', '', 'auto', '', '', 2147483647, 0, 'BxCoursesGridConnections', 'modules/boonex/courses/classes/BxCoursesGridConnections.php');
+
+INSERT INTO `sys_grid_fields` (`object`, `name`, `title`, `width`, `params`, `order`) VALUES
+('bx_courses_fans', 'name', '_sys_name', '50%', '', 10),
+('bx_courses_fans', 'role', '_bx_courses_txt_role', '10%', '', 15),
+('bx_courses_fans', 'role_added', '_bx_courses_txt_role_added', '10%', '', 16),
+('bx_courses_fans', 'role_expired', '_bx_courses_txt_role_expired', '10%', '', 17),
+('bx_courses_fans', 'actions', '', '20%', '', 20);
+
+INSERT INTO `sys_grid_actions` (`object`, `type`, `name`, `title`, `icon`, `confirm`, `order`) VALUES
+('bx_courses_fans', 'single', 'accept', '_sys_accept', '', 0, 10),
+('bx_courses_fans', 'single', 'set_role', '_bx_courses_txt_set_role', '', 0, 20),
+('bx_courses_fans', 'single', 'set_role_submit', '', '', 0, 21),
+('bx_courses_fans', 'single', 'delete', '', 'remove', 1, 40);
+
+
+-- GRID: invites
+INSERT INTO `sys_objects_grid` (`object`, `source_type`, `source`, `table`, `field_id`, `field_order`, `field_active`, `paginate_url`, `paginate_per_page`, `paginate_simple`, `paginate_get_start`, `paginate_get_per_page`, `filter_fields`, `filter_fields_translatable`, `filter_mode`, `sorting_fields`, `sorting_fields_translatable`, `visible_for_levels`, `responsive`, `override_class_name`, `override_class_file`) VALUES
+('bx_courses_invites', 'Sql', 'SELECT `bx_courses_invites`.`id`, `bx_courses_invites`.`invited_profile_id`, `bx_courses_invites`.`added`, `bx_courses_invites`.`author_profile_id` FROM `sys_profiles` AS `p` INNER JOIN `sys_accounts` AS `a` ON (`a`.`id` = `p`.`account_id`) INNER JOIN `bx_courses_invites` ON `bx_courses_invites`.`invited_profile_id` = `p`.`id` ', 'bx_courses_invites', 'id', 'bx_courses_invites`.`added', '', '', 10, NULL, 'start', '', 'name,email', '', 'auto', '', '', 2147483647, 0, 'BxCoursesGridInvites', 'modules/boonex/courses/classes/BxCoursesGridInvites.php');
+
+INSERT INTO `sys_grid_fields` (`object`, `name`, `title`, `width`, `params`, `order`) VALUES
+('bx_courses_invites', 'name', '_sys_name', '33%', '', 10),
+('bx_courses_invites', 'added', '_sys_added', '33%', '', 20),
+('bx_courses_invites', 'actions', '', '34%', '', 30);
+
+INSERT INTO `sys_grid_actions` (`object`, `type`, `name`, `title`, `icon`, `confirm`, `order`) VALUES
+('bx_courses_invites', 'single', 'delete', '', 'remove', 1, 10);
+
+
+-- GRIDS: administration
+
+INSERT INTO `sys_objects_grid` (`object`, `source_type`, `source`, `table`, `field_id`, `field_order`, `field_active`, `paginate_url`, `paginate_per_page`, `paginate_simple`, `paginate_get_start`, `paginate_get_per_page`, `filter_fields`, `filter_fields_translatable`, `filter_mode`, `sorting_fields`, `sorting_fields_translatable`, `visible_for_levels`, `override_class_name`, `override_class_file`) VALUES
+('bx_courses_administration', 'Sql', 'SELECT `td`.*, `td`.`name` AS `name`, `ta`.`email` AS `account`, `td`.`added` AS `added_ts`, `tp`.`status` AS `status` FROM `bx_courses_data` AS `td` LEFT JOIN `sys_profiles` AS `tp` ON `td`.`id`=`tp`.`content_id` AND `tp`.`type`=''bx_courses'' LEFT JOIN `sys_accounts` AS `ta` ON `tp`.`account_id`=`ta`.`id` WHERE 1 ', 'bx_courses_data', 'id', 'added', 'status', '', 20, NULL, 'start', '', 'name', '', 'like', 'reports', '', 192, 'BxCoursesGridAdministration', 'modules/boonex/courses/classes/BxCoursesGridAdministration.php'),
+('bx_courses_common', 'Sql', 'SELECT `td`.*, `td`.`name` AS `name`, `ta`.`email` AS `account`, `td`.`added` AS `added_ts`, `tp`.`status` AS `status` FROM `bx_courses_data` AS `td` LEFT JOIN `sys_profiles` AS `tp` ON `td`.`id`=`tp`.`content_id` AND `tp`.`type`=''bx_courses'' LEFT JOIN `sys_accounts` AS `ta` ON `tp`.`account_id`=`ta`.`id` WHERE 1 ', 'bx_courses_data', 'id', 'added', 'status', '', 20, NULL, 'start', '', 'name', '', 'like', '', '', 2147483647, 'BxCoursesGridCommon', 'modules/boonex/courses/classes/BxCoursesGridCommon.php');
+
+INSERT INTO `sys_grid_fields` (`object`, `name`, `title`, `width`, `translatable`, `chars_limit`, `params`, `order`) VALUES
+('bx_courses_administration', 'checkbox', '_sys_select', '2%', 0, '', '', 1),
+('bx_courses_administration', 'switcher', '_bx_courses_grid_column_title_adm_active', '8%', 0, '', '', 2),
+('bx_courses_administration', 'reports', '_sys_txt_reports_title', '5%', 0, '', '', 3),
+('bx_courses_administration', 'name', '_bx_courses_grid_column_title_adm_name', '25%', 0, '', '', 4),
+('bx_courses_administration', 'added_ts', '_bx_courses_grid_column_title_adm_added', '20%', 1, '25', '', 5),
+('bx_courses_administration', 'account', '_bx_courses_grid_column_title_adm_account', '20%', 0, '25', '', 6),
+('bx_courses_administration', 'actions', '', '20%', 0, '', '', 7),
+('bx_courses_common', 'checkbox', '_sys_select', '2%', 0, '', '', 1),
+('bx_courses_common', 'name', '_bx_courses_grid_column_title_adm_name', '48%', 0, '', '', 2),
+('bx_courses_common', 'added_ts', '_bx_courses_grid_column_title_adm_added', '30%', 1, '25', '', 3),
+('bx_courses_common', 'actions', '', '20%', 0, '', '', 4);
+
+INSERT INTO `sys_grid_actions` (`object`, `type`, `name`, `title`, `icon`, `icon_only`, `confirm`, `order`) VALUES
+('bx_courses_administration', 'bulk', 'delete', '_bx_courses_grid_action_title_adm_delete', '', 0, 1, 2),
+('bx_courses_administration', 'bulk', 'delete_with_content', '_bx_courses_grid_action_title_adm_delete_with_content', '', 0, 1, 3),
+('bx_courses_administration', 'bulk', 'clear_reports', '_bx_classes_grid_action_title_adm_clear_reports', '', 0, 1, 4),
+('bx_courses_administration', 'single', 'settings', '_bx_courses_grid_action_title_adm_more_actions', 'cog', 1, 0, 2),
+('bx_courses_administration', 'single', 'audit_content', '_bx_courses_grid_action_title_adm_audit_content', 'search', 1, 0, 3),
+('bx_courses_administration', 'single', 'audit_context', '_bx_courses_grid_action_title_adm_audit_context', 'search-location', 1, 0, 4),
+('bx_courses_common', 'bulk', 'delete', '_bx_courses_grid_action_title_adm_delete', '', 0, 1, 1),
+('bx_courses_common', 'bulk', 'delete_with_content', '_bx_courses_grid_action_title_adm_delete_with_content', '', 0, 1, 2),
+('bx_courses_common', 'single', 'settings', '_bx_courses_grid_action_title_adm_more_actions', 'cog', 1, 0, 1);
+
+-- GRIDS: Pricing
+INSERT INTO `sys_objects_grid` (`object`, `source_type`, `source`, `table`, `field_id`, `field_order`, `field_active`, `paginate_url`, `paginate_per_page`, `paginate_simple`, `paginate_get_start`, `paginate_get_per_page`, `filter_fields`, `filter_fields_translatable`, `filter_mode`, `sorting_fields`, `sorting_fields_translatable`, `visible_for_levels`, `override_class_name`, `override_class_file`) VALUES
+('bx_courses_prices_manage', 'Sql', 'SELECT * FROM `bx_courses_prices` WHERE 1 ', 'bx_courses_prices', 'id', 'order', '', '', 100, NULL, 'start', '', 'period,period_unit,price', '', 'like', '', '', 2147483647, 'BxCoursesGridPricesManage', 'modules/boonex/courses/classes/BxCoursesGridPricesManage.php'),
+('bx_courses_prices_view', 'Sql', 'SELECT * FROM `bx_courses_prices` WHERE 1 ', 'bx_courses_prices', 'id', 'order', '', '', 100, NULL, 'start', '', 'period,period_unit,price', '', 'like', '', '', 2147483647, 'BxCoursesGridPricesView', 'modules/boonex/courses/classes/BxCoursesGridPricesView.php');
+
+INSERT INTO `sys_grid_fields` (`object`, `name`, `title`, `width`, `translatable`, `chars_limit`, `params`, `order`) VALUES
+('bx_courses_prices_manage', 'checkbox', '_sys_select', '1%', 0, '', '', 1),
+('bx_courses_prices_manage', 'order', '', '1%', 0, '', '', 2),
+('bx_courses_prices_manage', 'name', '_bx_courses_grid_column_title_name', '38%', 0, 32, '', 3),
+('bx_courses_prices_manage', 'price', '_bx_courses_grid_column_title_price', '20%', 0, 16, '', 4),
+('bx_courses_prices_manage', 'period', '_bx_courses_grid_column_title_period', '20%', 0, 16, '', 5),
+('bx_courses_prices_manage', 'actions', '', '20%', 0, '', '', 6),
+
+('bx_courses_prices_view', 'role_id', '_bx_courses_grid_column_title_role_id', '40%', 0, 32, '', 1),
+('bx_courses_prices_view', 'price', '_bx_courses_grid_column_title_price', '20%', 0, 16, '', 2),
+('bx_courses_prices_view', 'period', '_bx_courses_grid_column_title_period', '20%', 0, 16, '', 3),
+('bx_courses_prices_view', 'actions', '', '20%', 0, '', '', 4);
+
+INSERT INTO `sys_grid_actions` (`object`, `type`, `name`, `title`, `icon`, `icon_only`, `confirm`, `order`) VALUES
+('bx_courses_prices_manage', 'independent', 'add', '_bx_courses_grid_action_title_add', '', 0, 0, 1),
+('bx_courses_prices_manage', 'single', 'edit', '_bx_courses_grid_action_title_edit', 'pencil-alt', 1, 0, 1),
+('bx_courses_prices_manage', 'single', 'delete', '_bx_courses_grid_action_title_delete', 'remove', 1, 1, 2),
+('bx_courses_prices_manage', 'bulk', 'delete', '_bx_courses_grid_action_title_delete', '', 0, 1, 1),
+
+('bx_courses_prices_view', 'single', 'buy', '_bx_courses_grid_action_title_buy', 'cart-plus', 0, 0, 1),
+('bx_courses_prices_view', 'single', 'subscribe', '_bx_courses_grid_action_title_subscribe', 'credit-card', 0, 0, 2),
+('bx_courses_prices_view', 'single', 'choose', '_bx_courses_grid_action_title_choose', 'far check-square', 0, 0, 3);
+
+
+-- ALERTS
+
+INSERT INTO `sys_alerts_handlers` (`name`, `class`, `file`, `service_call`) VALUES 
+('bx_courses', 'BxCoursesAlertsResponse', 'modules/boonex/courses/classes/BxCoursesAlertsResponse.php', '');
+SET @iHandler := LAST_INSERT_ID();
+
+INSERT INTO `sys_alerts` (`unit`, `action`, `handler_id`) VALUES
+('system', 'save_setting', @iHandler),
+('bx_timeline', 'post_common', @iHandler),
+('bx_courses_pics', 'file_deleted', @iHandler),
+('bx_courses_fans', 'connection_added', @iHandler),
+('bx_courses_fans', 'connection_removed', @iHandler),
+('profile', 'delete', @iHandler),
+('bx_courses', 'fan_added', @iHandler),
+('bx_courses', 'join_invitation', @iHandler),
+('bx_courses', 'join_request', @iHandler),
+('bx_courses', 'join_request_accepted', @iHandler),
+('bx_courses', 'timeline_view', @iHandler),
+('bx_courses', 'timeline_post', @iHandler),
+('bx_courses', 'timeline_delete', @iHandler),
+('bx_courses', 'timeline_comment', @iHandler),
+('bx_courses', 'timeline_vote', @iHandler),
+('bx_courses', 'timeline_score', @iHandler),
+('bx_courses', 'timeline_report', @iHandler),
+('bx_courses', 'timeline_repost', @iHandler),
+('bx_courses', 'timeline_pin', @iHandler),
+('bx_courses', 'timeline_promote', @iHandler);
+
+-- PRIVACY
+
+INSERT INTO `sys_objects_privacy` (`object`, `module`, `action`, `title`, `default_group`, `spaces`, `table`, `table_field_id`, `table_field_author`, `override_class_name`, `override_class_file`) VALUES
+('bx_courses_allow_view_to', 'bx_courses', 'view', '_bx_courses_form_profile_input_allow_view_to', '3', '', 'bx_courses_data', 'id', 'author', 'BxCoursesPrivacy', 'modules/boonex/courses/classes/BxCoursesPrivacy.php'),
+('bx_courses_allow_view_notification_to', 'bx_courses', 'view_event', '_bx_courses_form_profile_input_allow_view_notification_to', '3', '', 'bx_notifications_events', 'id', 'object_owner_id', 'BxCoursesPrivacyNotifications', 'modules/boonex/courses/classes/BxCoursesPrivacyNotifications.php'),
+('bx_courses_allow_post_to', 'bx_courses', 'post', '_bx_courses_form_profile_input_allow_post_to', 'p', '', 'bx_courses_data', 'id', 'author', 'BxCoursesPrivacyPost', 'modules/boonex/courses/classes/BxCoursesPrivacyPost.php'),
+('bx_courses_allow_view_favorite_list', 'bx_courses', 'view_favorite_list', '_bx_courses_form_profile_input_allow_view_favorite_list', '3', '', 'bx_courses_favorites_lists', 'id', 'author_id', 'BxCoursesPrivacy', 'modules/boonex/courses/classes/BxCoursesPrivacy.php');
+
+-- EMAIL TEMPLATES
+
+INSERT INTO `sys_email_templates` (`Module`, `NameSystem`, `Name`, `Subject`, `Body`) VALUES
+('bx_courses', '_bx_courses_email_join_request', 'bx_courses_join_request', '_bx_courses_email_join_request_subject', '_bx_courses_email_join_request_body'),
+('bx_courses', '_bx_courses_email_join_reject', 'bx_courses_join_reject', '_bx_courses_email_join_reject_subject', '_bx_courses_email_join_reject_body'),
+('bx_courses', '_bx_courses_email_join_confirm', 'bx_courses_join_confirm', '_bx_courses_email_join_confirm_subject', '_bx_courses_email_join_confirm_body'),
+('bx_courses', '_bx_courses_email_fan_remove', 'bx_courses_fan_remove', '_bx_courses_email_fan_remove_subject', '_bx_courses_email_fan_remove_body'),
+('bx_courses', '_bx_courses_email_fan_become_admin', 'bx_courses_fan_become_admin', '_bx_courses_email_fan_become_admin_subject', '_bx_courses_email_fan_become_admin_body'),
+('bx_courses', '_bx_courses_email_admin_become_fan', 'bx_courses_admin_become_fan', '_bx_courses_email_admin_become_fan_subject', '_bx_courses_email_admin_become_fan_body'),
+('bx_courses', '_bx_courses_email_set_role', 'bx_courses_set_role', '_bx_courses_email_set_role_subject', '_bx_courses_email_set_role_body'),
+('bx_courses', '_bx_courses_email_invitation', 'bx_courses_invitation', '_bx_courses_email_invitation_subject', '_bx_courses_email_invitation_body');
+
+-- UPLOADERS
+
+INSERT INTO `sys_objects_uploader` (`object`, `active`, `override_class_name`, `override_class_file`) VALUES
+('bx_courses_cover_crop', 1, 'BxCoursesUploaderCoverCrop', 'modules/boonex/courses/classes/BxCoursesUploaderCoverCrop.php'),
+('bx_courses_picture_crop', 1, 'BxCoursesUploaderPictureCrop', 'modules/boonex/courses/classes/BxCoursesUploaderPictureCrop.php');
+
+-- CRON
+
+INSERT INTO `sys_cron_jobs` (`name`, `time`, `class`, `file`, `service_call`) VALUES
+('bx_courses_pruning', '0 0 * * *', 'BxCoursesCronPruning', 'modules/boonex/courses/classes/BxCoursesCronPruning.php', '');

+ 459 - 0
modules/boonex/courses/updates/12.0.0_12.0.1/source/install/sql/install.sql

@@ -0,0 +1,459 @@
+SET @sStorageEngine = (SELECT `value` FROM `sys_options` WHERE `name` = 'sys_storage_default');
+
+-- TABLE: PROFILES
+CREATE TABLE IF NOT EXISTS `bx_courses_data` (
+  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+  `author` int(10) unsigned NOT NULL,
+  `added` int(11) NOT NULL,
+  `changed` int(11) NOT NULL,
+  `picture` int(11) NOT NULL,
+  `cover` int(11) NOT NULL,
+  `name` varchar(255) NOT NULL,
+  `cat` int(11) NOT NULL,
+  `desc` text NOT NULL,
+  `labels` text NOT NULL,
+  `location` text NOT NULL,
+  `views` int(11) NOT NULL default '0',
+  `rate` float NOT NULL default '0',
+  `votes` int(11) NOT NULL default '0',
+  `score` int(11) NOT NULL default '0',
+  `sc_up` int(11) NOT NULL default '0',
+  `sc_down` int(11) NOT NULL default '0',
+  `favorites` int(11) NOT NULL default '0',
+  `comments` int(11) NOT NULL default '0',
+  `reports` int(11) NOT NULL default '0',
+  `featured` int(11) NOT NULL default '0',
+  `join_confirmation` tinyint(4) NOT NULL DEFAULT '1',
+  `allow_view_to` varchar(16) NOT NULL DEFAULT '3',
+  `allow_post_to` varchar(16) NOT NULL DEFAULT '3',
+  `status` enum('active','awaiting','hidden') NOT NULL DEFAULT 'active',
+  PRIMARY KEY (`id`),
+  FULLTEXT KEY `search_fields` (`name`, `desc`)
+);
+
+-- TABLE: STORAGES & TRANSCODERS
+CREATE TABLE IF NOT EXISTS `bx_courses_pics` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `profile_id` int(10) unsigned NOT NULL,
+  `remote_id` varchar(128) NOT NULL,
+  `path` varchar(255) NOT NULL,
+  `file_name` varchar(255) NOT NULL,
+  `mime_type` varchar(128) NOT NULL,
+  `ext` varchar(32) NOT NULL,
+  `size` bigint(20) NOT NULL,
+  `added` int(11) NOT NULL,
+  `modified` int(11) NOT NULL,
+  `private` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `remote_id` (`remote_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_courses_pics_resized` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `profile_id` int(10) unsigned NOT NULL,
+  `remote_id` varchar(128) NOT NULL,
+  `path` varchar(255) NOT NULL,
+  `file_name` varchar(255) NOT NULL,
+  `mime_type` varchar(128) NOT NULL,
+  `ext` varchar(32) NOT NULL,
+  `size` bigint(20) NOT NULL,
+  `added` int(11) NOT NULL,
+  `modified` int(11) NOT NULL,
+  `private` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `remote_id` (`remote_id`)
+);
+
+-- TABLE: comments
+CREATE TABLE IF NOT EXISTS `bx_courses_cmts` (
+  `cmt_id` int(11) NOT NULL AUTO_INCREMENT,
+  `cmt_parent_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_vparent_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_object_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_author_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_level` int(11) NOT NULL DEFAULT '0',
+  `cmt_text` text NOT NULL,
+  `cmt_mood` tinyint(4) NOT NULL DEFAULT '0',
+  `cmt_rate` int(11) NOT NULL DEFAULT '0',
+  `cmt_rate_count` int(11) NOT NULL DEFAULT '0',
+  `cmt_time` int(11) unsigned NOT NULL DEFAULT '0',
+  `cmt_replies` int(11) NOT NULL DEFAULT '0',
+  `cmt_pinned` int(11) NOT NULL default '0',
+  PRIMARY KEY (`cmt_id`),
+  KEY `cmt_object_id` (`cmt_object_id`,`cmt_parent_id`),
+  FULLTEXT KEY `search_fields` (`cmt_text`)
+);
+
+-- TABLE: VIEWS
+CREATE TABLE IF NOT EXISTS `bx_courses_views_track` (
+  `object_id` int(11) NOT NULL default '0',
+  `viewer_id` int(11) NOT NULL default '0',
+  `viewer_nip` int(11) unsigned NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  KEY `id` (`object_id`,`viewer_id`,`viewer_nip`)
+);
+
+-- TABLE: VOTES
+CREATE TABLE IF NOT EXISTS `bx_courses_votes` (
+  `object_id` int(11) NOT NULL default '0',
+  `count` int(11) NOT NULL default '0',
+  `sum` int(11) NOT NULL default '0',
+  UNIQUE KEY `object_id` (`object_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_courses_votes_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `author_nip` int(11) unsigned NOT NULL default '0',
+  `value` tinyint(4) NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `vote` (`object_id`, `author_nip`)
+);
+
+-- TABLE: REPORTS
+CREATE TABLE IF NOT EXISTS `bx_courses_reports` (
+  `object_id` int(11) NOT NULL default '0',
+  `count` int(11) NOT NULL default '0',
+  UNIQUE KEY `object_id` (`object_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_courses_reports_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `author_nip` int(11) unsigned NOT NULL default '0',
+  `type` varchar(32) NOT NULL default '',
+  `text` text NOT NULL default '',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `report` (`object_id`, `author_nip`)
+);
+
+-- TABLE: metas
+CREATE TABLE IF NOT EXISTS `bx_courses_meta_keywords` (
+  `object_id` int(10) unsigned NOT NULL,
+  `keyword` varchar(255) NOT NULL,
+  KEY `object_id` (`object_id`),
+  KEY `keyword` (`keyword`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_courses_meta_locations` (
+  `object_id` int(10) unsigned NOT NULL,
+  `lat` double NOT NULL,
+  `lng` double NOT NULL,
+  `country` varchar(2) NOT NULL,
+  `state` varchar(255) NOT NULL,
+  `city` varchar(255) NOT NULL,
+  `zip` varchar(255) NOT NULL,
+  `street` varchar(255) NOT NULL,
+  `street_number` varchar(255) NOT NULL,
+  PRIMARY KEY (`object_id`),
+  KEY `country_state_city` (`country`,`state`(8),`city`(8))
+);
+
+CREATE TABLE IF NOT EXISTS `bx_courses_meta_mentions` (
+  `object_id` int(10) unsigned NOT NULL,
+  `profile_id` int(10) unsigned NOT NULL,
+  KEY `object_id` (`object_id`),
+  KEY `profile_id` (`profile_id`)
+);
+
+-- TABLE: fans
+CREATE TABLE IF NOT EXISTS `bx_courses_fans` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `initiator` int(11) NOT NULL,
+  `content` int(11) NOT NULL,
+  `mutual` tinyint(4) NOT NULL,
+  `added` int(10) unsigned NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `initiator` (`initiator`,`content`),
+  KEY `content` (`content`)
+);
+
+-- TABLE: admins
+CREATE TABLE IF NOT EXISTS `bx_courses_admins` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `group_profile_id` int(10) unsigned NOT NULL,
+  `fan_id` int(10) unsigned NOT NULL,
+  `role` int(10) unsigned NOT NULL default '0',
+  `order` varchar(32) NOT NULL default '',
+  `added` int(11) unsigned NOT NULL default '0',
+  `expired` int(11) unsigned NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `admin` (`group_profile_id`,`fan_id`)
+);
+
+-- TABLE: favorites
+CREATE TABLE IF NOT EXISTS `bx_courses_favorites_track` (
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `list_id` int(11) NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  KEY `id` (`object_id`,`author_id`)
+);
+
+CREATE TABLE `bx_courses_favorites_lists` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `title` varchar(255) NOT NULL,
+  `author_id` int(11) NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  `allow_view_favorite_list_to` varchar(16) NOT NULL DEFAULT '3',
+   PRIMARY KEY (`id`)
+);
+
+
+-- TABLE: scores
+CREATE TABLE IF NOT EXISTS `bx_courses_scores` (
+  `object_id` int(11) NOT NULL default '0',
+  `count_up` int(11) NOT NULL default '0',
+  `count_down` int(11) NOT NULL default '0',
+  UNIQUE KEY `object_id` (`object_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_courses_scores_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `author_nip` int(11) unsigned NOT NULL default '0',
+  `type` varchar(8) NOT NULL default '',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `vote` (`object_id`, `author_nip`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_courses_invites` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `key` varchar(128) NOT NULL default '0',
+  `group_profile_id` int(11) NOT NULL default '0',
+  `author_profile_id` int(11) NOT NULL default '0',
+  `invited_profile_id` int(11) NOT NULL default '0',
+  `added` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`)
+);
+
+-- TABLE: Pricing
+CREATE TABLE IF NOT EXISTS `bx_courses_prices` (
+  `id` int(11) NOT NULL auto_increment,
+  `profile_id` int(11) NOT NULL default '0',
+  `role_id` int(11) unsigned NOT NULL default '0',
+  `name` varchar(128) NOT NULL default '',
+  `period` int(11) unsigned NOT NULL default '1',
+  `period_unit` varchar(32) NOT NULL default '',
+  `price` float unsigned NOT NULL default '1',
+  `order` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `name` (`name`),
+  UNIQUE KEY `type` (`profile_id`, `role_id`,`period`, `period_unit`)
+);
+
+-- STORAGES & TRANSCODERS
+INSERT INTO `sys_objects_storage` (`object`, `engine`, `params`, `token_life`, `cache_control`, `levels`, `table_files`, `ext_mode`, `ext_allow`, `ext_deny`, `quota_size`, `current_size`, `quota_number`, `current_number`, `max_file_size`, `ts`) VALUES
+('bx_courses_pics', @sStorageEngine, '', 360, 2592000, 3, 'bx_courses_pics', 'allow-deny', 'jpg,jpeg,jpe,gif,png', '', 0, 0, 0, 0, 0, 0),
+('bx_courses_pics_resized', @sStorageEngine, '', 360, 2592000, 3, 'bx_courses_pics_resized', 'allow-deny', 'jpg,jpeg,jpe,gif,png', '', 0, 0, 0, 0, 0, 0);
+
+INSERT INTO `sys_objects_transcoder` (`object`, `storage_object`, `source_type`, `source_params`, `private`, `atime_tracking`, `atime_pruning`, `ts`) VALUES 
+('bx_courses_icon', 'bx_courses_pics_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_courses_pics";}', 'no', '1', '2592000', '0'),
+('bx_courses_thumb', 'bx_courses_pics_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_courses_pics";}', 'no', '1', '2592000', '0'),
+('bx_courses_avatar', 'bx_courses_pics_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_courses_pics";}', 'no', '1', '2592000', '0'),
+('bx_courses_avatar_big', 'bx_courses_pics_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_courses_pics";}', 'no', '1', '2592000', '0'),
+('bx_courses_picture', 'bx_courses_pics_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_courses_pics";}', 'no', '1', '2592000', '0'),
+('bx_courses_cover', 'bx_courses_pics_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_courses_pics";}', 'no', '1', '2592000', '0'),
+('bx_courses_cover_thumb', 'bx_courses_pics_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_courses_pics";}', 'no', '1', '2592000', '0'),
+('bx_courses_gallery', 'bx_courses_pics_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_courses_pics";}', 'no', '1', '2592000', '0');
+
+INSERT INTO `sys_transcoder_filters` (`transcoder_object`, `filter`, `filter_params`, `order`) VALUES 
+('bx_courses_icon', 'Resize', 'a:3:{s:1:"w";s:2:"30";s:1:"h";s:2:"30";s:13:"square_resize";s:1:"1";}', '0'),
+('bx_courses_thumb', 'Resize', 'a:3:{s:1:"w";s:2:"50";s:1:"h";s:2:"50";s:13:"square_resize";s:1:"1";}', '0'),
+('bx_courses_avatar', 'Resize', 'a:3:{s:1:"w";s:3:"100";s:1:"h";s:3:"100";s:13:"square_resize";s:1:"1";}', '0'),
+('bx_courses_avatar_big', 'Resize', 'a:3:{s:1:"w";s:3:"200";s:1:"h";s:3:"200";s:13:"square_resize";s:1:"1";}', '0'),
+('bx_courses_picture', 'Resize', 'a:3:{s:1:"w";s:4:"1024";s:1:"h";s:4:"1024";s:13:"square_resize";s:1:"0";}', '0'),
+('bx_courses_cover', 'Resize', 'a:1:{s:1:"w";s:4:"2000";}', '0'),
+('bx_courses_cover_thumb', 'Resize', 'a:3:{s:1:"w";s:2:"48";s:1:"h";s:2:"48";s:13:"square_resize";s:1:"1";}', '0'),
+('bx_courses_gallery', 'Resize', 'a:1:{s:1:"w";s:3:"500";}', '0');
+
+-- FORMS
+INSERT INTO `sys_objects_form`(`object`, `module`, `title`, `action`, `form_attrs`, `table`, `key`, `uri`, `uri_title`, `submit_name`, `params`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_course', 'bx_courses', '_bx_courses_form_profile', '', 'a:1:{s:7:\"enctype\";s:19:\"multipart/form-data\";}', 'bx_courses_data', 'id', '', '', 'do_submit', '', 0, 1, 'BxCoursesFormEntry', 'modules/boonex/courses/classes/BxCoursesFormEntry.php');
+
+INSERT INTO `sys_form_displays`(`object`, `display_name`, `module`, `view_mode`, `title`) VALUES 
+('bx_course', 'bx_course_add', 'bx_courses', 0, '_bx_courses_form_profile_display_add'),
+('bx_course', 'bx_course_delete', 'bx_courses', 0, '_bx_courses_form_profile_display_delete'),
+('bx_course', 'bx_course_edit', 'bx_courses', 0, '_bx_courses_form_profile_display_edit'),
+('bx_course', 'bx_course_edit_cover', 'bx_courses', 0, '_bx_courses_form_profile_display_edit_cover'),
+('bx_course', 'bx_course_view', 'bx_courses', 1, '_bx_courses_form_profile_display_view'),
+('bx_course', 'bx_course_view_full', 'bx_courses', 1, '_bx_courses_form_profile_display_view_full'),
+('bx_course', 'bx_course_invite', 'bx_courses', 0, '_bx_courses_form_profile_display_invite');
+
+INSERT INTO `sys_form_inputs`(`object`, `module`, `name`, `value`, `values`, `checked`, `type`, `caption_system`, `caption`, `info`, `required`, `collapsed`, `html`, `attrs`, `attrs_tr`, `attrs_wrapper`, `checker_func`, `checker_params`, `checker_error`, `db_pass`, `db_params`, `editable`, `deletable`) VALUES 
+('bx_course', 'bx_courses', 'allow_view_to', 3, '', 0, 'custom', '_bx_courses_form_profile_input_sys_allow_view_to', '_bx_courses_form_profile_input_allow_view_to', '_bx_courses_form_profile_input_allow_view_to_desc', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_course', 'bx_courses', 'allow_post_to', 3, '', 0, 'custom', '_bx_courses_form_profile_input_sys_allow_post_to', '_bx_courses_form_profile_input_allow_post_to', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_course', 'bx_courses', 'delete_confirm', 1, '', 0, 'checkbox', '_bx_courses_form_profile_input_sys_delete_confirm', '_bx_courses_form_profile_input_delete_confirm', '_bx_courses_form_profile_input_delete_confirm_info', 1, 0, 0, '', '', '', 'avail', '', '_bx_courses_form_profile_input_delete_confirm_error', '', '', 1, 0),
+('bx_course', 'bx_courses', 'do_submit', '_sys_form_account_input_submit', '', 0, 'submit', '_bx_courses_form_profile_input_sys_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_course', 'bx_courses', 'desc', '', '', 0, 'textarea', '_bx_courses_form_profile_input_sys_desc', '_bx_courses_form_profile_input_desc', '', 0, 0, 2, '', '', '', '', '', '', 'XssHtml', '', 1, 1),
+('bx_course', 'bx_courses', 'cat', '', '#!bx_courses_cats', 0, 'select', '_bx_courses_form_profile_input_sys_cat', '_bx_courses_form_profile_input_cat', '', 1, 0, 0, '', '', '', 'avail', '', '_bx_courses_form_profile_input_cat_err', 'Xss', '', 1, 1),
+('bx_course', 'bx_courses', 'name', '', '', 0, 'text', '_bx_courses_form_profile_input_sys_name', '_bx_courses_form_profile_input_name', '', 1, 0, 0, '', '', '', 'avail', '', '_bx_courses_form_profile_input_name_err', 'Xss', '', 1, 0),
+('bx_course', 'bx_courses', 'initial_members', '', '', 0, 'custom', '_bx_courses_form_profile_input_sys_initial_members', '_bx_courses_form_profile_input_initial_members', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 1),
+('bx_course', 'bx_courses', 'join_confirmation', 1, '', 1, 'switcher', '_bx_courses_form_profile_input_sys_join_confirm', '_bx_courses_form_profile_input_join_confirm', '', 0, 0, 0, '', '', '', '', '', '', 'Xss', '', 1, 0),
+('bx_course', 'bx_courses', 'cover', 'a:1:{i:0;s:21:"bx_courses_cover_crop";}', 'a:1:{s:21:"bx_courses_cover_crop";s:24:"_sys_uploader_crop_title";}', 0, 'files', '_bx_courses_form_profile_input_sys_cover', '_bx_courses_form_profile_input_cover', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_course', 'bx_courses', 'picture', 'a:1:{i:0;s:23:"bx_courses_picture_crop";}', 'a:1:{s:23:"bx_courses_picture_crop";s:24:"_sys_uploader_crop_title";}', 0, 'files', '_bx_courses_form_profile_input_sys_picture', '_bx_courses_form_profile_input_picture', '', 0, 0, 0, '', '', '', '', '', '_bx_courses_form_profile_input_picture_err', '', '', 1, 0),
+('bx_course', 'bx_courses', 'location', '', '', 0, 'location', '_sys_form_input_sys_location', '_sys_form_input_location', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_course', 'bx_courses', 'labels', '', '', 0, 'custom', '_sys_form_input_sys_labels', '_sys_form_input_labels', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0);
+
+INSERT INTO `sys_form_display_inputs`(`display_name`, `input_name`, `visible_for_levels`, `active`, `order`) VALUES 
+('bx_course_add', 'initial_members', 2147483647, 1, 1),
+('bx_course_add', 'name', 2147483647, 1, 2),
+('bx_course_add', 'cat', 2147483647, 1, 3),
+('bx_course_add', 'desc', 2147483647, 1, 4),
+('bx_course_add', 'location', 2147483647, 1, 5),
+('bx_course_add', 'join_confirmation', 2147483647, 1, 6),
+('bx_course_add', 'allow_view_to', 2147483647, 1, 7),
+('bx_course_add', 'allow_post_to', 2147483647, 1, 8),
+('bx_course_add', 'do_submit', 2147483647, 1, 9),
+
+('bx_course_invite', 'initial_members', 2147483647, 1, 1),
+('bx_course_invite', 'do_submit', 2147483647, 1, 2),
+
+('bx_course_delete', 'delete_confirm', 2147483647, 1, 1),
+('bx_course_delete', 'do_submit', 2147483647, 1, 2),
+
+('bx_course_edit', 'name', 2147483647, 1, 1),
+('bx_course_edit', 'cat', 2147483647, 1, 2),
+('bx_course_edit', 'desc', 2147483647, 1, 3),
+('bx_course_edit', 'location', 2147483647, 1, 4),
+('bx_course_edit', 'join_confirmation', 2147483647, 1, 5),
+('bx_course_edit', 'allow_view_to', 2147483647, 1, 6),
+('bx_course_edit', 'allow_post_to', 2147483647, 1, 7),
+('bx_course_edit', 'do_submit', 2147483647, 1, 8),
+
+('bx_course_edit_cover', 'cover', 2147483647, 1, 1),
+('bx_course_edit_cover', 'do_submit', 2147483647, 1, 2),
+
+('bx_course_view', 'name', 2147483647, 1, 1),
+('bx_course_view', 'cat', 2147483647, 1, 2),
+
+('bx_course_view_full', 'name', 2147483647, 1, 1),
+('bx_course_view_full', 'cat', 2147483647, 1, 2),
+('bx_course_view_full', 'desc', 2147483647, 1, 3);
+
+-- FORMS: Price
+INSERT INTO `sys_objects_form` (`object`, `module`, `title`, `action`, `form_attrs`, `submit_name`, `table`, `key`, `uri`, `uri_title`, `params`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES
+('bx_courses_price', 'bx_courses', '_bx_courses_form_price', '', '', 'do_submit', 'bx_courses_prices', 'id', '', '', '', 0, 1, 'BxCoursesFormPrice', 'modules/boonex/courses/classes/BxCoursesFormPrice.php');
+
+INSERT INTO `sys_form_displays` (`display_name`, `module`, `object`, `title`, `view_mode`) VALUES
+('bx_courses_price_add', 'bx_courses', 'bx_courses_price', '_bx_courses_form_price_display_add', 0),
+('bx_courses_price_edit', 'bx_courses', 'bx_courses_price', '_bx_courses_form_price_display_edit', 0);
+
+INSERT INTO `sys_form_inputs` (`object`, `module`, `name`, `value`, `values`, `checked`, `type`, `caption_system`, `caption`, `info`, `required`, `collapsed`, `html`, `attrs`, `attrs_tr`, `attrs_wrapper`, `checker_func`, `checker_params`, `checker_error`, `db_pass`, `db_params`, `editable`, `deletable`) VALUES
+('bx_courses_price', 'bx_courses', 'id', '', '', 0, 'hidden', '_bx_courses_form_price_input_sys_id', '', '', 1, 0, 0, '', '', '', '', '', '', 'Int', '', 1, 0),
+('bx_courses_price', 'bx_courses', 'role_id', '', '', 0, 'hidden', '_bx_courses_form_price_input_sys_role_id', '', '', 1, 0, 0, '', '', '', '', '', '', 'Int', '', 1, 0),
+('bx_courses_price', 'bx_courses', 'name', '', '', 0, 'text', '_bx_courses_form_price_input_sys_name', '_bx_courses_form_price_input_name', '_bx_courses_form_price_input_inf_name', 1, 0, 0, '', '', '', 'Avail', '', '_bx_courses_form_price_input_err_name', 'Xss', '', 1, 0),
+('bx_courses_price', 'bx_courses', 'period', '', '', 0, 'text', '_bx_courses_form_price_input_sys_period', '_bx_courses_form_price_input_period', '_bx_courses_form_price_input_inf_period', 1, 0, 0, '', '', '', '', '', '', 'Int', '', 1, 0),
+('bx_courses_price', 'bx_courses', 'period_unit', '', '#!bx_courses_period_units', 0, 'select', '_bx_courses_form_price_input_sys_period_unit', '_bx_courses_form_price_input_period_unit', '_bx_courses_form_price_input_inf_period_unit', 1, 0, 0, '', '', '', '', '', '', 'Xss', '', 1, 0),
+('bx_courses_price', 'bx_courses', 'price', '', '', 0, 'text', '_bx_courses_form_price_input_sys_price', '_bx_courses_form_price_input_price', '_bx_courses_form_price_input_inf_price', 1, 0, 0, '', '', '', '', '', '', 'Float', '', 1, 0),
+('bx_courses_price', 'bx_courses', 'controls', '', 'do_submit,do_cancel', 0, 'input_set', '', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_courses_price', 'bx_courses', 'do_submit', '_bx_courses_form_price_input_do_submit', '', 0, 'submit', '_bx_courses_form_price_input_sys_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_courses_price', 'bx_courses', 'do_cancel', '_bx_courses_form_price_input_do_cancel', '', 0, 'button', '_bx_courses_form_price_input_sys_do_cancel', '', '', 0, 0, 0, 'a:2:{s:7:"onclick";s:45:"$(''.bx-popup-applied:visible'').dolPopupHide()";s:5:"class";s:22:"bx-def-margin-sec-left";}', '', '', '', '', '', '', '', 1, 0);
+
+INSERT INTO `sys_form_display_inputs` (`display_name`, `input_name`, `visible_for_levels`, `active`, `order`) VALUES
+('bx_courses_price_add', 'id', 2147483647, 0, 1),
+('bx_courses_price_add', 'role_id', 2147483647, 1, 2),
+('bx_courses_price_add', 'name', 2147483647, 1, 3),
+('bx_courses_price_add', 'price', 2147483647, 1, 4),
+('bx_courses_price_add', 'period', 2147483647, 1, 5),
+('bx_courses_price_add', 'period_unit', 2147483647, 1, 6),
+('bx_courses_price_add', 'controls', 2147483647, 1, 7),
+('bx_courses_price_add', 'do_submit', 2147483647, 1, 8),
+('bx_courses_price_add', 'do_cancel', 2147483647, 1, 9),
+
+('bx_courses_price_edit', 'id', 2147483647, 1, 1),
+('bx_courses_price_edit', 'role_id', 2147483647, 1, 2),
+('bx_courses_price_edit', 'name', 2147483647, 1, 3),
+('bx_courses_price_edit', 'price', 2147483647, 1, 4),
+('bx_courses_price_edit', 'period', 2147483647, 1, 5),
+('bx_courses_price_edit', 'period_unit', 2147483647, 1, 6),
+('bx_courses_price_edit', 'controls', 2147483647, 1, 7),
+('bx_courses_price_edit', 'do_submit', 2147483647, 1, 8),
+('bx_courses_price_edit', 'do_cancel', 2147483647, 1, 9);
+
+-- PRE-VALUES
+INSERT INTO `sys_form_pre_lists`(`key`, `title`, `module`, `use_for_sets`) VALUES
+('bx_courses_cats', '_bx_courses_pre_lists_cats', 'bx_courses', '0');
+
+INSERT INTO `sys_form_pre_values`(`Key`, `Value`, `Order`, `LKey`, `LKey2`) VALUES
+('bx_courses_cats', '', 0, '_sys_please_select', ''),
+('bx_courses_cats', '1', 1, '_bx_courses_cat_General', '');
+
+INSERT INTO `sys_form_pre_lists`(`key`, `title`, `module`, `use_for_sets`) VALUES
+('bx_courses_roles', '_bx_courses_pre_lists_roles', 'bx_courses', '1');
+
+INSERT INTO `sys_form_pre_values`(`Key`, `Value`, `Order`, `LKey`, `LKey2`) VALUES
+('bx_courses_roles', '0', 1, '_bx_courses_role_regular', ''),
+('bx_courses_roles', '1', 2, '_bx_courses_role_administrator', ''),
+('bx_courses_roles', '2', 3, '_bx_courses_role_moderator', '');
+
+INSERT INTO `sys_form_pre_lists`(`key`, `title`, `module`, `use_for_sets`) VALUES
+('bx_courses_period_units', '_bx_courses_pre_lists_period_units', 'bx_courses', '0');
+
+INSERT INTO `sys_form_pre_values`(`Key`, `Value`, `Order`, `LKey`, `LKey2`) VALUES
+('bx_courses_period_units', '', 0, '_sys_please_select', ''),
+('bx_courses_period_units', 'day', 1, '_bx_courses_period_unit_day', ''),
+('bx_courses_period_units', 'week', 2, '_bx_courses_period_unit_week', ''),
+('bx_courses_period_units', 'month', 3, '_bx_courses_period_unit_month', ''),
+('bx_courses_period_units', 'year', 4, '_bx_courses_period_unit_year', '');
+
+-- COMMENTS
+INSERT INTO `sys_objects_cmts` (`Name`, `Module`, `Table`, `CharsPostMin`, `CharsPostMax`, `CharsDisplayMax`, `Html`, `PerView`, `PerViewReplies`, `BrowseType`, `IsBrowseSwitch`, `PostFormPosition`, `NumberOfLevels`, `IsDisplaySwitch`, `IsRatable`, `ViewingThreshold`, `IsOn`, `RootStylePrefix`, `BaseUrl`, `ObjectVote`, `TriggerTable`, `TriggerFieldId`, `TriggerFieldAuthor`, `TriggerFieldTitle`, `TriggerFieldComments`, `ClassName`, `ClassFile`) VALUES
+('bx_courses', 'bx_courses', 'bx_courses_cmts', 1, 5000, 1000, 3, 5, 3, 'tail', 1, 'bottom', 1, 1, 1, -3, 1, 'cmt', 'page.php?i=view-course-profile&id={object_id}', '', 'bx_courses_data', 'id', 'author', 'name', 'comments', 'BxCoursesCmts', 'modules/boonex/courses/classes/BxCoursesCmts.php');
+
+-- VIEWS
+INSERT INTO `sys_objects_view` (`name`, `table_track`, `period`, `is_on`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_count`, `class_name`, `class_file`) VALUES 
+('bx_courses', 'bx_courses_views_track', '86400', '1', 'bx_courses_data', 'id', 'author', 'views', '', '');
+
+-- VOTES
+INSERT INTO `sys_objects_vote` (`Name`, `TableMain`, `TableTrack`, `PostTimeout`, `MinValue`, `MaxValue`, `IsUndo`, `IsOn`, `TriggerTable`, `TriggerFieldId`, `TriggerFieldAuthor`, `TriggerFieldRate`, `TriggerFieldRateCount`, `ClassName`, `ClassFile`) VALUES 
+('bx_courses', 'bx_courses_votes', 'bx_courses_votes_track', '604800', '1', '1', '0', '1', 'bx_courses_data', 'id', 'author', 'rate', 'votes', '', '');
+
+-- SCORES
+INSERT INTO `sys_objects_score` (`name`, `module`, `table_main`, `table_track`, `post_timeout`, `is_on`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_score`, `trigger_field_cup`, `trigger_field_cdown`, `class_name`, `class_file`) VALUES 
+('bx_courses', 'bx_courses', 'bx_courses_scores', 'bx_courses_scores_track', '604800', '0', 'bx_courses_data', 'id', 'author', 'score', 'sc_up', 'sc_down', '', '');
+
+-- REPORTS
+INSERT INTO `sys_objects_report` (`name`, `module`, `table_main`, `table_track`, `is_on`, `base_url`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_count`, `class_name`, `class_file`) VALUES 
+('bx_courses', 'bx_courses', 'bx_courses_reports', 'bx_courses_reports_track', '1', 'page.php?i=view-course-profile&id={object_id}', 'bx_courses_data', 'id', 'author', 'reports', '', '');
+
+-- FAFORITES
+INSERT INTO `sys_objects_favorite` (`name`, `table_track`, `table_lists`, `is_on`, `is_undo`, `is_public`, `base_url`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_count`, `class_name`, `class_file`) VALUES 
+('bx_courses', 'bx_courses_favorites_track', 'bx_courses_favorites_lists', '1', '1', '1', 'page.php?i=view-course-profile&id={object_id}', 'bx_courses_data', 'id', 'author', 'favorites', '', '');
+
+-- FEATURED
+INSERT INTO `sys_objects_feature` (`name`, `module`, `is_on`, `is_undo`, `base_url`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_flag`, `class_name`, `class_file`) VALUES 
+('bx_courses', 'bx_courses', '1', '1', 'page.php?i=view-course-profile&id={object_id}', 'bx_courses_data', 'id', 'author', 'featured', '', '');
+
+-- CONTENT INFO
+INSERT INTO `sys_objects_content_info` (`name`, `title`, `alert_unit`, `alert_action_add`, `alert_action_update`, `alert_action_delete`, `class_name`, `class_file`) VALUES
+('bx_courses', '_bx_courses', 'bx_courses', 'added', 'edited', 'deleted', '', ''),
+('bx_courses_cmts', '_bx_courses_cmts', 'bx_courses', 'commentPost', 'commentUpdated', 'commentRemoved', 'BxDolContentInfoCmts', '');
+
+INSERT INTO `sys_content_info_grids` (`object`, `grid_object`, `grid_field_id`, `condition`, `selection`) VALUES
+('bx_courses', 'bx_courses_administration', 'td`.`id', '', ''),
+('bx_courses', 'bx_courses_common', 'td`.`id', '', '');
+
+-- SEARCH EXTENDED
+INSERT INTO `sys_objects_search_extended` (`object`, `object_content_info`, `module`, `title`, `active`, `class_name`, `class_file`) VALUES
+('bx_courses', 'bx_courses', 'bx_courses', '_bx_courses_search_extended', 1, '', ''),
+('bx_courses_cmts', 'bx_courses_cmts', 'bx_courses', '_bx_courses_search_extended_cmts', 1, 'BxTemplSearchExtendedCmts', '');
+
+-- STUDIO PAGE & WIDGET
+INSERT INTO `sys_std_pages`(`index`, `name`, `header`, `caption`, `icon`) VALUES
+(3, 'bx_courses', '_bx_courses', '_bx_courses', 'bx_courses@modules/boonex/courses/|std-icon.svg');
+SET @iPageId = LAST_INSERT_ID();
+
+SET @iParentPageId = (SELECT `id` FROM `sys_std_pages` WHERE `name` = 'home');
+SET @iParentPageOrder = (SELECT MAX(`order`) FROM `sys_std_pages_widgets` WHERE `page_id` = @iParentPageId);
+INSERT INTO `sys_std_widgets` (`page_id`, `module`, `type`, `url`, `click`, `icon`, `caption`, `cnt_notices`, `cnt_actions`) VALUES
+(@iPageId, 'bx_courses', 'content', '{url_studio}module.php?name=bx_courses', '', 'bx_courses@modules/boonex/courses/|std-icon.svg', '_bx_courses', '', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:11:"get_actions";s:6:"params";a:0:{}s:5:"class";s:18:"TemplStudioModules";}');
+INSERT INTO `sys_std_pages_widgets` (`page_id`, `widget_id`, `order`) VALUES
+(@iParentPageId, LAST_INSERT_ID(), IF(ISNULL(@iParentPageOrder), 1, @iParentPageOrder + 1));
+

+ 64 - 0
modules/boonex/courses/updates/12.0.0_12.0.1/source/install/sql/uninstall.sql

@@ -0,0 +1,64 @@
+
+-- TABLES
+
+DROP TABLE IF EXISTS `bx_courses_data`, `bx_courses_pics`, `bx_courses_pics_resized`, `bx_courses_cmts`, `bx_courses_views_track`, `bx_courses_meta_keywords`, `bx_courses_meta_locations`, `bx_courses_meta_mentions`, `bx_courses_fans`, `bx_courses_admins`, `bx_courses_votes`, `bx_courses_votes_track`, `bx_courses_reports`, `bx_courses_reports_track`, `bx_courses_favorites_track`, `bx_courses_favorites_lists`, `bx_courses_scores`, `bx_courses_scores_track`, `bx_courses_invites`, `bx_courses_prices`;
+
+-- PROFILES
+
+DELETE FROM sys_profiles WHERE `type` = 'bx_courses';
+
+-- STORAGES & TRANSCODERS
+
+DELETE FROM `sys_objects_storage` WHERE `object` IN('bx_courses_pics', 'bx_courses_pics_resized');
+DELETE FROM `sys_storage_tokens` WHERE `object` IN('bx_courses_pics', 'bx_courses_pics_resized');
+
+DELETE FROM `sys_objects_transcoder` WHERE `object` IN('bx_courses_icon', 'bx_courses_thumb', 'bx_courses_avatar', 'bx_courses_avatar_big', 'bx_courses_picture', 'bx_courses_cover', 'bx_courses_cover_thumb', 'bx_courses_gallery');
+DELETE FROM `sys_transcoder_filters` WHERE `transcoder_object` IN('bx_courses_icon', 'bx_courses_thumb', 'bx_courses_avatar', 'bx_courses_avatar_big', 'bx_courses_picture', 'bx_courses_cover', 'bx_courses_cover_thumb', 'bx_courses_gallery');
+DELETE FROM `sys_transcoder_images_files` WHERE `transcoder_object` IN('bx_courses_icon', 'bx_courses_thumb', 'bx_courses_avatar', 'bx_courses_avatar_big', 'bx_courses_picture', 'bx_courses_cover', 'bx_courses_cover_thumb', 'bx_courses_gallery');
+
+-- FORMS
+
+DELETE FROM `sys_objects_form` WHERE `module` = 'bx_courses';
+DELETE FROM `sys_form_displays` WHERE `module` = 'bx_courses';
+DELETE FROM `sys_form_inputs` WHERE `module` = 'bx_courses';
+DELETE FROM `sys_form_display_inputs` WHERE `display_name` IN('bx_course_add', 'bx_course_delete', 'bx_course_edit', 'bx_course_edit_cover', 'bx_course_view', 'bx_course_view_full', 'bx_course_invite', 'bx_courses_price_add', 'bx_courses_price_edit');
+
+-- PRE-VALUES
+
+DELETE FROM `sys_form_pre_lists` WHERE `module` = 'bx_courses';
+
+DELETE FROM `sys_form_pre_values` WHERE `Key` LIKE 'bx_courses%';
+
+-- COMMENTS
+DELETE FROM `sys_objects_cmts` WHERE `Name` = 'bx_courses';
+
+-- VIEWS
+DELETE FROM `sys_objects_view` WHERE `name` = 'bx_courses';
+
+-- VOTES
+DELETE FROM `sys_objects_vote` WHERE `Name` = 'bx_courses';
+
+-- SCORES
+DELETE FROM `sys_objects_score` WHERE `name` = 'bx_courses';
+
+-- REPORTS
+DELETE FROM `sys_objects_report` WHERE `name` = 'bx_courses';
+
+-- FAFORITES
+DELETE FROM `sys_objects_favorite` WHERE `name` = 'bx_courses';
+
+-- FEATURED
+DELETE FROM `sys_objects_feature` WHERE `name` = 'bx_courses';
+
+-- CONTENT INFO
+DELETE FROM `sys_objects_content_info` WHERE `name` IN ('bx_courses', 'bx_courses_cmts');
+
+DELETE FROM `sys_content_info_grids` WHERE `object` IN ('bx_courses');
+
+-- SEARCH EXTENDED
+DELETE FROM `sys_objects_search_extended` WHERE `module` = 'bx_courses';
+
+-- STUDIO PAGE & WIDGET
+DELETE FROM `tp`, `tw`, `twb`, `tpw` 
+USING `sys_std_pages` AS `tp` LEFT JOIN `sys_std_widgets` AS `tw` ON `tp`.`id` = `tw`.`page_id` LEFT JOIN `sys_std_widgets_bookmarks` AS `twb` ON `tw`.`id` = `twb`.`widget_id` LEFT JOIN `sys_std_pages_widgets` AS `tpw` ON `tw`.`id` = `tpw`.`widget_id`
+WHERE  `tp`.`name` = 'bx_courses';

+ 59 - 0
modules/boonex/courses/updates/12.0.0_12.0.1/source/js/prices.js

@@ -0,0 +1,59 @@
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Courses Courses
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+
+function BxCoursesPrices(oOptions) {
+    this._sActionsUri = oOptions.sActionUri;
+    this._sActionsUrl = oOptions.sActionUrl;
+    this._sObjNameGrid = oOptions.sObjNameGrid;
+    this._sObjName = oOptions.sObjName == undefined ? 'oBxCoursesPrices' : oOptions.sObjName;
+    this._aHtmlIds = oOptions.aHtmlIds == undefined ? {} : oOptions.aHtmlIds;
+    this._oRequestParams = oOptions.oRequestParams == undefined ? {} : oOptions.oRequestParams;
+}
+
+BxCoursesPrices.prototype.checkName = function(sNameId, iId) {
+    var oDate = new Date();
+
+    var oName = jQuery("[name='" + sNameId + "']");
+    var sName = oName.val();
+
+    if(!sName.length)
+        return;
+
+    jQuery.get(
+        this._sActionsUrl + 'check_name',
+        {
+            name: sName,
+            id: iId && parseInt(iId) > 0 ? iId : 0,
+            _t: oDate.getTime()
+        },
+        function(oData) {
+            if(!oData || oData.name == undefined)
+                return;
+
+            oName.val(oData.name);
+        },
+        'json'
+    );
+};
+
+BxCoursesPrices.prototype.onChangeRole = function() {
+	this.reloadGrid($('#bx-grid-level-' + this._sObjNameGrid).val());
+};
+
+BxCoursesPrices.prototype.reloadGrid = function(iRoleId) {
+    if(glGrids[this._sObjNameGrid]._oQueryAppend['role_id'] == iRoleId)
+        return;
+
+    glGrids[this._sObjNameGrid]._oQueryAppend['role_id'] = iRoleId;
+    glGrids[this._sObjNameGrid].reload(0);
+};
+
+/** @} */

+ 1 - 0
modules/boonex/courses/updates/12.0.0_12.0.1/source/template/css/prices.css

@@ -0,0 +1 @@
+@import url(../../../../base/groups/template/css/prices.css);

+ 1 - 0
modules/boonex/courses/updates/12.0.0_12.0.1/source/template/favorite-list-info.html

@@ -0,0 +1 @@
+<bx_include_base:../modules/base/general/template/favorite-list-info.html />

+ 1 - 0
modules/boonex/courses/updates/12.0.0_12.0.1/source/template/favorite-lists.html

@@ -0,0 +1 @@
+<bx_include_base:../modules/base/general/template/favorite-lists.html />

+ 1 - 0
modules/boonex/courses/updates/12.0.0_12.0.1/source/template/popup_price.html

@@ -0,0 +1 @@
+<bx_include_base:../modules/base/groups/template/popup_price.html />

+ 51 - 0
modules/boonex/credits/updates/12.0.0_12.0.1/install/config.php

@@ -0,0 +1,51 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'title' => 'Credits',
+    'version_from' => '12.0.0',
+    'version_to' => '12.0.1',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '12.1.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/credits/updates/update_12.0.0_12.0.1/',
+    'home_uri' => 'credits_update_1200_1201',
+
+    'module_dir' => 'boonex/credits/',
+    'module_uri' => 'credits',
+
+    'db_prefix' => 'bx_credits_',
+    'class_prefix' => 'BxCredits',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 0,
+        'update_files' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 0,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Credits',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

+ 13 - 0
modules/boonex/credits/updates/12.0.0_12.0.1/install/installer.php

@@ -0,0 +1,13 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+class BxCreditsUpdater extends BxDolStudioUpdater
+{
+    function __construct($aConfig)
+    {
+        parent::__construct($aConfig);
+    }
+}

+ 13 - 0
modules/boonex/credits/updates/12.0.0_12.0.1/install/langs/en.xml

@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources name="en" flag="gb" title="English">
+	<string_add name="_bx_credits_form_credit_input_message_inf_g"><![CDATA[]]></string_add>
+    <string_add name="_bx_credits_form_credit_input_message_inf_wr"><![CDATA[Payment instructions and other notes]]></string_add>
+    <string_add name="_bx_credits_form_credit_input_message_inf_wc"><![CDATA[Payment confirmation and other notes]]></string_add>
+
+	<string_upd name="_bx_credits_et_txt_body_withdraw_requested"><![CDATA[{email_header}
+<p><a href="{profile_link}">{profile_name}</a> requested to withdraw <b>{amount}</b> credits from his/her balance.</p>
+<p>Current withdraw conversion rate is <b>{rate}</b></p>
+<p>Withdrawal can be confirmed <a href="{confirm_url}">here</a>.</p>
+<p>Notes from <b>{profile_name}</b>:<br />{message}</p>
+{email_footer}]]></string_upd>
+</resources>

+ 267 - 0
modules/boonex/credits/updates/12.0.0_12.0.1/source/classes/BxCreditsConfig.php

@@ -0,0 +1,267 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Credits Credits
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxCreditsConfig extends BxBaseModGeneralConfig
+{
+    protected $_iAuthor;
+    protected $_aCurrency;
+
+    protected $_sCheckoutSessionKey;
+
+    function __construct($aModule)
+    {
+        parent::__construct($aModule);
+
+        $this->CNF = array (
+
+            // module icon
+            'ICON' => 'copyright col-green3',
+
+            // database tables
+            'TABLE_BUNDLES' => $aModule['db_prefix'] . 'bundles',
+            'TABLE_ORDERS' => $aModule['db_prefix'] . 'orders',
+            'TABLE_ORDERS_DELETED' => $aModule['db_prefix'] . 'orders_deleted',
+            'TABLE_PROFILES' => $aModule['db_prefix'] . 'profiles',
+            'TABLE_HISTORY' => $aModule['db_prefix'] . 'history',
+
+            // database fields
+            'FIELD_ID' => 'id',
+            'FIELD_AUTHOR' => '',
+            'FIELD_ADDED' => 'added',
+            'FIELD_CHANGED' => '',
+            'FIELD_NAME' => 'name',
+            'FIELD_TITLE' => 'title',
+            'FIELD_AMOUNT' => 'amount',
+            'FIELD_BONUS' => 'bonus',
+            'FIELD_PRICE' => 'price',
+            'FIELD_STATUS' => 'active',
+
+            'FIELD_C_MESSAGE' => 'message',
+
+            // page URIs
+            'URI_HOME' => 'credits-home',
+            'URL_HOME' => 'page.php?i=credits-home',
+            'URL_CHECKOUT' => 'page.php?i=credits-checkout',
+            'URL_ORDERS_COMMON' => 'page.php?i=credits-orders',
+            'URL_ORDERS_ADMINISTRATION' => 'page.php?i=credits-orders-administration',
+            'URL_HISTORY_COMMON' => 'page.php?i=credits-history-common',
+            'URL_HISTORY_ADMINISTRATION' => 'page.php?i=credits-history-administration',
+
+            // some params
+            'PARAM_WITHDRAW' => 'bx_credits_enable_withdraw',
+            'PARAM_WITHDRAW_EMAIL' => 'bx_credits_withdraw_email',
+            'PARAM_PRECISION' => 'bx_credits_precision',
+            'PARAM_CR_USE' => 'bx_credits_conversion_rate_use',
+            'PARAM_CR_WITHDRAW' => 'bx_credits_conversion_rate_withdraw',
+            'PARAM_PROVIDER_NAME' => 'credits',
+            'PARAM_PROVIDER_ENABLE' => 'bx_credits_enable_provider',
+            'PARAM_CODE' => 'bx_credits_code',
+            'PARAM_ICON' => 'bx_credits_icon',
+
+            // objects
+            'OBJECT_FORM_CREDIT' => 'bx_credits_credit',
+            'OBJECT_FORM_CREDIT_DISPLAY_GRANT' => 'bx_credits_credit_grant',
+            'OBJECT_FORM_CREDIT_DISPLAY_WITHDRAW_REQUEST' => 'bx_credits_credit_withdraw_request',
+            'OBJECT_FORM_CREDIT_DISPLAY_WITHDRAW_CONFIRM' => 'bx_credits_credit_withdraw_confirm',
+            'OBJECT_FORM_BUNDLE' => 'bx_credits_bundle',
+            'OBJECT_FORM_BUNDLE_DISPLAY_ADD' => 'bx_credits_bundle_add',
+            'OBJECT_FORM_BUNDLE_DISPLAY_EDIT' => 'bx_credits_bundle_edit',
+            'OBJECT_MENU_SUBMENU' => 'bx_credits_submenu', 
+            'OBJECT_MENU_MANAGE_SUBMENU' => 'bx_credits_manage_submenu',
+            'OBJECT_GRID_BUNDLES' => 'bx_credits_bundles',
+            'OBJECT_GRID_ORDERS_ADMINISTRATION' => 'bx_credits_orders_administration',
+            'OBJECT_GRID_ORDERS_COMMON' => 'bx_credits_orders_common',
+            'OBJECT_GRID_HISTORY_ADMINISTRATION' => 'bx_credits_history_administration',
+            'OBJECT_GRID_HISTORY_COMMON' => 'bx_credits_history_common',
+
+            // email templates
+            'ETEMPLATE_GRANTED' => 'bx_credits_granted',
+            'ETEMPLATE_PURCHASED' => 'bx_credits_purchased',
+            'ETEMPLATE_IN' => 'bx_credits_in',
+            'ETEMPLATE_OUT' => 'bx_credits_out',
+            'ETEMPLATE_WITHDRAW_REQUESTED' => 'bx_credits_withdraw_requested',
+            'ETEMPLATE_WITHDRAW_SENT' => 'bx_credits_withdraw_sent',
+
+            // some language keys
+            'T' => array (
+                'txt_sample_single' => '_bx_credits_txt_sample_single',
+                'grant_popup' => '_bx_credits_grid_popup_title_htr_grant',
+                'withdraw_request_popup' => '_bx_credits_grid_popup_title_htr_withdraw_request',
+                'withdraw_confirm_popup' => '_bx_credits_grid_popup_title_htr_withdraw_confirm',
+            ),
+        );
+
+        $this->_aJsClasses = array_merge($this->_aJsClasses, array(
+            'studio' => 'BxCreditsStudio',
+            'checkout' => 'BxCreditsCheckout',
+            'subscribe' => 'BxCreditsSubscribe',
+            'withdraw' => 'BxCreditsWithdraw',
+        ));
+
+        $this->_aJsObjects = array_merge($this->_aJsObjects, array(
+            'studio' => 'oBxCreditsStudio',
+            'checkout' => 'oBxCreditsCheckout',
+            'subscribe' => 'oBxCreditsSubscribe',
+            'withdraw' => 'oBxCreditsWithdraw',
+        ));
+
+        $sPrefix = str_replace('_', '-', $this->_sName);
+        $this->_aHtmlIds = array(
+            'add_bundle_popup' =>  $sPrefix . '-add-bundle-popup',
+            'edit_bundle_popup' =>  $sPrefix . '-edit-bundle-popup',
+
+            'grant_popup' =>  $sPrefix . '-grant-popup',
+            'withdraw_request_popup' =>  $sPrefix . '-withdraw-request-popup',
+            'withdraw_confirm_popup' =>  $sPrefix . '-withdraw-confirm-popup',
+            'withdraw_field_rate' => $sPrefix . '-wff-rate',
+            'withdraw_field_amount' => $sPrefix . '-wff-amount',
+            'withdraw_field_result' => $sPrefix . '-wff-result',
+
+            'subscribe_popup' =>  $sPrefix . '-subscribe-popup',
+        );
+
+        $this->_aPrefixes = array(
+            'style' => 'bx-credits',
+        );
+
+        $oPayments = BxDolPayments::getInstance();
+        $this->_iAuthor = (int)$oPayments->getOption('site_admin');
+        $this->_aCurrency = array(
+            'code' => $oPayments->getOption('default_currency_code'),
+            'sign' => $oPayments->getOption('default_currency_sign')
+        );
+        
+        $this->_sCheckoutSessionKey = $this->_sName . '_checkout';
+    }
+
+    public function getHtmlIds($sKey = '')
+    {
+        if(empty($sKey))
+            return $this->_aHtmlIds;
+
+        return isset($this->_aHtmlIds[$sKey]) ? $this->_aHtmlIds[$sKey] : '';
+    }
+
+    public function getAuthor()
+    {
+    	return $this->_iAuthor;
+    }
+
+    public function getCurrency()
+    {
+    	return $this->_aCurrency;
+    }
+
+    public function isWithdraw()
+    {
+        return getParam($this->CNF['PARAM_WITHDRAW']) == 'on';
+    }
+
+    public function getWithdrawEmail()
+    {
+        $sEmail = getParam($this->CNF['PARAM_WITHDRAW_EMAIL']);
+        if(empty($sEmail))
+            $sEmail = getParam('site_email');
+
+        return $sEmail;
+    }
+
+    public function getPrecision()
+    {
+        return (int)getParam($this->CNF['PARAM_PRECISION']);
+    }
+
+    public function getConversionRateUse()
+    {
+        return $this->_getConversionRate('use');
+    }
+
+    public function getConversionRateWithdraw()
+    {
+        return $this->_getConversionRate('withdraw');
+    }
+
+    public function getCheckoutUrl()
+    {
+        return BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink($this->CNF['URL_CHECKOUT']);
+    }
+
+    public function getBundleUrl($aBundle)
+    {
+        return BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink($this->CNF['URL_HOME']);
+    }
+
+    public function getBundleName($sName)
+    {
+        return uriGenerate($sName, $this->CNF['TABLE_BUNDLES'], $this->CNF['FIELD_NAME'], 'cat', '_');
+    }
+
+    public function getBundleDescription($aBundle)
+    {
+        if(empty($aBundle[$this->CNF['FIELD_BONUS']]))
+            return $aBundle[$this->CNF['FIELD_AMOUNT']];
+
+        return _t('_bx_credits_txt_n_plus_m_for_free', $aBundle[$this->CNF['FIELD_AMOUNT']], $aBundle[$this->CNF['FIELD_BONUS']]);
+    }
+
+    public function getCheckoutData()
+    {
+        return BxDolSession::getInstance()->getUnsetValue($this->_sCheckoutSessionKey);
+    }
+
+    public function setCheckoutData($aData)
+    {
+        return BxDolSession::getInstance()->setValue($this->_sCheckoutSessionKey, $aData);
+    }
+
+    public function getOrder($iLength = 16)
+    {
+        return genRndPwd($iLength, false);
+    }
+
+    /**
+     * Convert Credits to Money
+     */
+    public function convertC2M($fCredits, $fRate = false, $iPrecision = false)
+    {
+        if($fRate === false)
+            $fRate = $this->getConversionRateUse();
+        if($iPrecision === false)
+            $iPrecision = $this->getPrecision();
+
+        return round((float)$fCredits * $fRate, $iPrecision);
+    }
+
+    /**
+     * Convert Money to Credits
+     */
+    public function convertM2C($fMoney, $fRate = false, $iPrecision = false)
+    {
+        if($fRate === false)
+            $fRate = $this->getConversionRateUse();
+        if($iPrecision === false)
+            $iPrecision = $this->getPrecision();
+
+        return round((float)$fMoney / $fRate, $iPrecision);
+    }
+
+    /*
+     * Internal methods
+     */
+    protected function _getConversionRate($sType)
+    {
+        $fRate = (float)getParam($this->CNF['PARAM_CR_' . strtoupper($sType)]);
+
+        return $fRate > 0 && $fRate <= 1 ? $fRate : 1;
+    }
+}
+
+/** @} */

+ 110 - 0
modules/boonex/credits/updates/12.0.0_12.0.1/source/classes/BxCreditsFormWithdraw.php

@@ -0,0 +1,110 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Credits Credits
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+/**
+ * Withdraw form
+ */
+class BxCreditsFormWithdraw extends BxTemplFormView
+{
+    protected $_sModule;
+    protected $_oModule;
+
+    protected $_fRate;
+
+    public function __construct($aInfo, $oTemplate = false)
+    {
+        $this->_sModule = 'bx_credits';
+        $this->_oModule = BxDolModule::getInstance($this->_sModule);
+
+        parent::__construct($aInfo, $oTemplate);
+
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        $this->_fRate = $this->_oModule->_oConfig->getConversionRateWithdraw();
+
+        if(isset($this->aInputs[$CNF['FIELD_C_MESSAGE']])) {
+            $sInfo = '_bx_credits_form_credit_input_message_inf_';
+            switch($this->aParams['display']) {
+                case $CNF['OBJECT_FORM_CREDIT_DISPLAY_GRANT']:
+                    $sInfo .= 'g';
+                    break;
+
+                case $CNF['OBJECT_FORM_CREDIT_DISPLAY_WITHDRAW_REQUEST']:
+                    $sInfo .= 'wr';
+                    break;
+                
+                case $CNF['OBJECT_FORM_CREDIT_DISPLAY_WITHDRAW_CONFIRM']:
+                    $sInfo .= 'wc';
+                    break;
+            }
+
+            $this->aInputs[$CNF['FIELD_C_MESSAGE']]['info'] = _t($sInfo);
+        }
+    }
+
+    protected function genCustomRowRate(&$aInput)
+    {
+        if($this->_fRate == 1)
+            return '';
+
+        return $this->genRowStandard($aInput);
+    }
+
+    protected function genCustomRowResult(&$aInput)
+    {
+        if($this->_fRate == 1)
+            return '';
+
+        return $this->genRowStandard($aInput);
+    }
+    
+    protected function genCustomInputBalance(&$aInput)
+    {
+        $aInput['value'] = $this->_oModule->getProfileBalance();
+
+        return $this->genInputStandard($aInput);
+    }
+    
+    protected function genCustomInputRate(&$aInput)
+    {
+        $aInput['value'] = $this->_fRate;
+        $aInput['attrs']['id'] = $this->_oModule->_oConfig->getHtmlIds('withdraw_field_rate');
+        return $this->genInputStandard($aInput);
+    }
+
+    protected function genCustomInputAmount(&$aInput)
+    {
+        if($this->_fRate != 1)
+            $aInput['attrs']['onblur'] = $this->_oModule->_oConfig->getJsObject('withdraw') . '.getResult(this)';
+
+        $aInput['attrs']['id'] = $this->_oModule->_oConfig->getHtmlIds('withdraw_field_amount');
+        return $this->genInputStandard($aInput);
+    }
+
+    protected function genCustomInputResult(&$aInput)
+    {
+        $aInput['attrs']['id'] = $this->_oModule->_oConfig->getHtmlIds('withdraw_field_result');
+        return $this->genInputStandard($aInput);
+    }
+
+    protected function genCustomInputProfile(&$aInput)
+    {
+        if(empty($aInput['custom']) || !is_array($aInput['custom']))
+            $aInput['custom'] = array();
+        $aInput['custom']['only_once'] = 1;
+
+        $aInput['ajax_get_suggestions'] = BX_DOL_URL_ROOT . $this->_oModule->_oConfig->getBaseUri() . "get_profiles";
+
+        return $this->genCustomInputUsernamesSuggestions($aInput);
+    }
+}
+
+/** @} */

+ 998 - 0
modules/boonex/credits/updates/12.0.0_12.0.1/source/classes/BxCreditsModule.php

@@ -0,0 +1,998 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Credits Credits
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+define('BX_CREDITS_DIRECTION_IN', 'in');
+define('BX_CREDITS_DIRECTION_OUT', 'out');
+
+define('BX_CREDITS_ORDER_TYPE_SINGLE', 'single'); //--- one-time payment
+define('BX_CREDITS_ORDER_TYPE_RECURRING', 'recurring'); //--- recurring payment (subscription)
+
+
+class BxCreditsModule extends BxBaseModGeneralModule
+{
+    function __construct(&$aModule)
+    {
+        parent::__construct($aModule);
+    }
+
+    public function actionGetProfiles()
+    {
+        $sTerm = bx_get('term');
+
+        $a = BxDolService::call('system', 'profiles_search', array($sTerm), 'TemplServiceProfiles');
+
+        echoJson($a);
+    }
+
+    public function actionCheckBundleName()
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+    	$sName = bx_process_input(bx_get('name'));
+    	if(empty($sName))
+            return echoJson(array());
+
+        $sResult = '';
+
+        $iId = (int)bx_get('id');
+        if(!empty($iId)) {
+            $aBundle = $this->_oDb->getBundle(array('type' => 'id', 'id' => $iId)); 
+            if(strcmp($sName, $aBundle[$CNF['FIELD_NAME']]) == 0) 
+                $sResult = $sName;
+        }
+
+    	echoJson(array(
+            'name' => !empty($sResult) ? $sResult : $this->_oConfig->getBundleName($sName)
+    	));
+    }
+
+    public function actionCheckout()
+    {
+        $iBuyerId = bx_get_logged_profile_id();
+        if(!$iBuyerId)
+            return echoJson(array('code' => 1, 'msg' => _t('_bx_credits_err_unknown_buyer')));
+
+        $aData = $this->_oConfig->getCheckoutData();
+        if(empty($aData) || !is_array($aData))
+            return echoJson(array('code' => 2, 'msg' => _t('_bx_credits_err_incorrect_data')));
+
+        $iSellerId = (int)$aData['seller'];
+        $fAmount = (float)$aData['amount'];
+
+        $fBalance = (float)$this->_oDb->getProfile(array('type' => 'balance', 'id' => $iBuyerId));
+        if($fAmount > $fBalance)
+            return echoJson(array('code' => 3, 'msg' => _t('_bx_credits_err_low_balance')));
+
+        $sOrder = $this->_oConfig->getOrder();
+        $sInfo = '_bx_credits_txt_history_info_checkout';
+        $sData = serialize(array(
+            'conversion' => $this->_oConfig->getConversionRateUse(),
+            'precision' => $this->_oConfig->getPrecision()
+        ));
+
+        $this->updateProfileBalance($iBuyerId, $iSellerId, -$fAmount, $sOrder, $sInfo, $sData);
+        $this->updateProfileBalance($iSellerId, $iBuyerId, $fAmount, $sOrder, $sInfo, $sData);
+
+        bx_alert($this->getName(), 'checkout', 0, false, array(
+            'seller' => $iSellerId,
+            'buyer' => $iBuyerId,
+            'amount' => $fAmount, 
+            'order' => $sOrder
+        ));
+
+        return echoJson(array(
+            'code' => 0,
+            'redirect' => bx_append_url_params($aData['return_data_url'], array('o' => $sOrder, 'c' => $aData['custom']))
+        ));
+    }
+
+    public function actionSubscribe()
+    {
+        $iBuyerId = bx_get_logged_profile_id();
+        if(!$iBuyerId)
+            return echoJson(array('code' => 1, 'msg' => _t('_bx_credits_err_unknown_buyer')));
+
+        $aData = $this->_oConfig->getCheckoutData();
+        if(empty($aData) || !is_array($aData))
+            return echoJson(array('code' => 2, 'msg' => _t('_bx_credits_err_incorrect_data')));
+
+        $iSellerId = (int)$aData['seller'];
+        $fAmount = (float)$aData['amount'];
+
+        $fBalance = (float)$this->_oDb->getProfile(array('type' => 'balance', 'id' => $iBuyerId));
+        if($fAmount > $fBalance)
+            return echoJson(array('code' => 3, 'msg' => _t('_bx_credits_err_low_balance')));
+
+        $sUnique = $this->_oConfig->getOrder(9);
+        $sCustomer = 'bx_cus_' . $sUnique;
+        $sSubscription = 'bx_sub_' . $sUnique;
+
+        bx_alert($this->getName(), 'subscribe', 0, false, array(
+            'seller' => $iSellerId,
+            'buyer' => $iBuyerId,
+            'amount' => $fAmount, 
+            'trial' => $aData['trial'],
+            'customer' => $sCustomer,
+            'subscription' => $sSubscription
+        ));
+
+        return echoJson(array(
+            'code' => 0,
+            'redirect' => bx_append_url_params($aData['return_data_url'], array(
+                'cs' => $sCustomer, 
+                'sb' => $sSubscription,
+                'tr' => $aData['trial'],
+                'c' => $aData['custom']
+            ))
+        ));
+    }
+
+    public function serviceGetSafeServices()
+    {
+        return array (
+            'GetBlockBundles' => '',
+            'GetBlockOrders' => '',
+            'GetBlockHistory' => '',
+        );
+    }
+
+    public function serviceGetCheckoutUrl()
+    {
+        return $this->_oConfig->getCheckoutUrl();
+    }
+
+    public function serviceValidateCheckout($iSeller, $iBuyer, $fAmount, $sOrder)
+    {
+        $fAmount = (float)$fAmount;
+
+        $aOut = $this->_oDb->getHistory(array('type' => 'row_by', 'by' => array('first_pid' => $iBuyer, 'direction' => BX_CREDITS_DIRECTION_OUT, 'order' => $sOrder)));
+        if(empty($aOut) || !is_array($aOut) || (int)$aOut['second_pid'] != (int)$iSeller)
+            return false;
+        
+        $aDataOut = unserialize($aOut['data']);
+        if($this->_oConfig->convertM2C($fAmount, $aDataOut['conversion'], $aDataOut['precision']) != (float)$aOut['amount'])
+            return false;
+
+        $aIn = $this->_oDb->getHistory(array('type' => 'row_by', 'by' => array('first_pid' => $iSeller, 'direction' => BX_CREDITS_DIRECTION_IN, 'order' => $sOrder)));
+        if(empty($aIn) || !is_array($aIn) || (int)$aIn['second_pid'] != (int)$iBuyer)
+            return false;
+
+        $aDataIn = unserialize($aIn['data']);
+        if($this->_oConfig->convertM2C($fAmount, $aDataIn['conversion'], $aDataIn['precision']) != (float)$aIn['amount'])
+            return false;
+
+        return true;
+    }
+
+    public function serviceGetBlockCheckout()
+    {
+        $oBuyer = BxDolProfile::getInstance();
+        if(!$oBuyer)
+            return MsgBox(_t('_bx_credits_err_unknown_buyer'));
+        
+        $iSeller = (int)bx_get('seller');
+        $oSeller = BxDolProfile::getInstance($iSeller);
+        if(!$oSeller)
+            return MsgBox(_t('_bx_credits_err_unknown_seller'));
+
+        $fAmountM = (float)bx_get('amount');
+        $fAmountC = $this->_oConfig->convertM2C($fAmountM);
+
+        $aData = array(
+            'seller' => $iSeller,
+            'currency' => array(
+                'code' => bx_process_input(bx_get('currency_code')),
+                'sign' => bx_process_input(bx_get('currency_sign')),
+            ),
+            'amountm' => $fAmountM,
+            'amountc' => $fAmountC
+        );
+
+        $iItemsCount = (int)bx_get('items_count');
+        for($i = 0; $i < $iItemsCount; $i++) {
+            $aData['items'][] = array(
+                'title' => bx_process_input(bx_get('item_title_' . $i)),
+                'quantity' => (int)bx_get('item_quantity_' . $i)
+            );
+        }
+
+        $this->_oConfig->setCheckoutData(array(
+            'seller' => $iSeller,
+            'amount' => $fAmountC,
+            'custom' => bx_process_input(bx_get('custom')),
+            'return_data_url' => bx_process_input(bx_get('return_data_url')),
+        ));
+        return $this->_oTemplate->getBlockCheckout($oBuyer, $oSeller, $aData);
+    }
+
+    public function serviceGetPopupSubscribe($aData)
+    {
+        $oBuyer = BxDolProfile::getInstance();
+        if(!$oBuyer)
+            return array('msg' => _t('_bx_credits_err_unknown_buyer'));
+
+        $iSeller = (int)$aData['seller'];
+        $oSeller = BxDolProfile::getInstance($iSeller);
+        if(!$oSeller)
+            return array('msg' => _t('_bx_credits_err_unknown_seller'));
+
+        $fAmountM = (float)$aData['amount'];
+        $fAmountC = $this->_oConfig->convertM2C($fAmountM);
+
+        $aData = array_merge($aData, array(
+            'amountm' => $fAmountM,
+            'amountc' => $fAmountC
+        ));
+
+        $this->_oConfig->setCheckoutData(array(
+            'seller' => $iSeller,
+            'amount' => $fAmountC,
+            'trial' => (int)$aData['trial'] > 0,
+            'custom' => bx_process_input($aData['custom']),
+            'return_data_url' => bx_process_input($aData['return_data_url']),
+        ));
+        return $this->_oTemplate->getPopupSubscribe($oBuyer, $oSeller, $aData);
+    }
+
+    public function serviceGetMenuItemAddonAmount()
+    {
+        $iProfileId = bx_get_logged_profile_id();
+        if(!$iProfileId)
+            return '';
+
+        return array(
+            'unit' => $this->_oTemplate->getUnit(), 
+            'value' => $this->convertC2S($this->_oDb->getProfile(array('type' => 'balance', 'id' => $iProfileId)), false)
+        );
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_credits Credits
+     * @subsection bx_credits-page_blocks Page Blocks
+     * @subsubsection bx_credits-get_block_bundles get_block_bundles
+     * 
+     * @code bx_srv('bx_credits', 'get_block_bundles'); @endcode
+     * 
+     * Get page block with bundles
+     * 
+     * @see BxCreditsModule::serviceGetBlockBundles
+     */
+    /** 
+     * @ref bx_credits-get_block_bundles "get_block_bundles"
+     */
+    public function serviceGetBlockBundles()
+    {
+        return $this->_oTemplate->getBlockBundles();
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_credits Credits
+     * @subsection bx_credits-page_blocks Page Blocks
+     * @subsubsection bx_credits-get_block_orders_note get_block_orders_note
+     * 
+     * @code bx_srv('bx_credits', 'get_block_orders_note', [...]); @endcode
+     * 
+     * Get page block with a notice for orders usage.
+     *
+     * @return HTML string with block content to display on the site.
+     * 
+     * @see BxCreditsModule::serviceBlockLicensesNote
+     */
+    /** 
+     * @ref bx_credits-get_block_orders_note "get_block_orders_note"
+     */
+    public function serviceGetBlockOrdersNote()
+    {
+        return MsgBox(_t('_bx_credits_page_block_content_orders_common_note'));
+    }
+    
+    /**
+     * @page service Service Calls
+     * @section bx_credits Credits
+     * @subsection bx_credits-page_blocks Page Blocks
+     * @subsubsection bx_credits-block_orders get_block_orders
+     * 
+     * @code bx_srv('bx_credits', 'get_block_orders', [...]); @endcode
+     * 
+     * Get page block with a list of orders purchased by currently logged member.
+     *
+     * @return an array describing a block to display on the site or false if there is no enough input data. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
+     * 
+     * @see BxCreditsModule::serviceBlockLicenses
+     */
+    /** 
+     * @ref bx_credits-get_block_orders "get_block_orders"
+     */
+    public function serviceGetBlockOrders($sType = 'common') 
+    {
+        return $this->_getBlockOrders($sType);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_credits Credits
+     * @subsection bx_credits-page_blocks Page Blocks
+     * @subsubsection bx_credits-get_block_history get_block_history
+     * 
+     * @code bx_srv('bx_credits', 'get_block_history', [...]); @endcode
+     * 
+     * Get page block with a list of all changes with credits.
+     *
+     * @return an array describing a block to display on the site or false if there is no enough input data. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
+     * 
+     * @see BxCreditsModule::serviceGetBlockHistory
+     */
+    /** 
+     * @ref bx_credits-get_block_history "get_block_history"
+     */
+    public function serviceGetBlockHistory($sType = 'common') 
+    {
+        return $this->_getBlockHistory($sType);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_credits Credits
+     * @subsection bx_credits-payments Payments
+     * @subsubsection bx_credits-get_payment_data get_payment_data
+     * 
+     * @code bx_srv('bx_credits', 'get_payment_data', [...]); @endcode
+     * 
+     * Get an array with module's description. Is needed for payments processing module.
+     * 
+     * @return an array with module's description.
+     * 
+     * @see BxCreditsModule::serviceGetPaymentData
+     */
+    /** 
+     * @ref bx_credits-get_payment_data "get_payment_data"
+     */
+    public function serviceGetPaymentData()
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $oPermalink = BxDolPermalinks::getInstance();
+
+        $aResult = $this->_aModule;
+        $aResult['url_browse_order_common'] = BX_DOL_URL_ROOT . $oPermalink->permalink($CNF['URL_ORDERS_COMMON'], array('filter' => '{order}'));
+        $aResult['url_browse_order_administration'] = BX_DOL_URL_ROOT . $oPermalink->permalink($CNF['URL_ORDERS_ADMINISTRATION'], array('filter' => '{order}'));
+
+        return $aResult;
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_credits Credits
+     * @subsection bx_credits-payments Payments
+     * @subsubsection bx_credits-get_cart_item get_cart_item
+     * 
+     * @code bx_srv('bx_credits', 'get_cart_item', [...]); @endcode
+     * 
+     * Get an array with prodict's description. Is used in Shopping Cart in payments processing module.
+     * 
+     * @param $iItemId product's ID.
+     * @return an array with prodict's description. Empty array is returned if something is wrong.
+     * 
+     * @see BxCreditsModule::serviceGetCartItem
+     */
+    /** 
+     * @ref bx_credits-get_cart_item "get_cart_item"
+     */
+    public function serviceGetCartItem($iItemId)
+    {
+    	$CNF = &$this->_oConfig->CNF;
+
+        if(!$iItemId)
+            return array();
+
+        $aItem = $this->_oDb->getBundle(array('type' => 'id', 'id' => $iItemId));
+        if(empty($aItem) || !is_array($aItem))
+            return array();
+
+        return array (
+            'id' => $aItem[$CNF['FIELD_ID']],
+            'author_id' => $this->_oConfig->getAuthor(),
+            'name' => $aItem[$CNF['FIELD_NAME']],
+            'title' => _t($aItem[$CNF['FIELD_TITLE']]),
+            'description' => $this->_oConfig->getBundleDescription($aItem),
+            'url' => $this->_oConfig->getBundleUrl($aItem),
+            'price_single' => $aItem[$CNF['FIELD_PRICE']],
+            'price_recurring' => '',
+            'period_recurring' => 1,
+            'period_unit_recurring' => '',
+            'trial_recurring' => ''
+        );
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_credits Credits
+     * @subsection bx_credits-payments Payments
+     * @subsubsection bx_credits-get_cart_items get_cart_items
+     * 
+     * @code bx_srv('bx_credits', 'get_cart_items', [...]); @endcode
+     * 
+     * Get an array with prodicts' descriptions by seller. Is used in Manual Order Processing in payments processing module.
+     * 
+     * @param $iSellerId seller ID.
+     * @return an array with prodicts' descriptions. Empty array is returned if something is wrong or seller doesn't have any products.
+     * 
+     * @see BxCreditsModule::serviceGetCartItems
+     */
+    /** 
+     * @ref bx_credits-get_cart_items "get_cart_items"
+     */
+    public function serviceGetCartItems($iAuthorId)
+    {
+    	$CNF = &$this->_oConfig->CNF;
+
+        $iAuthorId = $this->_oConfig->getAuthor();
+        $aItems = $this->_oDb->getBundle(array('type' => 'all', 'active' => 1));
+
+        $aResult = array();
+        foreach($aItems as $aItem)
+            $aResult[] = array(
+                'id' => $aItem[$CNF['FIELD_ID']],
+                'author_id' => $iAuthorId,
+                'name' => $aItem[$CNF['FIELD_NAME']],
+                'title' => _t($aItem[$CNF['FIELD_TITLE']]),
+                'description' => $this->_oConfig->getBundleDescription($aItem),
+                'url' => $this->_oConfig->getBundleUrl($aItem),
+                'price_single' => $aItem[$CNF['FIELD_PRICE']],
+                'price_recurring' => '',
+                'period_recurring' => 1,
+                'period_unit_recurring' => '',
+                'trial_recurring' => ''
+            );
+
+        return $aResult;
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_credits Credits
+     * @subsection bx_credits-payments Payments
+     * @subsubsection bx_credits-register_cart_item register_cart_item
+     * 
+     * @code bx_srv('bx_credits', 'register_cart_item', [...]); @endcode
+     * 
+     * Register a processed single time payment inside the Credits module. Is called with payment processing module after the payment was registered there.
+     * 
+     * @param $iClientId client ID.
+     * @param $iSellerId seller ID
+     * @param $iItemId item ID.
+     * @param $iItemCount the number of purchased items.
+     * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
+     * @param $sLicense license number genereted with payment processing module for internal usage
+     * @return an array with purchased prodict's description. Empty array is returned if something is wrong.
+     * 
+     * @see BxCreditsModule::serviceRegisterCartItem
+     */
+    /** 
+     * @ref bx_credits-register_cart_item "register_cart_item"
+     */
+    public function serviceRegisterCartItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense)
+    {
+        return $this->_serviceRegisterItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense, BX_CREDITS_ORDER_TYPE_SINGLE);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_credits Credits
+     * @subsection bx_credits-payments Payments
+     * @subsubsection bx_credits-register_subscription_item register_subscription_item
+     * 
+     * @code bx_srv('bx_credits', 'register_subscription_item', [...]); @endcode
+     * 
+     * Register a processed subscription (recurring payment) inside the Credits module. Is called with payment processing module after the subscription was registered there.
+     * 
+     * @param $iClientId client ID.
+     * @param $iSellerId seller ID
+     * @param $iItemId item ID.
+     * @param $iItemCount the number of purchased items.
+     * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
+     * @param $sLicense license number genereted with payment processing module for internal usage
+     * @return an array with subscribed prodict's description. Empty array is returned if something is wrong.
+     * 
+     * @see BxCreditsModule::serviceRegisterSubscriptionItem
+     */
+    /** 
+     * @ref bx_credits-register_subscription_item "register_subscription_item"
+     */
+    public function serviceRegisterSubscriptionItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense)
+    {
+        return $this->_serviceRegisterItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense, BX_CREDITS_ORDER_TYPE_RECURRING);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_credits Credits
+     * @subsection bx_credits-payments Payments
+     * @subsubsection bx_credits-reregister_cart_item reregister_cart_item
+     * 
+     * @code bx_srv('bx_credits', 'reregister_cart_item', [...]); @endcode
+     * 
+     * Reregister a single time payment inside the Credits module. Is called with payment processing module after the payment was reregistered there.
+     * 
+     * @param $iClientId client ID.
+     * @param $iSellerId seller ID
+     * @param $iItemIdOld old item ID.
+     * @param $iItemIdNew new item ID.
+     * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
+     * @return an array with purchased prodict's description. Empty array is returned if something is wrong.
+     * 
+     * @see BxCreditsModule::serviceReregisterCartItem
+     */
+    /** 
+     * @ref bx_credits-reregister_cart_item "reregister_cart_item"
+     */
+    public function serviceReregisterCartItem($iClientId, $iSellerId, $iItemIdOld, $iItemIdNew, $sOrder)
+    {
+        return array();
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_credits Credits
+     * @subsection bx_credits-payments Payments
+     * @subsubsection bx_credits-reregister_subscription_item reregister_subscription_item
+     * 
+     * @code bx_srv('bx_credits', 'reregister_subscription_item', [...]); @endcode
+     * 
+     * Reregister a subscription (recurring payment) inside the Credits module. Is called with payment processing module after the subscription was reregistered there.
+     * 
+     * @param $iClientId client ID.
+     * @param $iSellerId seller ID
+     * @param $iItemIdOld old item ID.
+     * @param $iItemIdNew new item ID.
+     * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
+     * @return an array with subscribed prodict's description. Empty array is returned if something is wrong.
+     * 
+     * @see BxCreditsModule::serviceReregisterSubscriptionItem
+     */
+    /** 
+     * @ref bx_credits-reregister_subscription_item "reregister_subscription_item"
+     */
+    public function serviceReregisterSubscriptionItem($iClientId, $iSellerId, $iItemIdOld, $iItemIdNew, $sOrder)
+    {
+        return array();
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_credits Credits
+     * @subsection bx_credits-payments Payments
+     * @subsubsection bx_credits-unregister_cart_item unregister_cart_item
+     * 
+     * @code bx_srv('bx_credits', 'unregister_cart_item', [...]); @endcode
+     * 
+     * Unregister an earlier processed single time payment inside the Credits module. Is called with payment processing module after the payment was unregistered there.
+     * 
+     * @param $iClientId client ID.
+     * @param $iSellerId seller ID
+     * @param $iItemId item ID.
+     * @param $iItemCount the number of purchased items.
+     * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
+     * @param $sLicense license number genereted with payment processing module for internal usage
+     * @return boolean value determining where the payment was unregistered or not.
+     * 
+     * @see BxCreditsModule::serviceUnregisterCartItem
+     */
+    /** 
+     * @ref bx_credits-unregister_cart_item "unregister_cart_item"
+     */
+    public function serviceUnregisterCartItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense)
+    {
+        return $this->_serviceUnregisterItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense, BX_CREDITS_ORDER_TYPE_SINGLE);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_credits Credits
+     * @subsection bx_credits-payments Payments
+     * @subsubsection bx_credits-unregister_subscription_item unregister_subscription_item
+     * 
+     * @code bx_srv('bx_credits', 'unregister_subscription_item', [...]); @endcode
+     * 
+     * Unregister an earlier processed subscription (recurring payment) inside the Credits module. Is called with payment processing module after the subscription was unregistered there.
+     * 
+     * @param $iClientId client ID.
+     * @param $iSellerId seller ID
+     * @param $iItemId item ID.
+     * @param $iItemCount the number of purchased items.
+     * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
+     * @param $sLicense license number genereted with payment processing module for internal usage
+     * @return boolean value determining where the subscription was unregistered or not.
+     * 
+     * @see BxCreditsModule::serviceUnregisterSubscriptionItem
+     */
+    /** 
+     * @ref bx_credits-unregister_subscription_item "unregister_subscription_item"
+     */
+    public function serviceUnregisterSubscriptionItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense)
+    {
+    	return $this->_serviceUnregisterItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense, BX_CREDITS_ORDER_TYPE_RECURRING); 
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_credits Credits
+     * @subsection bx_credits-payments Payments
+     * @subsubsection bx_credits-cancel_subscription_item cancel_subscription_item
+     * 
+     * @code bx_srv('bx_credits', 'cancel_subscription_item', [...]); @endcode
+     * 
+     * Cancel an earlier processed subscription (recurring payment) inside the Credits module. Is called with payment processing module after the subscription was canceled there.
+     * 
+     * @param $iClientId client ID.
+     * @param $iSellerId seller ID
+     * @param $iItemId item ID.
+     * @param $iItemCount the number of purchased items.
+     * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
+     * @return boolean value determining where the subscription was canceled or not.
+     * 
+     * @see BxCreditsModule::serviceCancelSubscriptionItem
+     */
+    /** 
+     * @ref bx_credits-cancel_subscription_item "cancel_subscription_item"
+     */
+    public function serviceCancelSubscriptionItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder)
+    {
+    	return true;
+    }
+
+    public function serviceGetProfileBalance($iProfileId = 0)
+    {
+        return $this->getProfileBalance($iProfileId);
+    }
+
+    public function serviceUpdateProfileBalance($iFirstPid, $fAmount, $iSecondPid = 0, $sOrder = '', $sInfo = '')
+    {
+        if(empty($sInfo))
+            $sInfo = '_bx_credits_txt_history_info_service';
+
+        return $this->updateProfileBalance($iFirstPid, $iSecondPid, $fAmount, $sOrder, $sInfo);
+    }
+    
+    public function serviceMakePayment($iBuyerPid, $fAmount, $iSellerPid, $sOrder = '')
+    {
+        $sInfo = '_bx_credits_txt_history_info_checkout';
+
+        if(!$this->updateProfileBalance($iBuyerPid, $iSellerPid, -$fAmount, $sOrder, $sInfo))
+            return false;
+
+        if(!$this->updateProfileBalance($iSellerPid, $iBuyerPid, $fAmount, $sOrder, $sInfo)) {
+            $this->updateProfileBalance($iBuyerPid, 0, $fAmount, $sOrder, '_bx_credits_txt_history_info_refund');
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * Delete all content by profile 
+     * @param $iProfileId profile id 
+     * @return number of deleted items
+     */
+    public function serviceDeleteEntitiesByAuthor ($iProfileId)
+    {
+        $this->_oDb->deleteProfile(array('id' => $iProfileId));
+        $this->_oDb->deleteHistory(array('first_pid' => $iProfileId));
+    }
+
+
+    /*
+     * Common methods
+     */
+    public function convertC2S($fCredits, $bWithUnit = true)
+    {
+        $sResult = '';
+        if($bWithUnit)
+            $sResult .= $this->_oTemplate->getUnit();
+
+        $iPrecision = $this->_oConfig->getPrecision();
+        $sResult .= sprintf("%01." . $iPrecision . "f", round((float)$fCredits, $iPrecision));
+
+        return $sResult;
+    }
+
+    public function getProfileBalance($iProfileId = 0)
+    {
+        if(empty($iProfileId))
+            $iProfileId = bx_get_logged_profile_id();
+
+        if(empty($iProfileId))
+            return 0;
+
+        return (float)$this->_oDb->getProfile(array('type' => 'balance', 'id' => $iProfileId));
+    }
+
+    public function updateProfileBalance($iFirstPid, $iSecondPid, $fAmount, $sOrder = '', $sInfo = '', $sData = '')
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        if(empty($sOrder))
+            $sOrder = $this->_oConfig->getOrder();
+
+        if(empty($sData))
+            $sData = serialize(array(
+                'conversion' => $this->_oConfig->getConversionRateUse(),
+                'precision' => $this->_oConfig->getPrecision()
+            ));
+
+        if(!$this->_oDb->updateProfileBalance($iFirstPid, $fAmount))
+            return false;
+
+        $fAmountAbs = abs($fAmount);
+        $sDirection = $fAmount > 0 ? BX_CREDITS_DIRECTION_IN : BX_CREDITS_DIRECTION_OUT;
+
+        $this->_oDb->insertHistory(array(
+            'first_pid' => $iFirstPid,
+            'second_pid' => $iSecondPid,
+            'amount' => $fAmountAbs,
+            'direction' => $sDirection,
+            'order' => $sOrder,
+            'data' => $sData,
+            'info' => $sInfo,
+            'date' => time()
+        ));
+
+        bx_alert($this->getName(), 'update_balance', 0, false, array(
+            'first_pid' => $iFirstPid,
+            'second_pid' => $iSecondPid,
+            'amount' => $fAmountAbs,
+            'direction' => $sDirection,
+            'order' => $sOrder,
+        ));
+
+        $oSecondProfile = BxDolProfile::getInstanceMagic($iSecondPid);
+        sendMailTemplate($CNF['ETEMPLATE_' . strtoupper($sDirection)], 0, $iFirstPid, array(
+            'second_profile_name' => $oSecondProfile->getDisplayName(),
+            'amount' => $fAmountAbs,
+        ));
+
+        return true;
+    }
+
+    public function processGrant($iProfileId, $fAmount, $sMessage = '')
+    {
+        $CNF = &$this->_oConfig->CNF;
+        
+        $oProfile = BxDolProfile::getInstance($iProfileId);
+        if(!$oProfile)
+            return array('code' => 1, 'msg' => '_bx_credits_err_profile_not_found');
+
+        $sInfo = '_bx_credits_txt_history_info_grant';
+        if(!$this->updateProfileBalance($iProfileId, 0, $fAmount, '', $sInfo))
+            return array('code' => 2, 'msg' => '_bx_credits_err_cannot_update_balance');
+
+        sendMailTemplate($CNF['ETEMPLATE_GRANTED'], 0, $iProfileId, array(
+            'amount' => $fAmount,
+            'message' => $sMessage
+        ));
+
+        bx_alert($this->getName(), 'granted', 0, false, array(
+            'profile' => $iProfileId,
+            'amount' => $fAmount,
+        ));
+
+        return array('code' => 0);
+    }
+
+    public function processWithdrawRequest($iProfileId, $fAmount, $sMessage = '')
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        if(empty($iProfileId))
+            $iProfileId = bx_get_logged_profile_id ();
+
+        if(empty($iProfileId))
+            return array('code' => 1, 'msg' => '_bx_credits_err_login_required');
+
+        $oProfile = BxDolProfile::getInstance($iProfileId);
+        if(!$oProfile)
+            return array('code' => 1, 'msg' => '_bx_credits_err_login_required');
+
+        $fBalance = $this->getProfileBalance($iProfileId);
+        if($fAmount > $fBalance)
+            return array('code' => 2, 'msg' => '_bx_credits_err_low_balance');
+
+        $aResult = array('code' => 3, 'msg' => '_bx_credits_err_cannot_send');
+
+        $oEmailTemplates = BxDolEmailTemplates::getInstance();
+        if(!$oEmailTemplates)
+            return $aResult;
+
+        $fRate = $this->_oConfig->getConversionRateWithdraw();
+
+        $aTemplateVars = array(
+            'profile_link' => $oProfile->getUrl(),
+            'profile_name' => $oProfile->getDisplayName(),
+            'amount' => $fAmount,
+            'rate' => $fRate,
+            'message' => $sMessage,
+            'confirm_url' => BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink($CNF['URL_HISTORY_ADMINISTRATION'])
+        );
+        $aTemplate = $oEmailTemplates->parseTemplate($CNF['ETEMPLATE_WITHDRAW_REQUESTED'], $aTemplateVars);
+        if(!$aTemplate)
+            return $aResult;
+
+        $sEmail = $this->_oConfig->getWithdrawEmail();
+        if(!sendMail($sEmail, $aTemplate['Subject'], $aTemplate['Body'], 0, array(), BX_EMAIL_SYSTEM, 'html', false, array(), true))
+            return $aResult;
+
+        bx_alert($this->getName(), 'withdraw_requested', 0, $iProfileId, array(
+            'profile' => $iProfileId,
+            'amount' => $fAmount,
+            'rate' => $fRate
+        ));
+
+        return array('code' => 0);
+    }
+
+    public function processWithdrawConfirm($iProfileId, $fAmount, $sMessage = '')
+    {
+        $CNF = &$this->_oConfig->CNF;
+        
+        $oProfile = BxDolProfile::getInstance($iProfileId);
+        if(!$oProfile)
+            return array('code' => 1, 'msg' => '_bx_credits_err_profile_not_found');
+
+        $fBalance = $this->getProfileBalance($iProfileId);
+        if($fAmount > $fBalance)
+            return array('code' => 2, 'msg' => '_bx_credits_err_low_balance');
+
+        $sInfo = '_bx_credits_txt_history_info_withdraw';
+        if(!$this->updateProfileBalance($iProfileId, 0, -$fAmount, '', $sInfo))
+            return array('code' => 3, 'msg' => '_bx_credits_err_cannot_update_balance');
+
+        sendMailTemplate($CNF['ETEMPLATE_WITHDRAW_SENT'], 0, $iProfileId, array(
+            'amount' => $fAmount,
+            'message' => $sMessage
+        ));
+
+        bx_alert($this->getName(), 'withdraw_sent', 0, false, array(
+            'profile' => $iProfileId,
+            'amount' => $fAmount,
+        ));
+
+        return array('code' => 0);
+    }
+
+    /*
+     * Internal methods
+     */
+    protected function _serviceRegisterItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense, $sType)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+    	$aItem = $this->serviceGetCartItem($iItemId);
+        if(empty($aItem) || !is_array($aItem))
+            return array();
+
+        $aBundle = $this->_oDb->getBundle(array('type' => 'id', 'id' => $iItemId));
+        if(empty($aBundle) || !is_array($aBundle))
+            return array();
+
+        $iTrial = 0;
+        $sDuration = '';
+        $sAction = 'register';
+        if($sType == BX_CREDITS_ORDER_TYPE_RECURRING && isset($CNF['FIELD_DURATION_RECURRING'], $CNF['FIELD_TRIAL_RECURRING'])) {
+            $iTrial = $aBundle[$CNF['FIELD_TRIAL_RECURRING']];
+            $sDuration = $aBundle[$CNF['FIELD_DURATION_RECURRING']];
+
+            if($this->_oDb->isOrderByPbo($iClientId, $iItemId, $sOrder))
+                $sAction = 'prolong';
+        }
+
+        if(!$this->_oDb->{$sAction . 'Order'}($iClientId, $iItemId, $iItemCount, $sOrder, $sLicense, $sType, $sDuration, $iTrial))
+            return array();
+
+        $sInfo = '_bx_credits_txt_history_info_purchase';
+        $fAmount = ((float)$aBundle[$CNF['FIELD_AMOUNT']] + (float)$aBundle[$CNF['FIELD_BONUS']]) * $iItemCount;
+        if(!$this->updateProfileBalance($iClientId, 0, $fAmount, '', $sInfo))
+            return array();
+
+        bx_alert($this->getName(), 'order_' . $sAction, 0, false, array(
+            'profile_id' => $iClientId,
+            'bundle_id' => $iItemId,
+            'product_id' => $iItemId,   //--- Alias for 'bundle_id'
+            'count' => $iItemCount,
+            'order' => $sOrder,
+            'license' => $sLicense,
+            'type' => $sType,
+            'duration' => $sDuration,
+            'trial' => $iTrial
+        ));
+
+        $oClient = BxDolProfile::getInstanceMagic($iClientId);
+        $oSeller = BxDolProfile::getInstanceMagic($iSellerId);
+        $sSellerUrl = $oSeller->getUrl();
+        $sSellerName = $oSeller->getDisplayName();
+
+        sendMailTemplate($CNF['ETEMPLATE_PURCHASED'], 0, $iClientId, array(
+            'client_name' => $oClient->getDisplayName(),
+            'bundle_name' => $aBundle[$CNF['FIELD_NAME']],
+            'bundle_title' => _t($aBundle[$CNF['FIELD_TITLE']]),
+            'bundle_url' => $this->_oConfig->getBundleUrl($aBundle),
+            'vendor_url' => $sSellerUrl,
+            'vendor_name' => $sSellerName,
+            'order' => $sOrder,
+            'license' => $sLicense,
+            'notes' => _t('_bx_credits_txt_purchased_note', $sSellerUrl, $sSellerName),
+        ));
+
+        return $aItem;
+    }
+
+    protected function _serviceUnregisterItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense, $sType)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $aBundle = $this->_oDb->getBundle(array('type' => 'id', 'id' => $iItemId));
+        if(empty($aBundle) || !is_array($aBundle))
+            return false;
+
+        if(!$this->_oDb->unregisterOrder($iClientId, $iItemId, $sOrder, $sLicense, $sType))
+            return false;
+
+        $fAmount = (float)$aBundle[$CNF['FIELD_AMOUNT']] + (float)$aBundle[$CNF['FIELD_BONUS']];
+        $aProfile = $this->_oDb->getProfile(array('type' => 'id', 'id' => $iClientId));
+        if(!empty($aProfile) && is_array($aProfile))
+            $this->_oDb->updateProfile(array('balance' => (float)$aProfile['balance'] - $fAmount), array('id' => $aProfile['id']));
+
+        bx_alert($this->getName(), 'order_unregister', 0, false, array(
+            'profile_id' => $iClientId,
+            'bundle_id' => $iItemId,
+            'product_id' => $iItemId,   //--- Alias for 'bundle_id'
+            'count' => $iItemCount,
+            'order' => $sOrder,
+            'license' => $sLicense,
+            'type' => $sType,
+        ));
+
+        return true;
+    }
+
+    protected function _getBlockOrders($sType) 
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $sGrid = $CNF['OBJECT_GRID_ORDERS_' . strtoupper($sType)];
+        $oGrid = BxDolGrid::getObjectInstance($sGrid);
+        if(!$oGrid)
+            return '';
+
+        return array(
+            'content' => $oGrid->getCode(),
+            'menu' => $CNF['OBJECT_MENU_MANAGE_SUBMENU']
+        );
+    }
+
+    protected function _getBlockHistory($sType) 
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $sGrid = $CNF['OBJECT_GRID_HISTORY_' . strtoupper($sType)];
+        $oGrid = BxDolGrid::getObjectInstance($sGrid);
+        if(!$oGrid)
+            return '';
+
+        return array(
+            'content' => $oGrid->getCode(),
+            'menu' => $CNF['OBJECT_MENU_MANAGE_SUBMENU']
+        );
+    }
+}
+
+/** @} */

+ 77 - 0
modules/boonex/credits/updates/12.0.0_12.0.1/source/install/config.php

@@ -0,0 +1,77 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Credits Credits
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_credits',
+    'title' => 'Credits',
+    'note' => 'Credits module.',
+    'version' => '12.0.1',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '12.1.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/credits/',
+    'home_uri' => 'credits',
+
+    'db_prefix' => 'bx_credits_',
+    'class_prefix' => 'BxCredits',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Credits',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'uninstall' => array (
+        'execute_sql' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'enable' => array(
+        'execute_sql' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable' => array (
+        'execute_sql' => 1,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Dependencies Section
+     */
+    'dependencies' => array(),
+
+    /**
+     * Relations Section
+     */
+    'relations' => array(),
+
+);
+
+/** @} */

+ 254 - 0
modules/boonex/credits/updates/12.0.0_12.0.1/source/install/langs/en.xml

@@ -0,0 +1,254 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources name="en" flag="gb" title="English">
+    <string name="_bx_credits"><![CDATA[Credits]]></string>
+
+
+    <!-- Options -->
+    <string name="_bx_credits_option_enable_withdraw"><![CDATA[Allow members to withdraw credits converting them to money]]></string>
+    <string name="_bx_credits_option_withdraw_email"><![CDATA[Email for withdraw requests]]></string>
+    <string name="_bx_credits_option_precision"><![CDATA[Precision (number of digits after the decimal point)]]></string>
+    <string name="_bx_credits_option_conversion_rate_use"><![CDATA[Conversion rate to pay with credits]]></string>
+    <string name="_bx_credits_option_conversion_rate_withdraw"><![CDATA[Conversion rate to withdraw credits]]></string>
+    <string name="_bx_credits_option_code"><![CDATA[Code to prefix amount]]></string>
+    <string name="_bx_credits_option_icon"><![CDATA[Icon to prefix amount]]></string>
+    <string name="_bx_credits_enable_provider"><![CDATA[Auto activate 'Credits' provider for all newly created profiles]]></string>
+
+
+    <!-- Forms -->
+    <string name="_bx_credits_form_bundle"><![CDATA[Bundle]]></string>
+    <string name="_bx_credits_form_bundle_display_add"><![CDATA[Add Bundle]]></string>
+    <string name="_bx_credits_form_bundle_display_edit"><![CDATA[Edit Bundle]]></string>
+    <string name="_bx_credits_form_bundle_input_sys_title"><![CDATA[Title]]></string>
+    <string name="_bx_credits_form_bundle_input_title"><![CDATA[Title]]></string>
+    <string name="_bx_credits_form_bundle_input_title_err"><![CDATA[This field is essential. Please fill it in for all languages.]]></string>
+    <string name="_bx_credits_form_bundle_input_sys_name"><![CDATA[Name]]></string>
+    <string name="_bx_credits_form_bundle_input_name"><![CDATA[Name]]></string>
+    <string name="_bx_credits_form_bundle_input_name_err"><![CDATA[This field is essential for API calls. Please fill it in.]]></string>
+    <string name="_bx_credits_form_bundle_input_sys_amount"><![CDATA[Amount]]></string>
+    <string name="_bx_credits_form_bundle_input_amount"><![CDATA[Amount]]></string>
+    <string name="_bx_credits_form_bundle_input_amount_err"><![CDATA[This field is essential. Please fill it in.]]></string>
+    <string name="_bx_credits_form_bundle_input_sys_bonus"><![CDATA[Bonus]]></string>
+    <string name="_bx_credits_form_bundle_input_bonus"><![CDATA[Bonus]]></string>
+    <string name="_bx_credits_form_bundle_input_sys_price"><![CDATA[Price]]></string>
+    <string name="_bx_credits_form_bundle_input_price"><![CDATA[Price]]></string>
+    <string name="_bx_credits_form_bundle_input_price_err"><![CDATA[This field is essential. Please fill it in.]]></string>
+    <string name="_bx_credits_form_bundle_input_sys_do_submit"><![CDATA[Submit]]></string>
+    <string name="_bx_credits_form_bundle_input_do_submit"><![CDATA[Submit]]></string>
+    <string name="_bx_credits_form_bundle_input_sys_do_cancel"><![CDATA[Cancel]]></string>
+    <string name="_bx_credits_form_bundle_input_do_cancel"><![CDATA[Cancel]]></string>
+
+    <string name="_bx_credits_form_credit"><![CDATA[Credit]]></string>
+    <string name="_bx_credits_form_credit_display_grant"><![CDATA[Grant]]></string>
+    <string name="_bx_credits_form_credit_display_withdraw_request"><![CDATA[Request Withdraw]]></string>
+    <string name="_bx_credits_form_credit_display_withdraw_confirm"><![CDATA[Confirm withdraw]]></string>
+    <string name="_bx_credits_form_credit_input_sys_balance"><![CDATA[Balance]]></string>
+    <string name="_bx_credits_form_credit_input_balance"><![CDATA[Balance]]></string>
+    <string name="_bx_credits_form_credit_input_sys_rate"><![CDATA[Conversion rate]]></string>
+    <string name="_bx_credits_form_credit_input_rate"><![CDATA[Conversion rate]]></string>
+    <string name="_bx_credits_form_credit_input_sys_result"><![CDATA[Result]]></string>
+    <string name="_bx_credits_form_credit_input_result"><![CDATA[Result]]></string>
+    <string name="_bx_credits_form_credit_input_sys_amount"><![CDATA[Amount]]></string>
+    <string name="_bx_credits_form_credit_input_amount"><![CDATA[Amount]]></string>
+    <string name="_bx_credits_form_credit_input_sys_message"><![CDATA[Message]]></string>
+    <string name="_bx_credits_form_credit_input_message"><![CDATA[Message]]></string>
+    <string name="_bx_credits_form_credit_input_message_inf_g"><![CDATA[]]></string>
+    <string name="_bx_credits_form_credit_input_message_inf_wr"><![CDATA[Payment instructions and other notes]]></string>
+    <string name="_bx_credits_form_credit_input_message_inf_wc"><![CDATA[Payment confirmation and other notes]]></string>
+    <string name="_bx_credits_form_credit_input_profile"><![CDATA[Profile]]></string>
+    <string name="_bx_credits_form_credit_input_sys_do_submit"><![CDATA[Submit]]></string>
+    <string name="_bx_credits_form_credit_input_do_submit"><![CDATA[Submit]]></string>
+    <string name="_bx_credits_form_credit_input_sys_do_cancel"><![CDATA[Cancel]]></string>
+    <string name="_bx_credits_form_credit_input_do_cancel"><![CDATA[Cancel]]></string>
+
+
+    <!-- Pages -->
+    <string name="_bx_credits_page_title_sys_home"><![CDATA[Credits]]></string>
+    <string name="_bx_credits_page_title_home"><![CDATA[Credits]]></string>
+    <string name="_bx_credits_page_block_title_sys_bundles"><![CDATA[Credits]]></string>
+    <string name="_bx_credits_page_block_title_bundles"><![CDATA[Credits]]></string>
+    <string name="_bx_credits_page_title_sys_checkout"><![CDATA[Checkout]]></string>
+    <string name="_bx_credits_page_title_checkout"><![CDATA[Checkout]]></string>
+    <string name="_bx_credits_page_block_title_sys_checkout"><![CDATA[Checkout]]></string>
+    <string name="_bx_credits_page_block_title_checkout"><![CDATA[Checkout]]></string>
+    <string name="_bx_credits_page_title_sys_history_common"><![CDATA[My History]]></string>
+    <string name="_bx_credits_page_title_history_common"><![CDATA[History]]></string>
+    <string name="_bx_credits_page_block_title_sys_history_common"><![CDATA[My History]]></string>
+    <string name="_bx_credits_page_block_title_history_common"><![CDATA[History]]></string>    
+    <string name="_bx_credits_page_title_sys_history_administration"><![CDATA[All History]]></string>
+    <string name="_bx_credits_page_title_history_administration"><![CDATA[History]]></string>
+    <string name="_bx_credits_page_block_title_sys_history_administration"><![CDATA[All History]]></string>
+    <string name="_bx_credits_page_block_title_history_administration"><![CDATA[History]]></string>
+    <string name="_bx_credits_page_title_sys_orders_common"><![CDATA[My Orders]]></string>
+    <string name="_bx_credits_page_title_orders_common"><![CDATA[Orders]]></string>
+    <string name="_bx_credits_page_block_title_sys_orders_common_note"><![CDATA[Note]]></string>
+    <string name="_bx_credits_page_block_title_orders_common_note"><![CDATA[Note]]></string>
+    <string name="_bx_credits_page_block_content_orders_common_note"><![CDATA[The orders are for reference only.]]></string>
+    <string name="_bx_credits_page_block_title_sys_orders_common"><![CDATA[My Orders]]></string>
+    <string name="_bx_credits_page_block_title_orders_common"><![CDATA[Orders]]></string>
+    <string name="_bx_credits_page_title_sys_orders_administration"><![CDATA[All Orders]]></string>
+    <string name="_bx_credits_page_title_orders_administration"><![CDATA[Orders]]></string>
+    <string name="_bx_credits_page_block_title_sys_orders_administration"><![CDATA[All Orders]]></string>
+    <string name="_bx_credits_page_block_title_orders_administration"><![CDATA[Orders]]></string>
+
+
+    <!-- Menus -->
+    <string name="_bx_credits_menu_item_title_system_credits"><![CDATA[Credits]]></string>
+    <string name="_bx_credits_menu_item_title_credits"><![CDATA[Credits]]></string>
+    <string name="_bx_credits_menu_item_title_system_history"><![CDATA[Balance]]></string>
+    <string name="_bx_credits_menu_item_title_history"><![CDATA[{unit}{value}]]></string>
+    <string name="_bx_credits_menu_item_title_system_notifications"><![CDATA[Balance]]></string>
+    <string name="_bx_credits_menu_item_title_notifications"><![CDATA[{value}]]></string>
+    <string name="_bx_credits_menu_title_submenu"><![CDATA[Credits Submenu]]></string>
+    <string name="_bx_credits_menu_set_title_submenu"><![CDATA[Credits Submenu]]></string>
+    <string name="_bx_credits_menu_item_title_system_home"><![CDATA[Home]]></string>
+    <string name="_bx_credits_menu_item_title_home"><![CDATA[Home]]></string>
+    <string name="_bx_credits_menu_item_title_system_admt_credits"><![CDATA[Credits]]></string>
+    <string name="_bx_credits_menu_item_title_admt_credits"><![CDATA[Credits]]></string>
+    <string name="_bx_credits_menu_item_title_bundles"><![CDATA[Bundles]]></string>
+    <string name="_bx_credits_menu_item_title_system_manage"><![CDATA[Credits]]></string>
+    <string name="_bx_credits_menu_item_title_manage"><![CDATA[Credits]]></string>
+    <string name="_bx_credits_menu_title_manage_submenu"><![CDATA[Orders Submenu]]></string>
+    <string name="_bx_credits_menu_set_title_manage_submenu"><![CDATA[Orders Submenu]]></string>
+    <string name="_bx_credits_menu_item_title_system_orders_administration"><![CDATA[All Orders]]></string>
+    <string name="_bx_credits_menu_item_title_orders_administration"><![CDATA[All Orders]]></string>
+    <string name="_bx_credits_menu_item_title_system_orders_common"><![CDATA[My Orders]]></string>
+    <string name="_bx_credits_menu_item_title_orders_common"><![CDATA[My Orders]]></string>
+    <string name="_bx_credits_menu_item_title_system_history_administration"><![CDATA[All History]]></string>
+    <string name="_bx_credits_menu_item_title_history_administration"><![CDATA[All History]]></string>
+    <string name="_bx_credits_menu_item_title_system_history_common"><![CDATA[My History]]></string>
+    <string name="_bx_credits_menu_item_title_history_common"><![CDATA[My History]]></string>
+
+
+    <!-- Grids -->
+    <string name="_bx_credits_grid_column_title_name"><![CDATA[Name]]></string>
+    <string name="_bx_credits_grid_column_title_title"><![CDATA[Title]]></string>
+    <string name="_bx_credits_grid_column_title_amount"><![CDATA[Amount]]></string>
+    <string name="_bx_credits_grid_column_title_bonus"><![CDATA[Bonus]]></string>
+    <string name="_bx_credits_grid_column_title_price"><![CDATA[Price]]></string>
+    <string name="_bx_credits_grid_action_title_add"><![CDATA[Add]]></string>
+    <string name="_bx_credits_grid_action_title_edit"><![CDATA[Edit]]></string>
+    <string name="_bx_credits_grid_action_title_delete"><![CDATA[Delete]]></string>
+    <string name="_bx_credits_grid_popup_title_add_bundle"><![CDATA[Add Bundle]]></string>
+    <string name="_bx_credits_grid_popup_title_edit_bundle"><![CDATA[Edit '{0}' Bundle]]></string>
+
+    <string name="_bx_credits_grid_column_title_htr_pid"><![CDATA[Profile]]></string>
+    <string name="_bx_credits_grid_column_title_htr_first_pid"><![CDATA[Profile 1]]></string>
+    <string name="_bx_credits_grid_column_title_htr_second_pid"><![CDATA[Profile 2]]></string>
+    <string name="_bx_credits_grid_column_title_htr_amount"><![CDATA[Amount]]></string>
+    <string name="_bx_credits_grid_column_title_htr_order"><![CDATA[Order]]></string>
+    <string name="_bx_credits_grid_column_title_htr_direction"><![CDATA[Direction]]></string>
+    <string name="_bx_credits_grid_column_title_htr_info"><![CDATA[Notice]]></string>
+    <string name="_bx_credits_grid_column_title_htr_date"><![CDATA[Date]]></string>
+    <string name="_bx_credits_grid_action_title_htr_grant"><![CDATA[Grant]]></string>
+    <string name="_bx_credits_grid_action_title_htr_withdraw_confirm"><![CDATA[Confirm withdraw]]></string>
+    <string name="_bx_credits_grid_action_title_htr_withdraw_request"><![CDATA[Request withdraw]]></string>
+    <string name="_bx_credits_grid_popup_title_htr_grant"><![CDATA[Grant]]></string>
+    <string name="_bx_credits_grid_popup_title_htr_withdraw_confirm"><![CDATA[Confirm withdraw]]></string>
+    <string name="_bx_credits_grid_popup_title_htr_withdraw_request"><![CDATA[Request withdraw]]></string>
+
+    <string name="_bx_credits_grid_column_title_ord_profile_id"><![CDATA[Profile]]></string>
+    <string name="_bx_credits_grid_column_title_ord_bundle"><![CDATA[Bundle]]></string>
+    <string name="_bx_credits_grid_column_title_ord_transaction"><![CDATA[Transaction]]></string>
+    <string name="_bx_credits_grid_column_title_ord_type"><![CDATA[Type]]></string>
+    <string name="_bx_credits_grid_column_value_ord_type_single"><![CDATA[Single]]></string>
+    <string name="_bx_credits_grid_column_value_ord_type_recurring"><![CDATA[Recurring]]></string>
+    <string name="_bx_credits_grid_column_title_ord_added"><![CDATA[Added]]></string>
+    <string name="_bx_credits_grid_column_title_ord_expired"><![CDATA[Expires]]></string>
+
+
+    <!-- Email templates -->
+    <string name="_bx_credits_et_txt_name_granted"><![CDATA[Credits granted.]]></string>
+    <string name="_bx_credits_et_txt_subject_granted"><![CDATA[You're granted {amount} credits.]]></string>
+    <string name="_bx_credits_et_txt_body_granted"><![CDATA[{email_header}
+<p>Hello, {profile_name}.</p>
+<p>You're granted <b>{amount}</b> credits.</p>
+<p>{message}</p>
+{email_footer}]]></string>
+    <string name="_bx_credits_et_txt_name_purchased"><![CDATA[Credits purchased.]]></string>
+    <string name="_bx_credits_et_txt_subject_purchased"><![CDATA[You've purchased {bundle_title} credits bundle.]]></string>
+    <string name="_bx_credits_et_txt_body_purchased"><![CDATA[{email_header}
+<p>Hello, {client_name}.</p>
+<p>You've purchased <a href="{bundle_url}">{bundle_title}</a> credits bundle.<br />Your order is <b>{order}</b>.</p>
+<p>{notes}</p>
+{email_footer}]]></string>
+    <string name="_bx_credits_et_txt_name_in"><![CDATA[Credits in.]]></string>
+    <string name="_bx_credits_et_txt_subject_in"><![CDATA[Credits in.]]></string>
+    <string name="_bx_credits_et_txt_body_in"><![CDATA[{email_header}
+<p>Hello, {profile_name}.</p>
+<p>You've received <b>{amount}</b> credits from {second_profile_name}.</p>
+{email_footer}]]></string>
+    <string name="_bx_credits_et_txt_name_out"><![CDATA[Credits out.]]></string>
+    <string name="_bx_credits_et_txt_subject_out"><![CDATA[Credits out.]]></string>
+    <string name="_bx_credits_et_txt_body_out"><![CDATA[{email_header}
+<p>Hello, {profile_name}.</p>
+<p>You've sent <b>{amount}</b> credits to {second_profile_name}.</p>
+{email_footer}]]></string>
+    <string name="_bx_credits_et_txt_name_withdraw_requested"><![CDATA[Withdraw request.]]></string>
+    <string name="_bx_credits_et_txt_subject_withdraw_requested"><![CDATA[Withdraw request.]]></string>
+    <string name="_bx_credits_et_txt_body_withdraw_requested"><![CDATA[{email_header}
+<p><a href="{profile_link}">{profile_name}</a> requested to withdraw <b>{amount}</b> credits from his/her balance.</p>
+<p>Current withdraw conversion rate is <b>{rate}</b></p>
+<p>Withdrawal can be confirmed <a href="{confirm_url}">here</a>.</p>
+<p>Notes from <b>{profile_name}</b>:<br />{message}</p>
+{email_footer}]]></string>
+    <string name="_bx_credits_et_txt_name_withdraw_sent"><![CDATA[Withdraw was sent.]]></string>
+    <string name="_bx_credits_et_txt_subject_withdraw_sent"><![CDATA[Withdraw was sent.]]></string>
+    <string name="_bx_credits_et_txt_body_withdraw_sent"><![CDATA[{email_header}
+<p>Hello, {profile_name}.</p>
+<p>The requested amount of credits (<b>{amount}</b>) was withdrawn to you.</p>
+<p>{message}</p>
+{email_footer}]]></string>
+
+
+    <!-- Other -->
+    <string name="_bx_credits_txt_sample_single"><![CDATA[credit]]></string>
+    <string name="_bx_credits_txt_sample_single_with_article"><![CDATA[a credit]]></string>
+    <string name="_bx_credits_txt_for_free"><![CDATA[for Free]]></string>
+    <string name="_bx_credits_txt_n_plus_m_for_free"><![CDATA[{0} (+{1} for free)]]></string>
+    <string name="_bx_credits_txt_purchase"><![CDATA[Purchase]]></string>
+    <string name="_bx_credits_txt_never"><![CDATA[never]]></string>
+    <string name="_bx_credits_txt_direction_out"><![CDATA[sent to]]></string>
+    <string name="_bx_credits_txt_direction_in"><![CDATA[got from]]></string>
+    <string name="_bx_credits_txt_purchased_note"><![CDATA[Contact <a href="{0}">{1}</a> if you have any questions or need support.]]></string>
+    <string name="_bx_credits_txt_history_info_grant"><![CDATA[Grant]]></string>
+    <string name="_bx_credits_txt_history_info_purchase"><![CDATA[Bundle purchase]]></string>
+    <string name="_bx_credits_txt_history_info_checkout"><![CDATA[Profile to profile checkout]]></string>
+    <string name="_bx_credits_txt_history_info_withdraw"><![CDATA[Withdraw by request]]></string>
+    <string name="_bx_credits_txt_history_info_service"><![CDATA[Artificially initiated transfer]]></string>
+    <string name="_bx_credits_txt_history_info_refund"><![CDATA[Refund]]></string>
+
+    <string name="_bx_credits_msg_empty_author"><![CDATA['Main seller' is empty. You need to mark some profile as 'Main seller' in Settings of currently active Payment app.]]></string>
+    <string name="_bx_credits_msg_action_performed"><![CDATA[The action was performed successfully.]]></string>
+    <string name="_bx_credits_err_profile_not_found"><![CDATA[Profile wasn't found.]]></string>
+    <string name="_bx_credits_err_login_required"><![CDATA[Login required.]]></string>
+    <string name="_bx_credits_err_low_balance"><![CDATA[Low balance.]]></string>
+    <string name="_bx_credits_err_cannot_update_balance"><![CDATA[Cannot update balance.]]></string>
+    <string name="_bx_credits_err_cannot_send"><![CDATA[Cannot send message. Please report.]]></string>
+    <string name="_bx_credits_err_cannot_perform_action"><![CDATA[Cannot perform the action. Please report.]]></string>
+
+
+    <!-- Checkout process -->
+    <string name="_bx_credits_txt_checkout"><![CDATA[Checkout]]></string>
+    <string name="_bx_credits_txt_checkout_to"><![CDATA[Pay to {0} for:]]></string>
+    <string name="_bx_credits_txt_checkout_price_money"><![CDATA[Price:]]></string>
+    <string name="_bx_credits_txt_checkout_price_credits"><![CDATA[In Credits:]]></string>
+    <string name="_bx_credits_txt_checkout_rate"><![CDATA[Rate:]]></string>
+    <string name="_bx_credits_txt_checkout_qt"><![CDATA[qt.]]></string>
+
+    <!-- Subscribe process -->
+    <string name="_bx_credits_txt_subscribe"><![CDATA[Subscribe]]></string>
+    <string name="_bx_credits_txt_subscribe_for"><![CDATA[Subscribe for:]]></string>    
+    <string name="_bx_credits_txt_subscribe_period_mask"><![CDATA[{0} {1}]]></string>
+    <string name="_bx_credits_txt_subscribe_period_unit_year"><![CDATA[yr.]]></string>
+    <string name="_bx_credits_txt_subscribe_period_unit_month"><![CDATA[mo.]]></string>
+    <string name="_bx_credits_txt_subscribe_period_unit_week"><![CDATA[wk.]]></string>
+    <string name="_bx_credits_txt_subscribe_period_unit_day"><![CDATA[d.]]></string>
+    <string name="_bx_credits_txt_subscribe_period_unit_hour"><![CDATA[hr.]]></string>
+    <string name="_bx_credits_txt_subscribe_period_unit_minute"><![CDATA[min.]]></string>
+    <string name="_bx_credits_txt_subscribe_trial"><![CDATA[Trial:]]></string>
+    <string name="_bx_credits_txt_subscribe_trial_mask"><![CDATA[{0} {1}]]></string>
+
+    <string name="_bx_credits_err_unknown_buyer"><![CDATA[Login required.]]></string>
+    <string name="_bx_credits_err_unknown_seller"><![CDATA[Unknown seller.]]></string>
+    <string name="_bx_credits_err_incorrect_data"><![CDATA[Incorrect input data. Please report.]]></string>
+</resources>

+ 4 - 0
modules/boonex/credits/updates/12.0.0_12.0.1/source/template/css/withdraw.css

@@ -0,0 +1,4 @@
+/*--- Profile Auto Complete ---*/
+.ui-autocomplete.ui-front {
+    z-index: 10001;
+}

+ 51 - 0
modules/boonex/developer/updates/12.0.0_12.0.1/install/config.php

@@ -0,0 +1,51 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'title' => 'Developer',
+    'version_from' => '12.0.0',
+    'version_to' => '12.0.1',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '12.1.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/developer/updates/update_12.0.0_12.0.1/',
+    'home_uri' => 'developer_update_1200_1201',
+
+    'module_dir' => 'boonex/developer/',
+    'module_uri' => 'developer',
+
+    'db_prefix' => 'bx_dev_',
+    'class_prefix' => 'BxDev',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_files' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'BoonEx Developer',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

+ 13 - 0
modules/boonex/developer/updates/12.0.0_12.0.1/install/installer.php

@@ -0,0 +1,13 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+class BxDevUpdater extends BxDolStudioUpdater
+{
+    function __construct($aConfig)
+    {
+        parent::__construct($aConfig);
+    }
+}

+ 36 - 0
modules/boonex/developer/updates/12.0.0_12.0.1/install/langs/en.xml

@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources name="en" flag="gb" title="English">
+	<string_add name="_bx_dev_bp_txt_sys_block_async"><![CDATA[Asynchronous Mode]]></string_add>
+    <string_add name="_bx_dev_bp_txt_block_async"><![CDATA[Asynchronous Mode]]></string_add>
+    <string_add name="_bx_dev_bp_txt_sys_block_submenu"><![CDATA[Block submenu]]></string_add>
+    <string_add name="_bx_dev_bp_txt_block_submenu"><![CDATA[Block submenu]]></string_add>
+    <string_add name="_bx_dev_bp_txt_sys_block_tabs"><![CDATA[Use 'tabs']]></string_add>
+    <string_add name="_bx_dev_bp_txt_block_tabs"><![CDATA[Use 'tabs' based block submenu]]></string_add>
+    <string_add name="_bx_dev_bp_txt_sys_block_hidden_on"><![CDATA[Hidden on]]></string_add>
+    <string_add name="_bx_dev_bp_txt_block_hidden_on"><![CDATA[Hidden on]]></string_add>
+    <string_add name="_bx_dev_bp_txt_block_hidden_on_phone"><![CDATA[phone]]></string_add>
+    <string_add name="_bx_dev_bp_txt_block_hidden_on_tablet"><![CDATA[tablet]]></string_add>
+    <string_add name="_bx_dev_bp_txt_block_hidden_on_desktop"><![CDATA[desktop]]></string_add>
+    <string_add name="_bx_dev_bp_txt_block_hidden_on_mobile"><![CDATA[mobile]]></string_add>
+	<string_add name="_bx_dev_pgt_btn_manage_gl_add_keys"><![CDATA[Add Keys]]></string_add>
+	<string_add name="_bx_dev_pgt_txt_keys_add_popup"><![CDATA[Add Keys]]></string_add>
+    <string_add name="_bx_dev_pgt_txt_keys_form"><![CDATA[Keys]]></string_add>
+    <string_add name="_bx_dev_pgt_txt_keys_display_add"><![CDATA[Add Keys]]></string_add>
+    <string_add name="_bx_dev_pgt_txt_sys_keys_language"><![CDATA[Language]]></string_add>
+    <string_add name="_bx_dev_pgt_txt_keys_language"><![CDATA[Language]]></string_add>
+    <string_add name="_bx_dev_pgt_inf_keys_language"><![CDATA[Leave empty to add in all available languages.]]></string_add>
+    <string_add name="_bx_dev_pgt_txt_sys_keys_category"><![CDATA[Ñategory]]></string_add>
+    <string_add name="_bx_dev_pgt_txt_keys_category"><![CDATA[Ñategory]]></string_add>
+    <string_add name="_bx_dev_pgt_err_keys_category"><![CDATA[You need to select a ñategory]]></string_add>
+    <string_add name="_bx_dev_pgt_txt_sys_keys_content"><![CDATA[Keys]]></string_add>
+    <string_add name="_bx_dev_pgt_txt_keys_content"><![CDATA[Keys]]></string_add>
+    <string_add name="_bx_dev_pgt_err_keys_content"><![CDATA[You need to enter a value here]]></string_add>
+    <string_add name="_bx_dev_pgt_inf_keys_content"><![CDATA[Use XML format, like the following:<br />&lt;string name="_key_first"&gt;&lt;![CDATA[First Value]]&gt;&lt;/string&gt;<br />&lt;string name="_key_second"&gt;&lt;![CDATA[Second Value]]&gt;&lt;/string&gt;]]></string_add>
+    <string_add name="_bx_dev_pgt_txt_sys_keys_replace"><![CDATA[Replace]]></string_add>
+    <string_add name="_bx_dev_pgt_txt_keys_replace"><![CDATA[Force replace if exists]]></string_add>
+    <string_add name="_bx_dev_pgt_btn_sys_keys_submit"><![CDATA[Submit]]></string_add>
+    <string_add name="_bx_dev_pgt_btn_keys_submit"><![CDATA[Submit]]></string_add>
+    <string_add name="_bx_dev_pgt_btn_sys_keys_cancel"><![CDATA[Cancel]]></string_add>
+    <string_add name="_bx_dev_pgt_btn_keys_cancel"><![CDATA[Cancel]]></string_add>
+    <string_add name="_bx_dev_pgt_msg_keys_added"><![CDATA[{0} keys were added]]></string_add>
+</resources>

+ 53 - 0
modules/boonex/developer/updates/12.0.0_12.0.1/install/sql/install.sql

@@ -0,0 +1,53 @@
+SET @sName = 'bx_developer';
+
+
+-- FORMS
+DELETE FROM `sys_form_inputs` WHERE `object`='bx_developer_bp_block' AND `name` IN ('async', 'submenu', 'tabs', 'hidden_on');
+INSERT INTO `sys_form_inputs` (`object`, `module`, `name`, `value`, `values`, `checked`, `type`, `caption_system`, `caption`, `info`, `required`, `collapsed`, `html`, `attrs`, `attrs_tr`, `attrs_wrapper`, `checker_func`, `checker_params`, `checker_error`, `db_pass`, `db_params`, `editable`, `deletable`) VALUES
+('bx_developer_bp_block', @sName, 'async', '', '', 0, 'select', '_bx_dev_bp_txt_sys_block_async', '_bx_dev_bp_txt_block_async', '', 0, 0, 0, '', '', '', '', '', '', 'Int', '', 0, 0),
+('bx_developer_bp_block', @sName, 'submenu', '', '', 0, 'select', '_bx_dev_bp_txt_sys_block_submenu', '_bx_dev_bp_txt_block_submenu', '', 0, 0, 0, '', '', '', '', '', '', 'Xss', '', 0, 0),
+('bx_developer_bp_block', @sName, 'tabs', '1', '', 0, 'switcher', '_bx_dev_bp_txt_sys_block_tabs', '_bx_dev_bp_txt_block_tabs', '', 0, 0, 0, '', '', '', '', '', '', 'Int', '', 0, 0),
+('bx_developer_bp_block', @sName, 'hidden_on', '', '', 0, 'select_multiple', '_bx_dev_bp_txt_sys_block_hidden_on', '_bx_dev_bp_txt_block_hidden_on', '', 0, 0, 0, '', '', '', '', '', '', 'Set', '', 0, 0);
+
+DELETE FROM `sys_form_display_inputs` WHERE `display_name`='bx_developer_bp_block_edit' AND `input_name` IN ('async', 'submenu', 'tabs', 'hidden_on');
+INSERT INTO `sys_form_display_inputs` (`display_name`, `input_name`, `visible_for_levels`, `active`, `order`) VALUES
+('bx_developer_bp_block_edit', 'async', 2147483647, 1, 7),
+('bx_developer_bp_block_edit', 'submenu', 2147483647, 1, 8),
+('bx_developer_bp_block_edit', 'tabs', 2147483647, 1, 9),
+('bx_developer_bp_block_edit', 'hidden_on', 2147483647, 1, 10);
+
+DELETE FROM `sys_objects_form` WHERE `object`='bx_developer_pgt_keys';
+INSERT INTO `sys_objects_form` (`object`, `module`, `title`, `action`, `form_attrs`, `submit_name`, `table`, `key`, `uri`, `uri_title`, `params`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES
+('bx_developer_pgt_keys', @sName, '_bx_dev_pgt_txt_keys_form', '', '', 'do_submit', 'sys_localization_keys', 'ID', '', '', '', 0, 1, 'BxDevFormView', 'modules/boonex/developer/classes/BxDevFormView.php');
+
+DELETE FROM `sys_form_displays` WHERE `object`='bx_developer_pgt_keys';
+INSERT INTO `sys_form_displays` (`display_name`, `module`, `object`, `title`, `view_mode`) VALUES
+('bx_developer_pgt_keys_add', @sName, 'bx_developer_pgt_keys', '_bx_dev_pgt_txt_keys_display_add', 0);
+
+DELETE FROM `sys_form_inputs` WHERE `object`='bx_developer_pgt_keys';
+INSERT INTO `sys_form_inputs` (`object`, `module`, `name`, `value`, `values`, `checked`, `type`, `caption_system`, `caption`, `info`, `required`, `collapsed`, `html`, `attrs`, `attrs_tr`, `attrs_wrapper`, `checker_func`, `checker_params`, `checker_error`, `db_pass`, `db_params`, `editable`, `deletable`) VALUES
+('bx_developer_pgt_keys', @sName, 'language', '', '', 0, 'select', '_bx_dev_pgt_txt_sys_keys_language', '_bx_dev_pgt_txt_keys_language', '_bx_dev_pgt_inf_keys_language', 0, 0, 0, '', '', '', '', '', '', 'Int', '', 0, 0),
+('bx_developer_pgt_keys', @sName, 'category', '', '', 0, 'select', '_bx_dev_pgt_txt_sys_keys_category', '_bx_dev_pgt_txt_keys_category', '', 1, 0, 0, '', '', '', 'Avail', '', '_bx_dev_pgt_err_keys_category', 'Int', '', 0, 0),
+('bx_developer_pgt_keys', @sName, 'content', '', '', 0, 'textarea', '_bx_dev_pgt_txt_sys_keys_content', '_bx_dev_pgt_txt_keys_content', '_bx_dev_pgt_inf_keys_content', 1, 0, 0, '', '', '', 'Avail', '', '_bx_dev_pgt_err_keys_content', 'Xss', '', 0, 0),
+('bx_developer_pgt_keys', @sName, 'replace', '1', '', 0, 'switcher', '_bx_dev_pgt_txt_sys_keys_replace', '_bx_dev_pgt_txt_keys_replace', '', 0, 0, 0, '', '', '', '', '', '', 'Int', '', 0, 0),
+('bx_developer_pgt_keys', @sName, 'controls', '', 'do_submit,do_cancel', 0, 'input_set', '', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
+('bx_developer_pgt_keys', @sName, 'do_submit', '_bx_dev_pgt_btn_keys_submit', '', 0, 'submit', '_bx_dev_pgt_btn_sys_keys_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
+('bx_developer_pgt_keys', @sName, 'do_cancel', '_bx_dev_pgt_btn_keys_cancel', '', 0, 'button', '_bx_dev_pgt_btn_sys_keys_cancel', '', '', 0, 0, 0, 'a:2:{s:7:"onclick";s:45:"$(''.bx-popup-applied:visible'').dolPopupHide()";s:5:"class";s:22:"bx-def-margin-sec-left";}', '', '', '', '', '', '', '', 0, 0);
+
+DELETE FROM `sys_form_display_inputs` WHERE `display_name`='bx_developer_pgt_keys_add';
+INSERT INTO `sys_form_display_inputs` (`display_name`, `input_name`, `visible_for_levels`, `active`, `order`) VALUES
+('bx_developer_pgt_keys_add', 'language', 2147483647, 1, 1),
+('bx_developer_pgt_keys_add', 'category', 2147483647, 1, 2),
+('bx_developer_pgt_keys_add', 'content', 2147483647, 1, 3),
+('bx_developer_pgt_keys_add', 'replace', 2147483647, 1, 4),
+('bx_developer_pgt_keys_add', 'controls', 2147483647, 1, 5),
+('bx_developer_pgt_keys_add', 'do_submit', 2147483647, 1, 6),
+('bx_developer_pgt_keys_add', 'do_cancel', 2147483647, 1, 7);
+
+
+-- GRIDS
+DELETE FROM `sys_grid_actions` WHERE `object`='bx_developer_pgt_manage' AND `type`='independent' AND `name`='add_keys';
+INSERT INTO `sys_grid_actions` (`object`, `type`, `name`, `title`, `icon`, `confirm`, `order`) VALUES
+('bx_developer_pgt_manage', 'independent', 'add_keys', '_bx_dev_pgt_btn_manage_gl_add_keys', '', 0, 0);
+
+

+ 468 - 0
modules/boonex/developer/updates/12.0.0_12.0.1/source/classes/BxDevBuilderPage.php

@@ -0,0 +1,468 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Developer Developer
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxDevBuilderPage extends BxTemplStudioBuilderPage
+{
+    protected $sActionPageExport = 'page_export';
+
+    protected $oModule;
+    protected $aParams;
+
+    function __construct($aParams)
+    {
+        parent::__construct(isset($aParams['type']) ? $aParams['type'] : '',  isset($aParams['page']) ? $aParams['page'] : '');
+
+        $this->aParams = $aParams;
+        $this->sBaseUrl = $this->aParams['url'];
+        $this->sTypeUrl = $this->sBaseUrl . '&bp_type=%s';
+        $this->sPageUrl = $this->sTypeUrl . '&bp_page=%s';
+
+        $this->oModule = BxDolModule::getInstance('bx_developer');
+
+        $this->oModule->_oTemplate->addStudioCss(array('builder_page.css'));
+    }
+
+    function getBlockPanelTop($aBlock)
+    {
+         return BxBaseStudioWidget::getBlockPanelTop(
+            array('panel_top' => $this->oModule->_oTemplate->parseHtmlByName('bp_block_panel_top.html', $this->_getTmplVarsBlockPanelTop()))
+        );
+    }
+
+    protected function actionPageCreate()
+    {
+    	$sFormObject = $this->oModule->_oConfig->getObject('form_bp_page');
+        $sFormDisplay = $this->oModule->_oConfig->getObject('form_display_bp_page_add');
+
+        $oForm = BxDolForm::getObjectInstance($sFormObject, $sFormDisplay, $this->oModule->_oTemplate);
+        $oForm->aFormAttrs['action'] = sprintf($this->sPageUrl, $this->sType, $this->sPage) . '&bp_action=' . $this->sActionPageCreate;
+        $oForm->aInputs['module']['values'] = array_merge(array('' => _t('_bx_dev_bp_txt_select_module')), BxDolStudioUtils::getModules());
+
+        $oForm->aInputs['layout_id']['values'] = array(
+            array('key' => '', 'value' => _t('_bx_dev_bp_txt_page_layout_id_select'))
+        );
+
+        $aLayouts = array();
+        $this->oDb->getLayouts(array('type' => 'all'), $aLayouts, false);
+        foreach($aLayouts as $aLayout)
+            $oForm->aInputs['layout_id']['values'][] = array('key' => $aLayout['id'], 'value' => _t($aLayout['title']));
+
+        $oForm->initChecker();
+        if($oForm->isSubmittedAndValid()) {
+            $sObject = $oForm->getCleanValue('object');
+            $sModule = $oForm->getCleanValue('module');
+
+            if(($iId = (int)$oForm->insert()) != 0)
+                return array('eval' => $this->getPageJsObject() . '.onCreatePage(\'' . $sModule . '\', \'' . $sObject . '\')');
+            else
+                return array('msg' => _t('_bx_dev_bp_err_page_create'));
+        }
+
+        $sContent = BxTemplStudioFunctions::getInstance()->popupBox($this->aHtmlIds['add_popup_id'], _t('_bx_dev_bp_txt_page_create_popup'), $this->oModule->_oTemplate->parseHtmlByName('bp_add_page.html', array(
+            'form_id' => $oForm->aFormAttrs['id'],
+            'form' => $oForm->getCode(true)
+        )));
+
+        return array('popup' => $sContent);
+    }
+
+    protected function actionPageExport()
+    {
+        $sContentInsert = $sContentDelete = "";
+
+        $aPage = $this->oDb->getPages(array('type' => 'by_object', 'value' => $this->sPage));
+        if(empty($aPage) || !is_array($aPage))
+            return array();
+
+        $sContentInsert .= ($this->oModule->_oDb->getQueryInsert('sys_objects_page', array($aPage), "Dumping data for '" . $aPage['object'] . "' page"));
+        $sContentDelete .= ($this->oModule->_oDb->getQueryDelete('sys_objects_page', 'object', array($aPage), "Deleting data for '" . $aPage['object'] . "' page"));
+
+        $aBlocks = array();
+        $this->oDb->getBlocks(array('type' => 'by_object', 'value' => $aPage['object']), $aBlocks, false);
+        $sContentInsert .= $this->oModule->_oDb->getQueryInsert('sys_pages_blocks', $aBlocks, false, array('id', 'name'));
+        $sContentDelete .= $this->oModule->_oDb->getQueryDelete('sys_pages_blocks', 'object', array($aPage), false);
+
+        $aForm = array(
+            'form_attrs' => array(),
+            'inputs' => array (
+                'insert' => array(
+                    'type' => 'textarea',
+                    'name' => 'insert',
+                    'caption' => _t('_bx_dev_bp_txt_page_export_insert'),
+                    'value' => $sContentInsert,
+                ),
+                'delete' => array(
+                    'type' => 'textarea',
+                    'name' => 'delete',
+                    'caption' => _t('_bx_dev_bp_txt_page_export_delete'),
+                    'value' => $sContentDelete,
+                ),
+                'done' => array (
+                    'type' => 'button',
+                    'name' => 'done',
+                    'value' => _t('_bx_dev_bp_btn_page_done'),
+                    'attrs' => array(
+                        'onclick' => "$('.bx-popup-applied:visible').dolPopupHide()",
+                    ),
+                )
+            )
+        );
+        $oForm = new BxTemplStudioFormView($aForm);
+
+        $sContent = BxTemplStudioFunctions::getInstance()->popupBox('bx-dev-bp-page-export-popup', _t('_bx_dev_bp_txt_page_export_popup', _t($aPage['title'])), $this->oModule->_oTemplate->parseHtmlByName('bp_export.html', array(
+            'content' => $oForm->getCode()
+        )));
+
+        return array('popup' => $sContent);
+    }
+
+    protected function actionBlockEdit()
+    {
+    	$sFormObject = $this->oModule->_oConfig->getObject('form_bp_block');
+        $sFormDisplay = $this->oModule->_oConfig->getObject('form_display_bp_block_edit');
+        
+        $iId = (int)bx_get('id');
+        if(!$iId)
+            return array();
+
+        $aBlock = array();
+        $this->oDb->getBlocks(array('type' => 'by_id', 'value' => $iId), $aBlock, false);
+        if(empty($aBlock) || !is_array($aBlock))
+            return array('msg' => _t('_bx_dev_bp_err_block_not_found'));
+
+        $oForm = BxDolForm::getObjectInstance($sFormObject, $sFormDisplay, $this->oModule->_oTemplate);
+
+        $this->onLoadBlock($oForm, $aBlock);
+
+        $oForm->initChecker($aBlock);
+        if($oForm->isSubmittedAndValid()) {
+            $this->onSaveBlock($oForm, $aBlock);
+
+            if($oForm->update($iId) !== false)
+                return array('eval' => $this->getPageJsObject() . '.onEditBlock(oData)');
+            else
+                return array('msg' => _t('_bx_dev_bp_err_block_edit'));
+        }
+
+        $sContent = BxTemplStudioFunctions::getInstance()->popupBox($this->aHtmlIds['edit_block_popup_id'], _t('_bx_dev_bp_txt_block_edit_popup', _t($aBlock['title'])), $this->oModule->_oTemplate->parseHtmlByName('bp_add_block.html', array(
+            'form_id' => $oForm->aFormAttrs['id'],
+            'form' => $oForm->getCode(true)
+        )));
+
+        return array('popup' => $sContent);
+    }
+
+    protected function actionBlockDelete()
+    {
+        $sJsObject = $this->getPageJsObject();
+        $iId = (int)bx_get('id');
+
+        $aBlock = array();
+        $this->oDb->getBlocks(array('type' => 'by_id', 'value' => $iId), $aBlock, false);
+        if(empty($aBlock) || !is_array($aBlock))
+            return array('msg' => _t('_bx_dev_bp_err_block_not_found'));
+
+        if(!$this->oDb->deleteBlocks(array('type' => 'by_id', 'value' => $iId)))
+            return array('msg' => _t('_bx_dev_bp_err_block_delete'));
+
+        $this->onBlockDelete($aBlock);
+        return array('eval' => $sJsObject . '.onDeleteBlock(' . $iId . ', oData)');
+    }
+
+    protected function getSettingsOptions($aPage = array(), $bCreate = true, $bInputsOnly = false)
+    {
+        $aForm = array(
+            'form_attrs' => array(
+                'id' => 'adm-bp-settings-seo',
+            ),
+            'params' => array (
+                'remove_form' => '1',
+                'csrf' => array(
+                    'disable' => true
+                )
+            ),
+            'inputs' => array(
+                'object'  => array(
+                    'type' => 'text',
+                    'name' => 'object',
+                    'caption' => _t('_bx_dev_bp_txt_page_object'),
+                    'info' => '',
+                    'value' => $this->aPageRebuild['object'],
+                    'required' => '',
+                    'attrs' => array(
+                        'disabled' => 'disabled'
+                    ),
+                )
+            )
+        );
+
+        $aForm['inputs'] += parent::getSettingsOptions($aPage, $bCreate, true);
+
+        $aForm['inputs']['title_system']['type'] = 'text';
+        $aForm['inputs']['title_system']['caption'] = _t('_bx_dev_bp_txt_page_title_system');
+        $aForm['inputs']['title']['type'] = 'text';
+
+        $aUri = array(
+            'uri'  => array(
+                'type' => 'text',
+                'name' => 'uri',
+                'caption' => _t('_bx_dev_bp_txt_page_uri'),
+                'info' => '',
+                'value' => $this->aPageRebuild['uri'],
+                'required' => '',
+                'db' => array (
+                    'pass' => 'Xss',
+                ),
+            )
+        );
+        $aForm['inputs'] = bx_array_insert_before($aUri, $aForm['inputs'], 'url');
+
+        $aForm['inputs']['url']['caption'] = _t('_bx_dev_bp_txt_page_url');
+        $aForm['inputs']['url']['value'] = isset($aPage['url']) ? $aPage['url'] : '';
+        $aForm['inputs']['url']['db'] = array (
+            'pass' => 'Xss',
+        );
+        unset($aForm['inputs']['url']['attrs']['disabled']);
+
+        $aForm['inputs']['deletable'] = array(
+            'type' => 'switcher',
+            'name' => 'deletable',
+            'caption' => _t('_bx_dev_bp_txt_page_deletable'),
+            'info' => '',
+            'value' => '1',
+            'checked' => (int)$this->aPageRebuild['deletable'] == 1,
+            'required' => '',
+            'db' => array (
+                'pass' => 'Int',
+            )
+        );
+        $aForm['inputs']['override_class_name'] = array(
+            'type' => 'text',
+            'name' => 'override_class_name',
+            'caption' => _t('_bx_dev_bp_txt_page_override_class_name'),
+            'info' => '',
+            'value' => $this->aPageRebuild['override_class_name'],
+            'required' => '0',
+            'db' => array (
+                'pass' => 'Xss',
+            )
+        );
+        $aForm['inputs']['override_class_file'] = array(
+            'type' => 'text',
+            'name' => 'override_class_file',
+            'caption' => _t('_bx_dev_bp_txt_page_override_class_file'),
+            'info' => '',
+            'value' => $this->aPageRebuild['override_class_file'],
+            'required' => '0',
+            'db' => array (
+                'pass' => 'Xss',
+            )
+        );
+
+        if($bInputsOnly)
+            return $aForm['inputs'];
+
+        $oForm = new BxTemplStudioFormView($aForm);
+        return $oForm->getCode();
+    }
+
+    protected function getSettingsCache($aPage = array(), $bCreate = true, $bInputsOnly = false)
+    {
+        $aForm = array(
+            'form_attrs' => array(
+                'id' => 'adm-bp-settings-cache',
+            ),
+            'params' => array (
+                'remove_form' => '1',
+                'csrf' => array(
+                    'disable' => true
+                )
+            ),
+            'inputs' => parent::getSettingsCache($aPage, $bCreate, true)
+        );
+
+        unset($aForm['inputs']['cache_lifetime']['attrs']);
+
+        $aForm['inputs']['cache_editable'] = array(
+            'type' => 'switcher',
+            'name' => 'cache_editable',
+            'caption' => _t('_bx_dev_bp_txt_page_cache_editable'),
+            'info' => '',
+            'value' => '1',
+            'checked' => (int)$this->aPageRebuild['cache_editable'] == 1,
+            'required' => '',
+            'db' => array (
+                'pass' => 'Int',
+            )
+        );
+
+        if($bInputsOnly)
+            return $aForm['inputs'];
+
+        $oForm = new BxTemplStudioFormView($aForm);
+        return $oForm->getCode();
+    }
+
+    protected function getBlockModule($aBlock)
+    {
+        return $aBlock['module'] != BX_DOL_STUDIO_BP_SKELETONS ? $aBlock['module'] : $this->aPageRebuild['module'];
+    }
+
+    protected function getBlockContent($aBlock)
+    {
+        $aFields = array();
+
+        switch($aBlock['type']) {
+            case BX_DOL_STUDIO_BP_BLOCK_SERVICE:
+                $aFields = array(
+                    'content' => array(
+                        'type' => 'textarea',
+                        'name' => 'content',
+                        'caption' => _t('_bx_dev_bp_txt_block_content_service'),
+                        'info' => '',
+                        'value' => $aBlock['content'],
+                        'required' => '0',
+                        'db' => array (
+                            'pass' => 'Xss',
+                        ),
+                    )
+                );
+                break;
+
+            case BX_DOL_STUDIO_BP_BLOCK_LANG:
+                $aFields = array(
+                    'content' => array(
+                        'type' => 'text',
+                        'name' => 'content',
+                        'caption' => _t('_bx_dev_bp_txt_block_content_lang'),
+                        'info' => _t('_bx_dev_bp_dsc_block_content_lang'),
+                        'value' => $aBlock['content'],
+                        'required' => '0',
+                        'db' => array (
+                            'pass' => 'Xss',
+                        ),
+                    ),
+                );
+                break;
+
+            default:
+                $aFields = parent::getBlockContent($aBlock);
+                break;
+        }
+
+        return $aFields;
+    }
+
+    protected function getBlocks($sModule)
+    {
+        $aBlocks = parent::getBlocks($sModule);
+
+        if($sModule == BX_DOL_STUDIO_BP_SKELETONS) {
+            $aBlock = array();
+            $this->oDb->getBlocks(array('type' => 'skeleton_by_type', 'value' => 'service'), $aBlock, false);
+            if(!empty($aBlock) && is_array($aBlock))
+                $aBlocks[] = $aBlock;
+        }
+
+        return $aBlocks;
+    }
+
+    protected function onLoadBlock(&$oForm, &$aBlock)
+    {
+        $oForm->aFormAttrs['action'] = sprintf($this->sPageUrl, $this->sType, $this->sPage) . '&bp_action=' . $this->sActionBlockEdit;
+        $oForm->aInputs['module']['values'] = array_merge(array('' => _t('_bx_dev_bp_txt_select_module')), BxDolStudioUtils::getModules());
+
+        $aDBoxes = array();
+        $this->oDb->getDesignBoxes(array('type' => 'ordered'), $aDBoxes, false);
+        foreach($aDBoxes as $aDBox)
+            $oForm->aInputs['designbox_id']['values'][] = array('key' => $this->sSelectKeyPrefix . $aDBox['id'], 'value' => _t($aDBox['title']));
+
+        $aContentPlaceholders = $this->oDb->getContentPlaceholders();
+        $oForm->aInputs['async']['values'] = array(
+            array('key' => 0, 'value' => _t('_sys_no_async'))
+        );
+        foreach ($aContentPlaceholders as $iKey => $sTitle)
+            $oForm->aInputs['async']['values'][] = array('key' => $iKey, 'value' => _t($sTitle));
+
+        $oForm->aInputs['hidden_on']['values'] = array(
+            BX_DB_HIDDEN_PHONE => _t('_bx_dev_bp_txt_block_hidden_on_phone'),
+            BX_DB_HIDDEN_TABLET => _t('_bx_dev_bp_txt_block_hidden_on_tablet'),
+            BX_DB_HIDDEN_DESKTOP => _t('_bx_dev_bp_txt_block_hidden_on_desktop'),
+            BX_DB_HIDDEN_MOBILE => _t('_bx_dev_bp_txt_block_hidden_on_mobile')
+        );
+
+        $aSubmenus = $this->oDb->getBlockSubmenus();
+        $oForm->aInputs['submenu']['values'] = array(
+            array('key' => '', 'value' => _t('_sys_no_menu'))
+        );
+        foreach ($aSubmenus as $sObject => $sTitle)
+            $oForm->aInputs['submenu']['values'][] = array('key' => $sObject, 'value' => _t($sTitle));
+
+        $oForm->aInputs['visible_for']['value'] = $aBlock['visible_for_levels'] == BX_DOL_INT_MAX ? BX_DOL_STUDIO_VISIBLE_ALL : BX_DOL_STUDIO_VISIBLE_SELECTED;
+        $oForm->aInputs['visible_for']['values'] = array(
+            array('key' => BX_DOL_STUDIO_VISIBLE_ALL, 'value' => _t('_bx_dev_bp_txt_block_visible_for_all')),
+            array('key' => BX_DOL_STUDIO_VISIBLE_SELECTED, 'value' => _t('_bx_dev_bp_txt_block_visible_for_selected')),
+        );
+        $oForm->aInputs['visible_for']['attrs']['onchange'] = $this->getPageJsObject() . '.onChangeVisibleFor(this)';
+
+        $oForm->aInputs['visible_for_levels']['tr_attrs']['style'] = $aBlock['visible_for_levels'] == BX_DOL_INT_MAX ? 'display:none' : '';
+        BxDolStudioUtils::getVisibilityValues($aBlock['visible_for_levels'], $oForm->aInputs['visible_for_levels']['values'], $oForm->aInputs['visible_for_levels']['value']);
+        $aBlock['visible_for_levels'] = $oForm->aInputs['visible_for_levels']['value'];
+
+        $oForm->aInputs = $this->addInArray($oForm->aInputs, 'visible_for_levels', $this->getBlockContent($aBlock));
+
+        $oForm->aInputs['controls'][0]['value'] = _t('_bx_dev_bp_btn_block_save');
+        $oForm->aInputs['controls'][2]['attrs']['onclick'] = $this->getPageJsObject() . ".deleteBlock(" . $aBlock['id'] . ")";
+
+        if($aBlock['type'] == BX_DOL_STUDIO_BP_BLOCK_SERVICE)
+            $aBlock['content'] = BxDevFunctions::unserializeString($aBlock['content']);
+
+        $aBlock['designbox_id'] = $this->sSelectKeyPrefix . $aBlock['designbox_id'];
+    }
+
+    protected function onSaveBlock(&$oForm, &$aBlock)
+    {
+        parent::onSaveBlock($oForm, $aBlock);
+
+        if($aBlock['type'] == BX_DOL_STUDIO_BP_BLOCK_SERVICE && isset($oForm->aInputs['content']))
+            $this->onSaveBlockService($oForm, $aBlock);
+    }
+
+    protected function onSaveBlockLang(&$oForm, &$aBlock)
+    {
+        $sValue = $oForm->getCleanValue('content');
+        BxDolForm::setSubmittedValue('content', $sValue, $oForm->aFormAttrs['method']);
+    }
+
+    protected function onSaveBlockService(&$oForm, &$aBlock)
+    {
+        $sValue = $oForm->getCleanValue('content');
+        $sValue = BxDevFunctions::serializeString($sValue);
+        BxDolForm::setSubmittedValue('content', $sValue, $oForm->aFormAttrs['method']);
+    }
+
+    protected function _getTmplVarsBlockPanelTopActions()
+    {
+        $sJsObject = $this->getPageJsObject();
+
+        $oPermalinks = BxDolPermalinks::getInstance();
+
+        return array(
+            'js_object' => $sJsObject,
+            'url_view' => BX_DOL_URL_ROOT . $oPermalinks->permalink($this->aPageRebuild['url']),
+            'action_page_export' => $this->sActionPageExport,
+            'action_page_edit' => $this->sActionPageEdit,
+            'action_block_create' => $this->sActionBlockCreate,
+        );
+    }
+}
+
+/** @} */

+ 115 - 0
modules/boonex/developer/updates/12.0.0_12.0.1/source/classes/BxDevConfig.php

@@ -0,0 +1,115 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Developer Developer
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxDevConfig extends BxBaseModGeneralConfig
+{
+    protected $aJsClasses;
+    protected $aJsObjects;
+    protected $sAnimationEffect;
+    protected $iAnimationSpeed;
+
+    function __construct($aModule)
+    {
+        parent::__construct($aModule);
+
+        $this->_aObjects = array(
+            //--- Forms builder grids.
+            'grid_forms' => $this->_sName . '_forms',
+            'grid_forms_displays' => $this->_sName . '_forms_displays',
+            'grid_forms_fields' => $this->_sName . '_forms_fields',
+            'grid_forms_pre_lists' => $this->_sName . '_forms_pre_lists',
+            'grid_forms_pre_values' => $this->_sName . '_forms_pre_values',
+            'grid_search_forms' => $this->_sName . '_search_forms',
+            'grid_search_forms_fields' => $this->_sName . '_search_forms_fields',
+
+            //--- Forms builder forms.
+            'form_forms_form' => $this->_sName . '_forms_form',
+            'form_display_forms_form_add' => $this->_sName . '_forms_form_add',
+            'form_display_forms_form_edit' => $this->_sName . '_forms_form_edit',
+            'form_forms_display' => $this->_sName . '_forms_display',
+            'form_display_forms_display_add' => $this->_sName . '_forms_display_add',
+            'form_display_forms_display_edit' => $this->_sName . '_forms_display_edit',
+            'form_forms_prelist' => $this->_sName . '_forms_prelist',
+            'form_display_forms_prelist_add' => $this->_sName . '_forms_prelist_add',
+            'form_display_forms_prelist_edit' => $this->_sName . '_forms_prelist_edit',
+            'form_forms_prevalue' => $this->_sName . '_forms_prevalue',
+            'form_display_forms_prevalue_add' => $this->_sName . '_forms_prevalue_add',
+            'form_display_forms_prevalue_edit' => $this->_sName . '_forms_prevalue_edit',
+            'form_forms_search_form' => $this->_sName . '_forms_search_form',
+            'form_display_forms_search_form_add' => $this->_sName . '_forms_search_form_add',
+            'form_display_forms_search_form_edit' => $this->_sName . '_forms_search_form_edit',
+            'form_forms_search_fields' => $this->_sName . '_forms_search_fields',
+            'form_display_forms_search_fields_edit' => $this->_sName . '_forms_search_fields_edit',
+
+            //--- Navigation builder grids.
+            'grid_nav_menus' => $this->_sName . '_nav_menus',
+            'grid_nav_sets' => $this->_sName . '_nav_sets',
+            'grid_nav_items' => $this->_sName . '_nav_items',
+
+            //--- Navigation builder forms.
+            'form_nav_menu' => $this->_sName . '_nav_menu',
+            'form_display_nav_menu_add' => $this->_sName . '_nav_menu_add',
+            'form_display_nav_menu_edit' => $this->_sName . '_nav_menu_edit',        
+            'form_nav_set' => $this->_sName . '_nav_set',
+            'form_display_nav_set_add' => $this->_sName . '_nav_set_add',
+            'form_display_nav_set_edit' => $this->_sName . '_nav_set_edit',
+            'form_nav_item' => $this->_sName . '_nav_item',
+            'form_display_nav_item_add' => $this->_sName . '_nav_item_add',
+            'form_display_nav_item_edit' => $this->_sName . '_nav_item_edit',
+
+            //--- Pages builder forms.
+            'form_bp_page' => $this->_sName . '_bp_page',
+            'form_display_bp_page_add' => $this->_sName . '_bp_page_add',
+            'form_bp_block' => $this->_sName . '_bp_block',
+            'form_display_bp_block_edit' => $this->_sName . '_bp_block_edit',
+
+            //--- Polyglot grids.
+            'grid_pgt_manage' => $this->_sName . '_pgt_manage',
+            
+            //--- Polyglot forms.
+            'form_pgt_keys' => $this->_sName . '_pgt_keys',
+            'form_display_pgt_keys_add' => $this->_sName . '_pgt_keys_add'
+        );
+
+        $this->aJsClasses = array('polyglot' => 'BxDevPolyglot');
+        $this->aJsObjects = array('polyglot' => 'oBxDevPolyglot');
+        $this->sAnimationEffect = 'fade';
+        $this->iAnimationSpeed = 'slow';
+    }
+
+    function getJsClass($sType = 'main')
+    {
+        if(empty($sType))
+            return $this->aJsClasses;
+
+        return $this->aJsClasses[$sType];
+    }
+
+    function getJsObject($sType = 'main')
+    {
+        if(empty($sType))
+            return $this->aJsObjects;
+
+        return $this->aJsObjects[$sType];
+    }
+
+    function getAnimationEffect()
+    {
+        return $this->sAnimationEffect;
+    }
+
+    function getAnimationSpeed()
+    {
+        return $this->iAnimationSpeed;
+    }
+}
+
+/** @} */

+ 67 - 0
modules/boonex/developer/updates/12.0.0_12.0.1/source/classes/BxDevDb.php

@@ -0,0 +1,67 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Developer Developer
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxDevDb extends BxDolModuleDb
+{
+    function __construct(&$oConfig)
+    {
+        parent::__construct($oConfig);
+    }
+
+    function getQueryInsert($sTable, $aItems, $mixedComment = false, $aExclude = array('id'))
+    {
+        $bFirst = true;
+        $sContent = $sComment = "";
+        foreach($aItems as $aItem) {
+            foreach($aExclude as $sKey)
+                if(isset($aItem[$sKey]))
+                    unset($aItem[$sKey]);
+
+            $aKeys = array_keys($aItem);
+            $aValues = array_values($aItem);
+            $iValues = count($aValues);
+
+            if($bFirst) {
+                $sContent .= "INSERT INTO `" . $sTable . "`(`" . implode("`, `", $aKeys) . "`) VALUES \n";
+                $bFirst = false;
+            }
+
+            $sSql = "(" . implode(", ", array_fill(0, $iValues, "?")) . "),\n";            
+            $sSql = call_user_func_array(array($this, 'prepareAsString'), array_merge(array($sSql), $aValues));
+
+            $sContent .= $sSql;
+        }
+        $sContent = substr($sContent, 0, -2) . ";\n\n";
+
+        if($mixedComment === true || (is_string($mixedComment) && $mixedComment != ''))
+            $sComment = "--\n-- " . ($mixedComment === true ? "Dumping data for table `" . $sTable . "`" : $mixedComment) . "\n--\n";
+
+        return $sComment . $sContent;
+    }
+
+    function getQueryDelete($sTable, $sKey, $aItems, $mixedComment = false)
+    {
+        $sContent = $sComment = "";
+        foreach($aItems as $aItem)
+            if(isset($aItem[$sKey])) {
+                $sSql = "DELETE FROM `" . $sTable . "` WHERE `" . $sKey . "`=?;\n";
+                $sContent .= call_user_func_array(array($this, 'prepareAsString'), array($sSql, $aItem[$sKey]));
+            }
+        $sContent .= "\n";
+
+        if($mixedComment === true || (is_string($mixedComment) && $mixedComment != ''))
+            $sComment = "--\n-- " . ($mixedComment === true ? "Delete data from table `" . $sTable . "`" : $mixedComment) . "\n--\n";
+
+        return $sComment . $sContent;
+    }
+}
+
+/** @} */

Некоторые файлы не были показаны из-за большого количества измененных файлов