Ver Fonte

Modules updates.

AntonLV há 5 anos atrás
pai
commit
2111c3d7ff
100 ficheiros alterados com 14949 adições e 2 exclusões
  1. 1 1
      modules/boonex/developer/updates/12.0.0_12.0.1/install/langs/en.xml
  2. 1 1
      modules/boonex/developer/updates/12.0.0_12.0.1/source/install/langs/en.xml
  3. 51 0
      modules/boonex/files/updates/12.0.1_12.0.2/install/config.php
  4. 13 0
      modules/boonex/files/updates/12.0.1_12.0.2/install/installer.php
  5. 10 0
      modules/boonex/files/updates/12.0.1_12.0.2/install/langs/en.xml
  6. 15 0
      modules/boonex/files/updates/12.0.1_12.0.2/install/sql/enable.sql
  7. 10 0
      modules/boonex/files/updates/12.0.1_12.0.2/install/sql/install.sql
  8. 33 0
      modules/boonex/files/updates/12.0.1_12.0.2/source/classes/BxFilesAlertsResponse.php
  9. 164 0
      modules/boonex/files/updates/12.0.1_12.0.2/source/classes/BxFilesBulkDownloader.php
  10. 196 0
      modules/boonex/files/updates/12.0.1_12.0.2/source/classes/BxFilesConfig.php
  11. 21 0
      modules/boonex/files/updates/12.0.1_12.0.2/source/classes/BxFilesCronProcessData.php
  12. 260 0
      modules/boonex/files/updates/12.0.1_12.0.2/source/classes/BxFilesDb.php
  13. 32 0
      modules/boonex/files/updates/12.0.1_12.0.2/source/classes/BxFilesMenuSnippetMeta.php
  14. 57 0
      modules/boonex/files/updates/12.0.1_12.0.2/source/classes/BxFilesMenuView.php
  15. 607 0
      modules/boonex/files/updates/12.0.1_12.0.2/source/classes/BxFilesModule.php
  16. 532 0
      modules/boonex/files/updates/12.0.1_12.0.2/source/classes/BxFilesSearchResult.php
  17. 218 0
      modules/boonex/files/updates/12.0.1_12.0.2/source/classes/BxFilesTemplate.php
  18. 135 0
      modules/boonex/files/updates/12.0.1_12.0.2/source/install/config.php
  19. 302 0
      modules/boonex/files/updates/12.0.1_12.0.2/source/install/langs/en.xml
  20. 501 0
      modules/boonex/files/updates/12.0.1_12.0.2/source/install/sql/enable.sql
  21. 368 0
      modules/boonex/files/updates/12.0.1_12.0.2/source/install/sql/install.sql
  22. 56 0
      modules/boonex/files/updates/12.0.1_12.0.2/source/install/sql/uninstall.sql
  23. 155 0
      modules/boonex/files/updates/12.0.1_12.0.2/source/js/toolbar_tools.js
  24. 13 0
      modules/boonex/files/updates/12.0.1_12.0.2/source/template/bulk_downloader_process.html
  25. 164 0
      modules/boonex/files/updates/12.0.1_12.0.2/source/template/css/main.css
  26. 51 0
      modules/boonex/forum/updates/12.0.2_12.0.3/install/config.php
  27. 23 0
      modules/boonex/forum/updates/12.0.2_12.0.3/install/installer.php
  28. 5 0
      modules/boonex/forum/updates/12.0.2_12.0.3/install/sql/install.sql
  29. 1054 0
      modules/boonex/forum/updates/12.0.2_12.0.3/source/classes/BxForumModule.php
  30. 136 0
      modules/boonex/forum/updates/12.0.2_12.0.3/source/install/config.php
  31. 562 0
      modules/boonex/forum/updates/12.0.2_12.0.3/source/install/sql/install.sql
  32. 51 0
      modules/boonex/groups/updates/12.0.2_12.0.3/install/config.php
  33. 23 0
      modules/boonex/groups/updates/12.0.2_12.0.3/install/installer.php
  34. 15 0
      modules/boonex/groups/updates/12.0.2_12.0.3/install/langs/en.xml
  35. 37 0
      modules/boonex/groups/updates/12.0.2_12.0.3/install/sql/enable.sql
  36. 11 0
      modules/boonex/groups/updates/12.0.2_12.0.3/install/sql/install.sql
  37. 261 0
      modules/boonex/groups/updates/12.0.2_12.0.3/source/classes/BxGroupsConfig.php
  38. 22 0
      modules/boonex/groups/updates/12.0.2_12.0.3/source/classes/BxGroupsFormPrice.php
  39. 25 0
      modules/boonex/groups/updates/12.0.2_12.0.3/source/classes/BxGroupsModule.php
  40. 152 0
      modules/boonex/groups/updates/12.0.2_12.0.3/source/install/config.php
  41. 445 0
      modules/boonex/groups/updates/12.0.2_12.0.3/source/install/langs/en.xml
  42. 60 0
      modules/boonex/groups/updates/12.0.2_12.0.3/source/install/sql/disable.sql
  43. 660 0
      modules/boonex/groups/updates/12.0.2_12.0.3/source/install/sql/enable.sql
  44. 484 0
      modules/boonex/groups/updates/12.0.2_12.0.3/source/install/sql/install.sql
  45. 59 0
      modules/boonex/groups/updates/12.0.2_12.0.3/source/js/prices.js
  46. 1 0
      modules/boonex/groups/updates/12.0.2_12.0.3/source/template/css/main.css
  47. 1 0
      modules/boonex/groups/updates/12.0.2_12.0.3/source/template/css/prices.css
  48. 51 0
      modules/boonex/intercom/updates/12.0.0_12.0.1/install/config.php
  49. 13 0
      modules/boonex/intercom/updates/12.0.0_12.0.1/install/installer.php
  50. 356 0
      modules/boonex/intercom/updates/12.0.0_12.0.1/source/classes/BxIntercomModule.php
  51. 68 0
      modules/boonex/intercom/updates/12.0.0_12.0.1/source/install/config.php
  52. 51 0
      modules/boonex/mailchimp/updates/12.0.0_12.0.1/install/config.php
  53. 13 0
      modules/boonex/mailchimp/updates/12.0.0_12.0.1/install/installer.php
  54. 49 0
      modules/boonex/mailchimp/updates/12.0.0_12.0.1/source/classes/BxMailchimpAlerts.php
  55. 337 0
      modules/boonex/mailchimp/updates/12.0.0_12.0.1/source/classes/BxMailchimpModule.php
  56. 68 0
      modules/boonex/mailchimp/updates/12.0.0_12.0.1/source/install/config.php
  57. 51 0
      modules/boonex/market/updates/12.0.2_12.0.3/install/config.php
  58. 13 0
      modules/boonex/market/updates/12.0.2_12.0.3/install/installer.php
  59. 8 0
      modules/boonex/market/updates/12.0.2_12.0.3/install/langs/en.xml
  60. 4 0
      modules/boonex/market/updates/12.0.2_12.0.3/install/sql/enable.sql
  61. 140 0
      modules/boonex/market/updates/12.0.2_12.0.3/source/install/config.php
  62. 466 0
      modules/boonex/market/updates/12.0.2_12.0.3/source/install/langs/en.xml
  63. 655 0
      modules/boonex/market/updates/12.0.2_12.0.3/source/install/sql/enable.sql
  64. 133 0
      modules/boonex/market/updates/12.0.2_12.0.3/source/js/entry.js
  65. 51 0
      modules/boonex/massmailer/updates/12.0.0_12.0.1/install/config.php
  66. 13 0
      modules/boonex/massmailer/updates/12.0.0_12.0.1/install/installer.php
  67. 662 0
      modules/boonex/massmailer/updates/12.0.0_12.0.1/source/classes/BxMassMailerModule.php
  68. 77 0
      modules/boonex/massmailer/updates/12.0.0_12.0.1/source/install/config.php
  69. 19 0
      modules/boonex/massmailer/updates/12.0.0_12.0.1/source/template/manage_item.html
  70. 51 0
      modules/boonex/nexus/updates/12.0.0_12.0.1/install/config.php
  71. 13 0
      modules/boonex/nexus/updates/12.0.0_12.0.1/install/installer.php
  72. 5 0
      modules/boonex/nexus/updates/12.0.0_12.0.1/install/langs/en.xml
  73. 6 0
      modules/boonex/nexus/updates/12.0.0_12.0.1/install/sql/enable.sql
  74. 128 0
      modules/boonex/nexus/updates/12.0.0_12.0.1/source/classes/BxNexusModule.php
  75. 68 0
      modules/boonex/nexus/updates/12.0.0_12.0.1/source/install/config.php
  76. 22 0
      modules/boonex/nexus/updates/12.0.0_12.0.1/source/install/langs/en.xml
  77. 33 0
      modules/boonex/nexus/updates/12.0.0_12.0.1/source/install/sql/enable.sql
  78. 127 0
      modules/boonex/nexus/updates/12.0.0_12.0.1/source/template/js.html
  79. 51 0
      modules/boonex/notifications/updates/12.0.2_12.0.3/install/config.php
  80. 13 0
      modules/boonex/notifications/updates/12.0.2_12.0.3/install/installer.php
  81. 254 0
      modules/boonex/notifications/updates/12.0.2_12.0.3/source/classes/BxNtfsConfig.php
  82. 179 0
      modules/boonex/notifications/updates/12.0.2_12.0.3/source/classes/BxNtfsCronNotify.php
  83. 340 0
      modules/boonex/notifications/updates/12.0.2_12.0.3/source/classes/BxNtfsDb.php
  84. 569 0
      modules/boonex/notifications/updates/12.0.2_12.0.3/source/classes/BxNtfsModule.php
  85. 256 0
      modules/boonex/notifications/updates/12.0.2_12.0.3/source/classes/BxNtfsResponse.php
  86. 398 0
      modules/boonex/notifications/updates/12.0.2_12.0.3/source/classes/BxNtfsTemplate.php
  87. 82 0
      modules/boonex/notifications/updates/12.0.2_12.0.3/source/install/config.php
  88. 51 0
      modules/boonex/organizations/updates/12.0.2_12.0.3/install/config.php
  89. 28 0
      modules/boonex/organizations/updates/12.0.2_12.0.3/install/installer.php
  90. 66 0
      modules/boonex/organizations/updates/12.0.2_12.0.3/install/langs/en.xml
  91. 110 0
      modules/boonex/organizations/updates/12.0.2_12.0.3/install/sql/enable.sql
  92. 72 0
      modules/boonex/organizations/updates/12.0.2_12.0.3/install/sql/install.sql
  93. 302 0
      modules/boonex/organizations/updates/12.0.2_12.0.3/source/classes/BxOrgsConfig.php
  94. 22 0
      modules/boonex/organizations/updates/12.0.2_12.0.3/source/classes/BxOrgsCronPruning.php
  95. 22 0
      modules/boonex/organizations/updates/12.0.2_12.0.3/source/classes/BxOrgsFormPrice.php
  96. 56 0
      modules/boonex/organizations/updates/12.0.2_12.0.3/source/classes/BxOrgsFormsEntryHelper.php
  97. 22 0
      modules/boonex/organizations/updates/12.0.2_12.0.3/source/classes/BxOrgsGridPricesManage.php
  98. 30 0
      modules/boonex/organizations/updates/12.0.2_12.0.3/source/classes/BxOrgsGridPricesView.php
  99. 70 0
      modules/boonex/organizations/updates/12.0.2_12.0.3/source/classes/BxOrgsMenuViewActionsAll.php
  100. 152 0
      modules/boonex/organizations/updates/12.0.2_12.0.3/source/install/config.php

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

@@ -19,7 +19,7 @@
     <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_sys_keys_category"><![CDATA[Category]]></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>

+ 1 - 1
modules/boonex/developer/updates/12.0.0_12.0.1/source/install/langs/en.xml

@@ -485,7 +485,7 @@
     <string name="_bx_dev_pgt_txt_sys_keys_language"><![CDATA[Language]]></string>
     <string name="_bx_dev_pgt_txt_keys_language"><![CDATA[Language]]></string>
     <string name="_bx_dev_pgt_inf_keys_language"><![CDATA[Leave empty to add in all available languages.]]></string>
-    <string name="_bx_dev_pgt_txt_sys_keys_category"><![CDATA[Сategory]]></string>
+    <string name="_bx_dev_pgt_txt_sys_keys_category"><![CDATA[Category]]></string>
     <string name="_bx_dev_pgt_txt_keys_category"><![CDATA[Сategory]]></string>
     <string name="_bx_dev_pgt_err_keys_category"><![CDATA[You need to select a сategory]]></string>
     <string name="_bx_dev_pgt_txt_sys_keys_content"><![CDATA[Keys]]></string>

+ 51 - 0
modules/boonex/files/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' => 'Files',
+    '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/files/updates/update_12.0.1_12.0.2/',
+    'home_uri' => 'files_update_1201_1202',
+
+    'module_dir' => 'boonex/files/',
+    'module_uri' => 'files',
+
+    'db_prefix' => 'bx_files_',
+    'class_prefix' => 'BxFiles',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_files' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Files',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

+ 13 - 0
modules/boonex/files/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 BxFilesUpdater extends BxDolStudioUpdater
+{
+    function __construct($aConfig)
+    {
+        parent::__construct($aConfig);
+    }
+}

+ 10 - 0
modules/boonex/files/updates/12.0.1_12.0.2/install/langs/en.xml

@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources name="en" flag="gb" title="English">
+	<string_add name="_bx_files_menu_item_title_system_edit_title"><![CDATA[Rename]]></string_add>
+    <string_add name="_bx_files_menu_item_title_edit_title"><![CDATA[Rename]]></string_add>
+	<string_add name="_bx_files_txt_status_downloading"><![CDATA[Downloading...]]></string_add>
+    <string_add name="_bx_files_txt_status_downloading_msg"><![CDATA[The download will start shortly...]]></string_add>
+    <string_add name="_bx_files_txt_status_downloading_ready_msg"><![CDATA[Click <a href={0}>here</a> if the download doesn't start automatically.]]></string_add>
+    <string_add name="_bx_files_option_allowed_ext"><![CDATA[Allow only the following extensions (comma separated list)]]></string_add>
+    <string_add name="_bx_files_option_default_layout_mode"><![CDATA[Files default layout]]></string_add>
+</resources>

+ 15 - 0
modules/boonex/files/updates/12.0.1_12.0.2/install/sql/enable.sql

@@ -0,0 +1,15 @@
+-- SETTINGS
+SET @iCategId = (SELECT `id` FROM `sys_options_categories` WHERE `name`='bx_files' LIMIT 1);
+
+DELETE FROM `sys_options` WHERE `name` IN ('bx_files_default_layout_mode', 'bx_files_allowed_ext');
+INSERT INTO `sys_options` (`name`, `value`, `category_id`, `caption`, `type`, `check`, `check_params`, `check_error`, `extra`, `order`) VALUES
+('bx_files_default_layout_mode', 'gallery', @iCategId, '_bx_files_option_default_layout_mode', 'select', '', '', '', 'gallery,table', 4),
+('bx_files_allowed_ext', '', @iCategId, '_bx_files_option_allowed_ext', 'digit', '', '', '', '', 8);
+
+
+-- PAGES
+DELETE FROM `sys_pages_blocks` WHERE `object`='bx_files_author' AND `title`='_bx_files_page_block_title_entries_actions';
+
+
+-- MENUS
+UPDATE `sys_menu_items` SET `title_system`='_bx_files_menu_item_title_system_edit_title', `title`='_bx_files_menu_item_title_edit_title' WHERE `set_name`='bx_files_view_inline' AND `name`='edit-title';

+ 10 - 0
modules/boonex/files/updates/12.0.1_12.0.2/install/sql/install.sql

@@ -0,0 +1,10 @@
+-- TABLES
+CREATE TABLE IF NOT EXISTS `bx_files_downloading_jobs` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `name` varchar(255) NOT NULL,
+  `owner` int(11) NOT NULL,
+  `files` MEDIUMTEXT NOT NULL,
+  `result` TEXT NOT NULL,
+  `started` int(11) NOT NULL,
+  PRIMARY KEY (`id`)
+);

+ 33 - 0
modules/boonex/files/updates/12.0.1_12.0.2/source/classes/BxFilesAlertsResponse.php

@@ -0,0 +1,33 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Files Files
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxFilesAlertsResponse extends BxBaseModTextAlertsResponse
+{
+    public function __construct()
+    {
+        $this->MODULE = 'bx_files';
+        parent::__construct();
+    }
+
+    public function response($oAlert)
+    {
+        $CNF = $this->_oModule->_oConfig->CNF;
+
+        if('system' == $oAlert->sUnit && 'save_setting' == $oAlert->sAction && isset($CNF['PARAM_ALLOWED_EXT']) && $CNF['PARAM_ALLOWED_EXT'] == $oAlert->aExtras['option']) {
+            $this->_oModule->_oDb->setStorageAllowedExtensions($oAlert->aExtras['value']);
+            BxDolCacheUtilities::getInstance()->clear('db');
+        }
+
+        return parent::response($oAlert);
+    }
+}
+
+/** @} */

+ 164 - 0
modules/boonex/files/updates/12.0.1_12.0.2/source/classes/BxFilesBulkDownloader.php

@@ -0,0 +1,164 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Files Files
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+/**
+ * Files bulk downloader
+ */
+
+define('BX_FILES_DOWNLOADER_TIMEOUT', 10); //seconds
+define('BX_FILES_DOWNLOADER_TIMEOUT_REQUESTS', 15); //seconds
+
+define('BX_FILES_DOWNLOADER_STATUS_EMPTY', 0);
+define('BX_FILES_DOWNLOADER_STATUS_TOO_LARGE', 1);
+define('BX_FILES_DOWNLOADER_STATUS_DOWNLOADING', 2);
+define('BX_FILES_DOWNLOADER_STATUS_READY', 3);
+
+class BxFilesBulkDownloader
+{
+    var $oModule;
+    public function __construct(&$oModule)
+    {
+        $this->oModule = &$oModule;
+    }
+
+    public function createDownloadingJob($aFiles, $sZipFileName) {
+        $CNF = &$this->oModule->_oConfig->CNF;
+
+        $aFilesList = $this->getFolderFiles($aFiles, '/', 'mixed');
+        if(!$aFilesList) return [
+            'status' => BX_FILES_DOWNLOADER_STATUS_EMPTY,
+        ];
+
+        $iMaxSize = intval(getParam($CNF['PARAM_MAX_BULK_DOWNLOAD_SIZE'])) * 1024 * 1024;
+        if ($iMaxSize) {
+            $iTotalSize = 0;
+            foreach ($aFilesList as $aFile) {
+                $iTotalSize += $aFile['size'];
+            }
+            if ($iTotalSize >= $iMaxSize) return [
+                'status' => BX_FILES_DOWNLOADER_STATUS_TOO_LARGE,
+            ];
+        }
+
+        $mRes = $this->processDownloading($aFilesList);
+        if ($mRes === BX_FILES_DOWNLOADER_STATUS_DOWNLOADING) {
+            $iDownloadingJobId = $this->oModule->_oDb->createDownloadingJob($aFilesList, $sZipFileName, bx_get_logged_profile_id());
+            return [
+                'status' => BX_FILES_DOWNLOADER_STATUS_DOWNLOADING,
+                'job' => $iDownloadingJobId,
+            ];
+        } else {
+            return [
+                'status' => BX_FILES_DOWNLOADER_STATUS_READY,
+                'file' => $mRes,
+                'filename' => $this->sanitizeFileName($sZipFileName).'.zip',
+            ];
+        }
+    }
+
+    public function processDownloading(&$aFiles) {
+        $CNF = &$this->oModule->_oConfig->CNF;
+
+        $oStorage = BxDolStorage::getObjectInstance($CNF['OBJECT_STORAGE']);
+
+        $iJobStarted = time();
+
+        foreach ($aFiles as $iIndex => $aFile) {
+            if (isset($aFile['downloaded']) && file_exists($aFile['downloaded'])) continue;
+
+            $sFileUrl = $oStorage->getFileUrlById($aFile['id']);
+            $sFilePath = BX_DIRECTORY_PATH_TMP . 'download-job-file-'.$aFile['id'];
+            if (!file_exists($sFilePath)) {
+                @file_put_contents($sFilePath, bx_file_get_contents($sFileUrl));
+            }
+
+            $aFiles[$iIndex]['downloaded'] = $sFilePath;
+
+            if (time() - $iJobStarted >= BX_FILES_DOWNLOADER_TIMEOUT) {
+                return BX_FILES_DOWNLOADER_STATUS_DOWNLOADING;
+            }
+        }
+
+        return $this->createZipArchive($aFiles);
+    }
+
+    private function createZipArchive(&$aFiles) {
+        $sZipFile = BX_DIRECTORY_PATH_TMP.'files-folder-'.time().mt_rand().'.zip';
+        if (file_exists($sZipFile)) @unlink($sZipFile);
+
+        $oZipFile = new ZipArchive();
+        if ($oZipFile->open($sZipFile, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE)) {
+
+            $iIndex = 0;
+            foreach ($aFiles as $aFile) {
+                $sFilePath = $aFile['downloaded'];
+                if (file_exists($sFilePath) && is_readable($sFilePath)) {
+                    $oZipFile->addFile($sFilePath, $aFile['filename']);
+                    $oZipFile->setCompressionIndex($iIndex++, ZipArchive::CM_STORE);
+                }
+            }
+            $oZipFile->close();
+
+            foreach ($aFiles as $aFile)
+                @unlink($aFile['downloaded']);
+
+            return $sZipFile;
+        } else {
+            return BX_FILES_DOWNLOADER_STATUS_EMPTY;
+        }
+    }
+
+    private function getFolderFiles($mFile, $sRelPath, $sType) {
+        $aFiles = $this->oModule->_oDb->getFolderFilesEx($mFile, $sType);
+        if (!$aFiles) return [];
+
+        $aResult = [];
+        $aUniqueNames = [];
+        foreach ($aFiles as $aFile) {
+            if (CHECK_ACTION_RESULT_ALLOWED !== $this->oModule->checkAllowedView($aFile)) continue;
+
+            //in case title has been changed we might have to add extensions manually
+            $aFileInfo = pathinfo($aFile['title']);
+            $sFileBaseName = isset($aFileInfo['filename']) ? $aFileInfo['filename'] : '_';
+            $sFileExt = isset($aFileInfo['extension']) ? $aFileInfo['extension'] : '';
+
+            if (!$sFileExt || $sFileExt != $aFile['ext']) $sFileExt = $aFile['ext'];
+
+            //handle multiple files with the same name
+            $sFilename = $this->sanitizeFileName($sFileBaseName);
+            $iIndex = 1;
+            while (isset($aUniqueNames[$sFilename])) {
+                $sFilename = $this->sanitizeFileName($sFileBaseName.'_'.$iIndex++);
+            }
+            $aUniqueNames[$sFilename] = 1;
+
+            if ($aFile['type'] == 'folder') {
+                $aResult = array_merge($aResult, $this->getFolderFiles($aFile['id'], $sRelPath . $sFilename . '/', 'folder'));
+            } else {
+                $aResult[] = [
+                    'filename' => trim($sRelPath.$sFilename.'.'.$sFileExt, '/'),
+                    'size' => $aFile['size'],
+                    'id' => $aFile['file_id'],
+                ];
+            }
+        }
+
+        return $aResult;
+    }
+
+    private function sanitizeFileName($sDesiredFilename) {
+        $sDesiredFilename = mb_ereg_replace("([^\w\s\d\-_~,;\[\]\(\).])", '_', $sDesiredFilename);
+        $sDesiredFilename = mb_ereg_replace("([\.]{2,})", '_', $sDesiredFilename);
+        return $sDesiredFilename;
+    }
+}
+
+/** @} */

+ 196 - 0
modules/boonex/files/updates/12.0.1_12.0.2/source/classes/BxFilesConfig.php

@@ -0,0 +1,196 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Files Files
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxFilesConfig extends BxBaseModTextConfig
+{
+    function __construct($aModule)
+    {
+        parent::__construct($aModule);
+
+        $aMenuItems2Methods = array (
+            'download-file' => 'checkAllowedView',
+            'edit-file' => 'checkAllowedEdit',
+            'delete-file' => 'checkAllowedDelete',
+        );
+
+        $this->CNF = array (
+
+            // module icon
+            'ICON' => 'far file col-red3',
+
+            // database tables
+            'TABLE_ENTRIES' => $aModule['db_prefix'] . 'main',
+            'TABLE_ENTRIES_FULLTEXT' => 'search_fields',
+            'TABLE_FILES' => $aModule['db_prefix'] . 'files',
+            'TABLE_BOOKMARKS' => $aModule['db_prefix'] . 'bookmarks',
+            'TABLE_FOLDERS' => $aModule['db_prefix'] . 'folders',
+
+            // database fields
+            'FIELD_ID' => 'id',
+            'FIELD_AUTHOR' => 'author',
+            'FIELD_ADDED' => 'added',
+            'FIELD_CHANGED' => 'changed',
+            'FIELD_FILE_ID' => 'file_id',
+            'FIELD_FOR_STORING_FILE_ID' => 'file_id',
+            'FIELD_TITLE' => 'title',
+            'FIELD_CATEGORY' => 'cat',
+            'FIELD_TEXT' => 'desc',
+            'FIELD_TEXT_ID' => 'file-desc',
+            'FIELD_ALLOW_VIEW_TO' => 'allow_view_to',
+            'FIELD_PHOTO' => 'attachments',
+            'FIELD_VIEWS' => 'views',
+            'FIELD_COMMENTS' => 'comments',
+            'FIELD_STATUS' => 'status',
+            'FIELD_STATUS_ADMIN' => 'status_admin',
+            '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_BOOKMARKS_ID' => 'object_id',
+            'FIELD_BOOKMARKS_PROFILE' => 'profile_id',
+            'FIELD_MIME_TYPE' => 'mime_type',
+			
+            // some params
+            'PARAM_PER_PAGE_FOR_FAVORITES_LISTS' => 'bx_files_per_page_for_favorites_lists',
+            
+            // page URIs
+            'URI_VIEW_ENTRY' => 'view-file',
+            'URI_AUTHOR_ENTRIES' => 'files-author',
+            'URI_ENTRIES_BY_CONTEXT' => 'files-context',
+            'URI_ADD_ENTRY' => 'create-file',
+            'URI_EDIT_ENTRY' => 'edit-file',
+            'URI_MANAGE_COMMON' => 'files-manage',
+            'URI_FAVORITES_LIST' => 'files-favorites',
+
+            'URL_HOME' => 'page.php?i=files-home',
+            'URL_POPULAR' => 'page.php?i=files-popular',
+            'URL_TOP' => 'page.php?i=files-top',
+            'URL_UPDATED' => 'page.php?i=files-updated',
+            'URL_MANAGE_COMMON' => 'page.php?i=files-manage',
+            'URL_MANAGE_ADMINISTRATION' => 'page.php?i=files-administration',
+
+            // some params
+            'PARAM_CHARS_SUMMARY' => 'bx_files_summary_chars',
+            'PARAM_CHARS_SUMMARY_PLAIN' => '',
+            'PARAM_NUM_RSS' => 'bx_files_rss_num',
+            'PARAM_SEARCHABLE_FIELDS' => 'bx_files_searchable_fields',
+            'PARAM_LINK_TO_PREVIEW' => 'bx_files_show_link_to_preview',
+            'PARAM_MAX_NESTING_LEVEL' => 'bx_files_max_nesting_level',
+            'PARAM_MAX_BULK_DOWNLOAD_SIZE' => 'bx_files_max_bulk_download_size',
+            'PARAM_ALLOWED_EXT' => 'bx_files_allowed_ext',
+            'PARAM_DEFAULT_LAYOUT_MODE' => 'bx_files_default_layout_mode',
+
+            // objects
+            'OBJECT_STORAGE' => 'bx_files_files',
+            'OBJECT_IMAGES_TRANSCODER_PREVIEW' => 'bx_files_preview',
+            'OBJECT_IMAGES_TRANSCODER_GALLERY' => 'bx_files_gallery',
+            'OBJECT_VIDEOS_TRANSCODERS' => array(),
+            'OBJECT_REPORTS' => 'bx_files',
+            'OBJECT_VIEWS' => 'bx_files',
+            'OBJECT_VOTES' => 'bx_files',
+            'OBJECT_REACTIONS' => 'bx_files_reactions',
+            'OBJECT_SCORES' => 'bx_files',
+            'OBJECT_FAVORITES' => 'bx_files',
+            'OBJECT_FEATURED' => 'bx_files',
+            'OBJECT_METATAGS' => 'bx_files',
+            'OBJECT_COMMENTS' => 'bx_files',
+            'OBJECT_CATEGORY' => 'bx_files_cats',
+            'OBJECT_PRIVACY_VIEW' => 'bx_files_allow_view_to',
+            'OBJECT_PRIVACY_LIST_VIEW' => 'bx_files_allow_view_favorite_list',
+            'OBJECT_FORM_ENTRY_UPLOAD' => 'bx_files_upload',
+            'OBJECT_FORM_ENTRY_DISPLAY_UPLOAD' => 'bx_files_entry_upload',
+            'OBJECT_FORM_ENTRY' => 'bx_files',
+            'OBJECT_FORM_ENTRY_DISPLAY_VIEW' => 'bx_files_entry_view',
+            'OBJECT_FORM_ENTRY_DISPLAY_ADD' => 'bx_files_entry_edit',
+            'OBJECT_FORM_ENTRY_DISPLAY_EDIT' => 'bx_files_entry_edit',
+            'OBJECT_FORM_ENTRY_DISPLAY_DELETE' => 'bx_files_entry_delete',
+            'OBJECT_MENU_ACTIONS_VIEW_ENTRY' => 'bx_files_view', // actions menu on view entry page
+            'OBJECT_MENU_ACTIONS_VIEW_ENTRY_ALL' => 'bx_files_view_actions', // all actions menu on view entry page
+            'OBJECT_MENU_ACTIONS_MY_ENTRIES' => 'bx_files_my', // actions menu on my entries page
+            'OBJECT_MENU_SUBMENU' => 'bx_files_submenu', // main module submenu
+            'OBJECT_MENU_SUBMENU_VIEW_ENTRY' => 'bx_files_view_submenu', // view entry submenu
+            'OBJECT_MENU_SUBMENU_VIEW_ENTRY_MAIN_SELECTION' => 'files-home', // first item in view entry submenu from main module submenu
+            'OBJECT_MENU_SNIPPET_META' => 'bx_files_snippet_meta', // menu for snippet meta info
+            'OBJECT_MENU_MANAGE_TOOLS' => 'bx_files_menu_manage_tools', //manage menu in content administration tools
+            'OBJECT_GRID_ADMINISTRATION' => 'bx_files_administration',
+            'OBJECT_GRID_COMMON' => 'bx_files_common',
+            'OBJECT_UPLOADERS' => array('sys_simple', 'sys_html5'),
+
+            // menu items which visibility depends on custom visibility checking
+            'MENU_ITEM_TO_METHOD' => array (
+                'bx_files_my' => array (
+                    'create-file' => 'checkAllowedAdd',
+                ),
+                'bx_files_view' => $aMenuItems2Methods,
+            ),
+
+            // some language keys
+            'T' => array (
+                'txt_sample_single' => '_bx_files_txt_sample_single',
+            	'txt_sample_single_with_article' => '_bx_files_txt_sample_single_with_article',
+            	'txt_sample_comment_single' => '_bx_files_txt_sample_comment_single',
+            	'txt_sample_vote_single' => '_bx_files_txt_sample_vote_single',
+                'txt_sample_reaction_single' => '_bx_files_txt_sample_reaction_single',
+                'txt_sample_score_up_single' => '_bx_files_txt_sample_score_up_single',
+                'txt_sample_score_down_single' => '_bx_files_txt_sample_score_down_single',
+             	'form_field_author' => '_bx_files_form_entry_input_author',
+                'form_entry_upload_single_for_update' => '_bx_files_form_entry_input_pictures_upload',
+            	'grid_action_err_delete' => '_bx_files_grid_action_err_delete',
+            	'grid_txt_account_manager' => '_bx_files_grid_txt_account_manager',
+                'filter_item_active' => '_bx_files_grid_filter_item_title_adm_active',
+            	'filter_item_hidden' => '_bx_files_grid_filter_item_title_adm_hidden',
+            	'filter_item_select_one_filter1' => '_bx_files_grid_filter_item_title_adm_select_one_filter1',
+            	'menu_item_manage_my' => '_bx_files_menu_item_title_manage_my',
+            	'menu_item_manage_all' => '_bx_files_menu_item_title_manage_all',
+                'txt_all_entries_by' => '_bx_files_txt_all_entries_by',
+                'txt_all_entries_in' => '_bx_files_txt_all_entries_in',
+                'txt_all_entries_by_author' => '_bx_files_page_title_browse_by_author',
+                'txt_all_entries_by_context' => '_bx_files_page_title_browse_by_context',
+            ),
+        );
+
+        $this->_aJsClasses = array(
+        	'manage_tools' => 'BxFilesManageTools',
+            'toolbar_tools' => 'BxFilesBrowserTools',
+        );
+
+        $this->_aJsObjects = array(
+        	'manage_tools' => 'oBxFilesManageTools',
+            'toolbar_tools' => 'oBxFilesBrowserTools',
+        );
+
+        $this->_aGridObjects = array(
+        	'common' => $this->CNF['OBJECT_GRID_COMMON'],
+        	'administration' => $this->CNF['OBJECT_GRID_ADMINISTRATION'],
+        	
+        );
+    }
+
+    public function getJsClass($mixedType)
+    {
+        if (is_array($mixedType)) {
+            return parent::getJsClass($mixedType['type']);
+        } else {
+            return parent::getJsClass($mixedType);
+        }
+    }
+
+    public function getJsObject($mixedType)
+    {
+        if (is_array($mixedType)) {
+            return parent::getJsObject($mixedType['type']).$mixedType['uniq'];
+        } else {
+            return parent::getJsObject($mixedType);
+        }
+    }
+}
+
+/** @} */

+ 21 - 0
modules/boonex/files/updates/12.0.1_12.0.2/source/classes/BxFilesCronProcessData.php

@@ -0,0 +1,21 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Files Files
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxFilesCronProcessData extends BxDolCron
+{
+    function processing()
+    {
+        BxDolService::call('bx_files', 'process_files_data', array(3));
+        BxDolService::call('bx_files', 'prune_downloading_jobs', array());
+    }
+}
+
+/** @} */

+ 260 - 0
modules/boonex/files/updates/12.0.1_12.0.2/source/classes/BxFilesDb.php

@@ -0,0 +1,260 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Files Files
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+/*
+ * Module database queries
+ */
+class BxFilesDb extends BxBaseModFilesDb
+{
+    function __construct(&$oConfig)
+    {
+        parent::__construct($oConfig);
+    }
+	
+    public function updateFileId ($iContentId, $iFileId)
+    {
+		return $this->updateEntries(array('file_id' => $iFileId, 'data' => '', 'data_processed' => 0), array('id' => $iContentId));
+    }
+    
+    public function updateFileData ($iContentId, $sData, $iDataProcessed = 1)
+    {
+		return $this->updateEntries(array('data' => $sData, 'data_processed' => $iDataProcessed), array('id' => $iContentId));
+    }
+
+    public function getNotProcessedFiles ($iLimit)
+    {
+        $sQuery = $this->prepare ("SELECT * FROM `" . $this->_oConfig->CNF['TABLE_ENTRIES'] . "` WHERE `data_processed` = 0 ORDER BY `added` ASC LIMIT ?", $iLimit);
+        return $this->getAll($sQuery);
+    }
+
+    public function bookmarkFile($iContentId, $iProfileId) {
+        if ($this->isFileBookmarked($iContentId, $iProfileId)) {
+            $this->query("DELETE FROM `" . $this->_oConfig->CNF['TABLE_BOOKMARKS'] . "` WHERE `object_id` = :id AND `profile_id` = :profile_id", [
+                'id' => $iContentId,
+                'profile_id' => $iProfileId
+            ]);
+        } else {
+            $this->query("INSERT INTO `" . $this->_oConfig->CNF['TABLE_BOOKMARKS'] . "` (`object_id`, `profile_id`) VALUES (:id, :profile_id)", [
+                'id' => $iContentId,
+                'profile_id' => $iProfileId
+            ]);
+        }
+    }
+
+    public function deleteFileBookmarks($iContentId) {
+        $this->query("DELETE FROM `" . $this->_oConfig->CNF['TABLE_BOOKMARKS'] . "` WHERE `object_id` = :id", [
+            'id' => $iContentId,
+        ]);
+    }
+
+    public function deleteProfileBookmarks($iProfileId) {
+        $this->query("DELETE FROM `" . $this->_oConfig->CNF['TABLE_BOOKMARKS'] . "` WHERE `profile_id` = :profile_id", [
+            'profile_id' => $iProfileId,
+        ]);
+    }
+
+    public function isFileBookmarked($iContentId, $iProfileId) {
+        return $this->getOne("SELECT COUNT(*) FROM `" . $this->_oConfig->CNF['TABLE_BOOKMARKS'] . "` WHERE `object_id` = :id AND `profile_id` = :profile_id", [
+            'id' => $iContentId,
+            'profile_id' => $iProfileId
+        ]);
+    }
+
+    public function updateEntryTitle($iContentId, $sNewTitle) {
+        $this->query("UPDATE `" . $this->_oConfig->CNF['TABLE_ENTRIES'] . "` SET `" . $this->_oConfig->CNF['FIELD_TITLE'] . "` = :title WHERE `" . $this->_oConfig->CNF['FIELD_ID'] . "` = :id", [
+            'id' => $iContentId,
+            'title' => $sNewTitle,
+        ]);
+
+        $iFileId = $this->getOne("SELECT `file_id` FROM `" . $this->_oConfig->CNF['TABLE_ENTRIES'] . "` WHERE `" . $this->_oConfig->CNF['FIELD_ID'] . "` = :id", [
+            'id' => $iContentId,
+        ]);
+
+        if ($iFileId)
+            $this->query("UPDATE `" . $this->_oConfig->CNF['TABLE_FILES'] . "` SET `file_name` = :title WHERE `id` = :id", [
+                'id' => $iFileId,
+                'title' => $sNewTitle,
+            ]);
+    }
+
+    public function createFolder($iParentFolder, $iAuthor, $iContext, $sTitle) {
+        $CNF = &$this->_oConfig->CNF;
+
+        $this->query("
+            INSERT INTO `" . $CNF['TABLE_ENTRIES'] . "` 
+            (`{$CNF['FIELD_AUTHOR']}`, `{$CNF['FIELD_ADDED']}`, `{$CNF['FIELD_CHANGED']}`, `{$CNF['FIELD_TITLE']}`, `data_processed`, `{$CNF['FIELD_ALLOW_VIEW_TO']}`, `type`, `parent_folder_id`)
+            VALUES (:author, :when, :when, :title, 1, :context, 'folder', :parent_folder_id)", [
+                'author' => $iAuthor,
+                'when' => time(),
+                'title' => $sTitle,
+                'context' => $iContext,
+                'parent_folder_id' => $iParentFolder,
+        ]);
+    }
+
+    public function moveFilesToFolder($aFiles, $iFolder) {
+        $CNF = &$this->_oConfig->CNF;
+        $this->query("UPDATE `" . $CNF['TABLE_ENTRIES'] . "` SET `parent_folder_id` = {$iFolder} WHERE `" . $CNF['FIELD_ID'] . "` IN (".implode(',', $aFiles).")");
+    }
+
+    public function getParentFolderId($iFolder) {
+        $CNF = &$this->_oConfig->CNF;
+        return $this->getOne("SELECT `parent_folder_id` FROM `" . $CNF['TABLE_ENTRIES'] . "` WHERE `" . $CNF['FIELD_ID'] . "` = :folder", [
+            'folder' => $iFolder,
+        ]);
+    }
+
+    public function getFolderFiles($iFolder) {
+        $CNF = &$this->_oConfig->CNF;
+        return $this->getColumn("SELECT `{$CNF['FIELD_ID']}` FROM `" . $CNF['TABLE_ENTRIES'] . "` WHERE `parent_folder_id` = :folder", [
+            'folder' => $iFolder,
+        ]);
+    }
+
+    public function getFolderFilesEx($mFile, $sType = 'folder') {
+        $CNF = &$this->_oConfig->CNF;
+
+        $sQuery = "
+            SELECT `{$CNF['TABLE_ENTRIES']}`.`{$CNF['FIELD_ID']}`, `{$CNF['TABLE_ENTRIES']}`.`{$CNF['FIELD_FILE_ID']}`, `{$CNF['TABLE_ENTRIES']}`.`{$CNF['FIELD_AUTHOR']}`, `{$CNF['TABLE_ENTRIES']}`.`{$CNF['FIELD_TITLE']}`, `{$CNF['TABLE_ENTRIES']}`.`type`, `{$CNF['TABLE_FILES']}`.`path`, `{$CNF['TABLE_FILES']}`.`ext`, `{$CNF['TABLE_FILES']}`.`size` 
+            FROM `{$CNF['TABLE_ENTRIES']}` 
+            LEFT JOIN `{$CNF['TABLE_FILES']}` ON `{$CNF['TABLE_ENTRIES']}`.`{$CNF['FIELD_FILE_ID']}` = `{$CNF['TABLE_FILES']}`.`{$CNF['FIELD_ID']}`
+        ";
+
+        if ($sType == 'mixed') {
+            if (!is_array($mFile) || empty($mFile)) return false;
+            $aIDs = [];
+            foreach ($mFile as $iFile) $aIDs[] = intval($iFile);
+
+            return $this->getAll($sQuery. "WHERE `{$CNF['TABLE_ENTRIES']}`.`{$CNF['FIELD_ID']}` IN (".implode(',', $aIDs).")");
+        } else {
+            return $this->getAll($sQuery. "
+                WHERE `{$CNF['TABLE_ENTRIES']}`.`".($sType == 'folder' ? 'parent_folder_id' : $CNF['FIELD_ID'])."` = :file                
+                ", [
+                    'file' => $mFile,
+                ]
+            );
+        }
+    }
+
+    public function getFolderNestingLevel($iFolder) {
+        $iLevel = 1;
+
+        while($iParentFolder = $this->getParentFolderId($iFolder)) {
+            $iLevel++;
+            $iFolder = $iParentFolder;
+        }
+
+        return $iLevel;
+    }
+
+    public function getFolderPath($iFolder) {
+        $CNF = &$this->_oConfig->CNF;
+
+        $aPath = [];
+
+        $aFolder = $this->getContentInfoById($iFolder);
+        if (!$aFolder) return $aPath;
+
+        do {
+            $aPath[] = [
+                'folder' => $aFolder[$CNF['FIELD_ID']],
+                'name' => $aFolder[$CNF['FIELD_TITLE']],
+            ];
+
+            if (!$aFolder['parent_folder_id']) break;
+            $aFolder = $this->getContentInfoById($aFolder['parent_folder_id']);
+        } while (true);
+
+        return array_reverse($aPath);
+    }
+
+    public function getFoldersInContext($iContext) {
+        $CNF = &$this->_oConfig->CNF;
+        $sIdent = $iContext > 0 ? $CNF['FIELD_AUTHOR'] : $CNF['FIELD_ALLOW_VIEW_TO'];
+        $aFolders = $this->getAll("SELECT `{$CNF['FIELD_ID']}`, `parent_folder_id`, `{$CNF['FIELD_TITLE']}` FROM `" . $CNF['TABLE_ENTRIES'] . "` WHERE `{$sIdent}` = :context AND `type` = 'folder'", [
+            'context' => $iContext,
+        ]);
+
+        if (!$aFolders) return [];
+
+        return [
+            0 => [
+                $CNF['FIELD_ID'] => 0,
+                $CNF['FIELD_TITLE'] => _t('_bx_files_txt_folder_root'),
+                'subfolders' => $this->getSubfoldersOf($aFolders, 0),
+            ]
+        ];
+    }
+
+    public function getSubfoldersOf(&$aFolders, $iParent) {
+        $CNF = &$this->_oConfig->CNF;
+
+        $aResult = [];
+        foreach ($aFolders as $aFolder) {
+            if ($aFolder['parent_folder_id'] == $iParent) {
+                $aFolder['subfolders'] = $this->getSubfoldersOf($aFolders, $aFolder[$CNF['FIELD_ID']]);
+                $aResult[] = $aFolder;
+            }
+        }
+
+        return $aResult;
+    }
+
+    public function createDownloadingJob($aFiles, $sZipFileName, $iOwner) {
+        $this->query("INSERT INTO `bx_files_downloading_jobs` (`name`, `owner`, `files`, `started`) VALUES (:name, :owner, :files, UNIX_TIMESTAMP())", [
+            'files' => serialize($aFiles),
+            'owner' => $iOwner,
+            'name' => $sZipFileName
+        ]);
+        return $this->lastId();
+    }
+
+    public function getDownloadingJob($iJob) {
+        $aJob = $this->getRow("SELECT * FROM `bx_files_downloading_jobs` WHERE `id` = :id", ['id' => $iJob]);
+        if ($aJob && $aJob['files']) $aJob['files'] = unserialize($aJob['files']);
+        return $aJob;
+    }
+
+    public function updateDownloadingJob($iJob, $aFiles, $sZipFilePath) {
+        $this->query("UPDATE `bx_files_downloading_jobs` SET `result` = :result, `files` = :files WHERE `id` = :id", [
+            'result' => $sZipFilePath,
+            'files' => serialize($aFiles),
+            'id' => $iJob
+        ]);
+    }
+
+    public function deleteOldDownloadingJobs() {
+        $aFiles = $this->getColumn("SELECT `result` FROM `bx_files_downloading_jobs` WHERE UNIX_TIMESTAMP() - `started` > 24*3600");
+
+        if ($aFiles)
+            $this->query("DELETE FROM `bx_files_downloading_jobs` WHERE UNIX_TIMESTAMP() - `started` > 24*3600");
+        return $aFiles;
+    }
+
+    public function setStorageAllowedExtensions($sExtensions) {
+        $CNF = &$this->_oConfig->CNF;
+
+        $aExtensions = explode(',', $sExtensions);
+        if ($aExtensions) foreach ($aExtensions as $iKey => $sExtension) {
+            $aExtensions[$iKey] = trim($sExtension, ' .');
+        }
+
+        $sExtensionsSet = implode(',', $aExtensions);
+
+        $this->query("UPDATE `sys_objects_storage` SET `ext_mode` = :ext_mode, `ext_allow` = :extensions WHERE `sys_objects_storage`.`object` = :storage_object", [
+            'extensions' => $sExtensionsSet,
+            'ext_mode' => empty($sExtensionsSet) ? 'deny-allow' : 'allow-deny',
+            'storage_object' => $CNF['OBJECT_STORAGE'],
+        ]);
+    }
+}
+
+/** @} */

+ 32 - 0
modules/boonex/files/updates/12.0.1_12.0.2/source/classes/BxFilesMenuSnippetMeta.php

@@ -0,0 +1,32 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Files Files
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxFilesMenuSnippetMeta extends BxBaseModTextMenuSnippetMeta
+{
+    public function __construct($aObject, $oTemplate = false)
+    {
+        $this->_sModule = 'bx_files';
+
+        parent::__construct($aObject, $oTemplate);
+    }
+
+    protected function _getMenuItemSize($aItem)
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+        $aFile = $this->_oModule->getContentFile($this->_aContentInfo);
+
+        if (!$aFile) return 0;
+
+        return $this->getUnitMetaItemText(_t_format_size($aFile['size']));
+    }
+}
+
+/** @} */

+ 57 - 0
modules/boonex/files/updates/12.0.1_12.0.2/source/classes/BxFilesMenuView.php

@@ -0,0 +1,57 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Files Files
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+/**
+ * View entry menu
+ */
+class BxFilesMenuView extends BxBaseModTextMenuView
+{
+    public function __construct($aObject, $oTemplate = false)
+    {
+        $this->MODULE = 'bx_files';
+        parent::__construct($aObject, $oTemplate);
+    }
+
+    public function setContentId($iContentId)
+    {
+        parent::setContentId($iContentId);
+
+        $CNF = $this->_oModule->_oConfig->CNF;
+
+        $aFile = $this->_oModule->getContentFile($this->_aContentInfo);
+        $sFileExt = $aFile && !empty($aFile['ext']) ? $aFile['ext'] : '';
+
+        if (!$aFile || !$aFile['private']) {
+            $this->addMarkers(array(
+                'file_download_token' => '0',
+                'file_ext' => $sFileExt,
+            ));
+            return;
+        }
+
+        $oStorage = BxDolStorage::getObjectInstance($CNF['OBJECT_STORAGE']);
+        if (!$oStorage) {
+            $this->addMarkers(array(
+                'file_download_token' => '0',
+                'file_ext' => $sFileExt,
+            ));
+            return;
+        }
+
+        $this->addMarkers(array(
+            'file_download_token' => $oStorage->genToken($aFile['id']),
+            'file_ext' => $sFileExt,
+        ));
+    }
+
+}
+
+/** @} */

+ 607 - 0
modules/boonex/files/updates/12.0.1_12.0.2/source/classes/BxFilesModule.php

@@ -0,0 +1,607 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Files Files
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+/**
+ * Files module
+ */
+class BxFilesModule extends BxBaseModTextModule
+{
+    function __construct(&$aModule)
+    {
+        parent::__construct($aModule);
+    }
+
+    public function serviceIsAllowedAddContentToProfile($iGroupProfileId)
+    {
+        if (!$iGroupProfileId || !($oProfile = BxDolProfile::getInstance((int)$iGroupProfileId)))
+            return false;
+
+        if ($iGroupProfileId == bx_get_logged_profile_id())
+            return true;
+
+        return bx_srv($oProfile->getModule(), 'check_allowed_post_in_profile', array($oProfile->getContentId(), $this->getName())) === CHECK_ACTION_RESULT_ALLOWED;
+    }
+
+    public function serviceMyEntriesActions ($iProfileId = 0)
+    {
+        if (!$iProfileId)
+            $iProfileId = bx_process_input(bx_get('profile_id'), BX_DATA_INT);
+
+        if (!$this->serviceIsAllowedAddContentToProfile($iProfileId))
+            return false;
+
+        $oMenu = BxTemplMenu::getObjectInstance($this->_oConfig->CNF['OBJECT_MENU_ACTIONS_MY_ENTRIES']);
+        return $oMenu ? $oMenu->getCode() : false;
+    }
+
+    public function checkAllowedSetThumb ($iContentId = 0)
+    {
+        return _t('_sys_txt_access_denied');
+    }
+
+    public function actionDownload($sToken, $iContentId, $sBulk = '')
+    {
+        $CNF = $this->_oConfig->CNF;
+
+        $aFilesToDownload = [$iContentId];
+        if (!empty($sBulk)) {
+            $aFilesToDownload = json_decode($sBulk);
+        }
+
+        if (!is_array($aFilesToDownload)) {
+            $this->_oTemplate->displayPageNotFound();
+            return;
+        }
+
+        $iContentId = reset($aFilesToDownload);
+
+        $aData = $this->_oDb->getContentInfoById((int)$iContentId);
+        if (!$aData) {
+            $this->_oTemplate->displayPageNotFound();
+            return;
+        }
+
+        if (CHECK_ACTION_RESULT_ALLOWED !== $this->checkAllowedView($aData)) {
+            $this->_oTemplate->displayAccessDenied();
+            return;
+        }
+
+        if ($aData['type'] == 'folder' || $aFilesToDownload && count($aFilesToDownload) > 1) {
+            bx_import('BulkDownloader', $this->_aModule);
+            $oDownloader = new BxFilesBulkDownloader($this);
+            $aResult = $oDownloader->createDownloadingJob($aFilesToDownload, $aData[$CNF['FIELD_TITLE']]);
+
+            switch ($aResult['status']) {
+                case BX_FILES_DOWNLOADER_STATUS_TOO_LARGE:
+                    $this->_oTemplate->displayMsg(_t('_bx_files_txt_max_size_reached', _t_format_size(intval(getParam('bx_files_max_bulk_download_size')) * 1024 * 1024)));
+                    break;
+                case BX_FILES_DOWNLOADER_STATUS_DOWNLOADING:
+                    $this->_oTemplate->addJsTranslation('_bx_files_txt_status_downloading_ready_msg');
+                    $this->_oTemplate->displayMsg(['title' => _t('_bx_files_txt_status_downloading'), 'content' => $this->_oTemplate->parseHtmlByName('bulk_downloader_process.html', [
+                        'timeout' => BX_FILES_DOWNLOADER_TIMEOUT_REQUESTS,
+                        'action_url' => BX_DOL_URL_ROOT.$this->_oConfig->getBaseUri().'process_download/'.$aResult['job'],
+                    ])]);
+                    break;
+                case BX_FILES_DOWNLOADER_STATUS_READY:
+                    bx_smart_readfile($aResult['file'], $aResult['filename'], 'application/zip');
+                    break;
+                case BX_FILES_DOWNLOADER_STATUS_EMPTY:
+                default:
+                    $this->_oTemplate->displayPageNotFound();
+                    break;
+            }
+            exit;
+        }
+
+        $aFile = $this->getContentFile($aData);
+        if (!$aFile) {
+            $this->_oTemplate->displayPageNotFound();
+            return;
+        }
+
+        $oStorage = BxDolStorage::getObjectInstance($CNF['OBJECT_STORAGE']);
+        if (!$oStorage) {
+            $this->_oTemplate->displayErrorOccured();
+            return;
+        }
+
+        if (!$oStorage->download($aFile['remote_id'], $sToken, true)) {
+            $this->_oTemplate->displayErrorOccured();
+            return;
+        }
+        
+        exit;   
+    }
+
+    public function actionProcessDownload($iDownloadingJobId) {
+        if (!$iDownloadingJobId) die;
+
+        $aJob = $this->_oDb->getDownloadingJob($iDownloadingJobId);
+        if (!$aJob || $aJob['owner'] != bx_get_logged_profile_id()) die;
+
+        if ($aJob['result']) {
+            bx_smart_readfile($aJob['result'], $aJob['name'], 'application/zip');
+            exit;
+        }
+
+        bx_import('BulkDownloader', $this->_aModule);
+        $oDownloader = new BxFilesBulkDownloader($this);
+
+        $mRes = $oDownloader->processDownloading($aJob['files']);
+        if ($mRes === BX_FILES_DOWNLOADER_STATUS_DOWNLOADING) {
+            $this->_oDb->updateDownloadingJob($iDownloadingJobId, $aJob['files'], '');
+            echoJson([
+                'status' => 'downloading',
+            ]);
+        } else {
+            $this->_oDb->updateDownloadingJob($iDownloadingJobId, $aJob['files'], $mRes);
+            echoJson([
+                'status' => 'ready',
+            ]);
+        }
+    }
+    
+    public function getContentFile($aData) 
+    {
+        $CNF = $this->_oConfig->CNF;
+
+        if (!isset($aData[$CNF['FIELD_AUTHOR']]) || !isset($aData[$CNF['FIELD_ID']]))
+            return false;
+
+        if (isset($aData['type']) && $aData['type'] == 'folder') {
+            return [
+                'id' => $aData[$CNF['FIELD_ID']],
+                'profile_id' => $aData[$CNF['FIELD_AUTHOR']],
+                'remote_id' => 0,
+                'path' => '',
+                'file_name' => $aData[$CNF['FIELD_TITLE']],
+                'mime_type' => '',
+                'ext' => '',
+                'size' => 0,
+                'added' => $aData[$CNF['FIELD_ADDED']],
+                'modified' => 0,
+                'private' => false,
+                'is_image' => false,
+            ];
+        }
+
+        $oStorage = BxDolStorage::getObjectInstance($CNF['OBJECT_STORAGE']);
+        if (!$oStorage)
+            return false;
+
+        if (isset($aData[$CNF['FIELD_FILE_ID']]) && $aData[$CNF['FIELD_FILE_ID']])
+            return $this->_addFileFields($oStorage->getFile($aData[$CNF['FIELD_FILE_ID']]));
+        
+        $aGhostFiles = $oStorage->getGhosts ($aData[$CNF['FIELD_AUTHOR']], $aData[$CNF['FIELD_ID']]);
+        if (!$aGhostFiles)
+            return false;
+
+        return $this->_addFileFields(array_pop($aGhostFiles));
+    }
+
+    protected function _addFileFields($aFile) 
+    {
+        if (is_array($aFile))
+            $aFile['is_image'] = in_array($aFile['ext'], array('jpg', 'jpeg', 'png', 'gif', /* when ImageMagick is used - 'tif', 'tiff', 'bmp', 'ico', 'psd' */));
+        return $aFile;
+    }
+
+    public function serviceEntityFilePreview($iContentId = 0)
+    {
+        return $this->_serviceTemplateFunc ('entryFilePreview', $iContentId);
+    }
+
+    public function serviceProcessFilesData($iNumberOfFilesToProcessAtOnce = 3)
+    {
+        $CNF = $this->_oConfig->CNF;
+        
+        if (!defined('BX_SYSTEM_JAVA') || !constant('BX_SYSTEM_JAVA'))
+            return;
+        
+        $a = $this->_oDb->getNotProcessedFiles($iNumberOfFilesToProcessAtOnce);
+        if (!$a)
+            return;
+
+        $oStorage = BxDolStorage::getObjectInstance($CNF['OBJECT_STORAGE']);
+        if (!$oStorage)
+            return false;
+        
+        foreach ($a as $aContentInfo) {
+            $aFile = $this->getContentFile($aContentInfo);
+            if (!$aFile) {
+                $this->_oDb->updateFileData ($aContentInfo[$CNF['FIELD_ID']], '');
+                continue;
+            }
+
+            $sFileUrl = $oStorage->getFileUrlById($aFile['id']);
+            $sFilePath = BX_DIRECTORY_PATH_TMP . $aFile['remote_id'] . '.' . $aFile['ext'];
+            @file_put_contents($sFilePath, file_get_contents($sFileUrl));
+            if (!file_exists($sFilePath)) {
+                $this->_oDb->updateFileData ($aContentInfo[$CNF['FIELD_ID']], '');
+                continue;
+            }
+            
+            $sCommand = '"' . constant('BX_SYSTEM_JAVA') . '" -jar "' . $this->_oConfig->getHomePath() . 'data/tika-app.jar" --encoding=UTF-8 --text "' . $sFilePath . '"';
+            $sData = `$sCommand`;
+
+            @unlink($sFilePath);
+
+            $this->_oDb->updateFileData ($aContentInfo[$CNF['FIELD_ID']], $sData);
+        }
+    }
+
+    public function servicePruneDownloadingJobs()
+    {
+        $aFiles = $this->_oDb->deleteOldDownloadingJobs();
+        if ($aFiles) foreach ($aFiles as $sFile) @unlink($sFile);
+    }
+
+    protected function _getContentForTimelinePost($aEvent, $aContentInfo, $aBrowseParams = array())
+    {
+        $aResult = parent::_getContentForTimelinePost($aEvent, $aContentInfo, $aBrowseParams);
+
+        $aFile = $this->getContentFile($aContentInfo);
+        if (!$aFile['is_image']) {
+            $oStorage = BxDolStorage::getObjectInstance($this->_oConfig->CNF['OBJECT_STORAGE']);
+            $sIcon = $oStorage ? $oStorage->getFontIconNameByFileName($aFile['file_name']) : 'far file';
+
+            $aResult['raw'] = $this->_oTemplate->parseHtmlByName('timeline_post.html', array(
+                'title' => $aResult['title'],
+                'title_attr' => bx_html_attribute($aResult['title']),
+                'url' => $aResult['url'],
+                'icon' => $sIcon,
+            ));
+            $aResult['title'] = '';
+        }
+
+        return $aResult;
+    }
+
+    protected function _getImagesForTimelinePost($aEvent, $aContentInfo, $sUrl, $aBrowseParams = array())
+    {
+        $aFile = $this->getContentFile($aContentInfo);
+        if (!$aFile)
+            return array();
+
+        if (!$aFile['is_image'])
+            return array();
+
+        $sPhotoThumb = '';
+        if ($oImagesTranscoder = BxDolTranscoderImage::getObjectInstance($this->_oConfig->CNF['OBJECT_IMAGES_TRANSCODER_GALLERY']))
+            $sPhotoThumb = $oImagesTranscoder->getFileUrl($aFile['id']);
+
+        return array(
+            array('id' => $aFile['id'], 'url' => $sUrl, 'src' => $sPhotoThumb),
+        );
+    }
+
+    public function actionBookmark($iContentId) {
+        if (!$this->isLogged()) return;
+
+        $aFilesToBookmark = [];
+        if ($iContentId) $aFilesToBookmark = [$iContentId];
+        elseif (isset($_POST['bulk'])) $aFilesToBookmark = $_POST['bulk'];
+
+        if ($aFilesToBookmark)
+            foreach ($aFilesToBookmark as $iContentId) {
+                if ($iContentId <= 0) continue;
+
+                $aData = $this->_oDb->getContentInfoById((int)$iContentId);
+                if (!$aData) continue;
+
+                $this->_oDb->bookmarkFile((int)$iContentId, bx_get_logged_profile_id());
+            }
+    }
+
+    public function actionEntryPreview($iContentId) {
+        $aData = $this->_oDb->getContentInfoById((int)$iContentId);
+
+        $sJsCss = '';
+
+        $sPreviewCode = $this->_serviceTemplateFunc ('entryFilePreview', $iContentId);
+
+        // various init scripts could be there, which fail to work properly
+        // because of a fact that it is inside a popup which is at the moment is hidden
+        // so we need a way to postpone that initialization
+        $aScripts = [];
+        $sPreviewCode = preg_replace_callback('/<script>(.*)<\/script>/s', function($aMatch) use (&$aScripts) {
+            $aScripts[] = ['code' => $aMatch[1]];
+            return '';
+        }, $sPreviewCode);
+
+        // if there is a script then most likely it is a text + codemirror initialization, so include it here.
+        if ($aScripts) {
+            $sJsCss .= $this->_oTemplate->addJs('codemirror/codemirror-ext.min.js', true);
+            $sJsCss .= $this->_oTemplate->addCss(BX_DIRECTORY_PATH_PLUGINS_PUBLIC . 'codemirror/|codemirror.css', true);
+        }
+
+        $sJsCss .= $this->_oTemplate->addCss('file_handler.css', true);
+
+        $sPopupCode = $this->_oTemplate->parseHtmlByName('entry-popup.html', [
+            'content' => $sPreviewCode,
+            'bx_repeat:init_scripts' => $aScripts,
+        ]);
+
+        echoJson([
+            'popup' => [
+                'html' => PopupBox('bx-files-popup', bx_process_output($aData['title']), $sJsCss.$sPopupCode),
+                'options' => [
+                    'onShow' => 'bx_files_popup_init()',
+                ],
+            ],
+        ]);
+    }
+
+    public function actionEntryInfo($iContentId) {
+        $aData = $this->_oDb->getContentInfoById((int)$iContentId);
+
+        echoJson([
+            'popup' => [
+                'html' => PopupBox('bx-files-popup', bx_process_output($aData['title']), $this->_oTemplate->entryInfoPopup($aData)),
+            ],
+        ]);
+    }
+
+    public function actionEntryEditTitle($iContentId) {
+        $iContentId = intval($iContentId);
+        $aData = $this->_oDb->getContentInfoById($iContentId);
+
+        $CNF = &$this->_oConfig->CNF;
+
+        if (!$aData) {
+            echoJson(['message' => _t('_bx_files_txt_error')]);
+            exit;
+        }
+
+        if ($this->checkAllowedEdit($aData, false) !== CHECK_ACTION_RESULT_ALLOWED) {
+            echoJson(['message' => _t('_bx_files_txt_permission_denied')]);
+            exit;
+        }
+
+        setlocale(LC_ALL,'C.UTF-8'); //otherwise pathinfo returns empty string on a non-latin characters filenames
+
+        if (isset($_POST['title'])) {
+            if ($sNewTitle = bx_get('title')) {
+                $sExt = pathinfo($aData[$CNF['FIELD_TITLE']], PATHINFO_EXTENSION);
+                if ($sExt) $sExt = '.'.$sExt;
+
+                $this->_oDb->updateEntryTitle($iContentId, $sNewTitle.$sExt);
+                $aData = $this->_oDb->getContentInfoById($iContentId);
+                echo bx_process_output($aData[$CNF['FIELD_TITLE']]);
+            }
+            exit;
+        }
+
+
+        $sActionUrl = BX_DOL_URL_ROOT.$this->_oConfig->getBaseUri();
+        echoJson([
+            'eval' => "bx_prompt('"._t('_bx_files_form_entry_input_title')."', '".bx_js_string(pathinfo($aData[$CNF['FIELD_TITLE']], PATHINFO_FILENAME))."', function(val) {                
+                $.post('{$sActionUrl}entry_edit_title/{$iContentId}', {title: val.getValue()}, function(sTitle) {
+                    if (sTitle)
+                        $('.bx-file-entry[file_id=".$aData[$CNF['FIELD_ID']]."] .bx-files-filename a').html(sTitle);
+                });                
+            })",
+        ]);
+    }
+
+    public function actionEntryDelete($iContentId) {
+        $aFilesToDelete = [];
+        if ($iContentId) $aFilesToDelete = [$iContentId];
+        elseif (isset($_POST['bulk'])) $aFilesToDelete = $_POST['bulk'];
+
+        if ($aFilesToDelete)
+            foreach ($aFilesToDelete as $iContentId) {
+                $iContentId = intval($iContentId);
+                if ($iContentId <= 0) continue;
+
+                $aData = $this->_oDb->getContentInfoById($iContentId);
+
+                $CNF = &$this->_oConfig->CNF;
+
+                if (!$aData) {
+                    echoJson(['message' => _t('_bx_files_txt_error')]);
+                    exit;
+                }
+
+                if ($this->checkAllowedDelete($aData, false) !== CHECK_ACTION_RESULT_ALLOWED) {
+                    continue;
+                }
+
+                $this->serviceDeleteEntity($iContentId);
+            }
+
+        if (!isset($_POST['bulk'])) {
+            echoJson([
+                'eval' => "
+                    $('.bx-file-entry[file_id={$iContentId}]').fadeOut();
+                    $(window).trigger('files_browser.update');
+                ",
+            ]);
+        } else {
+            echoJson([]);
+        }
+    }
+
+    public function actionClearGhosts() {
+        if (!isLogged()) die;
+
+        $oStorage = BxDolStorage::getObjectInstance($this->_oConfig->CNF['OBJECT_STORAGE']);
+        if ($oStorage) {
+            $aFiles = $oStorage->getGhosts(bx_get_logged_profile_id(), 0);
+
+            if ($aFiles) foreach ($aFiles as $aFile) {
+                $oStorage->deleteFile($aFile['id']);
+            }
+        }
+    }
+
+    public function actionUploadCompleted() {
+        $iContext = intval(bx_get('context'));
+        $iFolder = intval(bx_get('folder'));
+
+        if (!isLogged()) {
+            echoJson(['message' => _t('_Access denied')]);
+            exit;
+        }
+
+        if ($this->checkAllowedAdd() != CHECK_ACTION_RESULT_ALLOWED || $iContext && !$this->serviceIsAllowedAddContentToProfile($iContext)) {
+            echoJson(['message' => _t('_Access denied')]);
+            exit;
+        }
+
+        $oStorage = BxDolStorage::getObjectInstance($this->_oConfig->CNF['OBJECT_STORAGE']);
+        if ($oStorage) {
+            $iAuthorProfile = bx_get_logged_profile_id();
+            $aFiles = $oStorage->getGhosts($iAuthorProfile, 0);
+
+            if ($aFiles) {
+                $aFilesIDs = [];
+                foreach($aFiles as $aFile) {
+                    $aFilesIDs[] = $aFile['id'];
+                    bx_set('title-'.$aFile['id'], $aFile['file_name'], 'post');
+                }
+                bx_set('attachments', $aFilesIDs, 'post');
+                bx_set('profile_id', $iAuthorProfile, 'post');
+                bx_set('allow_view_to', !$iContext ? BX_DOL_PG_ALL : -$iContext, 'post');
+
+                $oForm = BxDolForm::getObjectInstance($this->_oConfig->CNF['OBJECT_FORM_ENTRY_UPLOAD'], $this->_oConfig->CNF['OBJECT_FORM_ENTRY_DISPLAY_UPLOAD']);
+                $aFiles = $oForm->insert();
+
+                if ($iFolder != 0 && !empty($aFiles))
+                    $this->_oDb->moveFilesToFolder($aFiles, $iFolder);
+            }
+        }
+    }
+
+    public function actionCreateFolder() {
+        $iContext = intval(bx_get('context'));
+        $iFolder = intval(bx_get('current_folder'));
+        $sName = trim(bx_get('name'));
+
+        if (!isLogged()) {
+            echoJson(['message' => _t('_Access denied')]);
+            exit;
+        }
+
+        if ($this->checkAllowedAdd() != CHECK_ACTION_RESULT_ALLOWED || $iContext && !$this->serviceIsAllowedAddContentToProfile($iContext)) {
+            echoJson(['message' => _t('_Access denied')]);
+            exit;
+        }
+
+        if (!empty($sName)) {
+            $iAuthor = bx_get_logged_profile_id();
+            // in case it is posted to context make the context profile as an author of an entry
+            // to leave folder in case creator is removed
+            // and to delete folder when context profile is being deleted
+            $this->_oDb->createFolder($iFolder, $iContext ? $iContext : $iAuthor, !$iContext || $iAuthor == $iContext ? BX_DOL_PG_ALL : -$iContext, $sName);
+        }
+
+        echoJson([]);
+        exit;
+    }
+
+    public function actionMoveFiles() {
+        $iContentId = intval(bx_get('file'));
+
+        $aFilesToMove = [];
+        if ($iContentId) $aFilesToMove = [$iContentId];
+        elseif (isset($_POST['bulk'])) $aFilesToMove = $_POST['bulk'];
+
+        $iContentId = reset($aFilesToMove);
+
+        $aData = $this->_oDb->getContentInfoById($iContentId);
+
+        if (!$aData) {
+            echoJson(['message' => _t('_bx_files_txt_error')]);
+            exit;
+        }
+
+        $CNF = &$this->_oConfig->CNF;
+
+        $iContext = $aData[$CNF['FIELD_ALLOW_VIEW_TO']] < 0 ? -$aData[$CNF['FIELD_ALLOW_VIEW_TO']] : $aData[$CNF['FIELD_AUTHOR']];
+
+        if (!isAdmin() && ($this->checkAllowedAdd() != CHECK_ACTION_RESULT_ALLOWED || !$this->serviceIsAllowedAddContentToProfile($iContext))) {
+            echoJson(['message' => _t('_Access denied')]);
+            exit;
+        }
+
+        if (isset($_POST['move_to'])) {
+            $iMoveTo = intval(bx_get('move_to'));
+            if ($iMoveTo) {
+                $aDataMoveTo = $this->_oDb->getContentInfoById($iMoveTo);
+                if (!$aDataMoveTo) {
+                    echoJson(['message' => _t('_bx_files_txt_error')]);
+                    exit;
+                }
+
+                $iContextMoveTo = $aDataMoveTo[$CNF['FIELD_ALLOW_VIEW_TO']] < 0 ? -$aDataMoveTo[$CNF['FIELD_ALLOW_VIEW_TO']] : $aDataMoveTo[$CNF['FIELD_AUTHOR']];
+
+                if (!isAdmin() && ($this->checkAllowedAdd() != CHECK_ACTION_RESULT_ALLOWED || !$this->serviceIsAllowedAddContentToProfile($iContextMoveTo))) {
+                    echoJson(['message' => _t('_Access denied')]);
+                    exit;
+                }
+            }
+
+            $this->_oDb->moveFilesToFolder($aFilesToMove, $iMoveTo);
+
+            echoJson([
+                'eval' => "                        
+                    $(window).trigger('files_browser.update');
+                ",
+            ]);
+            exit;
+        }
+
+        $aFolders = $this->_oDb->getFoldersInContext($iContext);
+        if (!$aFolders) {
+            echoJson(['message' => _t('_bx_files_txt_move_to_nowhere')]);
+            exit;
+        }
+
+        echoJson([
+            'popup' => [
+                'html' => PopupBox('bx-files-popup', _t('_bx_files_txt_move_to'), $this->_oTemplate->getJsTree($aFilesToMove, $aFolders)),
+                'options' => [],
+            ],
+        ]);
+    }
+
+    public function serviceDeleteEntitiesByAuthor ($iProfileId) {
+        $this->_oDb->deleteProfileBookmarks($iProfileId);
+        return parent::serviceDeleteEntitiesByAuthor ($iProfileId);
+    }
+
+    public function serviceDeleteEntity ($iContentId, $sFuncDelete = 'deleteData') {
+        $aData = $this->_oDb->getContentInfoById($iContentId);
+        if ($aData['type'] == 'folder') {
+            $aNestedFiles = $this->_oDb->getFolderFiles($aData[$this->_oConfig->CNF['FIELD_ID']]);
+            if ($aNestedFiles)
+                foreach ($aNestedFiles as $iFile) {
+                    $this->serviceDeleteEntity($iFile);
+                }
+        }
+        parent::serviceDeleteEntity($iContentId, $sFuncDelete);
+    }
+
+    public function serviceBrowseContext ($iProfileId = 0, $aParams = array()) {
+        if(!$iProfileId)
+            $iProfileId = bx_process_input(bx_get('profile_id'), BX_DATA_INT);
+        if (!$iProfileId)
+            return;
+        // do not show files in context block for persons profiles
+        $oProfile = BxDolProfile::getInstance($iProfileId);
+        if ($oProfile && $oProfile->getModule() == 'bx_persons') return;
+
+        return parent::serviceBrowseContext($iProfileId, $aParams);
+    }
+}
+
+/** @} */

+ 532 - 0
modules/boonex/files/updates/12.0.1_12.0.2/source/classes/BxFilesSearchResult.php

@@ -0,0 +1,532 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Files Files
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxFilesSearchResult extends BxBaseModTextSearchResult
+{
+    protected $sOrderParamName = 'order';
+    protected $sBookmarksParamName = 'bookmarks';
+    protected $sSortingParamName = 'sorting';
+    protected $sCurrentFolderParamName = 'folder';
+    protected $sCurrentView;
+    protected $bFileManagerMode = false;
+    protected $iFileManagerUploadTo = 0;
+    protected $sMode = '';
+
+    function __construct($sMode = '', $aParams = array())
+    {
+        $aParams['unit_views'] = [
+            'extended' => 'unit.html',
+            'gallery' => 'unit_gallery.html',
+            'full' => 'unit_full.html',
+            'showcase' => 'unit_showcase.html',
+            'table' => 'unit_simple_row.html',
+        ];
+
+        //Enble filemanager (toolbar, table files layout, dynamic menus, folders support) only for author/context blocks.
+        if (($sMode == 'author' || $sMode == 'context') && !isset($aParams['no_toolbar'])) {
+            $this->bFileManagerMode = true;
+            $this->setUnitParams(['show_inline_menu' => true]);
+
+            if (!bx_get('unit_view'))
+                $aParams['unit_view'] = getParam('bx_files_default_layout_mode');
+        }
+
+        $this->sMode = $sMode;
+
+        parent::__construct($sMode, $aParams);
+
+        $this->sCurrentView = array_flip($aParams['unit_views'])[$this->sUnitTemplate];
+
+        $this->aGetParams = array_merge($this->aGetParams, [
+            $this->sOrderParamName,
+            $this->sBookmarksParamName,
+            $this->sSortingParamName,
+            $this->sUnitViewParamName,
+            $this->sCurrentFolderParamName,
+        ]);
+
+
+        $this->aSortingOptions = [
+            'name',
+            'date',
+            'type',
+            'author',
+        ];
+
+
+        $this->aCurrent = array(
+            'name' => 'bx_files',
+            'module_name' => 'bx_files',
+            'object_metatags' => 'bx_files',
+            'title' => _t('_bx_files_page_title_browse'),
+            'table' => 'bx_files_main',
+            'ownFields' => array('id', 'file_id', 'title', 'desc', 'author', 'added', 'type', 'parent_folder_id', 'allow_view_to'),
+            'searchFields' => array(),
+            'restriction' => array(
+                'author' => array('value' => '', 'field' => 'author', 'operator' => '='),
+                'featured' => array('value' => '', 'field' => 'featured', 'operator' => '<>'),
+                'status' => array('value' => 'active', 'field' => 'status', 'operator' => '='),
+                'statusAdmin' => array('value' => 'active', 'field' => 'status_admin', 'operator' => '='),
+                'files_only' => array('value' => 'file', 'field' => 'type', 'operator' => '='),
+                'context_filter' => array('value' => '', 'field' => 'allow_view_to', 'operator' => '>'),
+                'folder' => array('value' => '', 'field' => 'parent_folder_id', 'operator' => '='),
+            ),
+            'paginate' => array('perPage' => getParam('bx_files_per_page_browse'), 'start' => 0),
+            'sorting' => 'last',
+            'rss' => array(
+                'title' => '',
+                'link' => '',
+                'image' => '',
+                'profile' => 0,
+                'fields' => array (
+                    'Guid' => 'link',
+                    'Link' => 'link',
+                    'Title' => 'title',
+                    'DateTimeUTS' => 'added',
+                    'Desc' => 'desc',
+            		'Image' => 'thumb'
+                ),
+            ),
+            'ident' => 'id',
+        );
+
+        $this->sFilterName = 'bx_files_filter';
+        $this->oModule = $this->getMain();
+
+        $CNF = &$this->oModule->_oConfig->CNF;
+
+        $sSearchFields = getParam($CNF['PARAM_SEARCHABLE_FIELDS']);
+        $this->aCurrent['searchFields'] = !empty($sSearchFields) ? explode(',', $sSearchFields) : '';
+
+        $oProfileAuthor = null;
+
+        switch ($sMode) {
+            case 'author':
+                if(!$this->_updateCurrentForAuthor($sMode, $aParams, $oProfileAuthor))
+                    $this->isError = true;
+                else {
+                    //show only those files/folders which are not posted to some context
+                    $this->aCurrent['restriction']['context_filter']['value'] = 0;
+                }
+                break;
+
+            case 'context':
+                if(!$this->_updateCurrentForContext($sMode, $aParams, $oProfileAuthor))
+                    $this->isError = true;
+                break;
+
+            case 'favorite':
+                if(!$this->_updateCurrentForFavorite($sMode, $aParams, $oProfileAuthor)) 
+                    $this->isError = true;
+                break;
+
+            case 'public':
+                $this->sBrowseUrl = BxDolPermalinks::getInstance()->permalink($CNF['URL_HOME']);
+                $this->aCurrent['title'] = _t('_bx_files_page_title_browse_recent');
+                $this->aCurrent['rss']['link'] = 'modules/?r=files/rss/' . $sMode;
+                break;
+
+            case 'featured':
+                $this->sBrowseUrl = BxDolPermalinks::getInstance()->permalink($CNF['URL_HOME']);
+                $this->aCurrent['title'] = _t('_bx_files_page_title_browse_featured');
+                $this->aCurrent['restriction']['featured']['value'] = '0';
+                $this->aCurrent['rss']['link'] = 'modules/?r=files/rss/' . $sMode;
+                $this->aCurrent['sorting'] = 'featured';
+                break;
+
+            case 'popular':
+                $this->sBrowseUrl = BxDolPermalinks::getInstance()->permalink($CNF['URL_POPULAR']);
+                $this->aCurrent['title'] = _t('_bx_files_page_title_browse_popular');
+                $this->aCurrent['rss']['link'] = 'modules/?r=files/rss/' . $sMode;
+                $this->aCurrent['sorting'] = 'popular';
+                break;
+
+            case 'top':
+                $this->sBrowseUrl = BxDolPermalinks::getInstance()->permalink($CNF['URL_TOP']);
+                $this->aCurrent['title'] = _t('_bx_files_page_title_browse_top');
+                $this->aCurrent['rss']['link'] = 'modules/?r=files/rss/' . $sMode;
+                $this->aCurrent['sorting'] = 'top';
+                break;
+
+            case 'updated':
+                $this->sBrowseUrl = BxDolPermalinks::getInstance()->permalink($CNF['URL_UPDATED']);
+                $this->aCurrent['title'] = _t('_bx_files_page_title_browse_updated');
+                $this->aCurrent['rss']['link'] = 'modules/?r=files/rss/' . $sMode;
+                $this->aCurrent['sorting'] = 'updated';
+                break;
+
+            case '': // search results
+                $this->sBrowseUrl = BX_DOL_SEARCH_KEYWORD_PAGE;
+                $this->aCurrent['title'] = _t('_bx_files');
+                unset($this->aCurrent['paginate']['perPage'], $this->aCurrent['rss']);
+                break;
+
+            default:
+                $sMode = '';
+                $this->isError = true;
+        }
+
+        $this->processReplaceableMarkers($oProfileAuthor);
+        $this->addConditionsForPrivateContent($CNF, $oProfileAuthor);
+
+        if ($this->bFileManagerMode) {
+            $this->addContainerClass('bx-files-with-toolbar');
+
+            unset($this->aCurrent['restriction']['files_only']);
+            if (bx_get($this->sBookmarksParamName))
+                $this->addConditionsForBookmarks($CNF);
+
+            $this->aCurrent['sorting'] = 'name';
+            if (bx_get($this->sSortingParamName)) $this->aCurrent['sorting'] = bx_get($this->sSortingParamName);
+
+            if ($this->aCurrent['sorting'] == 'type')
+                $this->addConditionsForMimeType($CNF);
+
+            $this->removeContainerClass('bx-def-margin-sec-lefttopright-neg');
+
+            if (!$this->isError) {
+                if ($sMode == 'author' && $oProfileAuthor->id() == bx_get_logged_profile_id() || $sMode == 'context')
+                    $this->iFileManagerUploadTo = $oProfileAuthor->id();
+            }
+
+            if ($this->sCurrentView == 'table')
+                $this->removeContainerClass('bx-def-margin-bottom-neg');
+
+
+            $this->aCurrent['restriction']['folder']['value'] = intval(bx_get($this->sCurrentFolderParamName));
+            if ($this->aCurrent['restriction']['folder']['value'] < 0) {
+                //navigate folder top
+                bx_set($this->sCurrentFolderParamName, $this->oModule->_oDb->getParentFolderId(-$this->aCurrent['restriction']['folder']['value']));
+                $this->aCurrent['restriction']['folder']['value'] = bx_get($this->sCurrentFolderParamName);
+            }
+
+            //free up one place for folder up item
+            if ($this->aCurrent['restriction']['folder']['value']) {
+                $this->aCurrent['paginate']['perPage']--;
+            }
+        }
+    }
+
+    protected function addConditionsForBookmarks(&$CNF) {
+        if(empty($this->aCurrent['join']) || !is_array($this->aCurrent['join'])) $this->aCurrent['join'] = [];
+
+        $this->aCurrent['join'] = array_merge($this->aCurrent['join'], [
+            'bookmarks' => [
+                'type' => 'INNER',
+                'table' => $CNF['TABLE_BOOKMARKS'],
+                'mainTable' => $CNF['TABLE_ENTRIES'],
+                'mainField' => $CNF['FIELD_ID'],
+                'onField' => $CNF['FIELD_BOOKMARKS_ID'],
+                'joinFields' => array($CNF['FIELD_BOOKMARKS_PROFILE']),
+            ],
+        ]);
+
+        $this->aCurrent['restriction']['bookmarks'] = [
+            'value' => bx_get_logged_profile_id(),
+            'field' => $CNF['FIELD_BOOKMARKS_PROFILE'],
+            'operator' => '=',
+            'table' => $CNF['TABLE_BOOKMARKS'],
+        ];
+    }
+
+    protected function addConditionsForMimeType(&$CNF) {
+        if(empty($this->aCurrent['join']) || !is_array($this->aCurrent['join'])) $this->aCurrent['join'] = [];
+
+        $this->aCurrent['join'] = array_merge($this->aCurrent['join'], [
+            'files' => [
+                'type' => 'LEFT',
+                'table' => $CNF['TABLE_FILES'],
+                'mainTable' => $CNF['TABLE_ENTRIES'],
+                'mainField' => $CNF['FIELD_ID'],
+                'onField' => $CNF['FIELD_ID'],
+                'joinFields' => array($CNF['FIELD_MIME_TYPE']),
+            ],
+        ]);
+    }
+
+    public function addCustomParts() {
+        if ($this->_bLiveSearch) return;
+
+        if (!$this->bFileManagerMode) return;
+
+        $this->oModule->_oTemplate->addCss('main.css');
+
+        $aParams = [
+            'aRequestParams' => [
+                'unit_view_param' => $this->sUnitViewParamName,
+                'bookmarks_param' => $this->sBookmarksParamName,
+                'sorting_param' => $this->sSortingParamName,
+                'keyword_param' => 'keyword',
+                'current_folder' => $this->sCurrentFolderParamName,
+            ],
+
+            'layout' => $this->sCurrentView,
+            'bookmarks' => intval(bx_get($this->sBookmarksParamName)),
+            'sorting' => $this->aCurrent['sorting'],
+            'sorting_options' => $this->aSortingOptions,
+            'keyword' => bx_get('keyword') ? bx_get('keyword') : '',
+            'current_folder' => $this->aCurrent['restriction']['folder']['value'],
+            'current_page' => $this->aCurrent['paginate']['start'],
+        ];
+
+        return $this->getBrowseToolbar($aParams);
+    }
+
+    function getSearchData ()
+    {
+        $CNF = &$this->oModule->_oConfig->CNF;
+
+        $aData = parent::getSearchData();
+
+        if ($this->bFileManagerMode && $this->aCurrent['restriction']['folder']['value']) {
+            $aData = array_merge([0 => [
+                $CNF['FIELD_ID'] => '-1',
+                $CNF['FIELD_FILE_ID'] => '0',
+                $CNF['FIELD_TITLE'] => '..',
+                $CNF['FIELD_AUTHOR'] => bx_get_logged_profile_id(),
+                $CNF['FIELD_ADDED'] => 0,
+                $CNF['FIELD_ALLOW_VIEW_TO'] => BX_DOL_PG_ALL,
+                'type' => 'folder',
+            ]], $aData);
+            $this->aCurrent['paginate']['num']++;
+        }
+
+        return $aData;
+    }
+
+    function processing ()
+    {
+        $iViewedProfile = 0;
+        if ($this->_sMode == 'context' && $this->iFileManagerUploadTo) $iViewedProfile = $this->iFileManagerUploadTo;
+        if ($this->_sMode == 'author' && $this->aCurrent['restriction']['author']['value']) $iViewedProfile = $this->aCurrent['restriction']['author']['value'];
+
+        if ($iViewedProfile) {
+            if (is_array($iViewedProfile)) $iViewedProfile = abs($iViewedProfile[0]);
+            $oProfile = BxDolProfile::getInstance($iViewedProfile);
+            if ($oProfile->checkAllowedProfileView() !== CHECK_ACTION_RESULT_ALLOWED) {
+                $this->aCurrent['paginate']['num'] = 1;
+                return MsgBox(_t('_sys_access_denied_to_private_content'));
+            }
+        }
+
+        $sCode = parent::processing();
+        if (!$this->aCurrent['paginate']['num']  && $this->bFileManagerMode) {
+            //to show toolbar in case of empty results
+            $sCode = $this->displaySearchBox($this->addCustomParts().MsgBox(_t('_Empty')));
+        }
+        return $sCode;
+    }
+
+    function showPagination($bAdmin = false, $bChangePage = true, $bPageReload = true)
+    {
+        $aAdditionalParams = [
+            $this->sUnitViewParamName => $this->sCurrentView,
+            $this->sBookmarksParamName => intval(bx_get($this->sBookmarksParamName)),
+            $this->sSortingParamName => $this->aCurrent['sorting'],
+            $this->sCurrentFolderParamName => $this->aCurrent['restriction']['folder']['value'],
+        ];
+        $sPageUrl = $this->getCurrentUrl($aAdditionalParams, false);
+        $sOnClick = $this->getCurrentOnclick($aAdditionalParams, false);
+
+        $oPaginate = new BxTemplPaginate([
+            'page_url' => $sPageUrl,
+            'on_change_page' => $sOnClick,
+            'num' => $this->aCurrent['paginate']['num'],
+            'per_page' => $this->aCurrent['paginate']['perPage'],
+            'start' => $this->aCurrent['paginate']['start'],
+        ]);
+
+        return $sOnClick ? $oPaginate->getSimplePaginate() : $oPaginate->getPaginate();
+    }
+
+    function getAlterOrder() {
+        if (in_array($this->aCurrent['sorting'], $this->aSortingOptions)) {
+            $CNF = &$this->oModule->_oConfig->CNF;
+
+            $aSql = array();
+            switch ($this->aCurrent['sorting']) {
+                case 'name':
+                    $aSql['order'] = ' ORDER BY `'.$CNF['TABLE_ENTRIES'].'`.`type` DESC, `'.$CNF['TABLE_ENTRIES'].'`.`'.$CNF['FIELD_TITLE'].'` ASC';
+                    break;
+                case 'date':
+                    $aSql['order'] = ' ORDER BY `'.$CNF['TABLE_ENTRIES'].'`.`type` DESC, `'.$CNF['TABLE_ENTRIES'].'`.`'.$CNF['FIELD_ID'].'` DESC';
+                    break;
+                case 'author':
+                    $aSql['order'] = ' ORDER BY `'.$CNF['TABLE_ENTRIES'].'`.`type` DESC, `'.$CNF['TABLE_ENTRIES'].'`.`'.$CNF['FIELD_AUTHOR'].'` ASC, `'.$CNF['TABLE_ENTRIES'].'`.`'.$CNF['FIELD_TITLE'].'` ASC';
+                    break;
+                case 'type':
+                    $aSql['order'] = ' ORDER BY `'.$CNF['TABLE_ENTRIES'].'`.`type` DESC, `'.$CNF['TABLE_FILES'].'`.`'.$CNF['FIELD_MIME_TYPE'].'` ASC, `'.$CNF['TABLE_ENTRIES'].'`.`'.$CNF['FIELD_TITLE'].'` ASC';
+                    break;
+            }
+            return $aSql;
+        } else {
+            return parent::getAlterOrder();
+        }
+
+    }
+
+    protected function getBrowseToolbarControls(&$aParams, $sJsObject) {
+        $aSortingOptions = [];
+        if (isset($aParams['sorting_options'])) {
+            foreach ($aParams['sorting_options'] as $sSorting) {
+                $aSortingOptions[$sSorting] = _t('_bx_files_toolbar_sorting_' . $sSorting);
+            }
+        }
+
+        $oForm = new BxTemplFormView([], $this->oModule->_oTemplate);
+        $aInputSorting = [
+            'type' => 'select',
+            'name' => 'sorting',
+            'value' => $aParams['sorting'],
+            'values' => $aSortingOptions,
+            'attrs' => [
+                'onchange' => $sJsObject.'.setSorting(this.value);',
+            ],
+        ];
+
+        $aInputFilter = [
+            'type' => 'text',
+            'name' => 'keyword',
+            'value' => $aParams['keyword'],
+            'attrs' => [
+                'placeholder' => _t('_sys_search_placeholder'),
+                'onkeyup' => $sJsObject.'.onChangeFilter(this);',
+                'onpaste' => $sJsObject.'.onChangeFilter(this);',
+            ],
+        ];
+
+        $aUploadButtonParams = [];
+        $bUploadAllowed = $this->oModule->checkAllowedAdd() == CHECK_ACTION_RESULT_ALLOWED && $this->oModule->serviceIsAllowedAddContentToProfile($this->iFileManagerUploadTo);
+        if ($bUploadAllowed) {
+            $sUniqId = genRndPwd (8, false);
+            $oUploader = BxDolUploader::getObjectInstance('bx_files_html5', $this->oModule->_oConfig->CNF['OBJECT_STORAGE'], $sUniqId, $this->oModule->_oTemplate);
+
+            $aUploaderParams = array(
+                'button_title' => '',
+                'storage_private' => '0',
+                'images_transcoder' => 'bx_files_preview',
+                'content_id' => 0,
+                'attrs' => bx_convert_array2attrs(['style' => 'display:none;']),
+                'btn_class' => '',
+            );
+
+            $iMaxNestingLevel = intval(getParam($this->oModule->_oConfig->CNF['PARAM_MAX_NESTING_LEVEL']));
+            $aUploadButtonParams = [
+                'js_object' => $sJsObject,
+                'uploader_code' => $oUploader->getUploaderButton('', true, $aUploaderParams, true),
+                'uploader_js_object' => $oUploader->getNameJsInstanceUploader(),
+                'uploader_click_handler' => $oUploader->getNameJsInstanceUploader() . '.showUploaderForm();',
+                'bx_if:create_folder_allowed' => [
+                    'condition' => $iMaxNestingLevel == 0 || $this->oModule->_oDb->getFolderNestingLevel($this->aCurrent['restriction']['folder']['value']) < $iMaxNestingLevel,
+                    'content' => [
+                        'js_object' => $sJsObject,
+                        'folder_name_message' => _t('_bx_files_txt_folder_name'),
+                    ]
+                ],
+            ];
+        }
+
+        $aBulkActions = [];
+        $aBulkActions[] = ['js_object' => $sJsObject, 'handler' => 'downloadFiles', 'title' => _t('_bx_files_bulk_action_title_download'), 'icon' => 'download'];
+        if (isLogged()) {
+            $aBulkActions[] = ['js_object' => $sJsObject, 'handler' => 'bookmarkFiles', 'title' => _t('_bx_files_bulk_action_title_bookmark'), 'icon' => 'star'];
+            if ($bUploadAllowed) {
+                $aBulkActions[] = ['js_object' => $sJsObject, 'handler' => 'deleteFiles', 'title' => _t('_bx_files_bulk_action_title_delete'), 'icon' => 'remove'];
+                $aBulkActions[] = ['js_object' => $sJsObject, 'handler' => 'moveFiles', 'title' => _t('_bx_files_bulk_action_title_move_to'), 'icon' => 'file-export'];
+            }
+        }
+
+        return [
+            'sorting_dropdown' => $oForm->genRowStandard($aInputSorting),
+            'filter_box' => $oForm->genRowStandard($aInputFilter),
+            'bx_if:upload_visible' => [
+                'condition' => $bUploadAllowed,
+                'content' => $aUploadButtonParams,
+            ],
+            'bx_if:bookmarks_visible' => [
+                'condition' => isLogged(),
+                'content' => [
+                    'js_object' => $sJsObject,
+                    'bookmark_enabled' => $aParams['bookmarks'] ? 'fas' : 'far',
+                ],
+            ],
+            'bx_if:table_layout_btn' => [
+                'condition' => $aParams['layout'] == 'table',
+                'content' => [
+                    'js_object' => $sJsObject,
+                    'unit_view_param' => $aParams['aRequestParams']['unit_view_param'],
+                ],
+            ],
+            'bx_if:gallery_layout_btn' => [
+                'condition' => $aParams['layout'] == 'gallery',
+                'content' => [
+                    'js_object' => $sJsObject,
+                    'unit_view_param' => $aParams['aRequestParams']['unit_view_param'],
+                ],
+            ],
+            'bx_repeat:sorting_options' => $aSortingOptions,
+            'bx_repeat:bulk_actions' => $aBulkActions,
+        ];
+    }
+
+    protected function getBrowseToolbarBreadcrumbs($sJsObject) {
+        $aFolderPathTmpl = [];
+        $aFolderPath = $this->oModule->_oDb->getFolderPath($this->aCurrent['restriction']['folder']['value']);
+        if ($aFolderPath) {
+            $aFolderPathTmpl[] = [
+                'name' => _t('_bx_files_txt_folder_root'),
+                'folder' => '0',
+                'js_object' => $sJsObject,
+            ];
+
+            foreach ($aFolderPath as $aEntry) {
+                $aFolderPathTmpl[] = [
+                    'name' => strmaxtextlen($aEntry['name'], 20),
+                    'folder' => $aEntry['folder'],
+                    'js_object' => $sJsObject,
+                ];
+            }
+        }
+
+        return $aFolderPathTmpl;
+    }
+
+    protected function getBrowseToolbar(&$aParams) {
+        $this->oModule->_oTemplate->addJs('toolbar_tools.js');
+
+        $sUniqueIdent = mt_rand();
+        $aParams['unique_ident'] = $sUniqueIdent;
+        $aParams['context'] = $this->sMode == 'context' ? $this->iFileManagerUploadTo : '';
+
+        $sJsCode = $this->oModule->_oTemplate->getJsCode(['type' => 'toolbar_tools', 'uniq' => $sUniqueIdent], $aParams);
+        $sJsObject = $this->oModule->_oConfig->getJsObject(['type' => 'toolbar_tools', 'uniq' => $sUniqueIdent]);
+
+        $this->setUnitParams(['toolbar_js_object' => $sJsObject]);
+
+        $aToolbarControls = $this->getBrowseToolbarControls($aParams, $sJsObject);
+
+        return $this->oModule->_oTemplate->parseHtmlByName('files_browser_toolbar.html', array_merge($aToolbarControls, [
+            'js_object' => $sJsObject,
+            'js_code' => $sJsCode,
+            'unique_ident' => $sUniqueIdent,
+            'bx_repeat:folder_path' => $this->getBrowseToolbarBreadcrumbs($sJsObject),
+            'bx_if:select_all_checkbox' => [
+                'condition' => $aParams['layout'] == 'table',
+                'content' => [
+                    'js_object' => $sJsObject,
+                    'unique_ident' => $sUniqueIdent,
+                ],
+            ],
+        ]));
+    }
+}
+
+/** @} */

+ 218 - 0
modules/boonex/files/updates/12.0.1_12.0.2/source/classes/BxFilesTemplate.php

@@ -0,0 +1,218 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Files Files
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+/*
+ * Module representation.
+ */
+class BxFilesTemplate extends BxBaseModTextTemplate
+{
+    function __construct(&$oConfig, &$oDb)
+    {
+        $this->MODULE = 'bx_files';
+        parent::__construct($oConfig, $oDb);
+    }
+
+    protected function getUnitThumbAndGallery ($aData)
+    {
+        $aFile = BxDolModule::getInstance($this->MODULE)->getContentFile($aData);
+
+        if (!$aFile || !$aFile['is_image'])
+            return array('', '');
+
+        $sPhotoThumb = '';
+        if ($oImagesTranscoder = BxDolTranscoderImage::getObjectInstance(BxDolModule::getInstance($this->MODULE)->_oConfig->CNF['OBJECT_IMAGES_TRANSCODER_GALLERY']))
+            $sPhotoThumb = $oImagesTranscoder->getFileUrl($aFile['id']);
+
+        return array($sPhotoThumb, $sPhotoThumb);
+    }
+    
+    function unit ($aData, $isCheckPrivateContent = true, $sTemplateName = 'unit.html', $aParams = array())
+    {
+        $oModule = $this->getModule();
+
+        $sResult = $this->checkPrivacy($aData, $isCheckPrivateContent, $oModule, $sTemplateName);
+        if ($sResult)
+            return $sResult;
+
+        $CNF = &$oModule->_oConfig->CNF;
+
+        $aFile = $oModule->getContentFile($aData);
+        $oStorage = BxDolStorage::getObjectInstance($CNF['OBJECT_STORAGE']);
+
+        if(isset($CNF['FIELD_TITLE']) && empty($aData[$CNF['FIELD_TITLE']]))
+            $aData[$CNF['FIELD_TITLE']] = _t('_sys_txt_no_title');
+
+        $aParams['template_name'] = $sTemplateName;
+        $aVars = $this->getUnit($aData, $aParams);
+        $aVars['icon'] = $aFile && $oStorage ? $oStorage->getFontIconNameByFileName($aFile['file_name']) : 'far file';
+
+        $aVars['bx_if:no_thumb']['content']['icon'] = $aVars['icon'];
+
+
+        $aVars['bx_if:inline_menu']['condition'] = $aData[$CNF['FIELD_ID']] > 0 && isset($aParams['show_inline_menu']) && $aParams['show_inline_menu'];
+        $aVars['bx_if:inline_menu']['content'] = [];
+        if ($aVars['bx_if:inline_menu']['condition']) {
+            bx_import('BxTemplMenu');
+            $oMenu = BxTemplMenu::getObjectInstance('bx_files_view_inline', $this);
+            if ($oMenu) {
+                $oMenu->setContentId($aData[$CNF['FIELD_ID']]);
+                $oMenu->setBookmarked($this->_oDb->isFileBookmarked($aData[$CNF['FIELD_ID']], bx_get_logged_profile_id()));
+                $bEditAllowed = $this->getModule()->checkAllowedEdit($aData, false) === CHECK_ACTION_RESULT_ALLOWED;
+                $oMenu->setAllowEditOptions($bEditAllowed);
+                $aVars['bx_if:inline_menu']['content']['menu'] = $oMenu->getCode();
+            }
+        }
+
+        $sAltContentUrlHandler = '';
+        if ($oModule->_oDb->getParam($CNF['PARAM_LINK_TO_PREVIEW'])) {
+            $sAltContentUrlHandler = '$.get(\'' . BX_DOL_URL_ROOT . $oModule->_oConfig->getBaseUri() . 'entry_preview/' . $aData[$CNF['FIELD_ID']] . '\', processJsonData, \'json\'); return false;';
+        }
+
+        if ($aData['type'] == 'folder') {
+            $aVars['bx_if:meta']['condition'] = false;
+            $aVars['bx_if:no_thumb']['content']['icon'] = $aVars['icon'] = 'folder';
+            $sAltContentUrlHandler = "{$aParams['toolbar_js_object']}.folderNavigate({$aData[$CNF['FIELD_ID']]}); return false;";
+        }
+
+        $aVars['alt_content_url_handler'] = $sAltContentUrlHandler;
+        $aVars['bx_if:no_thumb']['content']['alt_content_url_handler'] = $sAltContentUrlHandler;
+        $aVars['bx_if:thumb']['content']['alt_content_url_handler'] = $sAltContentUrlHandler;
+
+        return $this->parseHtmlByName($sTemplateName, $aVars);
+    }
+
+    public function entryFilePreview ($aData)
+    {
+        $oModule = BxDolModule::getInstance($this->MODULE);
+        $CNF = $oModule->_oConfig->CNF;
+
+        $sNoPreview = MsgBox(_t('_bx_files_txt_preview_not_available'));
+        if (!($aFile = $oModule->getContentFile($aData)))
+            return $sNoPreview;
+        if (!($oFileHandler = BxDolFileHandler::getObjectInstanceByFile($aFile['file_name'])))
+            return $sNoPreview;
+        if (!($oStorage = BxDolStorage::getObjectInstance($CNF['OBJECT_STORAGE'])))
+            return $sNoPreview;
+        if (!($sFileUrl = $oStorage->getFileUrlById($aFile['id'])))
+            return $sNoPreview;
+
+        return $oFileHandler->display($sFileUrl, $aFile);
+    }
+
+    public function entryText ($aData, $sTemplateName = 'entry-text.html')
+    {
+        return $this->parseHtmlByName($sTemplateName, $this->getTmplVarsText($aData));
+    }
+
+    public function entryInfoPopup($aData) {
+        $CNF = &$this->getModule()->_oConfig->CNF;
+
+        $aFile = $this->getModule()->getContentFile($aData);
+
+        $oAuthor = BxDolProfile::getInstance($aData[$CNF['FIELD_AUTHOR']]);
+        if (!$oAuthor) $oAuthor = BxDolProfileUndefined::getInstance();
+
+        $aForm = [
+            'params' => [
+                'view_mode' => true,
+            ],
+            'inputs' => [
+                'size' => [
+                    'caption' => _t('_bx_files_entry_info_size'),
+                    'type' => 'value',
+                    'value' => _t_format_size($aFile['size']),
+                ],
+                'date' => [
+                    'caption' => _t('_bx_files_entry_info_date'),
+                    'type' => 'date_time',
+                    'value' => $aData[$CNF['FIELD_ADDED']],
+                ],
+                'author' => [
+                    'caption' => _t('_bx_files_entry_info_author'),
+                    'type' => 'textarea',
+                    'html' => 1,
+                    'value' => '<a href="'.$oAuthor->getUrl().'">'.$oAuthor->getDisplayName().'</a>',
+                ],
+            ],
+        ];
+
+        if ($aData['type'] == 'folder') {
+            unset($aForm['inputs']['size']);
+            unset($aForm['inputs']['author']);
+        }
+
+        if ($aData[$CNF['FIELD_ALLOW_VIEW_TO']] < 0) {
+            $oProfile = BxDolProfile::getInstance(-$aData[$CNF['FIELD_ALLOW_VIEW_TO']]);
+            if ($oProfile) {
+                $aForm['inputs']['context'] = [
+                    'caption' => _t('_bx_files_entry_info_context'),
+                    'type' => 'textarea',
+                    'html' => 1,
+                    'value' => '<a href="' . $oProfile->getUrl() . '">' . $oProfile->getDisplayName() . '</a>',
+                ];
+            }
+        }
+
+        $oForm = new BxTemplFormView($aForm);
+        return $this->parseHtmlByName('entry-popup.html', [
+            'content' => $oForm->getCode(),
+            'bx_repeat:init_scripts' => [],
+        ]);
+    }
+
+    public function getTmplVarsText($aData)
+    {
+        $aVars = parent::getTmplVarsText($aData);
+        $aVars = array_merge($aVars, array(
+            'entry_preview' => $this->entryFilePreview($aData),
+            'bx_if:show_content' => array(
+                'condition' => !empty($aVars['entry_title']) || !empty($aVars['entry_text']),
+                'content' => array(
+                    'entry_title' => $aVars['entry_title'],
+                    'entry_text' => $aVars['entry_text']
+                )
+            )
+        ));
+
+        return $aVars;
+    }
+
+    public function getJsTree($aFilesToMove, $aFolders) {
+        $sJsCss = '';
+        $sJsCss .= $this->addCss(BX_DIRECTORY_PATH_PLUGINS_PUBLIC . 'jstree/themes/default/|style.min.css', true);
+        $sJsCss .= $this->addJs(BX_DIRECTORY_PATH_PLUGINS_PUBLIC . 'jstree/|jstree.min.js', true);
+
+        return $this->parseHtmlByName('folders_tree.html', [
+            'js_css' => $sJsCss,
+            'list' => $this->foldersToList($aFolders, 0),
+            'files' => json_encode($aFilesToMove),
+            'actions_url' => BX_DOL_URL_ROOT.$this->getModule()->_oConfig->getBaseUri(),
+        ]);
+    }
+
+    private function foldersToList($aFolders, $iLevel) {
+        if (!$aFolders) return;
+
+        $sTreeList = '<ul>';
+        foreach ($aFolders as $aFolder) {
+            $sTreeList .=
+                '<li id="bx-files-folder-'.$aFolder['id'].'" '.($iLevel == 0 ? 'class="jstree-open"' : '').' data-jstree=\'{"icon":"sys-icon folder"}\'>'.
+                    bx_process_output($aFolder['title']).
+                    $this->foldersToList($aFolder['subfolders'], $iLevel+1).
+                '</li>';
+        }
+        $sTreeList .= '</ul>';
+
+        return $sTreeList;
+    }
+}
+
+/** @} */

+ 135 - 0
modules/boonex/files/updates/12.0.1_12.0.2/source/install/config.php

@@ -0,0 +1,135 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Files Files
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_files',
+    'title' => 'Files',
+    'note' => 'Basic blogging 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/files/',
+    'home_uri' => 'files',
+
+    'db_prefix' => 'bx_files_',
+    'class_prefix' => 'BxFiles',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Files',
+
+    /**
+     * 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_files_files'
+    ),
+
+    /**
+     * Transcoders.
+     */
+    'transcoders' => array(
+		'bx_files_preview',
+        'bx_files_gallery',
+    ),
+
+	/**
+     * Extended Search Forms.
+     */
+    'esearches' => array(
+        'bx_files',
+    	'bx_files_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',
+    ),
+
+);
+
+/** @} */

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

@@ -0,0 +1,302 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources name="en" flag="gb" title="English">
+
+	<string name="_bx_files"><![CDATA[Files]]></string>
+	<string name="_bx_files_cmts"><![CDATA[Files' Comments]]></string>
+        <string name="_bx_files_reactions"><![CDATA[Files' Reactions]]></string>
+
+	<string name="_bx_files_option_summary_chars"><![CDATA[Number of characters in auto-cropped file summary]]></string>
+	<string name="_bx_files_option_per_page_browse"><![CDATA[Number of items per page]]></string>
+    <string name="_bx_files_option_per_page_profile"><![CDATA[Number of items on profile/group page]]></string>
+	<string name="_bx_files_option_rss_num"><![CDATA[Number of items in RSS feed]]></string>
+	<string name="_bx_files_option_searchable_fields"><![CDATA[Searchable fields for keyword search]]></string>
+  <string name="_bx_files_option_per_page_for_favorites_lists"><![CDATA[Number of favorite lists per page]]></string>
+
+	<string name="_bx_files_form_upload"><![CDATA[Files Upload]]></string>
+	<string name="_bx_files_form_entry"><![CDATA[Files]]></string>
+	<string name="_bx_files_form_entry_display_add"><![CDATA[Add Files]]></string>
+	<string name="_bx_files_form_entry_display_edit"><![CDATA[Edit File]]></string>
+	<string name="_bx_files_form_entry_display_delete"><![CDATA[Delete File]]></string>
+	<string name="_bx_files_form_entry_display_view"><![CDATA[View File]]></string>
+	<string name="_bx_files_form_entry_input_author"><![CDATA[Author]]></string>
+        <string name="_bx_files_form_entry_input_sys_profile_id"><![CDATA[Profile ID]]></string>
+	<string name="_bx_files_form_entry_input_sys_do_submit"><![CDATA[Submit]]></string>
+	<string name="_bx_files_form_entry_input_do_submit"><![CDATA[Submit]]></string>
+	<string name="_bx_files_form_entry_input_sys_do_publish"><![CDATA[Publish]]></string>
+	<string name="_bx_files_form_entry_input_do_publish"><![CDATA[Publish]]></string>
+	<string name="_bx_files_form_entry_input_sys_title"><![CDATA[Title]]></string>
+	<string name="_bx_files_form_entry_input_title"><![CDATA[Title]]></string>
+	<string name="_bx_files_form_entry_input_title_err"><![CDATA[Title is essential. Please, fill in this field]]></string>
+	<string name="_bx_files_form_entry_input_sys_cat"><![CDATA[Category]]></string>
+	<string name="_bx_files_form_entry_input_cat"><![CDATA[Category]]></string>
+    <string name="_bx_files_form_entry_input_cat_err"><![CDATA[Please select category]]></string>
+	<string name="_bx_files_form_entry_input_sys_desc"><![CDATA[Description]]></string>
+    <string name="_bx_files_form_entry_input_desc"><![CDATA[Description]]></string>
+	<string name="_bx_files_form_entry_input_sys_data"><![CDATA[File data]]></string>
+	<string name="_bx_files_form_entry_input_data"><![CDATA[File data]]></string>
+	<string name="_bx_files_form_entry_input_sys_delete_confirm"><![CDATA[Delete confirmation]]></string>
+	<string name="_bx_files_form_entry_input_delete_confirm"><![CDATA[I am sure I want to delete this file]]></string>
+	<string name="_bx_files_form_entry_input_delete_confirm_info"><![CDATA[This action can not be undone]]></string>
+	<string name="_bx_files_form_entry_input_delete_confirm_error"><![CDATA[Please check this checkbox if you really want to delete the file]]></string>
+	<string name="_bx_files_form_entry_input_sys_attachment"><![CDATA[File]]></string>
+        <string name="_bx_files_form_entry_input_attachment"><![CDATA[File]]></string>
+        <string name="_bx_files_form_entry_input_attachment_err"><![CDATA[File is essential. Please, upload a file.]]></string>
+	<string name="_bx_files_form_entry_input_sys_attachments"><![CDATA[Files]]></string>
+	<string name="_bx_files_form_entry_input_attachments"><![CDATA[Files]]></string>
+        <string name="_bx_files_form_entry_input_attachments_err"><![CDATA[File is essential. Please, upload some file(s).]]></string>    
+    <string name="_bx_files_form_entry_input_sys_allow_view_to"><![CDATA[Visibility]]></string>
+    <string name="_bx_files_form_entry_input_allow_view_to"><![CDATA[Visibility]]></string>
+    <string name="_bx_files_form_entry_input_allow_view_favorite_list"><![CDATA[Visibility]]></string>
+    <string name="_bx_files_form_entry_input_picture_use_as_thumb"><![CDATA[Cover Image]]></string>
+    <string name="_bx_files_form_entry_input_sys_date_added"><![CDATA[Created]]></string>
+    <string name="_bx_files_form_entry_input_date_added"><![CDATA[Created]]></string>
+    <string name="_bx_files_form_entry_input_sys_date_changed"><![CDATA[Updated]]></string>
+    <string name="_bx_files_form_entry_input_date_changed"><![CDATA[Updated]]></string>
+	<string name="_bx_files_form_entry_input_pictures_upload"><![CDATA[Upload]]></string>
+	
+
+	<string name="_bx_files_acl_action_create_entry"><![CDATA[Create File]]></string>
+	<string name="_bx_files_acl_action_delete_entry"><![CDATA[Delete File]]></string>
+	<string name="_bx_files_acl_action_view_entry"><![CDATA[View File]]></string>
+	<string name="_bx_files_acl_action_edit_any_entry"><![CDATA[Edit Any File]]></string>
+
+	<string name="_bx_files_page_title_sys_create_entry"><![CDATA[Upload Files]]></string>
+	<string name="_bx_files_page_title_create_entry"><![CDATA[Upload Files]]></string>
+	<string name="_bx_files_page_block_title_create_entry"><![CDATA[Upload Files]]></string>
+	<string name="_bx_files_page_title_sys_edit_entry"><![CDATA[Edit]]></string>
+	<string name="_bx_files_page_title_edit_entry"><![CDATA[Edit]]></string>
+	<string name="_bx_files_page_block_title_edit_entry"><![CDATA[Edit]]></string>
+    <string name="_bx_files_page_title_sys_delete_entry"><![CDATA[Delete]]></string>
+    <string name="_bx_files_page_title_delete_entry"><![CDATA[Delete]]></string>
+    <string name="_bx_files_page_block_title_delete_entry"><![CDATA[Delete]]></string>
+	<string name="_bx_files_page_title_sys_view_entry"><![CDATA[View File]]></string>
+	<string name="_bx_files_page_title_view_entry"><![CDATA[{title}]]></string>
+	<string name="_bx_files_page_block_title_entry_text"><![CDATA[File Description]]></string>
+	<string name="_bx_files_page_title_browse"><![CDATA[Files]]></string>
+	<string name="_bx_files_page_title_search_results"><![CDATA[Files matching "{0}"]]></string>
+	<string name="_bx_files_page_title_browse_by_author"><![CDATA[Files of {display_name}]]></string>
+  <string name="_bx_files_page_title_browse_by_context"><![CDATA[Files in {display_name}]]></string>
+	<string name="_bx_files_page_title_browse_featured"><![CDATA[Featured Files]]></string>
+    <string name="_bx_files_page_title_browse_recent"><![CDATA[Latest Files]]></string>
+    <string name="_bx_files_page_title_browse_popular"><![CDATA[Popular Files]]></string>
+    <string name="_bx_files_page_title_browse_top"><![CDATA[Top Files]]></string>
+    <string name="_bx_files_page_title_browse_updated"><![CDATA[Updated Files]]></string>
+    <string name="_bx_files_page_title_sys_home"><![CDATA[Files Home]]></string>
+    <string name="_bx_files_page_title_home"><![CDATA[Files]]></string>
+    <string name="_bx_files_page_block_title_featured_entries_view_extended"><![CDATA[Featured Files]]></string>
+    <string name="_bx_files_page_block_title_recent_entries"><![CDATA[Latest Files (Gallery View)]]></string>
+    <string name="_bx_files_page_block_title_recent_entries_view_extended"><![CDATA[Latest Files]]></string>
+    <string name="_bx_files_page_block_title_entry_social_sharing"><![CDATA[Share]]></string>
+    <string name="_bx_files_page_block_title_entry_author"><![CDATA[Author]]></string>
+    <string name="_bx_files_page_block_title_entry_actions"><![CDATA[Actions]]></string>
+    <string name="_bx_files_page_block_title_sys_entry_context"><![CDATA[Posted in]]></string>
+    <string name="_bx_files_page_block_title_entry_context"><![CDATA[Posted in]]></string>
+    <string name="_bx_files_page_block_title_entry_comments"><![CDATA[Comments]]></string>
+    <string name="_bx_files_page_block_title_entry_comments_link"><![CDATA[Comments to <a href="{entry_link}">{title}</a>]]></string>
+    <string name="_bx_files_page_block_title_entry_location"><![CDATA[Location]]></string>
+    <string name="_bx_files_page_block_title_entry_attachments"><![CDATA[Attachments]]></string>
+    <string name="_bx_files_page_block_title_entry_all_actions"><![CDATA[All Actions]]></string>
+    <string name="_bx_files_page_title_sys_entries_popular"><![CDATA[Popular Files]]></string>
+    <string name="_bx_files_page_title_entries_popular"><![CDATA[Popular Files]]></string>
+    <string name="_bx_files_page_title_sys_entries_top"><![CDATA[Top Files]]></string>
+    <string name="_bx_files_page_title_entries_top"><![CDATA[Top Files]]></string>
+    <string name="_bx_files_page_title_sys_entries_updated"><![CDATA[Updated Files]]></string>
+    <string name="_bx_files_page_title_entries_updated"><![CDATA[Updated Files]]></string>
+    <string name="_bx_files_page_block_title_popular_entries"><![CDATA[Popular Files]]></string>
+    <string name="_bx_files_page_block_title_popular_entries_view_extended"><![CDATA[Popular Files (Extended View)]]></string>
+    <string name="_bx_files_page_block_title_top_entries"><![CDATA[Top Files]]></string>
+    <string name="_bx_files_page_block_title_updated_entries"><![CDATA[Updated Files]]></string>
+    <string name="_bx_files_page_block_title_favorites_entries"><![CDATA["{title}" List]]></string>
+    <string name="_bx_files_page_block_title_favorites_entries_info"><![CDATA[Info]]></string>
+    <string name="_bx_files_page_block_title_favorites_entries_actions"><![CDATA[Favorites List Actions]]></string>
+    <string name="_bx_files_page_title_sys_view_entry_comments"><![CDATA[File Comments]]></string>
+    <string name="_bx_files_page_title_view_entry_comments"><![CDATA[Comments to {title}]]></string>
+    <string name="_bx_files_page_title_sys_entries_of_author"><![CDATA[Files of author]]></string>
+    <string name="_bx_files_page_title_entries_of_author"><![CDATA[Files by {display_name}]]></string>
+    <string name="_bx_files_page_title_sys_entries_in_context"><![CDATA[Files in context]]></string>
+    <string name="_bx_files_page_title_entries_in_context"><![CDATA[Files in {display_name}]]></string>
+    <string name="_bx_files_page_block_title_favorites_of_author"><![CDATA[Favorites by <a href="{profile_link}">{display_name}</a>]]></string>
+    <string name="_bx_files_page_block_title_sys_favorites_of_author"><![CDATA[Favorites of author]]></string>
+    <string name="_bx_files_page_block_title_entries_of_author"><![CDATA[Files by <a href="{profile_link}">{display_name}</a>]]></string>
+    <string name="_bx_files_page_block_title_sys_entries_of_author"><![CDATA[Files of author]]></string>
+    <string name="_bx_files_page_block_title_entries_in_context"><![CDATA[Files in <a href="{profile_link}">{display_name}</a>]]></string>
+    <string name="_bx_files_page_block_title_sys_entries_in_context"><![CDATA[Files in context]]></string>
+    <string name="_bx_files_page_block_title_entries_actions"><![CDATA[Files actions]]></string>
+    <string name="_bx_files_page_block_title_browse_cmts"><![CDATA[Files' Comments]]></string>
+	<string name="_bx_files_page_title_sys_manage"><![CDATA[Manage Own]]></string>
+	<string name="_bx_files_page_title_sys_manage_administration"><![CDATA[Manage All]]></string>
+	<string name="_bx_files_page_title_manage"><![CDATA[Manage]]></string>
+	<string name="_bx_files_page_block_title_system_manage"><![CDATA[Manage Own]]></string>
+	<string name="_bx_files_page_block_title_system_manage_administration"><![CDATA[Manage All]]></string>
+	<string name="_bx_files_page_block_title_manage"><![CDATA[Manage]]></string>    
+	<string name="_bx_files_page_block_title_popular_keywords"><![CDATA[Popular Hashtags]]></string>
+	<string name="_bx_files_page_block_title_cats"><![CDATA[Files Categories]]></string>
+	<string name="_bx_files_page_block_title_entry_info"><![CDATA[Info]]></string>
+	<string name="_bx_files_page_block_title_sys_my_entries"><![CDATA[User Files]]></string>
+        <string name="_bx_files_page_block_title_my_entries"><![CDATA[{display_name} Files]]></string>
+	<string name="_bx_files_page_block_title_entry_file_preview"><![CDATA[File Preview]]></string>
+	<string name="_bx_files_page_title_sys_entries_search"><![CDATA[Search]]></string>
+    <string name="_bx_files_page_title_entries_search"><![CDATA[Search]]></string>
+    <string name="_bx_files_page_title_sys_entries_favorites"><![CDATA[Favorives Files]]></string>
+    <string name="_bx_files_page_title_entries_favorites"><![CDATA[Favorives Files]]></string>
+    <string name="_bx_files_page_block_title_search_form"><![CDATA[Search Form]]></string>
+    <string name="_bx_files_page_block_title_search_results"><![CDATA[Search Results]]></string>
+    <string name="_bx_files_page_block_title_search_form_cmts"><![CDATA[Comments Search Form]]></string>
+    <string name="_bx_files_page_block_title_search_results_cmts"><![CDATA[Comments Search Results]]></string>
+    <string name="_bx_files_page_block_title_sys_recent_entries_view_showcase"><![CDATA[Latest Files (Showcase View)]]></string>
+    <string name="_bx_files_page_block_title_recent_entries_view_showcase"><![CDATA[Latest Files]]></string>
+    <string name="_bx_files_page_block_title_sys_popular_entries_view_showcase"><![CDATA[Popular Files (Showcase View)]]></string>
+    <string name="_bx_files_page_block_title_popular_entries_view_showcase"><![CDATA[Popular Files]]></string>
+    <string name="_bx_files_page_block_title_sys_featured_entries_view_showcase"><![CDATA[Featured Files (Showcase View)]]></string>
+    <string name="_bx_files_page_block_title_featured_entries_view_showcase"><![CDATA[Featured Files]]></string>
+
+    <string name="_bx_files_menu_set_title_view_entry"><![CDATA[File Actions]]></string>
+    <string name="_bx_files_menu_title_view_entry"><![CDATA[File Actions]]></string>
+    <string name="_bx_files_menu_title_submenu"><![CDATA[Files Submenu]]></string>
+    <string name="_bx_files_menu_set_title_submenu"><![CDATA[Files Submenu]]></string>
+    <string name="_bx_files_menu_item_title_system_create_entry"><![CDATA[File]]></string>
+    <string name="_bx_files_menu_item_title_create_entry"><![CDATA[File]]></string>
+    <string name="_bx_files_menu_item_title_system_edit_entry"><![CDATA[Edit]]></string>
+    <string name="_bx_files_menu_item_title_edit_entry"><![CDATA[Edit]]></string>
+    <string name="_bx_files_menu_item_title_system_edit_title"><![CDATA[Rename]]></string>
+    <string name="_bx_files_menu_item_title_edit_title"><![CDATA[Rename]]></string>
+    <string name="_bx_files_menu_item_title_system_delete_entry"><![CDATA[Delete]]></string>
+    <string name="_bx_files_menu_item_title_delete_entry"><![CDATA[Delete]]></string>
+    <string name="_bx_files_menu_item_title_system_view_entry"><![CDATA[View File]]></string>
+    <string name="_bx_files_menu_item_title_system_entries_home"><![CDATA[Files]]></string>
+    <string name="_bx_files_menu_item_title_entries_home"><![CDATA[Files]]></string>
+    <string name="_bx_files_menu_item_title_system_entries_public"><![CDATA[Latest]]></string>
+    <string name="_bx_files_menu_item_title_entries_public"><![CDATA[Latest]]></string>
+    <string name="_bx_files_menu_item_title_system_entries_search"><![CDATA[Search]]></string>
+    <string name="_bx_files_menu_item_title_entries_search"><![CDATA[Search]]></string>
+    <string name="_bx_files_menu_item_title_system_entries_manage"><![CDATA[Manage]]></string>
+    <string name="_bx_files_menu_item_title_entries_manage"><![CDATA[Manage]]></string>
+    <string name="_bx_files_menu_item_title_system_entries_popular"><![CDATA[Popular]]></string>
+    <string name="_bx_files_menu_item_title_entries_popular"><![CDATA[Popular]]></string>
+    <string name="_bx_files_menu_item_title_system_entries_top"><![CDATA[Top]]></string>
+    <string name="_bx_files_menu_item_title_entries_top"><![CDATA[Top]]></string>
+    <string name="_bx_files_menu_title_view_entry_submenu"><![CDATA[View File Submenu]]></string>
+    <string name="_bx_files_menu_set_title_view_entry_submenu"><![CDATA[View File Submenu]]></string>
+    <string name="_bx_files_menu_item_title_view_entry_submenu_entry"><![CDATA[File]]></string>
+    <string name="_bx_files_menu_item_title_view_entry_submenu_comments"><![CDATA[Comments]]></string>
+    <string name="_bx_files_menu_item_title_system_view_entry_comments"><![CDATA[File Comments]]></string>
+    <string name="_bx_files_menu_item_title_system_view_entries_author"><![CDATA[Files]]></string>
+    <string name="_bx_files_menu_item_title_view_entries_author"><![CDATA[Files]]></string>
+    <string name="_bx_files_menu_item_title_system_view_entries_in_context"><![CDATA[Files]]></string>
+    <string name="_bx_files_menu_item_title_view_entries_in_context"><![CDATA[Files]]></string>
+    <string name="_bx_files_menu_title_entries_my"><![CDATA[My Files Action Menu]]></string>
+    <string name="_bx_files_menu_set_title_entries_my"><![CDATA[My Files Menu]]></string>
+	<string name="_bx_files_menu_item_title_system_manage_my_files"><![CDATA[My files]]></string>
+    <string name="_bx_files_menu_item_title_manage_my_files"><![CDATA[Files]]></string>
+    <string name="_bx_files_menu_set_title_manage_tools"><![CDATA[Manage Tools Submenu]]></string>
+    <string name="_bx_files_menu_title_manage_tools"><![CDATA[Manage Tools Submenu]]></string>
+    <string name="_bx_files_menu_item_title_system_manage_account"><![CDATA[Manage account]]></string>
+    <string name="_bx_files_menu_item_title_manage_account"><![CDATA[Manage account]]></string>
+	<string name="_bx_files_menu_item_title_system_admt_files"><![CDATA[Files]]></string>
+	<string name="_bx_files_menu_item_title_admt_files"><![CDATA[Files]]></string>
+	<string name="_bx_files_menu_item_title_manage_my"><![CDATA[My Files]]></string>
+	<string name="_bx_files_menu_item_title_manage_all"><![CDATA[All Files]]></string>
+	<string name="_bx_files_menu_item_title_system_download_file"><![CDATA[Download]]></string>
+	<string name="_bx_files_menu_item_title_download_file"><![CDATA[Download]]></string>
+
+	<string name="_bx_files_grid_filter_item_title_adm_select_one_filter1"><![CDATA[All Statuses]]></string>
+	<string name="_bx_files_grid_filter_item_title_adm_active"><![CDATA[Active]]></string>
+	<string name="_bx_files_grid_filter_item_title_adm_hidden"><![CDATA[Hidden]]></string>
+	<string name="_bx_files_grid_column_title_adm_active"><![CDATA[Active]]></string>
+    <string name="_bx_files_grid_column_title_adm_title"><![CDATA[Title]]></string>
+    <string name="_bx_files_grid_column_title_adm_added"><![CDATA[Added]]></string>
+    <string name="_bx_files_grid_column_title_adm_author"><![CDATA[Author]]></string>
+    <string name="_bx_files_grid_action_title_adm_edit"><![CDATA[Edit]]></string>
+    <string name="_bx_files_grid_action_title_adm_delete"><![CDATA[Delete]]></string>
+    <string name="_bx_files_grid_action_title_adm_clear_reports"><![CDATA[Clear reports]]></string>
+    <string name="_bx_files_grid_action_title_adm_more_actions"><![CDATA[More Actions]]></string>
+    <string name="_bx_files_grid_action_title_adm_audit_content"><![CDATA[Audit actions]]></string>
+  <string name="_bx_files_grid_action_err_delete"><![CDATA[Cannot delete the selected file(s).]]></string>
+    <string name="_bx_files_grid_txt_account_manager"><![CDATA[Redirect to manage account.]]></string>
+
+    <string name="_bx_files_chart_growth"><![CDATA[Files: Growth]]></string>
+    <string name="_bx_files_chart_growth_speed"><![CDATA[Files: Growth Speed]]></string>
+
+    <string name="_bx_files_search_extended"><![CDATA[Files Search]]></string>
+    <string name="_bx_files_search_extended_cmts"><![CDATA[Files Comments Search]]></string>
+
+    <string name="_bx_files_pre_lists_cats"><![CDATA[File categories]]></string>
+    <string name="_bx_files_cat_documentation"><![CDATA[Documentation]]></string>
+    <string name="_bx_files_cat_presentation"><![CDATA[Presentation]]></string>
+    <string name="_bx_files_cat_report"><![CDATA[Report]]></string>
+    <string name="_bx_files_cat_proposal"><![CDATA[Proposal]]></string>
+    <string name="_bx_files_cat_list"><![CDATA[List]]></string>
+    <string name="_bx_files_cat_record"><![CDATA[Audio record]]></string>
+    <string name="_bx_files_cat_screencast"><![CDATA[Screencast]]></string>
+    <string name="_bx_files_cat_screenshot"><![CDATA[Screenshot]]></string>
+    <string name="_bx_files_cat_sketch"><![CDATA[Sketch]]></string>
+    <string name="_bx_files_cat_archive"><![CDATA[Archive]]></string>
+    <string name="_bx_files_cat_backup"><![CDATA[Backup]]></string>
+
+    <string name="_bx_files_txt_all_entries_by"><![CDATA[{0} files]]></string>
+    <string name="_bx_files_txt_all_entries_in"><![CDATA[<a href="{0}">All Files in {1} ({2})</a>]]></string>
+    <string name="_bx_files_txt_preview_not_available"><![CDATA[Preview isn't available, please download this file to view it]]></string>
+    <string name="_bx_files_txt_sample_single"><![CDATA[file]]></string>
+    <string name="_bx_files_txt_sample_single_with_article"><![CDATA[a file]]></string>
+    <string name="_bx_files_txt_sample_comment_single"><![CDATA[comment to file]]></string>
+    <string name="_bx_files_txt_sample_vote_single"><![CDATA[vote to file]]></string>
+    <string name="_bx_files_txt_sample_reaction_single"><![CDATA['{0}' reaction to file]]></string>
+    <string name="_bx_files_txt_sample_score_up_single"><![CDATA[score up vote to file]]></string>
+    <string name="_bx_files_txt_sample_score_down_single"><![CDATA[score down vote to file]]></string>
+
+    <string name="_bx_files_privacy_public"><![CDATA[Public]]></string>
+    <string name="_bx_files_privacy_participants"><![CDATA[Participants]]></string>
+
+    <string name="_bx_files_menu_title_view_inline"><![CDATA[File inline menu]]></string>
+    <string name="_bx_files_menu_set_title_view_inline"><![CDATA[File inline menu]]></string>
+    <string name="_bx_files_menu_item_title_system_move_to_entry"><![CDATA[Move to...]]></string>
+    <string name="_bx_files_menu_item_title_move_to_entry"><![CDATA[Move to...]]></string>
+    <string name="_bx_files_menu_item_title_system_info_entry"><![CDATA[Info]]></string>
+    <string name="_bx_files_menu_item_title_info_entry"><![CDATA[Info]]></string>
+    <string name="_bx_files_menu_item_title_system_bookmark"><![CDATA[Bookmark]]></string>
+    <string name="_bx_files_menu_item_title_bookmark"><![CDATA[Bookmark]]></string>
+
+    <string name="_bx_files_menu_item_title_system_sm_size"><![CDATA[Size]]></string>
+    <string name="_bx_files_menu_item_title_sm_size"><![CDATA[Size]]></string>
+
+    <string name="_bx_files_option_link_to_preview"><![CDATA[Link file title to a preview popup instead of a file view page in context blocks]]></string>
+    <string name="_bx_files_option_max_nesting_level"><![CDATA[Folders max nesting level]]></string>
+    <string name="_bx_files_option_max_bulk_download_size"><![CDATA[Max size of files in a bulk/folder download archive (Mb)]]></string>
+
+    <string name="_bx_files_entry_info_size"><![CDATA[Size]]></string>
+    <string name="_bx_files_entry_info_date"><![CDATA[Date]]></string>
+    <string name="_bx_files_entry_info_author"><![CDATA[By]]></string>
+    <string name="_bx_files_entry_info_context"><![CDATA[Uploaded to]]></string>
+
+    <string name="_bx_files_toolbar_view_table"><![CDATA[Table View]]></string>
+    <string name="_bx_files_toolbar_view_gallery"><![CDATA[Gallery View]]></string>
+    <string name="_bx_files_toolbar_view_bookmarks"><![CDATA[Bookmarked files]]></string>
+    <string name="_bx_files_toolbar_sorting_name"><![CDATA[Order by Name]]></string>
+    <string name="_bx_files_toolbar_sorting_date"><![CDATA[Order by Date]]></string>
+    <string name="_bx_files_toolbar_sorting_type"><![CDATA[Order by Type]]></string>
+    <string name="_bx_files_toolbar_sorting_author"><![CDATA[Order by Author]]></string>
+
+    <string name="_bx_files_txt_error"><![CDATA[File not found]]></string>
+    <string name="_bx_files_txt_permission_denied"><![CDATA[Permission denied]]></string>
+    <string name="_bx_files_txt_upload"><![CDATA[Upload]]></string>
+    <string name="_bx_files_txt_add_folder"><![CDATA[Add Folder]]></string>
+    <string name="_bx_files_txt_folder_name"><![CDATA[Folder name]]></string>
+    <string name="_bx_files_txt_folder_root"><![CDATA[Root]]></string>
+    <string name="_bx_files_txt_move_to"><![CDATA[Move To]]></string>
+    <string name="_bx_files_txt_move_to_nowhere"><![CDATA[There are no folders created yet]]></string>
+    <string name="_bx_files_txt_move_here"><![CDATA[Move here?]]></string>
+    <string name="_bx_files_txt_max_size_reached"><![CDATA[Too large archive for downloading. Max overall size of files for bulk downloading is {0}.]]></string>
+
+    <string name="_bx_files_bulk_action_title_download"><![CDATA[Download]]></string>
+    <string name="_bx_files_bulk_action_title_bookmark"><![CDATA[Bookmark]]></string>
+    <string name="_bx_files_bulk_action_title_delete"><![CDATA[Delete]]></string>
+    <string name="_bx_files_bulk_action_title_move_to"><![CDATA[Move To...]]></string>
+
+    <string name="_bx_files_txt_status_downloading"><![CDATA[Downloading...]]></string>
+    <string name="_bx_files_txt_status_downloading_msg"><![CDATA[The download will start shortly...]]></string>
+    <string name="_bx_files_txt_status_downloading_ready_msg"><![CDATA[Click <a href={0}>here</a> if the download doesn't start automatically.]]></string>
+
+    <string name="_bx_files_option_allowed_ext"><![CDATA[Allow only the following extensions (comma separated list)]]></string>
+    <string name="_bx_files_option_default_layout_mode"><![CDATA[Files default layout]]></string>
+
+</resources>

+ 501 - 0
modules/boonex/files/updates/12.0.1_12.0.2/source/install/sql/enable.sql

@@ -0,0 +1,501 @@
+
+-- 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_files', '_bx_files', 'bx_files@modules/boonex/files/|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_files', '_bx_files', 1);
+SET @iCategId = LAST_INSERT_ID();
+
+INSERT INTO `sys_options` (`name`, `value`, `category_id`, `caption`, `type`, `check`, `check_error`, `extra`, `order`) VALUES
+('bx_files_summary_chars', '700', @iCategId, '_bx_files_option_summary_chars', 'digit', '', '', '', 1),
+('bx_files_default_layout_mode', 'gallery', @iCategId, '_bx_files_option_default_layout_mode', 'select', '', '', 'gallery,table', 4),
+('bx_files_show_link_to_preview', '', @iCategId, '_bx_files_option_link_to_preview', 'checkbox', '', '', '', 5),
+('bx_files_max_nesting_level', '3', @iCategId, '_bx_files_option_max_nesting_level', 'digit', '', '', '', 6),
+('bx_files_max_bulk_download_size', '100', @iCategId, '_bx_files_option_max_bulk_download_size', 'digit', '', '', '', 7),
+('bx_files_allowed_ext', '', @iCategId, '_bx_files_option_allowed_ext', 'digit', '', '', '', 8),
+('bx_files_per_page_browse', '12', @iCategId, '_bx_files_option_per_page_browse', 'digit', '', '', '', 10),
+('bx_files_per_page_profile', '6', @iCategId, '_bx_files_option_per_page_profile', 'digit', '', '', '', 12),
+('bx_files_per_page_browse_showcase', '32', @iCategId, '_sys_option_per_page_browse_showcase', 'digit', '', '', '', 15),
+('bx_files_per_page_for_favorites_lists', '5', @iCategId, '_bx_files_option_per_page_for_favorites_lists', 'digit', '', '', '', 17),
+('bx_files_rss_num', '10', @iCategId, '_bx_files_option_rss_num', 'digit', '', '', '', 20),
+('bx_files_searchable_fields', 'title,desc,data', @iCategId, '_bx_files_option_searchable_fields', 'list', '', '', 'a:2:{s:6:"module";s:8:"bx_files";s:6:"method";s:21:"get_searchable_fields";}', 30);
+
+
+-- PAGE: create entry
+
+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_files_create_entry', '_bx_files_page_title_sys_create_entry', '_bx_files_page_title_create_entry', 'bx_files', 5, 2147483647, 1, 'create-file', 'page.php?i=create-file', '', '', '', 0, 1, 0, 'BxFilesPageBrowse', 'modules/boonex/files/classes/BxFilesPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks` (`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES
+('bx_files_create_entry', 1, 'bx_files', '_bx_files_page_block_title_create_entry', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:8:"bx_files";s:6:"method";s:13:"entity_create";}', 0, 1, 1);
+
+
+-- PAGE: edit entry
+
+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_files_edit_entry', '_bx_files_page_title_sys_edit_entry', '_bx_files_page_title_edit_entry', 'bx_files', 5, 2147483647, 1, 'edit-file', '', '', '', '', 0, 1, 0, 'BxFilesPageEntry', 'modules/boonex/files/classes/BxFilesPageEntry.php');
+
+INSERT INTO `sys_pages_blocks` (`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES
+('bx_files_edit_entry', 1, 'bx_files', '_bx_files_page_block_title_edit_entry', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:8:"bx_files";s:6:"method";s:11:"entity_edit";}', 0, 0, 0);
+
+
+-- PAGE: delete entry
+
+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_files_delete_entry', '_bx_files_page_title_sys_delete_entry', '_bx_files_page_title_delete_entry', 'bx_files', 5, 2147483647, 1, 'delete-file', '', '', '', '', 0, 1, 0, 'BxFilesPageEntry', 'modules/boonex/files/classes/BxFilesPageEntry.php');
+
+INSERT INTO `sys_pages_blocks` (`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES
+('bx_files_delete_entry', 1, 'bx_files', '_bx_files_page_block_title_delete_entry', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:8:"bx_files";s:6:"method";s:13:"entity_delete";}', 0, 0, 0);
+
+
+-- PAGE: view entry
+
+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_files_view_entry', '_bx_files_page_title_sys_view_entry', '_bx_files_page_title_view_entry', 'bx_files', 12, 2147483647, 1, 'view-file', '', '', '', '', 0, 1, 0, 'BxFilesPageEntry', 'modules/boonex/files/classes/BxFilesPageEntry.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_files_view_entry', 2, 'bx_files', '', '_bx_files_page_block_title_entry_text', 13, 2147483647, 'service', 'a:2:{s:6:\"module\";s:8:\"bx_files\";s:6:\"method\";s:17:\"entity_text_block\";}', 0, 0, 1, 1),
+('bx_files_view_entry', 1, 'bx_files', '', '_bx_files_page_block_title_entry_file_preview', 3, 2147483647, 'service', 'a:2:{s:6:\"module\";s:8:\"bx_files\";s:6:\"method\";s:19:\"entity_file_preview\";}', 0, 0, 0, 0),
+('bx_files_view_entry', 3, 'bx_files', '', '_bx_files_page_block_title_entry_author', 13, 2147483647, 'service', 'a:2:{s:6:\"module\";s:8:\"bx_files\";s:6:\"method\";s:13:\"entity_author\";}', 0, 0, 1, 2),
+('bx_files_view_entry', 3, 'bx_files', '_bx_files_page_block_title_sys_entry_context', '_bx_files_page_block_title_entry_context', 13, 2147483647, 'service', 'a:2:{s:6:\"module\";s:8:\"bx_files\";s:6:\"method\";s:14:\"entity_context\";}', 0, 0, 1, 1),
+('bx_files_view_entry', 3, 'bx_files', '', '_bx_files_page_block_title_entry_info', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:8:\"bx_files\";s:6:\"method\";s:11:\"entity_info\";}', 0, 0, 1, 3),
+('bx_files_view_entry', 3, 'bx_files', '', '_bx_files_page_block_title_entry_location', 13, 2147483647, 'service', 'a:2:{s:6:\"module\";s:8:\"bx_files\";s:6:\"method\";s:15:\"entity_location\";}', 0, 0, 0, 0),
+('bx_files_view_entry', 2, 'bx_files', '', '_bx_files_page_block_title_entry_all_actions', 13, 2147483647, 'service', 'a:2:{s:6:\"module\";s:8:\"bx_files\";s:6:\"method\";s:18:\"entity_all_actions\";}', 0, 0, 1, 2),
+('bx_files_view_entry', 4, 'bx_files', '', '_bx_files_page_block_title_entry_actions', 13, 2147483647, 'service', 'a:2:{s:6:\"module\";s:8:\"bx_files\";s:6:\"method\";s:14:\"entity_actions\";}', 0, 0, 0, 0),
+('bx_files_view_entry', 4, 'bx_files', '', '_bx_files_page_block_title_entry_social_sharing', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:8:\"bx_files\";s:6:\"method\";s:21:\"entity_social_sharing\";}', 0, 0, 0, 0),
+('bx_files_view_entry', 2, 'bx_files', '', '_bx_files_page_block_title_entry_comments', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:8:\"bx_files\";s:6:\"method\";s:15:\"entity_comments\";}', 0, 0, 1, 3),
+('bx_files_view_entry', 3, 'bx_files', '', '_bx_files_page_block_title_entry_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:8:\"bx_files\";i:1;s:4:\"{id}\";}s:5:\"class\";s:20:\"TemplServiceMetatags\";}', 0, 0, 1, 4);
+
+
+-- 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_files_view_entry_comments', '_bx_files_page_title_sys_view_entry_comments', '_bx_files_page_title_view_entry_comments', 'bx_files', 5, 2147483647, 1, 'view-file-comments', '', '', '', '', 0, 1, 0, 'BxFilesPageEntry', 'modules/boonex/files/classes/BxFilesPageEntry.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_files_view_entry_comments', 1, 'bx_files', '_bx_files_page_block_title_entry_comments', '_bx_files_page_block_title_entry_comments_link', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:8:\"bx_files\";s:6:\"method\";s:15:\"entity_comments\";}', 0, 0, 1);
+
+
+-- PAGE: popular 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_files_popular', '_bx_files_page_title_sys_entries_popular', '_bx_files_page_title_entries_popular', 'bx_files', 5, 2147483647, 1, 'files-popular', 'page.php?i=files-popular', '', '', '', 0, 1, 0, 'BxFilesPageBrowse', 'modules/boonex/files/classes/BxFilesPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_files_popular', 1, 'bx_files', '_bx_files_page_block_title_popular_entries', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:8:"bx_files";s:6:"method";s:14:"browse_popular";s:6:"params";a:3:{s:9:"unit_view";s:7:"gallery";s:13:"empty_message";b:1;s:13:"ajax_paginate";b:0;}}', 0, 1, 1);
+
+
+-- PAGE: top 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_files_top', '_bx_files_page_title_sys_entries_top', '_bx_files_page_title_entries_top', 'bx_files', 5, 2147483647, 1, 'files-top', 'page.php?i=files-top', '', '', '', 0, 1, 0, 'BxFilesPageBrowse', 'modules/boonex/files/classes/BxFilesPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_files_top', 1, 'bx_files', '_bx_files_page_block_title_top_entries', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:8:"bx_files";s:6:"method";s:10:"browse_top";s:6:"params";a:3:{s:9:"unit_view";s:7:"gallery";s:13:"empty_message";b:1;s:13:"ajax_paginate";b:0;}}', 0, 1, 1);
+
+
+-- PAGE: recently updated 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_files_updated', '_bx_files_page_title_sys_entries_updated', '_bx_files_page_title_entries_updated', 'bx_files', 5, 2147483647, 1, 'files-updated', 'page.php?i=files-updated', '', '', '', 0, 1, 0, 'BxFilesPageBrowse', 'modules/boonex/files/classes/BxFilesPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_files_updated', 1, 'bx_files', '_bx_files_page_block_title_updated_entries', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:8:"bx_files";s:6:"method";s:14:"browse_updated";s:6:"params";a:3:{s:9:"unit_view";s:7:"gallery";s:13:"empty_message";b:1;s:13:"ajax_paginate";b:0;}}', 0, 1, 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_files_author', 'files-author', '_bx_files_page_title_sys_entries_of_author', '_bx_files_page_title_entries_of_author', 'bx_files', 5, 2147483647, 1, '', '', '', '', 0, 1, 0, 'BxFilesPageAuthor', 'modules/boonex/files/classes/BxFilesPageAuthor.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_files_author', 1, 'bx_files', '', '_bx_files_page_block_title_entries_actions', 13, 2147483647, 'service', 'a:2:{s:6:\"module\";s:8:\"bx_files\";s:6:\"method\";s:18:\"my_entries_actions\";}', 0, 0, 1, 1),
+('bx_files_author', 1, 'bx_files', '_bx_files_page_block_title_sys_favorites_of_author', '_bx_files_page_block_title_favorites_of_author', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:8:"bx_files";s:6:"method";s:21:"browse_favorite_lists";s:6:"params";a:2:{s:10:"profile_id";s:12:"{profile_id}";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, 2),
+('bx_files_author', 1, 'bx_files', '_bx_files_page_block_title_sys_entries_of_author', '_bx_files_page_block_title_entries_of_author', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:8:\"bx_files\";s:6:\"method\";s:13:\"browse_author\";}', 0, 0, 1, 3),
+('bx_files_author', 1, 'bx_files', '_bx_files_page_block_title_sys_entries_in_context', '_bx_files_page_block_title_entries_in_context', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:8:"bx_files";s:6:"method";s:14:"browse_context";s:6:"params";a:2:{s:10:"profile_id";s:12:"{profile_id}";i:0;a:1:{s:13:"empty_message";b:0;}}}', 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_files_favorites', '_bx_files_page_title_sys_entries_favorites', '_bx_files_page_title_entries_favorites', 'bx_files', 12, 2147483647, 1, 'files-favorites', 'page.php?i=files-favorites', '', '', '', 0, 1, 0, 'BxFilesPageListEntry', 'modules/boonex/files/classes/BxFilesPageListEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_files_favorites', 2, 'bx_files', '_bx_files_page_block_title_favorites_entries', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:8:"bx_files";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_files_favorites', 3, 'bx_files', '_bx_files_page_block_title_favorites_entries_info', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:8:"bx_files";s:6:"method";s:19:"favorites_list_info";}', 0, 0, 0),
+('bx_files_favorites', 3, 'bx_files', '_bx_files_page_block_title_favorites_entries_actions', 13, 2147483647, 'service', 'a:2:{s:6:"module";s:8:"bx_files";s:6:"method";s:22:"favorites_list_actions";}', 0, 0, 1);
+
+
+-- PAGE: entries in context
+ 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_files_context', 'files-context', '_bx_files_page_title_sys_entries_in_context', '_bx_files_page_title_entries_in_context', 'bx_files', 5, 2147483647, 1, '', '', '', '', 0, 1, 0, 'BxFilesPageAuthor', 'modules/boonex/files/classes/BxFilesPageAuthor.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_files_context', 1, 'bx_files', '_bx_files_page_block_title_sys_entries_in_context', '_bx_files_page_block_title_entries_in_context', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:8:\"bx_files\";s:6:\"method\";s:14:\"browse_context\";}', 0, 0, 1, 1);
+ 
+-- PAGE: module home
+
+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_files_home', 'files-home', '_bx_files_page_title_sys_home', '_bx_files_page_title_home', 'bx_files', 2, 2147483647, 1, 'page.php?i=files-home', '', '', '', 0, 1, 0, 'BxFilesPageBrowse', 'modules/boonex/files/classes/BxFilesPageBrowse.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_files_home', 1, 'bx_files', '', '_bx_files_page_block_title_featured_entries_view_extended', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:8:"bx_files";s:6:"method";s:15:"browse_featured";s:6:"params";a:1:{i:0;s:8:"extended";}}', 0, 1, 1, 0),
+('bx_files_home', 1, 'bx_files', '', '_bx_files_page_block_title_recent_entries_view_extended', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:8:"bx_files";s:6:"method";s:13:"browse_public";s:6:"params";a:1:{i:0;s:8:"extended";}}', 0, 1, 1, 1),
+('bx_files_home', 2, 'bx_files', '', '_bx_files_page_block_title_popular_keywords', 11, 2147483647, 'service', 'a:4:{s:6:\"module\";s:6:\"system\";s:6:\"method\";s:14:\"keywords_cloud\";s:6:\"params\";a:2:{i:0;s:8:\"bx_files\";i:1;s:8:\"bx_files\";}s:5:\"class\";s:20:\"TemplServiceMetatags\";}', 0, 1, 1, 0),
+('bx_files_home', 2, 'bx_files', '', '_bx_files_page_block_title_cats', 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:13:\"bx_files_cats\";i:1;a:1:{s:10:\"show_empty\";b:1;}}s:5:\"class\";s:20:\"TemplServiceCategory\";}', 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_files_search', '_bx_files_page_title_sys_entries_search', '_bx_files_page_title_entries_search', 'bx_files', 5, 2147483647, 1, 'files-search', 'page.php?i=files-search', '', '', '', 0, 1, 0, 'BxFilesPageBrowse', 'modules/boonex/files/classes/BxFilesPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_files_search', 1, 'bx_files', '_bx_files_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:8:"bx_files";}}s:5:"class";s:27:"TemplSearchExtendedServices";}', 0, 1, 1, 1),
+('bx_files_search', 1, 'bx_files', '_bx_files_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:8:"bx_files";s:10:"show_empty";b:1;}}s:5:"class";s:27:"TemplSearchExtendedServices";}', 0, 1, 1, 2),
+('bx_files_search', 1, 'bx_files', '_bx_files_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:13:"bx_files_cmts";}}s:5:"class";s:27:"TemplSearchExtendedServices";}', 0, 1, 0, 3),
+('bx_files_search', 1, 'bx_files', '_bx_files_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:13:"bx_files_cmts";s:10:"show_empty";b:1;}}s:5:"class";s:27:"TemplSearchExtendedServices";}', 0, 1, 0, 4);
+
+-- 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_files_manage', '_bx_files_page_title_sys_manage', '_bx_files_page_title_manage', 'bx_files', 5, 2147483647, 1, 'files-manage', 'page.php?i=files-manage', '', '', '', 0, 1, 0, 'BxFilesPageBrowse', 'modules/boonex/files/classes/BxFilesPageBrowse.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_files_manage', 1, 'bx_files', '_bx_files_page_block_title_system_manage', '_bx_files_page_block_title_manage', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:8:\"bx_files\";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_files_administration', '_bx_files_page_title_sys_manage_administration', '_bx_files_page_title_manage', 'bx_files', 5, 192, 1, 'files-administration', 'page.php?i=files-administration', '', '', '', 0, 1, 0, 'BxFilesPageBrowse', 'modules/boonex/files/classes/BxFilesPageBrowse.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_files_administration', 1, 'bx_files', '_bx_files_page_block_title_system_manage_administration', '_bx_files_page_block_title_manage', 11, 192, 'service', 'a:3:{s:6:\"module\";s:8:\"bx_files\";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`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('sys_home', 1, 'bx_files', '_bx_files_page_block_title_recent_entries', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:8:"bx_files";s:6:"method";s:13:"browse_public";s:6:"params";a:2:{i:0;b:0;i:1;b:0;}}}', 1, 0, 0, IFNULL(@iBlockOrder, 0) + 1);
+
+-- PAGES: add page block to profiles modules (trigger* page objects are processed separately upon modules enable/disable)
+SET @iPBCellProfile = 3;
+SET @iPBCellGroup = 4;
+INSERT INTO `sys_pages_blocks` (`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES
+('trigger_page_profile_view_entry', @iPBCellProfile, 'bx_files', '_bx_files_page_block_title_sys_my_entries', '_bx_files_page_block_title_my_entries', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:8:"bx_files";s:6:"method";s:13:"browse_author";s:6:"params";a:2:{i:0;s:12:"{profile_id}";i:1;a:3:{s:8:"per_page";s:25:"bx_files_per_page_profile";s:13:"empty_message";b:0;s:10:"no_toolbar";b:1;}}}', 0, 0, 0);
+
+-- 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`, `order`) VALUES 
+('', 0, 'bx_files', '', '_bx_files_page_block_title_recent_entries', 11, 2147483647, 'service', 'a:3:{s:6:\"module\";s:8:\"bx_files\";s:6:\"method\";s:13:\"browse_public\";s:6:\"params\";a:3:{s:9:\"unit_view\";s:7:\"gallery\";s:13:\"empty_message\";b:1;s:13:\"ajax_paginate\";b:0;}}', 0, 1, IFNULL(@iBlockOrder, 0) + 1),
+
+('', 0, 'bx_files', '', '_bx_files_page_block_title_popular_entries_view_extended', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:8:"bx_files";s:6:"method";s:14:"browse_popular";s:6:"params";a:1:{i:0;s:8:"extended";}}', 0, 1, IFNULL(@iBlockOrder, 0) + 2),
+('', 0, 'bx_files', '_bx_files_page_block_title_sys_recent_entries_view_showcase', '_bx_files_page_block_title_recent_entries_view_showcase', 11, 2147483647, 'service', 'a:3:{s:6:\"module\";s:8:\"bx_files\";s:6:\"method\";s:13:\"browse_public\";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, IFNULL(@iBlockOrder, 0) + 3),
+('', 0, 'bx_files', '_bx_files_page_block_title_sys_popular_entries_view_showcase', '_bx_files_page_block_title_popular_entries_view_showcase', 11, 2147483647, 'service', 'a:3:{s:6:\"module\";s:8:\"bx_files\";s:6:\"method\";s:14:\"browse_popular\";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, IFNULL(@iBlockOrder, 0) + 4),
+('', 0, 'bx_files', '_bx_files_page_block_title_sys_featured_entries_view_showcase', '_bx_files_page_block_title_featured_entries_view_showcase', 11, 2147483647, 'service', 'a:3:{s:6:\"module\";s:8:\"bx_files\";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, IFNULL(@iBlockOrder, 0) + 5);
+
+
+-- 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_files', 'files-home', '_bx_files_menu_item_title_system_entries_home', '_bx_files_menu_item_title_entries_home', 'page.php?i=files-home', '', '', 'far file col-red3', 'bx_files_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_files', 'files-home', '_bx_files_menu_item_title_system_entries_home', '_bx_files_menu_item_title_entries_home', 'page.php?i=files-home', '', '', 'far file col-red3', 'bx_files_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_files', 'create-file', '_bx_files_menu_item_title_system_create_entry', '_bx_files_menu_item_title_create_entry', 'page.php?i=create-file', '', '', 'far file col-red3', '', 2147483647, 1, 1, IFNULL(@iAddMenuOrder, 0) + 1);
+
+
+-- MENU: 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_files_view', '_bx_files_menu_title_view_entry', 'bx_files_view', 'bx_files', 9, 0, 1, 'BxFilesMenuView', 'modules/boonex/files/classes/BxFilesMenuView.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_files_view', 'bx_files', '_bx_files_menu_set_title_view_entry', 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_files_view', 'bx_files', 'download-file', '_bx_files_menu_item_title_system_download_file', '_bx_files_menu_item_title_download_file', 'modules/?r=files/download/{file_download_token}/{content_id}.{file_ext}', '', '_blank', 'download', '', 2147483647, 1, 0, 1),
+('bx_files_view', 'bx_files', 'edit-file', '_bx_files_menu_item_title_system_edit_entry', '_bx_files_menu_item_title_edit_entry', 'page.php?i=edit-file&id={content_id}', '', '', 'pencil-alt', '', 2147483647, 1, 0, 2),
+('bx_files_view', 'bx_files', 'delete-file', '_bx_files_menu_item_title_system_delete_entry', '_bx_files_menu_item_title_delete_entry', 'page.php?i=delete-file&id={content_id}', '', '', 'remove', '', 2147483647, 1, 0, 3);
+
+
+-- 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_files_view_actions', '_sys_menu_title_view_actions', 'bx_files_view_actions', 'bx_files', 15, 0, 1, 'BxFilesMenuViewActions', 'modules/boonex/files/classes/BxFilesMenuViewActions.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_files_view_actions', 'bx_files', '_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_files_view_actions', 'bx_files', 'download-file', '_bx_files_menu_item_title_system_download_file', '', '', '', '', '', '', '', 0, 2147483647, 1, 0, 10),
+('bx_files_view_actions', 'bx_files', 'edit-file', '_bx_files_menu_item_title_system_edit_entry', '', '', '', '', '', '', '', 0, 2147483647, 1, 0, 20),
+('bx_files_view_actions', 'bx_files', 'delete-file', '_bx_files_menu_item_title_system_delete_entry', '', '', '', '', '', '', '', 0, 2147483647, 1, 0, 30), 
+('bx_files_view_actions', 'bx_files', 'comment', '_sys_menu_item_title_system_va_comment', '', '', '', '', '', '', '', 0, 2147483647, 0, 0, 200),
+('bx_files_view_actions', 'bx_files', 'view', '_sys_menu_item_title_system_va_view', '', '', '', '', '', '', '', 0, 2147483647, 1, 0, 210),
+('bx_files_view_actions', 'bx_files', 'vote', '_sys_menu_item_title_system_va_vote', '', '', '', '', '', '', '', 0, 2147483647, 0, 0, 220),
+('bx_files_view_actions', 'bx_files', 'reaction', '_sys_menu_item_title_system_va_reaction', '', '', '', '', '', '', '', 0, 2147483647, 1, 0, 225),
+('bx_files_view_actions', 'bx_files', 'score', '_sys_menu_item_title_system_va_score', '', '', '', '', '', '', '', 0, 2147483647, 1, 0, 230),
+('bx_files_view_actions', 'bx_files', 'favorite', '_sys_menu_item_title_system_va_favorite', '', '', '', '', '', '', '', 0, 2147483647, 1, 0, 240),
+('bx_files_view_actions', 'bx_files', 'feature', '_sys_menu_item_title_system_va_feature', '', '', '', '', '', '', '', 0, 2147483647, 1, 0, 250),
+('bx_files_view_actions', 'bx_files', 'repost', '_sys_menu_item_title_system_va_repost', '', '', '', '', '', '', '', 0, 2147483647, 1, 0, 260),
+('bx_files_view_actions', 'bx_files', 'report', '_sys_menu_item_title_system_va_report', '', '', '', '', '', '', '', 0, 2147483647, 1, 0, 270),
+('bx_files_view_actions', 'bx_files', 'social-sharing-facebook', '_sys_menu_item_title_system_social_sharing_facebook', '', '', '', '', '', '', '', 0, 2147483647, 1, 0, 300),
+('bx_files_view_actions', 'bx_files', 'social-sharing-twitter', '_sys_menu_item_title_system_social_sharing_twitter', '', '', '', '', '', '', '', 0, 2147483647, 1, 0, 320),
+('bx_files_view_actions', 'bx_files', 'social-sharing-pinterest', '_sys_menu_item_title_system_social_sharing_pinterest', '', '', '', '', '', '', '', 0, 2147483647, 1, 0, 330),
+('bx_files_view_actions', 'bx_files', '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 view inline entry
+
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES
+('bx_files_view_inline', '_bx_files_menu_title_view_inline', 'bx_files_view_inline', 'bx_files', 9, 0, 1, 'BxFilesMenuViewActionsInline', 'modules/boonex/files/classes/BxFilesMenuViewActions.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES
+('bx_files_view_inline', 'bx_files', '_bx_files_menu_set_title_view_inline', 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_files_view_inline', 'bx_files', 'favorite', '_sys_menu_item_title_system_va_favorite', '_sys_menu_item_title_va_favorite', '', '', '', '', '', 2147483647, 0, 0, 1),
+('bx_files_view_inline', 'bx_files', 'bookmark', '_bx_files_menu_item_title_system_bookmark', '_bx_files_menu_item_title_bookmark', '', '{js_object}.bookmark({content_id}, this); return false;', '', 'far star', '', 2147483647, 1, 0, 2),
+('bx_files_view_inline', 'bx_files', 'download-file', '_bx_files_menu_item_title_system_download_file', '_bx_files_menu_item_title_download_file', 'modules/?r=files/download/{file_download_token}/{content_id}.{file_ext}', '', '_blank', 'download', '', 2147483647, 1, 0, 3),
+('bx_files_view_inline', 'bx_files', 'delete-file-quick', '_bx_files_menu_item_title_system_delete_entry', '_bx_files_menu_item_title_delete_entry', 'page.php?i=delete-file&id={content_id}', '{js_object}.delete({content_id}); return false;', '', 'remove', '', 2147483647, 1, 0, 4),
+('bx_files_view_inline', 'bx_files', 'move-to', '_bx_files_menu_item_title_system_move_to_entry', '_bx_files_menu_item_title_move_to_entry', '', '{js_object}.moveTo({content_id}); return false;', '', 'file-export', '', 2147483647, 1, 0, 5),
+('bx_files_view_inline', 'bx_files', 'edit-title', '_bx_files_menu_item_title_system_edit_title', '_bx_files_menu_item_title_edit_title', 'page.php?i=edit-file&id={content_id}', '{js_object}.edit({content_id}); return false;', '', 'pencil-alt', '', 2147483647, 1, 0, 6),
+('bx_files_view_inline', 'bx_files', 'preview', '_bx_files_menu_item_title_system_info_entry', '_bx_files_menu_item_title_info_entry', '', '{js_object}.info({content_id}); return false;', '', 'info', '', 2147483647, 1, 0, 7),
+('bx_files_view_inline', 'bx_files', 'report', '_sys_menu_item_title_system_va_report', '', '', '', '', '', '', 2147483647, 1, 0, 8),
+('bx_files_view_inline', 'bx_files', 'more-auto', '_sys_menu_item_title_system_va_more_auto', '_sys_menu_item_title_va_more_auto', 'javascript:void(0)', '', '', 'ellipsis-v', '', 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_files_my', '_bx_files_menu_title_entries_my', 'bx_files_my', 'bx_files', 9, 0, 1, 'BxFilesMenu', 'modules/boonex/files/classes/BxFilesMenu.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_files_my', 'bx_files', '_bx_files_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_files_my', 'bx_files', 'create-file', '_bx_files_menu_item_title_system_create_entry', '_bx_files_menu_item_title_create_entry', 'page.php?i=create-file', '', '', '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_files_submenu', '_bx_files_menu_title_submenu', 'bx_files_submenu', 'bx_files', 8, 0, 1, '', '');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_files_submenu', 'bx_files', '_bx_files_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_files_submenu', 'bx_files', 'files-home', '_bx_files_menu_item_title_system_entries_public', '_bx_files_menu_item_title_entries_public', 'page.php?i=files-home', '', '', '', '', 2147483647, 1, 1, 1),
+('bx_files_submenu', 'bx_files', 'files-popular', '_bx_files_menu_item_title_system_entries_popular', '_bx_files_menu_item_title_entries_popular', 'page.php?i=files-popular', '', '', '', '', 2147483647, 1, 1, 2),
+('bx_files_submenu', 'bx_files', 'files-top', '_bx_files_menu_item_title_system_entries_top', '_bx_files_menu_item_title_entries_top', 'page.php?i=files-top', '', '', '', '', 2147483647, 1, 1, 3),
+('bx_files_submenu', 'bx_files', 'files-search', '_bx_files_menu_item_title_system_entries_search', '_bx_files_menu_item_title_entries_search', 'page.php?i=files-search', '', '', '', '', 2147483647, 1, 1, 4),
+('bx_files_submenu', 'bx_files', 'files-manage', '_bx_files_menu_item_title_system_entries_manage', '_bx_files_menu_item_title_entries_manage', 'page.php?i=files-manage', '', '', '', '', 2147483646, 1, 1, 5);
+
+-- MENU: sub-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_files_view_submenu', '_bx_files_menu_title_view_entry_submenu', 'bx_files_view_submenu', 'bx_files', 8, 0, 1, 'BxFilesMenuView', 'modules/boonex/files/classes/BxFilesMenuView.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_files_view_submenu', 'bx_files', '_bx_files_menu_set_title_view_entry_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_files_view_submenu', 'bx_files', 'view-file', '_bx_files_menu_item_title_system_view_entry', '_bx_files_menu_item_title_view_entry_submenu_entry', 'page.php?i=view-file&id={content_id}', '', '', '', '', 2147483647, 0, 0, 1),
+('bx_files_view_submenu', 'bx_files', 'view-file-comments', '_bx_files_menu_item_title_system_view_entry_comments', '_bx_files_menu_item_title_view_entry_submenu_comments', 'page.php?i=view-file-comments&id={content_id}', '', '', '', '', 2147483647, 0, 0, 2);
+
+-- 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_files_snippet_meta', '_sys_menu_title_snippet_meta', 'bx_files_snippet_meta', 'bx_files', 15, 0, 1, 'BxFilesMenuSnippetMeta', 'modules/boonex/files/classes/BxFilesMenuSnippetMeta.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_files_snippet_meta', 'bx_files', '_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_files_snippet_meta', 'bx_files', 'date', '_sys_menu_item_title_system_sm_date', '_sys_menu_item_title_sm_date', '', '', '', '', '', 2147483647, 1, 0, 1, 1),
+('bx_files_snippet_meta', 'bx_files', 'size', '_bx_files_menu_item_title_system_sm_size', '_bx_files_menu_item_title_sm_size', '', '', '', '', '', 2147483647, 1, 0, 1, 2),
+('bx_files_snippet_meta', 'bx_files', 'author', '_sys_menu_item_title_system_sm_author', '_sys_menu_item_title_sm_author', '', '', '', '', '', 2147483647, 1, 0, 1, 3),
+('bx_files_snippet_meta', 'bx_files', 'category', '_sys_menu_item_title_system_sm_category', '_sys_menu_item_title_sm_category', '', '', '', '', '', 2147483647, 0, 0, 1, 4),
+('bx_files_snippet_meta', 'bx_files', 'tags', '_sys_menu_item_title_system_sm_tags', '_sys_menu_item_title_sm_tags', '', '', '', '', '', 2147483647, 0, 0, 1, 5),
+('bx_files_snippet_meta', 'bx_files', 'views', '_sys_menu_item_title_system_sm_views', '_sys_menu_item_title_sm_views', '', '', '', '', '', 2147483647, 0, 0, 1, 6),
+('bx_files_snippet_meta', 'bx_files', 'comments', '_sys_menu_item_title_system_sm_comments', '_sys_menu_item_title_sm_comments', '', '', '', '', '', 2147483647, 0, 0, 1, 7);
+
+-- 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_files', 'profile-stats-manage-files', '_bx_files_menu_item_title_system_manage_my_files', '_bx_files_menu_item_title_manage_my_files', 'page.php?i=files-manage', '', '_self', 'far file col-red3', 'a:2:{s:6:"module";s:8:"bx_files";s:6:"method";s:41:"get_menu_addon_manage_tools_profile_stats";}', '', 2147483646, 1, 0, @iNotifMenuOrder + 1);
+
+-- 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_files_menu_manage_tools', '_bx_files_menu_title_manage_tools', 'bx_files_menu_manage_tools', 'bx_files', 6, 0, 1, 'BxFilesMenuManageTools', 'modules/boonex/files/classes/BxFilesMenuManageTools.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_files_menu_manage_tools', 'bx_files', '_bx_files_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_files_menu_manage_tools', 'bx_files', 'delete-with-content', '_bx_files_menu_item_title_system_delete_with_content', '_bx_files_menu_item_title_delete_with_content', 'javascript:void(0)', 'javascript:{js_object}.onClickDeleteWithContent({content_id});', '_self', 'far trash-alt', '', 128, 1, 0, 0);
+
+-- 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_files', 'files-administration', '_bx_files_menu_item_title_system_admt_files', '_bx_files_menu_item_title_admt_files', 'page.php?i=files-administration', '', '_self', 'far file', 'a:2:{s:6:"module";s:8:"bx_files";s:6:"method";s:27:"get_menu_addon_manage_tools";}', '', 192, 1, 0, @iManageMenuOrder + 1);
+
+-- MENU: add menu item to profile & group based 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_files', 'files-author', '_bx_files_menu_item_title_system_view_entries_author', '_bx_files_menu_item_title_view_entries_author', 'page.php?i=files-author&profile_id={profile_id}', '', '', 'far file col-red3', '', 2147483647, 1, 0, 0),
+('trigger_group_view_submenu', 'bx_files', 'files-context', '_bx_files_menu_item_title_system_view_entries_in_context', '_bx_files_menu_item_title_view_entries_in_context', 'page.php?i=files-context&profile_id={profile_id}', '', '', 'far file col-red3', '', 2147483647, 1, 0, 0);
+
+-- PRIVACY 
+
+INSERT INTO `sys_objects_privacy` (`object`, `module`, `action`, `title`, `default_group`, `table`, `table_field_id`, `table_field_author`, `override_class_name`, `override_class_file`) VALUES
+('bx_files_allow_view_to', 'bx_files', 'view', '_bx_files_form_entry_input_allow_view_to', '3', 'bx_files_main', 'id', 'author', 'BxFilesPrivacy', 'modules/boonex/files/classes/BxFilesPrivacy.php'),
+('bx_files_allow_view_favorite_list', 'bx_files', 'view_favorite_list', '_bx_files_form_entry_input_allow_view_favorite_list', '3', 'bx_files_favorites_lists', 'id', 'author_id', 'BxFilesPrivacy', 'modules/boonex/files/classes/BxFilesPrivacy.php');
+
+
+-- ACL
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_files', 'create entry', NULL, '_bx_files_acl_action_create_entry', '', 1, 3);
+SET @iIdActionEntryCreate = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_files', 'delete entry', NULL, '_bx_files_acl_action_delete_entry', '', 1, 3);
+SET @iIdActionEntryDelete = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_files', 'view entry', NULL, '_bx_files_acl_action_view_entry', '', 1, 0);
+SET @iIdActionEntryView = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_files', 'edit any entry', NULL, '_bx_files_acl_action_edit_any_entry', '', 1, 3);
+SET @iIdActionEntryEditAny = 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
+
+-- entry create
+(@iStandard, @iIdActionEntryCreate),
+(@iModerator, @iIdActionEntryCreate),
+(@iAdministrator, @iIdActionEntryCreate),
+(@iPremium, @iIdActionEntryCreate),
+
+-- entry delete
+(@iStandard, @iIdActionEntryDelete),
+(@iModerator, @iIdActionEntryDelete),
+(@iAdministrator, @iIdActionEntryDelete),
+(@iPremium, @iIdActionEntryDelete),
+
+-- entry view
+(@iUnauthenticated, @iIdActionEntryView),
+(@iAccount, @iIdActionEntryView),
+(@iStandard, @iIdActionEntryView),
+(@iUnconfirmed, @iIdActionEntryView),
+(@iPending, @iIdActionEntryView),
+(@iModerator, @iIdActionEntryView),
+(@iAdministrator, @iIdActionEntryView),
+(@iPremium, @iIdActionEntryView),
+
+-- edit any entry
+(@iModerator, @iIdActionEntryEditAny),
+(@iAdministrator, @iIdActionEntryEditAny);
+
+
+-- SEARCH
+SET @iSearchOrder = (SELECT IFNULL(MAX(`Order`), 0) FROM `sys_objects_search`);
+INSERT INTO `sys_objects_search` (`ObjectName`, `Title`, `Order`, `ClassName`, `ClassPath`) VALUES
+('bx_files', '_bx_files', @iSearchOrder + 1, 'BxFilesSearchResult', 'modules/boonex/files/classes/BxFilesSearchResult.php'),
+('bx_files_cmts', '_bx_files_cmts', @iSearchOrder + 2, 'BxFilesCmtsSearchResult', 'modules/boonex/files/classes/BxFilesCmtsSearchResult.php');
+
+-- METATAGS
+INSERT INTO `sys_objects_metatags` (`object`, `table_keywords`, `table_locations`, `table_mentions`, `override_class_name`, `override_class_file`) VALUES
+('bx_files', 'bx_files_meta_keywords', '', 'bx_files_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_files_cats', 'bx_files', 'bx_files', 'bx_files_cats', 'bx_files_main', 'cat', 'INNER JOIN `sys_profiles` ON (`sys_profiles`.`id` = `bx_files_main`.`author`)', 'AND `sys_profiles`.`status` = ''active''', '', '');
+
+-- STATS
+SET @iMaxOrderStats = (SELECT IFNULL(MAX(`order`), 0) FROM `sys_statistics`);
+INSERT INTO `sys_statistics` (`module`, `name`, `title`, `link`, `icon`, `query`, `order`) VALUES 
+('bx_files', 'bx_files', '_bx_files', 'page.php?i=files-home', 'far file col-red3', 'SELECT COUNT(*) FROM `bx_files_main` WHERE 1 AND `status` = ''active'' AND `status_admin` = ''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_files_growth', '_bx_files_chart_growth', 'bx_files_main', 'added', '', 'status,status_admin', '', 1, @iMaxOrderCharts + 1, 'BxDolChartGrowth', ''),
+('bx_files_growth_speed', '_bx_files_chart_growth_speed', 'bx_files_main', 'added', '', 'status,status_admin', '', 1, @iMaxOrderCharts + 2, 'BxDolChartGrowthSpeed', '');
+
+-- GRIDS: moderation tools
+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_files_administration', 'Sql', 'SELECT * FROM `bx_files_main` WHERE 1 ', 'bx_files_main', 'id', 'added', 'status_admin', '', 20, NULL, 'start', '', 'title,desc', '', 'like', 'reports', '', 192, 'BxFilesGridAdministration', 'modules/boonex/files/classes/BxFilesGridAdministration.php'),
+('bx_files_common', 'Sql', 'SELECT * FROM `bx_files_main` WHERE 1 ', 'bx_files_main', 'id', 'added', 'status', '', 20, NULL, 'start', '', 'title,desc', '', 'like', '', '', 2147483647, 'BxFilesGridCommon', 'modules/boonex/files/classes/BxFilesGridCommon.php');
+
+
+INSERT INTO `sys_grid_fields` (`object`, `name`, `title`, `width`, `translatable`, `chars_limit`, `params`, `order`) VALUES
+('bx_files_administration', 'checkbox', '_sys_select', '2%', 0, '', '', 1),
+('bx_files_administration', 'switcher', '_bx_files_grid_column_title_adm_active', '8%', 0, '', '', 2),
+('bx_files_administration', 'reports', '_sys_txt_reports_title', '5%', 0, '', '', 3),
+('bx_files_administration', 'title', '_bx_files_grid_column_title_adm_title', '25%', 0, '', '', 4),
+('bx_files_administration', 'added', '_bx_files_grid_column_title_adm_added', '20%', 1, '25', '', 5),
+('bx_files_administration', 'author', '_bx_files_grid_column_title_adm_author', '20%', 0, '25', '', 6),
+('bx_files_administration', 'actions', '', '20%', 0, '', '', 7),
+('bx_files_common', 'checkbox', '_sys_select', '2%', 0, '', '', 1),
+('bx_files_common', 'switcher', '_bx_files_grid_column_title_adm_active', '8%', 0, '', '', 2),
+('bx_files_common', 'title', '_bx_files_grid_column_title_adm_title', '40%', 0, '', '', 3),
+('bx_files_common', 'added', '_bx_files_grid_column_title_adm_added', '30%', 1, '25', '', 4),
+('bx_files_common', 'actions', '', '20%', 0, '', '', 5);
+
+INSERT INTO `sys_grid_actions` (`object`, `type`, `name`, `title`, `icon`, `icon_only`, `confirm`, `order`) VALUES
+('bx_files_administration', 'bulk', 'delete', '_bx_files_grid_action_title_adm_delete', '', 0, 1, 1),
+('bx_files_administration', 'bulk', 'clear_reports', '_bx_files_grid_action_title_adm_clear_reports', '', 0, 1, 2),
+('bx_files_administration', 'single', 'edit', '_bx_files_grid_action_title_adm_edit', 'pencil-alt', 1, 0, 1),
+('bx_files_administration', 'single', 'delete', '_bx_files_grid_action_title_adm_delete', 'remove', 1, 1, 2),
+('bx_files_administration', 'single', 'settings', '_bx_files_grid_action_title_adm_more_actions', 'cog', 1, 0, 3),
+('bx_files_administration', 'single', 'audit_content', '_bx_files_grid_action_title_adm_audit_content', 'search', 1, 0, 4),
+('bx_files_administration', 'single', 'clear_reports', '_bx_files_grid_action_title_adm_clear_reports', 'eraser', 1, 0, 5),
+('bx_files_common', 'bulk', 'delete', '_bx_files_grid_action_title_adm_delete', '', 0, 1, 1),
+('bx_files_common', 'single', 'edit', '_bx_files_grid_action_title_adm_edit', 'pencil-alt', 1, 0, 1),
+('bx_files_common', 'single', 'delete', '_bx_files_grid_action_title_adm_delete', 'remove', 1, 1, 2),
+('bx_files_common', 'single', 'settings', '_bx_files_grid_action_title_adm_more_actions', 'cog', 1, 0, 3);
+
+-- UPLOADERS
+INSERT INTO `sys_objects_uploader` (`object`, `active`, `override_class_name`, `override_class_file`) VALUES
+('bx_files_simple', 1, 'BxFilesUploaderSimple', 'modules/boonex/files/classes/BxFilesUploaderSimple.php'),
+('bx_files_html5', 1, 'BxFilesUploaderHTML5', 'modules/boonex/files/classes/BxFilesUploaderHTML5.php');
+
+-- ALERTS
+
+INSERT INTO `sys_alerts_handlers` (`name`, `class`, `file`, `service_call`) VALUES 
+('bx_files', 'BxFilesAlertsResponse', 'modules/boonex/files/classes/BxFilesAlertsResponse.php', '');
+SET @iHandler := LAST_INSERT_ID();
+
+INSERT INTO `sys_alerts` (`unit`, `action`, `handler_id`) VALUES
+('system', 'save_setting', @iHandler),
+('profile', 'delete', @iHandler);
+
+-- CRON
+
+INSERT INTO `sys_cron_jobs` (`name`, `time`, `class`, `file`, `service_call`) VALUES
+('bx_files_process_data', '* * * * *', 'BxFilesCronProcessData', 'modules/boonex/files/classes/BxFilesCronProcessData.php', '');
+

+ 368 - 0
modules/boonex/files/updates/12.0.1_12.0.2/source/install/sql/install.sql

@@ -0,0 +1,368 @@
+
+SET @sStorageEngine = (SELECT `value` FROM `sys_options` WHERE `name` = 'sys_storage_default');
+
+-- TABLE: entries
+CREATE TABLE IF NOT EXISTS `bx_files_main` (
+  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+  `author` int(10) unsigned NOT NULL,
+  `added` int(11) NOT NULL,
+  `changed` int(11) NOT NULL,
+  `file_id` int(11) NOT NULL,
+  `title` varchar(255) NOT NULL,
+  `cat` int(11) NOT NULL,
+  `desc` text NOT NULL,
+  `data` text NOT NULL,
+  `data_processed` tinyint(4) NOT NULL DEFAULT '0',
+  `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','hidden') NOT NULL DEFAULT 'active',
+  `status_admin` enum('active','hidden') NOT NULL DEFAULT 'active',
+  `type` enum('file', 'folder') NOT NULL DEFAULT 'file',
+  `parent_folder_id` int(10) unsigned NOT NULL DEFAULT 0,
+  PRIMARY KEY (`id`),
+  FULLTEXT KEY `search_fields` (`title`,`desc`,`data`)
+);
+
+
+-- TABLE: storages & transcoders
+CREATE TABLE IF NOT EXISTS `bx_files_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_files_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`)
+);
+
+-- TABLE: comments
+CREATE TABLE IF NOT EXISTS `bx_files_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: bookmarks
+CREATE TABLE IF NOT EXISTS `bx_files_bookmarks` (
+  `object_id` int(11) NOT NULL default '0',
+  `profile_id` int(11) NOT NULL default '0',
+  PRIMARY KEY (`object_id`, `profile_id`)
+);
+
+-- TABLE: downloading jobs
+CREATE TABLE IF NOT EXISTS `bx_files_downloading_jobs` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `name` varchar(255) NOT NULL,
+  `owner` int(11) NOT NULL,
+  `files` MEDIUMTEXT NOT NULL,
+  `result` TEXT NOT NULL,
+  `started` int(11) NOT NULL,
+  PRIMARY KEY (`id`)
+);
+
+-- TABLE: votes
+CREATE TABLE IF NOT EXISTS `bx_files_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_files_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_files_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_files_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_files_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_files_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_files_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_files_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_files_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_files_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_files_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_files_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_files_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_files_files', @sStorageEngine, '', 360, 2592000, 3, 'bx_files_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),
+('bx_files_photos_resized', @sStorageEngine, '', 360, 2592000, 3, 'bx_files_photos_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_files_preview', 'bx_files_photos_resized', 'Storage', 'a:1:{s:6:"object";s:14:"bx_files_files";}', 'no', '1', '2592000', '0'),
+('bx_files_gallery', 'bx_files_photos_resized', 'Storage', 'a:1:{s:6:"object";s:14:"bx_files_files";}', 'no', '1', '2592000', '0');
+
+INSERT INTO `sys_transcoder_filters` (`transcoder_object`, `filter`, `filter_params`, `order`) VALUES 
+('bx_files_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_files_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_files', 'bx_files', '_bx_files_form_entry', '', 'a:1:{s:7:"enctype";s:19:"multipart/form-data";}', 'bx_files_main', 'id', '', '', 'a:2:{i:0;s:9:"do_submit";i:1;s:10:"do_publish";}', '', 0, 1, 'BxFilesFormEntry', 'modules/boonex/files/classes/BxFilesFormEntry.php'),
+('bx_files_upload', 'bx_files', '_bx_files_form_upload', '', 'a:1:{s:7:"enctype";s:19:"multipart/form-data";}', 'bx_files_main', 'id', '', '', 'do_submit', '', 0, 1, 'BxFilesFormUpload', 'modules/boonex/files/classes/BxFilesFormUpload.php');
+
+INSERT INTO `sys_form_displays`(`object`, `display_name`, `module`, `view_mode`, `title`) VALUES 
+('bx_files', 'bx_files_entry_delete', 'bx_files', 0, '_bx_files_form_entry_display_delete'),
+('bx_files', 'bx_files_entry_edit', 'bx_files', 0, '_bx_files_form_entry_display_edit'),
+('bx_files', 'bx_files_entry_view', 'bx_files', 1, '_bx_files_form_entry_display_view'),
+('bx_files_upload', 'bx_files_entry_upload', 'bx_files', 0, '_bx_files_form_entry_display_add');
+
+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_files', 'bx_files', 'allow_view_to', '', '', 0, 'custom', '_bx_files_form_entry_input_sys_allow_view_to', '_bx_files_form_entry_input_allow_view_to', '', 1, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_files', 'bx_files', 'delete_confirm', 1, '', 0, 'checkbox', '_bx_files_form_entry_input_sys_delete_confirm', '_bx_files_form_entry_input_delete_confirm', '_bx_files_form_entry_input_delete_confirm_info', 1, 0, 0, '', '', '', 'Avail', '', '_bx_files_form_entry_input_delete_confirm_error', '', '', 1, 0),
+('bx_files', 'bx_files', 'do_publish', '_bx_files_form_entry_input_do_publish', '', 0, 'submit', '_bx_files_form_entry_input_sys_do_publish', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_files', 'bx_files', 'do_submit', '_bx_files_form_entry_input_do_submit', '', 0, 'submit', '_bx_files_form_entry_input_sys_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_files', 'bx_files', 'attachments', 'a:1:{i:0;s:14:"bx_files_html5";}', 'a:2:{s:15:"bx_files_simple";s:26:"_sys_uploader_simple_title";s:14:"bx_files_html5";s:25:"_sys_uploader_html5_title";}', 0, 'files', '_bx_files_form_entry_input_sys_attachment', '_bx_files_form_entry_input_attachment', '', 1, 0, 0, '', '', '', 'avail', '', '_bx_files_form_entry_input_attachment', '', '', 1, 0),
+('bx_files', 'bx_files', 'desc', '', '', 0, 'textarea', '_bx_files_form_entry_input_sys_desc', '_bx_files_form_entry_input_desc', '', 0, 0, 2, '', '', '', '', '', '', 'XssHtml', '', 1, 0),
+('bx_files', 'bx_files', 'data', '', '', 0, 'textarea', '_bx_files_form_entry_input_sys_data', '_bx_files_form_entry_input_data', '', 0, 0, 0, '', '', '', '', '', '', 'Xss', '', 0, 0),
+('bx_files', 'bx_files', 'title', '', '', 0, 'text', '_bx_files_form_entry_input_sys_title', '_bx_files_form_entry_input_title', '', 1, 0, 0, '', '', '', 'Avail', '', '_bx_files_form_entry_input_title_err', 'Xss', '', 1, 0),
+('bx_files', 'bx_files', 'cat', '', '#!bx_files_cats', 0, 'select', '_bx_files_form_entry_input_sys_cat', '_bx_files_form_entry_input_cat', '', 1, 0, 0, '', '', '', 'avail', '', '_bx_files_form_entry_input_cat_err', 'Xss', '', 1, 0),
+('bx_files', 'bx_files', 'added', '', '', 0, 'datetime', '_bx_files_form_entry_input_sys_date_added', '_bx_files_form_entry_input_date_added', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_files', 'bx_files', 'changed', '', '', 0, 'datetime', '_bx_files_form_entry_input_sys_date_changed', '_bx_files_form_entry_input_date_changed', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_files', 'bx_files', 'labels', '', '', 0, 'custom', '_sys_form_input_sys_labels', '_sys_form_input_labels', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+
+('bx_files_upload', 'bx_files', 'attachments', 'a:1:{i:0;s:14:"bx_files_html5";}', 'a:2:{s:15:"bx_files_simple";s:26:"_sys_uploader_simple_title";s:14:"bx_files_html5";s:25:"_sys_uploader_html5_title";}', 0, 'files', '_bx_files_form_entry_input_sys_attachments', '_bx_files_form_entry_input_attachments', '', 1, 0, 0, '', '', '', 'avail', '', '_bx_files_form_entry_input_attachments', '', '', 1, 0),
+('bx_files_upload', 'bx_files', 'cat', '', '#!bx_files_cats', 0, 'select', '_bx_files_form_entry_input_sys_cat', '_bx_files_form_entry_input_cat', '', 1, 0, 0, '', '', '', 'avail', '', '_bx_files_form_entry_input_cat_err', 'Xss', '', 1, 0),
+('bx_files_upload', 'bx_files', 'allow_view_to', '', '', 0, 'custom', '_bx_files_form_entry_input_sys_allow_view_to', '_bx_files_form_entry_input_allow_view_to', '', 1, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_files_upload', 'bx_files', 'do_submit', '_bx_files_form_entry_input_do_submit', '', 0, 'submit', '_bx_files_form_entry_input_sys_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_files_upload', 'bx_files', 'profile_id', '0', '', 0, 'hidden', '_bx_files_form_entry_input_sys_profile_id', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0);
+
+INSERT INTO `sys_form_display_inputs`(`display_name`, `input_name`, `visible_for_levels`, `active`, `order`) VALUES 
+('bx_files_entry_delete', 'delete_confirm', 2147483647, 1, 1),
+('bx_files_entry_delete', 'do_submit', 2147483647, 1, 2),
+
+('bx_files_entry_edit', 'title', 2147483647, 1, 1),
+('bx_files_entry_edit', 'cat', 2147483647, 1, 2),
+('bx_files_entry_edit', 'desc', 2147483647, 1, 3),
+('bx_files_entry_edit', 'data', 0, 1, 4),
+('bx_files_entry_edit', 'attachments', 2147483647, 1, 5),
+('bx_files_entry_edit', 'allow_view_to', 2147483647, 1, 6),
+('bx_files_entry_edit', 'do_submit', 2147483647, 1, 7),
+
+('bx_files_entry_view', 'cat', 2147483647, 1, 1),
+('bx_files_entry_view', 'added', 2147483647, 1, 2),
+('bx_files_entry_view', 'changed', 2147483647, 1, 3),
+
+('bx_files_entry_upload', 'profile_id', 2147483647, 1, 1),
+('bx_files_entry_upload', 'attachments', 2147483647, 1, 2),
+('bx_files_entry_upload', 'cat', 2147483647, 1, 3),
+('bx_files_entry_upload', 'allow_view_to', 2147483647, 1, 4),
+('bx_files_entry_upload', 'do_submit', 2147483647, 1, 5);
+
+-- PRE-VALUES
+INSERT INTO `sys_form_pre_lists`(`key`, `title`, `module`, `use_for_sets`) VALUES
+('bx_files_cats', '_bx_files_pre_lists_cats', 'bx_files', '0');
+
+INSERT INTO `sys_form_pre_values`(`Key`, `Value`, `Order`, `LKey`, `LKey2`) VALUES
+('bx_files_cats', '', 0, '_sys_please_select', ''),
+('bx_files_cats', '1', 1, '_bx_files_cat_documentation', ''),
+('bx_files_cats', '2', 2, '_bx_files_cat_presentation', ''),
+('bx_files_cats', '3', 3, '_bx_files_cat_report', ''),
+('bx_files_cats', '4', 4, '_bx_files_cat_proposal', ''),
+('bx_files_cats', '5', 5, '_bx_files_cat_list', ''),
+('bx_files_cats', '6', 6, '_bx_files_cat_record', ''),
+('bx_files_cats', '7', 7, '_bx_files_cat_screencast', ''),
+('bx_files_cats', '8', 8, '_bx_files_cat_screenshot', ''),
+('bx_files_cats', '9', 9, '_bx_files_cat_sketch', ''),
+('bx_files_cats', '10', 10, '_bx_files_cat_archive', ''),
+('bx_files_cats', '11', 11, '_bx_files_cat_backup', '');
+
+-- 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_files', 'bx_files', 'bx_files_cmts', 1, 5000, 1000, 3, 5, 3, 'tail', 1, 'bottom', 1, 1, 1, -3, 1, 'cmt', 'page.php?i=view-file&id={object_id}', '', 'bx_files_main', 'id', 'author', 'title', 'comments', '', '');
+
+-- VOTES
+INSERT INTO `sys_objects_vote` (`Name`, `TableMain`, `TableTrack`, `PostTimeout`, `MinValue`, `MaxValue`, `IsUndo`, `IsOn`, `TriggerTable`, `TriggerFieldId`, `TriggerFieldAuthor`, `TriggerFieldRate`, `TriggerFieldRateCount`, `ClassName`, `ClassFile`) VALUES 
+('bx_files', 'bx_files_votes', 'bx_files_votes_track', '604800', '1', '1', '0', '1', 'bx_files_main', 'id', 'author', 'rate', 'votes', '', ''),
+('bx_files_reactions', 'bx_files_reactions', 'bx_files_reactions_track', '604800', '1', '1', '1', '1', 'bx_files_main', '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_files', 'bx_files', 'bx_files_scores', 'bx_files_scores_track', '604800', '0', 'bx_files_main', '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_files', 'bx_files', 'bx_files_reports', 'bx_files_reports_track', '1', 'page.php?i=view-file&id={object_id}', 'bx_files_main', '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_files', 'bx_files_views_track', '86400', '1', 'bx_files_main', 'id', 'author', 'views', '', '');
+
+-- FAVORITES
+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_files', 'bx_files_favorites_track', 'bx_files_favorites_lists', '1', '1', '1', 'page.php?i=view-file&id={object_id}', 'bx_files_main', '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_files', 'bx_files', '1', '1', 'page.php?i=view-file&id={object_id}', 'bx_files_main', '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_files', '_bx_files', 'bx_files', 'added', 'edited', 'deleted', '', ''),
+('bx_files_cmts', '_bx_files_cmts', 'bx_files', 'commentPost', 'commentUpdated', 'commentRemoved', 'BxDolContentInfoCmts', '');
+
+INSERT INTO `sys_content_info_grids` (`object`, `grid_object`, `grid_field_id`, `condition`, `selection`) VALUES
+('bx_files', 'bx_files_administration', 'id', '', ''),
+('bx_files', 'bx_files_common', 'id', '', '');
+
+-- SEARCH EXTENDED
+INSERT INTO `sys_objects_search_extended` (`object`, `object_content_info`, `module`, `title`, `active`, `class_name`, `class_file`) VALUES
+('bx_files', 'bx_files', 'bx_files', '_bx_files_search_extended', 1, '', ''),
+('bx_files_cmts', 'bx_files_cmts', 'bx_files', '_bx_files_search_extended_cmts', 1, 'BxTemplSearchExtendedCmts', '');
+
+-- STUDIO: page & widget
+INSERT INTO `sys_std_pages`(`index`, `name`, `header`, `caption`, `icon`) VALUES
+(3, 'bx_files', '_bx_files', '_bx_files', 'bx_files@modules/boonex/files/|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_files', 'content', '{url_studio}module.php?name=bx_files', '', 'bx_files@modules/boonex/files/|std-icon.svg', '_bx_files', '', '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));
+

+ 56 - 0
modules/boonex/files/updates/12.0.1_12.0.2/source/install/sql/uninstall.sql

@@ -0,0 +1,56 @@
+
+-- TABLES
+DROP TABLE IF EXISTS `bx_files_main`, `bx_files_files`, `bx_files_photos_resized`, `bx_files_cmts`, `bx_files_votes`, `bx_files_votes_track`, `bx_files_reactions`, `bx_files_reactions_track`, `bx_files_views_track`, `bx_files_meta_keywords`, `bx_files_meta_mentions`, `bx_files_reports`, `bx_files_reports_track`, `bx_files_favorites_track`, `bx_files_favorites_lists`, `bx_files_scores`, `bx_files_scores_track`, `bx_files_bookmarks`, `bx_files_downloading_jobs`;
+
+-- STORAGES & TRANSCODERS
+DELETE FROM `sys_objects_storage` WHERE `object` = 'bx_files_files' OR `object` = 'bx_files_photos_resized';
+DELETE FROM `sys_storage_tokens` WHERE `object` = 'bx_files_files' OR `object` = 'bx_files_photos_resized';
+
+DELETE FROM `sys_objects_transcoder` WHERE `object` IN('bx_files_preview', 'bx_files_gallery');
+DELETE FROM `sys_transcoder_filters` WHERE `transcoder_object` IN('bx_files_preview', 'bx_files_gallery');
+DELETE FROM `sys_transcoder_images_files` WHERE `transcoder_object` IN('bx_files_preview', 'bx_files_gallery');
+
+-- FORMS
+DELETE FROM `sys_objects_form` WHERE `module` = 'bx_files';
+DELETE FROM `sys_form_displays` WHERE `module` = 'bx_files';
+DELETE FROM `sys_form_inputs` WHERE `module` = 'bx_files';
+DELETE FROM `sys_form_display_inputs` WHERE `display_name` IN ('bx_files_entry_upload', 'bx_files_entry_edit', 'bx_files_entry_view', 'bx_files_entry_delete');
+
+-- PRE-VALUES
+DELETE FROM `sys_form_pre_lists` WHERE `module` = 'bx_files';
+
+DELETE FROM `sys_form_pre_values` WHERE `Key` IN('bx_files_cats');
+
+-- COMMENTS
+DELETE FROM `sys_objects_cmts` WHERE `Name` = 'bx_files';
+
+-- VOTES
+DELETE FROM `sys_objects_vote` WHERE `Name` IN ('bx_files', 'bx_files_reactions');
+
+-- SCORES
+DELETE FROM `sys_objects_score` WHERE `name` = 'bx_files';
+
+-- REPORTS
+DELETE FROM `sys_objects_report` WHERE `name` = 'bx_files';
+
+-- VIEWS
+DELETE FROM `sys_objects_view` WHERE `name` = 'bx_files';
+
+-- FAFORITES
+DELETE FROM `sys_objects_favorite` WHERE `name` = 'bx_files';
+
+-- FEATURED
+DELETE FROM `sys_objects_feature` WHERE `name` = 'bx_files';
+
+-- CONTENT INFO
+DELETE FROM `sys_objects_content_info` WHERE `name` IN ('bx_files', 'bx_files_cmts');
+
+DELETE FROM `sys_content_info_grids` WHERE `object` IN ('bx_files');
+
+-- SEARCH EXTENDED
+DELETE FROM `sys_objects_search_extended` WHERE `module` = 'bx_files';
+
+-- 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_files';

+ 155 - 0
modules/boonex/files/updates/12.0.1_12.0.2/source/js/toolbar_tools.js

@@ -0,0 +1,155 @@
+function BxFilesBrowserTools(oOptions) {
+    this._sView = oOptions.layout;
+    this._bBookmarks = oOptions.bookmarks;
+    this._sSorting = oOptions.sorting;
+    this._sKeyword = oOptions.keyword;
+    this._sUniq = oOptions.unique_ident;
+    this._aRequestParams = oOptions.aRequestParams;
+    this._iSearchTimeoutId = 0;
+    this._sActionUrl = oOptions.sActionUrl;
+    this._iContext = oOptions.context;
+    this._iCurrentFolder = oOptions.current_folder;
+    this._iCurrentPage = oOptions.current_page;
+
+    this._oToolbarObject = $('#bx-files-browser-toolbar-' + this._sUniq).get(0);
+
+    this.aSelectedFiles = [];
+
+    var $this = this;
+
+    $(document).ready(function(){
+        $('input[type=checkbox]', $($this._oToolbarObject).parent()).change(function(){
+            $this.updateBulkActionsPanelVisivility();
+        });
+    });
+
+    $(window).on('files_browser.update', function(){
+        $this.reloadBlock($this._iCurrentPage);
+    });
+}
+
+BxFilesBrowserTools.prototype.findSelectedFiles = function() {
+    this.aSelectedFiles = [];
+    var $this = this;
+    $('input[type=checkbox]:checked', $(this._oToolbarObject).parent()).each(function(i, el){
+        if ($(el).val() > 0) $this.aSelectedFiles.push($(el).val());
+    });
+}
+
+BxFilesBrowserTools.prototype.updateBulkActionsPanelVisivility = function() {
+    this.findSelectedFiles();
+    if (this.aSelectedFiles.length) $('.bx-files-bulk-actions', this._oToolbarObject).slideDown();
+    else $('.bx-files-bulk-actions', this._oToolbarObject).slideUp();
+}
+
+BxFilesBrowserTools.prototype.reloadBlock = function(iPage) {
+    if (typeof iPage == 'undefined') iPage = 0;
+    loadDynamicBlockAutoPaginate(this._oToolbarObject, iPage, '0', this.getRequestUrl());
+}
+
+BxFilesBrowserTools.prototype.onChangeFilter = function(oFilter) {
+	var $this = this;
+
+	clearTimeout($this._iSearchTimeoutId);
+    $this._iSearchTimeoutId = setTimeout(function () {
+        $this._sKeyword = $(oFilter).val();
+        $this.reloadBlock();
+    }, 500);
+};
+
+BxFilesBrowserTools.prototype.setView = function(val) {
+    this._sView = val;
+    this.reloadBlock();
+}
+
+BxFilesBrowserTools.prototype.toggleBookmarks = function() {
+    this._bBookmarks = this._bBookmarks ? 0 : 1;
+    this.reloadBlock();
+}
+
+BxFilesBrowserTools.prototype.setSorting = function(val) {
+    this._sSorting = val;
+    this.reloadBlock();
+}
+
+BxFilesBrowserTools.prototype.getRequestUrl = function() {
+    return  this._aRequestParams.unit_view_param + '=' + this._sView + '&' +
+            this._aRequestParams.bookmarks_param + '=' + this._bBookmarks + '&' +
+            this._aRequestParams.sorting_param + '=' + this._sSorting + '&' +
+            this._aRequestParams.keyword_param + '=' + this._sKeyword + '&' +
+            this._aRequestParams.current_folder + '=' + this._iCurrentFolder;
+}
+
+BxFilesBrowserTools.prototype.onSelectAll = function(el) {
+    $(el).
+        closest('.bx-files-text-unit-simple-row').
+        siblings().
+        find('input[type=checkbox]').
+        attr('checked', $(el).attr('checked') == 'checked').change(function(){
+            $(el).attr('checked', false);
+        });
+};
+
+BxFilesBrowserTools.prototype.onBeforeUpload = function() {
+    $.get(this._sActionUrl + 'clear_ghosts/');
+}
+
+BxFilesBrowserTools.prototype.onAfterUpload = function() {
+    var $this = this;
+    $.post(this._sActionUrl + 'upload_completed/', {context: this._iContext, folder: this._iCurrentFolder}, function(oData) {
+        processJsonData(oData);
+        $this.reloadBlock();
+    }, 'json');
+}
+
+BxFilesBrowserTools.prototype.addFolder = function(sMessage) {
+    var $this = this;
+    bx_prompt(sMessage, '', function(oPopup) {
+        var name = oPopup.getValue();
+
+        $.post($this._sActionUrl + 'create_folder/', {context: $this._iContext, current_folder: $this._iCurrentFolder, name: name}, function (oData) {
+            processJsonData(oData);
+            $this.reloadBlock();
+        }, 'json');
+    });
+}
+
+BxFilesBrowserTools.prototype.folderNavigate = function(id) {
+    this._iCurrentFolder = id >= 0 ? id : -this._iCurrentFolder;
+    this.reloadBlock();
+}
+
+BxFilesBrowserTools.prototype.bookmarkFiles = function() {
+    if (!this.aSelectedFiles.length) return;
+
+    var $this = this;
+    $.post(this._sActionUrl+'bookmark/0', {bulk: this.aSelectedFiles}, function(oData){
+        processJsonData(oData);
+        $this.reloadBlock();
+    }, 'json');
+}
+
+BxFilesBrowserTools.prototype.deleteFiles = function() {
+    if (!this.aSelectedFiles.length) return;
+
+    var $this = this;
+
+    bx_confirm(_t('_Are_you_sure'), function(){
+		$.post($this._sActionUrl+'entry_delete/0', {bulk: $this.aSelectedFiles}, function(oData){
+            processJsonData(oData);
+            $this.reloadBlock();
+        }, 'json');
+	});
+}
+
+BxFilesBrowserTools.prototype.moveFiles = function() {
+    if (!this.aSelectedFiles.length) return;
+
+    $.post(this._sActionUrl + 'move_files/', {bulk: this.aSelectedFiles}, processJsonData, 'json');
+}
+
+BxFilesBrowserTools.prototype.downloadFiles = function() {
+    if (!this.aSelectedFiles.length) return;
+
+    window.open(this._sActionUrl + 'download/0/0/' + JSON.stringify(this.aSelectedFiles),'_blank');
+}

+ 13 - 0
modules/boonex/files/updates/12.0.1_12.0.2/source/template/bulk_downloader_process.html

@@ -0,0 +1,13 @@
+<span id="bx-files-downloading-message"><bx_text:_bx_files_txt_status_downloading_msg /></span>
+<script>
+    var bx_files_h_interval = 0;
+    bx_files_h_interval = setInterval(function(){
+        $.get('__action_url__', function(oResult) {
+            if (oResult.status == 'ready') {
+                clearInterval(bx_files_h_interval);
+                window.location.href = '__action_url__';
+                $('#bx-files-downloading-message').html(_t('_bx_files_txt_status_downloading_ready_msg', '__action_url__'));
+            }
+        }, 'json');
+    }, __timeout__*1000);
+</script>

+ 164 - 0
modules/boonex/files/updates/12.0.1_12.0.2/source/template/css/main.css

@@ -0,0 +1,164 @@
+@import url(../../../../base/text/template/css/main.css);
+
+.bx-files-text-unit-gallery .bx-base-text-unit-no-thumb {
+    position:relative;
+}
+
+.bx-files-text-unit-gallery .bx-base-text-unit-no-thumb .sys-icon {
+    left:0;
+    top:0;
+    width:100%;
+    position:absolute;
+    font-size:10rem;
+    line-height:12.25rem;
+    text-align:center;
+    overflow:hidden;
+}
+
+.bx-files-text-unit-gallery .bx-files-filename,
+.bx-files-text-unit-simple-row .bx-files-filename{
+    overflow: hidden;
+    text-overflow: ellipsis;
+    line-height: 2rem;
+    margin: 0px;
+    font-weight: bold;
+    white-space: nowrap;
+}
+
+.bx-files-text-unit-gallery .bx-base-general-unit-meta ul.bx-menu-custom.bx-menu-custom-hor {
+    align-items: center;
+    -webkit-align-items: center;
+    justify-content: center;
+    -webkit-justify-content: center;
+}
+
+.bx-files-text-unit-gallery .bx-files-inline-menu ul.bx-menu-object-bx_files_view_inline li.bx-menu-item span.bx-base-general-entity-action {
+    margin: 0px;
+    vertical-align: top;
+}
+.bx-files-inline-menu ul.bx-menu-object-bx_files_view_inline li.bx-menu-item {
+    white-space: nowrap;
+}
+.bx-files-text-unit-gallery .bx-menu-custom.bx-menu-custom-hor.bx-menu-more-auto {
+    justify-content: center;
+}
+.bx-files-text-unit-gallery {
+    overflow: visible!important;
+}
+.bx-files-text-unit-gallery .bx-base-text-unit-thumb,
+.bx-files-text-unit-gallery .bx-base-text-unit-no-thumb,
+.bx-files-text-unit-gallery .bx-base-text-unit-text {
+    overflow: hidden;
+}
+.bx-media-phone .bx-files-text-unit-gallery {
+    max-width: 100%;
+}
+.bx-media-tablet2 .bx-files-text-unit-gallery {
+    max-width: 49.8%;
+}
+.bx-media-desktop .bx-files-text-unit-gallery {
+    max-width: 33.25%;
+}
+
+
+
+.bx-files-text-unit .bx-base-text-unit-text {
+    position:relative;
+}
+
+.bx-files-text-unit .bx-base-text-unit-text .sys-icon {
+    position: absolute;
+    line-height: normal;
+    font-size: 3.2rem;
+}
+
+.bx-files-text-unit .bx-base-text-unit-text h2,
+.bx-files-text-unit .bx-base-text-unit-text > div {
+    margin-left:3.5rem;
+}
+
+/*--- View page ---*/
+.bx-files-entity-preview {
+    overflow: hidden;
+}
+.bx-files-entity-preview .bx-msg-box-container {
+    margin: 0;
+    padding: 0;
+}
+
+.bx-files-border-thick {
+    border-width: 3px;
+}
+
+/*--- Files Browser Table layout ---*/
+.bx-files-text-unit-simple-row {
+    text-align: left;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+}
+.bx-files-text-unit-simple-row .bx-files-fileinfo {
+    overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+    display: flex;
+    align-items: center;
+    -webkit-align-items: center;
+}
+.bx-files-text-unit-simple-row .bx-files-fileinfo-text {
+    display: inline-block;
+    overflow: hidden;
+}
+.bx-files-text-unit-simple-row .bx-files-inline-menu ul.bx-menu-object-bx_files_view_inline {
+    float: right;
+}
+.bx-files-text-unit-simple-row .bx-files-inline-menu ul.bx-menu-object-bx_files_view_inline li.bx-menu-item span.bx-base-general-entity-action {
+    margin: 0px;
+    vertical-align: top;
+}
+.bx-files-text-unit-simple-row .bx-files-fileinfo i {
+    font-size: 2.3rem;
+    line-height: 2.3rem;
+}
+.bx-files-text-unit-simple-row .bx-base-general-unit-meta ul {
+    margin: 0px!important;
+    margin-top: 0.2rem;
+}
+.bx-files-text-unit-simple-row .bx-files-filename {
+    line-height: unset;
+}
+
+
+/*--- Toolbar ---*/
+.bx-files-browser-toolbar {
+    width: 100%;
+    box-sizing: border-box;
+    text-align: left;
+    padding-top: 0px;
+}
+.bx-files-browser-toolbar .bx-form-element-wrapper {
+    display: inline-block;
+    margin: 0px;
+}
+.bx-files-browser-toolbar .bx-btn {
+    float: none;
+    display: inline-block;
+    vertical-align: top;
+}
+.bx-files-toolbar-controls-group {
+    display: inline-block;
+    margin-right: 10px;
+    white-space: nowrap;
+    margin-bottom: 1rem;
+    vertical-align: middle;
+}
+.bx-files-toolbar-spacer {
+    width: 100%;
+    margin-bottom: 0.5rem;
+}
+.bx-files-folder-path i:last-child {
+    display: none;
+}
+.bx-files-bulk-actions {
+    display: none;
+}

+ 51 - 0
modules/boonex/forum/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' => 'Discussions',
+    '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/forum/updates/update_12.0.2_12.0.3/',
+    'home_uri' => 'forum_update_1202_1203',
+
+    'module_dir' => 'boonex/forum/',
+    'module_uri' => 'forum',
+
+    'db_prefix' => 'bx_forum_',
+    'class_prefix' => 'BxForum',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_files' => 1,
+        'update_languages' => 0,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Discussions',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

+ 23 - 0
modules/boonex/forum/updates/12.0.2_12.0.3/install/installer.php

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

+ 5 - 0
modules/boonex/forum/updates/12.0.2_12.0.3/install/sql/install.sql

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

+ 1054 - 0
modules/boonex/forum/updates/12.0.2_12.0.3/source/classes/BxForumModule.php

@@ -0,0 +1,1054 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Forum Forum
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxForumModule extends BxBaseModTextModule
+{
+    function __construct(&$aModule)
+    {
+        parent::__construct($aModule);
+    }
+
+    public function sortParticipants ($aParticipants, $iProfileIdLastComment, $iProfileIdAuthor, $iProfileIdCurrent = 0)
+    {
+        if (!$iProfileIdCurrent)
+            $iProfileIdCurrent = bx_get_logged_profile_id();
+
+        $aMoveUp = array($iProfileIdCurrent, $iProfileIdLastComment, $iProfileIdAuthor);
+
+        asort($aParticipants, SORT_NUMERIC);
+
+        foreach ($aMoveUp as $iProfileId) {
+            if (!isset($aParticipants[$iProfileId]))
+                continue;
+
+            $a = array($iProfileId => $aParticipants[$iProfileId]);
+            unset($aParticipants[$iProfileId]);
+            $aParticipants = $a + $aParticipants;
+        }
+
+        return $aParticipants;
+    }
+
+    /**
+     * Action methods
+     */
+    public function actionUpdateStatus($sAction = '', $iContentId = 0)
+    {
+        if(empty($sAction) && bx_get('action') !== false)
+            $sAction = bx_process_input(bx_get('action'));
+
+        if(empty($iContentId) && bx_get('id') !== false)
+            $iContentId = (int)bx_get('id');
+
+        $aContentInfo = $this->_oDb->getContentInfoById($iContentId);
+        if(empty($aContentInfo) || !is_array($aContentInfo))
+            return echoJson(array('code' => 1, 'message' => _t('_bx_forum_err_not_found')));
+
+        $sMethodCheck = 'checkAllowed' . bx_gen_method_name($sAction) . 'AnyEntry';
+        $sResult = $this->$sMethodCheck($aContentInfo);
+        if($sResult !== CHECK_ACTION_RESULT_ALLOWED)
+            return echoJson(array('code' => 2, 'message' => $sResult));
+
+        bx_audit(
+            $iContentId, 
+            $this->getName(), 
+            '_sys_audit_action_' . $sAction,  
+            $this->_prepareAuditParams($aContentInfo, false)
+        );
+        
+        if(!$this->_oDb->updateStatus($sAction, $aContentInfo))
+            return echoJson(array('code' => 3, 'message' => _t('_error occured')));
+
+        $aContentInfo = $this->_oDb->getContentInfoById($iContentId);
+        $this->alertAfterEdit($aContentInfo);
+
+        echoJson(array('code' => 0, 'id' => $iContentId, 'reload' => 1));
+    }
+
+    public function actionAjaxGetAuthors()
+    {
+        $aResult = BxDolService::call('system', 'profiles_search', array(bx_get('term')), 'TemplServiceProfiles');
+
+        header('Content-Type:text/javascript; charset=utf-8');
+        echo json_encode($aResult);
+    }
+
+    /**
+     * Service methods
+     */
+
+    public function serviceGetSafeServices()
+    {
+        $a = parent::serviceGetSafeServices();
+        return array_merge($a, array (
+            'BrowseNew' => '',
+            'BrowseLatest' => '',
+            'BrowseTop' => '',
+            'BrowsePopular' => '',
+            'BrowseUpdated' => '',
+            'BrowsePartaken' => '',
+            'BrowseIndex' => '',
+            'Search' => '',
+        ));
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_forum Discussions
+     * @subsection bx_forum-other Other
+     * @subsubsection bx_forum-get_searchable_fields get_searchable_fields
+     * 
+     * @code bx_srv('bx_forum', 'get_searchable_fields', [...]); @endcode
+     * 
+     * Get searchable fields for Studio settings.
+     * 
+     * @return an array with key-value pairs to be used in settings dropdown field.
+     * 
+     * @see BxForumModule::serviceGetSearchableFields
+     */
+    /** 
+     * @ref bx_forum-get_searchable_fields "get_searchable_fields"
+     */
+    public function serviceGetSearchableFields ($aInputsAdd = array())
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $aResult = parent::serviceGetSearchableFields($aInputsAdd);
+        $aResult[$CNF['FIELD_TEXT_COMMENTS']] = _t('_bx_forum_form_entry_input_text_comments');
+
+        return $aResult;
+    }
+
+    /**
+     * Service methods
+     */
+    /**
+     * @page service Service Calls
+     * @section bx_forum Discussions
+     * @subsection bx_forum-other Other
+     * @subsubsection bx_forum-get_info get_info
+     * 
+     * @code bx_srv('bx_forum', 'get_info', [...]); @endcode
+     * 
+     * Get content info by content ID. Is used in "Content Info Objects" system.
+     * 
+     * @param $iContentId integer value with content ID.
+     * @param $bSearchableFieldsOnly (optional) boolean value determining all info or "searchable fields" only will be returned.
+     * @return an array with content info. Empty array is returned if something is wrong.
+     * 
+     * @see BxForumModule::serviceGetInfo
+     */
+    /** 
+     * @ref bx_forum-get_info "get_info"
+     */
+    public function serviceGetInfo ($iContentId, $bSearchableFieldsOnly = true)
+    {
+        $aContentInfo = $this->_getFields($iContentId);
+        if(empty($aContentInfo))
+            return array();
+
+        return $aContentInfo;
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_forum Discussions
+     * @subsection bx_forum-page_blocks Page Blocks
+     * @subsubsection bx_forum-browse_new browse_new
+     * 
+     * @code bx_srv('bx_forum', 'browse_new', [...]); @endcode
+     * 
+     * Get page block with a list of items ordered by newness and represented as table.
+     * 
+     * @param $sUnitView (optional) string with unit view type.
+     * @param $bEmptyMessage (optional) boolean value determining whether an "Empty" message should be returned or not.
+     * @param $bAjaxPaginate (optional) boolean value determining whether an Ajax based pagination should be used or not.
+     * @return HTML string with block content to display on the site or false if something is wrong. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
+     * 
+     * @see BxForumModule::serviceBrowseNew
+     */
+    /** 
+     * @ref bx_forum-browse_new "browse_new"
+     */
+	public function serviceBrowseNew ($sUnitView = false, $bEmptyMessage = true, $bAjaxPaginate = true, $bShowHeader = false)
+    {
+    	$sType = 'new';
+
+    	if($sUnitView != 'table')   
+        	return $this->_serviceBrowse($sType, $sUnitView ? array('unit_view' => $sUnitView) : false, BX_DB_PADDING_DEF, $bEmptyMessage, $bAjaxPaginate);
+
+        return $this->_serviceBrowseTable(array(
+            'type' => $sType,
+            'empty_message' => $bEmptyMessage,
+            'ajax_paginate' => $bAjaxPaginate
+        ), $bShowHeader);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_forum Discussions
+     * @subsection bx_forum-page_blocks Page Blocks
+     * @subsubsection bx_forum-browse_latest browse_latest
+     * 
+     * @code bx_srv('bx_forum', 'browse_latest', [...]); @endcode
+     * 
+     * Get page block with a list of items ordered by Recent Posts in them and represented as table.
+     * 
+     * @param $sUnitView (optional) string with unit view type.
+     * @param $bEmptyMessage (optional) boolean value determining whether an "Empty" message should be returned or not.
+     * @param $bAjaxPaginate (optional) boolean value determining whether an Ajax based pagination should be used or not.
+     * @param $bShowHeader (optional) boolean value determining whether a resulting table should have Header section or not.
+     * @return HTML string with block content to display on the site or false if something is wrong. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
+     * 
+     * @see BxForumModule::serviceBrowseNew
+     */
+    /** 
+     * @ref bx_forum-browse_latest "browse_latest"
+     */
+    public function serviceBrowseLatest($sUnitView = false, $bEmptyMessage = true, $bAjaxPaginate = true, $bShowHeader = false)
+    {
+        $sType = 'latest';
+
+        if($sUnitView != 'table')
+            return $this->_serviceBrowse($sType, $sUnitView ? array('unit_view' => $sUnitView) : false, BX_DB_PADDING_DEF, $bEmptyMessage, $bAjaxPaginate);
+
+        return $this->_serviceBrowseTable(array(
+            'type' => $sType,
+            'empty_message' => $bEmptyMessage, 
+            'ajax_paginate' => $bAjaxPaginate
+        ), $bShowHeader);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_forum Discussions
+     * @subsection bx_forum-page_blocks Page Blocks
+     * @subsubsection bx_forum-browse_featured browse_featured
+     * 
+     * @code bx_srv('bx_forum', 'browse_featured', [...]); @endcode
+     * 
+     * Get page block with a list of featured items represented as table.
+     * 
+     * @param $sUnitView (optional) string with unit view type.
+     * @param $bEmptyMessage (optional) boolean value determining whether an "Empty" message should be returned or not.
+     * @param $bAjaxPaginate (optional) boolean value determining whether an Ajax based pagination should be used or not.
+     * @param $bShowHeader (optional) boolean value determining whether a resulting table should have Header section or not.
+     * @return HTML string with block content to display on the site or false if something is wrong. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
+     * 
+     * @see BxForumModule::serviceBrowseFeatured
+     */
+    /** 
+     * @ref bx_forum-browse_featured "browse_featured"
+     */
+    public function serviceBrowseFeatured($sUnitView = false, $bEmptyMessage = false, $bAjaxPaginate = true, $bShowHeader = false)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+    	$sType = 'featured';
+
+    	if($sUnitView != 'table')
+            return $this->_serviceBrowse($sType, $sUnitView ? array('unit_view' => $sUnitView) : false, BX_DB_PADDING_DEF, $bEmptyMessage, $bAjaxPaginate);
+
+        return $this->_serviceBrowseTable(array(
+            'grid' => $CNF['OBJECT_GRID_FEATURE'],
+            'type' => $sType, 
+            'where' => array('fld' => 'featured', 'val' => 0, 'opr' => '<>'),
+            'empty_message' => $bEmptyMessage,
+            'ajax_paginate' => $bAjaxPaginate
+        ), $bShowHeader);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_forum Discussions
+     * @subsection bx_forum-page_blocks Page Blocks
+     * @subsubsection bx_forum-browse_top browse_top
+     * 
+     * @code bx_srv('bx_forum', 'browse_top', [...]); @endcode
+     * 
+     * Get page block with a list of items ordered by a number of comments and represented as table.
+     * 
+     * @param $sUnitView (optional) string with unit view type.
+     * @param $bEmptyMessage (optional) boolean value determining whether an "Empty" message should be returned or not.
+     * @param $bAjaxPaginate (optional) boolean value determining whether an Ajax based pagination should be used or not.
+     * @return HTML string with block content to display on the site or false if something is wrong. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
+     * 
+     * @see BxForumModule::serviceBrowseTop
+     */
+    /** 
+     * @ref bx_forum-browse_top "browse_top"
+     */
+    public function serviceBrowseTop($sUnitView = false, $bEmptyMessage = true, $bAjaxPaginate = true, $bShowHeader = false)
+    {
+        $sType = 'top';
+
+        if($sUnitView != 'table')
+            return $this->_serviceBrowse($sType, $sUnitView ? array('unit_view' => $sUnitView) : false, BX_DB_PADDING_DEF, $bEmptyMessage, $bAjaxPaginate);
+
+        return $this->_serviceBrowseTable(array(
+            'type' => $sType,
+            'empty_message' => $bEmptyMessage,
+            'ajax_paginate' => $bAjaxPaginate
+        ), $bShowHeader);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_forum Discussions
+     * @subsection bx_forum-page_blocks Page Blocks
+     * @subsubsection bx_forum-browse_popular browse_popular
+     * 
+     * @code bx_srv('bx_forum', 'browse_popular', [...]); @endcode
+     * 
+     * Get page block with a list of items ordered by a number of views and represented as table.
+     * 
+     * @param $sUnitView (optional) string with unit view type.
+     * @param $bEmptyMessage (optional) boolean value determining whether an "Empty" message should be returned or not.
+     * @param $bAjaxPaginate (optional) boolean value determining whether an Ajax based pagination should be used or not.
+     * @return HTML string with block content to display on the site or false if something is wrong. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
+     * 
+     * @see BxForumModule::serviceBrowsePopular
+     */
+    /** 
+     * @ref bx_forum-browse_popular "browse_popular"
+     */
+    public function serviceBrowsePopular ($sUnitView = false, $bEmptyMessage = true, $bAjaxPaginate = true, $bShowHeader = false)
+    {
+        $sType = 'popular';
+
+        if($sUnitView != 'table')
+            return $this->_serviceBrowse($sType, $sUnitView ? array('unit_view' => $sUnitView) : false, BX_DB_PADDING_DEF, $bEmptyMessage, $bAjaxPaginate);
+
+        return $this->_serviceBrowseTable(array(
+            'type' => $sType,
+            'empty_message' => $bEmptyMessage,
+            'ajax_paginate' => $bAjaxPaginate
+        ), $bShowHeader);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_forum Discussions
+     * @subsection bx_forum-page_blocks Page Blocks
+     * @subsubsection bx_forum-browse_updated browse_updated
+     * 
+     * @code bx_srv('bx_forum', 'browse_updated', [...]); @endcode
+     * 
+     * Get page block with a list of updated items represented as table.
+     * 
+     * @param $sUnitView (optional) string with unit view type.
+     * @param $bEmptyMessage (optional) boolean value determining whether an "Empty" message should be returned or not.
+     * @param $bAjaxPaginate (optional) boolean value determining whether an Ajax based pagination should be used or not.
+     * @return HTML string with block content to display on the site or false if something is wrong. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
+     * 
+     * @see BxForumModule::serviceBrowseUpdated
+     */
+    /** 
+     * @ref bx_forum-browse_updated "browse_updated"
+     */
+    public function serviceBrowseUpdated ($sUnitView = false, $bEmptyMessage = true, $bAjaxPaginate = true, $bShowHeader = false)
+    {
+        $sType = 'updated';
+
+        if($sUnitView != 'table')
+            return $this->_serviceBrowse($sType, $sUnitView ? array('unit_view' => $sUnitView) : false, BX_DB_PADDING_DEF, $bEmptyMessage, $bAjaxPaginate);
+
+        return $this->_serviceBrowseTable(array(
+            'type' => $sType,
+            'empty_message' => $bEmptyMessage,
+            'ajax_paginate' => $bAjaxPaginate
+        ), $bShowHeader);
+    }
+
+        /**
+     * @page service Service Calls
+     * @section bx_forum Discussions
+     * @subsection bx_forum-page_blocks Page Blocks
+     * @subsubsection bx_forum-browse_partaken browse_partaken
+     * 
+     * @code bx_srv('bx_forum', 'browse_partaken', [...]); @endcode
+     * 
+     * Get page block with a list of partaken items represented as table.
+     * 
+     * @param $sUnitView (optional) string with unit view type.
+     * @param $bEmptyMessage (optional) boolean value determining whether an "Empty" message should be returned or not.
+     * @param $bAjaxPaginate (optional) boolean value determining whether an Ajax based pagination should be used or not.
+     * @return HTML string with block content to display on the site or false if something is wrong. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
+     * 
+     * @see BxForumModule::serviceBrowsePartaken
+     */
+    /** 
+     * @ref bx_forum-browse_partaken "browse_partaken"
+     */
+    public function serviceBrowsePartaken ($sUnitView = false, $bEmptyMessage = true, $bAjaxPaginate = true, $bShowHeader = false)
+    {
+        $sType = 'partaken';
+
+        if($sUnitView != 'table')
+            return $this->_serviceBrowse($sType, $sUnitView ? array('unit_view' => $sUnitView) : false, BX_DB_PADDING_DEF, $bEmptyMessage, $bAjaxPaginate);
+
+        $aSelect = array(
+            'tbla' => 'tco', 
+            'fld' => 'cmt_author_id',
+        );
+
+        $aJoin = array(
+            'tp' => 'INNER',
+            'tbl1' => 'bx_forum_cmts',
+            'tbl1a' => 'tco',
+            'fld1' => 'cmt_object_id',
+            'tbl2' => 'bx_forum_discussions',
+            'fld2' => 'id'
+        );
+
+        $aWhere = array(
+            'tbl' => 'tco', 
+            'fld' => 'cmt_author_id', 
+            'val' => bx_get_logged_profile_id(), 
+            'opr' => '='
+        );
+
+        $aGroupBy = array(
+            'tbl' => 'bx_forum_discussions', 
+            'fld' => 'id',
+        );
+
+        return $this->_serviceBrowseTable(array(
+            'type' => $sType,
+            'select' => $aSelect,
+            'join' => $aJoin,
+            'where' => $aWhere,
+            'group_by' => $aGroupBy,
+            'empty_message' => $bEmptyMessage,
+            'ajax_paginate' => $bAjaxPaginate
+        ), $bShowHeader);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_forum Discussions
+     * @subsection bx_forum-page_blocks Page Blocks
+     * @subsubsection bx_forum-browse_index browse_index
+     * 
+     * @code bx_srv('bx_forum', 'browse_index', [...]); @endcode
+     * 
+     * Get page block for Site's Home page with a list of items ordered by newness and represented as table.
+     * 
+     * @param $sUnitView (optional) string with unit view type.
+     * @param $bEmptyMessage (optional) boolean value determining whether an "Empty" message should be returned or not.
+     * @param $bAjaxPaginate (optional) boolean value determining whether an Ajax based pagination should be used or not.
+     * @param $bShowHeader (optional) boolean value determining whether a resulting table should have Header section or not.
+     * @return HTML string with block content to display on the site or false if something is wrong. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
+     * 
+     * @see BxForumModule::serviceBrowseIndex
+     */
+    /** 
+     * @ref bx_forum-browse_index "browse_index"
+     */
+    public function serviceBrowseIndex($sUnitView = false, $bEmptyMessage = true, $bAjaxPaginate = true, $bShowHeader = false)
+    {
+    	$sType = 'index';
+
+    	if($sUnitView != 'table')
+            return $this->_serviceBrowse($sType, $sUnitView ? array('unit_view' => $sUnitView) : false, BX_DB_PADDING_DEF, $bEmptyMessage, $bAjaxPaginate);
+
+        return $this->_serviceBrowseTable(array(
+            'type' => $sType,
+            'per_page' => (int)$this->_oDb->getParam('bx_forum_per_page_index'),
+            'empty_message' => $bEmptyMessage,
+            'ajax_paginate' => $bAjaxPaginate
+        ), $bShowHeader);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_forum Discussions
+     * @subsection bx_forum-page_blocks Page Blocks
+     * @subsubsection bx_forum-browse_author browse_author
+     * 
+     * @code bx_srv('bx_forum', 'browse_author', [...]); @endcode
+     * 
+     * Get page block with a list of items filtered by Author and represented as table.
+     * 
+     * @param $iProfileId (optional) integer value with author ID. If empty value is provided, an attempt to get it from GET/POST arrays will be performed.
+     * @param $aParams (optional) an array of additional params. It's not used for now.
+     * @return HTML string with block content to display on the site or false if something is wrong. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
+     * 
+     * @see BxForumModule::serviceBrowseAuthor
+     */
+    /** 
+     * @ref bx_forum-browse_author "browse_author"
+     */
+	public function serviceBrowseAuthor ($iProfileId = 0, $aParams = array())
+    {
+        if(!$iProfileId)
+            $iProfileId = bx_process_input(bx_get('profile_id'), BX_DATA_INT);
+
+        if(!$iProfileId)
+            return '';
+
+        $bEmptyMessage = true;
+        if(isset($aParams['empty_message'])) {
+            $bEmptyMessage = (bool)$aParams['empty_message'];
+            unset($aParams['empty_message']);
+        }
+
+        $bAjaxPaginate = true;
+        if(isset($aParams['ajax_paginate'])) {
+            $bAjaxPaginate = (bool)$aParams['ajax_paginate'];
+            unset($aParams['ajax_paginate']);
+        }
+
+        return $this->_serviceBrowseTable(array(
+        	'type' => 'author', 
+        	'author' => $iProfileId, 
+        	'where' => array('fld' => 'author', 'val' => $iProfileId, 'opr' => '='), 
+        	'per_page' => (int)$this->_oDb->getParam('bx_forum_per_page_profile'),
+        	'empty_message' => $bEmptyMessage,
+                'ajax_paginate' => $bAjaxPaginate
+        ), false);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_forum Discussions
+     * @subsection bx_forum-page_blocks Page Blocks
+     * @subsubsection bx_forum-browse_favorite browse_favorite
+     * 
+     * @code bx_srv('bx_forum', 'browse_favorite', [...]); @endcode
+     * 
+     * Get page block with a list of favorited items by some profile and represented as table.
+     * 
+     * @param $iProfileId (optional) integer value with profile ID. If empty value is provided, an attempt to get it from GET/POST arrays will be performed.
+     * @param $aParams (optional) an array of additional params. It's not used for now.
+     * @return HTML string with block content to display on the site or false if something is wrong. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
+     * 
+     * @see BxForumModule::serviceBrowseFavorite
+     */
+    /** 
+     * @ref bx_forum-browse_favorite "browse_favorite"
+     */
+    public function serviceBrowseFavorite ($iProfileId = 0, $aParams = array())
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $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 '';
+
+        $iProfileAuthor = $oProfile->id();
+        $oFavorite = $this->getObjectFavorite();
+        if(!$oFavorite->isPublic() && $iProfileAuthor != bx_get_logged_profile_id())
+            return '';
+
+        $bEmptyMessage = false;
+        if(isset($aParams['empty_message'])) {
+            $bEmptyMessage = (bool)$aParams['empty_message'];
+            unset($aParams['empty_message']);
+        }
+
+        $bAjaxPaginate = true;
+        if(isset($aParams['ajax_paginate'])) {
+            $bAjaxPaginate = (bool)$aParams['ajax_paginate'];
+            unset($aParams['ajax_paginate']);
+        }
+
+        $aConditions = $oFavorite->getConditionsTrack($CNF['TABLE_ENTRIES'], 'id', $iProfileAuthor);
+        if(empty($aConditions) || !is_array($aConditions)) 
+            return '';
+
+        $aJoinGroup = array('grp' => true, 'cnds' => array());
+        if(!empty($aConditions['join']))
+            foreach($aConditions['join'] as $aCondition)
+                $aJoinGroup['cnds'][] = array(
+                    'tp' => $aCondition['type'],
+                    'tbl1' => $aCondition['table'],
+                    'fld1' => $aCondition['onField'],
+                    'tbl2' => $aCondition['mainTable'],
+                    'fld2' => $aCondition['mainField']
+                );
+
+        $aWhereGroup = array('grp' => true, 'opr' => 'AND', 'cnds' => array());
+        if(!empty($aConditions['restriction']))
+            foreach($aConditions['restriction'] as $aCondition)
+                $aWhereGroup['cnds'][] = array(
+                    'tbl' => (!empty($aCondition['table']) ? $aCondition['table'] : ''), 
+                    'fld' => $aCondition['field'], 
+                    'val' => $aCondition['value'], 
+                    'opr' => $aCondition['operator']
+                );
+
+        return $this->_serviceBrowseTable(array(
+            'grid' => $CNF['OBJECT_GRID_FAVORITE'],
+            'type' => 'favorite', 
+            'author' => $iProfileId, 
+            'join' => $aJoinGroup,
+            'where' => $aWhereGroup, 
+            'per_page' => (int)$this->_oDb->getParam('bx_forum_per_page_profile'),
+            'empty_message' => $bEmptyMessage,
+            'ajax_paginate' => $bAjaxPaginate
+        ), false);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_forum Discussions
+     * @subsection bx_forum-page_blocks Page Blocks
+     * @subsubsection bx_forum-browse_category browse_category
+     * 
+     * @code bx_srv('bx_forum', 'browse_category', [...]); @endcode
+     * 
+     * Get page block with a list of items filter by some category and represented as table.
+     * 
+     * @param $sUnitView (optional) string with unit view type.
+     * @param $bEmptyMessage (optional) boolean value determining whether an "Empty" message should be returned or not.
+     * @param $bAjaxPaginate (optional) boolean value determining whether an Ajax based pagination should be used or not.
+     * @return HTML string with block content to display on the site or false if something is wrong. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
+     * 
+     * @see BxForumModule::serviceBrowseCategory
+     */
+    /** 
+     * @ref bx_forum-browse_category "browse_category"
+     */
+    public function serviceBrowseCategory($sUnitView = false, $bEmptyMessage = true, $bAjaxPaginate = true, $bShowHeader = false)
+    {
+        $sType = 'category';
+        $iCategory = bx_process_input(bx_get('category'), BX_DATA_INT);
+
+        $aCategory = $this->_oDb->getCategories(array('type' => 'by_category', 'category' => $iCategory));
+        if(!empty($aCategory['visible_for_levels']) && !BxDolAcl::getInstance()->isMemberLevelInSet($aCategory['visible_for_levels']))
+            return $bEmptyMessage ? MsgBox(_t('_sys_txt_access_denied')) : '';
+
+        if($sUnitView != 'table') {
+            $aParams = array('category' => $iCategory);
+            if ($sUnitView)
+                $aParams['unit_view'] = $sUnitView;
+            return $this->_serviceBrowse($sType, $aParams, BX_DB_PADDING_DEF, $bEmptyMessage, $bAjaxPaginate);
+        }
+
+        return $this->_serviceBrowseTable(array(
+            'type' => $sType, 
+            'where' => array('fld' => 'cat', 'val' => $iCategory, 'opr' => '='),
+            'empty_message' => $bEmptyMessage,
+            'ajax_paginate' => $bAjaxPaginate
+        ), $bShowHeader);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_forum Discussions
+     * @subsection bx_forum-page_blocks Page Blocks
+     * @subsubsection bx_forum-browse_keyword browse_keyword
+     * 
+     * @code bx_srv('bx_forum', 'browse_keyword', [...]); @endcode
+     * 
+     * Get page block with a list of items filter by some keyword and represented as table.
+     * 
+     * @param $sUnitView (optional) string with unit view type.
+     * @param $bEmptyMessage (optional) boolean value determining whether an "Empty" message should be returned or not.
+     * @param $bAjaxPaginate (optional) boolean value determining whether an Ajax based pagination should be used or not.
+     * @return HTML string with block content to display on the site or false if something is wrong. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
+     * 
+     * @see BxForumModule::serviceBrowseKeyword
+     */
+    /** 
+     * @ref bx_forum-browse_keyword "browse_keyword"
+     */
+    public function serviceBrowseKeyword($sUnitView = false, $bEmptyMessage = true, $bAjaxPaginate = true, $bShowHeader = false)
+    {
+        $sType = 'keyword';
+        $sKeyword = bx_process_input(bx_get('keyword'));
+
+        if($sUnitView != 'table')   
+            return $this->_serviceBrowse($sType, $sUnitView ? array('unit_view' => $sUnitView) : false, BX_DB_PADDING_DEF, $bEmptyMessage, $bAjaxPaginate);
+
+        return $this->_serviceBrowseTable(array(
+            'type' => $sType, 
+            'where' => $this->_getSearchKeywordDescriptor('#' . $sKeyword),
+            'empty_message' => $bEmptyMessage,
+            'ajax_paginate' => $bAjaxPaginate
+        ), $bShowHeader);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_forum Discussions
+     * @subsection bx_forum-page_blocks Page Blocks
+     * @subsubsection bx_forum-browse_search_results browse_search_results
+     * 
+     * @code bx_srv('bx_forum', 'browse_search_results', [...]); @endcode
+     * 
+     * Get page block with search results by Author(s), Category, Keyword represented as table.
+     * 
+     * @param $sUnitView (optional) string with unit view type.
+     * @param $bEmptyMessage (optional) boolean value determining whether an "Empty" message should be returned or not.
+     * @param $bAjaxPaginate (optional) boolean value determining whether an Ajax based pagination should be used or not.
+     * @return HTML string with block content to display on the site or false if something is wrong. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
+     * 
+     * @see BxForumModule::serviceBrowseSearchResults
+     */
+    /** 
+     * @ref bx_forum-browse_search_results "browse_search_results"
+     */
+    public function serviceBrowseSearchResults($sUnitView = false, $bEmptyMessage = true, $bAjaxPaginate = true)
+    {
+        $sType = 'search';
+
+        $aAuthors = bx_process_input(bx_get('author'));
+        $iCategory = bx_process_input(bx_get('category'), BX_DATA_INT);
+        $sKeyword = bx_process_input(bx_get('keyword'));
+
+        $aCategory = $this->_oDb->getCategories(array('type' => 'by_category', 'category' => $iCategory));
+        if(!empty($aCategory['visible_for_levels']) && !BxDolAcl::getInstance()->isMemberLevelInSet($aCategory['visible_for_levels']))
+            return $bEmptyMessage ? MsgBox(_t('_sys_txt_access_denied')) : '';
+
+        if($sUnitView != 'table')   
+            return $this->_serviceBrowse('', $sUnitView ? array('unit_view' => $sUnitView) : false, BX_DB_PADDING_DEF, $bEmptyMessage, $bAjaxPaginate);
+
+        $aWhereGroupAnd = array('grp' => true, 'opr' => 'AND', 'cnds' => array());
+        if(!empty($aAuthors) && is_array($aAuthors))
+            $aWhereGroupAnd['cnds'][] = $this->_getSearchAuthorDescriptor($aAuthors);
+
+        if(!empty($iCategory))
+            $aWhereGroupAnd['cnds'][] = array('fld' => 'cat', 'val' => $iCategory, 'opr' => '=');
+
+        if(!empty($sKeyword))
+            $aWhereGroupAnd['cnds'][] = $this->_getSearchKeywordDescriptor($sKeyword);
+
+        return $this->_serviceBrowseTable(array(
+            'type' => $sType, 
+            'where' => $aWhereGroupAnd,
+            'empty_message' => $bEmptyMessage,
+            'ajax_paginate' => $bAjaxPaginate
+        ), false);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_forum Discussions
+     * @subsection bx_forum-other Other
+     * @subsubsection bx_forum-get_discussions_num get_discussions_num
+     * 
+     * @code bx_srv('bx_forum', 'get_discussions_num', [...]); @endcode
+     * 
+     * Get number of discussions for some profile.
+     * 
+     * @param $iProfileId (optional) profile to get discussions for, if omitted then currently logged in profile is used.
+     * @return integer value with a number of discussions.
+     * 
+     * @see BxForumModule::serviceGetDiscussionsNum
+     */
+    /** 
+     * @ref bx_forum-get_discussions_num "get_discussions_num"
+     */
+    public function serviceGetDiscussionsNum ($iProfileId = 0)
+    {
+        if (!$iProfileId)
+            $iProfileId = bx_get_logged_profile_id();
+
+        return $this->_oDb->getEntriesNumByAuthor((int)$iProfileId);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_forum Discussions
+     * @subsection bx_forum-other Other
+     * @subsubsection bx_forum-get_unreplied_discussions_num get_unreplied_discussions_num
+     * 
+     * @code bx_srv('bx_forum', 'get_unreplied_discussions_num', [...]); @endcode
+     * 
+     * Get number of unreplied discussions for some profile.
+     * 
+     * @param $iProfileId (optional) profile to get unreplied discussions for, if omitted then currently logged is profile is used.
+     * @return integer value with a number of discussions.
+     * 
+     * @see BxForumModule::serviceGetUnrepliedDiscussionsNum
+     */
+    /** 
+     * @ref bx_forum-get_unreplied_discussions_num "get_unreplied_discussions_num"
+     */
+    public function serviceGetUnrepliedDiscussionsNum ($iProfileId = 0)
+    {
+        if (!$iProfileId)
+            $iProfileId = bx_get_logged_profile_id();
+
+        return $this->_oDb->getUnrepliedDiscussionsNum((int)$iProfileId);
+    }
+
+    /**
+     * 
+     */
+    /**
+     * @page service Service Calls
+     * @section bx_forum Discussions
+     * @subsection bx_forum-other Other
+     * @subsubsection bx_forum-trigger_comment_post trigger_comment_post
+     * 
+     * @code bx_srv('bx_forum', 'trigger_comment_post', [...]); @endcode
+     * 
+     * Update last comment time and author when new comment was added in the discussion.
+     * 
+     * @param $iContentId integer value with content ID.
+     * @param $iProfileId integer value with profile ID.
+     * @param $iCommentId integer value with comment ID.
+     * @param $iTimestamp (optional) date in UNIX Timestamp format, if omitted then current date is used.
+     * @param $sCommentText (optional) string value with text of comment.
+     * @return boolean value determining where the operation is successful or not.
+     * 
+     * @see BxForumModule::serviceTriggerCommentPost
+     */
+    /** 
+     * @ref bx_forum-trigger_comment_post "trigger_comment_post"
+     */
+    public function serviceTriggerCommentPost ($iContentId, $iProfileId, $iCommentId, $iTimestamp = 0, $sCommentText = '')
+    {
+    	$CNF = $this->_oConfig->CNF;
+
+    	$iContentId = (int)$iContentId;
+        if(!$iContentId)
+            return false;
+
+        $aContentInfo = $this->_oDb->getContentInfoById($iContentId);
+        if(!$aContentInfo)
+			return false;
+
+        $oCmts = BxDolCmts::getObjectInstance($CNF['OBJECT_COMMENTS'], $iContentId);
+        if(!$oCmts)
+            return false;
+
+        if(!$iTimestamp)
+			$iTimestamp = time();
+
+        if(!$this->_oDb->updateLastCommentTimeProfile((int)$iContentId, (int)$iProfileId, $iCommentId, $iTimestamp))
+			return false;
+
+        // send notification to author
+        if($iProfileId != $aContentInfo[$CNF['FIELD_AUTHOR']]) {
+	        $oProfile = BxDolProfile::getInstanceMagic($iProfileId);
+	        if($oProfile) 
+                sendMailTemplate('bx_forum_new_reply', 0, $aContentInfo[$CNF['FIELD_AUTHOR']], array(
+                    'SenderDisplayName' => $oProfile->getDisplayName(),
+                    'SenderUrl' => $oProfile->getUrl(),
+                    'PageUrl' => $oCmts->getItemUrl($iCommentId),
+                    'PageTitle' => $oCmts->getObjectTitle(),
+                    'Message' => $sCommentText,
+                ), BX_EMAIL_NOTIFY);
+        }
+
+        return true;
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_forum Discussions
+     * @subsection bx_forum-page_blocks Page Blocks
+     * @subsubsection bx_forum-entity_participants entity_participants
+     * 
+     * @code bx_srv('bx_forum', 'entity_participants', [...]); @endcode
+     * 
+     * Get page block with discussion's collaborators.
+     * 
+     * @param $iContentId (optional) content ID. If empty value is provided, an attempt to get it from GET/POST arrays will be performed.
+     * @return HTML string with block content to display on the site or false if something is wrong. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
+     * 
+     * @see BxForumModule::serviceEntityParticipants
+     */
+    /** 
+     * @ref bx_forum-entity_participants "entity_participants"
+     */
+    public function serviceEntityParticipants ($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->entryParticipants ($aContentInfo, 5, 'right');
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_forum Discussions
+     * @subsection bx_forum-page_blocks Page Blocks
+     * @subsubsection bx_forum-search search
+     * 
+     * @code bx_srv('bx_forum', 'search', [...]); @endcode
+     * 
+     * Get page block with search form.
+     * 
+     * @return HTML string with block content to display on the site or false if something is wrong. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
+     * 
+     * @see BxForumModule::serviceSearch
+     */
+    /** 
+     * @ref bx_forum-search "search"
+     */
+	public function serviceSearch()
+    {
+    	$CNF = $this->_oConfig->CNF;
+    	$oForm = BxDolForm::getObjectInstance($CNF['OBJECT_FORM_SEARCH'], $CNF['OBJECT_FORM_SEARCH_DISPLAY_FULL'], $this->_oTemplate);
+    	$oForm->initChecker();
+
+        return $oForm->getCode();
+    }
+
+    public function checkAllowedSubscribe(&$aDataEntry, $isPerformAction = false)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $sMsg = $this->checkAllowedView($aDataEntry);
+        if($sMsg !== CHECK_ACTION_RESULT_ALLOWED)
+            return $sMsg;
+
+        return $this->_checkAllowedConnect ($aDataEntry, $isPerformAction, $CNF['OBJECT_CONNECTION_SUBSCRIBERS'], false, false);
+    }
+
+    public function checkAllowedUnsubscribe(&$aDataEntry, $isPerformAction = false)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        return $this->_checkAllowedConnect ($aDataEntry, $isPerformAction, $CNF['OBJECT_CONNECTION_SUBSCRIBERS'], false, true);
+    }
+
+    public function checkAllowedStickAnyEntry($aDataEntry, $isPerformAction = false)
+    {
+    	$CNF = &$this->_oConfig->CNF;
+
+    	if((int)$aDataEntry[$CNF['FIELD_STICK']] != 0)
+    		return false;
+
+		return $this->_checkAllowedAction('stick any entry', $aDataEntry, $isPerformAction);
+    }
+
+    public function checkAllowedUnstickAnyEntry($aDataEntry, $isPerformAction = false)
+    {
+    	$CNF = $this->_oConfig->CNF;
+
+    	if((int)$aDataEntry[$CNF['FIELD_STICK']] != 1)
+			return false;
+
+    	return $this->_checkAllowedAction('stick any entry', $aDataEntry, $isPerformAction);
+    }
+
+    public function checkAllowedLockAnyEntry($aDataEntry, $isPerformAction = false)
+    {
+    	$CNF = $this->_oConfig->CNF;
+
+    	if((int)$aDataEntry[$CNF['FIELD_LOCK']] != 0)
+    		return false;
+
+		return $this->_checkAllowedAction('lock any entry', $aDataEntry, $isPerformAction);
+    }
+
+	public function checkAllowedUnlockAnyEntry($aDataEntry, $isPerformAction = false)
+    {
+    	$CNF = $this->_oConfig->CNF;
+
+    	if((int)$aDataEntry[$CNF['FIELD_LOCK']] != 1)
+    		return false;
+
+		return $this->_checkAllowedAction('lock any entry', $aDataEntry, $isPerformAction);
+    }
+
+    public function checkAllowedHideAnyEntry($aDataEntry, $isPerformAction = false)
+    {
+    	$CNF = $this->_oConfig->CNF;
+
+    	if($aDataEntry[$CNF['FIELD_STATUS_ADMIN']] == 'hidden')
+    		return false;
+
+		return $this->_checkAllowedAction('hide any entry', $aDataEntry, $isPerformAction);
+    }
+
+	public function checkAllowedUnhideAnyEntry($aDataEntry, $isPerformAction = false)
+    {
+    	$CNF = &$this->_oConfig->CNF;
+
+    	if($aDataEntry[$CNF['FIELD_STATUS_ADMIN']] != 'hidden')
+    		return false;
+
+		return $this->_checkAllowedAction('hide any entry', $aDataEntry, $isPerformAction);
+    }
+
+    protected function _checkAllowedConnect (&$aDataEntry, $isPerformAction, $sObjConnection, $isMutual, $isInvertResult)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        if(!$this->_iProfileId)
+            return _t('_sys_txt_access_denied');
+
+        $isConnected = BxDolConnection::getObjectInstance($sObjConnection)->isConnected($this->_iProfileId, $aDataEntry[$CNF['FIELD_ID']], $isMutual);
+        if($isInvertResult)
+            $isConnected = !$isConnected;
+
+        return $isConnected ? _t('_sys_txt_access_denied') : CHECK_ACTION_RESULT_ALLOWED;
+    }
+
+	/**
+     * @return CHECK_ACTION_RESULT_ALLOWED if access is granted or error message if access is forbidden. So make sure to make strict(===) checking.
+     */
+    protected function _checkAllowedAction($sAction, $aDataEntry, $isPerformAction = false)
+    {
+        if($this->_isModerator($isPerformAction))
+			return CHECK_ACTION_RESULT_ALLOWED;
+
+		$aCheck = checkActionModule($this->_iProfileId, $sAction, $this->getName(), $isPerformAction);
+    	if($aCheck[CHECK_ACTION_RESULT] === CHECK_ACTION_RESULT_ALLOWED)
+    		return CHECK_ACTION_RESULT_ALLOWED;
+
+        return _t('_sys_txt_access_denied');
+    }
+
+    protected function _serviceBrowseTable($aParams, $isDisplayHeader = true)
+    {
+        $sGrid = $this->_oConfig->CNF['OBJECT_GRID'];
+        if(!empty($aParams['grid'])) {
+            $sGrid = $aParams['grid'];
+            unset($aParams['grid']);
+        }
+
+        $oGrid = BxDolGrid::getObjectInstance($sGrid);
+        if(!$oGrid)
+            return false;
+
+        $oGrid->setBrowseParams($aParams);
+
+        return $oGrid->getCode($isDisplayHeader);
+    }
+
+    protected function _getSearchAuthorDescriptor($aAutor)
+    {
+        return array('grp' => true, 'opr' => 'OR', 'cnds' => array(
+            array('fld' => 'author', 'val' => $aAutor, 'opr' => 'IN'),
+            array('fld' => 'author_comment', 'val' => $aAutor, 'opr' => 'IN'),
+        ));
+    }
+
+    protected function _getSearchKeywordDescriptor($sKeyword)
+    {
+        return array('grp' => true, 'opr' => 'OR', 'cnds' => array(
+            array('fld' => 'title', 'val' => $sKeyword, 'opr' => 'LIKE'),
+            array('fld' => 'text', 'val' => $sKeyword, 'opr' => 'LIKE'),
+            array('fld' => 'text_comments', 'val' => $sKeyword, 'opr' => 'LIKE')
+        ));
+    }
+}
+
+/** @} */

+ 136 - 0
modules/boonex/forum/updates/12.0.2_12.0.3/source/install/config.php

@@ -0,0 +1,136 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Forum Forum
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_forum',
+    'title' => 'Discussions',
+    'note' => 'Discussions 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/forum/',
+    'home_uri' => 'forum',
+
+    'db_prefix' => 'bx_forum_',
+    'class_prefix' => 'BxForum',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Discussions',
+    
+    /**
+     * 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_forum_files'
+    ),
+
+	/**
+     * Transcoders.
+     */
+    'transcoders' => array(
+		'bx_forum_preview',
+        'bx_forum_preview_cmts',
+        'bx_forum_gallery',
+        'bx_forum_cover'
+    ),
+
+    /**
+     * Extended Search Forms.
+     */
+    'esearches' => array(
+        'bx_forum',
+    	'bx_forum_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'
+    ),
+);
+
+/** @} */

+ 562 - 0
modules/boonex/forum/updates/12.0.2_12.0.3/source/install/sql/install.sql

@@ -0,0 +1,562 @@
+SET @sName = 'bx_forum';
+SET @sStorageEngine = (SELECT `value` FROM `sys_options` WHERE `name` = 'sys_storage_default');
+
+-- TABLE: entries
+CREATE TABLE IF NOT EXISTS `bx_forum_discussions` (
+  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+  `author` int(11) NOT NULL,
+  `added` int(11) NOT NULL,
+  `changed` int(11) NOT NULL,
+  `thumb` int(11) NOT NULL,
+  `title` varchar(255) NOT NULL,
+  `cat` int(11) NOT NULL,
+  `multicat` text NOT NULL,
+  `text` mediumtext NOT NULL,
+  `text_comments` mediumtext NOT NULL,
+  `lr_timestamp` int(11) NOT NULL,
+  `lr_profile_id` int(11) NOT NULL,
+  `lr_comment_id` int(11) NOT NULL,
+  `labels` 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',
+  `stick` tinyint(4) NOT NULL DEFAULT '0',
+  `lock` tinyint(4) NOT NULL DEFAULT '0',
+  `allow_view_to` varchar(16) NOT NULL DEFAULT '3',
+  `status` enum('active','hidden') NOT NULL DEFAULT 'active',
+  `status_admin` enum('active','hidden') NOT NULL DEFAULT 'active',
+  PRIMARY KEY (`id`),
+  FULLTEXT KEY `title_text` (`title`,`text`,`text_comments`),
+  KEY `lr_timestamp` (`lr_timestamp`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_forum_categories` (
+  `category` int(11) NOT NULL default '0',
+  `visible_for_levels` int(11) NOT NULL default '2147483647',
+  PRIMARY KEY (`category`)
+);
+
+-- TABLE: storages & transcoders
+CREATE TABLE IF NOT EXISTS `bx_forum_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_forum_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_forum_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_forum_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_forum_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_forum_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: subscribers
+CREATE TABLE IF NOT EXISTS `bx_forum_subscribers` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `initiator` int(11) NOT NULL,
+  `content` int(11) NOT NULL,
+  `added` int(10) unsigned NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `initiator` (`initiator`,`content`),
+  KEY `content` (`content`)
+);
+
+-- TABLE: comments
+CREATE TABLE IF NOT EXISTS `bx_forum_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_forum_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_forum_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_forum_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_forum_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_forum_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: metas
+CREATE TABLE `bx_forum_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_forum_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_forum_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_forum_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`)
+);
+
+-- TABLES: favorites
+CREATE TABLE `bx_forum_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_forum_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_forum_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_forum_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_forum_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_forum_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_forum_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_forum_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
+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_forum_covers', @sStorageEngine, '', 360, 2592000, 3, 'bx_forum_covers', 'allow-deny', 'jpg,jpeg,jpe,gif,png', '', 0, 0, 0, 0, 0, 0),
+
+('bx_forum_photos', @sStorageEngine, '', 360, 2592000, 3, 'bx_forum_photos', 'allow-deny', 'jpg,jpeg,jpe,gif,png', '', 0, 0, 0, 0, 0, 0),
+('bx_forum_photos_resized', @sStorageEngine, '', 360, 2592000, 3, 'bx_forum_photos_resized', 'allow-deny', 'jpg,jpeg,jpe,gif,png', '', 0, 0, 0, 0, 0, 0),
+
+('bx_forum_videos', @sStorageEngine, 'a:1:{s:6:"fields";a:1:{s:10:"dimensions";s:17:"getFileDimensions";}}', 360, 2592000, 3, 'bx_forum_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_forum_videos_resized', @sStorageEngine, '', 360, 2592000, 3, 'bx_forum_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_forum_files', @sStorageEngine, '', 360, 2592000, 3, 'bx_forum_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),
+
+-- For Comments
+('bx_forum_files_cmts', @sStorageEngine, '', 360, 2592000, 3, 'bx_forum_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_forum_preview', 'bx_forum_photos_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_forum_covers";}', 'no', '1', '2592000', '0', '', ''),
+('bx_forum_gallery', 'bx_forum_photos_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_forum_covers";}', 'no', '1', '2592000', '0', '', ''),
+('bx_forum_cover', 'bx_forum_photos_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_forum_covers";}', 'no', '1', '2592000', '0', '', ''),
+
+('bx_forum_preview_photos', 'bx_forum_photos_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_forum_photos";}', 'no', '1', '2592000', '0', '', ''),
+('bx_forum_gallery_photos', 'bx_forum_photos_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_forum_photos";}', 'no', '1', '2592000', '0', '', ''),
+
+('bx_forum_videos_poster', 'bx_forum_videos_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_forum_videos";}', 'no', '0', '0', '0', 'BxDolTranscoderVideo', ''),
+('bx_forum_videos_poster_preview', 'bx_forum_videos_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_forum_videos";}', 'no', '0', '0', '0', 'BxDolTranscoderVideo', ''),
+('bx_forum_videos_mp4', 'bx_forum_videos_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_forum_videos";}', 'no', '0', '0', '0', 'BxDolTranscoderVideo', ''),
+('bx_forum_videos_mp4_hd', 'bx_forum_videos_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_forum_videos";}', 'no', '0', '0', '0', 'BxDolTranscoderVideo', ''),
+
+('bx_forum_preview_files', 'bx_forum_photos_resized', 'Storage', 'a:1:{s:6:"object";s:14:"bx_forum_files";}', 'no', '1', '2592000', '0', '', ''),
+('bx_forum_gallery_files', 'bx_forum_photos_resized', 'Storage', 'a:1:{s:6:"object";s:14:"bx_forum_files";}', 'no', '1', '2592000', '0', '', ''),
+
+-- For Comments
+('bx_forum_preview_cmts', 'bx_forum_photos_resized', 'Storage', 'a:1:{s:6:"object";s:19:"bx_forum_files_cmts";}', 'no', '1', '2592000', '0', '', '');
+
+INSERT INTO `sys_transcoder_filters` (`transcoder_object`, `filter`, `filter_params`, `order`) VALUES 
+('bx_forum_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_forum_gallery', 'Resize', 'a:1:{s:1:"w";s:3:"500";}', '0'),
+('bx_forum_cover', 'Resize', 'a:1:{s:1:"w";s:4:"2000";}', '0'),
+
+('bx_forum_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_forum_gallery_photos', 'Resize', 'a:1:{s:1:"w";s:4:"2000";}', '0'),
+
+('bx_forum_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_forum_videos_poster_preview', 'Poster', 'a:2:{s:1:"h";s:3:"480";s:10:"force_type";s:3:"jpg";}', 0),
+('bx_forum_videos_poster', 'Poster', 'a:2:{s:1:"h";s:3:"318";s:10:"force_type";s:3:"jpg";}', 0),
+('bx_forum_videos_mp4', 'Mp4', 'a:2:{s:1:"h";s:3:"318";s:10:"force_type";s:3:"mp4";}', 0),
+('bx_forum_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_forum_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_forum_gallery_files', 'Resize', 'a:1:{s:1:"w";s:3:"500";}', '0'),
+
+-- For Comments
+('bx_forum_preview_cmts', 'Resize', 'a:4:{s:1:"w";s:3:"100";s:1:"h";s:3:"100";s:13:"square_resize";s:1:"1";s:10:"force_type";s:3:"jpg";}', '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 
+(@sName, @sName, '_bx_forum_form_entry', '', 'a:1:{s:7:\"enctype\";s:19:\"multipart/form-data\";}', 'bx_forum_discussions', 'id', '', '', 'do_submit', '', 0, 1, 'BxForumFormEntry', 'modules/boonex/forum/classes/BxForumFormEntry.php'),
+('bx_forum_search', @sName, '_bx_forum_form_search', '', 'a:1:{s:7:\"enctype\";s:19:\"multipart/form-data\";}', 'bx_forum_discussions', 'id', '', '', 'do_submit', '', 0, 1, 'BxForumFormSearch', 'modules/boonex/forum/classes/BxForumFormSearch.php');
+
+INSERT INTO `sys_form_displays`(`object`, `display_name`, `module`, `view_mode`, `title`) VALUES 
+(@sName, 'bx_forum_entry_add', @sName, 0, '_bx_forum_form_entry_display_add'),
+(@sName, 'bx_forum_entry_delete', @sName, 0, '_bx_forum_form_entry_display_delete'),
+(@sName, 'bx_forum_entry_edit', @sName, 0, '_bx_forum_form_entry_display_edit'),
+(@sName, 'bx_forum_entry_view', @sName, 1, '_bx_forum_form_entry_display_view'),
+
+('bx_forum_search', 'bx_forum_search_full', @sName, 0, '_bx_forum_form_search_display_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
+(@sName, @sName, 'allow_view_to', '', '', 0, 'custom', '_bx_forum_form_entry_input_sys_allow_view_to', '_bx_forum_form_entry_input_allow_view_to', '', 1, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+(@sName, @sName, 'delete_confirm', 1, '', 0, 'checkbox', '_bx_forum_form_entry_input_sys_delete_confirm', '_bx_forum_form_entry_input_delete_confirm', '_bx_forum_form_entry_input_delete_confirm_info', 1, 0, 0, '', '', '', 'Avail', '', '_bx_forum_form_entry_input_delete_confirm_error', '', '', 1, 0),
+(@sName, @sName, 'do_submit', '_bx_forum_form_entry_input_do_submit', '', 0, 'submit', '_bx_forum_form_entry_input_sys_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+(@sName, @sName, 'text', '', '', 0, 'textarea', '_bx_forum_form_entry_input_sys_text', '_bx_forum_form_entry_input_text', '', 1, 0, 2, '', '', '', 'Avail', '', '_bx_forum_form_entry_input_text_err', 'XssHtml', '', 1, 0),
+(@sName, @sName, 'title', '', '', 0, 'text', '_bx_forum_form_entry_input_sys_title', '_bx_forum_form_entry_input_title', '', 1, 0, 0, '', '', '', 'Avail', '', '_bx_forum_form_entry_input_title_err', 'Xss', '', 1, 0),
+(@sName, @sName, 'cat', '', '#!bx_forum_cats', 0, 'select', '_bx_forum_form_entry_input_sys_cat', '_bx_forum_form_entry_input_cat', '', 1, 0, 0, '', '', '', 'avail', '', '_bx_forum_form_entry_input_cat_err', 'Xss', '', 1, 0),
+(@sName, @sName, 'multicat', '', '', 0, 'custom', '_bx_forum_form_entry_input_sys_multicat', '_bx_forum_form_entry_input_multicat', '', 1, 0, 0, '', '', '', 'avail', '', '_bx_forum_form_entry_input_multicat_err', 'Xss', '', 1, 0),
+(@sName, @sName, 'attachments', '', '', 0, 'custom', '_bx_forum_form_entry_input_sys_attachments', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+(@sName, @sName, 'covers', 'a:1:{i:0;s:14:"bx_forum_html5";}', 'a:2:{s:15:"bx_forum_simple";s:26:"_sys_uploader_simple_title";s:14:"bx_forum_html5";s:25:"_sys_uploader_html5_title";}', 0, 'files', '_bx_forum_form_entry_input_sys_covers', '_bx_forum_form_entry_input_covers', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+(@sName, @sName, 'pictures', 'a:1:{i:0;s:21:"bx_forum_photos_html5";}', 'a:2:{s:22:"bx_forum_photos_simple";s:26:"_sys_uploader_simple_title";s:21:"bx_forum_photos_html5";s:25:"_sys_uploader_html5_title";}', 0, 'files', '_bx_forum_form_entry_input_sys_pictures', '_bx_forum_form_entry_input_pictures', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+(@sName, @sName, 'videos', 'a:2:{i:0;s:21:"bx_forum_videos_html5";i:1;s:28:"bx_forum_videos_record_video";}', 'a:3:{s:22:"bx_forum_videos_simple";s:26:"_sys_uploader_simple_title";s:21:"bx_forum_videos_html5";s:25:"_sys_uploader_html5_title";s:28:"bx_forum_videos_record_video";s:32:"_sys_uploader_record_video_title";}', 0, 'files', '_bx_forum_form_entry_input_sys_videos', '_bx_forum_form_entry_input_videos', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+(@sName, @sName, 'files', 'a:1:{i:0;s:20:"bx_forum_files_html5";}', 'a:2:{s:21:"bx_forum_files_simple";s:26:"_sys_uploader_simple_title";s:20:"bx_forum_files_html5";s:25:"_sys_uploader_html5_title";}', 0, 'files', '_bx_forum_form_entry_input_sys_files', '_bx_forum_form_entry_input_files', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+(@sName, @sName, 'polls', '', '', 0, 'custom', '_bx_forum_form_entry_input_sys_polls', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+(@sName, @sName, 'labels', '', '', 0, 'custom', '_sys_form_input_sys_labels', '_sys_form_input_labels', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+(@sName, @sName, 'anonymous', '', '', 0, 'switcher', '_sys_form_input_sys_anonymous', '_sys_form_input_anonymous', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+(@sName, @sName, 'added', '', '', 0, 'datetime', '_bx_forum_form_entry_input_sys_date_added', '_bx_forum_form_entry_input_date_added', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+(@sName, @sName, 'changed', '', '', 0, 'datetime', '_bx_forum_form_entry_input_sys_date_changed', '_bx_forum_form_entry_input_date_changed', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+
+('bx_forum_search', @sName, 'author', '', '', 0, 'custom', '_bx_forum_form_search_input_sys_author', '_bx_forum_form_search_input_author', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_forum_search', @sName, 'category', '', '#!bx_forum_cats', 0, 'select', '_bx_forum_form_search_input_sys_category', '_bx_forum_form_search_input_category', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_forum_search', @sName, 'keyword', '', '', 0, 'text', '_bx_forum_form_search_input_sys_keyword', '_bx_forum_form_search_input_keyword', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_forum_search', @sName, 'do_submit', '_bx_forum_form_search_input_do_submit', '', 0, 'submit', '_bx_forum_form_search_input_sys_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0);
+
+INSERT INTO `sys_form_display_inputs` (`display_name`, `input_name`, `visible_for_levels`, `active`, `order`) VALUES
+('bx_forum_entry_add', 'title', 2147483647, 1, 1),
+('bx_forum_entry_add', 'cat', 2147483647, 1, 2),
+('bx_forum_entry_add', 'text', 2147483647, 1, 3),
+('bx_forum_entry_add', 'attachments', 2147483647, 1, 4),
+('bx_forum_entry_add', 'pictures', 2147483647, 1, 5),
+('bx_forum_entry_add', 'videos', 2147483647, 1, 6),
+('bx_forum_entry_add', 'files', 2147483647, 1, 7),
+('bx_forum_entry_add', 'polls', 2147483647, 1, 8),
+('bx_forum_entry_add', 'covers', 2147483647, 1, 9),
+('bx_forum_entry_add', 'allow_view_to', 2147483647, 1, 10),
+('bx_forum_entry_add', 'do_submit', 2147483647, 1, 11),
+
+('bx_forum_entry_edit', 'title', 2147483647, 1, 1),
+('bx_forum_entry_edit', 'cat', 2147483647, 1, 2),
+('bx_forum_entry_edit', 'text', 2147483647, 1, 3),
+('bx_forum_entry_edit', 'attachments', 2147483647, 1, 4),
+('bx_forum_entry_edit', 'pictures', 2147483647, 1, 5),
+('bx_forum_entry_edit', 'videos', 2147483647, 1, 6),
+('bx_forum_entry_edit', 'files', 2147483647, 1, 7),
+('bx_forum_entry_edit', 'polls', 2147483647, 1, 8),
+('bx_forum_entry_edit', 'covers', 2147483647, 1, 9),
+('bx_forum_entry_edit', 'allow_view_to', 2147483647, 1, 10),
+('bx_forum_entry_edit', 'do_submit', 2147483647, 1, 11),
+
+('bx_forum_entry_view', 'title', 2147483647, 1, 1),
+('bx_forum_entry_view', 'cat', 2147483647, 1, 2),
+('bx_forum_entry_view', 'text', 2147483647, 1, 3),
+
+('bx_forum_entry_delete', 'delete_confirm', 2147483647, 1, 1),
+('bx_forum_entry_delete', 'do_submit', 2147483647, 1, 2),
+
+('bx_forum_search_full', 'author', 2147483647, 1, 1),
+('bx_forum_search_full', 'category', 2147483647, 1, 2),
+('bx_forum_search_full', 'keyword', 2147483647, 1, 3),
+('bx_forum_search_full', 'do_submit', 2147483647, 1, 4);
+
+-- 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_forum_poll', 'bx_forum', '_bx_forum_form_poll', '', '', 'do_submit', 'bx_forum_polls', 'id', '', '', 'a:1:{s:14:"checker_helper";s:28:"BxForumFormPollCheckerHelper";}', 0, 1, 'BxForumFormPoll', 'modules/boonex/forum/classes/BxForumFormPoll.php');
+
+INSERT INTO `sys_form_displays` (`display_name`, `module`, `object`, `title`, `view_mode`) VALUES
+('bx_forum_poll_add', 'bx_forum', 'bx_forum_poll', '_bx_forum_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_forum_poll', 'bx_forum', 'text', '', '', 0, 'text', '_bx_forum_form_poll_input_sys_text', '_bx_forum_form_poll_input_text', '', 1, 0, 0, '', '', '', 'Avail', '', '_bx_forum_form_poll_input_text_err', 'Xss', '', 1, 0),
+('bx_forum_poll', 'bx_forum', 'answers', '', '', 0, 'custom', '_bx_forum_form_poll_input_sys_answers', '_bx_forum_form_poll_input_answers', '', 1, 0, 0, '', '', '', 'AvailAnswers', '', '_bx_forum_form_poll_input_answers_err', '', '', 1, 0),
+('bx_forum_poll', 'bx_forum', 'controls', '', 'do_submit,do_cancel', 0, 'input_set', '', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
+('bx_forum_poll', 'bx_forum', 'do_submit', '_bx_forum_form_poll_input_do_submit', '', 0, 'submit', '_bx_forum_form_poll_input_sys_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
+('bx_forum_poll', 'bx_forum', 'do_cancel', '_bx_forum_form_poll_input_do_cancel', '', 0, 'button', '_bx_forum_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_forum_poll_add', 'text', 2147483647, 1, 1),
+('bx_forum_poll_add', 'answers', 2147483647, 1, 2),
+('bx_forum_poll_add', 'controls', 2147483647, 1, 3),
+('bx_forum_poll_add', 'do_submit', 2147483647, 1, 4),
+('bx_forum_poll_add', 'do_cancel', 2147483647, 1, 5);
+
+
+-- PRE-VALUES
+INSERT INTO `sys_form_pre_lists`(`key`, `title`, `module`, `use_for_sets`) VALUES
+('bx_forum_cats', '_bx_forum_pre_lists_cats', 'bx_forum', '0');
+
+INSERT INTO `sys_form_pre_values`(`Key`, `Value`, `Order`, `LKey`, `LKey2`) VALUES
+('bx_forum_cats', '', 0, '_sys_please_select', ''),
+('bx_forum_cats', '1', 1, '_bx_forum_cat_General', '');
+
+
+-- 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
+(@sName, @sName, 'bx_forum_cmts', 1, 5000, 1000, 2, 50, 3, 'tail', 0, 'bottom', 1, 1, 1, -3, 1, 'cmt', 'page.php?i=view-discussion&id={object_id}', '', 'bx_forum_discussions', 'id', 'author', 'title', 'comments', 'BxForumCmts', 'modules/boonex/forum/classes/BxForumCmts.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 
+(@sName, 'bx_forum_views_track', '86400', '1', 'bx_forum_discussions', '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 
+(@sName, 'bx_forum_votes', 'bx_forum_votes_track', '604800', '1', '1', '0', '1', 'bx_forum_discussions', 'id', 'author', 'rate', 'votes', '', ''),
+('bx_forum_reactions', 'bx_forum_reactions', 'bx_forum_reactions_track', '604800', '1', '1', '1', '1', 'bx_forum_discussions', 'id', 'author', 'rrate', 'rvotes', 'BxTemplVoteReactions', ''),
+('bx_forum_poll_answers', 'bx_forum_polls_answers_votes', 'bx_forum_polls_answers_votes_track', '604800', '1', '1', '0', '1', 'bx_forum_polls_answers', 'id', 'author_id', 'rate', 'votes', 'BxForumVotePollAnswers', 'modules/boonex/forum/classes/BxForumVotePollAnswers.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 
+(@sName, @sName, 'bx_forum_scores', 'bx_forum_scores_track', '604800', '0', 'bx_forum_discussions', 'id', 'author', 'score', 'sc_up', 'sc_down', '', '');
+
+
+-- FAVORITES
+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 
+(@sName, 'bx_forum_favorites_track', 'bx_forum_favorites_lists', '1', '1', '1', 'page.php?i=view-discussion&id={object_id}', 'bx_forum_discussions', '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 
+(@sName, @sName, '1', '1', 'page.php?i=view-discussion&id={object_id}', 'bx_forum_discussions', '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
+(@sName, '_bx_forum', @sName, 'added', 'edited', 'deleted', '', ''),
+('bx_forum_cmts', '_bx_forum_cmts', @sName, 'commentPost', 'commentUpdated', 'commentRemoved', 'BxDolContentInfoCmts', '');
+
+INSERT INTO `sys_content_info_grids` (`object`, `grid_object`, `grid_field_id`, `condition`, `selection`) VALUES
+(@sName, @sName, 'id', '', 'a:1:{s:4:"sort";a:2:{s:5:"stick";s:4:"desc";s:12:"lr_timestamp";s:4:"desc";}}'),
+(@sName, 'bx_forum_administration', 'id', '', ''),
+(@sName, 'bx_forum_common', 'id', '', '');
+
+
+-- SEARCH EXTENDED
+INSERT INTO `sys_objects_search_extended` (`object`, `object_content_info`, `module`, `title`, `active`, `class_name`, `class_file`) VALUES
+('bx_forum', 'bx_forum', 'bx_forum', '_bx_forum_search_extended', 1, '', ''),
+('bx_forum_cmts', 'bx_forum_cmts', 'bx_forum', '_bx_forum_search_extended_cmts', 1, 'BxTemplSearchExtendedCmts', '');
+
+
+-- 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_forum', 'bx_forum', 'bx_forum_reports', 'bx_forum_reports_track', '1', 'page.php?i=view-discussion&id={object_id}', 'bx_forum_discussions', 'id', 'author', 'reports', '', '');
+
+
+-- STUDIO: page & widget
+INSERT INTO `sys_std_pages`(`index`, `name`, `header`, `caption`, `icon`) VALUES
+(3, @sName, '_bx_forum', '_bx_forum', 'bx_forum@modules/boonex/forum/|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, @sName, 'content', '{url_studio}module.php?name=bx_forum', '', 'bx_forum@modules/boonex/forum/|std-icon.svg', '_bx_forum', '', '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/groups/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' => 'Groups',
+    '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/groups/updates/update_12.0.2_12.0.3/',
+    'home_uri' => 'groups_update_1202_1203',
+
+    'module_dir' => 'boonex/groups/',
+    'module_uri' => 'groups',
+
+    'db_prefix' => 'bx_groups_',
+    'class_prefix' => 'BxGroups',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_files' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Groups',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

+ 23 - 0
modules/boonex/groups/updates/12.0.2_12.0.3/install/installer.php

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

+ 15 - 0
modules/boonex/groups/updates/12.0.2_12.0.3/install/langs/en.xml

@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources name="en" flag="gb" title="English">
+	<string_add name="_bx_groups_form_profile_input_allow_view_favorite_list"><![CDATA[Visibility]]></string_add>
+	<string_add name="_bx_groups_form_price_input_sys_name"><![CDATA[Name]]></string_add>
+    <string_add name="_bx_groups_form_price_input_name"><![CDATA[Name]]></string_add>
+    <string_add name="_bx_groups_form_price_input_inf_name"><![CDATA[Unique value which will be used in back end and API calls]]></string_add>
+    <string_add name="_bx_groups_form_price_input_err_name"><![CDATA[You need to enter a unique value here]]></string_add>
+	<string_add name="_bx_groups_acl_action_use_paid_join"><![CDATA[Use paid join]]></string_add>
+
+	<string_upd name="_bx_groups_grid_action_title_subscribe"><![CDATA[Subscribe]]></string_upd>
+    <string_upd name="_bx_groups_grid_action_title_subscribe_title"><![CDATA[Create a subscription with recurring billing]]></string_upd>
+
+	<string_del name="_bx_groups_option_members_mode_paid_join"><![CDATA[Paid Join]]></string_del>
+	<string_del name="_bx_groups_form_entry_input_allow_view_favorite_list"><![CDATA[Visibility]]></string_del>
+</resources>

+ 37 - 0
modules/boonex/groups/updates/12.0.2_12.0.3/install/sql/enable.sql

@@ -0,0 +1,37 @@
+-- MENUS
+UPDATE `sys_menu_items` SET `title_system`='_bx_groups_menu_item_title_system_pay_and_join' WHERE `set_name`='bx_groups_view_actions_all' AND `name`='join-group-profile';
+UPDATE `sys_menu_items` SET `title_system`='_bx_groups_menu_item_title_system_edit_pricing' WHERE `set_name`='bx_groups_view_actions_all' AND `name`='edit-group-pricing';
+
+
+-- ACL
+SET @iIdActionUsePaidJoin = (SELECT `ID` FROM `sys_acl_actions` WHERE `Module`='bx_groups' 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_groups', 'use paid join', NULL, '_bx_groups_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);
+
+
+-- GRIDS
+UPDATE `sys_objects_grid` SET `responsive`='1' WHERE `object`='bx_groups_fans';
+
+
+-- PRIVACY 
+UPDATE `sys_objects_privacy` SET `title`='_bx_groups_form_profile_input_allow_view_favorite_list' WHERE `object`='bx_groups_allow_view_favorite_list';

+ 11 - 0
modules/boonex/groups/updates/12.0.2_12.0.3/install/sql/install.sql

@@ -0,0 +1,11 @@
+-- FORMS
+UPDATE `sys_objects_form` SET `override_class_name`='BxGroupsFormPrice', `override_class_file`='modules/boonex/groups/classes/BxGroupsFormPrice.php' WHERE `object`='bx_groups_price';
+
+DELETE FROM `sys_form_inputs` WHERE `object`='bx_groups_price' AND `name`='name';
+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_groups_price', 'bx_groups', 'name', '', '', 0, 'text', '_bx_groups_form_price_input_sys_name', '_bx_groups_form_price_input_name', '_bx_groups_form_price_input_inf_name', 1, 0, 0, '', '', '', 'Avail', '', '_bx_groups_form_price_input_err_name', 'Xss', '', 1, 0);
+
+DELETE FROM `sys_form_display_inputs` WHERE `display_name` IN ('bx_groups_price_add', 'bx_groups_price_edit') AND `input_name`='name';
+INSERT INTO `sys_form_display_inputs` (`display_name`, `input_name`, `visible_for_levels`, `active`, `order`) VALUES
+('bx_groups_price_add', 'name', 2147483647, 1, 2),
+('bx_groups_price_edit', 'name', 2147483647, 1, 2);

+ 261 - 0
modules/boonex/groups/updates/12.0.2_12.0.3/source/classes/BxGroupsConfig.php

@@ -0,0 +1,261 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Groups Groups
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxGroupsConfig extends BxBaseModGroupsConfig
+{
+    function __construct($aModule)
+    {
+        parent::__construct($aModule);
+
+        $this->_aMenuItems2MethodsActions = array_merge($this->_aMenuItems2MethodsActions, array(
+            'view-group-profile' => 'checkAllowedView',
+            'edit-group-profile' => 'checkAllowedEdit',
+            'edit-group-cover' => 'checkAllowedChangeCover',
+            'invite-to-group' => 'checkAllowedInvite',
+            'delete-group-profile' => 'checkAllowedDelete'
+        ));
+
+        $this->CNF = array (
+
+            // module icon
+            'ICON' => 'users col-red2',
+
+            // 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' => 'group_name',
+            'FIELD_TITLE' => 'group_name',
+            'FIELD_TEXT' => 'group_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('group_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-group-profile',
+            'URI_EDIT_ENTRY' => 'edit-group-profile',
+            'URI_EDIT_COVER' => 'edit-group-cover',
+            'URI_JOIN_ENTRY' => 'join-group-profile',
+            'URI_JOINED_ENTRIES' => 'joined-groups',
+            'URI_ENTRIES_BY_CONTEXT' => 'groups-context',
+            'URI_MANAGE_COMMON' => 'groups-manage',
+            'URI_FAVORITES_LIST' => 'groups-favorites',
+
+            'URL_HOME' => 'page.php?i=groups-home',
+            'URL_ENTRY_FANS' => 'page.php?i=group-fans',
+            'URL_MANAGE_COMMON' => 'page.php?i=groups-manage',
+            'URL_MANAGE_ADMINISTRATION' => 'page.php?i=groups-administration',
+
+            'PARAM_NUM_RSS' => 'bx_groups_num_rss',
+            'PARAM_NUM_CONNECTIONS_QUICK' => 'bx_groups_num_connections_quick',
+
+            'PARAM_SEARCHABLE_FIELDS' => 'bx_groups_searchable_fields',
+            'PARAM_PER_PAGE_BROWSE_SHOWCASE' => 'bx_groups_per_page_browse_showcase',
+            'PARAM_PER_PAGE_BROWSE_RECOMMENDED' => 'bx_groups_per_page_browse_recommended',
+
+            'PARAM_MMODE' => 'bx_groups_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_groups_per_page_for_favorites_lists',
+            'PARAM_USE_IN' => 'bx_groups_internal_notifications',
+            
+            // objects
+            'OBJECT_STORAGE' => 'bx_groups_pics',
+            'OBJECT_STORAGE_COVER' => 'bx_groups_pics',
+            'OBJECT_IMAGES_TRANSCODER_THUMB' => 'bx_groups_thumb',
+            'OBJECT_IMAGES_TRANSCODER_ICON' => 'bx_groups_icon',
+            'OBJECT_IMAGES_TRANSCODER_AVATAR' => 'bx_groups_avatar',
+            'OBJECT_IMAGES_TRANSCODER_AVATAR_BIG' => 'bx_groups_avatar_big',
+            'OBJECT_IMAGES_TRANSCODER_PICTURE' => 'bx_groups_picture',
+            'OBJECT_IMAGES_TRANSCODER_COVER' => 'bx_groups_cover',
+            'OBJECT_IMAGES_TRANSCODER_COVER_THUMB' => 'bx_groups_cover_thumb',
+            'OBJECT_IMAGES_TRANSCODER_GALLERY' => 'bx_groups_gallery',
+            'OBJECT_VIEWS' => 'bx_groups',
+            'OBJECT_VOTES' => 'bx_groups',
+            'OBJECT_SCORES' => 'bx_groups',
+            'OBJECT_FAVORITES' => 'bx_groups',
+            'OBJECT_FEATURED' => 'bx_groups',
+            'OBJECT_COMMENTS' => 'bx_groups',
+            'OBJECT_NOTES' => 'bx_groups_notes',
+            'OBJECT_REPORTS' => 'bx_groups',
+            'OBJECT_METATAGS' => 'bx_groups',
+            'OBJECT_FORM_ENTRY' => 'bx_group',
+            'OBJECT_FORM_ENTRY_DISPLAY_VIEW' => 'bx_group_view',
+            'OBJECT_FORM_ENTRY_DISPLAY_VIEW_FULL' => 'bx_group_view_full', // for "info" tab on view group page
+            'OBJECT_FORM_ENTRY_DISPLAY_ADD' => 'bx_group_add',
+            'OBJECT_FORM_ENTRY_DISPLAY_EDIT' => 'bx_group_edit',
+            'OBJECT_FORM_ENTRY_DISPLAY_EDIT_COVER' => 'bx_group_edit_cover',
+            'OBJECT_FORM_ENTRY_DISPLAY_DELETE' => 'bx_group_delete',
+            'OBJECT_FORM_ENTRY_DISPLAY_INVITE' => 'bx_group_invite',
+            'OBJECT_FORM_PRICE' => 'bx_groups_price',
+            'OBJECT_FORM_PRICE_DISPLAY_ADD' => 'bx_groups_price_add',
+            'OBJECT_FORM_PRICE_DISPLAY_EDIT' => 'bx_groups_price_edit',
+            'OBJECT_MENU_ACTIONS_VIEW_ENTRY' => 'bx_groups_view_actions', // actions menu on view entry page
+            'OBJECT_MENU_ACTIONS_VIEW_ENTRY_MORE' => 'bx_groups_view_actions_more', // actions menu on view entry page for "more" popup
+            'OBJECT_MENU_ACTIONS_VIEW_ENTRY_ALL' => 'bx_groups_view_actions_all', // all actions menu on view entry page
+            'OBJECT_MENU_ACTIONS_MY_ENTRIES' => 'bx_groups_my', // actions menu on profile entries page
+            'OBJECT_MENU_SUBMENU' => 'bx_groups_submenu', // main module submenu
+            'OBJECT_MENU_SUBMENU_VIEW_ENTRY' => 'bx_groups_view_submenu',  // view entry submenu
+            'OBJECT_MENU_SUBMENU_VIEW_ENTRY_COVER' => 'bx_groups_view_submenu_cover',  // view entry submenu displayed in cover
+            'OBJECT_MENU_SUBMENU_VIEW_ENTRY_MAIN_SELECTION' => 'groups-home', // first item in view entry submenu from main module submenu
+            'OBJECT_MENU_SNIPPET_META' => 'bx_groups_snippet_meta', // menu for snippet meta info
+            'OBJECT_MENU_MANAGE_TOOLS' => 'bx_groups_menu_manage_tools', //manage menu in content administration tools
+            'OBJECT_PAGE_VIEW_ENTRY' => 'bx_groups_view_profile',
+            'OBJECT_PAGE_VIEW_ENTRY_CLOSED' => 'bx_groups_view_profile_closed',
+            'OBJECT_PRIVACY_VIEW' => 'bx_groups_allow_view_to',
+            'OBJECT_PRIVACY_LIST_VIEW' => 'bx_groups_allow_view_favorite_list',
+            'OBJECT_PRIVACY_VIEW_NOTIFICATION_EVENT' => 'bx_groups_allow_view_notification_to',
+            'OBJECT_PRIVACY_POST' => 'bx_groups_allow_post_to',
+            'OBJECT_GRID_ADMINISTRATION' => 'bx_groups_administration',
+            'OBJECT_GRID_COMMON' => 'bx_groups_common',
+            'OBJECT_GRID_CONNECTIONS' => 'bx_groups_fans',
+            'OBJECT_GRID_INVITES' => 'bx_groups_invites',
+            'OBJECT_GRID_PRICES_MANAGE' => 'bx_groups_prices_manage',
+            'OBJECT_GRID_PRICES_VIEW' => 'bx_groups_prices_view',
+            'OBJECT_CONNECTIONS' => 'bx_groups_fans',
+            'OBJECT_UPLOADERS_COVER' => array('bx_groups_cover_crop'),
+            'OBJECT_UPLOADERS_PICTURE' => array('bx_groups_picture_crop'),
+            'OBJECT_PRE_LIST_ROLES' => 'bx_groups_roles',
+            'OBJECT_PRE_LIST_PERIOD_UNITS' => 'bx_groups_period_units',
+            
+            'BADGES_AVALIABLE' => true,
+            'INVITES_KEYS_LIFETIME' => 86400,
+            'ENABLE_FOR_CONTEXT_IN_MODULES' => array('bx_events', 'bx_spaces'),
+
+            'EMAIL_INVITATION' => 'bx_groups_invitation',
+            'EMAIL_JOIN_REQUEST' => 'bx_groups_join_request',
+            'EMAIL_JOIN_CONFIRM' => 'bx_groups_join_confirm',
+            'EMAIL_FAN_BECOME_ADMIN' => 'bx_groups_fan_become_admin',
+            'EMAIL_ADMIN_BECOME_FAN' => 'bx_groups_admin_become_fan',
+            'EMAIL_FAN_SET_ROLE' => 'bx_groups_set_role',
+            'EMAIL_FAN_REMOVE' => 'bx_groups_fan_remove',
+            'EMAIL_JOIN_REJECT' => 'bx_groups_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_groups_view_actions' => $this->_aMenuItems2MethodsActions,
+                'bx_groups_view_actions_more' => $this->_aMenuItems2MethodsActions,
+                'bx_groups_view_actions_all' => $this->_aMenuItems2MethodsActions,
+            ),
+
+            // informer messages
+            'INFORMERS' => array (
+                'status' => array (
+                    'name' => 'bx-groups-status-not-active',
+                    'map' => array (
+                        BX_PROFILE_STATUS_PENDING => '_bx_groups_txt_account_pending',
+                        BX_PROFILE_STATUS_SUSPENDED => '_bx_groups_txt_account_suspended',
+                    ),
+                ),
+            ),
+
+            // some language keys
+            'T' => array (
+                'txt_sample_single' => '_bx_groups_txt_sample_single',
+                'txt_sample_single_with_article' => '_bx_groups_txt_sample_single_with_article',
+                'txt_sample_comment_single' => '_bx_groups_txt_sample_comment_single',
+                'txt_sample_vote_single' => '_bx_groups_txt_sample_vote_single',
+                'txt_sample_score_up_single' => '_bx_groups_txt_sample_score_up_single',
+                'txt_sample_score_down_single' => '_bx_groups_txt_sample_score_down_single',
+                'txt_private_group' => '_bx_groups_txt_private_group',
+                'txt_N_fans' => '_bx_groups_txt_N_fans',
+                'txt_ntfs_join_invitation' => '_bx_groups_txt_ntfs_join_invitation',
+                'txt_ntfs_join_request' => '_bx_groups_txt_ntfs_join_request',
+                'txt_ntfs_fan_added' => '_bx_groups_txt_ntfs_fan_added',
+                'txt_ntfs_timeline_post_common' => '_bx_groups_txt_ntfs_timeline_post_common',
+                'option_members_mode_multi_roles' => '_bx_groups_option_members_mode_multi_roles',
+                'form_field_author' => '_bx_groups_form_entry_input_author',
+                'menu_item_title_befriend_sent' => '_bx_groups_menu_item_title_befriend_sent',
+                'menu_item_title_unfriend_cancel_request' => '_bx_groups_menu_item_title_unfriend_cancel_request',
+                'menu_item_title_befriend_confirm' => '_bx_groups_menu_item_title_befriend_confirm',
+                'menu_item_title_unfriend_reject_request' => '_bx_groups_menu_item_title_unfriend_reject_request',
+                'menu_item_title_befriend' => '_bx_groups_menu_item_title_befriend',
+                'menu_item_title_unfriend' => '_bx_groups_menu_item_title_unfriend',
+                'grid_action_err_delete' => '_bx_groups_grid_action_err_delete',
+                'grid_txt_account_manager' => '_bx_groups_grid_txt_account_manager',
+                'filter_item_active' => '_bx_groups_grid_filter_item_title_adm_active',
+                'filter_item_pending' => '_bx_groups_grid_filter_item_title_adm_pending',
+                'filter_item_suspended' => '_bx_groups_grid_filter_item_title_adm_suspended',
+                'filter_item_select_one_filter1' => '_bx_groups_grid_filter_item_title_adm_select_one_filter1',
+                'menu_item_manage_my' => '_bx_groups_menu_item_title_manage_my',
+                'menu_item_manage_all' => '_bx_groups_menu_item_title_manage_all',
+                'menu_item_title_become_fan_sent' => '_bx_groups_menu_item_title_become_fan_sent',
+                'menu_item_title_leave_group_cancel_request' => '_bx_groups_menu_item_title_leave_group_cancel_request',
+                'menu_item_title_become_fan' => '_bx_groups_menu_item_title_become_fan',
+                'menu_item_title_leave_group' => '_bx_groups_menu_item_title_leave_group',
+                'txt_all_entries_in' => '_bx_groups_txt_all_entries_in',
+                'txt_all_entries_by_author' => '_bx_groups_page_title_browse_by_author',
+                'txt_all_entries_by_context' => '_bx_groups_page_title_browse_by_context',
+                'txt_invitation_popup_title' => '_bx_groups_txt_invite_popup_title',
+                'txt_invitation_popup_text' => '_bx_groups_txt_invite_popup_text',
+                'txt_invitation_popup_accept_button' => '_bx_groups_txt_invite_popup_button_accept',
+                'txt_invitation_popup_decline_button' => '_bx_groups_txt_invite_popup_button_decline',
+                'txt_invitation_popup_error_invitation_absent' => '_bx_groups_txt_invite_popup_error_invitation_absent',
+                'txt_invitation_popup_error_wrong_user' => '_bx_groups_txt_invite_popup_error_invitation_wrong_user',
+                'txt_n_unit' => '_bx_groups_txt_n_unit',
+                'txt_buy_title' => '_bx_groups_grid_action_title_buy_title',
+                'txt_cart_item_title' => '_bx_groups_txt_cart_item_title',
+                'txt_subscribe_title' => '_bx_groups_grid_action_title_subscribe_title',
+                'msg_performed' => '_bx_groups_msg_performed',
+                'err_cannot_perform' => '_bx_groups_err_cannot_perform',
+            ),
+
+        );
+
+        $this->_aJsClasses = array(
+            'main' => 'BxGroupsMain',
+            'manage_tools' => 'BxGroupsManageTools',
+            'invite_popup' => 'BxGroupsInvitePopup',
+            'prices' => 'BxGroupsPrices'
+        );
+
+        $this->_aJsObjects = array(
+            'main' => 'oBxGroupsMain',
+            'manage_tools' => 'oBxGroupsManageTools',
+            'invite_popup' => 'oBxGroupsInvitePopup',
+            'prices' => 'oBxGroupsPrices'
+        );
+
+        $this->_aGridObjects = array(
+            'common' => $this->CNF['OBJECT_GRID_COMMON'],
+            'administration' => $this->CNF['OBJECT_GRID_ADMINISTRATION'],
+        );
+    }
+
+}
+
+/** @} */

+ 22 - 0
modules/boonex/groups/updates/12.0.2_12.0.3/source/classes/BxGroupsFormPrice.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    Groups Groups
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxGroupsFormPrice extends BxBaseModGroupsFormPrice
+{
+    public function __construct($aInfo, $oTemplate = false)
+    {
+        $this->_sModule = 'bx_groups';
+
+        parent::__construct($aInfo, $oTemplate);
+    }
+}
+
+/** @} */

+ 25 - 0
modules/boonex/groups/updates/12.0.2_12.0.3/source/classes/BxGroupsModule.php

@@ -0,0 +1,25 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Groups Groups
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+/**
+ * Groups profiles module.
+ */
+class BxGroupsModule extends BxBaseModGroupsModule
+{
+    function __construct(&$aModule)
+    {
+        parent::__construct($aModule);
+
+        $this->_aSearchableNamesExcept[] = $this->_oConfig->CNF['FIELD_JOIN_CONFIRMATION'];
+    }
+}
+
+/** @} */

+ 152 - 0
modules/boonex/groups/updates/12.0.2_12.0.3/source/install/config.php

@@ -0,0 +1,152 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Groups Groups
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_groups',
+    'title' => 'Groups',
+    'note' => 'Basic group profiles functionality.',
+    '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/groups/',
+    'home_uri' => 'groups',
+
+    'db_prefix' => 'bx_groups_',
+    'class_prefix' => 'BxGroups',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Groups',
+
+    /**
+     * 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_groups_pics'
+    ),
+
+	/**
+     * Transcoders.
+     */
+    'transcoders' => array(
+    	'bx_groups_icon', 
+    	'bx_groups_thumb', 
+    	'bx_groups_avatar', 
+        'bx_groups_avatar_big', 
+    	'bx_groups_picture', 
+    	'bx_groups_cover', 
+    	'bx_groups_cover_thumb',
+        'bx_groups_gallery'
+    ),
+
+    /**
+     * Extended Search Forms.
+     */
+    'esearches' => array(
+        'bx_groups',
+    	'bx_groups_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',
+    ),
+);
+
+/** @} */

+ 445 - 0
modules/boonex/groups/updates/12.0.2_12.0.3/source/install/langs/en.xml

@@ -0,0 +1,445 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources name="en" flag="gb" title="English">
+    <string name="_bx_groups"><![CDATA[Groups]]></string>
+    <string name="_bx_groups_cmts"><![CDATA[Groups' Comments]]></string>
+
+    <string name="_bx_groups_option_num_connections_quick"><![CDATA[Number of items in friends block]]></string>
+    <string name="_bx_groups_option_per_page_browse"><![CDATA[Number of items per page]]></string>
+    <string name="_bx_groups_option_num_rss"><![CDATA[Number of items in RSS feed]]></string>
+    <string name="_bx_groups_option_searchable_fields"><![CDATA[Searchable fields]]></string>
+    <string name="_bx_groups_option_members_mode"><![CDATA[Special mode for group members]]></string>
+    <string name="_bx_groups_option_members_mode_multi_roles"><![CDATA[Multi Roles]]></string>
+    <string name="_bx_groups_option_per_page_for_favorites_lists"><![CDATA[Number of favorite lists per page]]></string>
+    <string name="_bx_groups_option_internal_notifications"><![CDATA[Use internal notifications]]></string>
+
+    <string name="_bx_groups_form_profile"><![CDATA[Groups]]></string>
+    <string name="_bx_groups_form_profile_display_add"><![CDATA[Add Group]]></string>
+    <string name="_bx_groups_form_profile_display_edit"><![CDATA[Edit Group]]></string>
+    <string name="_bx_groups_form_profile_display_edit_cover"><![CDATA[Edit Cover]]></string>
+    <string name="_bx_groups_form_profile_display_delete"><![CDATA[Delete Group]]></string>
+    <string name="_bx_groups_form_profile_display_view"><![CDATA[View Group]]></string>
+    <string name="_bx_groups_form_profile_display_view_full"><![CDATA[Full View Group]]></string>
+    <string name="_bx_groups_form_profile_display_invite"><![CDATA[Invite to Group]]></string>
+    <string name="_bx_groups_form_entry_input_author"><![CDATA[Author]]></string>
+    <string name="_bx_groups_form_profile_input_sys_do_submit"><![CDATA[Submit]]></string>
+    <string name="_bx_groups_form_profile_input_sys_join_confirm"><![CDATA[Join confirmation]]></string>
+    <string name="_bx_groups_form_profile_input_join_confirm"><![CDATA[Join confirmation]]></string>
+    <string name="_bx_groups_form_profile_input_sys_allow_view_to"><![CDATA[Visible to]]></string>
+    <string name="_bx_groups_form_profile_input_allow_view_to"><![CDATA[Visible to]]></string>
+    <string name="_bx_groups_form_profile_input_allow_view_favorite_list"><![CDATA[Visibility]]></string>
+    <string name="_bx_groups_form_profile_input_allow_view_to_desc"><![CDATA[Closed - anyone can find the group and see who's in it, only members can see posts. Secret - only members can find the group and see posts.]]></string>
+    <string name="_bx_groups_form_profile_input_sys_allow_post_to"><![CDATA[Who can post]]></string>
+    <string name="_bx_groups_form_profile_input_allow_post_to"><![CDATA[Who can post]]></string>
+    <string name="_bx_groups_form_profile_input_sys_initial_members"><![CDATA[Invite Members]]></string>
+    <string name="_bx_groups_form_profile_input_initial_members"><![CDATA[Invite Members]]></string>
+    <string name="_bx_groups_form_profile_input_sys_group_name"><![CDATA[Group Name]]></string>
+    <string name="_bx_groups_form_profile_input_group_name"><![CDATA[Group Name]]></string>
+    <string name="_bx_groups_form_profile_input_group_name_err"><![CDATA[This information is essential. Please, fill in this field.]]></string>
+    <string name="_bx_groups_form_profile_input_sys_group_desc"><![CDATA[Description]]></string>
+    <string name="_bx_groups_form_profile_input_group_desc"><![CDATA[Description]]></string>
+    <string name="_bx_groups_form_profile_input_sys_group_cat"><![CDATA[Category]]></string>
+    <string name="_bx_groups_form_profile_input_group_cat"><![CDATA[Category]]></string>
+    <string name="_bx_groups_form_profile_input_group_cat_err"><![CDATA[Category field is mandatory]]></string>
+    <string name="_bx_groups_form_profile_input_sys_picture"><![CDATA[Group Picture]]></string>
+    <string name="_bx_groups_form_profile_input_picture"><![CDATA[Upload New Group Picture]]></string>
+    <string name="_bx_groups_form_profile_input_picture_err"><![CDATA[Group picture is mandatory.]]></string>
+    <string name="_bx_groups_form_profile_input_sys_cover"><![CDATA[Cover Picture]]></string>
+    <string name="_bx_groups_form_profile_input_cover"><![CDATA[Upload New Cover Picture]]></string>
+    <string name="_bx_groups_form_profile_input_sys_delete_confirm"><![CDATA[Delete confirmation]]></string>
+    <string name="_bx_groups_form_profile_input_delete_confirm"><![CDATA[I am sure I want to delete this group]]></string>
+    <string name="_bx_groups_form_profile_input_delete_confirm_info"><![CDATA[This action can not be undone.]]></string>
+    <string name="_bx_groups_form_profile_input_delete_confirm_error"><![CDATA[Please check this checkbox if you really want to delete group.]]></string>
+
+    <string name="_bx_groups_form_price"><![CDATA[Price]]></string>
+    <string name="_bx_groups_form_price_display_add"><![CDATA[Add]]></string>
+    <string name="_bx_groups_form_price_display_edit"><![CDATA[Edit]]></string>
+    <string name="_bx_groups_form_price_input_sys_id"><![CDATA[ID]]></string>
+    <string name="_bx_groups_form_price_input_sys_role_id"><![CDATA[Role ID]]></string>
+    <string name="_bx_groups_form_price_input_sys_name"><![CDATA[Name]]></string>
+    <string name="_bx_groups_form_price_input_name"><![CDATA[Name]]></string>
+    <string name="_bx_groups_form_price_input_inf_name"><![CDATA[Unique value which will be used in back end and API calls]]></string>
+    <string name="_bx_groups_form_price_input_err_name"><![CDATA[You need to enter a unique value here]]></string>
+    <string name="_bx_groups_form_price_input_sys_period"><![CDATA[Period]]></string>
+    <string name="_bx_groups_form_price_input_period"><![CDATA[Period]]></string>
+    <string name="_bx_groups_form_price_input_inf_period"><![CDATA[Use 0 for lifetime]]></string>
+    <string name="_bx_groups_form_price_input_sys_period_unit"><![CDATA[Period unit]]></string>
+    <string name="_bx_groups_form_price_input_period_unit"><![CDATA[Period unit]]></string>
+    <string name="_bx_groups_form_price_input_inf_period_unit"><![CDATA[Leave empty for lifetime level.]]></string>
+    <string name="_bx_groups_form_price_input_err_period_unit"><![CDATA[You need to select a period unit here.]]></string>
+    <string name="_bx_groups_form_price_input_sys_price"><![CDATA[Price]]></string>
+    <string name="_bx_groups_form_price_input_price"><![CDATA[Price]]></string>
+    <string name="_bx_groups_form_price_input_inf_price"><![CDATA[Use 0 or leave empty to create free level.]]></string>
+    <string name="_bx_groups_form_price_input_sys_do_submit"><![CDATA[Submit]]></string>
+    <string name="_bx_groups_form_price_input_do_submit"><![CDATA[Submit]]></string>
+    <string name="_bx_groups_form_price_input_sys_do_cancel"><![CDATA[Cancel]]></string>
+    <string name="_bx_groups_form_price_input_do_cancel"><![CDATA[Cancel]]></string>
+
+    <string name="_bx_groups_acl_action_create_profile"><![CDATA[Create Group]]></string>
+    <string name="_bx_groups_acl_action_use_paid_join"><![CDATA[Use paid join]]></string>
+    <string name="_bx_groups_acl_action_delete_profile"><![CDATA[Delete Group]]></string>
+    <string name="_bx_groups_acl_action_view_profile"><![CDATA[View Group]]></string>
+    <string name="_bx_groups_acl_action_edit_any_profile"><![CDATA[Edit Any Group]]></string>
+    <string name="_bx_groups_acl_action_delete_invites"><![CDATA[Delete Invites]]></string>
+
+        <string name="_bx_groups_page_title_sys_entries_in_context"><![CDATA[Groups in context]]></string>
+        <string name="_bx_groups_page_title_entries_in_context"><![CDATA[Groups in {display_name}]]></string>
+	<string name="_bx_groups_page_title_sys_joined_entries"><![CDATA[Profile Groups]]></string>
+	<string name="_bx_groups_page_title_joined_entries"><![CDATA[Profile Groups]]></string>
+	<string name="_bx_groups_page_title_sys_create_profile"><![CDATA[Create Group]]></string>
+	<string name="_bx_groups_page_title_create_profile"><![CDATA[Create Group]]></string>
+	<string name="_bx_groups_page_title_sys_edit_profile"><![CDATA[Edit Group]]></string>
+	<string name="_bx_groups_page_title_edit_profile"><![CDATA[Edit Group]]></string>
+	<string name="_bx_groups_page_title_sys_edit_profile_cover"><![CDATA[Edit Group Cover]]></string>
+	<string name="_bx_groups_page_title_edit_profile_cover"><![CDATA[Edit Cover]]></string>
+	<string name="_bx_groups_page_title_sys_delete_profile"><![CDATA[Delete Group]]></string>
+	<string name="_bx_groups_page_title_delete_profile"><![CDATA[Delete Group]]></string>
+        <string name="_bx_groups_page_title_sys_join_profile"><![CDATA[Join Group]]></string>
+	<string name="_bx_groups_page_title_join_profile"><![CDATA[Join Group]]></string>
+	<string name="_bx_groups_page_title_sys_view_profile_closed"><![CDATA[View Closed Group]]></string>
+	<string name="_bx_groups_page_title_sys_view_profile"><![CDATA[View Group]]></string>
+	<string name="_bx_groups_page_title_view_profile"><![CDATA[{display_name}]]></string>
+	<string name="_bx_groups_page_title_browse"><![CDATA[Groups]]></string>
+	<string name="_bx_groups_page_title_browse_by_author"><![CDATA[Groups of {display_name}]]></string>
+        <string name="_bx_groups_page_title_browse_by_context"><![CDATA[Groups in {display_name}]]></string>
+	<string name="_bx_groups_page_title_browse_featured"><![CDATA[Featured Groups]]></string>
+	<string name="_bx_groups_page_title_browse_top"><![CDATA[Top Groups]]></string>
+	<string name="_bx_groups_page_title_browse_recent"><![CDATA[New Groups]]></string>
+	<string name="_bx_groups_page_title_browse_connections"><![CDATA[{0} connections]]></string>
+	<string name="_bx_groups_page_title_browse_connections_mutual"><![CDATA[{0} and {1} mutual connections]]></string>
+	<string name="_bx_groups_page_title_sys_profile_friends"><![CDATA[Friends]]></string>
+	<string name="_bx_groups_page_title_profile_friends"><![CDATA[Friends]]></string>
+	<string name="_bx_groups_page_title_sys_group_fans"><![CDATA[Members]]></string>
+	<string name="_bx_groups_page_title_group_fans"><![CDATA[Members]]></string>
+	<string name="_bx_groups_page_title_sys_profile_comments"><![CDATA[Comments]]></string>
+    <string name="_bx_groups_page_title_profile_comments"><![CDATA[Comments]]></string>
+	<string name="_bx_groups_page_title_sys_profile_info"><![CDATA[Group Info]]></string>
+	<string name="_bx_groups_page_title_profile_info"><![CDATA[Info about {display_name}]]></string>
+        <string name="_bx_groups_page_title_sys_profile_pricing"><![CDATA[Pricing]]></string>
+	<string name="_bx_groups_page_title_profile_pricing"><![CDATA[Pricing]]></string>
+	<string name="_bx_groups_page_title_sys_recent"><![CDATA[New Groups]]></string>
+	<string name="_bx_groups_page_title_recent"><![CDATA[New Groups]]></string>
+	<string name="_bx_groups_page_title_sys_manage"><![CDATA[Manage Own Groups]]></string>
+	<string name="_bx_groups_page_title_sys_manage_administration"><![CDATA[Manage All Groups]]></string>
+	<string name="_bx_groups_page_title_manage"><![CDATA[Manage Groups]]></string>
+	<string name="_bx_groups_page_title_sys_top"><![CDATA[Top Groups]]></string>
+	<string name="_bx_groups_page_title_top"><![CDATA[Top Groups]]></string>
+  <string name="_bx_groups_page_title_sys_joined"><![CDATA[Joined  Groups]]></string>
+  <string name="_bx_groups_page_title_joined"><![CDATA[Joined Groups]]></string>
+	<string name="_bx_groups_page_title_sys_invite_to_group"><![CDATA[Invite Members to the Group]]></string>
+	<string name="_bx_groups_page_title_invite_to_group"><![CDATA[Invite Members to the Group]]></string>
+	<string name="_bx_groups_page_title_sys_entries_search"><![CDATA[Search]]></string>
+    <string name="_bx_groups_page_title_entries_search"><![CDATA[Search]]></string>
+  <string name="_bx_groups_page_title_sys_entries_favorites"><![CDATA[Favorives Groups]]></string>
+  <string name="_bx_groups_page_title_entries_favorites"><![CDATA[Favorives Groups]]></string>
+
+    <string name="_bx_groups_page_block_title_sys_entries_actions"><![CDATA[Groups actions]]></string>
+    <string name="_bx_groups_page_block_title_entries_actions"><![CDATA[Groups actions]]></string>
+    <string name="_bx_groups_page_block_title_favorites_entries"><![CDATA["{title}" List]]></string>
+    <string name="_bx_groups_page_block_title_favorites_entries_info"><![CDATA[Info]]></string>
+    <string name="_bx_groups_page_block_title_favorites_entries_actions"><![CDATA[Favorites List Actions]]></string>
+    <string name="_bx_groups_page_block_title_sys_entries_of_author"><![CDATA[Groups of author]]></string>
+    <string name="_bx_groups_page_block_title_entries_of_author"><![CDATA[Groups by {display_name}]]></string>
+    <string name="_bx_groups_page_block_title_favorites_of_author"><![CDATA[Favorite Groups]]></string>
+    <string name="_bx_groups_page_block_title_sys_favorites_of_author"><![CDATA[Favorite Groups]]></string>
+    <string name="_bx_groups_page_block_title_entries_in_context_link"><![CDATA[Groups in <a href="{profile_link}">{display_name}</a>]]></string>
+    <string name="_bx_groups_page_block_title_entries_in_context"><![CDATA[Groups in context]]></string>
+    <string name="_bx_groups_page_block_title_sys_entries_in_context"><![CDATA[Groups in context]]></string>
+	<string name="_bx_groups_page_block_title_sys_joined_entries"><![CDATA[Joined Groups]]></string>
+	<string name="_bx_groups_page_block_title_joined_entries"><![CDATA[Joined Groups]]></string>
+	<string name="_bx_groups_page_block_title_create_profile"><![CDATA[Create Group]]></string>
+	<string name="_bx_groups_page_block_title_edit_profile"><![CDATA[Edit Group]]></string>
+	<string name="_bx_groups_page_block_title_edit_profile_cover"><![CDATA[Edit Cover]]></string>
+	<string name="_bx_groups_page_block_title_delete_profile"><![CDATA[Delete Group]]></string>
+        <string name="_bx_groups_page_block_title_join_profile"><![CDATA[Join Group]]></string>
+	<string name="_bx_groups_page_block_title_profile_info_link"><![CDATA[About <a href="{profile_link}">{display_name}</a>]]></string>
+	<string name="_bx_groups_page_block_title_profile_info"><![CDATA[Info]]></string>
+	<string name="_bx_groups_page_block_title_system_profile_info"><![CDATA[Info]]></string>
+        <string name="_bx_groups_page_block_title_system_profile_pricing"><![CDATA[Pricing]]></string>
+        <string name="_bx_groups_page_block_title_profile_pricing"><![CDATA[Pricing]]></string>
+        <string name="_bx_groups_page_block_title_profile_pricing_link"><![CDATA[Pricing of <a href="{profile_link}">{display_name}</a>]]></string>
+	<string name="_bx_groups_page_block_title_profile_description"><![CDATA[Description]]></string>
+	<string name="_bx_groups_page_block_title_profile_friends_link"><![CDATA[Friends of <a href="{profile_link}">{display_name}</a>]]></string>
+	<string name="_bx_groups_page_block_title_profile_friends"><![CDATA[Friends]]></string>
+	<string name="_bx_groups_page_block_title_system_profile_friends"><![CDATA[Friends]]></string>
+        <string name="_bx_groups_page_block_title_entry_context"><![CDATA[Posted in]]></string>
+	<string name="_bx_groups_page_block_title_admins"><![CDATA[Administrators]]></string>
+	<string name="_bx_groups_page_block_title_fans_link"><![CDATA[Members of <a href="{profile_link}">{display_name}</a>]]></string>
+    <string name="_bx_groups_page_block_title_fans"><![CDATA[Members]]></string>
+	<string name="_bx_groups_page_block_title_system_fans"><![CDATA[Members]]></string>
+  <string name="_bx_groups_page_block_title_fans_invites"><![CDATA[Invites]]></string>
+  <string name="_bx_groups_page_block_title_system_invites"><![CDATA[Invites]]></string>
+        <string name="_bx_groups_page_block_title_profile_location"><![CDATA[Location]]></string>
+	<string name="_bx_groups_page_block_title_profile_comments"><![CDATA[Comments]]></string>
+    <string name="_bx_groups_page_block_title_profile_comments_link"><![CDATA[Comments to <a href="{entry_link}">{title}</a>]]></string>
+	<string name="_bx_groups_page_block_title_profile_actions"><![CDATA[Actions]]></string>
+	<string name="_bx_groups_page_block_title_featured_profiles"><![CDATA[Featured Groups]]></string>
+	<string name="_bx_groups_page_block_title_latest_profiles"><![CDATA[New Groups]]></string>
+	<string name="_bx_groups_page_block_title_system_manage"><![CDATA[Manage Own Groups]]></string>
+	<string name="_bx_groups_page_block_title_system_manage_administration"><![CDATA[Manage All Groups]]></string>
+	<string name="_bx_groups_page_block_title_manage"><![CDATA[Manage Groups]]></string>
+    <string name="_bx_groups_page_block_title_top_profiles"><![CDATA[Top Groups]]></string>
+  <string name="_bx_groups_page_block_title_joined_profiles"><![CDATA[Joined Groups]]></string>
+    <string name="_bx_groups_page_block_title_entry_all_actions"><![CDATA[All Actions]]></string>
+    <string name="_bx_groups_page_block_title_entry_social_sharing"><![CDATA[Share]]></string>
+    <string name="_bx_groups_page_block_title_categories"><![CDATA[Groups Categories]]></string>
+    <string name="_bx_groups_page_block_title_invite_to_group"><![CDATA[Invite Members to the Group]]></string>
+    <string name="_bx_groups_page_block_title_search_form"><![CDATA[Search Form]]></string>
+    <string name="_bx_groups_page_block_title_search_results"><![CDATA[Search Results]]></string>
+    <string name="_bx_groups_page_block_title_search_form_cmts"><![CDATA[Comments Search Form]]></string>
+    <string name="_bx_groups_page_block_title_search_results_cmts"><![CDATA[Comments Search Results]]></string>
+    <string name="_bx_groups_page_block_title_sys_featured_entries_view_showcase"><![CDATA[Featured Groups (Showcase View)]]></string>
+    <string name="_bx_groups_page_block_title_featured_entries_view_showcase"><![CDATA[Featured Groups]]></string>
+    <string name="_bx_groups_page_block_title_sys_recommended_entries_view_showcase"><![CDATA[Recommended Groups (Showcase View)]]></string>
+    <string name="_bx_groups_page_block_title_recommended_entries_view_showcase"><![CDATA[Recommended Groups]]></string>
+    <string name="_bx_groups_page_block_title_sys_labels_tree"><![CDATA[Labels tree]]></string>
+    <string name="_bx_groups_page_block_title_labels_tree"><![CDATA[Labels tree]]></string>
+    <string name="_bx_groups_page_block_title_sys_groups_browse_by_label"><![CDATA[Browse by label]]></string>
+    <string name="_bx_groups_page_block_title_groups_browse_by_label"><![CDATA[Browse by label]]></string>
+    <string name="_bx_groups_page_block_title_sys_labels_breadcrumbs"><![CDATA[Labels breadcrumbs]]></string>
+    <string name="_bx_groups_page_block_title_labels_breadcrumbs"><![CDATA[Labels breadcrumbs]]></string>
+    
+
+  <string name="_bx_groups_menu_title_submenu"><![CDATA[Groups Submenu]]></string>
+    <string name="_bx_groups_menu_set_title_submenu"><![CDATA[Groups Submenu]]></string>
+    <string name="_bx_groups_menu_set_title_view_profile_actions"><![CDATA[Group Actions]]></string>
+    <string name="_bx_groups_menu_title_view_profile_actions"><![CDATA[Group Actions]]></string>
+    <string name="_bx_groups_menu_set_title_view_profile_actions_more"><![CDATA[Group More Actions]]></string>
+    <string name="_bx_groups_menu_title_view_profile_actions_more"><![CDATA[Group More Actions]]></string>
+    <string name="_bx_groups_menu_set_title_view_profile_submenu"><![CDATA[View Group Submenu]]></string>
+    <string name="_bx_groups_menu_title_view_profile_submenu"><![CDATA[View Group Submenu]]></string>
+    <string name="_bx_groups_menu_title_view_profile_submenu_cover"><![CDATA[Group Cover Submenu]]></string>
+    <string name="_bx_groups_menu_title_entries_my"><![CDATA[Profile Groups Action Menu]]></string>
+    <string name="_bx_groups_menu_set_title_entries_my"><![CDATA[Profile Groups Menu]]></string>
+	<string name="_bx_groups_menu_set_title_manage_tools"><![CDATA[Manage Tools Submenu]]></string>
+    <string name="_bx_groups_menu_title_manage_tools"><![CDATA[Manage Tools Submenu]]></string>
+    <string name="_bx_groups_menu_item_title_system_delete"><![CDATA[Delete]]></string>
+    <string name="_bx_groups_menu_item_title_delete"><![CDATA[Delete]]></string>
+    <string name="_bx_groups_menu_item_title_system_delete_with_content"><![CDATA[Delete With Content]]></string>
+    <string name="_bx_groups_menu_item_title_delete_with_content"><![CDATA[Delete With Content]]></string>
+    <string name="_bx_groups_menu_item_title_system_clear_reports"><![CDATA[Clear reports]]></string>
+    <string name="_bx_groups_menu_item_title_clear_reports"><![CDATA[Clear reports]]></string>
+    <string name="_bx_groups_menu_item_title_system_edit_cover"><![CDATA[Edit Cover]]></string>
+    <string name="_bx_groups_menu_item_title_edit_cover"><![CDATA[Edit Cover]]></string>
+    <string name="_bx_groups_menu_item_title_system_edit_pricing"><![CDATA[Edit Pricing]]></string>
+    <string name="_bx_groups_menu_item_title_edit_pricing"><![CDATA[Edit Pricing]]></string>
+    <string name="_bx_groups_menu_item_title_system_edit_profile"><![CDATA[Edit Group]]></string>
+    <string name="_bx_groups_menu_item_title_edit_profile"><![CDATA[Edit Group]]></string>
+    <string name="_bx_groups_menu_item_title_system_delete_profile"><![CDATA[Delete Group]]></string>
+    <string name="_bx_groups_menu_item_title_delete_profile"><![CDATA[Delete Group]]></string>
+    <string name="_bx_groups_menu_item_title_system_delete_account"><![CDATA[Delete Account]]></string>
+    <string name="_bx_groups_menu_item_title_delete_account"><![CDATA[Delete Account]]></string>
+    <string name="_bx_groups_menu_item_title_system_profile_type"><![CDATA[Group]]></string>
+    <string name="_bx_groups_menu_item_title_profile_type"><![CDATA[Group]]></string>
+    <string name="_bx_groups_menu_item_title_system_create_profile"><![CDATA[Group]]></string>
+    <string name="_bx_groups_menu_item_title_create_profile"><![CDATA[Group]]></string>
+    <string name="_bx_groups_menu_item_title_system_view_profile_friends"><![CDATA[Friends]]></string>
+    <string name="_bx_groups_menu_item_title_view_profile_friends"><![CDATA[Friends]]></string>
+    <string name="_bx_groups_menu_item_title_system_view_entries_in_context"><![CDATA[Groups]]></string>
+    <string name="_bx_groups_menu_item_title_view_entries_in_context"><![CDATA[Groups]]></string>
+    <string name="_bx_groups_menu_item_title_system_view_joined_groups"><![CDATA[Groups]]></string>
+    <string name="_bx_groups_menu_item_title_view_joined_groups"><![CDATA[Groups]]></string>
+    <string name="_bx_groups_menu_item_title_system_view_fans"><![CDATA[Members]]></string>
+    <string name="_bx_groups_menu_item_title_view_fans"><![CDATA[Members]]></string>
+    <string name="_bx_groups_menu_item_title_system_view_profile_comments"><![CDATA[Comments]]></string>
+    <string name="_bx_groups_menu_item_title_view_profile_comments"><![CDATA[Comments]]></string>
+    <string name="_bx_groups_menu_item_title_system_view_profile_info"><![CDATA[Info]]></string>
+    <string name="_bx_groups_menu_item_title_view_profile_info"><![CDATA[Info]]></string>
+    <string name="_bx_groups_menu_item_title_system_view_profile_view"><![CDATA[Group]]></string>
+    <string name="_bx_groups_menu_item_title_view_profile_view"><![CDATA[Group]]></string>
+    <string name="_bx_groups_menu_item_title_system_view_profile_more_auto"><![CDATA[More]]></string>
+    <string name="_bx_groups_menu_item_title_view_profile_more_auto"><![CDATA[More]]></string>
+    <string name="_bx_groups_menu_item_title_system_invite"><![CDATA[Invite]]></string>
+    <string name="_bx_groups_menu_item_title_invite"><![CDATA[Invite]]></string>
+
+    <string name="_bx_groups_menu_item_title_system_befriend"><![CDATA[Add friend]]></string>
+    <string name="_bx_groups_menu_item_title_befriend"><![CDATA[Add friend]]></string>
+    <string name="_bx_groups_menu_item_title_befriend_sent"><![CDATA[Add friend (requested)]]></string>
+    <string name="_bx_groups_menu_item_title_befriend_confirm"><![CDATA[Accept friend request]]></string>
+    <string name="_bx_groups_menu_item_title_system_unfriend"><![CDATA[Unfriend]]></string>
+    <string name="_bx_groups_menu_item_title_unfriend"><![CDATA[Unfriend]]></string>
+    <string name="_bx_groups_menu_item_title_unfriend_cancel_request"><![CDATA[Cancel friend request]]></string>
+    <string name="_bx_groups_menu_item_title_unfriend_reject_request"><![CDATA[Reject friend request]]></string>
+
+    <string name="_bx_groups_menu_item_title_system_become_fan"><![CDATA[Join Group]]></string>
+    <string name="_bx_groups_menu_item_title_become_fan"><![CDATA[Join Group]]></string>
+    <string name="_bx_groups_menu_item_title_become_fan_sent"><![CDATA[Join Group (requested)]]></string>
+    <string name="_bx_groups_menu_item_title_become_fan_confirm"><![CDATA[Accept Request]]></string>
+    <string name="_bx_groups_menu_item_title_system_leave_group"><![CDATA[Leave Group]]></string>
+    <string name="_bx_groups_menu_item_title_leave_group"><![CDATA[Leave Group]]></string>
+    <string name="_bx_groups_menu_item_title_leave_group_cancel_request"><![CDATA[Cancel Request]]></string>
+    <string name="_bx_groups_menu_item_title_leave_group_reject_request"><![CDATA[Reject Request]]></string>
+
+    <string name="_bx_groups_menu_item_title_system_pay_and_join"><![CDATA[Pay & Join]]></string>
+    <string name="_bx_groups_menu_item_title_pay_and_join"><![CDATA[Pay & Join]]></string>
+
+    <string name="_bx_groups_menu_item_title_system_subscribe"><![CDATA[Follow]]></string>
+    <string name="_bx_groups_menu_item_title_subscribe"><![CDATA[Follow]]></string>
+    <string name="_bx_groups_menu_item_title_system_unsubscribe"><![CDATA[Unfollow]]></string>
+    <string name="_bx_groups_menu_item_title_unsubscribe"><![CDATA[Unfollow]]></string>
+    <string name="_bx_groups_menu_item_title_system_more_actions"><![CDATA[More Actions]]></string>
+    <string name="_bx_groups_menu_item_title_more_actions"><![CDATA[]]></string>
+    <string name="_bx_groups_menu_item_title_system_friends"><![CDATA[Friends]]></string>
+    <string name="_bx_groups_menu_item_title_friends"><![CDATA[Friends]]></string>
+    <string name="_bx_groups_menu_item_title_system_manage_my_groups"><![CDATA[My groups]]></string>
+    <string name="_bx_groups_menu_item_title_manage_my_groups"><![CDATA[Groups]]></string>
+    <string name="_bx_groups_menu_item_title_system_entries_recent"><![CDATA[New]]></string>
+    <string name="_bx_groups_menu_item_title_entries_recent"><![CDATA[New]]></string>
+    <string name="_bx_groups_menu_item_title_system_entries_search"><![CDATA[Search]]></string>
+    <string name="_bx_groups_menu_item_title_entries_search"><![CDATA[Search]]></string>
+    <string name="_bx_groups_menu_item_title_system_entries_joined"><![CDATA[Joined]]></string>
+    <string name="_bx_groups_menu_item_title_entries_joined"><![CDATA[Joined]]></string>
+    <string name="_bx_groups_menu_item_title_system_entries_manage"><![CDATA[Manage]]></string>
+    <string name="_bx_groups_menu_item_title_entries_manage"><![CDATA[Manage]]></string>
+    <string name="_bx_groups_menu_item_title_system_entries_home"><![CDATA[Groups]]></string>
+    <string name="_bx_groups_menu_item_title_entries_home"><![CDATA[Groups]]></string>
+    <string name="_bx_groups_menu_item_title_system_admt_groups"><![CDATA[Groups]]></string>
+    <string name="_bx_groups_menu_item_title_admt_groups"><![CDATA[Groups]]></string>
+    <string name="_bx_groups_menu_item_title_manage_my"><![CDATA[My Groups]]></string>
+    <string name="_bx_groups_menu_item_title_manage_all"><![CDATA[All Groups]]></string>
+    <string name="_bx_groups_menu_item_title_system_entries_top"><![CDATA[Top]]></string>
+    <string name="_bx_groups_menu_item_title_entries_top"><![CDATA[Top]]></string>
+    <string name="_bx_groups_menu_item_title_system_sm_privacy"><![CDATA[Privacy]]></string>
+    <string name="_bx_groups_menu_item_title_sm_privacy"><![CDATA[Privacy]]></string>
+
+    <string name="_bx_groups_grid_filter_item_title_adm_select_one_filter1"><![CDATA[All Statuses]]></string>
+    <string name="_bx_groups_grid_filter_item_title_adm_active"><![CDATA[Active]]></string>
+    <string name="_bx_groups_grid_filter_item_title_adm_pending"><![CDATA[Pending]]></string>
+    <string name="_bx_groups_grid_filter_item_title_adm_suspended"><![CDATA[Suspended]]></string>
+    <string name="_bx_groups_grid_column_title_adm_active"><![CDATA[Active]]></string>
+    <string name="_bx_groups_grid_column_title_adm_name"><![CDATA[Name]]></string>
+    <string name="_bx_groups_grid_column_title_adm_added"><![CDATA[Created]]></string>
+    <string name="_bx_groups_grid_column_title_adm_account"><![CDATA[Account]]></string>
+    <string name="_bx_groups_grid_action_title_adm_audit_context"><![CDATA[Audit actions in context]]></string>
+    <string name="_bx_groups_grid_action_title_adm_audit_content"><![CDATA[Audit actions with context]]></string>
+    <string name="_bx_groups_grid_action_title_adm_delete"><![CDATA[Delete]]></string>
+    <string name="_bx_groups_grid_action_title_adm_delete_with_content"><![CDATA[Delete With Content]]></string>
+    <string name="_bx_groups_grid_action_title_adm_clear_reports"><![CDATA[Clear reports]]></string>
+    <string name="_bx_groups_grid_action_title_adm_more_actions"><![CDATA[More Actions]]></string>
+    <string name="_bx_groups_grid_action_err_delete"><![CDATA[Cannot delete the selected group(s).]]></string>
+    <string name="_bx_groups_grid_txt_account_manager"><![CDATA[Redirect to manage account.]]></string>
+
+    <string name="_bx_groups_grid_column_title_name"><![CDATA[Name]]></string>
+    <string name="_bx_groups_grid_column_title_role_id"><![CDATA[Role]]></string>
+    <string name="_bx_groups_grid_column_title_period"><![CDATA[Period]]></string>
+    <string name="_bx_groups_grid_column_title_price"><![CDATA[Price]]></string>
+    <string name="_bx_groups_grid_action_title_add"><![CDATA[Add]]></string>
+    <string name="_bx_groups_grid_action_title_edit"><![CDATA[Edit]]></string>
+    <string name="_bx_groups_grid_action_title_delete"><![CDATA[Delete]]></string>
+    <string name="_bx_groups_grid_action_title_buy"><![CDATA[Buy]]></string>
+    <string name="_bx_groups_grid_action_title_buy_title"><![CDATA[One-time payment]]></string>
+    <string name="_bx_groups_grid_action_title_subscribe"><![CDATA[Subscribe]]></string>
+    <string name="_bx_groups_grid_action_title_subscribe_title"><![CDATA[Create a subscription with recurring billing]]></string>
+    <string name="_bx_groups_grid_action_title_choose"><![CDATA[Choose]]></string>
+    <string name="_bx_groups_grid_action_title_choose_title"><![CDATA[Switch to the level for free]]></string>
+    <string name="_bx_groups_popup_title_price_add"><![CDATA[Add Pricing Plan]]></string>
+    <string name="_bx_groups_popup_title_price_edit"><![CDATA[Edit Pricing Plan]]></string>
+
+    <string name="_bx_groups_chart_growth"><![CDATA[Groups: Growth]]></string>
+    <string name="_bx_groups_chart_growth_speed"><![CDATA[Groups: Growth Speed]]></string>
+
+    <string name="_bx_groups_search_extended"><![CDATA[Groups Search]]></string>
+    <string name="_bx_groups_search_extended_cmts"><![CDATA[Groups Comments Search]]></string>
+
+    <string name="_bx_groups_txt_all_entries_in"><![CDATA[<a href="{0}">All Groups in {1} ({2})</a>]]></string>
+    <string name="_bx_groups_txt_account_pending"><![CDATA[This group is pending approval, please wait until it is activated.]]></string>
+    <string name="_bx_groups_txt_account_suspended"><![CDATA[This group is suspended.]]></string>
+    <string name="_bx_groups_txt_N_fans"><![CDATA[{0} members]]></string>
+    <string name="_bx_groups_txt_role"><![CDATA[Role]]></string>
+    <string name="_bx_groups_txt_role_added"><![CDATA[Added]]></string>
+    <string name="_bx_groups_txt_role_expired"><![CDATA[Expires]]></string>
+    <string name="_bx_groups_txt_sample_single"><![CDATA[group]]></string>
+    <string name="_bx_groups_txt_sample_single_with_article"><![CDATA[a group]]></string>
+    <string name="_bx_groups_txt_sample_comment_single"><![CDATA[comment to group]]></string>
+    <string name="_bx_groups_txt_sample_vote_single"><![CDATA[vote to group]]></string>
+    <string name="_bx_groups_txt_sample_score_up_single"><![CDATA[score up vote to group]]></string>
+    <string name="_bx_groups_txt_sample_score_down_single"><![CDATA[score down vote to group]]></string>
+    <string name="_bx_groups_txt_set_role"><![CDATA[Set Role]]></string>
+    <string name="_bx_groups_txt_private_group"><![CDATA[Private group]]></string>
+    <string name="_bx_groups_txt_invite_popup_text"><![CDATA[You have been invited to a group. Click the button below to accept the invitation.]]></string>
+    <string name="_bx_groups_txt_invite_popup_title"><![CDATA[Invitation to a group]]></string>
+    <string name="_bx_groups_txt_invite_popup_button_accept"><![CDATA[Accept]]></string>
+    <string name="_bx_groups_txt_invite_popup_button_decline"><![CDATA[Decline]]></string>
+    <string name="_bx_groups_txt_invite_popup_error_invitation_absent"><![CDATA[Sorry, an error has occurred. You can not join this group. The invitation is expired or deleted.]]></string>
+    <string name="_bx_groups_txt_invite_popup_error_invitation_wrong_user"><![CDATA[Sorry, an error has occurred. You can not join this group. This invitation cannot be used by you.]]></string>
+    <string name="_bx_groups_txt_n_unit"><![CDATA[{0} ({1})]]></string>
+    <string name="_bx_groups_txt_cart_item_title"><![CDATA[{0}: {1} ({2} {3})]]></string>
+
+    <string name="_bx_groups_msg_performed"><![CDATA[The action was successfully performed.]]></string>
+    <string name="_bx_groups_err_price_duplicate"><![CDATA[Similar pricing plan is already exists.]]></string>
+    <string name="_bx_groups_err_cannot_perform"><![CDATA[An error appeared. Please report.]]></string>
+
+    <string name="_bx_groups_alert_action_fan_added"><![CDATA[member joined]]></string>
+    <string name="_bx_groups_txt_ntfs_fan_added"><![CDATA[Group <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_groups_alert_action_join_invitation_notif"><![CDATA[join invitation]]></string>
+    <string name="_bx_groups_alert_action_join_request"><![CDATA[join request]]></string>
+    <string name="_bx_groups_txt_ntfs_join_invitation"><![CDATA[<b class="bx-ntfs-content-profile">{owner_name}</b> group's representative invites <b class="bx-ntfs-content-entry">{subentry_sample}</b> to join group]]></string>
+    <string name="_bx_groups_txt_ntfs_join_request"><![CDATA[Group <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_groups_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> group timeline]]></string>
+
+    <string name="_bx_groups_pre_lists_cats"><![CDATA[Group categories]]></string>
+    <string name="_bx_groups_cat_General"><![CDATA[General]]></string>
+    <string name="_bx_groups_cat_Business"><![CDATA[Business]]></string>
+    <string name="_bx_groups_cat_Interests"><![CDATA[Interests]]></string>
+    <string name="_bx_groups_cat_Causes"><![CDATA[Causes]]></string>
+    <string name="_bx_groups_cat_Fun"><![CDATA[Fun]]></string>
+    <string name="_bx_groups_cat_Uncategorised"><![CDATA[Uncategorised]]></string>
+    
+    <string name="_bx_groups_pre_lists_roles"><![CDATA[Group roles]]></string>
+    <string name="_bx_groups_role_regular"><![CDATA[Regular]]></string>
+    <string name="_bx_groups_role_administrator"><![CDATA[Administrator]]></string>
+    <string name="_bx_groups_role_moderator"><![CDATA[Moderator]]></string>
+
+    <string name="_bx_groups_pre_lists_period_units"><![CDATA[Billing Interval]]></string>
+    <string name="_bx_groups_period_unit_day"><![CDATA[day]]></string>
+    <string name="_bx_groups_period_unit_week"><![CDATA[week]]></string>
+    <string name="_bx_groups_period_unit_month"><![CDATA[month]]></string>
+    <string name="_bx_groups_period_unit_year"><![CDATA[year]]></string>
+
+    <string name="_bx_groups_email_join_request"><![CDATA[Group join request]]></string>
+    <string name="_bx_groups_email_join_request_subject"><![CDATA[Request to join your group]]></string>
+    <string name="_bx_groups_email_join_request_body"><![CDATA[{email_header}
+<p>New request to join <a href="{EntryUrl}">{EntryTitle}</a> group from <a href="{NewMemberUrl}">{NewMemberDisplayName}</a></p>
+{email_footer}]]></string>
+
+    <string name="_bx_groups_email_join_reject"><![CDATA[Group join request was rejected]]></string>
+    <string name="_bx_groups_email_join_reject_subject"><![CDATA[Request to join a group was rejected]]></string>
+    <string name="_bx_groups_email_join_reject_body"><![CDATA[{email_header}
+<p>Your request to join <a href="{EntryUrl}">{EntryTitle}</a> group was rejected by group admin.</p>
+{email_footer}]]></string>
+
+    <string name="_bx_groups_email_join_confirm"><![CDATA[Group join request was confirmed]]></string>
+    <string name="_bx_groups_email_join_confirm_subject"><![CDATA[Your request to join a group was confirmed]]></string>
+    <string name="_bx_groups_email_join_confirm_body"><![CDATA[{email_header}
+<p>Your request to join <a href="{EntryUrl}">{EntryTitle}</a> group was confirmed by the group admin.</p>
+{email_footer}]]></string>
+
+    <string name="_bx_groups_email_fan_remove"><![CDATA[Profile was removed from group fans]]></string>
+    <string name="_bx_groups_email_fan_remove_subject"><![CDATA[Your profile was removed from the group]]></string>
+    <string name="_bx_groups_email_fan_remove_body"><![CDATA[{email_header}
+<p>Your profile was removed from <a href="{EntryUrl}">{EntryTitle}</a> group by the group admin.</p>
+{email_footer}]]></string>
+
+    <string name="_bx_groups_email_fan_become_admin"><![CDATA[Group admin status was granted]]></string>
+    <string name="_bx_groups_email_fan_become_admin_subject"><![CDATA[You are a group admin now]]></string>
+    <string name="_bx_groups_email_fan_become_admin_body"><![CDATA[{email_header}
+<p>You are an admin of <a href="{EntryUrl}">{EntryTitle}</a> group now.</p>
+{email_footer}]]></string>
+
+    <string name="_bx_groups_email_admin_become_fan"><![CDATA[Group admin status was revoked]]></string>
+    <string name="_bx_groups_email_admin_become_fan_subject"><![CDATA[Your group admin status was revoked]]></string>
+    <string name="_bx_groups_email_admin_become_fan_body"><![CDATA[{email_header}
+<p>Your admin status was revoked from <a href="{EntryUrl}">{EntryTitle}</a> group.</p>
+{email_footer}]]></string>
+
+    <string name="_bx_groups_email_set_role"><![CDATA[Group member status was changed]]></string>
+    <string name="_bx_groups_email_set_role_subject"><![CDATA[Your group status was changed]]></string>
+    <string name="_bx_groups_email_set_role_body"><![CDATA[{email_header}
+<p>Your status in <a href="{EntryUrl}">{EntryTitle}</a> group was changed to <b>{Role}</b>.</p>
+{email_footer}]]></string>
+
+    <string name="_bx_groups_email_invitation"><![CDATA[Invitation to group]]></string>
+    <string name="_bx_groups_email_invitation_subject"><![CDATA[Invitation to "{EntryTitle}" group]]></string>
+    <string name="_bx_groups_email_invitation_body"><![CDATA[{email_header}
+<p><a href="{InviterUrl}">{InviterDisplayName}</a> invited you to <a href="{EntryUrl}">{EntryTitle} group</a>.</p>
+{email_footer}]]></string>
+</resources>

+ 60 - 0
modules/boonex/groups/updates/12.0.2_12.0.3/source/install/sql/disable.sql

@@ -0,0 +1,60 @@
+
+-- SETTINGS
+SET @iTypeId = (SELECT `ID` FROM `sys_options_types` WHERE `name` = 'bx_groups' 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_groups';
+DELETE FROM `sys_pages_blocks` WHERE `module` = 'bx_groups' OR `object` IN('bx_groups_create_profile', 'bx_groups_delete_profile', 'bx_groups_context', 'bx_groups_join_profile', 'bx_groups_edit_profile', 'bx_groups_edit_profile_cover', 'bx_groups_invite', 'bx_groups_view_profile', 'bx_groups_view_profile_closed', 'bx_groups_profile_info', 'bx_groups_profile_pricing', 'bx_groups_profile_comments', 'bx_groups_home', 'bx_groups_fans', 'bx_groups_joined', 'bx_groups_favorites', 'bx_groups_top', 'bx_groups_search', 'bx_groups_manage', 'bx_groups_administration');
+
+-- MENU
+DELETE FROM `sys_objects_menu` WHERE `module` = 'bx_groups';
+DELETE FROM `sys_menu_sets` WHERE `module` = 'bx_groups';
+DELETE FROM `sys_menu_items` WHERE `module` = 'bx_groups' OR `set_name` IN('bx_groups_view_submenu', 'bx_groups_submenu', 'bx_groups_view_actions', 'bx_groups_view_actions_more', 'bx_groups_view_actions_all', 'bx_groups_my', 'bx_groups_snippet_meta', 'bx_groups_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_groups';
+DELETE FROM `sys_acl_actions` WHERE `Module` = 'bx_groups';
+
+-- METATAGS
+DELETE FROM `sys_objects_metatags` WHERE `object` = 'bx_groups';
+
+-- CATEGORY
+DELETE FROM `sys_objects_category` WHERE `object` = 'bx_groups_cats';
+
+-- SEARCH
+DELETE FROM `sys_objects_search` WHERE `ObjectName` = 'bx_groups';
+
+-- CONNECTIONS
+DELETE FROM `sys_objects_connection` WHERE `object` = 'bx_groups_fans';
+
+-- STATS
+DELETE FROM `sys_statistics` WHERE `name` LIKE 'bx_groups%';
+
+-- CHARTS
+DELETE FROM `sys_objects_chart` WHERE `object` LIKE 'bx_groups%';
+
+-- GRIDS
+DELETE FROM `sys_objects_grid` WHERE `object` IN ('bx_groups_administration', 'bx_groups_moderation', 'bx_groups_common', 'bx_groups_fans', 'bx_groups_invites', 'bx_groups_prices_manage', 'bx_groups_prices_view');
+DELETE FROM `sys_grid_fields` WHERE `object` IN ('bx_groups_administration', 'bx_groups_moderation', 'bx_groups_common', 'bx_groups_fans', 'bx_groups_invites', 'bx_groups_prices_manage', 'bx_groups_prices_view');
+DELETE FROM `sys_grid_actions` WHERE `object` IN ('bx_groups_administration', 'bx_groups_moderation', 'bx_groups_common', 'bx_groups_fans', 'bx_groups_invites', 'bx_groups_prices_manage', 'bx_groups_prices_view');
+
+-- ALERTS
+SET @iHandler := (SELECT `id` FROM `sys_alerts_handlers` WHERE `name` = 'bx_groups' 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_groups_allow_view_to', 'bx_groups_allow_view_notification_to', 'bx_groups_allow_post_to', 'bx_groups_allow_view_favorite_list');
+
+-- EMAIL TEMPLATES
+DELETE FROM `sys_email_templates` WHERE `Module` = 'bx_groups';
+
+-- UPLOADERS
+DELETE FROM `sys_objects_uploader` WHERE `object` IN ('bx_groups_cover_crop', 'bx_groups_picture_crop');
+
+-- CRON
+DELETE FROM `sys_cron_jobs` WHERE `name` IN ('bx_groups_pruning');

+ 660 - 0
modules/boonex/groups/updates/12.0.2_12.0.3/source/install/sql/enable.sql

@@ -0,0 +1,660 @@
+
+-- 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_groups', '_bx_groups', 'bx_groups@modules/boonex/groups/|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_groups', '_bx_groups', 1);
+SET @iCategId = LAST_INSERT_ID();
+
+INSERT INTO `sys_options` (`name`, `value`, `category_id`, `caption`, `type`, `extra`, `check`, `check_error`, `order`) VALUES
+('bx_groups_num_connections_quick', '6', @iCategId, '_bx_groups_option_num_connections_quick', 'digit', '', '', '', 10),
+('bx_groups_per_page_browse', '24', @iCategId, '_bx_groups_option_per_page_browse', 'digit', '', '', '', 11),
+('bx_groups_num_rss', '10', @iCategId, '_bx_groups_option_num_rss', 'digit', '', '', '', 12),
+('bx_groups_per_page_browse_showcase', '32', @iCategId, '_sys_option_per_page_browse_showcase', 'digit', '', '', '', 15),
+('bx_groups_per_page_browse_recommended', '10', @iCategId, '_sys_option_per_page_browse_recommended', 'digit', '', '', '', 16),
+('bx_groups_per_page_for_favorites_lists', '5', @iCategId, '_bx_groups_option_per_page_for_favorites_lists', 'digit', '', '', '', 17),
+('bx_groups_searchable_fields', 'group_name,group_desc', @iCategId, '_bx_groups_option_searchable_fields', 'list', 'a:2:{s:6:"module";s:9:"bx_groups";s:6:"method";s:21:"get_searchable_fields";}', '', '', 30),
+('bx_groups_members_mode', '', @iCategId, '_bx_groups_option_members_mode', 'select', 'a:2:{s:6:"module";s:9:"bx_groups";s:6:"method";s:24:"get_options_members_mode";}', '', '', 40),
+('bx_groups_internal_notifications', '', @iCategId, '_bx_groups_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_groups_create_profile', 'create-group-profile', '_bx_groups_page_title_sys_create_profile', '_bx_groups_page_title_create_profile', 'bx_groups', 5, 2147483647, 1, 'page.php?i=create-group-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_groups_create_profile', 1, 'bx_groups', '_bx_groups_page_block_title_create_profile', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_groups\";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_groups_view_profile', 'view-group-profile', '_bx_groups_page_title_sys_view_profile', '_bx_groups_page_title_view_profile', 'bx_groups', 10, 2147483647, 1, 'page.php?i=view-group-profile', '', '', '', 0, 1, 0, 'BxGroupsPageEntry', 'modules/boonex/groups/classes/BxGroupsPageEntry.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_groups_view_profile', 1, 'bx_groups', '', '_bx_groups_page_block_title_entry_social_sharing', 13, 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_groups\";s:6:\"method\";s:21:\"entity_social_sharing\";}', 0, 0, 0, 0),
+('bx_groups_view_profile', 1, 'bx_groups', '', '_bx_groups_page_block_title_entry_all_actions', 13, 2147483647, 'service', 'a:2:{s:6:"module";s:9:"bx_groups";s:6:"method";s:18:"entity_all_actions";}', 0, 0, 0, 0),
+('bx_groups_view_profile', 2, 'bx_groups', '', '_bx_groups_page_block_title_profile_info', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_groups\";s:6:\"method\";s:11:\"entity_info\";}', 0, 0, 1, 0),
+('bx_groups_view_profile', 3, 'bx_groups', '', '_bx_groups_page_block_title_profile_location', 13, 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_groups\";s:6:\"method\";s:15:\"entity_location\";}', 0, 0, 0, 0),
+('bx_groups_view_profile', 3, 'bx_groups', '', '_bx_groups_page_block_title_entry_context', 13, 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_groups\";s:6:\"method\";s:14:\"entity_context\";}', 0, 0, 1, 1),
+('bx_groups_view_profile', 3, 'bx_groups', '', '_bx_groups_page_block_title_fans', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_groups\";s:6:\"method\";s:4:\"fans\";}', 0, 0, 1, 2),
+('bx_groups_view_profile', 3, 'bx_groups', '', '_bx_groups_page_block_title_admins', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_groups\";s:6:\"method\";s:6:\"admins\";}', 0, 0, 1, 3),
+('bx_groups_view_profile', 3, 'bx_groups', '', '_bx_groups_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:9:\"bx_groups\";i:1;s:12:\"{content_id}\";}s:5:\"class\";s:20:\"TemplServiceMetatags\";}', 0, 0, 1, 4),
+('bx_groups_view_profile', 4, 'bx_groups', '', '_bx_groups_page_block_title_profile_description', 13, 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_groups\";s:6:\"method\";s:17:\"entity_text_block\";}', 0, 0, 1, 0),
+('bx_groups_view_profile', 4, 'bx_groups', '', '_bx_groups_page_block_title_profile_comments', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_groups\";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_groups_view_profile_closed', 'view-group-profile-closed', '_bx_groups_page_title_sys_view_profile_closed', '_bx_groups_page_title_view_profile', 'bx_groups', 10, 2147483647, 1, 'page.php?i=view-group-profile', '', '', '', 0, 1, 0, 'BxGroupsPageEntry', 'modules/boonex/groups/classes/BxGroupsPageEntry.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_groups_view_profile_closed', 2, 'bx_groups', '', '_bx_groups_page_block_title_profile_info', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_groups\";s:6:\"method\";s:11:\"entity_info\";}', 0, 0, 1, 0),
+('bx_groups_view_profile_closed', 3, 'bx_groups', '', '_bx_groups_page_block_title_fans', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_groups\";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_groups_edit_profile', 'edit-group-profile', '_bx_groups_page_title_sys_edit_profile', '_bx_groups_page_title_edit_profile', 'bx_groups', 5, 2147483647, 1, 'page.php?i=edit-group-profile', '', '', '', 0, 1, 0, 'BxGroupsPageEntry', 'modules/boonex/groups/classes/BxGroupsPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_groups_edit_profile', 1, 'bx_groups', '_bx_groups_page_block_title_edit_profile', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_groups\";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_groups_edit_profile_cover', 'edit-group-cover', '_bx_groups_page_title_sys_edit_profile_cover', '_bx_groups_page_title_edit_profile_cover', 'bx_groups', 5, 2147483647, 1, 'page.php?i=edit-group-cover', '', '', '', 0, 1, 0, 'BxGroupsPageEntry', 'modules/boonex/groups/classes/BxGroupsPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_groups_edit_profile_cover', 1, 'bx_groups', '_bx_groups_page_block_title_edit_profile_cover', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_groups\";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_groups_invite', 'invite-to-group', '_bx_groups_page_title_sys_invite_to_group', '_bx_groups_page_title_invite_to_group', 'bx_groups', 5, 2147483647, 1, 'page.php?i=invite-to-group', '', '', '', 0, 1, 0, 'BxGroupsPageEntry', 'modules/boonex/groups/classes/BxGroupsPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_groups_invite', 1, 'bx_groups', '_bx_groups_page_block_title_invite_to_group', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_groups\";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_groups_delete_profile', 'delete-group-profile', '_bx_groups_page_title_sys_delete_profile', '_bx_groups_page_title_delete_profile', 'bx_groups', 5, 2147483647, 1, 'page.php?i=delete-group-profile', '', '', '', 0, 1, 0, 'BxGroupsPageEntry', 'modules/boonex/groups/classes/BxGroupsPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_groups_delete_profile', 1, 'bx_groups', '_bx_groups_page_block_title_delete_profile', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_groups\";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_groups_join_profile', 'join-group-profile', '_bx_groups_page_title_sys_join_profile', '_bx_groups_page_title_join_profile', 'bx_groups', 5, 2147483647, 1, 'page.php?i=join-group-profile', '', '', '', 0, 1, 0, 'BxGroupsPageEntry', 'modules/boonex/groups/classes/BxGroupsPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_groups_join_profile', 1, 'bx_groups', '_bx_groups_page_block_title_join_profile', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:9:"bx_groups";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_groups_profile_info', 'group-profile-info', '_bx_groups_page_title_sys_profile_info', '_bx_groups_page_title_profile_info', 'bx_groups', 5, 2147483647, 1, 'page.php?i=group-profile-info', '', '', '', 0, 1, 0, 'BxGroupsPageEntry', 'modules/boonex/groups/classes/BxGroupsPageEntry.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_groups_profile_info', 1, 'bx_groups', '_bx_groups_page_block_title_system_profile_info', '_bx_groups_page_block_title_profile_info_link', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_groups\";s:6:\"method\";s:16:\"entity_info_full\";}', 0, 0, 1, 1),
+('bx_groups_profile_info', 1, 'bx_groups', '', '_bx_groups_page_block_title_profile_description', 13, 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_groups\";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_groups_profile_pricing', 'edit-group-pricing', '_bx_groups_page_title_sys_profile_pricing', '_bx_groups_page_title_profile_pricing', 'bx_groups', 5, 2147483647, 1, 'page.php?i=edit-group-pricing', '', '', '', 0, 1, 0, 'BxGroupsPageEntry', 'modules/boonex/groups/classes/BxGroupsPageEntry.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_groups_profile_pricing', 1, 'bx_groups', '_bx_groups_page_block_title_system_profile_pricing', '_bx_groups_page_block_title_profile_pricing_link', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:9:"bx_groups";s:6:"method";s:14:"entity_pricing";s:6:"params";a:1:{i:0;s:12:"{profile_id}";}}', 0, 0, 1, 1);
+
+-- PAGE: group 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_groups_fans', 'group-fans', '_bx_groups_page_title_sys_group_fans', '_bx_groups_page_title_group_fans', 'bx_groups', 5, 2147483647, 1, 'page.php?i=group-fans', '', '', '', 0, 1, 0, 'BxGroupsPageEntry', 'modules/boonex/groups/classes/BxGroupsPageEntry.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_groups_fans', 1, 'bx_groups', '_bx_groups_page_block_title_system_fans', '_bx_groups_page_block_title_fans_link', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:9:"bx_groups";s:6:"method";s:10:"fans_table";}', 0, 0, 1, 1),
+('bx_groups_fans', 1, 'bx_groups', '_bx_groups_page_block_title_system_invites', '_bx_groups_page_block_title_fans_invites', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:9:"bx_groups";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_groups_profile_comments', '_bx_groups_page_title_sys_profile_comments', '_bx_groups_page_title_profile_comments', 'bx_groups', 5, 2147483647, 1, 'group-profile-comments', '', '', '', '', 0, 1, 0, 'BxGroupsPageEntry', 'modules/boonex/groups/classes/BxGroupsPageEntry.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_groups_profile_comments', 1, 'bx_groups', '_bx_groups_page_block_title_profile_comments', '_bx_groups_page_block_title_profile_comments_link', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_groups\";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_groups_home', '_bx_groups_page_title_sys_recent', '_bx_groups_page_title_recent', 'bx_groups', 5, 2147483647, 1, 'groups-home', 'page.php?i=groups-home', '', '', '', 0, 1, 0, 'BxGroupsPageBrowse', 'modules/boonex/groups/classes/BxGroupsPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES
+('bx_groups_home', 1, 'bx_groups', '_bx_groups_page_block_title_featured_profiles', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:9:"bx_groups";s:6:"method";s:15:"browse_featured";s:6:"params";a:1:{i:0;s:7:"gallery";}}', 0, 1, 0),
+('bx_groups_home', 1, 'bx_groups', '_bx_groups_page_block_title_latest_profiles', 11, 2147483647, 'service', 'a:3:{s:6:\"module\";s:9:\"bx_groups\";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_groups_top', '_bx_groups_page_title_sys_top', '_bx_groups_page_title_top', 'bx_groups', 5, 2147483647, 1, 'groups-top', 'page.php?i=groups-top', '', '', '', 0, 1, 0, 'BxGroupsPageBrowse', 'modules/boonex/groups/classes/BxGroupsPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_groups_top', 1, 'bx_groups', '_bx_groups_page_block_title_top_profiles', 11, 2147483647, 'service', 'a:3:{s:6:\"module\";s:9:\"bx_groups\";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_groups_search', '_bx_groups_page_title_sys_entries_search', '_bx_groups_page_title_entries_search', 'bx_groups', 5, 2147483647, 1, 'groups-search', 'page.php?i=groups-search', '', '', '', 0, 1, 0, 'BxGroupsPageBrowse', 'modules/boonex/groups/classes/BxGroupsPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_groups_search', 1, 'bx_groups', '_bx_groups_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:9:"bx_groups";}}s:5:"class";s:27:"TemplSearchExtendedServices";}', 0, 1, 1, 1),
+('bx_groups_search', 1, 'bx_groups', '_bx_groups_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:9:"bx_groups";s:10:"show_empty";b:1;}}s:5:"class";s:27:"TemplSearchExtendedServices";}', 0, 1, 1, 2),
+('bx_groups_search', 1, 'bx_groups', '_bx_groups_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:14:"bx_groups_cmts";}}s:5:"class";s:27:"TemplSearchExtendedServices";}', 0, 1, 0, 3),
+('bx_groups_search', 1, 'bx_groups', '_bx_groups_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:14:"bx_groups_cmts";s:10:"show_empty";b:1;}}s:5:"class";s:27:"TemplSearchExtendedServices";}', 0, 1, 0, 4);
+
+-- PAGE: entries in context
+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_groups_context', 'groups-context', '_bx_groups_page_title_sys_entries_in_context', '_bx_groups_page_title_entries_in_context', 'bx_groups', 5, 2147483647, 1, '', '', '', '', 0, 1, 0, 'BxGroupsPageEntriesInContext', 'modules/boonex/groups/classes/BxGroupsPageEntriesInContext.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_groups_context', 1, 'bx_groups', '_bx_groups_page_block_title_sys_entries_in_context', '_bx_groups_page_block_title_entries_in_context_link', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:9:"bx_groups";s:6:"method";s:14:"browse_context";}', 0, 0, 1, 1);
+
+-- 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_groups', '_bx_groups_page_title_sys_joined', '_bx_groups_page_title_joined', 'bx_groups', 5, 2147483647, 1, 'groups-joined', 'page.php?i=groups-joined', '', '', '', 0, 1, 0, 'BxGroupsPageBrowse', 'modules/boonex/groups/classes/BxGroupsPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_joined_groups', 1, 'bx_groups', '_bx_groups_page_block_title_joined_entries', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:9:"bx_groups";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_groups_manage', '_bx_groups_page_title_sys_manage', '_bx_groups_page_title_manage', 'bx_groups', 5, 2147483647, 1, 'groups-manage', 'page.php?i=groups-manage', '', '', '', 0, 1, 0, 'BxGroupsPageBrowse', 'modules/boonex/groups/classes/BxGroupsPageBrowse.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_groups_manage', 1, 'bx_groups', '_bx_groups_page_block_title_system_manage', '_bx_groups_page_block_title_manage', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_groups\";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_groups_administration', '_bx_groups_page_title_sys_manage_administration', '_bx_groups_page_title_manage', 'bx_groups', 5, 192, 1, 'groups-administration', 'page.php?i=groups-administration', '', '', '', 0, 1, 0, 'BxGroupsPageBrowse', 'modules/boonex/groups/classes/BxGroupsPageBrowse.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_groups_administration', 1, 'bx_groups', '_bx_groups_page_block_title_system_manage_administration', '_bx_groups_page_block_title_manage', 11, 192, 'service', 'a:3:{s:6:\"module\";s:9:\"bx_groups\";s:6:\"method\";s:12:\"manage_tools\";s:6:\"params\";a:1:{i:0;s:14:\"administration\";}}', 0, 1, 0);
+
+-- PAGE: user's groups
+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_groups_joined', 'joined-groups', '_bx_groups_page_title_sys_joined_entries', '_bx_groups_page_title_joined_entries', 'bx_groups', 5, 2147483647, 1, '', '', '', '', 0, 1, 0, 'BxGroupsPageJoinedEntries', 'modules/boonex/groups/classes/BxGroupsPageJoinedEntries.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_groups_joined', 1, 'bx_groups', '_bx_groups_page_block_title_sys_entries_actions', '_bx_groups_page_block_title_entries_actions', 13, 2147483647, 'service', 'a:2:{s:6:"module";s:9:"bx_groups";s:6:"method";s:18:"my_entries_actions";}', 0, 0, 1, 1),
+('bx_groups_joined', 1, 'bx_groups', '_bx_groups_page_block_title_sys_entries_of_author', '_bx_groups_page_block_title_sys_entries_of_author', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:9:"bx_groups";s:6:"method";s:21:"browse_favorite_lists";s:6:"params";a:2:{s:10:"profile_id";s:12:"{profile_id}";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, 2),
+('bx_groups_joined', 1, 'bx_groups', '_bx_groups_page_block_title_sys_favorites_of_author', '_bx_groups_page_block_title_favorites_of_author', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:9:"bx_groups";s:6:"method";s:15:"browse_favorite";s:6:"params";a:1:{i:0;s:12:"{profile_id}";}}', 0, 1, 1, 3),
+('bx_groups_joined', 1, 'bx_groups', '_bx_groups_page_block_title_sys_joined_entries', '_bx_groups_page_block_title_joined_entries', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:9:"bx_groups";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_groups_favorites', '_bx_groups_page_title_sys_entries_favorites', '_bx_groups_page_title_entries_favorites', 'bx_groups', 12, 2147483647, 1, 'groups-favorites', 'page.php?i=groups-favorites', '', '', '', 0, 1, 0, 'BxGroupsPageListEntry', 'modules/boonex/groups/classes/BxGroupsPageListEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_groups_favorites', 2, 'bx_groups', '_bx_groups_page_block_title_favorites_entries', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:9:"bx_groups";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_groups_favorites', 3, 'bx_groups', '_bx_groups_page_block_title_favorites_entries_info', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:9:"bx_groups";s:6:"method";s:19:"favorites_list_info";}', 0, 0, 0),
+('bx_groups_favorites', 3, 'bx_groups', '_bx_groups_page_block_title_favorites_entries_actions', 13, 2147483647, 'service', 'a:2:{s:6:"module";s:9:"bx_groups";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_groups', '', '_bx_groups_page_block_title_latest_profiles', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:9:"bx_groups";s:6:"method";s:22:"browse_recent_profiles";}', 1, 0, 0, IFNULL(@iBlockOrder, 0) + 1),
+('sys_home', 1, 'bx_groups', '_bx_groups_page_block_title_sys_recommended_entries_view_showcase', '_bx_groups_page_block_title_recommended_entries_view_showcase', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:9:"bx_groups";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_groups', '', '_bx_groups_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:14:"bx_groups_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_groups', '_bx_groups_page_block_title_sys_featured_entries_view_showcase', '_bx_groups_page_block_title_featured_entries_view_showcase', 11, 2147483647, 'service', 'a:3:{s:6:\"module\";s:9:\"bx_groups\";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_groups', '_bx_groups_page_block_title_sys_recommended_entries_view_showcase', '_bx_groups_page_block_title_recommended_entries_view_showcase', 11, 2147483647, 'service', 'a:3:{s:6:\"module\";s:9:\"bx_groups\";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_groups', '_bx_groups_page_block_title_sys_labels_tree', '_bx_groups_page_block_title_labels_tree', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:9:"bx_groups";s:6:"method";s:15:"get_lables_tree";}', 0, 1, 1, IFNULL(@iBlockOrder, 0) + 4),
+('', 0, 'bx_groups', '_bx_groups_page_block_title_sys_groups_browse_by_label', '_bx_groups_page_block_title_groups_browse_by_label', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:9:"bx_groups";s:6:"method";s:15:"browse_by_label";}', 0, 1, 1, IFNULL(@iBlockOrder, 0) + 5),
+('', 0, 'bx_groups', '_bx_groups_page_block_title_sys_labels_breadcrumbs', '_bx_groups_page_block_title_labels_breadcrumbs', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:9:"bx_groups";s:6:"method";s:22:"get_lables_breadcrumbs";}', 0, 1, 1, IFNULL(@iBlockOrder, 0) + 6);
+
+
+ -- PAGES: add page block to profiles modules (trigger* page objects are processed separately upon modules enable/disable)
+INSERT INTO `sys_pages_blocks` (`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`, `active`) VALUES
+('trigger_page_group_view_entry', 4, 'bx_groups', '_bx_groups_page_block_title_entries_in_context', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:9:"bx_groups";s:6:"method";s:14:"browse_context";s:6:"params";a:1:{s:10:"context_id";s:12:"{profile_id}";}}', 0, 0, 1, 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_groups', 'groups-home', '_bx_groups_menu_item_title_system_entries_home', '_bx_groups_menu_item_title_entries_home', 'page.php?i=groups-home', '', '', 'users col-red2', 'bx_groups_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_groups', 'groups-home', '_bx_groups_menu_item_title_system_entries_home', '_bx_groups_menu_item_title_entries_home', 'page.php?i=groups-home', '', '', 'users col-red2', 'bx_groups_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_groups', 'create-group-profile', '_bx_groups_menu_item_title_system_create_profile', '_bx_groups_menu_item_title_create_profile', 'page.php?i=create-group-profile', '', '', 'users col-red2', '', 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_groups_view_actions', '_bx_groups_menu_title_view_profile_actions', 'bx_groups_view_actions', 'bx_groups', 9, 0, 1, 'BxGroupsMenuViewActions', 'modules/boonex/groups/classes/BxGroupsMenuViewActions.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_groups_view_actions', 'bx_groups', '_bx_groups_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_groups_view_actions', 'bx_groups', 'join-group-profile', '_bx_groups_menu_item_title_system_pay_and_join', '_bx_groups_menu_item_title_pay_and_join', 'page.php?i=join-group-profile&profile_id={profile_id}', '', '', 'sign-in-alt', '', 0, 2147483647, 'a:3:{s:6:"module";s:9:"bx_groups";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_groups_view_actions', 'bx_groups', 'profile-fan-add', '_bx_groups_menu_item_title_system_become_fan', '{title_add_fan}', 'javascript:void(0)', 'bx_conn_action(this, \'bx_groups_fans\', \'add\', \'{profile_id}\')', '', 'sign-in-alt', '', 0, 2147483647, 'a:3:{s:6:"module";s:9:"bx_groups";s:6:"method";s:22:"is_free_join_avaliable";s:6:"params";a:1:{i:0;s:12:"{profile_id}";}}', 1, 0, 0, 10),
+('bx_groups_view_actions', 'bx_groups', 'profile-subscribe-add', '_bx_groups_menu_item_title_system_subscribe', '_bx_groups_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_groups_view_actions', 'bx_groups', '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_groups'', content_id: {content_id}});', '', 'check-circle', '', 0, 192, 'a:2:{s:6:"module";s:9:"bx_groups";s:6:"method";s:19:"is_badges_avaliable";}', 1, 0, 1, 30),
+('bx_groups_view_actions', 'bx_groups', 'profile-actions-more', '_bx_groups_menu_item_title_system_more_actions', '_bx_groups_menu_item_title_more_actions', 'javascript:void(0)', 'bx_menu_popup(''bx_groups_view_actions_more'', this, {}, {profile_id:{profile_id}});', '', 'cog', 'bx_groups_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_groups_view_actions_more', '_bx_groups_menu_title_view_profile_actions_more', 'bx_groups_view_actions_more', 'bx_groups', 6, 0, 1, 'BxGroupsMenuViewActions', 'modules/boonex/groups/classes/BxGroupsMenuViewActions.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_groups_view_actions_more', 'bx_groups', '_bx_groups_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_groups_view_actions_more', 'bx_groups', 'profile-fan-remove', '_bx_groups_menu_item_title_system_leave_group', '{title_remove_fan}', 'javascript:void(0)', 'bx_conn_action(this, \'bx_groups_fans\', \'remove\', \'{profile_id}\')', '', 'sign-out-alt', '', 2147483647, '', 1, 0, 10),
+('bx_groups_view_actions_more', 'bx_groups', 'profile-subscribe-remove', '_bx_groups_menu_item_title_system_unsubscribe', '_bx_groups_menu_item_title_unsubscribe', 'javascript:void(0)', 'bx_conn_action(this, \'sys_profiles_subscriptions\', \'remove\', \'{profile_id}\')', '', 'check', '', 2147483647, '', 1, 0, 20),
+('bx_groups_view_actions_more', 'bx_groups', 'edit-group-cover', '_bx_groups_menu_item_title_system_edit_cover', '_bx_groups_menu_item_title_edit_cover', 'page.php?i=edit-group-cover&id={content_id}', '', '', 'edit', '', 2147483647, '', 1, 0, 30),
+('bx_groups_view_actions_more', 'bx_groups', 'edit-group-profile', '_bx_groups_menu_item_title_system_edit_profile', '_bx_groups_menu_item_title_edit_profile', 'page.php?i=edit-group-profile&id={content_id}', '', '', 'pencil-alt', '', 2147483647, '', 1, 0, 40),
+('bx_groups_view_actions_more', 'bx_groups', 'edit-group-pricing', '_bx_groups_menu_item_title_system_edit_pricing', '_bx_groups_menu_item_title_edit_pricing', 'page.php?i=edit-group-pricing&profile_id={profile_id}', '', '', 'money-check-alt', '', 2147483647, 'a:3:{s:6:"module";s:9:"bx_groups";s:6:"method";s:20:"is_pricing_avaliable";s:6:"params";a:1:{i:0;s:12:"{profile_id}";}}', 1, 0, 41),
+('bx_groups_view_actions_more', 'bx_groups', 'invite-to-group', '_bx_groups_menu_item_title_system_invite', '_bx_groups_menu_item_title_invite', 'page.php?i=invite-to-group&id={content_id}', '', '', 'user-friends', '', 2147483647, '', 1, 0, 42),
+('bx_groups_view_actions_more', 'bx_groups', 'delete-group-profile', '_bx_groups_menu_item_title_system_delete_profile', '_bx_groups_menu_item_title_delete_profile', 'page.php?i=delete-group-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_groups_view_actions_all', '_sys_menu_title_view_actions', 'bx_groups_view_actions_all', 'bx_groups', 15, 0, 1, 'BxGroupsMenuViewActionsAll', 'modules/boonex/groups/classes/BxGroupsMenuViewActionsAll.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_groups_view_actions_all', 'bx_groups', '_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_groups_view_actions_all', 'bx_groups', 'join-group-profile', '_bx_groups_menu_item_title_system_pay_and_join', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 5),
+('bx_groups_view_actions_all', 'bx_groups', 'profile-fan-add', '_bx_groups_menu_item_title_system_become_fan', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 10),
+('bx_groups_view_actions_all', 'bx_groups', 'profile-fan-remove', '_bx_groups_menu_item_title_system_leave_group', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 20),
+('bx_groups_view_actions_all', 'bx_groups', 'profile-subscribe-add', '_bx_groups_menu_item_title_system_subscribe', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 30),
+('bx_groups_view_actions_all', 'bx_groups', 'profile-subscribe-remove', '_bx_groups_menu_item_title_system_unsubscribe', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 40),
+('bx_groups_view_actions_all', 'bx_groups', 'profile-set-badges', '_sys_menu_item_title_system_set_badges', '', '', '', '', '', '', '', 0, 192, 'a:2:{s:6:"module";s:9:"bx_groups";s:6:"method";s:19:"is_badges_avaliable";}', 1, 0, 50),
+('bx_groups_view_actions_all', 'bx_groups', 'comment', '_sys_menu_item_title_system_va_comment', '', '', '', '', '', '', '', 0, 2147483647, '', 0, 0, 200),
+('bx_groups_view_actions_all', 'bx_groups', 'view', '_sys_menu_item_title_system_va_view', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 210),
+('bx_groups_view_actions_all', 'bx_groups', 'vote', '_sys_menu_item_title_system_va_vote', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 220),
+('bx_groups_view_actions_all', 'bx_groups', 'score', '_sys_menu_item_title_system_va_score', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 230),
+('bx_groups_view_actions_all', 'bx_groups', 'favorite', '_sys_menu_item_title_system_va_favorite', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 240),
+('bx_groups_view_actions_all', 'bx_groups', 'feature', '_sys_menu_item_title_system_va_feature', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 250),
+('bx_groups_view_actions_all', 'bx_groups', 'repost', '_sys_menu_item_title_system_va_repost', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 260),
+('bx_groups_view_actions_all', 'bx_groups', 'report', '_sys_menu_item_title_system_va_report', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 270),
+('bx_groups_view_actions_all', 'bx_groups', 'notes', '_sys_menu_item_title_system_va_notes', '_sys_menu_item_title_va_notes', 'javascript:void(0)', 'javascript:bx_get_notes(this,  ''{module_uri}'', {content_id});', '', 'exclamation-triangle', '', '', 0, 2147483647, '', 1, 0, 280),
+('bx_groups_view_actions_all', 'bx_groups', 'social-sharing-facebook', '_sys_menu_item_title_system_social_sharing_facebook', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 300),
+('bx_groups_view_actions_all', 'bx_groups', 'social-sharing-twitter', '_sys_menu_item_title_system_social_sharing_twitter', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 320),
+('bx_groups_view_actions_all', 'bx_groups', 'social-sharing-pinterest', '_sys_menu_item_title_system_social_sharing_pinterest', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 330),
+('bx_groups_view_actions_all', 'bx_groups', 'edit-group-cover', '_bx_groups_menu_item_title_system_edit_cover', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 400),
+('bx_groups_view_actions_all', 'bx_groups', 'edit-group-profile', '_bx_groups_menu_item_title_system_edit_profile', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 410),
+('bx_groups_view_actions_all', 'bx_groups', 'edit-group-pricing', '_bx_groups_menu_item_title_system_edit_pricing', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 415),
+('bx_groups_view_actions_all', 'bx_groups', 'invite-to-group', '_bx_groups_menu_item_title_system_invite', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 420),
+('bx_groups_view_actions_all', 'bx_groups', 'delete-group-profile', '_bx_groups_menu_item_title_system_delete_profile', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 430),
+('bx_groups_view_actions_all', 'bx_groups', '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_groups_my', '_bx_groups_menu_title_entries_my', 'bx_groups_my', 'bx_groups', 9, 0, 1, 'BxGroupsMenu', 'modules/boonex/groups/classes/BxGroupsMenu.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_groups_my', 'bx_groups', '_bx_groups_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_groups_my', 'bx_groups', 'create-group-profile', '_bx_groups_menu_item_title_system_create_profile', '_bx_groups_menu_item_title_create_profile', 'page.php?i=create-group-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_groups_submenu', '_bx_groups_menu_title_submenu', 'bx_groups_submenu', 'bx_groups', 8, 0, 1, '', '');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_groups_submenu', 'bx_groups', '_bx_groups_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_groups_submenu', 'bx_groups', 'groups-home', '_bx_groups_menu_item_title_system_entries_recent', '_bx_groups_menu_item_title_entries_recent', 'page.php?i=groups-home', '', '', '', '', 2147483647, 1, 1, 1),
+('bx_groups_submenu', 'bx_groups', 'groups-top', '_bx_groups_menu_item_title_system_entries_top', '_bx_groups_menu_item_title_entries_top', 'page.php?i=groups-top', '', '', '', '', 2147483647, 1, 1, 2),
+('bx_groups_submenu', 'bx_groups', 'groups-search', '_bx_groups_menu_item_title_system_entries_search', '_bx_groups_menu_item_title_entries_search', 'page.php?i=groups-search', '', '', '', '', 2147483647, 1, 1, 3),
+('bx_groups_submenu', 'bx_groups', 'groups-joined', '_bx_groups_menu_item_title_system_entries_joined', '_bx_groups_menu_item_title_entries_joined', 'page.php?i=groups-joined', '', '', '', '', 2147483647, 1, 1, 4),
+('bx_groups_submenu', 'bx_groups', 'groups-manage', '_bx_groups_menu_item_title_system_entries_manage', '_bx_groups_menu_item_title_entries_manage', 'page.php?i=groups-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_groups_view_submenu', '_bx_groups_menu_title_view_profile_submenu', 'bx_groups_view_submenu', 'bx_groups', 18, 0, 1, 'BxGroupsMenuView', 'modules/boonex/groups/classes/BxGroupsMenuView.php'),
+('bx_groups_view_submenu_cover', '_bx_groups_menu_title_view_profile_submenu_cover', 'bx_groups_view_submenu', 'bx_groups', 7, 0, 1, 'BxGroupsMenuView', 'modules/boonex/groups/classes/BxGroupsMenuView.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_groups_view_submenu', 'bx_groups', '_bx_groups_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_groups_view_submenu', 'bx_groups', 'view-group-profile', '_bx_groups_menu_item_title_system_view_profile_view', '_bx_groups_menu_item_title_view_profile_view', 'page.php?i=view-group-profile&id={content_id}', '', '', 'users col-red2', '', '', 0, 2147483647, 1, 0, 1),
+('bx_groups_view_submenu', 'bx_groups', 'group-profile-info', '_bx_groups_menu_item_title_system_view_profile_info', '_bx_groups_menu_item_title_view_profile_info', 'page.php?i=group-profile-info&id={content_id}', '', '', 'info-circle col-gray', '', '', 0, 2147483647, 1, 0, 2),
+('bx_groups_view_submenu', 'bx_groups', 'group-profile-comments', '_bx_groups_menu_item_title_system_view_profile_comments', '_bx_groups_menu_item_title_view_profile_comments', 'page.php?i=group-profile-comments&id={content_id}', '', '', '', '', '', 0, 2147483647, 0, 0, 3),
+('bx_groups_view_submenu', 'bx_groups', 'group-fans', '_bx_groups_menu_item_title_system_view_fans', '_bx_groups_menu_item_title_view_fans', 'page.php?i=group-fans&profile_id={profile_id}', '', '', 'users col-blue3', '', '', 0, 2147483647, 1, 0, 4),
+('bx_groups_view_submenu', 'bx_groups', 'more-auto', '_bx_groups_menu_item_title_system_view_profile_more_auto', '_bx_groups_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_groups_snippet_meta', '_sys_menu_title_snippet_meta', 'bx_groups_snippet_meta', 'bx_groups', 15, 0, 1, 'BxGroupsMenuSnippetMeta', 'modules/boonex/groups/classes/BxGroupsMenuSnippetMeta.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_groups_snippet_meta', 'bx_groups', '_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_groups_snippet_meta', 'bx_groups', 'privacy', '_bx_groups_menu_item_title_system_sm_privacy', '_bx_groups_menu_item_title_sm_privacy', '', '', '', '', '', 2147483647, '', 1, 0, 1, 1),
+('bx_groups_snippet_meta', 'bx_groups', 'date', '_sys_menu_item_title_system_sm_date', '_sys_menu_item_title_sm_date', '', '', '', '', '', 2147483647, '', 0, 0, 1, 2),
+('bx_groups_snippet_meta', 'bx_groups', 'tags', '_sys_menu_item_title_system_sm_tags', '_sys_menu_item_title_sm_tags', '', '', '', '', '', 2147483647, '', 0, 0, 1, 3),
+('bx_groups_snippet_meta', 'bx_groups', 'views', '_sys_menu_item_title_system_sm_views', '_sys_menu_item_title_sm_views', '', '', '', '', '', 2147483647, '', 0, 0, 1, 4),
+('bx_groups_snippet_meta', 'bx_groups', 'comments', '_sys_menu_item_title_system_sm_comments', '_sys_menu_item_title_sm_comments', '', '', '', '', '', 2147483647, '', 0, 0, 1, 5),
+('bx_groups_snippet_meta', 'bx_groups', 'members', '_sys_menu_item_title_system_sm_members', '_sys_menu_item_title_sm_members', '', '', '', '', '', 2147483647, '', 1, 0, 1, 6),
+('bx_groups_snippet_meta', 'bx_groups', 'subscribers', '_sys_menu_item_title_system_sm_subscribers', '_sys_menu_item_title_sm_subscribers', '', '', '', '', '', 2147483647, '', 0, 0, 1, 7),
+('bx_groups_snippet_meta', 'bx_groups', 'nl', '_sys_menu_item_title_system_sm_nl', '_sys_menu_item_title_sm_nl', '', '', '', '', '', 2147483647, '', 1, 0, 1, 8),
+('bx_groups_snippet_meta', 'bx_groups', 'join-paid', '_sys_menu_item_title_system_sm_join_paid', '_sys_menu_item_title_sm_join_paid', '', '', '', '', '', 2147483647, 'a:3:{s:6:"module";s:9:"bx_groups";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_groups_snippet_meta', 'bx_groups', 'join', '_sys_menu_item_title_system_sm_join', '_sys_menu_item_title_sm_join', '', '', '', '', '', 2147483647, 'a:3:{s:6:"module";s:9:"bx_groups";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_groups_snippet_meta', 'bx_groups', 'leave', '_sys_menu_item_title_system_sm_leave', '_sys_menu_item_title_sm_leave', '', '', '', '', '', 2147483647, '', 0, 0, 1, 12),
+('bx_groups_snippet_meta', 'bx_groups', 'subscribe', '_sys_menu_item_title_system_sm_subscribe', '_sys_menu_item_title_sm_subscribe', '', '', '', '', '', 2147483647, '', 0, 0, 1, 13),
+('bx_groups_snippet_meta', 'bx_groups', 'unsubscribe', '_sys_menu_item_title_system_sm_unsubscribe', '_sys_menu_item_title_sm_unsubscribe', '', '', '', '', '', 2147483647, '', 0, 0, 1, 14);
+
+-- 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_groups', 'profile-stats-manage-groups', '_bx_groups_menu_item_title_system_manage_my_groups', '_bx_groups_menu_item_title_manage_my_groups', 'page.php?i=groups-manage', '', '_self', 'users col-red2', 'a:2:{s:6:"module";s:9:"bx_groups";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_groups_menu_manage_tools', '_bx_groups_menu_title_manage_tools', 'bx_groups_menu_manage_tools', 'bx_groups', 6, 0, 1, 'BxGroupsMenuManageTools', 'modules/boonex/groups/classes/BxGroupsMenuManageTools.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_groups_menu_manage_tools', 'bx_groups', '_bx_groups_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_groups_menu_manage_tools', 'bx_groups', 'delete', '_bx_groups_menu_item_title_system_delete', '_bx_groups_menu_item_title_delete', 'javascript:void(0)', 'javascript:{js_object}.onClickDelete({content_id});', '_self', 'far trash-alt', '', 2147483647, 1, 0, 1),
+('bx_groups_menu_manage_tools', 'bx_groups', 'delete-with-content', '_bx_groups_menu_item_title_system_delete_with_content', '_bx_groups_menu_item_title_delete_with_content', 'javascript:void(0)', 'javascript:{js_object}.onClickDeleteWithContent({content_id});', '_self', 'far trash-alt', '', 2147483647, 1, 0, 2),
+('bx_groups_menu_manage_tools', 'bx_groups', 'clear-reports', '_bx_groups_menu_item_title_system_clear_reports', '_bx_groups_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_groups', 'groups-administration', '_bx_groups_menu_item_title_system_admt_groups', '_bx_groups_menu_item_title_admt_groups', 'page.php?i=groups-administration', '', '_self', 'users', 'a:2:{s:6:"module";s:9:"bx_groups";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`, `visibility_custom`, `active`, `copyable`, `order`) VALUES 
+('trigger_profile_view_submenu', 'bx_groups', 'joined-groups', '_bx_groups_menu_item_title_system_view_joined_groups', '_bx_groups_menu_item_title_view_joined_groups', 'page.php?i=joined-groups&profile_id={profile_id}', '', '', 'users col-red2', '', 2147483647, '', 1, 0, 0),
+('trigger_group_view_submenu', 'bx_groups', 'groups-context', '_bx_groups_menu_item_title_system_view_entries_in_context', '_bx_groups_menu_item_title_view_entries_in_context', 'page.php?i=groups-context&profile_id={profile_id}', '', '', 'users col-red2', '', 2147483647, 'a:3:{s:6:"module";s:9:"bx_groups";s:6:"method";s:21:"is_enable_for_context";s:6:"params";a:1:{i:0;s:12:"{profile_id}";}}', 1, 0, 0);
+
+-- ACL
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_groups', 'create entry', NULL, '_bx_groups_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_groups', 'use paid join', NULL, '_bx_groups_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_groups', 'delete entry', NULL, '_bx_groups_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_groups', 'view entry', NULL, '_bx_groups_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_groups', 'edit any entry', NULL, '_bx_groups_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_groups', 'delete invites', NULL, '_bx_groups_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_groups', 'bx_groups_meta_keywords', 'bx_groups_meta_locations', 'bx_groups_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_groups_cats', 'bx_groups', 'bx_group', 'bx_groups_cats', 'bx_groups_data', 'group_cat', 'INNER JOIN `sys_profiles` ON (`sys_profiles`.`content_id` = `bx_groups_data`.`id` AND `sys_profiles`.`type` = ''bx_groups'')', '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_groups', '_bx_groups', @iSearchOrder + 1, 'BxGroupsSearchResult', 'modules/boonex/groups/classes/BxGroupsSearchResult.php');
+
+-- CONNECTIONS
+INSERT INTO `sys_objects_connection` (`object`, `table`, `type`, `override_class_name`, `override_class_file`) VALUES
+('bx_groups_fans', 'bx_groups_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_groups', 'bx_groups', '_bx_groups', 'page.php?i=groups-home', 'users col-red2', 'SELECT COUNT(*) FROM `bx_groups_data` AS `td` LEFT JOIN `sys_profiles` AS `tp` ON `td`.`id` = `tp`.`content_id` AND `tp`.`type`=''bx_groups'' 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_groups_growth', '_bx_groups_chart_growth', 'bx_groups_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_groups'' WHERE 1 AND `tp`.`status`=''active'' {where_inteval} GROUP BY `period` ORDER BY {table}.{field_date} ASC', 1, @iMaxOrderCharts + 1, 'BxDolChartGrowth', ''),
+('bx_groups_growth_speed', '_bx_groups_chart_growth_speed', 'bx_groups_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_groups'' 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_groups_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, 1, 'BxGroupsGridConnections', 'modules/boonex/groups/classes/BxGroupsGridConnections.php');
+
+INSERT INTO `sys_grid_fields` (`object`, `name`, `title`, `width`, `params`, `order`) VALUES
+('bx_groups_fans', 'name', '_sys_name', '50%', '', 10),
+('bx_groups_fans', 'role', '_bx_groups_txt_role', '10%', '', 15),
+('bx_groups_fans', 'role_added', '_bx_groups_txt_role_added', '10%', '', 16),
+('bx_groups_fans', 'role_expired', '_bx_groups_txt_role_expired', '10%', '', 17),
+('bx_groups_fans', 'actions', '', '20%', '', 20);
+
+INSERT INTO `sys_grid_actions` (`object`, `type`, `name`, `title`, `icon`, `confirm`, `order`) VALUES
+('bx_groups_fans', 'single', 'accept', '_sys_accept', '', 0, 10),
+('bx_groups_fans', 'single', 'set_role', '_bx_groups_txt_set_role', '', 0, 20),
+('bx_groups_fans', 'single', 'set_role_submit', '', '', 0, 21),
+('bx_groups_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_groups_invites', 'Sql', 'SELECT `bx_groups_invites`.`id`, `bx_groups_invites`.`invited_profile_id`, `bx_groups_invites`.`added`, `bx_groups_invites`.`author_profile_id` FROM `sys_profiles` AS `p` INNER JOIN `sys_accounts` AS `a` ON (`a`.`id` = `p`.`account_id`) INNER JOIN `bx_groups_invites` ON `bx_groups_invites`.`invited_profile_id` = `p`.`id` ', 'bx_groups_invites', 'id', 'bx_groups_invites`.`added', '', '', 10, NULL, 'start', '', 'name,email', '', 'auto', '', '', 2147483647, 0, 'BxGroupsGridInvites', 'modules/boonex/groups/classes/BxGroupsGridInvites.php');
+
+INSERT INTO `sys_grid_fields` (`object`, `name`, `title`, `width`, `params`, `order`) VALUES
+('bx_groups_invites', 'name', '_sys_name', '33%', '', 10),
+('bx_groups_invites', 'added', '_sys_added', '33%', '', 20),
+('bx_groups_invites', 'actions', '', '34%', '', 30);
+
+INSERT INTO `sys_grid_actions` (`object`, `type`, `name`, `title`, `icon`, `confirm`, `order`) VALUES
+('bx_groups_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_groups_administration', 'Sql', 'SELECT `td`.*, `td`.`group_name` AS `name`, `ta`.`email` AS `account`, `td`.`added` AS `added_ts`, `tp`.`status` AS `status` FROM `bx_groups_data` AS `td` LEFT JOIN `sys_profiles` AS `tp` ON `td`.`id`=`tp`.`content_id` AND `tp`.`type`=''bx_groups'' LEFT JOIN `sys_accounts` AS `ta` ON `tp`.`account_id`=`ta`.`id` WHERE 1 ', 'bx_groups_data', 'id', 'added', 'status', '', 20, NULL, 'start', '', 'group_name', '', 'like', 'reports', '', 192, 'BxGroupsGridAdministration', 'modules/boonex/groups/classes/BxGroupsGridAdministration.php'),
+('bx_groups_common', 'Sql', 'SELECT `td`.*, `td`.`group_name` AS `name`, `ta`.`email` AS `account`, `td`.`added` AS `added_ts`, `tp`.`status` AS `status` FROM `bx_groups_data` AS `td` LEFT JOIN `sys_profiles` AS `tp` ON `td`.`id`=`tp`.`content_id` AND `tp`.`type`=''bx_groups'' LEFT JOIN `sys_accounts` AS `ta` ON `tp`.`account_id`=`ta`.`id` WHERE 1 ', 'bx_groups_data', 'id', 'added', 'status', '', 20, NULL, 'start', '', 'group_name', '', 'like', '', '', 2147483647, 'BxGroupsGridCommon', 'modules/boonex/groups/classes/BxGroupsGridCommon.php');
+
+INSERT INTO `sys_grid_fields` (`object`, `name`, `title`, `width`, `translatable`, `chars_limit`, `params`, `order`) VALUES
+('bx_groups_administration', 'checkbox', '_sys_select', '2%', 0, '', '', 1),
+('bx_groups_administration', 'switcher', '_bx_groups_grid_column_title_adm_active', '8%', 0, '', '', 2),
+('bx_groups_administration', 'reports', '_sys_txt_reports_title', '5%', 0, '', '', 3),
+('bx_groups_administration', 'name', '_bx_groups_grid_column_title_adm_name', '25%', 0, '', '', 4),
+('bx_groups_administration', 'added_ts', '_bx_groups_grid_column_title_adm_added', '20%', 1, '25', '', 5),
+('bx_groups_administration', 'account', '_bx_groups_grid_column_title_adm_account', '20%', 0, '25', '', 6),
+('bx_groups_administration', 'actions', '', '20%', 0, '', '', 7),
+('bx_groups_common', 'checkbox', '_sys_select', '2%', 0, '', '', 1),
+('bx_groups_common', 'name', '_bx_groups_grid_column_title_adm_name', '48%', 0, '', '', 2),
+('bx_groups_common', 'added_ts', '_bx_groups_grid_column_title_adm_added', '30%', 1, '25', '', 3),
+('bx_groups_common', 'actions', '', '20%', 0, '', '', 4);
+
+INSERT INTO `sys_grid_actions` (`object`, `type`, `name`, `title`, `icon`, `icon_only`, `confirm`, `order`) VALUES
+('bx_groups_administration', 'bulk', 'delete', '_bx_groups_grid_action_title_adm_delete', '', 0, 1, 2),
+('bx_groups_administration', 'bulk', 'delete_with_content', '_bx_groups_grid_action_title_adm_delete_with_content', '', 0, 1, 3),
+('bx_groups_administration', 'bulk', 'clear_reports', '_bx_groups_grid_action_title_adm_clear_reports', '', 0, 1, 4),
+('bx_groups_administration', 'single', 'settings', '_bx_groups_grid_action_title_adm_more_actions', 'cog', 1, 0, 2),
+('bx_groups_administration', 'single', 'audit_content', '_bx_groups_grid_action_title_adm_audit_content', 'search', 1, 0, 3),
+('bx_groups_administration', 'single', 'audit_context', '_bx_groups_grid_action_title_adm_audit_context', 'search-location', 1, 0, 4),
+('bx_groups_common', 'bulk', 'delete', '_bx_groups_grid_action_title_adm_delete', '', 0, 1, 1),
+('bx_groups_common', 'bulk', 'delete_with_content', '_bx_groups_grid_action_title_adm_delete_with_content', '', 0, 1, 2),
+('bx_groups_common', 'single', 'settings', '_bx_groups_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_groups_prices_manage', 'Sql', 'SELECT * FROM `bx_groups_prices` WHERE 1 ', 'bx_groups_prices', 'id', 'order', '', '', 100, NULL, 'start', '', 'period,period_unit,price', '', 'like', '', '', 2147483647, 'BxGroupsGridPricesManage', 'modules/boonex/groups/classes/BxGroupsGridPricesManage.php'),
+('bx_groups_prices_view', 'Sql', 'SELECT * FROM `bx_groups_prices` WHERE 1 ', 'bx_groups_prices', 'id', 'order', '', '', 100, NULL, 'start', '', 'period,period_unit,price', '', 'like', '', '', 2147483647, 'BxGroupsGridPricesView', 'modules/boonex/groups/classes/BxGroupsGridPricesView.php');
+
+INSERT INTO `sys_grid_fields` (`object`, `name`, `title`, `width`, `translatable`, `chars_limit`, `params`, `order`) VALUES
+('bx_groups_prices_manage', 'checkbox', '_sys_select', '1%', 0, '', '', 1),
+('bx_groups_prices_manage', 'order', '', '1%', 0, '', '', 2),
+('bx_groups_prices_manage', 'name', '_bx_groups_grid_column_title_name', '38%', 0, 32, '', 3),
+('bx_groups_prices_manage', 'price', '_bx_groups_grid_column_title_price', '20%', 0, 16, '', 4),
+('bx_groups_prices_manage', 'period', '_bx_groups_grid_column_title_period', '20%', 0, 16, '', 5),
+('bx_groups_prices_manage', 'actions', '', '20%', 0, '', '', 6),
+
+('bx_groups_prices_view', 'role_id', '_bx_groups_grid_column_title_role_id', '40%', 0, 32, '', 1),
+('bx_groups_prices_view', 'price', '_bx_groups_grid_column_title_price', '20%', 0, 16, '', 2),
+('bx_groups_prices_view', 'period', '_bx_groups_grid_column_title_period', '20%', 0, 16, '', 3),
+('bx_groups_prices_view', 'actions', '', '20%', 0, '', '', 4);
+
+INSERT INTO `sys_grid_actions` (`object`, `type`, `name`, `title`, `icon`, `icon_only`, `confirm`, `order`) VALUES
+('bx_groups_prices_manage', 'independent', 'add', '_bx_groups_grid_action_title_add', '', 0, 0, 1),
+('bx_groups_prices_manage', 'single', 'edit', '_bx_groups_grid_action_title_edit', 'pencil-alt', 1, 0, 1),
+('bx_groups_prices_manage', 'single', 'delete', '_bx_groups_grid_action_title_delete', 'remove', 1, 1, 2),
+('bx_groups_prices_manage', 'bulk', 'delete', '_bx_groups_grid_action_title_delete', '', 0, 1, 1),
+
+('bx_groups_prices_view', 'single', 'buy', '_bx_groups_grid_action_title_buy', 'cart-plus', 0, 0, 1),
+('bx_groups_prices_view', 'single', 'subscribe', '_bx_groups_grid_action_title_subscribe', 'credit-card', 0, 0, 2),
+('bx_groups_prices_view', 'single', 'choose', '_bx_groups_grid_action_title_choose', 'far check-square', 0, 0, 3);
+
+
+-- ALERTS
+
+INSERT INTO `sys_alerts_handlers` (`name`, `class`, `file`, `service_call`) VALUES 
+('bx_groups', 'BxGroupsAlertsResponse', 'modules/boonex/groups/classes/BxGroupsAlertsResponse.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_groups_pics', 'file_deleted', @iHandler),
+('bx_groups_fans', 'connection_added', @iHandler),
+('bx_groups_fans', 'connection_removed', @iHandler),
+('profile', 'delete', @iHandler),
+('bx_groups', 'fan_added', @iHandler),
+('bx_groups', 'join_invitation', @iHandler),
+('bx_groups', 'join_request', @iHandler),
+('bx_groups', 'join_request_accepted', @iHandler),
+('bx_groups', 'timeline_view', @iHandler),
+('bx_groups', 'timeline_post', @iHandler),
+('bx_groups', 'timeline_delete', @iHandler),
+('bx_groups', 'timeline_comment', @iHandler),
+('bx_groups', 'timeline_vote', @iHandler),
+('bx_groups', 'timeline_score', @iHandler),
+('bx_groups', 'timeline_report', @iHandler),
+('bx_groups', 'timeline_repost', @iHandler),
+('bx_groups', 'timeline_pin', @iHandler),
+('bx_groups', '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_groups_allow_view_to', 'bx_groups', 'view', '_bx_groups_form_profile_input_allow_view_to', '3', 'bx_events,bx_spaces', 'bx_groups_data', 'id', 'author', 'BxGroupsPrivacy', 'modules/boonex/groups/classes/BxGroupsPrivacy.php'),
+('bx_groups_allow_view_notification_to', 'bx_groups', 'view_event', '_bx_groups_form_profile_input_allow_view_notification_to', '3', '', 'bx_notifications_events', 'id', 'object_owner_id', 'BxGroupsPrivacyNotifications', 'modules/boonex/groups/classes/BxGroupsPrivacyNotifications.php'),
+('bx_groups_allow_post_to', 'bx_groups', 'post', '_bx_groups_form_profile_input_allow_post_to', 'p', '', 'bx_groups_data', 'id', 'author', 'BxGroupsPrivacyPost', 'modules/boonex/groups/classes/BxGroupsPrivacyPost.php'),
+('bx_groups_allow_view_favorite_list', 'bx_groups', 'view_favorite_list', '_bx_groups_form_profile_input_allow_view_favorite_list', '3', '', 'bx_groups_favorites_lists', 'id', 'author_id', 'BxGroupsPrivacy', 'modules/boonex/groups/classes/BxGroupsPrivacy.php');
+-- EMAIL TEMPLATES
+
+INSERT INTO `sys_email_templates` (`Module`, `NameSystem`, `Name`, `Subject`, `Body`) VALUES
+('bx_groups', '_bx_groups_email_join_request', 'bx_groups_join_request', '_bx_groups_email_join_request_subject', '_bx_groups_email_join_request_body'),
+('bx_groups', '_bx_groups_email_join_reject', 'bx_groups_join_reject', '_bx_groups_email_join_reject_subject', '_bx_groups_email_join_reject_body'),
+('bx_groups', '_bx_groups_email_join_confirm', 'bx_groups_join_confirm', '_bx_groups_email_join_confirm_subject', '_bx_groups_email_join_confirm_body'),
+('bx_groups', '_bx_groups_email_fan_remove', 'bx_groups_fan_remove', '_bx_groups_email_fan_remove_subject', '_bx_groups_email_fan_remove_body'),
+('bx_groups', '_bx_groups_email_fan_become_admin', 'bx_groups_fan_become_admin', '_bx_groups_email_fan_become_admin_subject', '_bx_groups_email_fan_become_admin_body'),
+('bx_groups', '_bx_groups_email_admin_become_fan', 'bx_groups_admin_become_fan', '_bx_groups_email_admin_become_fan_subject', '_bx_groups_email_admin_become_fan_body'),
+('bx_groups', '_bx_groups_email_set_role', 'bx_groups_set_role', '_bx_groups_email_set_role_subject', '_bx_groups_email_set_role_body'),
+('bx_groups', '_bx_groups_email_invitation', 'bx_groups_invitation', '_bx_groups_email_invitation_subject', '_bx_groups_email_invitation_body');
+
+-- UPLOADERS
+
+INSERT INTO `sys_objects_uploader` (`object`, `active`, `override_class_name`, `override_class_file`) VALUES
+('bx_groups_cover_crop', 1, 'BxGroupsUploaderCoverCrop', 'modules/boonex/groups/classes/BxGroupsUploaderCoverCrop.php'),
+('bx_groups_picture_crop', 1, 'BxGroupsUploaderPictureCrop', 'modules/boonex/groups/classes/BxGroupsUploaderPictureCrop.php');
+
+
+-- CRON
+INSERT INTO `sys_cron_jobs` (`name`, `time`, `class`, `file`, `service_call`) VALUES
+('bx_groups_pruning', '0 0 * * *', 'BxGroupsCronPruning', 'modules/boonex/groups/classes/BxGroupsCronPruning.php', '');

+ 484 - 0
modules/boonex/groups/updates/12.0.2_12.0.3/source/install/sql/install.sql

@@ -0,0 +1,484 @@
+SET @sStorageEngine = (SELECT `value` FROM `sys_options` WHERE `name` = 'sys_storage_default');
+
+-- TABLE: PROFILES
+CREATE TABLE IF NOT EXISTS `bx_groups_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,
+  `group_name` varchar(255) NOT NULL,
+  `group_cat` int(11) NOT NULL,
+  `group_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` (`group_name`, `group_desc`)
+);
+
+-- TABLE: STORAGES & TRANSCODERS
+CREATE TABLE `bx_groups_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_groups_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_groups_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_groups_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: VIEWS
+CREATE TABLE `bx_groups_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_groups_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_groups_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_groups_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_groups_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_groups_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_groups_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_groups_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_groups_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_groups_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 `bx_groups_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_groups_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_groups_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_groups_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_groups_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_groups_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_groups_pics', @sStorageEngine, '', 360, 2592000, 3, 'bx_groups_pics', 'allow-deny', 'jpg,jpeg,jpe,gif,png', '', 0, 0, 0, 0, 0, 0),
+('bx_groups_pics_resized', @sStorageEngine, '', 360, 2592000, 3, 'bx_groups_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_groups_icon', 'bx_groups_pics_resized', 'Storage', 'a:1:{s:6:"object";s:14:"bx_groups_pics";}', 'no', '1', '2592000', '0'),
+('bx_groups_thumb', 'bx_groups_pics_resized', 'Storage', 'a:1:{s:6:"object";s:14:"bx_groups_pics";}', 'no', '1', '2592000', '0'),
+('bx_groups_avatar', 'bx_groups_pics_resized', 'Storage', 'a:1:{s:6:"object";s:14:"bx_groups_pics";}', 'no', '1', '2592000', '0'),
+('bx_groups_avatar_big', 'bx_groups_pics_resized', 'Storage', 'a:1:{s:6:"object";s:14:"bx_groups_pics";}', 'no', '1', '2592000', '0'),
+('bx_groups_picture', 'bx_groups_pics_resized', 'Storage', 'a:1:{s:6:"object";s:14:"bx_groups_pics";}', 'no', '1', '2592000', '0'),
+('bx_groups_cover', 'bx_groups_pics_resized', 'Storage', 'a:1:{s:6:"object";s:14:"bx_groups_pics";}', 'no', '1', '2592000', '0'),
+('bx_groups_cover_thumb', 'bx_groups_pics_resized', 'Storage', 'a:1:{s:6:"object";s:14:"bx_groups_pics";}', 'no', '1', '2592000', '0'),
+('bx_groups_gallery', 'bx_groups_pics_resized', 'Storage', 'a:1:{s:6:"object";s:14:"bx_groups_pics";}', 'no', '1', '2592000', '0');
+
+INSERT INTO `sys_transcoder_filters` (`transcoder_object`, `filter`, `filter_params`, `order`) VALUES 
+('bx_groups_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_groups_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_groups_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_groups_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_groups_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_groups_cover', 'Resize', 'a:1:{s:1:"w";s:4:"2000";}', '0'),
+('bx_groups_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_groups_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_group', 'bx_groups', '_bx_groups_form_profile', '', 'a:1:{s:7:\"enctype\";s:19:\"multipart/form-data\";}', 'bx_groups_data', 'id', '', '', 'do_submit', '', 0, 1, 'BxGroupsFormEntry', 'modules/boonex/groups/classes/BxGroupsFormEntry.php');
+
+INSERT INTO `sys_form_displays`(`object`, `display_name`, `module`, `view_mode`, `title`) VALUES 
+('bx_group', 'bx_group_add', 'bx_groups', 0, '_bx_groups_form_profile_display_add'),
+('bx_group', 'bx_group_delete', 'bx_groups', 0, '_bx_groups_form_profile_display_delete'),
+('bx_group', 'bx_group_edit', 'bx_groups', 0, '_bx_groups_form_profile_display_edit'),
+('bx_group', 'bx_group_edit_cover', 'bx_groups', 0, '_bx_groups_form_profile_display_edit_cover'),
+('bx_group', 'bx_group_view', 'bx_groups', 1, '_bx_groups_form_profile_display_view'),
+('bx_group', 'bx_group_view_full', 'bx_groups', 1, '_bx_groups_form_profile_display_view_full'),
+('bx_group', 'bx_group_invite', 'bx_groups', 0, '_bx_groups_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_group', 'bx_groups', 'allow_view_to', 3, '', 0, 'custom', '_bx_groups_form_profile_input_sys_allow_view_to', '_bx_groups_form_profile_input_allow_view_to', '_bx_groups_form_profile_input_allow_view_to_desc', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_group', 'bx_groups', 'allow_post_to', 3, '', 0, 'custom', '_bx_groups_form_profile_input_sys_allow_post_to', '_bx_groups_form_profile_input_allow_post_to', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_group', 'bx_groups', 'delete_confirm', 1, '', 0, 'checkbox', '_bx_groups_form_profile_input_sys_delete_confirm', '_bx_groups_form_profile_input_delete_confirm', '_bx_groups_form_profile_input_delete_confirm_info', 1, 0, 0, '', '', '', 'avail', '', '_bx_groups_form_profile_input_delete_confirm_error', '', '', 1, 0),
+('bx_group', 'bx_groups', 'do_submit', '_sys_form_account_input_submit', '', 0, 'submit', '_bx_groups_form_profile_input_sys_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_group', 'bx_groups', 'group_desc', '', '', 0, 'textarea', '_bx_groups_form_profile_input_sys_group_desc', '_bx_groups_form_profile_input_group_desc', '', 0, 0, 2, '', '', '', '', '', '', 'XssHtml', '', 1, 1),
+('bx_group', 'bx_groups', 'group_cat', '', '#!bx_groups_cats', 0, 'select', '_bx_groups_form_profile_input_sys_group_cat', '_bx_groups_form_profile_input_group_cat', '', 1, 0, 0, '', '', '', 'avail', '', '_bx_groups_form_profile_input_group_cat_err', 'Xss', '', 1, 1),
+('bx_group', 'bx_groups', 'group_name', '', '', 0, 'text', '_bx_groups_form_profile_input_sys_group_name', '_bx_groups_form_profile_input_group_name', '', 1, 0, 0, '', '', '', 'avail', '', '_bx_groups_form_profile_input_group_name_err', 'Xss', '', 1, 0),
+('bx_group', 'bx_groups', 'initial_members', '', '', 0, 'custom', '_bx_groups_form_profile_input_sys_initial_members', '_bx_groups_form_profile_input_initial_members', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 1),
+('bx_group', 'bx_groups', 'join_confirmation', 1, '', 1, 'switcher', '_bx_groups_form_profile_input_sys_join_confirm', '_bx_groups_form_profile_input_join_confirm', '', 0, 0, 0, '', '', '', '', '', '', 'Xss', '', 1, 0),
+('bx_group', 'bx_groups', 'cover', 'a:1:{i:0;s:20:"bx_groups_cover_crop";}', 'a:1:{s:20:"bx_groups_cover_crop";s:24:"_sys_uploader_crop_title";}', 0, 'files', '_bx_groups_form_profile_input_sys_cover', '_bx_groups_form_profile_input_cover', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_group', 'bx_groups', 'picture', 'a:1:{i:0;s:22:"bx_groups_picture_crop";}', 'a:1:{s:22:"bx_groups_picture_crop";s:24:"_sys_uploader_crop_title";}', 0, 'files', '_bx_groups_form_profile_input_sys_picture', '_bx_groups_form_profile_input_picture', '', 0, 0, 0, '', '', '', '', '', '_bx_groups_form_profile_input_picture_err', '', '', 1, 0),
+('bx_group', 'bx_groups', 'location', '', '', 0, 'location', '_sys_form_input_sys_location', '_sys_form_input_location', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_group', 'bx_groups', '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_group_add', 'initial_members', 2147483647, 1, 1),
+('bx_group_add', 'group_name', 2147483647, 1, 2),
+('bx_group_add', 'group_cat', 2147483647, 1, 3),
+('bx_group_add', 'group_desc', 2147483647, 1, 4),
+('bx_group_add', 'location', 2147483647, 1, 5),
+('bx_group_add', 'join_confirmation', 2147483647, 1, 6),
+('bx_group_add', 'allow_view_to', 2147483647, 1, 7),
+('bx_group_add', 'allow_post_to', 2147483647, 1, 8),
+('bx_group_add', 'do_submit', 2147483647, 1, 9),
+
+('bx_group_invite', 'initial_members', 2147483647, 1, 1),
+('bx_group_invite', 'do_submit', 2147483647, 1, 2),
+
+('bx_group_delete', 'delete_confirm', 2147483647, 1, 1),
+('bx_group_delete', 'do_submit', 2147483647, 1, 2),
+
+('bx_group_edit', 'group_name', 2147483647, 1, 1),
+('bx_group_edit', 'group_cat', 2147483647, 1, 2),
+('bx_group_edit', 'group_desc', 2147483647, 1, 3),
+('bx_group_edit', 'location', 2147483647, 1, 4),
+('bx_group_edit', 'join_confirmation', 2147483647, 1, 5),
+('bx_group_edit', 'allow_view_to', 2147483647, 1, 6),
+('bx_group_edit', 'allow_post_to', 2147483647, 1, 7),
+('bx_group_edit', 'do_submit', 2147483647, 1, 8),
+
+('bx_group_edit_cover', 'cover', 2147483647, 1, 1),
+('bx_group_edit_cover', 'do_submit', 2147483647, 1, 2),
+
+('bx_group_view', 'group_name', 2147483647, 1, 1),
+('bx_group_view', 'group_cat', 2147483647, 1, 2),
+
+('bx_group_view_full', 'group_name', 2147483647, 1, 1),
+('bx_group_view_full', 'group_cat', 2147483647, 1, 2),
+('bx_group_view_full', 'group_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_groups_price', 'bx_groups', '_bx_groups_form_price', '', '', 'do_submit', 'bx_groups_prices', 'id', '', '', '', 0, 1, 'BxGroupsFormPrice', 'modules/boonex/groups/classes/BxGroupsFormPrice.php');
+
+INSERT INTO `sys_form_displays` (`display_name`, `module`, `object`, `title`, `view_mode`) VALUES
+('bx_groups_price_add', 'bx_groups', 'bx_groups_price', '_bx_groups_form_price_display_add', 0),
+('bx_groups_price_edit', 'bx_groups', 'bx_groups_price', '_bx_groups_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_groups_price', 'bx_groups', 'id', '', '', 0, 'hidden', '_bx_groups_form_price_input_sys_id', '', '', 1, 0, 0, '', '', '', '', '', '', 'Int', '', 1, 0),
+('bx_groups_price', 'bx_groups', 'role_id', '', '', 0, 'hidden', '_bx_groups_form_price_input_sys_role_id', '', '', 1, 0, 0, '', '', '', '', '', '', 'Int', '', 1, 0),
+('bx_groups_price', 'bx_groups', 'name', '', '', 0, 'text', '_bx_groups_form_price_input_sys_name', '_bx_groups_form_price_input_name', '_bx_groups_form_price_input_inf_name', 1, 0, 0, '', '', '', 'Avail', '', '_bx_groups_form_price_input_err_name', 'Xss', '', 1, 0),
+('bx_groups_price', 'bx_groups', 'period', '', '', 0, 'text', '_bx_groups_form_price_input_sys_period', '_bx_groups_form_price_input_period', '_bx_groups_form_price_input_inf_period', 1, 0, 0, '', '', '', '', '', '', 'Int', '', 1, 0),
+('bx_groups_price', 'bx_groups', 'period_unit', '', '#!bx_groups_period_units', 0, 'select', '_bx_groups_form_price_input_sys_period_unit', '_bx_groups_form_price_input_period_unit', '_bx_groups_form_price_input_inf_period_unit', 1, 0, 0, '', '', '', '', '', '', 'Xss', '', 1, 0),
+('bx_groups_price', 'bx_groups', 'price', '', '', 0, 'text', '_bx_groups_form_price_input_sys_price', '_bx_groups_form_price_input_price', '_bx_groups_form_price_input_inf_price', 1, 0, 0, '', '', '', '', '', '', 'Float', '', 1, 0),
+('bx_groups_price', 'bx_groups', 'controls', '', 'do_submit,do_cancel', 0, 'input_set', '', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_groups_price', 'bx_groups', 'do_submit', '_bx_groups_form_price_input_do_submit', '', 0, 'submit', '_bx_groups_form_price_input_sys_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_groups_price', 'bx_groups', 'do_cancel', '_bx_groups_form_price_input_do_cancel', '', 0, 'button', '_bx_groups_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_groups_price_add', 'id', 2147483647, 0, 1),
+('bx_groups_price_add', 'role_id', 2147483647, 1, 2),
+('bx_groups_price_add', 'name', 2147483647, 1, 3),
+('bx_groups_price_add', 'price', 2147483647, 1, 4),
+('bx_groups_price_add', 'period', 2147483647, 1, 5),
+('bx_groups_price_add', 'period_unit', 2147483647, 1, 6),
+('bx_groups_price_add', 'controls', 2147483647, 1, 7),
+('bx_groups_price_add', 'do_submit', 2147483647, 1, 8),
+('bx_groups_price_add', 'do_cancel', 2147483647, 1, 9),
+
+('bx_groups_price_edit', 'id', 2147483647, 1, 1),
+('bx_groups_price_edit', 'role_id', 2147483647, 1, 2),
+('bx_groups_price_edit', 'name', 2147483647, 1, 3),
+('bx_groups_price_edit', 'price', 2147483647, 1, 4),
+('bx_groups_price_edit', 'period', 2147483647, 1, 5),
+('bx_groups_price_edit', 'period_unit', 2147483647, 1, 6),
+('bx_groups_price_edit', 'controls', 2147483647, 1, 7),
+('bx_groups_price_edit', 'do_submit', 2147483647, 1, 8),
+('bx_groups_price_edit', 'do_cancel', 2147483647, 1, 9);
+
+-- PRE-VALUES
+INSERT INTO `sys_form_pre_lists`(`key`, `title`, `module`, `use_for_sets`) VALUES
+('bx_groups_cats', '_bx_groups_pre_lists_cats', 'bx_groups', '0');
+
+INSERT INTO `sys_form_pre_values`(`Key`, `Value`, `Order`, `LKey`, `LKey2`) VALUES
+('bx_groups_cats', '', 0, '_sys_please_select', ''),
+('bx_groups_cats', '1', 1, '_bx_groups_cat_General', ''),
+('bx_groups_cats', '2', 2, '_bx_groups_cat_Business', ''),
+('bx_groups_cats', '3', 3, '_bx_groups_cat_Interests', ''),
+('bx_groups_cats', '4', 4, '_bx_groups_cat_Causes', ''),
+('bx_groups_cats', '5', 5, '_bx_groups_cat_Fun', ''),
+('bx_groups_cats', '6', 6, '_bx_groups_cat_Uncategorised', '');
+
+INSERT INTO `sys_form_pre_lists`(`key`, `title`, `module`, `use_for_sets`) VALUES
+('bx_groups_roles', '_bx_groups_pre_lists_roles', 'bx_groups', '1');
+
+INSERT INTO `sys_form_pre_values`(`Key`, `Value`, `Order`, `LKey`, `LKey2`) VALUES
+('bx_groups_roles', '0', 1, '_bx_groups_role_regular', ''),
+('bx_groups_roles', '1', 2, '_bx_groups_role_administrator', ''),
+('bx_groups_roles', '2', 3, '_bx_groups_role_moderator', '');
+
+INSERT INTO `sys_form_pre_lists`(`key`, `title`, `module`, `use_for_sets`) VALUES
+('bx_groups_period_units', '_bx_groups_pre_lists_period_units', 'bx_groups', '0');
+
+INSERT INTO `sys_form_pre_values`(`Key`, `Value`, `Order`, `LKey`, `LKey2`) VALUES
+('bx_groups_period_units', '', 0, '_sys_please_select', ''),
+('bx_groups_period_units', 'day', 1, '_bx_groups_period_unit_day', ''),
+('bx_groups_period_units', 'week', 2, '_bx_groups_period_unit_week', ''),
+('bx_groups_period_units', 'month', 3, '_bx_groups_period_unit_month', ''),
+('bx_groups_period_units', 'year', 4, '_bx_groups_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_groups', 'bx_groups', 'bx_groups_cmts', 1, 5000, 1000, 3, 5, 3, 'tail', 1, 'bottom', 1, 1, 1, -3, 1, 'cmt', 'page.php?i=view-group-profile&id={object_id}', '', 'bx_groups_data', 'id', 'author', 'group_name', 'comments', 'BxGroupsCmts', 'modules/boonex/groups/classes/BxGroupsCmts.php'),
+('bx_groups_notes', 'bx_groups', 'bx_groups_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_groups_data', 'id', 'author', 'group_name', 'comments', 'BxTemplCmtsNotes', '');
+
+-- 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_groups', 'bx_groups_views_track', '86400', '1', 'bx_groups_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_groups', 'bx_groups_votes', 'bx_groups_votes_track', '604800', '1', '1', '0', '1', 'bx_groups_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_groups', 'bx_groups', 'bx_groups_scores', 'bx_groups_scores_track', '604800', '0', 'bx_groups_data', '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_groups', 'bx_groups', 'bx_groups_reports', 'bx_groups_reports_track', '1', 'page.php?i=view-group-profile&id={object_id}', 'bx_groups_notes', 'bx_groups_data', 'id', 'author', 'reports', '', '');
+
+-- FAVORITES
+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_groups', 'bx_groups_favorites_track', 'bx_groups_favorites_lists', '1', '1', '1', 'page.php?i=view-group-profile&id={object_id}', 'bx_groups_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_groups', 'bx_groups', '1', '1', 'page.php?i=view-group-profile&id={object_id}', 'bx_groups_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_groups', '_bx_groups', 'bx_groups', 'added', 'edited', 'deleted', '', ''),
+('bx_groups_cmts', '_bx_groups_cmts', 'bx_groups', 'commentPost', 'commentUpdated', 'commentRemoved', 'BxDolContentInfoCmts', '');
+
+INSERT INTO `sys_content_info_grids` (`object`, `grid_object`, `grid_field_id`, `condition`, `selection`) VALUES
+('bx_groups', 'bx_groups_administration', 'td`.`id', '', ''),
+('bx_groups', 'bx_groups_common', 'td`.`id', '', '');
+
+-- SEARCH EXTENDED
+INSERT INTO `sys_objects_search_extended` (`object`, `object_content_info`, `module`, `title`, `active`, `class_name`, `class_file`) VALUES
+('bx_groups', 'bx_groups', 'bx_groups', '_bx_groups_search_extended', 1, '', ''),
+('bx_groups_cmts', 'bx_groups_cmts', 'bx_groups', '_bx_groups_search_extended_cmts', 1, 'BxTemplSearchExtendedCmts', '');
+
+-- STUDIO PAGE & WIDGET
+INSERT INTO `sys_std_pages`(`index`, `name`, `header`, `caption`, `icon`) VALUES
+(3, 'bx_groups', '_bx_groups', '_bx_groups', 'bx_groups@modules/boonex/groups/|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_groups', 'content', '{url_studio}module.php?name=bx_groups', '', 'bx_groups@modules/boonex/groups/|std-icon.svg', '_bx_groups', '', '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));
+

+ 59 - 0
modules/boonex/groups/updates/12.0.2_12.0.3/source/js/prices.js

@@ -0,0 +1,59 @@
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Groups Groups
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+
+function BxGroupsPrices(oOptions) {
+    this._sActionsUri = oOptions.sActionUri;
+    this._sActionsUrl = oOptions.sActionUrl;
+    this._sObjNameGrid = oOptions.sObjNameGrid;
+    this._sObjName = oOptions.sObjName == undefined ? 'oBxGroupsPrices' : oOptions.sObjName;
+    this._aHtmlIds = oOptions.aHtmlIds == undefined ? {} : oOptions.aHtmlIds;
+    this._oRequestParams = oOptions.oRequestParams == undefined ? {} : oOptions.oRequestParams;
+}
+
+BxGroupsPrices.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'
+    );
+};
+
+BxGroupsPrices.prototype.onChangeRole = function() {
+	this.reloadGrid($('#bx-grid-level-' + this._sObjNameGrid).val());
+};
+
+BxGroupsPrices.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/groups/updates/12.0.2_12.0.3/source/template/css/main.css

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

+ 1 - 0
modules/boonex/groups/updates/12.0.2_12.0.3/source/template/css/prices.css

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

+ 51 - 0
modules/boonex/intercom/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' => 'Intercom',
+    '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/intercom/updates/update_12.0.0_12.0.1/',
+    'home_uri' => 'intercom_update_1200_1201',
+    
+    'module_dir' => 'boonex/intercom/',
+    'module_uri' => 'intercom',
+
+    'db_prefix' => 'bx_intercom_',
+    'class_prefix' => 'BxIntercom',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 0,
+        'update_files' => 1,
+        'update_languages' => 0,
+        'clear_db_cache' => 0,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Intercom',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

+ 13 - 0
modules/boonex/intercom/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 BxIntercomUpdater extends BxDolStudioUpdater
+{
+    function __construct($aConfig)
+    {
+        parent::__construct($aConfig);
+    }
+}

+ 356 - 0
modules/boonex/intercom/updates/12.0.0_12.0.1/source/classes/BxIntercomModule.php

@@ -0,0 +1,356 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Intercom Intercom integration module
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxIntercomModule extends BxDolModule
+{
+    protected $sHostnameAPI = 'https://api.intercom.io';
+
+    function __construct(&$aModule)
+    {
+        parent::__construct($aModule);
+    }
+
+    public function serviceIntegrationCode ()
+    {
+        $sAppId = getParam('bx_intercom_option_app_id');
+        if (!$sAppId)
+            return '';
+
+        $aSettings = array(
+            'app_id' => $sAppId,
+            'hide_default_launcher' => ('on' == getParam('bx_intercom_option_hide_launcher') || 'messenger' == bx_get('i')),
+            'alignment' => getParam('bx_intercom_option_alignment'),
+            'horizontal_padding' => getParam('bx_intercom_option_horizontal_padding'),
+            'vertical_padding' => getParam('bx_intercom_option_vertical_padding'),
+        );
+
+        $oProfile = null;
+        if (isLogged() && ($oProfile = BxDolProfile::getInstance()) && ($oAccountObject = $oProfile->getAccountObject())) {
+            $aInfoProfile = $oProfile->getInfo();
+            $aInfoAccount = $oAccountObject->getInfo();
+            $aProfilesIds = $oAccountObject->getProfilesIds();
+
+            // membership
+            $aMembership = BxDolAcl::getInstance()->getMemberMembershipInfo($oProfile->id());
+
+            // profiles
+            $sProfiles = '';
+            foreach ($aProfilesIds as $iId) {
+                if (!($o = BxDolProfile::getInstance($iId)))
+                    continue;
+                $sProfiles .= $o->getDisplayName() . ', ';
+            }
+            $sProfiles = trim($sProfiles, ', ');
+
+            $aSettings['user_id'] = $oAccountObject->id();
+            $aSettings['name'] = $oProfile->getDisplayName();
+            $aSettings['email'] = $oAccountObject->getEmail();
+            $aSettings['created_at'] = $aInfoAccount['added'];
+
+            $aSettings['link'] = $oProfile->getUrl();
+            $aSettings['email_confirmed'] = $aInfoAccount['email_confirmed'] ? 'yes' : 'no';
+            $aSettings['email_receive_news'] = $aInfoAccount['receive_news'] ? 'yes' : 'no';
+            $aSettings['email_receive_updates'] = $aInfoAccount['receive_updates'] ? 'yes' : 'no';
+
+            $aSettings['membership'] = _t($aMembership['name']) . (isset($aMembership['date_expires']) && $aMembership['date_expires'] ? ' (expires:' . bx_time_utc($aMembership['date_expires']) . ')' : '');
+            $aSettings['status'] = $aInfoProfile['status'];
+            $aSettings['type'] = $aInfoProfile['type'];
+
+            $aSettings['all profiles'] = $sProfiles;
+        }
+
+        bx_alert('bx_intercom', 'integration', $oProfile ? $oProfile->id() : 0, $oProfile ? $oProfile->id() : 0, array('settings' => &$aSettings));
+        
+        $sSettings = json_encode($aSettings);
+
+        return <<<EOS
+
+        <!-- BEGIN Intercom integration -->
+        <script>
+            window.intercomSettings = $sSettings;
+        </script>
+        <script>(function(){var w=window;var ic=w.Intercom;if(typeof ic==="function"){ic('reattach_activator');ic('update',intercomSettings);}else{var d=document;var i=function(){i.c(arguments)};i.q=[];i.c=function(args){i.q.push(args)};w.Intercom=i;function l(){var s=d.createElement('script');s.type='text/javascript';s.async=true;s.src='https://widget.intercom.io/widget/{$sAppId}';var x=d.getElementsByTagName('script')[0];x.parentNode.insertBefore(s,x);}if(w.attachEvent){w.attachEvent('onload',l);}else{w.addEventListener('load',l,false);}}})()</script>
+        <!-- END Intercom integration -->
+
+EOS;
+    }
+
+    /**
+     * remove user from intercom by email or account id
+     */      
+    public function serviceRemoveAccount($mixed)
+    {
+        if (!$mixed)
+            return false;
+
+        if ($mixed && !(int)$mixed) {
+            $sId = BxDolAccount::getID($mixed);
+        } else {
+            $sId = (int)$mixed;
+        }
+        
+        $s = $this->_request('/users?user_id=' . $sId, 'DELETE', array(), $sErrorCurl);
+        if ($sErrorJson = $this->_checkForErrors($s, $sErrorCurl))
+            return false;
+    
+        return true;
+    }
+
+    /**
+     * update user by email or account id
+     */      
+    public function serviceUpdateAccount($sEmail)
+    {
+        if (!$sEmail || !($oAccount = BxDolAccount::getInstance($sEmail)))
+            return false;
+
+        $aUserInfo = $this->_prepareUser($oAccount);
+
+        $s = $this->_request('/users', 'POST', $aUserInfo, $sErrorCurl);
+        if ($sErrorJson = $this->_checkForErrors($s, $sErrorCurl))
+            return false;
+
+        return true;
+    }
+    
+    /**
+     * remove user from intercom by email or account id
+     */      
+    public function actionAccountRemove($sEmail)
+    {
+        if (!isAdmin())
+            die('{}');
+
+        if (!$this->serviceRemoveAccount($sEmail))
+            die(json_encode(array('error' => true, 'message' => "Delete failed")));
+
+        echo json_encode(array('message' => "User was successfully deleted"));
+    }
+
+    /**
+     * update user by email or account id
+     */  
+    public function actionAccountUpdate($sEmail)
+    {
+        if (!isAdmin())
+            die('{}');
+
+        if (!$this->serviceUpdateAccount($sEmail))
+            die(json_encode(array('error' => true, 'message' => "Update failed")));
+
+        echo json_encode(array('message' => "User was successfully updated"));
+    }
+
+    /**
+     * Add members in bulk from local database to Intercom
+     */
+    public function actionBulkAdd($iLimit = 5000)
+    {
+        if (!isAdmin())
+            die('{}');
+
+        $this->serviceBulkAdd($iLimit);
+    }
+
+    public function serviceBulkAdd($iLimit = 5000)
+    {
+        set_time_limit(3600);
+        $aIds = $this->_oDb->getInitialUsers($iLimit);
+        $aChunks = array_chunk($aIds, 10);
+        $iTotal = count($aIds);
+        $iCounter = 0;
+        foreach ($aChunks as $aIds) {
+            $aUsers = array();
+            foreach ($aIds as $iAccountId) {
+                if (!($oAccount = BxDolAccount::getInstance($iAccountId)))
+                    continue;
+                if (!($aUserInfo = $this->_prepareUser($oAccount)))
+                    continue;
+                $aUsers[] = $aUserInfo;
+            }
+            $s = $this->_request('/users/bulk', 'POST', array('users' => $aUsers), $sErrorCurl);
+            if (trim($s) && $sErrorJson = $this->_checkForErrors($s, $sErrorCurl))
+                die($sErrorJson);
+            $iCounter += count($aUsers);
+            header('X-Users-Processed: ' . $iCounter . '/' . $iTotal);
+            flush();
+            sleep(1);
+        }
+        echo json_encode(array('message' => "{$iCounter} users were successfully added"));
+    }
+
+    /**
+     * Test query to return number of users registered in intercom
+     */     
+    public function actionNum()
+    {
+        if (!isAdmin())
+            die('{}');
+
+        $s = $this->_request('/users', 'GET', array(), $sErrorCurl);
+        if ($sErrorJson = $this->_checkForErrors($s, $sErrorCurl))
+            die($sErrorJson);
+
+        $a = json_decode($s);
+        
+        echo json_encode(array(
+            'type' => $a->type,
+            'total_count' => $a->total_count,
+        ));
+    }
+
+    protected function _prepareUser($oAccount)
+    {
+        $oProfile = BxDolProfile::getInstanceByAccount($oAccount->id());
+        if (!$oProfile)
+            return false;
+
+        $aInfoProfile = $oProfile->getInfo();
+        $aInfoAccount = $oAccount->getInfo();
+        $aInfoSession = $this->_oDb->getSessionRowByAccountId($oAccount->id());
+        $aProfilesIds = $oAccount->getProfilesIds();
+
+        // membership
+        $aMembership = BxDolAcl::getInstance()->getMemberMembershipInfo($oProfile->id());
+
+        // profiles
+        $sProfiles = '';
+        foreach ($aProfilesIds as $iId) {
+            if (!($o = BxDolProfile::getInstance($iId)))
+                continue;
+            $sProfiles .= $o->getDisplayName() . ', ';
+        }
+        $sProfiles = trim($sProfiles, ', ');
+
+        $aSettings = array (
+            'user_id' => $oAccount->id(),
+            'name' => $oProfile->getDisplayName(),
+            'email' => $oAccount->getEmail(),
+            'unsubscribed_from_emails' => !$aInfoAccount['receive_news'],
+            'signed_up_at' => $aInfoAccount['added'],
+            //'last_seen_ip' => ?,
+            'last_request_at' => isset($aInfoSession['date']) ? $aInfoSession['date'] : $aInfoAccount['logged'],
+            'custom_attributes' => array (
+                'link' => $oProfile->getUrl(),
+
+                'email_confirmed' => $aInfoAccount['email_confirmed'] ? 'yes' : 'no',
+                'email_receive_news' => $aInfoAccount['receive_news'] ? 'yes' : 'no',
+                'email_receive_updates' => $aInfoAccount['receive_updates'] ? 'yes' : 'no',
+
+                'membership' => _t($aMembership['name']) . (isset($aMembership['date_expires']) && $aMembership['date_expires'] ? ' (expires:' . bx_time_utc($aMembership['date_expires']) . ')' : ''),
+                'status' => $aInfoProfile['status'],
+                'type' => $aInfoProfile['type'],
+
+                'all profiles' => $sProfiles,
+            ),
+        );
+
+        bx_alert('bx_intercom', 'user_info', $oProfile->id(), $oProfile->id(), array('settings' => &$aSettings));
+
+        return $aSettings;
+    }
+
+    /**
+     * @return json error object on error or empty string on success
+     */
+    protected function _checkForErrors($s, $sErrorCurl, $sReturnType = 'json')
+    {
+        if (!$s)
+            return $this->_returnErrors(array('error' => 'curl error: ' . $sErrorCurl), $sReturnType);
+
+        $a = json_decode($s);
+        if (null === $a)
+            return $this->_returnErrors(array('error' => 'json decode failed:' . htmlspecialchars($s)), $sReturnType);
+
+        if (0 === strncmp('error', $a->type, 5)) {
+            $sError = '';
+            foreach ($a->errors as $o)
+                $sError .= $o->code . ": " . $o->message . "\n";
+            return $this->_returnErrors(array('error' => $sError), $sReturnType);
+        }
+
+        return '';
+    }
+
+    protected function _returnErrors($mixed, $sReturnType = 'json')
+    {
+        switch ($sReturnType) {
+            case 'array':
+                return $mixed;
+            case 'json':
+            default:
+                return json_encode($mixed);
+        }
+    }
+
+    /**
+     * Perform JSON request to the API endpoint and get JSON response
+     * @return false on error
+     */
+    protected function _request($sURI, $sMethod, $aData, &$sError)
+    {
+        $sMethod = !empty($sMethod) ? $sMethod : 'GET';
+        $aData = !empty($aData) ? $aData : array();
+
+        $sAppId = getParam('bx_intercom_option_app_id');
+        $sApiKey = getParam('bx_intercom_option_api_key');
+        if (!$sAppId || !$sApiKey) {
+            $sError = "No App ID or API Key";
+            return false;
+        }
+        
+        $r = curl_init();
+    
+        $aHeaders = array(
+            'Accept: application/json',
+        );
+
+        curl_setopt($r, CURLOPT_USERPWD, $sApiKey . ":");
+        curl_setopt($r, CURLOPT_TIMEOUT, 10);
+        curl_setopt($r, CURLOPT_URL, $this->sHostnameAPI . $sURI);
+        curl_setopt($r, CURLOPT_HEADER, 0);
+        curl_setopt($r, CURLOPT_RETURNTRANSFER, 1);
+        curl_setopt($r, CURLOPT_FOLLOWLOCATION, 1);
+
+        if ('POST' == $sMethod) {
+
+            $sDataJson = json_encode($aData); 
+
+            curl_setopt($r, CURLOPT_POST, true);
+            curl_setopt($r, CURLOPT_POSTFIELDS, $sDataJson);
+
+            $aHeaders = array_merge($aHeaders, array(
+                'Content-Type: application/json',
+                'Content-Length: ' . strlen($sDataJson)
+            )); 
+
+        } elseif ('DELETE' == $sMethod) {
+
+            curl_setopt($r, CURLOPT_CUSTOMREQUEST, "DELETE");
+
+        }
+
+        curl_setopt($r, CURLOPT_HTTPHEADER, $aHeaders); 
+
+        $sResult = curl_exec($r);        
+
+        if (false === $sResult) {
+            $sError = curl_error ($r);
+            curl_close($r);
+            return false;
+        }
+
+        curl_close($r);
+        return $sResult;
+    }
+}
+
+/** @} */

+ 68 - 0
modules/boonex/intercom/updates/12.0.0_12.0.1/source/install/config.php

@@ -0,0 +1,68 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Intercom Intercom integration module
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_intercom',
+    'title' => 'Intercom',
+    'note' => 'Intercom integration.',
+    '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/intercom/',
+    'home_uri' => 'intercom',
+
+    'db_prefix' => 'bx_intercom_',
+    'class_prefix' => 'BxIntercom',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Intercom',
+
+    /**
+     * 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(),
+);
+
+/** @} */

+ 51 - 0
modules/boonex/mailchimp/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' => 'Mailchimp',
+    '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/mailchimp/updates/update_12.0.0_12.0.1/',
+    'home_uri' => 'mailchimp_update_1200_1201',
+    
+    'module_dir' => 'boonex/mailchimp/',
+    'module_uri' => 'mailchimp',
+
+    'db_prefix' => 'bx_mailchimp_',
+    'class_prefix' => 'BxMailchimp',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 0,
+        'update_files' => 1,
+        'update_languages' => 0,
+        'clear_db_cache' => 0,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Mailchimp',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

+ 13 - 0
modules/boonex/mailchimp/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 BxMailchimpUpdater extends BxDolStudioUpdater
+{
+    function __construct($aConfig)
+    {
+        parent::__construct($aConfig);
+    }
+}

+ 49 - 0
modules/boonex/mailchimp/updates/12.0.0_12.0.1/source/classes/BxMailchimpAlerts.php

@@ -0,0 +1,49 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Mailchimp Mailchimp integration module
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxMailchimpAlerts extends BxDolAlertsResponse
+{
+    protected $_oModule;
+    function __construct()
+    {
+        parent::__construct();
+        $this->_oModule = BxDolModule::getInstance('bx_mailchimp');
+    }
+
+    public function response($o)
+    {
+        if ('system' == $o->sUnit && 'save_setting' == $o->sAction && 'bx_mailchimp_option_list_id' == $o->aExtras['option']) {
+            $this->_oModule->serviceUpdateMergeFields();
+        }
+        
+        if ('account' == $o->sUnit && 'delete' == $o->sAction) {
+            $this->_oModule->serviceRemoveAccount($o->iObject);
+        }
+
+        if ('account' == $o->sUnit && ('edited' == $o->sAction || 'switch_context' == $o->sAction || 'confirm' == $o->sAction || 'unconfirm' == $o->sAction)) {
+            $this->_oModule->serviceUpdateAccount($o->iObject);
+        }
+        
+        if ('profile' == $o->sUnit && ('delete' == $o->sAction || 'edit' == $o->sAction || 'add' == $o->sAction)) {
+            $oProfile = BxDolProfile::getInstance($o->iObject);
+            $oAccount = $oProfile ? $oProfile->getAccountObject() : null;
+            
+            if ($oAccount) {
+                if ('delete' == $o->sAction && isset($o->aExtras['type']) && 'system' == $o->aExtras['type'])
+                    $this->_oModule->serviceRemoveAccount($oAccount->id());
+                else
+                    $this->_oModule->serviceUpdateAccount($oAccount->id());
+            }
+        }
+    }    
+}
+
+/** @} */

+ 337 - 0
modules/boonex/mailchimp/updates/12.0.0_12.0.1/source/classes/BxMailchimpModule.php

@@ -0,0 +1,337 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Mailchimp Mailchimp integration module
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+define('BX_MAILCHIMP_LIMIT', 5000);
+
+class BxMailchimpModule extends BxDolModule
+{
+    protected $sHostnameAPI = 'https://{dc}.api.mailchimp.com/3.0';                
+    protected $aFields = array(
+        'ACCOUNT_ID' => 'number', 
+        'PROFILE_ID' => 'number',
+        'MEMBERSHIP' => 'text', 
+        'STATUS' => 'text', 
+        'TYPE' => 'text', 
+        'PROFILES' => 'text',
+        'PROFILE_URL' => 'url',
+        'IMAGE_URL' => 'imageurl',
+    );
+
+    function __construct(&$aModule)
+    {
+        parent::__construct($aModule);
+
+        if (($sKey = getParam('bx_mailchimp_option_api_key')) && ($a = explode('-', $sKey)) && !empty($a[1]))
+            $this->sHostnameAPI = str_replace('{dc}', $a[1], $this->sHostnameAPI);
+        else
+            $this->sHostnameAPI = '';
+    }
+
+    public function serviceUpdateMergeFields()
+    {
+        if (!isAdmin() || !($sListId = getParam('bx_mailchimp_option_list_id')))
+            return false;
+
+        foreach ($this->aFields as $sName => $sType) {
+            $s = $this->_request('/lists/' . $sListId . '/merge-fields', 'POST', array('name' => $sName, 'tag' => $sName, 'type' => $sType), $sErrorCurl);
+            if (!($a = $this->_checkForErrors($s, $sErrorCurl)) || isset($a['error']))
+                return false;
+        }
+
+        return true;
+    }
+
+    public function serviceGetLists($bAddEmptyValue = true)
+    {
+        if (!isAdmin())
+            return false;
+
+        $s = $this->_request('/lists?count=100', 'GET', array(), $sErrorCurl);
+        if (!($a = $this->_checkForErrors($s, $sErrorCurl)) || isset($a['error']))
+            return array();
+        
+        if (isset($a['type']) && isset($a['detail']))
+            die(json_encode(array('error' => $a['detail'])));
+
+        if (!isset($a['lists']))
+            return array();
+
+        $aRet = array();
+        foreach ($a['lists'] as $r)
+            $aRet[] = array('key' => $r['id'], 'value' => $r['name']);
+
+        if ($bAddEmptyValue)
+            array_unshift($aRet, _t('_sys_please_select'));
+
+        return $aRet;
+    }
+
+    /**
+     * remove user from mailchimp by email or account id
+     */      
+    public function serviceRemoveAccount($mixed)
+    {
+        return $this->_accountAction($mixed, 'DELETE');
+    }
+
+    /**
+     * update user in mailchimp by email or account id
+     */      
+    public function serviceUpdateAccount($sEmail)
+    {
+        return $this->_accountAction($sEmail, 'PUT');
+    }
+
+    protected function _accountAction($sEmail, $sMethod)
+    {
+        if (!$sEmail || !($oAccount = BxDolAccount::getInstance($sEmail)) || !($sListId = getParam('bx_mailchimp_option_list_id')))
+            return false;
+
+        $aUserInfo = $this->_prepareUser($oAccount);
+
+        $s = $this->_request('/lists/' . $sListId . '/members/' . md5(strtolower($aUserInfo['email_address'])), $sMethod, $aUserInfo, $sErrorCurl);
+        if (!($a = $this->_checkForErrors($s, $sErrorCurl)) || isset($a['error']))
+            return false;
+
+        if (isset($a['type']) && isset($a['detail']))
+            return false;
+        
+        return true;
+    }
+
+    /**
+     * remove user from mailchimp by email or account id
+     */      
+    public function actionAccountRemove($sEmail)
+    {
+        if (!isAdmin())
+            die('{}');
+
+        if (!$this->serviceRemoveAccount($sEmail))
+            die(json_encode(array('error' => true, 'message' => "Delete failed")));
+
+        echo json_encode(array('message' => "User was successfully deleted"));
+    }
+
+    /**
+     * update user by email or account id
+     */  
+    public function actionAccountUpdate($sEmail)
+    {
+        if (!isAdmin())
+            die('{}');
+
+        if (!$this->serviceUpdateAccount($sEmail))
+            die(json_encode(array('error' => true, 'message' => "Update failed")));
+
+        echo json_encode(array('message' => "User was successfully updated"));
+    }
+
+    /**
+     * Add members in bulk from local database to mailchimp
+     */      
+    public function actionBulkAdd($iLimit = BX_MAILCHIMP_LIMIT)
+    {
+        if (!isAdmin() || !($sListId = getParam('bx_mailchimp_option_list_id')))
+            die('{}');
+
+        set_time_limit(3600);
+        $aIds = $this->_oDb->getInitialUsers($iLimit);
+        $aChunks = array_chunk($aIds, 1000);
+        $iTotal = count($aIds);
+        $iCounter = 0;
+        foreach ($aChunks as $aIds) {
+            $aOperations = array();
+            $iTotal2 = 0;
+            foreach ($aIds as $iAccountId) {
+                if (!($oAccount = BxDolAccount::getInstance($iAccountId)))
+                    continue;
+                if (!($aUserInfo = $this->_prepareUser($oAccount)))
+                    continue;
+                $aOperations[] = array(
+                    'method' => 'PUT',
+                    'path' => '/lists/' . $sListId . '/members/' . md5(strtolower($aUserInfo['email_address'])),
+                    'body' => json_encode($aUserInfo),
+                );
+                ++$iTotal2;
+            }
+
+            $s = $this->_request('/batches', 'POST', array('operations' => $aOperations), $sErrorCurl);
+            if (!($a = $this->_checkForErrors($s, $sErrorCurl)) || isset($a['error']))
+                die(json_encode($a));
+
+            if (isset($a['type']) && isset($a['detail']))
+                die(json_encode(array('error' => $a['detail'])));
+        
+            $iCounter += $iTotal2;
+            sleep(1);
+        }
+        
+        echo json_encode(array('message' => _t('_bx_mailchimp_accounts_processed', $iCounter)));
+    }
+
+    /**
+     * Test query to return some stats
+     */     
+    public function actionStats()
+    {
+        if (!isAdmin() || !($sListId = getParam('bx_mailchimp_option_list_id')))
+            die('{}');
+
+        $s = $this->_request('/lists/' . $sListId, 'GET', array(), $sErrorCurl);
+        if (!($a = $this->_checkForErrors($s, $sErrorCurl)) || isset($a['error']))
+            die(json_encode($a));
+
+        if (isset($a['type']) && isset($a['detail']))
+            die(json_encode(array('error' => $a['detail'])));
+        
+        echo json_encode(array(
+            'unsubscribed' => $a['stats']['unsubscribe_count'],
+            'cleaned' => $a['stats']['cleaned_count'],
+            'total' => $a['stats']['member_count'],
+        ));
+    }
+
+    protected function _prepareUser($oAccount)
+    {
+        $oProfile = BxDolProfile::getInstanceByAccount($oAccount->id());
+        if (!$oProfile)
+            return false;
+
+        $aInfoProfile = $oProfile->getInfo();
+        $aInfoAccount = $oAccount->getInfo();
+        //$aInfoSession = $this->_oDb->getSessionRowByAccountId($oAccount->id());
+        $aProfilesIds = $oAccount->getProfilesIds();
+
+        // membership
+        $aMembership = BxDolAcl::getInstance()->getMemberMembershipInfo($oProfile->id());
+
+        // profiles
+        $sProfiles = '';
+        foreach ($aProfilesIds as $iId) {
+            if (!($o = BxDolProfile::getInstance($iId)))
+                continue;
+
+            $sProfiles .= $o->getDisplayName() . ', ';
+        }
+        $sProfiles = trim($sProfiles, ', ');
+        $sEmail = $oAccount->getEmail();
+        $iAccountId = $oAccount->id();
+        $iProfileId = $oProfile->id();
+
+        $aMarkers = array (
+            'FNAME' => $oProfile->getDisplayName(),
+            'ACCOUNT_ID' => $iAccountId,
+            'PROFILE_ID' => $iProfileId,
+            'MEMBERSHIP' => _t($aMembership['name']) . (isset($aMembership['date_expires']) && $aMembership['date_expires'] ? ' (expires:' . bx_time_utc($aMembership['date_expires']) . ')' : ''),
+            'STATUS' => $aInfoProfile['status'],
+            'TYPE' => $aInfoProfile['type'],
+            'PROFILES' => $sProfiles,
+            'PROFILEURL' => $oProfile->getUrl(),
+            'IMAGE_URL' => $oProfile->getAvatar(),
+            'RPASS_URL' => ''
+        );
+
+        if(($sResetPasswordUrl = bx_get_reset_password_link($sEmail)) !== false)
+            $aMarkers['RPASS_URL'] = $sResetPasswordUrl;
+
+        bx_alert($this->_aModule['name'], 'user_fields', $iAccountId, $iProfileId, array('email' => $sEmail, 'markers' => &$aMarkers));	
+
+        return array (
+            'email_address' => $oAccount->getEmail(),
+            'status' => $aInfoAccount['receive_news'] ? 'subscribed' : 'unsubscribed',            
+            'merge_fields' => $aMarkers
+        );
+    }
+
+    /**
+     * @return json error object on error or empty string on success
+     */
+    protected function _checkForErrors($s, $sErrorCurl)
+    {
+        if (!$s)
+            return array('error' => 'curl error: ' . $sErrorCurl);
+
+        $a = json_decode($s, true);
+        if (null === $a)
+            return array('error' => 'json decode failed:' . htmlspecialchars($s));
+
+        return $a;
+    }
+
+    /**
+     * Perform JSON request to the API endpoint and get JSON response
+     * @return false on error
+     */
+    protected function _request($sURI, $sMethod, $aData, &$sError)
+    {
+        $sMethod = !empty($sMethod) ? $sMethod : 'GET';
+        $aData = !empty($aData) ? $aData : array();
+
+        $sApiKey = getParam('bx_mailchimp_option_api_key');
+        if (!$sApiKey || !$this->sHostnameAPI) {
+            $sError = "No API Key or hostname isn't configured";
+            return false;
+        }
+        
+        $r = curl_init();
+    
+        $aHeaders = array(
+            'Accept: application/json',
+        );
+
+        curl_setopt($r, CURLOPT_USERPWD, "user:" . $sApiKey);
+        curl_setopt($r, CURLOPT_TIMEOUT, 30);
+        curl_setopt($r, CURLOPT_URL, $this->sHostnameAPI . $sURI);
+        curl_setopt($r, CURLOPT_HEADER, 0);
+        curl_setopt($r, CURLOPT_RETURNTRANSFER, 1);
+        curl_setopt($r, CURLOPT_FOLLOWLOCATION, 1);
+
+        if ('POST' == $sMethod || 'PUT' == $sMethod || 'PATCH' == $sMethod) {
+
+            $sDataJson = json_encode($aData); 
+
+            if ('POST' == $sMethod)
+                curl_setopt($r, CURLOPT_POST, true);
+            else
+                curl_setopt($r, CURLOPT_CUSTOMREQUEST, $sMethod);
+
+            curl_setopt($r, CURLOPT_POSTFIELDS, $sDataJson);
+
+            $aHeaders = array_merge($aHeaders, array(
+                'Content-Type: application/json',
+                'Content-Length: ' . strlen($sDataJson)
+            )); 
+
+        } elseif ('DELETE' == $sMethod) {
+
+            curl_setopt($r, CURLOPT_CUSTOMREQUEST, "DELETE");
+
+        }
+
+        // $aHeaders[] = 'X-Trigger-Error: APIKeyMissing'; // test error handling
+
+        curl_setopt($r, CURLOPT_HTTPHEADER, $aHeaders); 
+
+        $sResult = curl_exec($r);        
+
+        if (false === $sResult) {
+            $sError = curl_error ($r);
+            curl_close($r);
+            return false;
+        }
+
+        curl_close($r);
+        return $sResult;
+    }
+}
+
+/** @} */

+ 68 - 0
modules/boonex/mailchimp/updates/12.0.0_12.0.1/source/install/config.php

@@ -0,0 +1,68 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Mailchimp Mailchimp integration module
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_mailchimp',
+    'title' => 'Mailchimp',
+    'note' => 'Mailchimp integration.',
+    '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/mailchimp/',
+    'home_uri' => 'mailchimp',
+
+    'db_prefix' => 'bx_mailchimp_',
+    'class_prefix' => 'BxMailchimp',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Mailchimp',
+
+    /**
+     * 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(),
+);
+
+/** @} */

+ 51 - 0
modules/boonex/market/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' => 'Market',
+    '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/market/updates/update_12.0.2_12.0.3/',
+    'home_uri' => 'market_update_1202_1203',
+
+    'module_dir' => 'boonex/market/',
+    'module_uri' => 'market',
+
+    'db_prefix' => 'bx_market_',
+    'class_prefix' => 'BxMarket',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_files' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Market',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

+ 13 - 0
modules/boonex/market/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 BxMarketUpdater extends BxDolStudioUpdater
+{
+    function __construct($aConfig)
+    {
+        parent::__construct($aConfig);
+    }
+}

+ 8 - 0
modules/boonex/market/updates/12.0.2_12.0.3/install/langs/en.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources name="en" flag="gb" title="English">
+    <string_upd name="_bx_market_form_entry_input_price_recurring"><![CDATA[Price]]></string_upd>
+    <string_upd name="_bx_market_form_entry_input_price_recurring_inf"><![CDATA[Leave empty to make the product free.]]></string_upd>
+	<string_upd name="_bx_market_menu_item_title_system_subscribe"><![CDATA[Subscribe]]></string_upd>
+    <string_upd name="_bx_market_menu_item_title_subscribe"><![CDATA[Subscribe for {0}{1}/{2}]]></string_upd>
+	<string_upd name="_bx_market_txt_price_recurring"><![CDATA[Subscribe for {0}{1}/{2}]]></string_upd>
+</resources>

+ 4 - 0
modules/boonex/market/updates/12.0.2_12.0.3/install/sql/enable.sql

@@ -0,0 +1,4 @@
+-- PRIVACY 
+DELETE FROM `sys_objects_privacy` WHERE `object`='bx_market_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_market_allow_view_favorite_list', 'bx_market', 'view_favorite_list', '_bx_market_form_entry_input_allow_view_favorite_list', '3', 'all', 'bx_market_favorites_lists', 'id', 'author_id', '', '');

+ 140 - 0
modules/boonex/market/updates/12.0.2_12.0.3/source/install/config.php

@@ -0,0 +1,140 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Market Market
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_market',
+    'title' => 'Market',
+    'note' => 'Market 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/market/',
+    'home_uri' => 'market',
+
+    'db_prefix' => 'bx_market_',
+    'class_prefix' => 'BxMarket',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Market',
+
+	/**
+     * 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_market_files',
+        'bx_market_photos'
+    ),
+
+    /**
+     * Transcoders.
+     */
+    'transcoders' => array(
+        'bx_market_icon',
+        'bx_market_thumb',
+        'bx_market_cover',
+        'bx_market_screenshot',
+		'bx_market_preview',
+        'bx_market_gallery',
+    ),
+
+    /**
+     * Extended Search Forms.
+     */
+    'esearches' => array(
+        'bx_market',
+    	'bx_market_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_page_triggers' => 1,
+    	'process_menu_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'
+    ),
+
+);
+
+/** @} */

+ 466 - 0
modules/boonex/market/updates/12.0.2_12.0.3/source/install/langs/en.xml

@@ -0,0 +1,466 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources name="en" flag="gb" title="English">
+
+	<string name="_bx_market"><![CDATA[Market]]></string>
+	<string name="_bx_market_cmts"><![CDATA[Market's Reviews]]></string>
+        <string name="_bx_market_reactions"><![CDATA[Market's Reactions]]></string>
+
+	<string name="_bx_market_option_enable_recurring"><![CDATA[Allow to sell subscriptions]]></string>
+	<string name="_bx_market_option_recurring_reserve"><![CDATA[Reserve (in days) to accept and process recurring payment notification]]></string>
+	<string name="_bx_market_option_summary_chars"><![CDATA[Number of characters in auto-cropped product summary]]></string>
+	<string name="_bx_market_option_plain_summary_chars"><![CDATA[Number of characters in plain product description when product hasn't thumb]]></string>
+	<string name="_bx_market_option_per_page_browse"><![CDATA[Number of items per page]]></string>
+	<string name="_bx_market_option_per_page_profile"><![CDATA[Number of items on profile page]]></string>
+	<string name="_bx_market_option_rss_num"><![CDATA[Number of items in RSS feed]]></string>
+	<string name="_bx_market_option_searchable_fields"><![CDATA[Searchable fields for keyword search]]></string>
+  <string name="_bx_market_option_per_page_for_favorites_lists"><![CDATA[Number of favorite lists per page]]></string>
+
+	<string name="_bx_market_form_entry"><![CDATA[Product]]></string>
+	<string name="_bx_market_form_entry_display_add"><![CDATA[Add Product]]></string>
+	<string name="_bx_market_form_entry_display_edit"><![CDATA[Edit Product]]></string>
+	<string name="_bx_market_form_entry_display_delete"><![CDATA[Delete Product]]></string>
+	<string name="_bx_market_form_entry_display_view"><![CDATA[View Product]]></string>
+	<string name="_bx_market_form_entry_display_view_full"><![CDATA[Full View Product]]></string>
+	<string name="_bx_market_form_entry_input_author"><![CDATA[Author]]></string>
+	<string name="_bx_market_form_entry_input_sys_do_submit"><![CDATA[Submit]]></string>
+	<string name="_bx_market_form_entry_input_do_submit"><![CDATA[Submit]]></string>
+	<string name="_bx_market_form_entry_input_sys_do_publish"><![CDATA[Publish]]></string>
+	<string name="_bx_market_form_entry_input_do_publish"><![CDATA[Publish]]></string>
+	<string name="_bx_market_form_entry_input_sys_title"><![CDATA[Title]]></string>
+	<string name="_bx_market_form_entry_input_title"><![CDATA[Title]]></string>
+	<string name="_bx_market_form_entry_input_title_err"><![CDATA[Title is essential. Please, fill in this field]]></string>
+	<string name="_bx_market_form_entry_input_sys_name"><![CDATA[Name]]></string>
+	<string name="_bx_market_form_entry_input_name"><![CDATA[Name]]></string>
+	<string name="_bx_market_form_entry_input_name_err"><![CDATA[Name should be unique and is needed for internal usage. Please, fill in this field]]></string>
+	<string name="_bx_market_form_entry_input_sys_cat"><![CDATA[Category]]></string>
+	<string name="_bx_market_form_entry_input_cat"><![CDATA[Category]]></string>
+    <string name="_bx_market_form_entry_input_cat_err"><![CDATA[Please select category]]></string>
+    <string name="_bx_market_form_entry_input_sys_price_single"><![CDATA[Price]]></string>
+	<string name="_bx_market_form_entry_input_price_single"><![CDATA[Price]]></string>
+    <string name="_bx_market_form_entry_input_price_single_inf"><![CDATA[Leave empty to make the product free.]]></string>
+    <string name="_bx_market_form_entry_input_sys_price_recurring"><![CDATA[Recurring price]]></string>
+	<string name="_bx_market_form_entry_input_price_recurring"><![CDATA[Price]]></string>
+    <string name="_bx_market_form_entry_input_price_recurring_inf"><![CDATA[Leave empty to make the product free.]]></string>
+    <string name="_bx_market_form_entry_input_sys_duration_recurring"><![CDATA[Billing period]]></string>
+    <string name="_bx_market_form_entry_input_duration_recurring"><![CDATA[Billing period]]></string>
+    <string name="_bx_market_form_entry_input_sys_trial_recurring"><![CDATA[Recurring trial]]></string>
+    <string name="_bx_market_form_entry_input_trial_recurring"><![CDATA[Trial period]]></string>
+    <string name="_bx_market_form_entry_input_trial_recurring_inf"><![CDATA[The number of days new customers should receive a free trial. Leave empty to disable trial period.]]></string>
+    <string name="_bx_market_form_entry_input_sys_header_beg_single"><![CDATA[One-time payment: begin]]></string>
+    <string name="_bx_market_form_entry_input_header_beg_single"><![CDATA[One-time payment]]></string>
+    <string name="_bx_market_form_entry_input_sys_header_beg_recurring"><![CDATA[Recurring payment: begin]]></string>
+    <string name="_bx_market_form_entry_input_header_beg_recurring"><![CDATA[Recurring payment]]></string>
+    <string name="_bx_market_form_entry_input_sys_header_beg_privacy"><![CDATA[Privacy: begin]]></string>
+    <string name="_bx_market_form_entry_input_header_beg_privacy"><![CDATA[Privacy]]></string>
+    <string name="_bx_market_form_entry_input_sys_header_beg_notes"><![CDATA[Notes: begin]]></string>
+    <string name="_bx_market_form_entry_input_header_beg_notes"><![CDATA[Notes]]></string>
+    <string name="_bx_market_form_entry_input_sys_header_beg_other"><![CDATA[Other: begin]]></string>
+    <string name="_bx_market_form_entry_input_header_beg_other"><![CDATA[Other]]></string>
+    <string name="_bx_market_form_entry_input_sys_header_end_single"><![CDATA[One-time payment: end]]></string>
+    <string name="_bx_market_form_entry_input_sys_header_end_recurring"><![CDATA[Recurring payment: end]]></string>
+    <string name="_bx_market_form_entry_input_sys_header_end_privacy"><![CDATA[Privacy: end]]></string>
+    <string name="_bx_market_form_entry_input_sys_header_end_notes"><![CDATA[Notes: end]]></string>
+    <string name="_bx_market_form_entry_input_sys_header_end_other"><![CDATA[Other: end]]></string>
+	<string name="_bx_market_form_entry_input_sys_text"><![CDATA[Text]]></string>
+	<string name="_bx_market_form_entry_input_text"><![CDATA[Text]]></string>
+	<string name="_bx_market_form_entry_input_text_err"><![CDATA[Text field can't be empty]]></string>
+	<string name="_bx_market_form_entry_input_sys_notes"><![CDATA[Notes]]></string>
+	<string name="_bx_market_form_entry_input_notes"><![CDATA[Notes]]></string>
+        <string name="_bx_market_form_entry_input_notes_inf"><![CDATA[Will be shown on product's info page.]]></string>
+        <string name="_bx_market_form_entry_input_sys_notes_purchased"><![CDATA[After purchase notes]]></string>
+        <string name="_bx_market_form_entry_input_notes_purchased"><![CDATA[After purchase notes]]></string>
+        <string name="_bx_market_form_entry_input_notes_purchased_inf"><![CDATA[Will be attached to email message which is sent to buyer after purchase.]]></string>
+	<string name="_bx_market_form_entry_input_sys_delete_confirm"><![CDATA[Delete confirmation]]></string>
+	<string name="_bx_market_form_entry_input_delete_confirm"><![CDATA[I am sure I want to delete this product]]></string>
+	<string name="_bx_market_form_entry_input_delete_confirm_info"><![CDATA[This action can not be undone]]></string>
+	<string name="_bx_market_form_entry_input_delete_confirm_error"><![CDATA[Please check this checkbox if you really want to delete the product]]></string>
+	<string name="_bx_market_form_entry_input_sys_pictures"><![CDATA[Pictures]]></string>
+	<string name="_bx_market_form_entry_input_pictures"><![CDATA[Pictures]]></string>
+	<string name="_bx_market_form_entry_input_pictures_title"><![CDATA[Title]]></string>
+	<string name="_bx_market_form_entry_input_pictures_use_as_thumb"><![CDATA[Icon]]></string>
+	<string name="_bx_market_form_entry_input_pictures_use_as_cover"><![CDATA[Header Image]]></string>
+	<string name="_bx_market_form_entry_input_sys_files"><![CDATA[Files]]></string>
+	<string name="_bx_market_form_entry_input_files"><![CDATA[Files]]></string>
+	<string name="_bx_market_form_entry_input_files_use_as_main"><![CDATA[Use as Main]]></string>
+	<string name="_bx_market_form_entry_input_files_name"><![CDATA[Name:]]></string>
+	<string name="_bx_market_form_entry_input_files_version"><![CDATA[Version:]]></string>
+	<string name="_bx_market_form_entry_input_files_type"><![CDATA[Type:]]></string>
+	<string name="_bx_market_form_entry_input_files_type_version"><![CDATA[version]]></string>
+	<string name="_bx_market_form_entry_input_files_type_update"><![CDATA[update]]></string>
+	<string name="_bx_market_form_entry_input_files_version_from"><![CDATA[Version from:]]></string>
+	<string name="_bx_market_form_entry_input_files_version_to"><![CDATA[Version to:]]></string>
+	<string name="_bx_market_form_entry_input_files_version_from_x_to_y"><![CDATA[{0} to {1}]]></string>
+    <string name="_bx_market_form_entry_input_sys_allow_view_to"><![CDATA[Who can view]]></string>
+    <string name="_bx_market_form_entry_input_allow_view_to"><![CDATA[Who can view]]></string>
+    <string name="_bx_market_form_entry_input_allow_view_favorite_list"><![CDATA[Visibility]]></string>
+    <string name="_bx_market_form_entry_input_sys_allow_purchase_to"><![CDATA[Who can purchase]]></string>
+    <string name="_bx_market_form_entry_input_allow_purchase_to"><![CDATA[Who can purchase]]></string>
+    <string name="_bx_market_form_entry_input_sys_allow_comment_to"><![CDATA[Who can review]]></string>
+    <string name="_bx_market_form_entry_input_allow_comment_to"><![CDATA[Who can review]]></string>
+    <string name="_bx_market_form_entry_input_sys_allow_vote_to"><![CDATA[Who can vote]]></string>
+    <string name="_bx_market_form_entry_input_allow_vote_to"><![CDATA[Who can vote]]></string>
+    <string name="_bx_market_form_entry_input_sys_added"><![CDATA[Created]]></string>
+    <string name="_bx_market_form_entry_input_added"><![CDATA[Created]]></string>
+    <string name="_bx_market_form_entry_input_sys_changed"><![CDATA[Updated]]></string>
+    <string name="_bx_market_form_entry_input_changed"><![CDATA[Updated]]></string>
+    <string name="_bx_market_form_entry_input_sys_warning_single"><![CDATA[Warning for single payments]]></string>
+    <string name="_bx_market_form_entry_input_sys_warning_recurring"><![CDATA[Warning for recurring payments]]></string>
+    <string name="_bx_market_form_entry_input_sys_subentries"><![CDATA[Subproducts]]></string>
+    <string name="_bx_market_form_entry_input_subentries"><![CDATA[Subproducts]]></string>
+    <string name="_bx_market_form_entry_input_subentries_inf"><![CDATA[Leave empty if you don't want to create association.]]></string>
+    <string name="_bx_market_form_entry_input_subentries_placeholder"><![CDATA[Type product name here...]]></string>
+    <string name="_bx_market_form_entry_input_files_version_caption_latest"><![CDATA[Latest version]]></string>
+    <string name="_bx_market_form_entry_input_files_version_caption_version"><![CDATA[Older versions]]></string>
+    <string name="_bx_market_form_entry_input_files_version_caption_update"><![CDATA[Updates]]></string>
+
+  <string name="_bx_market_acl_action_create_entry"><![CDATA[Create Product]]></string>
+	<string name="_bx_market_acl_action_delete_entry"><![CDATA[Delete Product]]></string>
+	<string name="_bx_market_acl_action_download_entry"><![CDATA[Download Product]]></string>
+	<string name="_bx_market_acl_action_view_entry"><![CDATA[View Product]]></string>
+	<string name="_bx_market_acl_action_set_cover"><![CDATA[Set Product Cover]]></string>
+	<string name="_bx_market_acl_action_set_subentries"><![CDATA[Set Product Subproducts]]></string>
+	<string name="_bx_market_acl_action_set_thumb"><![CDATA[Set Product Thumbnail]]></string>
+	<string name="_bx_market_acl_action_edit_any_entry"><![CDATA[Edit Any Product]]></string>
+
+	<string name="_bx_market_privacy_group_customers"><![CDATA[Customers]]></string>
+
+	<string name="_bx_market_page_title_sys_create_entry"><![CDATA[New Product]]></string>
+	<string name="_bx_market_page_title_create_entry"><![CDATA[New Product]]></string>
+	<string name="_bx_market_page_block_title_create_entry"><![CDATA[New Product]]></string>
+	<string name="_bx_market_page_title_sys_edit_entry"><![CDATA[Edit Product]]></string>
+	<string name="_bx_market_page_title_edit_entry"><![CDATA[Edit Product]]></string>
+	<string name="_bx_market_page_block_title_edit_entry"><![CDATA[Edit Product]]></string>
+    <string name="_bx_market_page_title_sys_delete_entry"><![CDATA[Delete Product]]></string>
+    <string name="_bx_market_page_title_delete_entry"><![CDATA[Delete Product]]></string>
+    <string name="_bx_market_page_block_title_delete_entry"><![CDATA[Delete Product]]></string>
+	<string name="_bx_market_page_title_sys_download_entry"><![CDATA[Download Product]]></string>
+    <string name="_bx_market_page_title_download_entry"><![CDATA[Download Product]]></string>
+    <string name="_bx_market_page_block_title_download_entry"><![CDATA[Download Product]]></string>
+	<string name="_bx_market_page_title_sys_view_entry"><![CDATA[View Product]]></string>
+	<string name="_bx_market_page_title_view_entry"><![CDATA[{title}]]></string>
+	<string name="_bx_market_page_block_title_entry_text"><![CDATA[Product Overview]]></string>
+	<string name="_bx_market_page_title_browse"><![CDATA[Products]]></string>
+	<string name="_bx_market_page_title_search_results"><![CDATA[Products matching "{0}"]]></string>
+	<string name="_bx_market_page_title_browse_by_author"><![CDATA[Products of {display_name}]]></string>
+  <string name="_bx_market_page_title_browse_by_context"><![CDATA[Products in {display_name}]]></string>
+	<string name="_bx_market_page_title_browse_featured"><![CDATA[Featured Products]]></string>
+    <string name="_bx_market_page_title_browse_latest"><![CDATA[Latest Products]]></string>
+    <string name="_bx_market_page_title_browse_popular"><![CDATA[Popular Products]]></string>
+    <string name="_bx_market_page_title_browse_top"><![CDATA[Top Products]]></string>
+    <string name="_bx_market_page_title_browse_updated"><![CDATA[Updated Products]]></string>
+    <string name="_bx_market_page_title_browse_category"><![CDATA[Products by category: {0}]]></string>
+    <string name="_bx_market_page_title_browse_keyword"><![CDATA[Products by hashtag: {0}]]></string>
+    <string name="_bx_market_page_title_sys_home"><![CDATA[Market Home]]></string>
+    <string name="_bx_market_page_title_home"><![CDATA[Market]]></string>
+    <string name="_bx_market_page_block_title_featured_entries"><![CDATA[Featured Products]]></string>
+    <string name="_bx_market_page_block_title_featured_entries_view_extended"><![CDATA[Featured Products (Extended View)]]></string>
+    <string name="_bx_market_page_block_title_featured_entries_view_full"><![CDATA[Featured Products (Full View)]]></string>
+    <string name="_bx_market_page_block_title_latest_entries"><![CDATA[Latest Products]]></string>
+    <string name="_bx_market_page_block_title_latest_entries_view_extended"><![CDATA[Latest Products (Extended View)]]></string>
+    <string name="_bx_market_page_block_title_latest_entries_view_full"><![CDATA[Latest Products (Full View)]]></string>
+    <string name="_bx_market_page_block_title_entry_social_sharing"><![CDATA[Share]]></string>
+    <string name="_bx_market_page_block_title_entry_author"><![CDATA[Vendor]]></string>
+    <string name="_bx_market_page_block_title_entry_author_entries"><![CDATA[More Products From {0}]]></string>
+    <string name="_bx_market_page_block_title_entry_actions"><![CDATA[Actions]]></string>
+    <string name="_bx_market_page_block_title_entry_breadcrumb"><![CDATA[Breadcrumb]]></string>
+    <string name="_bx_market_page_block_title_entry_comments"><![CDATA[Reviews]]></string>
+    <string name="_bx_market_page_block_title_entry_comments_link"><![CDATA[Reviews to <a href="{entry_link}">{title}</a>]]></string>
+    <string name="_bx_market_page_block_title_entry_comments_n"><![CDATA[Reviews ({0})]]></string>
+    <string name="_bx_market_page_block_title_entry_info"><![CDATA[Info]]></string>
+    <string name="_bx_market_page_block_title_entry_info_link"><![CDATA[<a href="{entry_link}">{title}</a> Info]]></string>
+    <string name="_bx_market_page_block_title_entry_location"><![CDATA[Location]]></string>
+    <string name="_bx_market_page_block_title_entry_attachments"><![CDATA[Attachments]]></string>
+    <string name="_bx_market_page_block_title_entry_all_actions"><![CDATA[All Actions]]></string>
+    <string name="_bx_market_page_block_title_entry_rating"><![CDATA[Rating]]></string>
+    <string name="_bx_market_page_title_sys_entries_latest"><![CDATA[Latest Products]]></string>
+    <string name="_bx_market_page_title_entries_latest"><![CDATA[Latest Products]]></string>
+    <string name="_bx_market_page_title_sys_entries_featured"><![CDATA[Featured Products]]></string>
+    <string name="_bx_market_page_title_entries_featured"><![CDATA[Featured Products]]></string>
+    <string name="_bx_market_page_title_sys_entries_popular"><![CDATA[Popular Products]]></string>
+    <string name="_bx_market_page_title_entries_popular"><![CDATA[Popular Products]]></string>
+    <string name="_bx_market_page_title_sys_entries_top"><![CDATA[Top Products]]></string>
+    <string name="_bx_market_page_title_entries_top"><![CDATA[Top Products]]></string>
+    <string name="_bx_market_page_title_sys_entries_updated"><![CDATA[Updated Products]]></string>
+    <string name="_bx_market_page_title_entries_updated"><![CDATA[Updated Products]]></string>
+    <string name="_bx_market_page_block_title_popular_entries"><![CDATA[Popular Products]]></string>
+    <string name="_bx_market_page_block_title_popular_entries_view_extended"><![CDATA[Popular Products (Extended View)]]></string>
+    <string name="_bx_market_page_block_title_popular_entries_view_full"><![CDATA[Popular Products (Full View)]]></string>
+    <string name="_bx_market_page_block_title_top_entries"><![CDATA[Top Products]]></string>
+    <string name="_bx_market_page_block_title_updated_entries"><![CDATA[Updated Products]]></string>
+    <string name="_bx_market_page_block_title_updated_entries_view_extended"><![CDATA[Updated Products (Extended View)]]></string>
+    <string name="_bx_market_page_block_title_updated_entries_view_full"><![CDATA[Updated Products (Full View)]]></string>
+    <string name="_bx_market_page_block_title_favorites_entries"><![CDATA["{title}" List]]></string>
+    <string name="_bx_market_page_block_title_favorites_entries_info"><![CDATA[Info]]></string>
+	<string name="_bx_market_page_block_title_sys_entry_context"><![CDATA[Posted in]]></string>
+    <string name="_bx_market_page_block_title_entry_context"><![CDATA[Posted in]]></string>
+	
+    <string name="_bx_market_page_title_sys_view_entry_comments"><![CDATA[Product Reviews]]></string>
+    <string name="_bx_market_page_title_view_entry_comments"><![CDATA[Reviews to {title}]]></string>
+    <string name="_bx_market_page_title_sys_view_entry_info"><![CDATA[Product Info]]></string>
+    <string name="_bx_market_page_title_view_entry_info"><![CDATA[{title} Info]]></string>
+    <string name="_bx_market_page_title_sys_entries_of_author"><![CDATA[Products of author]]></string>
+    <string name="_bx_market_page_title_entries_of_author"><![CDATA[Products by {display_name}]]></string>
+    <string name="_bx_market_page_title_sys_entries_in_context"><![CDATA[Products in context]]></string>
+    <string name="_bx_market_page_title_entries_in_context"><![CDATA[Products in {display_name}]]></string>
+    <string name="_bx_market_page_block_title_favorites_of_author"><![CDATA[Favorites by <a href="{profile_link}">{display_name}</a>]]></string>
+    <string name="_bx_market_page_block_title_sys_favorites_of_author"><![CDATA[Favorites of author]]></string>
+    <string name="_bx_market_page_block_title_entries_of_author"><![CDATA[Products by <a href="{profile_link}">{display_name}</a>]]></string>
+    <string name="_bx_market_page_block_title_sys_entries_of_author"><![CDATA[Products of author]]></string>
+    <string name="_bx_market_page_block_title_entries_in_context"><![CDATA[Products in <a href="{profile_link}">{display_name}</a>]]></string>
+    <string name="_bx_market_page_block_title_sys_entries_in_context"><![CDATA[Products in context]]></string>
+    <string name="_bx_market_page_block_title_entries_actions"><![CDATA[Products actions]]></string>
+    <string name="_bx_market_page_block_title_browse_cmts"><![CDATA[Products' Reviews]]></string>
+	<string name="_bx_market_page_title_sys_manage"><![CDATA[Manage Own Products]]></string>
+	<string name="_bx_market_page_title_sys_manage_administration"><![CDATA[Manage All Products]]></string>
+	<string name="_bx_market_page_title_manage"><![CDATA[Manage Products]]></string>
+	<string name="_bx_market_page_block_title_system_manage"><![CDATA[Manage Own Products]]></string>
+	<string name="_bx_market_page_block_title_system_manage_administration"><![CDATA[Manage All Products]]></string>
+	<string name="_bx_market_page_block_title_manage"><![CDATA[Manage Products]]></string>    
+	<string name="_bx_market_page_block_title_popular_keywords"><![CDATA[Popular Hashtags]]></string>
+	<string name="_bx_market_page_block_title_cats"><![CDATA[Products Categories]]></string>
+	<string name="_bx_market_page_title_sys_entries_categories"><![CDATA[Categories]]></string>
+    <string name="_bx_market_page_title_entries_categories"><![CDATA[Categories]]></string>
+    <string name="_bx_market_page_block_title_categories_entries"><![CDATA[Products]]></string>
+    
+    <string name="_bx_market_page_title_sys_licenses_administration"><![CDATA[Licenses]]></string>
+    <string name="_bx_market_page_title_licenses_administration"><![CDATA[Licenses]]></string>
+    <string name="_bx_market_page_block_title_licenses_administration"><![CDATA[Licenses]]></string>
+    <string name="_bx_market_page_title_sys_licenses"><![CDATA[Licenses]]></string>
+    <string name="_bx_market_page_title_licenses"><![CDATA[Licenses]]></string>
+    <string name="_bx_market_page_block_title_licenses"><![CDATA[Licenses]]></string>
+    <string name="_bx_market_page_block_title_licenses_note"><![CDATA[Note]]></string>
+    <string name="_bx_market_page_block_content_licenses_note"><![CDATA[The licenses are for reference only. There is no need to "register" them, as you can simply download and install licensed UNA apps directly from your site Studio Apps store.]]></string>
+    <string name="_bx_market_page_block_title_sys_view_profile"><![CDATA[User Products]]></string>
+    <string name="_bx_market_page_block_title_view_profile"><![CDATA[{display_name} Products]]></string>
+    <string name="_bx_market_page_title_sys_entries_search"><![CDATA[Search]]></string>
+    <string name="_bx_market_page_title_entries_search"><![CDATA[Search]]></string>
+    <string name="_bx_market_page_title_sys_entries_favorites"><![CDATA[Favorives Products]]></string>
+    <string name="_bx_market_page_title_entries_favorites"><![CDATA[Favorives Products]]></string>
+    <string name="_bx_market_page_block_title_search_form"><![CDATA[Search Form]]></string>
+    <string name="_bx_market_page_block_title_search_results"><![CDATA[Search Results]]></string>
+    <string name="_bx_market_page_block_title_search_form_cmts"><![CDATA[Comments Search Form]]></string>
+    <string name="_bx_market_page_block_title_search_results_cmts"><![CDATA[Comments Search Results]]></string>
+    <string name="_bx_market_page_block_title_sys_recent_entries_view_showcase"><![CDATA[Latest Products (Showcase View)]]></string>
+    <string name="_bx_market_page_block_title_recent_entries_view_showcase"><![CDATA[Latest Products]]></string>
+    <string name="_bx_market_page_block_title_sys_popular_entries_view_showcase"><![CDATA[Popular Products (Showcase View)]]></string>
+    <string name="_bx_market_page_block_title_popular_entries_view_showcase"><![CDATA[Popular Products]]></string>
+    <string name="_bx_market_page_block_title_sys_featured_entries_view_showcase"><![CDATA[Featured Products (Showcase View)]]></string>
+    <string name="_bx_market_page_block_title_featured_entries_view_showcase"><![CDATA[Featured Products]]></string>
+
+    <string name="_bx_market_menu_set_title_view_entry"><![CDATA[Product Actions]]></string>
+    <string name="_bx_market_menu_title_view_entry"><![CDATA[Product Actions]]></string>
+    <string name="_bx_market_menu_set_title_view_entry_more"><![CDATA[Product More Actions]]></string>
+    <string name="_bx_market_menu_title_view_entry_more"><![CDATA[Product More Actions]]></string>
+    <string name="_bx_market_menu_title_submenu"><![CDATA[Market Submenu]]></string>
+    <string name="_bx_market_menu_set_title_submenu"><![CDATA[Market Submenu]]></string>
+    <string name="_bx_market_menu_item_title_system_create_entry"><![CDATA[Product]]></string>
+    <string name="_bx_market_menu_item_title_create_entry"><![CDATA[Product]]></string>
+    <string name="_bx_market_menu_item_title_system_edit_entry"><![CDATA[Edit Product]]></string>
+    <string name="_bx_market_menu_item_title_edit_entry"><![CDATA[Edit]]></string>
+    <string name="_bx_market_menu_item_title_system_delete_entry"><![CDATA[Delete Product]]></string>
+    <string name="_bx_market_menu_item_title_delete_entry"><![CDATA[Delete]]></string>
+    <string name="_bx_market_menu_item_title_system_add_to_cart"><![CDATA[Add to Cart]]></string>
+    <string name="_bx_market_menu_item_title_add_to_cart"><![CDATA[Buy for {0}{1}]]></string>
+    <string name="_bx_market_menu_item_title_system_subscribe"><![CDATA[Subscribe]]></string>
+    <string name="_bx_market_menu_item_title_subscribe"><![CDATA[Subscribe for {0}{1}/{2}]]></string>
+    <string name="_bx_market_menu_item_title_system_download"><![CDATA[Download Product]]></string>
+    <string name="_bx_market_menu_item_title_download"><![CDATA[Download]]></string>
+    <string name="_bx_market_menu_item_title_system_product_more"><![CDATA[More Actions]]></string>
+    <string name="_bx_market_menu_item_title_product_more"><![CDATA[]]></string>
+    <string name="_bx_market_menu_item_title_system_unhide_entry"><![CDATA[Unhide Product]]></string>
+    <string name="_bx_market_menu_item_title_unhide_entry"><![CDATA[Publish]]></string>
+    <string name="_bx_market_menu_item_title_system_hide_entry"><![CDATA[Hide Product]]></string>
+    <string name="_bx_market_menu_item_title_hide_entry"><![CDATA[Hide]]></string>
+    <string name="_bx_market_menu_item_title_system_entries_home"><![CDATA[Market]]></string>
+    <string name="_bx_market_menu_item_title_entries_home"><![CDATA[Market]]></string>
+    <string name="_bx_market_menu_item_title_system_entries_categories"><![CDATA[Categories]]></string>
+    <string name="_bx_market_menu_item_title_entries_categories"><![CDATA[Categories]]></string>
+    <string name="_bx_market_menu_item_title_system_entries_public"><![CDATA[Storefront]]></string>
+    <string name="_bx_market_menu_item_title_entries_public"><![CDATA[Storefront]]></string>
+    <string name="_bx_market_menu_item_title_system_entries_search"><![CDATA[Search]]></string>
+    <string name="_bx_market_menu_item_title_entries_search"><![CDATA[Search]]></string>
+    <string name="_bx_market_menu_item_title_system_entries_manage"><![CDATA[Manage Products]]></string>
+    <string name="_bx_market_menu_item_title_entries_manage"><![CDATA[Manage]]></string>
+    <string name="_bx_market_menu_item_title_system_entries_latest"><![CDATA[Latest Products]]></string>
+    <string name="_bx_market_menu_item_title_entries_latest"><![CDATA[Latest]]></string>
+    <string name="_bx_market_menu_item_title_system_entries_featured"><![CDATA[Featured Products]]></string>
+    <string name="_bx_market_menu_item_title_entries_featured"><![CDATA[Featured]]></string>
+    <string name="_bx_market_menu_item_title_system_entries_popular"><![CDATA[Popular Products]]></string>
+    <string name="_bx_market_menu_item_title_entries_popular"><![CDATA[Popular]]></string>
+    <string name="_bx_market_menu_item_title_system_entries_top"><![CDATA[Top Products]]></string>
+    <string name="_bx_market_menu_item_title_entries_top"><![CDATA[Top]]></string>
+    <string name="_bx_market_menu_item_title_system_entries_updated"><![CDATA[Updated Products]]></string>
+    <string name="_bx_market_menu_item_title_entries_updated"><![CDATA[Updated]]></string>
+    <string name="_bx_market_menu_title_view_entry_submenu"><![CDATA[View Product Submenu]]></string>
+    <string name="_bx_market_menu_set_title_view_entry_submenu"><![CDATA[View Product Submenu]]></string>
+    <string name="_bx_market_menu_item_title_system_view_entry_submenu_entry"><![CDATA[Overview]]></string>
+    <string name="_bx_market_menu_item_title_view_entry_submenu_entry"><![CDATA[Overview]]></string>
+    <string name="_bx_market_menu_item_title_system_view_entry_submenu_comments"><![CDATA[Reviews]]></string>
+    <string name="_bx_market_menu_item_title_view_entry_submenu_comments"><![CDATA[Reviews]]></string>
+    <string name="_bx_market_menu_item_title_system_view_entry_submenu_info"><![CDATA[Info]]></string>
+    <string name="_bx_market_menu_item_title_view_entry_submenu_info"><![CDATA[Info]]></string>
+    <string name="_bx_market_menu_item_title_system_view_entries_author"><![CDATA[Products]]></string>
+    <string name="_bx_market_menu_item_title_view_entries_author"><![CDATA[Products]]></string>
+    <string name="_bx_market_menu_item_title_system_view_entries_in_context"><![CDATA[Products]]></string>
+    <string name="_bx_market_menu_item_title_view_entries_in_context"><![CDATA[Products]]></string>
+    <string name="_bx_market_menu_title_entries_my"><![CDATA[My Products Action Menu]]></string>
+    <string name="_bx_market_menu_set_title_entries_my"><![CDATA[My Products Menu]]></string>
+	<string name="_bx_market_menu_item_title_system_manage_my_products"><![CDATA[My products]]></string>
+    <string name="_bx_market_menu_item_title_manage_my_products"><![CDATA[Products]]></string>
+    <string name="_bx_market_menu_set_title_manage_tools"><![CDATA[Manage Tools Submenu]]></string>
+    <string name="_bx_market_menu_title_manage_tools"><![CDATA[Manage Tools Submenu]]></string>
+    <string name="_bx_market_menu_item_title_system_manage_account"><![CDATA[Manage account]]></string>
+    <string name="_bx_market_menu_item_title_manage_account"><![CDATA[Manage account]]></string>
+	<string name="_bx_market_menu_item_title_system_admt_products"><![CDATA[Products]]></string>
+	<string name="_bx_market_menu_item_title_admt_products"><![CDATA[Products]]></string>
+	<string name="_bx_market_menu_item_title_manage_my"><![CDATA[My Products]]></string>
+	<string name="_bx_market_menu_item_title_manage_all"><![CDATA[All Products]]></string>
+	<string name="_bx_market_menu_item_title_system_licenses"><![CDATA[Licenses]]></string>
+	<string name="_bx_market_menu_item_title_licenses"><![CDATA[Licenses]]></string>
+	<string name="_bx_market_menu_title_snippet"><![CDATA[Snippet Actions]]></string>
+    <string name="_bx_market_menu_set_title_snippet"><![CDATA[Snippet Actions]]></string>
+    <string name="_bx_market_menu_item_title_system_snippet_more"><![CDATA[More Actions]]></string>
+    <string name="_bx_market_menu_item_title_snippet_more"><![CDATA[More Actions]]></string>
+    <string name="_bx_market_menu_title_snippet_more"><![CDATA[Snippet More Actions]]></string>
+    <string name="_bx_market_menu_set_title_snippet_more"><![CDATA[Snippet More Actions]]></string>
+    <string name="_bx_market_menu_item_title_downloads_more"><![CDATA[Show More]]></string>
+    <string name="_bx_market_menu_title_licenses_submenu"><![CDATA[Licenses Submenu]]></string>
+    <string name="_bx_market_menu_set_title_licenses_submenu"><![CDATA[Licenses Submenu]]></string>
+    <string name="_bx_market_menu_item_title_system_products_licenses_administration"><![CDATA[All Licenses]]></string>
+    <string name="_bx_market_menu_item_title_products_licenses_administration"><![CDATA[All Licenses]]></string>
+    <string name="_bx_market_menu_item_title_system_products_licenses"><![CDATA[My Licenses]]></string>
+    <string name="_bx_market_menu_item_title_products_licenses"><![CDATA[My Licenses]]></string>
+    
+
+	<string name="_bx_market_grid_filter_item_title_adm_select_one_filter1"><![CDATA[All Statuses]]></string>
+	<string name="_bx_market_grid_filter_item_title_adm_active"><![CDATA[Active]]></string>
+	<string name="_bx_market_grid_filter_item_title_adm_hidden"><![CDATA[Hidden]]></string>
+	<string name="_bx_market_grid_column_title_adm_active"><![CDATA[Active]]></string>
+    <string name="_bx_market_grid_column_title_adm_title"><![CDATA[Title]]></string>
+    <string name="_bx_market_grid_column_title_adm_added"><![CDATA[Added]]></string>
+    <string name="_bx_market_grid_column_title_adm_author"><![CDATA[Author]]></string>
+    <string name="_bx_market_grid_action_title_adm_edit"><![CDATA[Edit]]></string>
+    <string name="_bx_market_grid_action_title_adm_delete"><![CDATA[Delete]]></string>
+    <string name="_bx_market_grid_action_title_adm_more_actions"><![CDATA[More Actions]]></string>
+    <string name="_bx_market_grid_action_title_adm_audit_content"><![CDATA[Audit actions]]></string>
+    <string name="_bx_market_grid_action_title_adm_clear_reports"><![CDATA[Clear reports]]></string>
+    <string name="_bx_market_grid_action_err_delete"><![CDATA[Cannot delete the selected product(s).]]></string>
+    <string name="_bx_market_grid_txt_account_manager"><![CDATA[Redirect to manage account.]]></string>
+
+
+    <string name="_bx_market_grid_column_title_lcs_profile_id"><![CDATA[Owner]]></string>
+    <string name="_bx_market_grid_column_title_lcs_transaction"><![CDATA[Order]]></string>
+    <string name="_bx_market_grid_column_title_lcs_product"><![CDATA[Product]]></string>
+    <string name="_bx_market_grid_column_title_lcs_license"><![CDATA[License]]></string>
+    <string name="_bx_market_grid_column_title_lcs_type"><![CDATA[Type]]></string>
+    <string name="_bx_market_grid_column_title_lcs_domain"><![CDATA[Domain]]></string>
+    <string name="_bx_market_grid_column_title_lcs_added"><![CDATA[Begin]]></string>
+    <string name="_bx_market_grid_column_title_lcs_expired"><![CDATA[Expire]]></string>
+    <string name="_bx_market_grid_action_title_lcs_reset"><![CDATA[Reset]]></string>
+    <string name="_bx_market_grid_action_err_cannot_perform"><![CDATA[Cannot perform the action. Please report.]]></string>
+    <string name="_bx_market_grid_txt_lcs_type_single"><![CDATA[one-time]]></string>
+    <string name="_bx_market_grid_txt_lcs_type_recurring"><![CDATA[recurring]]></string>
+    <string name="_bx_market_grid_txt_lcs_never"><![CDATA[never]]></string>
+
+    <string name="_bx_market_chart_growth"><![CDATA[Market: Growth]]></string>
+    <string name="_bx_market_chart_growth_speed"><![CDATA[Market: Growth Speed]]></string>
+
+    <string name="_bx_market_search_extended"><![CDATA[Market Search]]></string>
+    <string name="_bx_market_search_extended_cmts"><![CDATA[Market Comments Search]]></string>
+
+    <string name="_bx_market_pre_lists_cats"><![CDATA[Product categories]]></string>
+    <string name="_bx_market_cat_administration"><![CDATA[Administration]]></string>
+    <string name="_bx_market_cat_adult"><![CDATA[Adult]]></string>
+    <string name="_bx_market_cat_advertisement"><![CDATA[Advertisement]]></string>
+    <string name="_bx_market_cat_affiliates"><![CDATA[Affiliates]]></string>
+    <string name="_bx_market_cat_authentication"><![CDATA[Authentication]]></string>
+    <string name="_bx_market_cat_calendars"><![CDATA[Calendars]]></string>
+    <string name="_bx_market_cat_communication"><![CDATA[Communication]]></string>
+    <string name="_bx_market_cat_content"><![CDATA[Content]]></string>
+    <string name="_bx_market_cat_conversion"><![CDATA[Conversion]]></string>
+    <string name="_bx_market_cat_core_changes"><![CDATA[Core Changes]]></string>
+    <string name="_bx_market_cat_dating"><![CDATA[Dating]]></string>
+    <string name="_bx_market_cat_documentation"><![CDATA[Documentation]]></string>
+    <string name="_bx_market_cat_ecommerce"><![CDATA[eCommerce]]></string>
+    <string name="_bx_market_cat_events"><![CDATA[Events]]></string>
+    <string name="_bx_market_cat_feedback"><![CDATA[Feedback]]></string>
+    <string name="_bx_market_cat_flash"><![CDATA[Flash]]></string>
+    <string name="_bx_market_cat_games"><![CDATA[Games]]></string>
+    <string name="_bx_market_cat_graphics"><![CDATA[Graphics]]></string>
+    <string name="_bx_market_cat_hosting"><![CDATA[Hosting]]></string>
+    <string name="_bx_market_cat_integrations"><![CDATA[Integrations]]></string>
+    <string name="_bx_market_cat_location"><![CDATA[Location]]></string>
+    <string name="_bx_market_cat_management"><![CDATA[Management]]></string>
+    <string name="_bx_market_cat_mobile"><![CDATA[Mobile]]></string>
+    <string name="_bx_market_cat_multimedia"><![CDATA[Multimedia]]></string>
+    <string name="_bx_market_cat_music"><![CDATA[Music]]></string>
+    <string name="_bx_market_cat_navigation"><![CDATA[Navigation]]></string>
+    <string name="_bx_market_cat_other"><![CDATA[Other]]></string>
+    <string name="_bx_market_cat_performance"><![CDATA[Performance]]></string>
+    <string name="_bx_market_cat_photos"><![CDATA[Photos]]></string>
+    <string name="_bx_market_cat_search"><![CDATA[Search]]></string>
+    <string name="_bx_market_cat_security"><![CDATA[Security]]></string>
+    <string name="_bx_market_cat_services"><![CDATA[Services]]></string>
+    <string name="_bx_market_cat_social"><![CDATA[Social]]></string>
+    <string name="_bx_market_cat_spam_prevention"><![CDATA[Spam Prevention]]></string>
+    <string name="_bx_market_cat_statistics"><![CDATA[Statistics]]></string>
+    <string name="_bx_market_cat_templates"><![CDATA[Templates]]></string>
+    <string name="_bx_market_cat_tools"><![CDATA[Tools]]></string>
+    <string name="_bx_market_cat_translations"><![CDATA[Translations]]></string>
+    <string name="_bx_market_cat_video"><![CDATA[Video]]></string>
+
+	<string name="_bx_market_pre_lists_durations"><![CDATA[Product durations]]></string>
+	<string name="_bx_market_cat_duration_day"><![CDATA[daily]]></string>
+	<string name="_bx_market_cat_duration_week"><![CDATA[weekly]]></string>
+	<string name="_bx_market_cat_duration_month"><![CDATA[monthly]]></string>
+	<string name="_bx_market_cat_duration_year"><![CDATA[yearly]]></string>
+
+    <string name="_bx_market_vote_counter"><![CDATA[{0} ratings]]></string>
+
+	<string name="_bx_market_err_access_denied"><![CDATA[Access denied.]]></string>
+	<string name="_bx_market_err_no_payments"><![CDATA[There is no installed payment processing module.]]></string>
+	<string name="_bx_market_err_not_accept_payments"><![CDATA[You need to activate at least one payment provider. You may do it via My Account menu -> Settings page -> <a href="{0}">Payments</a> tab.]]></string>
+	<string name="_bx_market_err_not_accept_payments_single"><![CDATA[You need to activate at least one payment provider, which is working with Shopping Cart. You may do it via My Account menu -> Settings page -> <a href="{0}">Payments</a> tab.]]></string>
+	<string name="_bx_market_err_not_accept_payments_recurring"><![CDATA[You need to activate at least one payment provider, which is working with Subscriptions. You may do it via My Account menu -> Settings page -> <a href="{0}">Payments</a> tab.]]></string>
+
+    <string name="_bx_market_txt_all_entries_by"><![CDATA[{0} products]]></string>
+    <string name="_bx_market_txt_all_entries_in"><![CDATA[<a href="{0}">All Products in {1} ({2})</a>]]></string>
+    <string name="_bx_market_txt_category"><![CDATA[Category:]]></string>
+    <string name="_bx_market_txt_most_current_version"><![CDATA[The most current version]]></string>
+    <string name="_bx_market_txt_sample_single"><![CDATA[product]]></string>
+    <string name="_bx_market_txt_sample_single_with_article"><![CDATA[a product]]></string>
+    <string name="_bx_market_txt_sample_comment_single"><![CDATA[comment to product]]></string>
+    <string name="_bx_market_txt_sample_vote_single"><![CDATA[vote to product]]></string>
+    <string name="_bx_market_txt_sample_reaction_single"><![CDATA['{0}' reaction to product]]></string>
+    <string name="_bx_market_txt_sample_score_up_single"><![CDATA[score up vote to product]]></string>
+    <string name="_bx_market_txt_sample_score_down_single"><![CDATA[score down vote to product]]></string>
+    <string name="_bx_market_txt_author_added_product"><![CDATA[{0} {1}]]></string>
+    <string name="_bx_market_txt_joined"><![CDATA[Joined:]]></string>
+    <string name="_bx_market_txt_last_active"><![CDATA[Last Active:]]></string>
+    <string name="_bx_market_txt_price_single"><![CDATA[Buy for {0}{1}]]></string>
+    <string name="_bx_market_txt_price_single_short"><![CDATA[{0}{1}]]></string>
+    <string name="_bx_market_txt_price_recurring"><![CDATA[Subscribe for {0}{1}/{2}]]></string>
+    <string name="_bx_market_txt_price_recurring_short"><![CDATA[{0}{1}/{2}]]></string>
+    <string name="_bx_market_txt_price_free"><![CDATA[Free]]></string>
+    <string name="_bx_market_txt_per_hour"><![CDATA[hour]]></string>
+    <string name="_bx_market_txt_per_hour_short"><![CDATA[hour]]></string>
+    <string name="_bx_market_txt_per_day"><![CDATA[day]]></string>
+    <string name="_bx_market_txt_per_day_short"><![CDATA[day]]></string>
+    <string name="_bx_market_txt_per_week"><![CDATA[week]]></string>
+    <string name="_bx_market_txt_per_week_short"><![CDATA[week]]></string>
+    <string name="_bx_market_txt_per_month"><![CDATA[month]]></string>
+    <string name="_bx_market_txt_per_month_short"><![CDATA[month]]></string>
+    <string name="_bx_market_txt_per_year"><![CDATA[year]]></string>
+    <string name="_bx_market_txt_per_year_short"><![CDATA[year]]></string>
+    <string name="_bx_market_txt_get_for_free"><![CDATA[Download for Free]]></string>
+    <string name="_bx_market_txt_purchased_note"><![CDATA[Contact <a href="{0}">{1}</a> if you have any questions or need support.]]></string>
+
+    <!-- EMAIL TEMPLATES -->
+    <string name="_bx_market_et_txt_name_purchased"><![CDATA[Product purchased.]]></string>
+    <string name="_bx_market_et_txt_subject_purchased"><![CDATA[You've purchased {product_name} product.]]></string>
+    <string name="_bx_market_et_txt_body_purchased"><![CDATA[{email_header}
+<p>Hello, {client_name}.</p>
+<p>You've purchased <a href="{product_url}">{product_name}</a> product from <a href="{vendor_url}">{vendor_name}</a>.<br />Your license is <b>{license}</b>.</p>
+<p>{notes}</p>
+{email_footer}]]></string>
+</resources>

+ 655 - 0
modules/boonex/market/updates/12.0.2_12.0.3/source/install/sql/enable.sql

@@ -0,0 +1,655 @@
+
+-- 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_market', '_bx_market', 'bx_market@modules/boonex/market/|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_market', '_bx_market', 1);
+SET @iCategId = LAST_INSERT_ID();
+
+INSERT INTO `sys_options` (`name`, `value`, `category_id`, `caption`, `type`, `check`, `check_error`, `extra`, `order`) VALUES
+('bx_market_enable_recurring', 'on', @iCategId, '_bx_market_option_enable_recurring', 'checkbox', '', '', '', 1),
+('bx_market_recurring_reserve', '4', @iCategId, '_bx_market_option_recurring_reserve', 'digit', '', '', '', 2),
+('bx_market_summary_chars', '700', @iCategId, '_bx_market_option_summary_chars', 'digit', '', '', '', 10),
+('bx_market_plain_summary_chars', '240', @iCategId, '_bx_market_option_plain_summary_chars', 'digit', '', '', '', 11),
+('bx_market_per_page_browse', '12', @iCategId, '_bx_market_option_per_page_browse', 'digit', '', '', '', 20),
+('bx_market_per_page_profile', '6', @iCategId, '_bx_market_option_per_page_profile', 'digit', '', '', '', 21),
+('bx_market_per_page_browse_showcase', '32', @iCategId, '_sys_option_per_page_browse_showcase', 'digit', '', '', '', 23),
+('bx_market_rss_num', '10', @iCategId, '_bx_market_option_rss_num', 'digit', '', '', '', 25),
+('bx_market_searchable_fields', 'title,text', @iCategId, '_bx_market_option_searchable_fields', 'list', '', '', 'a:2:{s:6:"module";s:9:"bx_market";s:6:"method";s:21:"get_searchable_fields";}', 30);
+
+-- PAGE: create entry
+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_market_create_entry', '_bx_market_page_title_sys_create_entry', '_bx_market_page_title_create_entry', 'bx_market', 5, 2147483647, 1, 'create-product', 'page.php?i=create-product', '', '', '', 0, 1, 0, 'BxMarketPageBrowse', 'modules/boonex/market/classes/BxMarketPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks` (`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES
+('bx_market_create_entry', 1, 'bx_market', '_bx_market_page_block_title_create_entry', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:9:"bx_market";s:6:"method";s:13:"entity_create";}', 0, 1, 1);
+
+
+-- PAGE: edit entry
+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_market_edit_entry', '_bx_market_page_title_sys_edit_entry', '_bx_market_page_title_edit_entry', 'bx_market', 5, 2147483647, 1, 'edit-product', '', '', '', '', 0, 1, 0, 'BxMarketPageEntry', 'modules/boonex/market/classes/BxMarketPageEntry.php');
+
+INSERT INTO `sys_pages_blocks` (`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES
+('bx_market_edit_entry', 1, 'bx_market', '_bx_market_page_block_title_edit_entry', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:9:"bx_market";s:6:"method";s:11:"entity_edit";}', 0, 0, 0);
+
+
+-- PAGE: delete entry
+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_market_delete_entry', '_bx_market_page_title_sys_delete_entry', '_bx_market_page_title_delete_entry', 'bx_market', 5, 2147483647, 1, 'delete-product', '', '', '', '', 0, 1, 0, 'BxMarketPageEntry', 'modules/boonex/market/classes/BxMarketPageEntry.php');
+
+INSERT INTO `sys_pages_blocks` (`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES
+('bx_market_delete_entry', 1, 'bx_market', '_bx_market_page_block_title_delete_entry', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:9:"bx_market";s:6:"method";s:13:"entity_delete";}', 0, 0, 0);
+
+
+-- PAGE: download entry
+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_market_download_entry', '_bx_market_page_title_sys_download_entry', '_bx_market_page_title_download_entry', 'bx_market', 5, 2147483647, 1, 'download-product', '', '', '', '', 0, 1, 0, 'BxMarketPageEntry', 'modules/boonex/market/classes/BxMarketPageEntry.php');
+
+INSERT INTO `sys_pages_blocks` (`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES
+('bx_market_download_entry', 1, 'bx_market', '_bx_market_page_block_title_download_entry', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:9:"bx_market";s:6:"method";s:15:"entity_download";}', 0, 0, 0);
+
+
+-- PAGE: view entry
+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_market_view_entry', '_bx_market_page_title_sys_view_entry', '_bx_market_page_title_view_entry', 'bx_market', 12, 2147483647, 1, 'view-product', '', '', '', '', 0, 1, 0, 'BxMarketPageEntry', 'modules/boonex/market/classes/BxMarketPageEntry.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_market_view_entry', 1, 'bx_market', '', '_bx_market_page_block_title_entry_breadcrumb', 13, 2147483647, 'service', 'a:2:{s:6:"module";s:9:"bx_market";s:6:"method";s:17:"entity_breadcrumb";}', 0, 0, 1, 1),
+('bx_market_view_entry', 2, 'bx_market', '', '_bx_market_page_block_title_entry_text', 13, 2147483647, 'service', 'a:2:{s:6:"module";s:9:"bx_market";s:6:"method";s:17:"entity_text_block";}', 0, 0, 1, 1),
+('bx_market_view_entry', 2, 'bx_market', '', '_bx_market_page_block_title_entry_all_actions', 13, 2147483647, 'service', 'a:2:{s:6:"module";s:9:"bx_market";s:6:"method";s:18:"entity_all_actions";}', 0, 0, 1, 2),
+('bx_market_view_entry', 2, 'bx_market', '', '_bx_market_page_block_title_entry_actions', 13, 2147483647, 'service', 'a:2:{s:6:"module";s:9:"bx_market";s:6:"method";s:14:"entity_actions";}', 0, 0, 0, 0),
+('bx_market_view_entry', 2, 'bx_market', '', '_bx_market_page_block_title_entry_comments', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:9:"bx_market";s:6:"method";s:15:"entity_comments";}', 0, 0, 1, 3),
+('bx_market_view_entry', 3, 'bx_market', '', '_bx_market_page_block_title_entry_author_entries', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:9:"bx_market";s:6:"method";s:22:"entity_author_entities";}', 0, 0, 1, 6),
+('bx_market_view_entry', 3, 'bx_market', '', '_bx_market_page_block_title_entry_social_sharing', 13, 2147483647, 'service', 'a:2:{s:6:"module";s:9:"bx_market";s:6:"method";s:21:"entity_social_sharing";}', 0, 0, 0, 0),
+('bx_market_view_entry', 3, 'bx_market', '', '_bx_market_page_block_title_entry_info', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:9:"bx_market";s:6:"method";s:11:"entity_info";}', 0, 0, 1, 2),
+('bx_market_view_entry', 3, 'bx_market', '', '_bx_market_page_block_title_entry_rating', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:9:"bx_market";s:6:"method";s:13:"entity_rating";}', 0, 0, 1, 4),
+('bx_market_view_entry', 3, 'bx_market', '', '_bx_market_page_block_title_entry_author', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:9:"bx_market";s:6:"method";s:13:"entity_author";}', 0, 0, 1, 3),
+('bx_market_view_entry', 3, 'bx_market', '_bx_market_page_block_title_sys_entry_context', '_bx_market_page_block_title_entry_context', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_market\";s:6:\"method\";s:14:\"entity_context\";}', 0, 0, 1, 1),
+('bx_market_view_entry', 3, 'bx_market', '', '_bx_market_page_block_title_entry_location', 13, 2147483647, 'service', 'a:2:{s:6:"module";s:9:"bx_market";s:6:"method";s:15:"entity_location";}', 0, 0, 0, 0),
+('bx_market_view_entry', 3, 'bx_market', '', '_bx_market_page_block_title_entry_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:9:"bx_market";i:1;s:4:"{id}";}s:5:"class";s:20:"TemplServiceMetatags";}', 0, 0, 1, 5),
+('bx_market_view_entry', 3, 'bx_market', '', '_bx_market_page_block_title_entry_attachments', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:9:"bx_market";s:6:"method";s:18:"entity_attachments";}', 0, 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_market_view_entry_comments', '_bx_market_page_title_sys_view_entry_comments', '_bx_market_page_title_view_entry_comments', 'bx_market', 5, 2147483647, 1, 'view-product-comments', '', '', '', '', 0, 1, 0, 'BxMarketPageEntry', 'modules/boonex/market/classes/BxMarketPageEntry.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_market_view_entry_comments', 1, 'bx_market', '_bx_market_page_block_title_entry_comments', '_bx_market_page_block_title_entry_comments_link', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:9:"bx_market";s:6:"method";s:15:"entity_comments";}', 0, 0, 1);
+
+
+-- PAGE: view entry info
+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_market_view_entry_info', '_bx_market_page_title_sys_view_entry_info', '_bx_market_page_title_view_entry_info', 'bx_market', 5, 2147483647, 1, 'view-product-info', '', '', '', '', 0, 1, 0, 'BxMarketPageEntry', 'modules/boonex/market/classes/BxMarketPageEntry.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_market_view_entry_info', 1, 'bx_market', '_bx_market_page_block_title_entry_info', '_bx_market_page_block_title_entry_info_link', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:9:"bx_market";s:6:"method";s:16:"entity_info_full";}', 0, 0, 1),
+('bx_market_view_entry_info', 1, 'bx_market', '', '_bx_market_page_block_title_entry_text', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:9:"bx_market";s:6:"method";s:17:"entity_text_block";}', 0, 0, 2);
+
+
+-- PAGE: categories
+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_market_categories', '_bx_market_page_title_sys_entries_categories', '_bx_market_page_title_entries_categories', 'bx_market', 5, 2147483647, 1, 'products-categories', 'page.php?i=products-categories', '', '', '', 0, 1, 0, 'BxMarketPageBrowse', 'modules/boonex/market/classes/BxMarketPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_market_categories', 1, 'bx_market', '_bx_market_page_block_title_cats', 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:14:"bx_market_cats";i:1;a:1:{s:10:"show_empty";b:1;}}s:5:"class";s:20:"TemplServiceCategory";}', 0, 1, 1);
+
+
+-- PAGE: latest 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_market_latest', '_bx_market_page_title_sys_entries_latest', '_bx_market_page_title_entries_latest', 'bx_market', 5, 2147483647, 1, 'products-latest', 'page.php?i=products-latest', '', '', '', 0, 1, 0, 'BxMarketPageBrowse', 'modules/boonex/market/classes/BxMarketPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_market_latest', 1, 'bx_market', '_bx_market_page_block_title_latest_entries', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:9:"bx_market";s:6:"method";s:13:"browse_public";s:6:"params";a:3:{s:9:"unit_view";s:7:"gallery";s:13:"empty_message";b:1;s:13:"ajax_paginate";b:0;}}', 0, 0, 1);
+
+
+-- PAGE: featured 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_market_featured', '_bx_market_page_title_sys_entries_featured', '_bx_market_page_title_entries_featured', 'bx_market', 5, 2147483647, 1, 'products-featured', 'page.php?i=products-featured', '', '', '', 0, 1, 0, 'BxMarketPageBrowse', 'modules/boonex/market/classes/BxMarketPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_market_featured', 1, 'bx_market', '_bx_market_page_block_title_featured_entries', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:9:"bx_market";s:6:"method";s:15:"browse_featured";s:6:"params";a:3:{s:9:"unit_view";s:7:"gallery";s:13:"empty_message";b:1;s:13:"ajax_paginate";b:0;}}', 0, 0, 1);
+
+
+-- PAGE: popular 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_market_popular', '_bx_market_page_title_sys_entries_popular', '_bx_market_page_title_entries_popular', 'bx_market', 5, 2147483647, 1, 'products-popular', 'page.php?i=products-popular', '', '', '', 0, 1, 0, 'BxMarketPageBrowse', 'modules/boonex/market/classes/BxMarketPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_market_popular', 1, 'bx_market', '_bx_market_page_block_title_popular_entries', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:9:"bx_market";s:6:"method";s:14:"browse_popular";s:6:"params";a:3:{s:9:"unit_view";s:7:"gallery";s:13:"empty_message";b:1;s:13:"ajax_paginate";b:0;}}', 0, 0, 1);
+
+
+-- PAGE: top 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_market_top', '_bx_market_page_title_sys_entries_top', '_bx_market_page_title_entries_top', 'bx_market', 5, 2147483647, 1, 'products-top', 'page.php?i=products-top', '', '', '', 0, 1, 0, 'BxMarketPageBrowse', 'modules/boonex/market/classes/BxMarketPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_market_top', 1, 'bx_market', '_bx_market_page_block_title_top_entries', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:9:"bx_market";s:6:"method";s:10:"browse_top";s:6:"params";a:3:{s:9:"unit_view";s:7:"gallery";s:13:"empty_message";b:1;s:13:"ajax_paginate";b:0;}}', 0, 0, 1);
+
+
+-- PAGE: updated 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_market_updated', '_bx_market_page_title_sys_entries_updated', '_bx_market_page_title_entries_updated', 'bx_market', 5, 2147483647, 1, 'products-updated', 'page.php?i=products-updated', '', '', '', 0, 1, 0, 'BxMarketPageBrowse', 'modules/boonex/market/classes/BxMarketPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_market_updated', 1, 'bx_market', '_bx_market_page_block_title_updated_entries', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:9:"bx_market";s:6:"method";s:14:"browse_updated";s:6:"params";a:3:{s:9:"unit_view";s:7:"gallery";s:13:"empty_message";b:1;s:13:"ajax_paginate";b: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_market_author', 'products-author', '_bx_market_page_title_sys_entries_of_author', '_bx_market_page_title_entries_of_author', 'bx_market', 5, 2147483647, 1, '', '', '', '', 0, 1, 0, 'BxMarketPageAuthor', 'modules/boonex/market/classes/BxMarketPageAuthor.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_market_author', 1, 'bx_market', '', '_bx_market_page_block_title_entries_actions', 13, 2147483647, 'service', 'a:2:{s:6:"module";s:9:"bx_market";s:6:"method";s:18:"my_entries_actions";}', 0, 0, 1, 1),
+('bx_market_author', 1, 'bx_market', '_bx_market_page_block_title_sys_favorites_of_author', '_bx_market_page_block_title_favorites_of_author', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:9:"bx_market";s:6:"method";s:15:"browse_favorite";s:6:"params";a:1:{i:0;s:12:"{profile_id}";}}', 0, 1, 1, 2),
+('bx_market_author', 1, 'bx_market', '_bx_market_page_block_title_sys_entries_of_author', '_bx_market_page_block_title_entries_of_author', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:9:"bx_market";s:6:"method";s:13:"browse_author";}', 0, 0, 1, 3),
+('bx_market_author', 1, 'bx_market', '_bx_market_page_block_title_sys_entries_in_context', '_bx_market_page_block_title_entries_in_context', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:9:"bx_market";s:6:"method";s:14:"browse_context";s:6:"params";a:2:{s:10:"profile_id";s:12:"{profile_id}";i:0;a:1:{s:13:"empty_message";b:0;}}}', 0, 0, 1, 4);
+
+-- PAGE: licenses 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_market_licenses_administration', '_bx_market_page_title_sys_licenses_administration', '_bx_market_page_title_licenses_administration', 'bx_market', 5, 192, 1, 'products-licenses-administration', '', '', '', '', 0, 1, 0, 'BxMarketPageLicenses', 'modules/boonex/market/classes/BxMarketPageLicenses.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_market_licenses_administration', 1, 'bx_market', '', '_bx_market_page_block_title_licenses_administration', 11, 192, 'service', 'a:2:{s:6:"module";s:9:"bx_market";s:6:"method";s:29:"block_licenses_administration";}', 0, 0, 1, 0);
+
+-- PAGE: profile's licenses
+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_market_licenses', '_bx_market_page_title_sys_licenses', '_bx_market_page_title_licenses', 'bx_market', 5, 2147483647, 1, 'products-licenses', '', '', '', '', 0, 1, 0, 'BxMarketPageLicenses', 'modules/boonex/market/classes/BxMarketPageLicenses.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_market_licenses', 1, 'bx_market', '', '_bx_market_page_block_title_licenses_note', 13, 2147483647, 'service', 'a:2:{s:6:"module";s:9:"bx_market";s:6:"method";s:19:"block_licenses_note";}', 0, 0, 1, 0),
+('bx_market_licenses', 1, 'bx_market', '', '_bx_market_page_block_title_licenses', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:9:"bx_market";s:6:"method";s:14:"block_licenses";}', 0, 0, 1, 1);
+
+-- PAGE: entries in context
+
+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_market_context', 'products-context', '_bx_market_page_title_sys_entries_in_context', '_bx_market_page_title_entries_in_context', 'bx_market', 5, 2147483647, 1, '', '', '', '', 0, 1, 0, 'BxMarketPageAuthor', 'modules/boonex/market/classes/BxMarketPageAuthor.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_market_context', 1, 'bx_market', '_bx_market_page_block_title_sys_entries_in_context', '_bx_market_page_block_title_entries_in_context', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_market\";s:6:\"method\";s:14:\"browse_context\";}', 0, 0, 1, 1);
+
+-- PAGE: module home
+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_market_home', 'products-home', '_bx_market_page_title_sys_home', '_bx_market_page_title_home', 'bx_market', 1, 2147483647, 1, 'page.php?i=products-home', '', '', '', 0, 1, 0, 'BxMarketPageBrowse', 'modules/boonex/market/classes/BxMarketPageBrowse.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_market_home', 1, 'bx_market', '', '_bx_market_page_block_title_popular_keywords', 11, 2147483647, 'service', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:14:"keywords_cloud";s:6:"params";a:2:{i:0;s:9:"bx_market";i:1;s:9:"bx_market";}s:5:"class";s:20:"TemplServiceMetatags";}', 0, 1, 1, 0),
+('bx_market_home', 1, 'bx_market', '', '_bx_market_page_block_title_cats', 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:14:"bx_market_cats";i:1;a:1:{s:10:"show_empty";b:1;}}s:5:"class";s:20:"TemplServiceCategory";}', 0, 0, 1, 1),
+('bx_market_home', 2, 'bx_market', '', '_bx_market_page_block_title_featured_entries', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:9:"bx_market";s:6:"method";s:15:"browse_featured";s:6:"params";a:1:{i:0;s:7:"gallery";}}', 0, 1, 1, 0),
+('bx_market_home', 2, 'bx_market', '', '_bx_market_page_block_title_latest_entries', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:9:"bx_market";s:6:"method";s:13:"browse_public";s:6:"params";a:1:{i:0;s:7:"gallery";}}', 0, 1, 1, 1),
+('bx_market_home', 2, 'bx_market', '', '_bx_market_page_block_title_popular_entries', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:9:"bx_market";s:6:"method";s:14:"browse_popular";s:6:"params";a:2:{i:0;s:7:"gallery";i:1;b:0;}}', 0, 1, 1, 2),
+('bx_market_home', 2, 'bx_market', '', '_bx_market_page_block_title_updated_entries', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:9:"bx_market";s:6:"method";s:14:"browse_updated";s:6:"params";a:2:{i:0;s:7:"gallery";i:1;b:0;}}', 0, 1, 0, 3);
+
+-- 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_market_search', '_bx_market_page_title_sys_entries_search', '_bx_market_page_title_entries_search', 'bx_market', 5, 2147483647, 1, 'products-search', 'page.php?i=products-search', '', '', '', 0, 1, 0, 'BxMarketPageBrowse', 'modules/boonex/market/classes/BxMarketPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_market_search', 1, 'bx_market', '_bx_market_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:9:"bx_market";}}s:5:"class";s:27:"TemplSearchExtendedServices";}', 0, 1, 1, 1),
+('bx_market_search', 1, 'bx_market', '_bx_market_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:9:"bx_market";s:10:"show_empty";b:1;}}s:5:"class";s:27:"TemplSearchExtendedServices";}', 0, 1, 1, 2),
+('bx_market_search', 1, 'bx_market', '_bx_market_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:14:"bx_market_cmts";}}s:5:"class";s:27:"TemplSearchExtendedServices";}', 0, 1, 0, 3),
+('bx_market_search', 1, 'bx_market', '_bx_market_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:14:"bx_market_cmts";s:10:"show_empty";b:1;}}s:5:"class";s:27:"TemplSearchExtendedServices";}', 0, 1, 0, 4);
+
+-- 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_market_manage', '_bx_market_page_title_sys_manage', '_bx_market_page_title_manage', 'bx_market', 5, 2147483647, 1, 'products-manage', 'page.php?i=products-manage', '', '', '', 0, 1, 0, 'BxMarketPageBrowse', 'modules/boonex/market/classes/BxMarketPageBrowse.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_market_manage', 1, 'bx_market', '_bx_market_page_block_title_system_manage', '_bx_market_page_block_title_manage', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:9:"bx_market";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_market_administration', '_bx_market_page_title_sys_manage_administration', '_bx_market_page_title_manage', 'bx_market', 5, 192, 1, 'products-administration', 'page.php?i=products-administration', '', '', '', 0, 1, 0, 'BxMarketPageBrowse', 'modules/boonex/market/classes/BxMarketPageBrowse.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_market_administration', 1, 'bx_market', '_bx_market_page_block_title_system_manage_administration', '_bx_market_page_block_title_manage', 11, 192, 'service', 'a:3:{s:6:"module";s:9:"bx_market";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`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('sys_home', 1, 'bx_market', '_bx_market_page_block_title_latest_entries', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:9:"bx_market";s:6:"method";s:13:"browse_public";s:6:"params";a:2:{i:0;b:0;i:1;b:0;}}', 1, 0, 0, IFNULL(@iBlockOrder, 0) + 1);
+
+-- 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_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES
+('trigger_page_profile_view_entry', @iPBCellProfile, 'bx_market', '_bx_market_page_block_title_sys_view_profile', '_bx_market_page_block_title_view_profile', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:9:"bx_market";s:6:"method";s:13:"browse_author";s:6:"params";a:2:{i:0;s:12:"{profile_id}";i:1;a:2:{s:8:"per_page";s:26:"bx_market_per_page_profile";s:13:"empty_message";b:0;}}}', 0, 0, 0);
+
+-- 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`, `order`) VALUES 
+('', 0, 'bx_market', '', '_bx_market_page_block_title_latest_entries_view_extended', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:9:"bx_market";s:6:"method";s:13:"browse_public";s:6:"params";a:1:{s:9:"unit_view";s:8:"extended";}}', 0, 1, IFNULL(@iBlockOrder, 0) + 1),
+('', 0, 'bx_market', '', '_bx_market_page_block_title_latest_entries_view_full', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:9:"bx_market";s:6:"method";s:13:"browse_public";s:6:"params";a:1:{i:0;s:4:"full";}}', 0, 1, IFNULL(@iBlockOrder, 0) + 2),
+('', 0, 'bx_market', '', '_bx_market_page_block_title_popular_entries_view_extended', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:9:"bx_market";s:6:"method";s:14:"browse_popular";s:6:"params";a:1:{i:0;s:8:"extended";}}', 0, 1, IFNULL(@iBlockOrder, 0) + 3),
+('', 0, 'bx_market', '', '_bx_market_page_block_title_popular_entries_view_full', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:9:"bx_market";s:6:"method";s:14:"browse_popular";s:6:"params";a:1:{i:0;s:4:"full";}}', 0, 1, IFNULL(@iBlockOrder, 0) + 4),
+('', 0, 'bx_market', '', '_bx_market_page_block_title_featured_entries_view_extended', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:9:"bx_market";s:6:"method";s:15:"browse_featured";s:6:"params";a:1:{s:9:"unit_view";s:8:"extended";}}', 0, 1, IFNULL(@iBlockOrder, 0) + 5),
+('', 0, 'bx_market', '', '_bx_market_page_block_title_featured_entries_view_full', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:9:"bx_market";s:6:"method";s:15:"browse_featured";s:6:"params";a:1:{i:0;s:4:"full";}}', 0, 1, IFNULL(@iBlockOrder, 0) + 6),
+('', 0, 'bx_market', '', '_bx_market_page_block_title_updated_entries_view_extended', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:9:"bx_market";s:6:"method";s:14:"browse_updated";s:6:"params";a:1:{s:9:"unit_view";s:8:"extended";}}', 0, 1, IFNULL(@iBlockOrder, 0) + 7),
+('', 0, 'bx_market', '', '_bx_market_page_block_title_updated_entries_view_full', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:9:"bx_market";s:6:"method";s:14:"browse_updated";s:6:"params";a:1:{i:0;s:4:"full";}}', 0, 1, IFNULL(@iBlockOrder, 0) + 8),
+('', 0, 'bx_market', '_bx_market_page_block_title_sys_recent_entries_view_showcase', '_bx_market_page_block_title_recent_entries_view_showcase', 11, 2147483647, 'service', 'a:3:{s:6:\"module\";s:9:\"bx_market\";s:6:\"method\";s:13:\"browse_public\";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, IFNULL(@iBlockOrder, 0) + 9),
+('', 0, 'bx_market', '_bx_market_page_block_title_sys_popular_entries_view_showcase', '_bx_market_page_block_title_popular_entries_view_showcase', 11, 2147483647, 'service', 'a:3:{s:6:\"module\";s:9:\"bx_market\";s:6:\"method\";s:14:\"browse_popular\";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, IFNULL(@iBlockOrder, 0) + 10),
+('', 0, 'bx_market', '_bx_market_page_block_title_sys_featured_entries_view_showcase', '_bx_market_page_block_title_featured_entries_view_showcase', 11, 2147483647, 'service', 'a:3:{s:6:\"module\";s:9:\"bx_market\";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, IFNULL(@iBlockOrder, 0) + 11);
+
+
+-- 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_market', 'products-home', '_bx_market_menu_item_title_system_entries_home', '_bx_market_menu_item_title_entries_home', 'page.php?i=products-home', '', '', 'shopping-cart col-green3', 'bx_market_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_market', 'products-home', '_bx_market_menu_item_title_system_entries_home', '_bx_market_menu_item_title_entries_home', 'page.php?i=products-home', '', '', 'shopping-cart col-green3', 'bx_market_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_market', 'create-product', '_bx_market_menu_item_title_system_create_entry', '_bx_market_menu_item_title_create_entry', 'page.php?i=create-product', '', '', 'shopping-cart col-green3', '', 2147483647, 1, 1, IFNULL(@iAddMenuOrder, 0) + 1);
+
+
+-- MENU: 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_market_view', '_bx_market_menu_title_view_entry', 'bx_market_view', 'bx_market', 9, 0, 1, 'BxMarketMenuView', 'modules/boonex/market/classes/BxMarketMenuView.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_market_view', 'bx_market', '_bx_market_menu_set_title_view_entry', 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`, `order`) VALUES
+('bx_market_view', 'bx_market', 'download', '_bx_market_menu_item_title_system_download', '_bx_market_menu_item_title_download', 'page.php?i=download-product&id={content_id}', '', '', 'download', '', 0, 2147483647, 1, 0, 10),
+('bx_market_view', 'bx_market', 'add-to-cart', '_bx_market_menu_item_title_system_add_to_cart', '{add_to_cart_title}', 'javascript:void(0);', 'javascript:{add_to_cart_onclick}', '', 'cart-plus', '', 0, 2147483647, 1, 0, 20),
+('bx_market_view', 'bx_market', 'subscribe', '_bx_market_menu_item_title_system_subscribe', '{subscribe_title}', 'javascript:void(0);', 'javascript:{subscribe_onclick}', '', 'credit-card', '', 0, 2147483647, 1, 0, 30),
+('bx_market_view', 'bx_market', 'unhide-product', '_bx_market_menu_item_title_system_unhide_entry', '_bx_market_menu_item_title_unhide_entry', 'javascript:void(0);', 'javascript:{js_object}.perform(this, ''unhide-product'', {content_id});', '', 'play-circle', '', 0, 2147483647, 1, 0, 40),
+('bx_market_view', 'bx_market', 'product-more', '_bx_market_menu_item_title_system_product_more', '_bx_market_menu_item_title_product_more', 'javascript:void(0)', 'bx_menu_popup(''bx_market_view_more'', this, {}, {id:{content_id}});', '', 'cog', 'bx_market_view_more', 1, 2147483647, 1, 0, 9999);
+
+-- MENU: actions more 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_market_view_more', '_bx_market_menu_title_view_entry_more', 'bx_market_view_more', 'bx_market', 6, 0, 1, 'BxMarketMenuView', 'modules/boonex/market/classes/BxMarketMenuView.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_market_view_more', 'bx_market', '_bx_market_menu_set_title_view_entry_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_market_view_more', 'bx_market', 'hide-product', '_bx_market_menu_item_title_system_hide_entry', '_bx_market_menu_item_title_hide_entry', 'javascript:void(0);', 'javascript:{js_object}.perform(this, ''hide-product'', {content_id});', '', 'stop-circle', '', 2147483647, 1, 0, 10),
+('bx_market_view_more', 'bx_market', 'edit-product', '_bx_market_menu_item_title_system_edit_entry', '_bx_market_menu_item_title_edit_entry', 'page.php?i=edit-product&id={content_id}', '', '', 'pencil-alt', '', 2147483647, 1, 0, 20),
+('bx_market_view_more', 'bx_market', 'delete-product', '_bx_market_menu_item_title_system_delete_entry', '_bx_market_menu_item_title_delete_entry', 'page.php?i=delete-product&id={content_id}', '', '', 'remove', '', 2147483647, 1, 0, 30);
+
+-- 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_market_view_actions', '_sys_menu_title_view_actions', 'bx_market_view_actions', 'bx_market', 15, 0, 1, 'BxMarketMenuViewActions', 'modules/boonex/market/classes/BxMarketMenuViewActions.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_market_view_actions', 'bx_market', '_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_market_view_actions', 'bx_market', 'download', '_bx_market_menu_item_title_system_download', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 10),
+('bx_market_view_actions', 'bx_market', 'add-to-cart', '_bx_market_menu_item_title_system_add_to_cart', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 20),
+('bx_market_view_actions', 'bx_market', 'subscribe', '_bx_market_menu_item_title_system_subscribe', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 30),
+('bx_market_view_actions', 'bx_market', 'unhide-product', '_bx_market_menu_item_title_system_unhide_entry', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 40),
+('bx_market_view_actions', 'bx_market', 'hide-product', '_bx_market_menu_item_title_system_hide_entry', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 50),
+('bx_market_view_actions', 'bx_market', 'edit-product', '_bx_market_menu_item_title_system_edit_entry', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 60),
+('bx_market_view_actions', 'bx_market', 'delete-product', '_bx_market_menu_item_title_system_delete_entry', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 70),
+('bx_market_view_actions', 'bx_market', '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_market'', content_id: {content_id}});', '', 'check-circle', '', '', 0, 2147483647, 'a:2:{s:6:"module";s:9:"bx_market";s:6:"method";s:19:"is_badges_avaliable";}', 1, 0, 80),
+('bx_market_view_actions', 'bx_market', 'comment', '_sys_menu_item_title_system_va_comment', '', '', '', '', '', '', '', 0, 2147483647, '', 0, 0, 200),
+('bx_market_view_actions', 'bx_market', 'view', '_sys_menu_item_title_system_va_view', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 210),
+('bx_market_view_actions', 'bx_market', 'vote', '_sys_menu_item_title_system_va_vote', '', '', '', '', '', '', '', 0, 2147483647, '', 0, 0, 220),
+('bx_market_view_actions', 'bx_market', 'reaction', '_sys_menu_item_title_system_va_reaction', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 225),
+('bx_market_view_actions', 'bx_market', 'score', '_sys_menu_item_title_system_va_score', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 230),
+('bx_market_view_actions', 'bx_market', 'favorite', '_sys_menu_item_title_system_va_favorite', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 240),
+('bx_market_view_actions', 'bx_market', 'feature', '_sys_menu_item_title_system_va_feature', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 250),
+('bx_market_view_actions', 'bx_market', 'repost', '_sys_menu_item_title_system_va_repost', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 260),
+('bx_market_view_actions', 'bx_market', 'report', '_sys_menu_item_title_system_va_report', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 270),
+('bx_market_view_actions', 'bx_market', 'notes', '_sys_menu_item_title_system_va_notes', '_sys_menu_item_title_va_notes', 'javascript:void(0)', 'javascript:bx_get_notes(this,  ''{module_uri}'', {content_id});', '', 'exclamation-triangle', '', '', 0, 2147483647, '', 1, 0, 280),
+('bx_market_view_actions', 'bx_market', 'social-sharing-facebook', '_sys_menu_item_title_system_social_sharing_facebook', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 300),
+('bx_market_view_actions', 'bx_market', 'social-sharing-twitter', '_sys_menu_item_title_system_social_sharing_twitter', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 320),
+('bx_market_view_actions', 'bx_market', 'social-sharing-pinterest', '_sys_menu_item_title_system_social_sharing_pinterest', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 330),
+('bx_market_view_actions', 'bx_market', '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_market_my', '_bx_market_menu_title_entries_my', 'bx_market_my', 'bx_market', 9, 0, 1, 'BxMarketMenu', 'modules/boonex/market/classes/BxMarketMenu.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_market_my', 'bx_market', '_bx_market_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_market_my', 'bx_market', 'create-product', '_bx_market_menu_item_title_system_create_entry', '_bx_market_menu_item_title_create_entry', 'page.php?i=create-product', '', '', 'plus', '', 2147483647, 1, 0, 0);
+
+-- MENU: actions menu for snippet
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_market_snippet', '_bx_market_menu_title_snippet', 'bx_market_snippet', 'bx_market', 17, 0, 1, 'BxMarketMenuSnippetActions', 'modules/boonex/market/classes/BxMarketMenuSnippetActions.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_market_snippet', 'bx_market', '_bx_market_menu_set_title_snippet', 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`, `editable`, `order`) VALUES 
+('bx_market_snippet', 'bx_market', 'snippet-more', '_bx_market_menu_item_title_system_snippet_more', '_bx_market_menu_item_title_snippet_more', 'javascript:void(0)', 'bx_menu_popup(''bx_market_snippet_more'', this, {''id'':''bx_market_snippet_{content_id}''}, {id:{content_id}});', '', 'ellipsis-v', '', 'bx_market_snippet_more', 1, 2147483647, 1, 0, 0, 1);
+
+-- MENU: actions more menu for snippet actions menu
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES
+('bx_market_snippet_more', '_bx_market_menu_title_snippet_more', 'bx_market_snippet_more', 'bx_market', 4, 0, 1, 'BxMarketMenuView', 'modules/boonex/market/classes/BxMarketMenuView.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES
+('bx_market_snippet_more', 'bx_market', '_bx_market_menu_set_title_snippet_more', 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`, `order`) VALUES
+('bx_market_snippet_more', 'bx_market', 'download', '_bx_market_menu_item_title_system_download', '_bx_market_menu_item_title_download', 'page.php?i=download-product&id={content_id}', '', '', 'download', '', 0, 2147483647, 1, 0, 10),
+('bx_market_snippet_more', 'bx_market', 'add-to-cart', '_bx_market_menu_item_title_system_add_to_cart', '{add_to_cart_title}', 'javascript:void(0);', 'javascript:{add_to_cart_onclick}', '', 'cart-plus', '', 0, 2147483647, 1, 0, 20),
+('bx_market_snippet_more', 'bx_market', 'subscribe', '_bx_market_menu_item_title_system_subscribe', '{subscribe_title}', 'javascript:void(0);', 'javascript:{subscribe_onclick}', '', 'credit-card', '', 0, 2147483647, 1, 0, 30);
+
+-- 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_market_snippet_meta', '_sys_menu_title_snippet_meta', 'bx_market_snippet_meta', 'bx_market', 15, 0, 1, 'BxMarketMenuSnippetMeta', 'modules/boonex/market/classes/BxMarketMenuSnippetMeta.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_market_snippet_meta', 'bx_market', '_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_market_snippet_meta', 'bx_market', 'author', '_sys_menu_item_title_system_sm_author', '_sys_menu_item_title_sm_author', '', '', '', '', '', 2147483647, 1, 0, 1, 1),
+('bx_market_snippet_meta', 'bx_market', 'date', '_sys_menu_item_title_system_sm_date', '_sys_menu_item_title_sm_date', '', '', '', '', '', 2147483647, 0, 0, 1, 2),
+('bx_market_snippet_meta', 'bx_market', 'category', '_sys_menu_item_title_system_sm_category', '_sys_menu_item_title_sm_category', '', '', '', '', '', 2147483647, 0, 0, 1, 3),
+('bx_market_snippet_meta', 'bx_market', 'tags', '_sys_menu_item_title_system_sm_tags', '_sys_menu_item_title_sm_tags', '', '', '', '', '', 2147483647, 0, 0, 1, 4),
+('bx_market_snippet_meta', 'bx_market', 'views', '_sys_menu_item_title_system_sm_views', '_sys_menu_item_title_sm_views', '', '', '', '', '', 2147483647, 0, 0, 1, 5),
+('bx_market_snippet_meta', 'bx_market', 'comments', '_sys_menu_item_title_system_sm_comments', '_sys_menu_item_title_sm_comments', '', '', '', '', '', 2147483647, 0, 0, 1, 6);
+
+-- 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_market_submenu', '_bx_market_menu_title_submenu', 'bx_market_submenu', 'bx_market', 18, 0, 1, 'BxMarketMenuSubmenu', 'modules/boonex/market/classes/BxMarketMenuSubmenu.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_market_submenu', 'bx_market', '_bx_market_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_market_submenu', 'bx_market', 'products-home', '_bx_market_menu_item_title_system_entries_public', '_bx_market_menu_item_title_entries_public', 'page.php?i=products-home', '', '', '', '', 2147483647, 1, 1, 1),
+('bx_market_submenu', 'bx_market', 'products-latest', '_bx_market_menu_item_title_system_entries_latest', '_bx_market_menu_item_title_entries_latest', 'page.php?i=products-latest', '', '', '', '', 2147483647, 1, 1, 2),
+('bx_market_submenu', 'bx_market', 'products-featured', '_bx_market_menu_item_title_system_entries_featured', '_bx_market_menu_item_title_entries_featured', 'page.php?i=products-featured', '', '', '', '', 2147483647, 1, 1, 3),
+('bx_market_submenu', 'bx_market', 'products-popular', '_bx_market_menu_item_title_system_entries_popular', '_bx_market_menu_item_title_entries_popular', 'page.php?i=products-popular', '', '', '', '', 2147483647, 1, 1, 4),
+('bx_market_submenu', 'bx_market', 'products-top', '_bx_market_menu_item_title_system_entries_top', '_bx_market_menu_item_title_entries_top', 'page.php?i=products-top', '', '', '', '', 2147483647, 1, 1, 5),
+('bx_market_submenu', 'bx_market', 'products-updated', '_bx_market_menu_item_title_system_entries_updated', '_bx_market_menu_item_title_entries_updated', 'page.php?i=products-updated', '', '', '', '', 2147483647, 1, 1, 6),
+('bx_market_submenu', 'bx_market', 'products-categories', '_bx_market_menu_item_title_system_entries_categories', '_bx_market_menu_item_title_entries_categories', 'page.php?i=products-categories', '', '', '', '', 2147483647, 1, 1, 7),
+('bx_market_submenu', 'bx_market', 'products-search', '_bx_market_menu_item_title_system_entries_search', '_bx_market_menu_item_title_entries_search', 'page.php?i=products-search', '', '', '', '', 2147483647, 1, 1, 8),
+('bx_market_submenu', 'bx_market', 'products-manage', '_bx_market_menu_item_title_system_entries_manage', '_bx_market_menu_item_title_entries_manage', 'page.php?i=products-manage', '', '', '', '', 2147483646, 1, 1, 9),
+('bx_market_submenu', 'bx_market', 'more-auto', '_sys_menu_item_title_system_more_auto', '_sys_menu_item_title_more_auto', 'javascript:void(0)', '', '', '', '', 2147483647, 1, 0, 9999);
+
+-- MENU: sub-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_market_view_submenu', '_bx_market_menu_title_view_entry_submenu', 'bx_market_view_submenu', 'bx_market', 8, 0, 1, 'BxMarketMenuView', 'modules/boonex/market/classes/BxMarketMenuView.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_market_view_submenu', 'bx_market', '_bx_market_menu_set_title_view_entry_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_market_view_submenu', 'bx_market', 'view-product', '_bx_market_menu_item_title_system_view_entry_submenu_entry', '_bx_market_menu_item_title_view_entry_submenu_entry', 'page.php?i=view-product&id={content_id}', '', '', '', '', 2147483647, 1, 0, 1),
+('bx_market_view_submenu', 'bx_market', 'view-product-info', '_bx_market_menu_item_title_system_view_entry_submenu_info', '_bx_market_menu_item_title_view_entry_submenu_info', 'page.php?i=view-product-info&id={content_id}', '', '', '', '', 2147483647, 1, 0, 2),
+('bx_market_view_submenu', 'bx_market', 'view-product-comments', '_bx_market_menu_item_title_system_view_entry_submenu_comments', '_bx_market_menu_item_title_view_entry_submenu_comments', 'page.php?i=view-product-comments&id={content_id}', '', '', '', '', 2147483647, 1, 0, 3);
+
+-- MENU: licenses submenu
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_market_licenses_submenu', '_bx_market_menu_title_licenses_submenu', 'bx_market_licenses_submenu', 'bx_market', 6, 0, 1, '', '');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_market_licenses_submenu', 'bx_market', '_bx_market_menu_set_title_licenses_submenu', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `addon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `editable`, `order`) VALUES 
+('bx_market_licenses_submenu', 'bx_market', 'products-licenses-administration', '_bx_market_menu_item_title_system_products_licenses_administration', '_bx_market_menu_item_title_products_licenses_administration', 'page.php?i=products-licenses-administration', '', '_self', '', '', '', 192, 1, 0, 1, 1),
+('bx_market_licenses_submenu', 'bx_market', 'products-licenses', '_bx_market_menu_item_title_system_products_licenses', '_bx_market_menu_item_title_products_licenses', 'page.php?i=products-licenses', '', '_self', '', '', '', 2147483646, 1, 0, 1, 2);
+
+-- 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_market', 'profile-stats-manage-products', '_bx_market_menu_item_title_system_manage_my_products', '_bx_market_menu_item_title_manage_my_products', 'page.php?i=products-manage', '', '_self', 'shopping-cart col-green3', 'a:2:{s:6:"module";s:9:"bx_market";s:6:"method";s:41:"get_menu_addon_manage_tools_profile_stats";}', '', 2147483646, 1, 0, @iNotifMenuOrder + 1);
+
+-- 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_market_menu_manage_tools', '_bx_market_menu_title_manage_tools', 'bx_market_menu_manage_tools', 'bx_market', 6, 0, 1, 'BxMarketMenuManageTools', 'modules/boonex/market/classes/BxMarketMenuManageTools.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_market_menu_manage_tools', 'bx_market', '_bx_market_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_market_menu_manage_tools', 'bx_market', 'delete-with-content', '_bx_market_menu_item_title_system_delete_with_content', '_bx_market_menu_item_title_delete_with_content', 'javascript:void(0)', 'javascript:{js_object}.onClickDeleteWithContent({content_id});', '_self', 'far trash-alt', '', 128, 1, 0, 0);
+
+-- 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_market', 'products-administration', '_bx_market_menu_item_title_system_admt_products', '_bx_market_menu_item_title_admt_products', 'page.php?i=products-administration', '', '_self', 'shopping-cart', 'a:2:{s:6:"module";s:9:"bx_market";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_market', 'products-author', '_bx_market_menu_item_title_system_view_entries_author', '_bx_market_menu_item_title_view_entries_author', 'page.php?i=products-author&profile_id={profile_id}', '', '', 'shopping-cart col-green3', '', 2147483647, 1, 0, 0),
+('trigger_group_view_submenu', 'bx_market', 'products-context', '_bx_market_menu_item_title_system_view_entries_in_context', '_bx_market_menu_item_title_view_entries_in_context', 'page.php?i=products-context&profile_id={profile_id}', '', '', 'shopping-cart col-green3', '', 2147483647, 1, 0, 0);
+
+-- MENU: account dashboard
+SET @iMoAccountDashboard = (SELECT IFNULL(MAX(`order`), 0) FROM `sys_menu_items` WHERE `set_name`='sys_account_dashboard' 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`, `editable`, `order`) VALUES
+('sys_account_dashboard', 'bx_market', 'dashboard-licenses', '_bx_market_menu_item_title_system_licenses', '_bx_market_menu_item_title_licenses', 'page.php?i=products-licenses', '', '', 'certificate col-green2', '', '', 2147483646, 1, 0, 1, @iMoAccountDashboard + 1);
+
+
+-- 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_market_allow_view_to', 'bx_market', 'view', '_bx_market_form_entry_input_allow_view_to', '3', 'all', 'bx_market_products', 'id', 'author', '', ''),
+('bx_market_allow_purchase_to', 'bx_market', 'purchase', '_bx_market_form_entry_input_allow_purchase_to', '3', '', 'bx_market_products', 'id', 'author', '', ''),
+('bx_market_allow_comment_to', 'bx_market', 'comment', '_bx_market_form_entry_input_allow_comment_to', 'c', '', 'bx_market_products', 'id', 'author', 'BxMarketPrivacy', 'modules/boonex/market/classes/BxMarketPrivacy.php'),
+('bx_market_allow_vote_to', 'bx_market', 'vote', '_bx_market_form_entry_input_allow_vote_to', 'c', '', 'bx_market_products', 'id', 'author', 'BxMarketPrivacy', 'modules/boonex/market/classes/BxMarketPrivacy.php'),
+('bx_market_allow_view_favorite_list', 'bx_market', 'view_favorite_list', '_bx_market_form_entry_input_allow_view_favorite_list', '3', 'all', 'bx_market_favorites_lists', 'id', 'author_id', '', '');
+
+
+-- ACL
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_market', 'create entry', NULL, '_bx_market_acl_action_create_entry', '', 1, 3);
+SET @iIdActionEntryCreate = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_market', 'delete entry', NULL, '_bx_market_acl_action_delete_entry', '', 1, 3);
+SET @iIdActionEntryDelete = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_market', 'download entry', NULL, '_bx_market_acl_action_download_entry', '', 1, 0);
+SET @iIdActionEntryDownload = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_market', 'view entry', NULL, '_bx_market_acl_action_view_entry', '', 1, 0);
+SET @iIdActionEntryView = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_market', 'set thumb', NULL, '_bx_market_acl_action_set_thumb', '', 1, 3);
+SET @iIdActionSetThumb = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_market', 'set cover', NULL, '_bx_market_acl_action_set_cover', '', 1, 3);
+SET @iIdActionSetCover = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_market', 'set subentries', NULL, '_bx_market_acl_action_set_subentries', '', 1, 3);
+SET @iIdActionSetSubentries = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_market', 'edit any entry', NULL, '_bx_market_acl_action_edit_any_entry', '', 1, 3);
+SET @iIdActionEntryEditAny = 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
+
+-- entry create
+(@iStandard, @iIdActionEntryCreate),
+(@iModerator, @iIdActionEntryCreate),
+(@iAdministrator, @iIdActionEntryCreate),
+(@iPremium, @iIdActionEntryCreate),
+
+-- entry delete
+(@iStandard, @iIdActionEntryDelete),
+(@iModerator, @iIdActionEntryDelete),
+(@iAdministrator, @iIdActionEntryDelete),
+(@iPremium, @iIdActionEntryDelete),
+
+-- entry download
+(@iUnauthenticated, @iIdActionEntryDownload),
+(@iAccount, @iIdActionEntryDownload),
+(@iStandard, @iIdActionEntryDownload),
+(@iUnconfirmed, @iIdActionEntryDownload),
+(@iPending, @iIdActionEntryDownload),
+(@iModerator, @iIdActionEntryDownload),
+(@iAdministrator, @iIdActionEntryDownload),
+(@iPremium, @iIdActionEntryDownload),
+
+-- entry view
+(@iUnauthenticated, @iIdActionEntryView),
+(@iAccount, @iIdActionEntryView),
+(@iStandard, @iIdActionEntryView),
+(@iUnconfirmed, @iIdActionEntryView),
+(@iPending, @iIdActionEntryView),
+(@iModerator, @iIdActionEntryView),
+(@iAdministrator, @iIdActionEntryView),
+(@iPremium, @iIdActionEntryView),
+
+-- set entry thumb
+(@iStandard, @iIdActionSetThumb),
+(@iModerator, @iIdActionSetThumb),
+(@iAdministrator, @iIdActionSetThumb),
+(@iPremium, @iIdActionSetThumb),
+
+-- set entry cover
+(@iStandard, @iIdActionSetCover),
+(@iModerator, @iIdActionSetCover),
+(@iAdministrator, @iIdActionSetCover),
+(@iPremium, @iIdActionSetCover),
+
+-- set entry subentries
+(@iStandard, @iIdActionSetSubentries),
+(@iModerator, @iIdActionSetSubentries),
+(@iAdministrator, @iIdActionSetSubentries),
+(@iPremium, @iIdActionSetSubentries),
+
+-- edit any entry
+(@iModerator, @iIdActionEntryEditAny),
+(@iAdministrator, @iIdActionEntryEditAny);
+
+
+-- SEARCH
+SET @iSearchOrder = (SELECT IFNULL(MAX(`Order`), 0) FROM `sys_objects_search`);
+INSERT INTO `sys_objects_search` (`ObjectName`, `Title`, `Order`, `ClassName`, `ClassPath`) VALUES
+('bx_market', '_bx_market', @iSearchOrder + 1, 'BxMarketSearchResult', 'modules/boonex/market/classes/BxMarketSearchResult.php'),
+('bx_market_cmts', '_bx_market_cmts', @iSearchOrder + 2, 'BxMarketCmtsSearchResult', 'modules/boonex/market/classes/BxMarketCmtsSearchResult.php');
+
+-- CONNECTIONS
+INSERT INTO `sys_objects_connection` (`object`, `table`, `type`, `override_class_name`, `override_class_file`) VALUES
+('bx_market_subentries', 'bx_market_subproducts', 'one-way', '', '');
+
+-- METATAGS
+INSERT INTO `sys_objects_metatags` (`object`, `table_keywords`, `table_locations`, `table_mentions`, `override_class_name`, `override_class_file`) VALUES
+('bx_market', 'bx_market_meta_keywords', 'bx_market_meta_locations', 'bx_market_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_market_cats', 'bx_market', 'bx_market', 'bx_market_cats', 'bx_market_products', 'cat', 'INNER JOIN `sys_profiles` ON (`sys_profiles`.`id` = `bx_market_products`.`author`)', 'AND `sys_profiles`.`status` = ''active''', '', '');
+
+-- STATS
+SET @iMaxOrderStats = (SELECT IFNULL(MAX(`order`), 0) FROM `sys_statistics`);
+INSERT INTO `sys_statistics` (`module`, `name`, `title`, `link`, `icon`, `query`, `order`) VALUES 
+('bx_market', 'bx_market', '_bx_market', 'page.php?i=products-home', 'shopping-cart col-green3', 'SELECT COUNT(*) FROM `bx_market_products` WHERE 1 AND `status` = ''active'' AND `status_admin` = ''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_market_growth', '_bx_market_chart_growth', 'bx_market_products', 'added', '', 'status,status_admin', '', 1, @iMaxOrderCharts + 1, 'BxDolChartGrowth', ''),
+('bx_market_growth_speed', '_bx_market_chart_growth_speed', 'bx_market_products', 'added', '', 'status,status_admin', '', 1, @iMaxOrderCharts + 2, 'BxDolChartGrowthSpeed', '');
+
+-- GRIDS: moderation tools
+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_market_administration', 'Sql', 'SELECT * FROM `bx_market_products` WHERE 1 ', 'bx_market_products', 'id', 'added', 'status_admin', '', 20, NULL, 'start', '', 'title,text', '', 'like', 'reports', '', 192, 'BxMarketGridAdministration', 'modules/boonex/market/classes/BxMarketGridAdministration.php'),
+('bx_market_common', 'Sql', 'SELECT * FROM `bx_market_products` WHERE 1 ', 'bx_market_products', 'id', 'added', 'status', '', 20, NULL, 'start', '', 'title,text', '', 'like', '', '', 2147483647, 'BxMarketGridCommon', 'modules/boonex/market/classes/BxMarketGridCommon.php'),
+
+-- GRIDS: Licenses
+('bx_market_licenses_administration', 'Sql', 'SELECT `tl`.`id` AS `id`, `tl`.`profile_id` AS `profile_id`, `tl`.`product_id` AS `product_id`, `tp`.`title` AS `product`, `tl`.`order` AS `transaction`, `tl`.`license` AS `license`, `tl`.`type` AS `type`, `tl`.`domain` AS `domain`, `tl`.`added` AS `added`, `tl`.`expired` AS `expired` FROM `bx_market_licenses` AS `tl` LEFT JOIN `bx_market_products` AS `tp` ON `tl`.`product_id`=`tp`.`id` WHERE 1 ', 'bx_market_licenses', 'id', 'added', '', '', 20, NULL, 'start', '', 'tp`.`title,tl`.`order,tl`.`license,tl`.`type,tl`.`domain', '', 'like', '', '', 192, 'BxMarketGridLicensesAdministration', 'modules/boonex/market/classes/BxMarketGridLicensesAdministration.php'),
+('bx_market_licenses', 'Sql', 'SELECT `tl`.`id` AS `id`, `tl`.`profile_id` AS `profile_id`, `tl`.`product_id` AS `product_id`, `tp`.`title` AS `product`, `tl`.`order` AS `transaction`, `tl`.`license` AS `license`, `tl`.`type` AS `type`, `tl`.`domain` AS `domain`, `tl`.`added` AS `added`, `tl`.`expired` AS `expired` FROM `bx_market_licenses` AS `tl` LEFT JOIN `bx_market_products` AS `tp` ON `tl`.`product_id`=`tp`.`id` WHERE 1 ', 'bx_market_licenses', 'id', 'added', '', '', 20, NULL, 'start', '', 'tp`.`title,tl`.`order,tl`.`license,tl`.`type,tl`.`domain', '', 'like', '', '', 2147483647, 'BxMarketGridLicenses', 'modules/boonex/market/classes/BxMarketGridLicenses.php');
+
+
+INSERT INTO `sys_grid_fields` (`object`, `name`, `title`, `width`, `translatable`, `chars_limit`, `params`, `order`) VALUES
+('bx_market_administration', 'checkbox', '_sys_select', '2%', 0, '', '', 1),
+('bx_market_administration', 'switcher', '_bx_market_grid_column_title_adm_active', '8%', 0, '', '', 2),
+('bx_market_administration', 'reports', '_sys_txt_reports_title', '5%', 0, '', '', 3),
+('bx_market_administration', 'title', '_bx_market_grid_column_title_adm_title', '25%', 0, '', '', 4),
+('bx_market_administration', 'added', '_bx_market_grid_column_title_adm_added', '20%', 1, '25', '', 5),
+('bx_market_administration', 'author', '_bx_market_grid_column_title_adm_author', '20%', 0, '25', '', 6),
+('bx_market_administration', 'actions', '', '20%', 0, '', '', 7),
+
+('bx_market_common', 'checkbox', '_sys_select', '2%', 0, '', '', 1),
+('bx_market_common', 'switcher', '_bx_market_grid_column_title_adm_active', '8%', 0, '', '', 2),
+('bx_market_common', 'title', '_bx_market_grid_column_title_adm_title', '40%', 0, '', '', 3),
+('bx_market_common', 'added', '_bx_market_grid_column_title_adm_added', '30%', 1, '25', '', 4),
+('bx_market_common', 'actions', '', '20%', 0, '', '', 5),
+
+('bx_market_licenses_administration', 'profile_id', '_bx_market_grid_column_title_lcs_profile_id', '10%', 0, '28', '', 1),
+('bx_market_licenses_administration', 'product', '_bx_market_grid_column_title_lcs_product', '20%', 0, '28', '', 2),
+('bx_market_licenses_administration', 'transaction', '_bx_market_grid_column_title_lcs_transaction', '10%', 0, '32', '', 3),
+('bx_market_licenses_administration', 'license', '_bx_market_grid_column_title_lcs_license', '10%', 0, '8', '', 4),
+('bx_market_licenses_administration', 'type', '_bx_market_grid_column_title_lcs_type', '5%', 1, '12', '', 5),
+('bx_market_licenses_administration', 'domain', '_bx_market_grid_column_title_lcs_domain', '15%', 0, '18', '', 6),
+('bx_market_licenses_administration', 'added', '_bx_market_grid_column_title_lcs_added', '10%', 1, '25', '', 7),
+('bx_market_licenses_administration', 'expired', '_bx_market_grid_column_title_lcs_expired', '10%', 1, '25', '', 8),
+('bx_market_licenses_administration', 'actions', '', '10%', 0, '', '', 9),
+
+('bx_market_licenses', 'product', '_bx_market_grid_column_title_lcs_product', '20%', 0, '28', '', 1),
+('bx_market_licenses', 'transaction', '_bx_market_grid_column_title_lcs_transaction', '10%', 0, '32', '', 2),
+('bx_market_licenses', 'license', '_bx_market_grid_column_title_lcs_license', '10%', 0, '8', '', 3),
+('bx_market_licenses', 'type', '_bx_market_grid_column_title_lcs_type', '10%', 1, '12', '', 4),
+('bx_market_licenses', 'domain', '_bx_market_grid_column_title_lcs_domain', '20%', 0, '18', '', 5),
+('bx_market_licenses', 'added', '_bx_market_grid_column_title_lcs_added', '10%', 1, '25', '', 6),
+('bx_market_licenses', 'expired', '_bx_market_grid_column_title_lcs_expired', '10%', 1, '25', '', 7),
+('bx_market_licenses', 'actions', '', '10%', 0, '', '', 8);
+
+INSERT INTO `sys_grid_actions` (`object`, `type`, `name`, `title`, `icon`, `icon_only`, `confirm`, `order`) VALUES
+('bx_market_administration', 'bulk', 'delete', '_bx_market_grid_action_title_adm_delete', '', 0, 1, 1),
+('bx_market_administration', 'bulk', 'clear_reports', '_bx_market_grid_action_title_adm_clear_reports', '', 0, 1, 2),
+('bx_market_administration', 'single', 'edit', '_bx_market_grid_action_title_adm_edit', 'pencil-alt', 1, 0, 1),
+('bx_market_administration', 'single', 'delete', '_bx_market_grid_action_title_adm_delete', 'remove', 1, 1, 2),
+('bx_market_administration', 'single', 'settings', '_bx_market_grid_action_title_adm_more_actions', 'cog', 1, 0, 3),
+('bx_market_administration', 'single', 'audit_content', '_bx_market_grid_action_title_adm_audit_content', 'search', 1, 0, 4),
+('bx_market_administration', 'single', 'clear_reports', '_bx_market_grid_action_title_adm_clear_reports', 'eraser', 1, 0, 5),
+('bx_market_common', 'bulk', 'delete', '_bx_market_grid_action_title_adm_delete', '', 0, 1, 1),
+('bx_market_common', 'single', 'edit', '_bx_market_grid_action_title_adm_edit', 'pencil-alt', 1, 0, 1),
+('bx_market_common', 'single', 'delete', '_bx_market_grid_action_title_adm_delete', 'remove', 1, 1, 2),
+('bx_market_common', 'single', 'settings', '_bx_market_grid_action_title_adm_more_actions', 'cog', 1, 0, 3),
+
+('bx_market_licenses_administration', 'single', 'reset', '_bx_market_grid_action_title_lcs_reset', 'eraser', 1, 1, 1),
+('bx_market_licenses', 'single', 'reset', '_bx_market_grid_action_title_lcs_reset', 'eraser', 1, 1, 1);
+
+
+-- UPLOADERS
+INSERT INTO `sys_objects_uploader` (`object`, `active`, `override_class_name`, `override_class_file`) VALUES
+('bx_market_simple', 1, 'BxMarketUploaderSimple', 'modules/boonex/market/classes/BxMarketUploaderSimple.php'),
+('bx_market_html5', 1, 'BxMarketUploaderHTML5', 'modules/boonex/market/classes/BxMarketUploaderHTML5.php');
+
+
+-- ALERTS
+INSERT INTO `sys_alerts_handlers` (`name`, `class`, `file`, `service_call`) VALUES 
+('bx_market', 'BxMarketAlertsResponse', 'modules/boonex/market/classes/BxMarketAlertsResponse.php', '');
+SET @iHandler := LAST_INSERT_ID();
+
+INSERT INTO `sys_alerts` (`unit`, `action`, `handler_id`) VALUES
+('system', 'save_setting', @iHandler),
+('bx_market_files', 'file_deleted', @iHandler),
+('bx_market_files', 'file_downloaded', @iHandler),
+('bx_market_photos', 'file_deleted', @iHandler),
+('profile', 'delete', @iHandler);
+
+
+-- CRON
+INSERT INTO `sys_cron_jobs` (`name`, `time`, `class`, `file`, `service_call`) VALUES
+('bx_market_pruning', '0 0 * * *', 'BxMarketCronPruning', 'modules/boonex/market/classes/BxMarketCronPruning.php', '');
+
+
+-- EMAIL TEMPLATES
+INSERT INTO `sys_email_templates` (`Module`, `NameSystem`, `Name`, `Subject`, `Body`) VALUES 
+('bx_market', '_bx_market_et_txt_name_purchased', 'bx_market_purchased', '_bx_market_et_txt_subject_purchased', '_bx_market_et_txt_body_purchased');

+ 133 - 0
modules/boonex/market/updates/12.0.2_12.0.3/source/js/entry.js

@@ -0,0 +1,133 @@
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Market Market
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+function BxMarketEntry(oOptions) {
+	this._sActionsUri = oOptions.sActionUri;
+    this._sActionsUrl = oOptions.sActionUrl;
+    this._sObjName = oOptions.sObjName == undefined ? 'oBxMarketEntry' : oOptions.sObjName;
+    this._iOwnerId = oOptions.iOwnerId == undefined ? 0 : oOptions.iOwnerId;
+    this._sAnimationEffect = oOptions.sAnimationEffect == undefined ? 'slide' : oOptions.sAnimationEffect;
+    this._iAnimationSpeed = oOptions.iAnimationSpeed == undefined ? 'slow' : oOptions.iAnimationSpeed;
+    this._aHtmlIds = oOptions.aHtmlIds == undefined ? {} : oOptions.aHtmlIds;
+    this._oRequestParams = oOptions.oRequestParams == undefined ? {} : oOptions.oRequestParams;
+
+    var $this = this;
+    $(document).ready(function() {
+    	$this.initScreenshots();
+    });
+}
+
+BxMarketEntry.prototype.perform = function(oLink, sAction, iId) {
+	var oDate = new Date();
+    var oData = {
+    	action: sAction,
+    	id: iId,
+		_t:oDate.getTime()
+    };
+
+    $(oLink).parents('.bx-popup-applied:first:visible').dolPopupHide({});
+
+    $.post(
+        this._sActionsUrl + 'perform/',
+        oData,
+        function(oData) {
+        	processJsonData(oData);
+        },
+        'json'
+    );
+};
+
+BxMarketEntry.prototype.checkName = function(sTitleId, sNameId, iId) {
+	var oDate = new Date();
+
+	var oName = jQuery("[name='" + sNameId + "']");
+	var sName = oName.val();
+	var bName = sName.length != 0;
+	
+	var oTitle = jQuery("[name='" + sTitleId + "']");
+	var sTitle = oTitle.val();
+	var bTitle = sTitle.length != 0;
+
+	if(!bName && !bTitle)
+		return;
+
+	var sTitleCheck = '';
+	if(bName)
+		sTitleCheck = sName;
+	else if(bTitle) {
+		sTitleCheck = sTitle;
+
+		sTitle = sTitle.replace(/[^A-Za-z0-9_]/g, '-');
+		sTitle = sTitle.replace(/[-]{2,}/g, '-');
+		oName.val(sTitle.toLowerCase());
+	}
+
+	jQuery.get(
+		this._sActionsUrl + 'check_name',
+		{
+			title: sTitleCheck,
+			id: iId && parseInt(iId) > 0 ? iId : 0,
+    		_t: oDate.getTime()
+    	},
+    	function(oData) {
+    		if(!oData || oData.name == undefined)
+    			return;
+
+    		oName.val(oData.name);
+    	},
+    	'json'
+	);
+};
+
+BxMarketEntry.prototype.changeFileType = function(oSelect) {
+	var sValue = jQuery(oSelect).val();
+
+	jQuery(oSelect).parents('.bx-uploader-ghost:first').find('.bx-uploader-ghost-type-rel:visible').bx_anim('hide', 'fade', 'fast', function() {
+		jQuery(this).parent().find('.bx-uploader-ghost-type-' + sValue).bx_anim('show', 'fade', 'fast');
+	});
+};
+
+BxMarketEntry.prototype.initScreenshots = function() {
+	var oItems = jQuery(".bx-market-screenshots .bx-market-ss-item");
+	if(oItems.length == 0)
+            return;
+
+	var iWidth = oItems.width();
+	var iWidthOuter = oItems.outerWidth();
+	var bBusy = false;
+
+	oItems.find('a[rel=group]').fancybox({
+            type: 'image',
+            transitionIn: 'elastic',
+            transitionOut: 'elastic',
+            speedIn: 600,
+            speedOut: 200
+	});
+
+	if(oItems.length <= 2)
+            return;
+
+	$('.bx-market-screenshots').flickity({
+            cellSelector: '.bx-market-ss-item',
+            cellAlign: 'left',
+            imagesLoaded: true,
+            wrapAround: true,
+            pageDots: false
+	});
+};
+
+/**
+ * Is used on Downloads page to show old versions. 
+ */
+BxMarketEntry.prototype.showMore = function() {
+	$('.bx-market-attachment:not(.bx-market-attachment-main)').bx_anim('toggle', this._sAnimationEffect, this._sAnimationSpeed);
+};
+
+/** @} */

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

@@ -0,0 +1,51 @@
+<?php
+/**
+ * Copyright (c) BoonEx Pty Limited - http://www.boonex.com/
+ * CC-BY License - http://creativecommons.org/licenses/by/3.0/
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'title' => 'Mass mailer',
+    '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/massmailer/updates/update_12.0.0_12.0.1/',
+    'home_uri' => 'massmailer_update_1200_1201',
+
+    'module_dir' => 'boonex/massmailer/',
+    'module_uri' => 'massmailer',
+
+    'db_prefix' => 'bx_massmailer_',
+    'class_prefix' => 'BxMassMailer',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 0,
+        'update_files' => 1,
+        'update_languages' => 0,
+        'clear_db_cache' => 0,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'MassMailer',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

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

@@ -0,0 +1,13 @@
+<?php
+/**
+ * Copyright (c) BoonEx Pty Limited - http://www.boonex.com/
+ * CC-BY License - http://creativecommons.org/licenses/by/3.0/
+ */
+
+class BxMassMailerUpdater extends BxDolStudioUpdater
+{
+    function __construct($aConfig)
+    {
+        parent::__construct($aConfig);
+    }
+}

+ 662 - 0
modules/boonex/massmailer/updates/12.0.0_12.0.1/source/classes/BxMassMailerModule.php

@@ -0,0 +1,662 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+* Copyright (c) UNA, Inc - https://una.io
+* MIT License - https://opensource.org/licenses/MIT
+*
+* @defgroup    MassMailer Mass Mailer
+* @ingroup     UnaModules
+*
+* @{
+*/
+
+class BxMassMailerModule extends BxBaseModGeneralModule
+{
+    private $aSegments = array();
+          
+    function __construct(&$aModule)
+    {
+        parent::__construct($aModule);
+        $CNF = &$this->_oConfig->CNF;
+        $aRv = array('lvl:0' => _t('_bx_massmailer_segments_all'));
+        $oAccountQuery = BxDolAclQuery::getInstance();
+              
+        $aTmp = array();
+        $oAccountQuery->getLevels(array('type' => 'all_active_pair'), $aTmp);
+        foreach ($aTmp as $sKey => $sTmp){
+            if ($sKey != MEMBERSHIP_ID_NON_MEMBER && $sKey != MEMBERSHIP_ID_ACCOUNT)
+                $aRv['lvl:' . $sKey] = _t($sTmp);
+        };
+              
+        $aTmp = $this->_oDb->getSegments();
+        foreach ($aTmp as $sKey => $sTmp){
+            $aRv['cst:' . $sKey] = _t($sTmp);
+        };
+        $this->aSegments = $aRv;
+    }
+          
+    /**
+    * ACTION METHODS
+    */
+    public function actionTrack($sActionName, $sHash)
+    {
+        if (isset($sHash) && trim($sHash) != ""){
+            switch ($sActionName) {
+                case 'click':
+                    $sLink = $this->_oDb->updateDateClickForLink($sHash);
+                    if (strpos($sLink, '://') === false)
+                        $sLink = BX_DOL_URL_ROOT . $sLink;
+                    header('Location: ' . $sLink);
+                    break;
+                    
+                case 'seen':
+                    header('Content-Type: image/png');
+                    $this->_oDb->updateDateSeenForLetter($sHash);
+                    break;
+            }
+        }
+    }
+    
+    public function actionGetReportsData($sReportName, $sReportType, $sDateFrom, $sDateTo, $sSegment)
+    {
+        if($this->checkAllowed() !== CHECK_ACTION_RESULT_ALLOWED)
+            return '';
+        
+        header('Content-Type: application/json');
+        
+        $aColors = array('#3366CC', '#DC3912', '#FF9900', '#109618', '#990099');
+        $iDateFrom = strtotime($sDateFrom);
+        $iDateTo = strtotime($sDateTo);
+        $sType = "bar";
+        $bIsTimeX = false;
+        $iMinValueY = 0;
+        $iMaxValueY = 0;
+        $aValues = array('labels' => array(), 'values' => array(array('legend' => '', 'data' => array())), 'links' => array(), 'strings' => array(0 => _t('_bx_massmailer_txt_item'), 1 => _t('_bx_massmailer_txt_value')));
+        
+        switch ($sReportName) {
+            case "SUBSCRIBERS_INFO":
+                $sType = "line";
+                $bIsTimeX = true;
+                $aValues['strings'][0] = _t('_bx_massmailer_txt_date');
+                $aValues['strings'][1] = '';
+                $sSql = $this->getSqlBySegment($sSegment);
+                $aData = $this->_oDb->getAccountsByTermsStat($iDateFrom, $iDateTo, $sSql);
+                $aData2 = $this->_oDb->getAccountsByTermsStatUnsubscribe($iDateFrom, $iDateTo, $sSql);
+                $iValuePrev = $this->_oDb->getAccountsByTermsStatInitValue($iDateFrom, $sSql);
+                $iValuePrev2 = $this->_oDb->getAccountsByTermsStatInitValueUnsubscribe($iDateFrom, $sSql);
+                $aTmpDates = array();
+                $aTmpDates2 = array();
+                $aValues['values'][0]['legend'] = _t('_bx_massmailer_txt_subscribed');
+                $aValues['values'][1] = array('legend' => _t('_bx_massmailer_txt_unsubscribed') , 'data' => array());
+                foreach ($aData as $aValue) {
+                    $aTmpDates[$aValue['period']] = $aValue['count'];
+                }
+                foreach ($aData2 as $aValue) {
+                    $aTmpDates2[$aValue['period']] = $aValue['count'];
+                }
+                for ($i = $iDateFrom; $i < $iDateTo ; $i = $i + 86400 ){
+                    $sX = date('Y-m-d', $i);
+                    
+                    if (!array_key_exists($sX, $aTmpDates)){
+                        array_push($aValues['values'][0]['data'], array('x' => $sX, 'y' => $sReportType == 'content_total' ? $iValuePrev : 0));
+                        
+                    }
+                    else{
+                        array_push($aValues['values'][0]['data'], array('x' => $sX, 'y' => $sReportType == 'content_total' ? $iValuePrev : $aTmpDates[$sX]));
+                        $iValuePrev += $aTmpDates[$sX];
+                    }
+                    
+                    if (!array_key_exists($sX, $aTmpDates2)){
+                        array_push($aValues['values'][1]['data'], array('x' => $sX, 'y' => $sReportType == 'content_total' ? $iValuePrev2 : 0));
+                        
+                    }
+                    else{
+                        array_push($aValues['values'][1]['data'], array('x' => $sX, 'y' => $sReportType == 'content_total' ? $iValuePrev2 : $aTmpDates2[$sX]));
+                        $iValuePrev2 += $aTmpDates2[$sX];
+                    }
+                    
+                    if ($sReportType == 'content_total'){
+                        if ($iValuePrev > $iMaxValueY)
+                            $iMaxValueY = $iValuePrev;
+                        if ($iValuePrev2 > $iMaxValueY)
+                            $iMaxValueY = $iValuePrev2;
+                    }
+                    else{
+                        if (array_key_exists($sX, $aTmpDates) && $aTmpDates[$sX] > $iMaxValueY)
+                            $iMaxValueY = $aTmpDates[$sX];
+                        if (array_key_exists($sX, $aTmpDates2) && $aTmpDates2[$sX] > $iMaxValueY)
+                            $iMaxValueY = $aTmpDates2[$sX];
+                    }
+                }
+                break;
+            
+            case "CAMPAIGN_REPORT":
+                $aDataStat = $this->_oDb->getStatByCampaignId($sReportType);
+                $aValues['values'][0]['legend'] = _t('_bx_massmailer_txt_sent_total_title', $aDataStat['total']);
+                array_push($aValues['values'][0]['data'], $aDataStat['total']);
+                $aValues['values'][1] = array('legend' => _t('_bx_massmailer_txt_opened_total_title', $aDataStat['seen']) , 'data' => array($aDataStat['seen']));
+                $aValues['values'][2] = array('legend' => _t('_bx_massmailer_txt_unopened_total_title', $aDataStat['total'] - $aDataStat['seen']), 'data' => array($aDataStat['total'] - $aDataStat['seen']));
+                $aValues['values'][3] = array('legend' => _t('_bx_massmailer_txt_clicked_total_title', $aDataStat['clicked']), 'data' => array($aDataStat['clicked']));
+                $aValues['values'][4] = array('legend' => _t('_bx_massmailer_txt_unsubscribed_total_title', $aDataStat['unsubscribed']), 'data' => array($aDataStat['unsubscribed']));
+                $iMaxValueY = $aDataStat['total'];
+                break;
+        }
+        
+        $iMaxValueY = ceil($iMaxValueY * 1.1);
+        
+        $aDataForChartXAxes = array();
+        if ($bIsTimeX){
+            $sUnit = 'day';
+            $iInterval = ($iDateTo - $iDateFrom) / 86400;
+            if ($iInterval > 50)
+                $sUnit = 'week';
+            if ($iInterval > 100)
+                $sUnit = 'month';
+            
+            $aDataForChartXAxes = array(
+                'type' => 'time',
+                'time' => array(
+                    'tooltipFormat' => 'DD.MM.YYYY',
+                    'unit' => $sUnit,
+                 ),
+                'display' => true,
+                'distribution' => 'linear',
+                'ticks' => array(
+                    'display' => true,
+                    'autoSkip' => true,
+                )
+            );
+        }
+        else{
+            $aDataForChartXAxes = array(
+                'ticks' => array(
+                    'autoSkip' => false
+                ),
+                'display' => true
+            );
+        }
+        
+        $aDataForChartDatasets = array();
+        for($i = 0; $i < count($aValues['values']); $i++){
+            $aDataForChartDatasets[] = array(
+                'label' => $aValues['values'][$i]['legend'],
+                'fill' => false,
+                'backgroundColor' => $aColors[$i],
+                'borderColor' => $aColors[$i],
+                'borderWidth' => 1,
+                'data' => $aValues['values'][$i]['data']
+            );
+        }
+        
+        $aDataForChart = array(
+            'type' => $sType,
+            'data' => array(
+                'labels' => $aValues['labels'],
+                'datasets' => $aDataForChartDatasets
+            ),
+            'options' => array(
+                'legend' => array(
+                    'position' => 'bottom',
+                    'display' => count($aValues['values']) == 1 ? false : true
+                ),
+                'scales' => array(
+                    'yAxes' => array(
+                        array(
+                            'ticks' => array(
+                                'max' => $iMaxValueY,
+                                'min' => $iMinValueY,
+                                'stepSize' => $this->getReportStep($iMinValueY, $iMaxValueY),
+                                'autoSkip' => true
+                            )
+                        )
+                    ),
+                    'xAxes' => array($aDataForChartXAxes)
+                )
+            ),
+            'links' => $aValues['links'],
+            'strings' => $aValues['strings'],
+        );
+        
+        echo json_encode($aDataForChart);
+    }
+  
+    /**
+    * SERVICE METHODS
+    */
+
+    public function serviceGetSafeServices()
+    {
+        return array ();
+    }
+
+    /**
+    * @page service Service Calls
+    * @section bx_massmailer Mass mailer
+    * @subsection bx_massmailer-page_blocks Page Blocks
+     * @subsubsection bx_massmailer-campagn_subscribers campagn_subscribers
+    * 
+     * @code bx_srv('bx_massmailer', 'campagn_subscribers', [...]); @endcode
+    * 
+    * Get page block with the campagn's subscribers list
+    *
+    * @param $iContentId content ID.
+    * @return HTML string with block content to display on the site. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
+    * 
+    * @see BxMassMailerModule::serviceCampagnSubscribers
+    */
+    /** 
+    * @ref bx_massmailer-campagn_subscribers "entity_view"
+    */
+    public function serviceCampagnSubscribers ($iContentId = 0, $sDisplay = false)
+    {
+        if(!$iContentId)
+            $iContentId = bx_process_input(bx_get('id'), BX_DATA_INT);
+
+        if(!$iContentId)
+            return false;
+              
+        $aData = $this->_oDb->getLettersByCampaignId($iContentId);
+        if (count($aData) > 0)
+            return $this->_oTemplate->getSubscribers($aData);
+        return $iContentId;
+    }
+    
+    /**
+     * @page service Service Calls
+     * @section bx_massmailer Mass mailer
+     * @subsection bx_massmailer-page_blocks Page Blocks
+     * @subsubsection bx_massmailer-campagn_info campagn_info
+     * 
+     * @code bx_srv('bx_massmailer', 'campagn_info', [...]); @endcode
+     * 
+     * Get page block with the campagn info
+     *
+     * @param $iContentId content ID.
+     * @return HTML string with block content to display on the site. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
+     * 
+     * @see BxMassMailerModule::serviceCampagnInfo
+     */
+    /** 
+     * @ref bx_massmailer-campagn_info "campagn_info"
+     */
+    public function serviceCampagnInfo ($iContentId = 0, $sDisplay = false)
+    {
+        if(!$iContentId)
+            $iContentId = bx_process_input(bx_get('id'), BX_DATA_INT);
+
+        if(!$iContentId)
+            return false;
+        
+        return $this->_oTemplate->getInfo($iContentId);
+    }
+    
+    /**
+     * @page service Service Calls
+     * @section bx_massmailer Mass mailer
+     * @subsection bx_massmailer-page_blocks Page Blocks
+     * @subsubsection bx_massmailer-campagn_links campagn_links
+     * 
+     * @code bx_srv('bx_massmailer', 'campagn_links', [...]); @endcode
+     * 
+     * Get page block with the campagn links list
+     *
+     * @param $iContentId content ID
+     * @return HTML string with block content to display on the site. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
+     * 
+     * @see BxMassMailerModule::serviceCampagnLinks
+     */
+    /** 
+     * @ref bx_massmailer-campagn_links "campagn_links"
+     */
+    public function serviceCampagnLinks ($iContentId = 0, $sDisplay = false)
+    {
+        if(!$iContentId)
+            $iContentId = bx_process_input(bx_get('id'), BX_DATA_INT);
+
+        if(!$iContentId)
+            return false;
+        
+        $aData = $this->_oDb->getClicksByCampaignId($iContentId);
+        if (count($aData) > 0)
+            return $this->_oTemplate->getClicks($aData);
+        return $iContentId;
+    }
+    
+    /**
+     * @page service Service Calls
+     * @section bx_massmailer Mass mailer
+     * @subsection bx_massmailer-page_blocks Page Blocks
+     * @subsubsection bx_massmailer-total_subscribers total_subscribers
+     * 
+     * @code bx_srv('bx_massmailer', 'total_subscribers', [...]); @endcode
+     * 
+     * Get page block with subscribers charts
+     *
+     * @param $aParams an array with search params.
+     * @return HTML string with block content to display on the site. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
+     * 
+     * @see BxMassMailerModule::serviceTotalSubscribers
+     */
+    /** 
+     * @ref bx_massmailer-total_subscribers "total_subscribers"
+     */
+    public function serviceTotalSubscribers ()
+    {
+        if($this->checkAllowed() !== CHECK_ACTION_RESULT_ALLOWED)
+            return '';
+        
+        return $this->_oTemplate->getTotalSubscribers();
+    }
+    
+    /**
+     * @page service Service Calls
+     * @section bx_massmailer Mass mailer
+     * @subsection bx_massmailer-page_blocks Page Blocks
+     * @subsubsection bx_massmailer-entity_breadcrumb entity_breadcrumb
+     * 
+     * @code bx_srv('bx_massmailer', 'entity_breadcrumb', [...]); @endcode
+     * 
+     * Get page block with page's breadcrumbs
+     *
+     * @param $iContentId content ID
+     * @return HTML string with block content to display on the site. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
+     * 
+     * @see BxMassMailerModule::serviceEntityBreadcrumb
+     */
+    /** 
+     * @ref bx_massmailer-entity_breadcrumb "entity_breadcrumb"
+     */
+    public function serviceEntityBreadcrumb ($iContentId = 0)
+    {
+        $CNF = &$this->_oConfig->CNF;
+        $oPermalink = BxDolPermalinks::getInstance();
+        if (!$iContentId)
+            $iContentId = bx_process_input(bx_get('id'), BX_DATA_INT);
+        if (!$iContentId){
+            $aContentInfo[$CNF['FIELD_TITLE']] = _t('_bx_massmailer_txt_breadcrumb_title_new_campaign');
+            $aContentInfo['url'] = $oPermalink->permalink('page.php?i=' . $CNF['URI_ADD_CAMPAIGN']);
+        }
+        else{
+            $aContentInfo = $this->_oDb->getCampaignInfoById($iContentId);
+            if (!$aContentInfo)
+                return false;
+            $aContentInfo['url'] = $oPermalink->permalink('page.php?i=' . $CNF['URI_VIEW_CAMPAIGN'] . '&id=' . $aContentInfo[$CNF['FIELD_ID']]);
+        }
+        return $this->_oTemplate->entryBreadcrumb($aContentInfo);
+    }
+    
+    /**
+     * @page service Service Calls
+     * @section bx_massmailer Mass mailer
+     * @subsection bx_massmailer-page_blocks Page Blocks
+     * @subsubsection bx_massmailer-attributes attributes
+     * 
+     * @code bx_srv('bx_massmailer', 'attributes', [...]); @endcode
+     * 
+     * Get page block with attributes list
+     *
+     * @return HTML string with block content to display on the site. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
+     * 
+     * @see BxMassMailerModule::serviceAttributes
+     */
+    /** 
+     * @ref bx_massmailer-attributes "attributes"
+     */
+    public function serviceAttributes ()
+    {
+        $aAttributesParts = array();
+        $aAttributesParts['account'] = array(
+            _t('_bx_massmailer_txt_attribute_global'), 
+            array(
+                'email' => _t('_bx_massmailer_txt_attribute_email'), 
+                'account_name' => _t('_bx_massmailer_txt_attribute_account_name'), 
+                'account_id' => _t('_bx_massmailer_txt_attribute_account_id'), 
+                'reset_password_url' => _t('_bx_massmailer_txt_attribute_reset_password_url'),
+                'unsubscribe_url' => _t('_bx_massmailer_txt_attribute_unsubscribe_url')
+            )
+        );
+        $BxDolModuleQuery = BxDolModuleQuery::getInstance();
+        $aModules = $BxDolModuleQuery->getModulesBy(array('type' => 'modules', 'active' => 1));
+        foreach($aModules as $aModule){
+            if(BxDolRequest::serviceExists($aModule['name'], 'act_as_profile') && BxDolService::call($aModule['name'], 'act_as_profile') == true){
+                $oModule = BxDolModule::getInstance($aModule['name']);
+                $aTmp2 = array();
+                $aTmp = $oModule->serviceGetSearchableFieldsExtended('view');
+                foreach($aTmp as $sKey => $aField){
+                    $aTmp2[$sKey] = _t($aField['caption']);
+                }
+                $aAttributesParts[$aModule['name']] = array($aModule['title'], $aTmp2);
+            }
+        }
+        return $this->_oTemplate->getAttributes($aAttributesParts);
+    }
+    
+    /**
+     * @return CHECK_ACTION_RESULT_ALLOWED if access is granted or error message if access is forbidden. So make sure to make strict(===) checking.
+     */
+    public function checkAllowedAdd ($isPerformAction = false)
+    {
+        return $this->checkAllowed($isPerformAction);
+    }
+    
+    /**
+     * @return CHECK_ACTION_RESULT_ALLOWED if access is granted or error message if access is forbidden. So make sure to make strict(===) checking.
+     */
+    public function checkAllowedEdit ($aDataEntry, $isPerformAction = false)
+    {
+        return $this->checkAllowed($isPerformAction);
+    }
+    
+    /**
+     * @return CHECK_ACTION_RESULT_ALLOWED if access is granted or error message if access is forbidden. So make sure to make strict(===) checking.
+     */
+    public function checkAllowedEditAnyEntryForProfile ($isPerformAction = false, $iProfileId = false)
+    {
+        return $this->checkAllowed($isPerformAction);
+    }
+
+    /**
+     * @return CHECK_ACTION_RESULT_ALLOWED if access is granted or error message if access is forbidden. So make sure to make strict(===) checking.
+     */
+    public function checkAllowedDelete (&$aDataEntry, $isPerformAction = false)
+    {
+        return $this->checkAllowed($isPerformAction);
+    }
+          
+    public function getSegments($sKey = "")
+    {
+        if ($sKey == ""){
+            return $this->aSegments;
+        }
+        else{
+            if (isset($this->aSegments[$sKey]))
+                return $this->aSegments[$sKey];
+            return false;
+        }
+    }
+          
+    public function sendTest($sEmail, $iCampaignId)
+    {
+        $aTmp = $this->getDataForCampaign($iCampaignId);
+        $aTemplate = $aTmp[0];
+        $aCustomHeaders = $aTmp[1];
+              
+        if (!$aTemplate)
+            return false;
+        
+        return $this->sendLetter($sEmail, $iCampaignId, $aCustomHeaders, bx_get_logged_profile_id(), $aTemplate, false);
+    }
+          
+    public function sendAll($iCampaignId)
+    {
+        $aEmails = array();
+        $aTmp = $this->getDataForCampaign($iCampaignId);
+        $aTemplate = $aTmp[0];
+        $aCustomHeaders = $aTmp[1];
+        $aCampaign = $aTmp[2];
+              
+        if (!$aTemplate)
+            return false;
+        $this->_oDb->deleteCampaignData($iCampaignId);
+        $aAccounts = $this->getEmailsBySegment($aCampaign['segments'], $aCampaign['is_one_per_account']);
+        foreach ($aAccounts as $aAccountInfo){
+            array_push($aEmails, $aAccountInfo['email']);
+            $this->sendLetter($aAccountInfo['email'], $iCampaignId, $aCustomHeaders, $aAccountInfo['profile_id'], $aTemplate, true);
+        }
+              
+        $this->_oDb->sendCampaign($iCampaignId, implode(',', $aEmails));
+        return true;
+    }
+    
+    private function sendLetter($sEmail, $iCampaignId, $aCustomHeaders, $iProfileId, $aTemplate, $bAddToQueue)
+    {
+        $sLetterCode = $this->_oDb->addLetter($iCampaignId, $sEmail);
+        
+        $aMarkers = $this->addMarkers($iProfileId, $sLetterCode);
+        bx_alert($this->_aModule['name'], 'user_fields', $iCampaignId, $iProfileId, array('email' => $sEmail, 'markers' => &$aMarkers));
+        
+        $regexp = "<a\s[^>]*href=(\"??)([^\" >]*?)\\1[^>]*>(.*)<\/a>";
+        $aTemplate['Body'] = preg_replace_callback("/$regexp/siU",
+            function ($aMatch) use ($iCampaignId, $sLetterCode, $aMarkers) {
+                if ($aMatch[2] != '{unsubscribe_url}'){
+                    $sUrl = bx_replace_markers($aMatch[2], $aMarkers);
+                    $sLinkCode = $this->_oDb->addLink($sLetterCode, $sUrl, $aMatch[3], $iCampaignId);
+                    return str_replace($sUrl, BX_DOL_URL_ROOT . $this->_oConfig->getBaseUri() . 'track/click/' . $sLinkCode . "/", $aMatch[0]);
+                }
+                else{
+                    return $aMatch[0];
+                }
+            },
+            $aTemplate['Body']);
+        
+        return sendMail($sEmail, $aTemplate['Subject'], $aTemplate['Body'], 0, $aMarkers, BX_EMAIL_MASS, 'html', false, $aCustomHeaders, $bAddToQueue);
+    }
+
+    public function getEmailCountInSegment($iCampaignId)
+    {
+        $aTmp = $this->getDataForCampaign($iCampaignId);
+        $aCampaign = $aTmp[2];
+        $aAccounts = $this->getEmailsBySegment($aCampaign['segments'], $aCampaign['is_one_per_account']);
+        return count($aAccounts);
+    }
+          
+    private function getEmailsBySegment($sSegment, $bIsOnePerAccount)
+    {
+        $sTerms = $this->getSqlBySegment($sSegment);
+        if ($bIsOnePerAccount){
+            $sTerms .= "AND `tp`.`id` = `ta`.`profile_id` ";
+        }
+        return $this->_oDb->getAccountsByTerms($sTerms);
+    }
+    
+    public function checkAllowed($isPerformAction = false)
+    {
+        $aCheck = checkActionModule($this->_iProfileId, 'use massmailer', $this->getName(), $isPerformAction);
+        if ($aCheck[CHECK_ACTION_RESULT] !== CHECK_ACTION_RESULT_ALLOWED)
+             return _t('_sys_txt_access_denied');
+        return CHECK_ACTION_RESULT_ALLOWED;
+    }
+    
+    private function getSqlBySegment($sSegment)
+    {
+        $sRv = '';
+        $sJoin = ' INNER ';
+        if (strpos($sSegment, 'lvl:') !== false){
+            $sLvl = str_replace('lvl:', '', $sSegment);
+            switch ($sLvl) {
+                case 0:
+                    $sRv = '';
+                    $sJoin = ' LEFT ';
+                    break;
+                case MEMBERSHIP_ID_UNCONFIRMED:
+                    $sRv = " AND `ta`.`email_confirmed` = 0 AND `ta`.`phone_confirmed` = 0 ";
+                    break;
+                case MEMBERSHIP_ID_SUSPENDED:
+                    $sRv = " AND `tp`.`status` = 'suspended' ";
+                    break;
+                case MEMBERSHIP_ID_PENDING:
+                    $sRv = " AND `tp`.`status` = 'pending' ";
+                    break;
+                case MEMBERSHIP_ID_STANDARD:
+                    $sRv = " AND `tp`.`id` NOT IN (SELECT `IDMember` FROM `sys_acl_levels_members`) ";
+                    break;
+                default:
+                    $sRv = $this->_oDb->prepareAsString(" AND `tp`.`id` IN (SELECT `IDMember` FROM `sys_acl_levels_members` WHERE IDLevel = ?) ", $sLvl);
+                    break;
+            }
+            $sRv .= " AND `tp`.`type` IN (" . $this->_oDb->implode_escape($this->getProfileModules()) . ")";
+        }
+        return $sJoin . " JOIN `sys_profiles` AS `tp` ON `tp`.`account_id`=`ta`.`id` " . $sRv;
+    }
+    
+    private function getProfileModules()
+    {
+        $aResult = array();
+        $BxDolModuleQuery = BxDolModuleQuery::getInstance();
+        $aModules = $BxDolModuleQuery->getModulesBy(array('type' => 'modules', 'active' => 1));
+        foreach($aModules as $aModule){
+            if(BxDolRequest::serviceExists($aModule['name'], 'act_as_profile') && BxDolService::call($aModule['name'], 'act_as_profile') == true){
+                array_push($aResult, $aModule['name']);
+            }
+        }
+        return $aResult;
+    }
+          
+    private function getDataForCampaign($iCampaignId)
+    {
+        $aCampaign = $this->_oDb->getCampaignInfoById($iCampaignId);
+        $oEmailTemplates = BxDolEmailTemplates::getInstance();
+        $aTemplate = $oEmailTemplates->parseTemplate('bx_massmailer_email', array('content' => $aCampaign['body']));
+        $aTemplate['Subject'] = $aCampaign['subject'];
+              
+        $aCustomHeaders = array();
+        $sFrom = $aCampaign['from_name'] != '' ? $aCampaign['from_name'] : getParam('site_title');
+        $aCustomHeaders['From'] = "=?UTF-8?B?" . base64_encode($sFrom) . "?= <" . getParam('site_email_notify') . ">" ;
+        if ($aCampaign['reply_to'] != ''){
+            $sFrom = $aCampaign['from_name'] != '' ? $aCampaign['from_name'] : getParam('site_title');
+            $aCustomHeaders['Reply-To'] = "=?UTF-8?B?" . base64_encode($sFrom) . '?= <' . bx_process_output($aCampaign['reply_to']) . '>';
+            $aCustomHeaders['X-Original-From'] = "=?UTF-8?B?" . base64_encode($sFrom) . '?= <' . bx_process_output($aCampaign['reply_to']) . '>';
+        }
+              
+        return array($aTemplate, $aCustomHeaders, $aCampaign);
+    }
+          
+    private function addMarkers($iProfileId, $sLetterCode)
+    {
+        $CNF = &$this->_oConfig->CNF;
+        $aMarkers = array();
+        $oProfile = BxDolProfile::getInstance($iProfileId);
+        if ($oProfile){
+            $oAccount = BxDolAccount::getInstance($oProfile->getAccountId());
+            $sAccountEmail = $oAccount->getEmail();
+
+            $aMarkers['email'] = $sAccountEmail;
+            $aMarkers['account_name'] = $oAccount->getDisplayName();
+            $aMarkers['account_id'] = $oProfile->getAccountId();
+
+            $sModule = $oProfile->getModule();
+            if (BxDolRequest::serviceExists($sModule, 'get_info')) {
+                $aProfileInfo = bx_srv($sModule, 'get_info', array($oProfile->getContentId(), false));
+                foreach ($aProfileInfo as $sKey => $sValue)
+                    if(!isset($aMarkers[$sKey]))
+                        $aMarkers[$sKey] = $sValue;
+            }
+
+            $aMarkers['seen_image_url'] = BX_DOL_URL_ROOT . $this->_oConfig->getBaseUri() . 'track/seen/' . $sLetterCode . "/";
+            $aMarkers['unsubscribe_url'] = BX_DOL_URL_ROOT . $oAccount->getUnsubscribeLink(BX_EMAIL_MASS) . "&lhash=" . $sLetterCode;
+
+            $aMarkers['reset_password_url'] = '';
+            if(($sResetPasswordUrl = bx_get_reset_password_link($sAccountEmail)) !== false)
+                $aMarkers['reset_password_url'] = $sResetPasswordUrl . "&lhash=" . $sLetterCode;
+        }
+
+        return $aMarkers;
+    }
+    
+    private function getReportStep($iMin, $iMax)
+    {
+        $iCount = 10;
+        return ceil(($iMax - $iMin) / $iCount);
+    }
+}
+
+/** @} */

+ 77 - 0
modules/boonex/massmailer/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    MassMailer Mass Mailer
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_massmailer',
+    'title' => 'Mass mailer',
+    'note' => 'Mass mailer 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/massmailer/',
+    'home_uri' => 'massmailer',
+
+    'db_prefix' => 'bx_massmailer_',
+    'class_prefix' => 'BxMassMailer',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'MassMailer',
+
+    /**
+     * 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(
+        'clear_db_cache' => 1,
+    ),
+    'disable' => array (
+        'execute_sql' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable_failed' => array (
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Dependencies Section
+     */
+    'dependencies' => array(),
+);
+
+/** @} */

+ 19 - 0
modules/boonex/massmailer/updates/12.0.0_12.0.1/source/template/manage_item.html

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

+ 51 - 0
modules/boonex/nexus/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' => 'Nexus',
+    '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/nexus/updates/update_12.0.0_12.0.1/',
+    'home_uri' => 'nexus_update_1200_1201',
+
+    'module_dir' => 'boonex/nexus/',
+    'module_uri' => 'nexus',
+
+    'db_prefix' => 'bx_nexus_',
+    'class_prefix' => 'BxNexus',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_files' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Nexus',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

+ 13 - 0
modules/boonex/nexus/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 BxNexusUpdater extends BxDolStudioUpdater
+{
+    function __construct($aConfig)
+    {
+        parent::__construct($aConfig);
+    }
+}

+ 5 - 0
modules/boonex/nexus/updates/12.0.0_12.0.1/install/langs/en.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources name="en" flag="gb" title="English">
+    <string_add name="_bx_nexus_option_main_menu"><![CDATA[Main menu]]></string_add>
+    <string_add name="_bx_nexus_option_main_menu_value"><![CDATA[{0}: {1}]]></string_add>
+</resources>

+ 6 - 0
modules/boonex/nexus/updates/12.0.0_12.0.1/install/sql/enable.sql

@@ -0,0 +1,6 @@
+-- SETTINGS
+SET @iCategId = (SELECT `id` FROM `sys_options_categories` WHERE `name`='bx_nexus_general' LIMIT 1);
+
+DELETE FROM `sys_options` WHERE `name`='bx_nexus_option_main_menu';
+INSERT INTO `sys_options` (`name`, `value`, `category_id`, `caption`, `type`, `extra`, `check`, `check_params`, `check_error`, `order`) VALUES
+('bx_nexus_option_main_menu', 'default', @iCategId, '_bx_nexus_option_main_menu', 'select', 'a:3:{s:6:"module";s:8:"bx_nexus";s:6:"method";s:14:"get_menus_list";s:6:"params";a:0:{}}', '', '', '', 40);

+ 128 - 0
modules/boonex/nexus/updates/12.0.0_12.0.1/source/classes/BxNexusModule.php

@@ -0,0 +1,128 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Nexus Nexus - Mobile Apps and Desktop apps connector
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxNexusModule extends BxDolModule
+{
+    function __construct(&$aModule)
+    {
+        parent::__construct($aModule);
+    }
+
+    /**
+     * Get injection code required for Nexus apps
+     * @return string
+     */
+    public function serviceInjectionHeadBegin()
+    {
+        $s = '';
+        if (false !== strpos($_SERVER['HTTP_USER_AGENT'], 'UNAMobileApp/Desktop')) {
+            $s .= "<script>if (typeof module === 'object') {window.module = module; module = undefined;}</script>";
+        }
+        return $s;
+    }
+    
+    /**
+     * Get injection code required for Nexus apps
+     * @return string with Styles and JS code
+     */
+    public function serviceInjectionHead()
+    {
+        if (false === strpos($_SERVER['HTTP_USER_AGENT'], 'UNAMobileApp')) 
+            return '';
+
+        $this->redirects();
+
+        $aBubbles = array();
+        $iBubbles = BxDolPush::getNotificationsCount(0, $aBubbles);
+
+        $s = $this->_oTemplate->parseHtmlByName('styles.html', array());
+        if ($sCustomStyles = getParam('bx_nexus_option_styles'))
+            $s .= "<style>\n" . $sCustomStyles . "\n</style>";
+
+        $oProfile = BxDolProfile::getInstance();
+        $s .= $this->_oTemplate->parseHtmlByName('js.html', array(
+            'msg' => json_encode(array(
+                'loggedin' => isLogged(),
+                'user_info' => isLogged() && $oProfile ? array (
+                    'displayName' => $oProfile->getDisplayName(),
+                    'email' => $oProfile->getAccountObject()->getEmail(),
+                    'avatar' => $oProfile->getAvatar(),
+                    'id' => $oProfile->id(),
+                ) : false,
+                'bubbles_num' => $iBubbles ? $iBubbles : '',
+                'bubbles' => $aBubbles,
+                'push_tags' => BxDolPush::getTags(),
+            )),
+            'txt_pull_to_refresh' => bx_js_string(_t('_bx_nexus_pull_to_refresh')),
+            'txt_release_to_refresh' => bx_js_string(_t('_bx_nexus_release_to_refresh')),
+            'txt_refreshing' => bx_js_string(_t('_bx_nexus_refreshing')),
+            'main_menu' => getParam('bx_nexus_option_main_menu'),
+        ));
+
+        //  TODO: enable it back when it will work correctly on Android
+        // $this->_oTemplate->addJs('pulltorefresh.min.js');
+
+        if (false !== strpos($_SERVER['HTTP_USER_AGENT'], 'Desktop')) {
+            $s .= "<script>if (window.module) module = window.module;</script>";
+        }
+
+        return $s;
+    }
+
+    public function serviceGetMenusList()
+    {
+        $a = BxDolMenuQuery::getMenuObjects();
+        array_unshift($a, array('object' => 'default', 'title' => '_sys_page_type_default', 'module' => '', 'uri' => ''));
+        $aRes = array();
+        foreach($a as $r) {
+            $aRes[] = array('key' => $r['object'], 'value' => $r['uri'] ? _t('_bx_nexus_option_main_menu_value', BxDolModule::getTitle($r['uri']), _t($r['title'])) : _t($r['title']));
+        }
+        return $aRes;
+    }
+
+    protected function redirects()
+    {
+        $bLoggedIn = isLogged() ? 1 : 0;
+        $i = bx_get('i');
+
+        // only several pages are available for guest, for other pages user is redirected to login page
+        $aURIs = explode(',', getParam('bx_nexus_option_guest_pages'));
+        array_walk($aURIs, function (&$sVal) {
+            $sVal = trim($sVal);
+        });
+        $aI = array_combine($aURIs, array_fill(0, count($aURIs), 1));
+        if (!$bLoggedIn && !preg_match('/\/oauth2\//', $_SERVER['REQUEST_URI']) && !preg_match('/searchKeyword.php$/', $_SERVER['PHP_SELF']) && !preg_match('/member.php$/', $_SERVER['PHP_SELF']) && !isset($aI[$i])) {
+            header("Location: " . BX_DOL_URL_ROOT);
+            exit;
+        }
+
+        if ($bLoggedIn) {
+            if (false !== strpos($_SERVER['HTTP_USER_AGENT'], 'Desktop')) {
+                // desktop: for logged in members show messenger only
+                $aI = array('messenger' => 1);
+                if (!preg_match('/member.php$/', $_SERVER['PHP_SELF']) && !isset($aI[$i])) {
+                    header("Location: " . BX_DOL_URL_ROOT . 'page.php?i=messenger');
+                    exit;
+                }
+            }
+            else {        
+                // mobile: for logged in members some pages aren't available as well
+                $aI = array('forgot-password' => 1, 'create-account' => 1, 'login' => 1);
+                if (isset($aI[$i])) {
+                    header("Location: " . BX_DOL_URL_ROOT);
+                    exit;
+                }
+            }
+        }
+    }
+}
+
+/** @} */

+ 68 - 0
modules/boonex/nexus/updates/12.0.0_12.0.1/source/install/config.php

@@ -0,0 +1,68 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Nexus Nexus - Mobile Apps and Desktop apps connector
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_nexus',
+    'title' => 'Nexus',
+    'note' => 'Nexus - Mobile Apps and Desktop apps connector.',
+    '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/nexus/',
+    'home_uri' => 'nexus',
+
+    'db_prefix' => 'bx_nexus_',
+    'class_prefix' => 'BxNexus',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Nexus',
+    
+    /**
+     * 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(),
+);
+
+/** @} */

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

@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources name="en" flag="gb" title="English">
+	<string name="_sys_module_nexus"><![CDATA[Nexus]]></string>
+	<string name="_bx_nexus"><![CDATA[Nexus]]></string>
+
+	<string name="_bx_nexus_setting"><![CDATA[Nexus Setting]]></string>
+    <string name="_bx_nexus_adm_stg_cpt_type"><![CDATA[Nexus]]></string>
+    <string name="_bx_nexus_adm_stg_cpt_category_general"><![CDATA[General]]></string>
+    <string name="_bx_nexus_option_styles"><![CDATA[Custom CSS styles for mobile apps]]></string>
+    <string name="_bx_nexus_option_guest_pages"><![CDATA[Comma separated list of pages URIs, which are avalilable for guests]]></string>
+    <string name="_bx_nexus_option_custom_homepage"><![CDATA[Display custom homepage with login form only]]></string>
+    <string name="_bx_nexus_option_main_menu"><![CDATA[Main menu]]></string>
+    <string name="_bx_nexus_option_main_menu_value"><![CDATA[{0}: {1}]]></string>
+
+	<string name="_bx_nexus_information"><![CDATA[Information]]></string>
+    <string name="_bx_nexus_information_block"><![CDATA[This module adds neccesary styles and functionalty for proper functionality of UNA Nexus apps. Installing this module isn't enough, you need to get source code of mobile apps then modify them for your needs then publish in Google and Apple stores.]]></string>
+
+    <string name="_bx_nexus_pull_to_refresh"><![CDATA[Pull to refresh]]></string> <!-- потяни, чтобы обновить -->
+    <string name="_bx_nexus_release_to_refresh"><![CDATA[Release to refresh]]></string> <!-- отпусти, чтобы обновить -->
+    <string name="_bx_nexus_refreshing"><![CDATA[Refreshing]]></string> <!-- обновление -->
+
+</resources>

+ 33 - 0
modules/boonex/nexus/updates/12.0.0_12.0.1/source/install/sql/enable.sql

@@ -0,0 +1,33 @@
+
+-- 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_nexus', '_bx_nexus_adm_stg_cpt_type', 'bx_nexus@modules/boonex/nexus/|std-icon.svg', IF(NOT ISNULL(@iTypeOrder), @iTypeOrder + 1, 1));
+SET @iTypeId = LAST_INSERT_ID();
+
+INSERT INTO `sys_options_categories` (`type_id`, `name`, `caption`, `order` )  
+VALUES (@iTypeId, 'bx_nexus_general', '_bx_nexus_adm_stg_cpt_category_general', 1);
+SET @iCategId = LAST_INSERT_ID();
+
+INSERT INTO `sys_options` (`name`, `value`, `category_id`, `caption`, `type`, `extra`, `check`, `check_error`, `order`) VALUES
+('bx_nexus_option_styles', '', @iCategId, '_bx_nexus_option_styles', 'text', '', '', '', 10),
+('bx_nexus_option_guest_pages', 'forgot-password,create-account,terms,privacy,contact,about,home', @iCategId, '_bx_nexus_option_guest_pages', 'text', '', '', '', 20),
+('bx_nexus_option_custom_homepage', 'on', @iCategId, '_bx_nexus_option_custom_homepage', 'checkbox', '', '', '', 30),
+('bx_nexus_option_main_menu', 'default', @iCategId, '_bx_nexus_option_main_menu', 'select', 'a:3:{s:6:"module";s:8:"bx_nexus";s:6:"method";s:14:"get_menus_list";s:6:"params";a:0:{}}', '', '', 40);
+
+-- Injections
+
+INSERT INTO `sys_injections`(`name`, `page_index`, `key`, `type`, `data`, `replace`, `active`) VALUES
+('bx_nexus', 0, 'injection_head_begin', 'service', 'a:2:{s:6:"module";s:8:"bx_nexus";s:6:"method";s:20:"injection_head_begin";}', 0, 1),
+('bx_nexus', 0, 'injection_head', 'service', 'a:2:{s:6:"module";s:8:"bx_nexus";s:6:"method";s:14:"injection_head";}', 0, 1);
+
+-- Alerts
+
+INSERT INTO `sys_alerts_handlers` SET `name` = 'bx_nexus', `class` = 'BxNexusAlerts', `file` = 'modules/boonex/nexus/classes/BxNexusAlerts.php';
+
+SET @iHandlerId = LAST_INSERT_ID();
+
+INSERT INTO `sys_alerts` (`unit`, `action`, `handler_id`) VALUES
+('system', 'page_output', @iHandlerId);
+

+ 127 - 0
modules/boonex/nexus/updates/12.0.0_12.0.1/source/template/js.html

@@ -0,0 +1,127 @@
+<script>
+    function bx_mobile_apps_show_main_menu () {
+        if ('__main_menu__' == 'default') {
+            if ($('.cd-dropdown-trigger').size())
+                $('.cd-dropdown-trigger').click();
+            else if ($('.cd-side-nav').size())
+                $([$('.cd-side-nav'), $('.cd-nav-trigger')]).toggleClass('nav-is-visible');
+            else
+                bx_menu_slide_inline('#bx-sliding-menu-sys_site', null, 'site');
+        }
+        else {
+            bx_menu_popup('__main_menu__');
+        }
+    }
+
+    function bx_mobile_apps_show_profile_menu () {
+        bx_menu_slide_inline('#bx-sliding-menu-account', null, 'site');
+    }
+
+    function bx_mobile_apps_show_add_menu () {
+        bx_menu_slide_inline('#bx-sliding-menu-sys_add_content', null, 'site');
+    }
+
+    function bx_mobile_apps_show_notifications_menu () {
+        bx_menu_slide('bx_notifications_preview', null, 'site', {id:{value:'bx_notifications_preview', force:1}});
+    }
+
+    function bx_mobile_apps_show_messenger_menu () {
+        document.location = sUrlRoot + 'page.php?i=messenger';
+    }
+
+    function bx_mobile_apps_home () {
+        if (window.history.length > 1)
+            window.history.go(-(window.history.length - 1));
+    }
+
+    function bx_mobile_apps_close_sliding_menus () {
+        if ($('.bx-sliding-menu-main:visible').size()) // hide sliding menu if they are open
+            bx_menu_slide_inline('.bx-sliding-menu-main');
+    }
+
+    function bx_mobile_apps_video_terminated (e) {
+        if (typeof window.glBxVideoCallTerminated !== 'undefined' && window.glBxVideoCallTerminated instanceof Array) {
+            for (let i = 0; i < window.glBxVideoCallTerminated.length; i++)
+                if (typeof window.glBxVideoCallTerminated[i] === "function")
+                    window.glBxVideoCallTerminated[i](e);
+        }
+    }
+
+    function bx_mobile_apps_video_joined (e) {
+        if (typeof window.glBxVideoCallJoined !== 'undefined' && window.glBxVideoCallJoined instanceof Array) {
+            for (let i = 0; i < window.glBxVideoCallJoined.length; i++)
+                if (typeof window.glBxVideoCallJoined[i] === "function")
+                    window.glBxVideoCallJoined[i](e);
+        }
+    }
+
+    function bx_mobile_apps_video_will_join (e) {
+        if (typeof window.glBxVideoCallWillJoin !== 'undefined' && window.glBxVideoCallWillJoin instanceof Array) {
+            for (let i = 0; i < window.glBxVideoCallWillJoin.length; i++)
+                if (typeof window.glBxVideoCallWillJoin[i] === "function")
+                    window.glBxVideoCallWillJoin[i](e);
+        }
+    }
+
+    function bx_mobile_apps_post_message (oJSON) {
+        var sMsg = JSON.stringify(oJSON);
+        if ('undefined' !== typeof(window.ReactNativeWebView))
+            window.ReactNativeWebView.postMessage(sMsg);
+        else
+            window.postMessage(sMsg, '*');
+    }
+
+    bx_mobile_apps_post_message (__msg__);
+
+    if (window && window.process && window.process.type) { // if run in electron
+        const { ipcRenderer, shell } = require('electron')
+        
+        // send all notification badges
+        ipcRenderer.send('message', __msg__);
+
+        // send messenger badge
+        if (typeof window.glBxMessengerOnNotificationChange === 'undefined')
+            window.glBxMessengerOnNotificationChange = [];
+
+        window.glBxMessengerOnNotificationChange.push(function (iNewNumberOfUnreadChats) {
+            sMsg = {
+                'bubbles': {
+                    'notifications-messenger': iNewNumberOfUnreadChats,
+                },
+            };
+            ipcRenderer.send('message', sMsg);
+        });
+
+        if ($.cookie('memberID')) {
+            // force links to open in external browser in electron
+            $(document).ready(function () {
+                document.querySelector('body').addEventListener('click', event => {
+                    let link = event.target.href;
+                    if (event.target.tagName.toLowerCase() !== 'a') 
+                        return;
+                    event.preventDefault();
+                    shell.openExternal(link);
+                });
+            });
+        }
+    }
+
+    // pull to refresh
+    $(document).ready(function () {
+/*
+        if ($('.bx-messenger-block-lots').length)
+            glBxMobileDisablePullToRefresh = true;
+        if ('undefined' === typeof glBxMobileDisablePullToRefresh || false === glBxMobileDisablePullToRefresh) {
+            PullToRefresh.init({
+                instructionsPullToRefresh: '__txt_pull_to_refresh__',
+                instructionsReleaseToRefresh: '__txt_release_to_refresh__',
+                instructionsRefreshing: '__txt_refreshing__',
+                onRefresh() {
+                    window.location.reload();
+                },
+            });
+        }
+*/
+        bx_mobile_apps_post_message({stop_loading: 1});
+    });
+</script>

+ 51 - 0
modules/boonex/notifications/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' => 'Notifications',
+    '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/notifications/updates/update_12.0.2_12.0.3/',
+    'home_uri' => 'notifications_update_1202_1203',
+
+    'module_dir' => 'boonex/notifications/',
+    'module_uri' => 'notifications',
+
+    'db_prefix' => 'bx_notifications_',
+    'class_prefix' => 'BxNtfs',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 0,
+        'update_files' => 1,
+        'update_languages' => 0,
+        'clear_db_cache' => 0,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Notifications',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

+ 13 - 0
modules/boonex/notifications/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 BxNtfsUpdater extends BxDolStudioUpdater
+{
+    function __construct($aConfig)
+    {
+        parent::__construct($aConfig);
+    }
+}

+ 254 - 0
modules/boonex/notifications/updates/12.0.2_12.0.3/source/classes/BxNtfsConfig.php

@@ -0,0 +1,254 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Notifications Notifications
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+bx_import('BxDolPrivacy');
+
+class BxNtfsConfig extends BxBaseModNotificationsConfig
+{
+    protected $_iOwnerNameMaxLen;
+    protected $_iContentMaxLen;
+    protected $_iPushMaxLen;
+
+    protected $_aHandlersHiddenEmail;
+    protected $_aHandlersHiddenPush;
+
+    /**
+     * Group settings by action. Enabled by default.
+     */
+    protected $_bSettingsGrouped;
+    protected $_aSettingsTypes;
+
+    protected $_aModulesProfiles;
+    protected $_aModulesContexts;
+
+    protected $_iDeliveryTimeout;
+    protected $_iProcessedEvent;
+
+    /**
+     * Constructor
+     */
+    public function __construct($aModule)
+    {
+        parent::__construct($aModule);
+
+        $this->CNF = array (
+            // page URIs
+            'URL_HOME' => 'page.php?i=notifications-view',
+
+            // some params
+            'PARAM_QUEUE_ADD_THRESHOLD' => 0,
+
+            // objects
+            'OBJECT_MENU_SUBMENU' => 'bx_notifications_submenu', // main module submenu
+            'OBJECT_MENU_SETTINGS' => 'bx_notifications_settings', // settings submenu
+            'OBJECT_GRID_SETTINGS_ADMINISTRATION' => 'bx_notifications_settings_administration',
+            'OBJECT_GRID_SETTINGS_COMMON' => 'bx_notifications_settings_common',
+
+            // some language keys
+            'T' => array(
+                'setting_personal' => '_bx_ntfs_setting_type_personal',
+                'setting_follow_member' => '_bx_ntfs_setting_type_follow_member',
+                'setting_follow_context' => '_bx_ntfs_setting_type_follow_context',
+                'setting_other' => '_bx_ntfs_setting_type_other',
+            )
+        );
+
+        $this->_aPrefixes = array(
+            'style' => 'bx-ntfs',
+            'language' => '_bx_ntfs',
+            'option' => 'bx_notifications_'
+        );
+
+        $this->_iOwnerNameMaxLen = 21;
+        $this->_iContentMaxLen = 32;
+        $this->_iPushMaxLen = 190;
+
+        $this->_aHandlerDescriptor = array('module_name' => '', 'module_method' => '', 'module_class' => '');
+        $this->_sHandlersMethod = 'get_notifications_data';
+        $this->_aHandlersHiddenEmail = array();
+        $this->_aHandlersHiddenPush = array();
+
+        $this->_bSettingsGrouped = true;
+        $this->_aSettingsTypes = array(
+            BX_NTFS_STYPE_PERSONAL,
+            BX_NTFS_STYPE_FOLLOW_MEMBER,
+            BX_NTFS_STYPE_FOLLOW_CONTEXT,
+            //BX_NTFS_STYPE_OTHER           //TODO: May be it can be removed, because there is no events(alerts) for this type.
+        );
+
+        $this->_aModulesProfiles = false;
+        $this->_aModulesContexts = false;
+
+        $this->_aJsClasses = array(
+            'main' => 'BxNtfsMain',
+            'view' => 'BxNtfsView',
+        );
+        $this->_aJsObjects = array(
+            'main' => 'oBxNtfsMain',
+            'view' => 'oBxNtfsView',
+        );
+
+        $sHtmlPrefix = str_replace('_', '-', $this->_sName);
+        $this->_aHtmlIds = array(
+            'view' => array(
+                'block' => $sHtmlPrefix,
+                'events' => $sHtmlPrefix . '-events',
+                'event' => $sHtmlPrefix . '-event-'
+            )
+        );
+    }
+
+    public function init(&$oDb)
+    {
+    	parent::init($oDb);
+
+    	$sOptionPrefix = $this->getPrefix('option');
+    	$this->_aPerPage = array(
+            'default' => (int)getParam($sOptionPrefix . 'events_per_page'),
+    	    'preview' => (int)getParam($sOptionPrefix . 'events_per_preview')
+    	);
+
+        $this->_bSettingsGrouped = getParam($sOptionPrefix . 'enable_group_settings') == 'on';
+
+    	$aSettings = array(
+    	    'site' => '',
+    	    'email' => 'Email',
+    	    'push' => 'Push'
+    	);
+    	foreach($aSettings as $sSetting => $sVariable) {
+    	    $sHideTimeline = getParam($sOptionPrefix . 'events_hide_' . $sSetting);
+            if(!empty($sHideTimeline))
+                $this->{'_aHandlersHidden' . $sVariable} = explode(',', $sHideTimeline);
+    	}
+
+        $this->_iDeliveryTimeout = (int)getParam($sOptionPrefix . 'delivery_timeout');
+        $this->_iProcessedEvent = (int)getParam($sOptionPrefix . 'processed_event');
+    }
+
+    public function getOwnerNameMaxLen()
+    {
+        return $this->_iOwnerNameMaxLen;
+    }
+
+    public function getContentMaxLen()
+    {
+        return $this->_iContentMaxLen;
+    }
+
+    public function getPushMaxLen()
+    {
+        return $this->_iPushMaxLen;
+    }
+
+    public function getHandlersHidden($sType = '')
+    {
+        if(!in_array($sType, array('', 'email', 'push')))
+            return array();
+
+        return $this->{'_aHandlersHidden' . ucfirst($sType)};
+    }
+
+    public function isSettingsGrouped()
+    {
+        return $this->_bSettingsGrouped;
+    }
+
+    public function getSettingsTypes()
+    {
+        return $this->_aSettingsTypes;
+    }
+
+    public function getDeliveryTimeout()
+    {
+        return $this->_iDeliveryTimeout;
+    }
+
+    public function getProcessedEvent()
+    {
+        return $this->_iProcessedEvent;
+    }
+    
+    public function setProcessedEvent($iEvent)
+    {
+        $this->_iProcessedEvent = $iEvent;
+
+        setParam($this->getPrefix('option') . 'processed_event', $iEvent);
+    }
+
+    /**
+     * Ancillary functions
+     */
+    public function getViewUrl()
+    {
+        return BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink('page.php?i=notifications-view');
+    }
+
+    public function getContentModule(&$aEvent)
+    {
+        $sModule = $aEvent['type'];
+        if($this->_oDb->isEnabledByName($sModule))
+            return $sModule;
+
+        $sModule = str_replace(array('_media', '_reactions'), array('', ''), $sModule);
+        if($this->_oDb->isEnabledByName($sModule))
+            return $sModule;
+
+        return '';
+    }
+
+    public function getContentObjectId(&$aEvent)
+    {
+        return !empty($aEvent['content']['object_id']) ? (int)$aEvent['content']['object_id'] : (int)$aEvent['object_id'];
+    }
+
+    public function getProfileBasedModules() 
+    {
+        if ($this->_aModulesProfiles !== false && $this->_aModulesContexts !== false)
+            return array($this->_aModulesProfiles, $this->_aModulesContexts);
+
+        if (getParam('sys_db_cache_enable')) {
+            $oDb = BxDolDb::getInstance();
+            $oCache = $oDb->getDbCacheObject();
+            $sCacheKey = $oDb->genDbCacheKey('bx_ntfs_profile_based_modules');
+            $aData = $oCache->getData($sCacheKey);
+            if (null === $aData) {
+                $aData = $this->_getProfileBasedModulesData();
+                $oCache->setData ($sCacheKey, $aData);
+            }
+        } 
+        else {
+            $aData = $this->_getProfileBasedModulesData();
+        }
+
+        return $aData;
+    }
+
+    protected function _getProfileBasedModulesData() 
+    {
+        $this->_aModulesProfiles = array();
+        $this->_aModulesContexts = array();
+
+        $aModules = BxDolModuleQuery::getInstance()->getModulesBy(array('type' => 'modules'));
+        foreach($aModules as $aModule) {
+            if(!BxDolRequest::serviceExists($aModule['name'], 'act_as_profile'))
+                continue;
+
+            if(BxDolService::call($aModule['name'], 'act_as_profile'))
+                $this->_aModulesProfiles[] = $aModule['name'];
+            else
+                $this->_aModulesContexts[] = $aModule['name'];
+        }
+
+        return array($this->_aModulesProfiles, $this->_aModulesContexts);        
+    }
+}
+
+/** @} */

+ 179 - 0
modules/boonex/notifications/updates/12.0.2_12.0.3/source/classes/BxNtfsCronNotify.php

@@ -0,0 +1,179 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Notifications Notifications
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxNtfsCronNotify extends BxDolCron
+{
+    protected $_sModule;
+    protected $_oModule;
+
+    protected $_iAddThreshold;
+
+    public function __construct()
+    {
+    	$this->_sModule = 'bx_notifications';
+    	$this->_oModule = BxDolModule::getInstance($this->_sModule);
+
+        parent::__construct();
+    }
+
+    public function processing()
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        $iCount = (int)$this->_oModule->_oDb->queueGet(array('type' => 'count'));
+        if($iCount > $CNF['PARAM_QUEUE_ADD_THRESHOLD'])
+            return;
+
+        $aEvents = $this->_oModule->_oDb->getEventsToProcess();
+
+        foreach($aEvents as $aEvent) {
+            if(!empty($aEvent['content']) && is_string($aEvent['content']))
+                $aEvent['content'] = unserialize($aEvent['content']);
+
+            $this->_sendNotifications($aEvent);
+        }
+    }
+
+    protected function _sendNotifications(&$aEvent)
+    {
+        $aHandler = $this->_oModule->_oConfig->getHandlers($aEvent['type'] . '_' . $aEvent['action']);
+        if(empty($aHandler) || !is_array($aHandler))
+            return;
+
+        $aDeliveryTypes = array();
+
+        $iId = (int)$aEvent['id'];
+        $iSilentMode = $this->_oModule->getSilentMode($aEvent['content']);
+        switch($iSilentMode) {
+            case BX_BASE_MOD_NTFS_SLTMODE_ABSOLUTE:
+            case BX_NTFS_SLTMODE_ABSOLUTE:
+            case BX_NTFS_SLTMODE_SITE:
+                return;
+
+            case BX_NTFS_SLTMODE_SITE_EMAIL:
+                $aDeliveryTypes[] = BX_BASE_MOD_NTFS_DTYPE_EMAIL;
+                break;
+
+            case BX_NTFS_SLTMODE_SITE_PUSH:
+                $aDeliveryTypes[] = BX_BASE_MOD_NTFS_DTYPE_PUSH;
+                break;
+
+            default:
+                $aDeliveryTypes = array(BX_BASE_MOD_NTFS_DTYPE_EMAIL, BX_BASE_MOD_NTFS_DTYPE_PUSH);
+        }
+
+        $aSendUsing = array();
+        foreach($aDeliveryTypes as $sDeliveryType) {
+            $aHidden = $this->_oModule->_oConfig->getHandlersHidden($sDeliveryType);
+            if(in_array($aHandler['id'], $aHidden))
+                continue;
+
+            $sMethodPostfix = bx_gen_method_name($sDeliveryType);
+            $sMethodGet = 'getNotification' . $sMethodPostfix;
+            $sMethodSend = 'sendNotification' . $sMethodPostfix;
+            if(!$this->_oModule->_oTemplate->isMethodExists($sMethodGet) || !method_exists($this->_oModule, $sMethodSend))
+                continue;
+
+            $aSendUsing[$sDeliveryType] = array(
+                'method_get' => $sMethodGet,
+            	'method_send' => $sMethodSend,
+            );
+        }
+
+        if(empty($aSendUsing) || !is_array($aSendUsing))
+            return;
+
+        $iOwner = (int)$aEvent['owner_id'];
+        $aRecipients = array();
+
+        //--- Get recipients: Subscribers.
+        $oConnection = BxDolConnection::getObjectInstance($this->_oModule->_oConfig->getObject('conn_subscriptions'));
+        $aSubscribers = $oConnection->getConnectedInitiators($iOwner);
+        if(!empty($aSubscribers) && is_array($aSubscribers)) {
+            $oOwner = BxDolProfile::getInstance($iOwner);
+            if(!empty($oOwner)) {
+                $sSettingType = bx_srv($oOwner->getModule(), 'act_as_profile') ? BX_NTFS_STYPE_FOLLOW_MEMBER : BX_NTFS_STYPE_FOLLOW_CONTEXT;
+
+                foreach($aSubscribers as $iSubscriber) 
+                    $this->_addRecipient($iSubscriber, $sSettingType, $aRecipients);
+            }
+        }
+
+        //--- Get recipients: Content owner.
+        $iObjectOwner = (int)$aEvent['object_owner_id'];
+        if($iOwner != $iObjectOwner)
+            $this->_addRecipient($iObjectOwner, BX_NTFS_STYPE_PERSONAL, $aRecipients);
+
+        $bDeliveryTimeout = $this->_oModule->_oConfig->getDeliveryTimeout() > 0;
+
+        //--- Check recipients and send notifications.
+        $oPrivacyInt = BxDolPrivacy::getObjectInstance($this->_oModule->_oConfig->getObject('privacy_view'));
+        $oPrivacyExt = $this->_oModule->_oConfig->getPrivacyObject($aEvent['type'] . '_' . $aEvent['action']);
+        foreach($aRecipients as $iRecipient => $aSettingTypes) {
+            $iIdRead = $this->_oModule->_oDb->getLastRead($iRecipient);
+            if($iIdRead >= $iId)
+                continue;
+
+            $oProfile = BxDolProfile::getInstance($iRecipient);
+            if(!$oProfile)
+                continue;
+
+            if(!bx_srv($oProfile->getModule(), 'act_as_profile'))
+                continue;
+
+            if($oPrivacyExt !== false && !$oPrivacyExt->check($aEvent['id'], $iRecipient)) 
+                continue;
+
+            if($oPrivacyInt !== false && !$oPrivacyInt->check($aEvent['id'], $iRecipient))
+                continue;
+
+            foreach($aSendUsing as $sDeliveryType => $aDeliveryType)
+                foreach($aSettingTypes as $sSettingType) {
+                    $aSetting = $this->_oModule->_oDb->getSetting(array('by' => 'tsu_allowed', 'handler_id' => $aHandler['id'], 'delivery' => $sDeliveryType, 'type' => $sSettingType, 'user_id' => $iRecipient));
+                    if(empty($aSetting) || !is_array($aSetting))
+                        continue;
+
+                    if((int)$aSetting['active_adm'] == 0 || (int)$aSetting['active_pnl'] == 0)
+                        continue;
+
+                    $mixedNotification = $this->_oModule->_oTemplate->{$aDeliveryType['method_get']}($iRecipient, $aEvent);
+                    if($mixedNotification === false)
+                        continue;
+            
+                    /**
+                     * 'break' is essential in the next two conditions to avoid 
+                     * duplicate sending to the same recipient.
+                     */
+                    if($bDeliveryTimeout && $this->_oModule->_oDb->queueAdd(array(
+                        'profile_id' => $iRecipient, 
+                        'event_id' => $aEvent['id'], 
+                        'delivery' => $sDeliveryType,
+                        'content' => serialize($mixedNotification),
+                        'date' => time()
+                    )) !== false)
+                        break;
+
+                    if($this->_oModule->{$aDeliveryType['method_send']}($oProfile, $mixedNotification) !== false)
+                        break;
+                }
+        }
+    }
+
+    protected function _addRecipient($iUser, $sSettingType, &$aRecipients)
+    {
+        if(!isset($aRecipients[$iUser]))
+            $aRecipients[$iUser] = array();
+
+        $aRecipients[$iUser][] = $sSettingType;
+    }
+}
+
+/** @} */

+ 340 - 0
modules/boonex/notifications/updates/12.0.2_12.0.3/source/classes/BxNtfsDb.php

@@ -0,0 +1,340 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Notifications Notifications
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxNtfsDb extends BxBaseModNotificationsDb
+{
+    protected $_sTableEvt2Usr;
+    protected $_sTableQueue;
+
+    /*
+     * Constructor.
+     */
+    function __construct(&$oConfig)
+    {
+        parent::__construct($oConfig);
+
+        $this->_aDeliveryTypes = array(
+            BX_BASE_MOD_NTFS_DTYPE_SITE, 
+            BX_BASE_MOD_NTFS_DTYPE_EMAIL, 
+            BX_BASE_MOD_NTFS_DTYPE_PUSH
+        );
+
+        $this->_sTableEvt2Usr = $this->_sPrefix . 'events2users';
+        $this->_sTableQueue = $this->_sPrefix . 'queue';
+    }
+
+    public function markAsRead($iUserId, $iEventId)
+    {
+        $this->queueDeleteByProfile($iUserId, $iEventId);
+
+        return (int)$this->query("INSERT INTO `" . $this->_sTableEvt2Usr . "` (`user_id`, `event_id`) VALUES (:user_id, :event_id) ON DUPLICATE KEY UPDATE `event_id`=:event_id", array(
+            'user_id' => $iUserId,
+            'event_id' => $iEventId
+        )) > 0;
+    }
+
+    public function getLastRead($iUserId)
+    {
+        return (int)$this->getOne("SELECT `event_id` FROM `" . $this->_sTableEvt2Usr . "` WHERE `user_id`=:user_id LIMIT 1", array(
+            'user_id' => (int)$iUserId
+        ));
+    }
+
+    public function deleteEvent($aParams, $sWhereAddon = "")
+    {
+        $aEvents = $this->getAll("SELECT * FROM `{$this->_sTable}` WHERE " . $this->arrayToSQL($aParams, " AND ") . $sWhereAddon);
+        if(!empty($aEvents) && is_array($aEvents)) 
+            foreach($aEvents as $aEvent)
+                $this->queueDelete(array('event_id' => $aEvent['id']));
+
+        return parent::deleteEvent($aParams, $sWhereAddon);
+    }
+
+    public function getEvents($aParams, $bReturnCount = false)
+    {
+        if($aParams['browse'] != 'list' || $aParams['type'] != BX_NTFS_TYPE_OBJECT_OWNER_AND_CONNECTIONS)
+            return parent::getEvents($aParams);
+
+        $bCountOnly = !empty($aParams['count_only']);
+
+        //--- Get query for 'Object Owner' notifications
+        $sLimitClause = isset($aParams['per_page']) ? "LIMIT 0, " . ($aParams['start'] + $aParams['per_page']) : "";
+
+        $aParams['type'] = BX_BASE_MOD_NTFS_TYPE_OBJECT_OWNER;
+        list($sMethod, $sSelectClause, $sJoinClause, $sWhereClause, $sOrderClause) = $this->_getSqlPartsEvents($aParams);
+
+        $sQueryOwner = "SELECT {select}
+            FROM `{$this->_sTable}`
+            LEFT JOIN `{$this->_sTableHandlers}` ON `{$this->_sTable}`.`type`=`{$this->_sTableHandlers}`.`alert_unit` AND `{$this->_sTable}`.`action`=`{$this->_sTableHandlers}`.`alert_action` " . $sJoinClause . "
+            WHERE 1 " . $sWhereClause . (!$bCountOnly ? " " . $sOrderClause . " " . $sLimitClause : "");
+
+        //--- Get query for 'Connections based' notifications
+        $aParams['type'] = BX_BASE_MOD_NTFS_TYPE_CONNECTIONS;
+        list($sMethod, $sSelectClause, $sJoinClause, $sWhereClause, $sOrderClause) = $this->_getSqlPartsEvents($aParams);
+
+        $sQueryConnections = "SELECT {select}
+            FROM `{$this->_sTable}`
+            LEFT JOIN `{$this->_sTableHandlers}` ON `{$this->_sTable}`.`type`=`{$this->_sTableHandlers}`.`alert_unit` AND `{$this->_sTable}`.`action`=`{$this->_sTableHandlers}`.`alert_action` " . $sJoinClause . "
+            WHERE 1 " . $sWhereClause . (!$bCountOnly ? " " . $sOrderClause . " " . $sLimitClause : "");
+
+        //--- Combine both queries in one
+        $sUnionMethod = 'getColumn';
+        $sUnionOrderClause = $sUnionLimitClause = '';
+        if(!$bCountOnly) {
+            $sUnionMethod = $sMethod;
+            $sUnionOrderClause = "ORDER BY `date` DESC, `id` DESC";
+            $sUnionLimitClause = isset($aParams['per_page']) ? "LIMIT " . $aParams['start'] . ", " . $aParams['per_page'] : "";
+        }
+        
+        $sQuery = "(" . $sQueryOwner . ") UNION (" . $sQueryConnections . ") {order} {limit}";
+        $sQuery = str_replace(array('{select}', '{order}', '{limit}'), array($sSelectClause, $sUnionOrderClause, $sUnionLimitClause), $sQuery);
+        $aEntries = $this->$sUnionMethod($sQuery);
+
+        if($bCountOnly)
+            $aEntries = (int)array_sum($aEntries);
+
+        return $aEntries;
+    }
+
+    protected function _getSqlPartsEvents($aParams)
+    {
+        list($sMethod, $sSelectClause, $sJoinClause, $sWhereClause, $sOrderClause, $sLimitClause) = parent::_getSqlPartsEvents($aParams);
+
+        switch($aParams['browse']) {
+            case 'list':
+                if(!empty($aParams['count_only'])) {
+                    $sMethod = 'getOne';
+                    $sSelectClause = 'COUNT(DISTINCT `' . $this->_sTable . '`.`id`)';
+                }
+                else if(in_array($aParams['type'], array(BX_BASE_MOD_NTFS_TYPE_CONNECTIONS, BX_NTFS_TYPE_OBJECT_OWNER_AND_CONNECTIONS)))
+                    $sSelectClause = 'DISTINCT ' . $sSelectClause;
+
+                break;
+        }
+
+        return array($sMethod, $sSelectClause, $sJoinClause, $sWhereClause, $sOrderClause, $sLimitClause);
+    }
+
+    protected function _getSqlPartsEventsList($aParams)
+    {
+        $sJoinClause = $sWhereClause = "";
+
+        if(isset($aParams['active']))
+            $sWhereClause .= $this->prepareAsString("AND `{$this->_sTable}`.`active`=? ", (int)$aParams['active']);
+
+        //--- Apply modules or handlers filter
+        $sWhereModuleFilter = '';
+        if(!empty($aParams['modules']) && is_array($aParams['modules']))
+            $sWhereModuleFilter = "AND `" . $this->_sTable . "`.`type` IN (" . $this->implode_escape($aParams['modules']) . ") ";
+
+        if($sWhereModuleFilter == '') {
+            $aHidden = $this->_oConfig->getHandlersHidden();
+            $sWhereModuleFilter = !empty($aHidden) && is_array($aHidden) ? "AND `" . $this->_sTableHandlers . "`.`id` NOT IN (" . $this->implode_escape($aHidden) . ") " : "";
+        }
+
+        if($sWhereModuleFilter != '')
+            $sWhereClause .= $sWhereModuleFilter;
+
+        //--- Check flag 'New'
+        if(!empty($aParams['new']) && !empty($aParams['owner_id']))
+            $sWhereClause .= $this->prepareAsString("AND `{$this->_sTable}`.`id`>? ", $this->getLastRead((int)$aParams['owner_id']));
+
+        //--- Check type
+        if(!empty($aParams['owner_id']))
+            switch($aParams['type']) {
+                /*
+                 * Note. It isn't used for now and outdated.
+                 */
+                case BX_BASE_MOD_NTFS_TYPE_OWNER:
+                    $sWhereClause .= $this->prepareAsString("AND `{$this->_sTable}`.`owner_id`=? ", $aParams['owner_id']);
+                    break;
+
+                case BX_BASE_MOD_NTFS_TYPE_OBJECT_OWNER:
+                    $sJoinClause .= $this->prepareAsString(" INNER JOIN `{$this->_sTableSettings}` ON `{$this->_sTableHandlers}`.`id`=`{$this->_sTableSettings}`.`handler_id` AND `{$this->_sTableSettings}`.`delivery`='" . BX_BASE_MOD_NTFS_DTYPE_SITE . "' AND `{$this->_sTableSettings}`.`active`='1' AND `{$this->_sTableSettings}`.`type`=?", BX_NTFS_STYPE_PERSONAL);
+
+                    $sJoinClauseS2U = " LEFT JOIN `{$this->_sTableSettings2Users}` ON `{$this->_sTableSettings}`.`id`=`{$this->_sTableSettings2Users}`.`setting_id` ";
+                    if(!empty($aParams['owner_id']))
+                        $sJoinClauseS2U .= $this->prepareAsString("AND `{$this->_sTableSettings2Users}`.`user_id`=? ", $aParams['owner_id']);
+
+                    $sJoinClause .= $sJoinClauseS2U;
+                    $sWhereClause .= "AND ((ISNULL(`{$this->_sTableSettings2Users}`.`active`) AND `{$this->_sTableSettings}`.`value`='1') OR (NOT ISNULL(`{$this->_sTableSettings2Users}`.`active`) AND `{$this->_sTableSettings2Users}`.`active`='1')) ";
+
+                    $sWhereClause .= $this->prepareAsString("AND `{$this->_sTable}`.`owner_id`<>`{$this->_sTable}`.`object_owner_id` AND ((`{$this->_sTable}`.`owner_id`=? AND `{$this->_sTable}`.`object_privacy_view`<0 AND `{$this->_sTable}`.`owner_id`=ABS(`{$this->_sTable}`.`object_privacy_view`)) OR `{$this->_sTable}`.`object_owner_id`=?) ", $aParams['owner_id'], $aParams['owner_id']);
+                    break;
+
+                case BX_BASE_MOD_NTFS_TYPE_CONNECTIONS:
+                    $oConnection = BxDolConnection::getObjectInstance($this->_oConfig->getObject('conn_subscriptions'));
+                    $aQueryParts = $oConnection->getConnectedContentAsSQLParts($this->_sPrefix . "events", 'owner_id', $aParams['owner_id']);
+                    if(empty($aQueryParts) || !is_array($aQueryParts) || empty($aQueryParts['join']))
+                        break;
+
+                    $sJoinClause .= " LEFT JOIN `sys_profiles` AS `tsp` ON `{$this->_sTable}`.`owner_id`=`tsp`.`id` " . $aQueryParts['join'];
+
+                    if(!empty($aQueryParts['fields']['added']))
+                        $sWhereClause .= "AND `{$this->_sTable}`.`date` > " . $aQueryParts['fields']['added'];
+
+                    list($aModulesProfiles, $aModulesContexts) = $this->_oConfig->getProfileBasedModules();
+                    $sJoinClause .= $this->prepareAsString(" INNER JOIN `{$this->_sTableSettings}` ON `{$this->_sTableHandlers}`.`id`=`{$this->_sTableSettings}`.`handler_id` AND `{$this->_sTableSettings}`.`delivery`='" . BX_BASE_MOD_NTFS_DTYPE_SITE . "' AND `{$this->_sTableSettings}`.`active`='1' AND ((`{$this->_sTableSettings}`.`type`=? AND `tsp`.`type` IN (" . $this->implode_escape($aModulesProfiles) . ")) || (`{$this->_sTableSettings}`.`type`=? AND `tsp`.`type` IN (" . $this->implode_escape($aModulesContexts) . ")))", BX_NTFS_STYPE_FOLLOW_MEMBER, BX_NTFS_STYPE_FOLLOW_CONTEXT);
+
+                    $sJoinClauseS2U = " LEFT JOIN `{$this->_sTableSettings2Users}` ON `{$this->_sTableSettings}`.`id`=`{$this->_sTableSettings2Users}`.`setting_id` ";
+                    if(!empty($aParams['owner_id']))
+                        $sJoinClauseS2U .= $this->prepareAsString("AND `{$this->_sTableSettings2Users}`.`user_id`=? ", $aParams['owner_id']);
+
+                    $sJoinClause .= $sJoinClauseS2U;
+                    $sWhereClause .= "AND ((ISNULL(`{$this->_sTableSettings2Users}`.`active`) AND `{$this->_sTableSettings}`.`value`='1') OR (NOT ISNULL(`{$this->_sTableSettings2Users}`.`active`) AND `{$this->_sTableSettings2Users}`.`active`='1')) ";
+                    break;
+
+                case BX_NTFS_TYPE_OBJECT_OWNER_AND_CONNECTIONS:
+                    /**
+                     * 'personal' notifications are taken by: 
+                     * 1. 'owner_id', in case of somebody performed an action in requested profile's context
+                     * 'object_privacy_view' < 0 AND 'owner_id' == ABS('object_privacy_view'))
+                     * Currently it happens when somebody posted a Direct Timeline post in requested profile.
+                     * 2. 'object_owner_id', in case of somebody performed an action with content 
+                     * owned by the requested profile.
+                     */
+                    $sWhereClauseObjectOwner = $this->prepareAsString("`{$this->_sTable}`.`owner_id` <> `{$this->_sTable}`.`object_owner_id` AND ((`{$this->_sTable}`.`owner_id`=? AND `{$this->_sTable}`.`object_privacy_view`<0 AND `{$this->_sTable}`.`owner_id`=ABS(`{$this->_sTable}`.`object_privacy_view`)) OR `{$this->_sTable}`.`object_owner_id`=?) ", $aParams['owner_id'], $aParams['owner_id']);
+
+                    /**
+                     * 'follow' notifications are taken by connection with `owner_id`
+                     */
+                    $sWhereClauseConnections = '0';
+                    $oConnection = BxDolConnection::getObjectInstance($this->_oConfig->getObject('conn_subscriptions'));
+                    $aQueryParts = $oConnection->getConnectedContentAsSQLPartsExt($this->_sTable, 'owner_id', $aParams['owner_id']);
+                    if(!empty($aQueryParts) && is_array($aQueryParts) && !empty($aQueryParts['join'])) {
+                        $sJoinClause .= " LEFT JOIN `sys_profiles` AS `tsp` ON `{$this->_sTable}`.`owner_id`=`tsp`.`id`";
+                        $sJoinClause .= " LEFT JOIN `" . $aQueryParts['join']['table'] . "` AS `" . $aQueryParts['join']['table_alias'] . "` ON (" . $aQueryParts['join']['condition'] . ")";
+
+                        $sWhereClauseConnections = "NOT ISNULL(`c`.`content`) ";
+                        if(!empty($aQueryParts['fields']['added']))
+                            $sWhereClauseConnections .= "AND `{$this->_sTable}`.`date` > `" . $aQueryParts['fields']['added']['table_alias'] . "`.`" . $aQueryParts['fields']['added']['name'] . "` ";
+                    }
+
+                    list($aModulesProfiles, $aModulesContexts) = $this->_oConfig->getProfileBasedModules();
+                    $sJoinClause .= $this->prepareAsString(" INNER JOIN `{$this->_sTableSettings}` ON `{$this->_sTableHandlers}`.`id`=`{$this->_sTableSettings}`.`handler_id` AND `{$this->_sTableSettings}`.`delivery`='" . BX_BASE_MOD_NTFS_DTYPE_SITE . "' AND `{$this->_sTableSettings}`.`active`='1' AND (`{$this->_sTableSettings}`.`type`=? OR ((`{$this->_sTableSettings}`.`type`=? AND `tsp`.`type` IN (" . $this->implode_escape($aModulesProfiles) . ")) || (`{$this->_sTableSettings}`.`type`=? AND `tsp`.`type` IN (" . $this->implode_escape($aModulesContexts) . "))))", BX_NTFS_STYPE_PERSONAL, BX_NTFS_STYPE_FOLLOW_MEMBER, BX_NTFS_STYPE_FOLLOW_CONTEXT);
+
+                    $sJoinClauseS2U = " LEFT JOIN `{$this->_sTableSettings2Users}` ON `{$this->_sTableSettings}`.`id`=`{$this->_sTableSettings2Users}`.`setting_id` ";
+                    if(!empty($aParams['owner_id']))
+                        $sJoinClauseS2U .= $this->prepareAsString("AND `{$this->_sTableSettings2Users}`.`user_id`=? ", $aParams['owner_id']);
+
+                    $sJoinClause .= $sJoinClauseS2U;
+                    $sWhereClause .= "AND ((ISNULL(`{$this->_sTableSettings2Users}`.`active`) AND `{$this->_sTableSettings}`.`value`='1') OR (NOT ISNULL(`{$this->_sTableSettings2Users}`.`active`) AND `{$this->_sTableSettings2Users}`.`active`='1')) ";
+
+                    $sWhereClause .= "AND ((" . $sWhereClauseObjectOwner . ") || (" . $sWhereClauseConnections . ")) ";
+                    break;
+            }
+
+        return array($sJoinClause, $sWhereClause);
+    }
+
+    public function getEventsToProcess()
+    {
+        $aEvents = $this->getAll("SELECT * FROM `" . $this->_sTable . "` WHERE `id`>:id ORDER BY `id` ASC", array('id' => $this->_oConfig->getProcessedEvent()));
+
+        if(!empty($aEvents) && is_array($aEvents)) {
+            $aEventEnd = end($aEvents);
+
+            $this->_oConfig->setProcessedEvent($aEventEnd['id']);
+
+            reset($aEvents);
+        }
+
+        return $aEvents;
+    }
+
+    public function queueGet($aParams)
+    {
+    	$aMethod = array('name' => 'getAll', 'params' => array(0 => 'query'));
+
+    	$sSelectClause = "*";
+    	$sWhereClause = $sOrderClause = $sLimitClause = "";
+
+        switch($aParams['type']) {
+            case 'count':
+            	$aMethod['name'] = 'getOne';
+
+                $sSelectClause = "COUNT(*)";
+                break;
+
+            case 'id':
+            	$aMethod['name'] = 'getRow';
+            	$aMethod['params'][1] = array(
+                    'id' => $aParams['id']
+                );
+
+                $sWhereClause = " AND `id`=:id";
+                break;
+
+            case 'all_to_send':
+                $aMethod['name'] = 'getAllWithKey';
+                $aMethod['params'][1] = 'id';
+                $aMethod['params'][2] = array(
+                    'timeout' => $aParams['timeout']
+                );
+
+                $sWhereClause = " AND `date`+:timeout < UNIX_TIMESTAMP()";
+                $sOrderClause = "`date` ASC";
+                break;
+        }
+
+        $sOrderClause = !empty($sOrderClause) ? "ORDER BY " . $sOrderClause : $sOrderClause;
+        $sLimitClause = !empty($sLimitClause) ? "LIMIT " . $sLimitClause : $sLimitClause;
+
+        $aMethod['params'][0] = "SELECT
+                " . $sSelectClause . "
+            FROM `" . $this->_sTableQueue . "`
+            WHERE 1" . $sWhereClause . " " . $sOrderClause . " " . $sLimitClause;
+
+        return call_user_func_array(array($this, $aMethod['name']), $aMethod['params']);
+    }
+
+    public function queueAdd($aSet)
+    {
+        if(empty($aSet))
+            return false;
+
+        return (int)$this->query("INSERT INTO `" . $this->_sTableQueue . "` SET " . $this->arrayToSQL($aSet)) > 0;
+    }
+
+    public function queueDelete($aWhere)
+    {
+    	if(empty($aWhere))
+            return false;
+
+        return (int)$this->query("DELETE FROM `" . $this->_sTableQueue . "` WHERE " . $this->arrayToSQL($aWhere, ' AND ')) > 0;
+    }
+
+    public function queueDeleteByProfile($iProfileId, $iEventId)
+    {
+        return (int)$this->query("DELETE FROM `" . $this->_sTableQueue . "` WHERE `profile_id`=:profile_id AND `event_id`<=:event_id", array(
+            'profile_id' => $iProfileId,
+            'event_id' => $iEventId
+        )) > 0;
+    }
+
+    public function queueDeleteByIds($mixedId)
+    {
+        if(empty($mixedId))
+            return false;
+
+        if(!is_array($mixedId))
+            $mixedId = array($mixedId);
+
+        return (int)$this->query("DELETE FROM `" . $this->_sTableQueue . "` WHERE `id` IN (" . $this->implode_escape($mixedId) . ")") > 0;
+    }
+    
+    public function cleanEvents($iClearIntervalInDays)
+    {
+        $this->query("DELETE FROM `{$this->_sTable}` WHERE `date` < :date", array('date' => time() - $iClearIntervalInDays * 86400));
+    }   
+}
+
+/** @} */

+ 569 - 0
modules/boonex/notifications/updates/12.0.2_12.0.3/source/classes/BxNtfsModule.php

@@ -0,0 +1,569 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Notifications Notifications
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+bx_import('BxBaseModNotificationsModule');
+
+define('BX_NTFS_TYPE_OBJECT_OWNER_AND_CONNECTIONS', 'obj_own_and_con');
+define('BX_NTFS_TYPE_DEFAULT', BX_NTFS_TYPE_OBJECT_OWNER_AND_CONNECTIONS);
+
+/**
+ * STYPE - Setting Type:
+ * 1. personal - related to you;
+ * 2. follow_member - related to members you follow;
+ * 3. follow_context - related to contexts you follow;
+ * 4. other - others.
+ */
+define('BX_NTFS_STYPE_PERSONAL', 'personal');
+define('BX_NTFS_STYPE_FOLLOW_MEMBER', 'follow_member');
+define('BX_NTFS_STYPE_FOLLOW_CONTEXT', 'follow_context');
+define('BX_NTFS_STYPE_OTHER', 'other');
+
+/**
+ * SLTMODE - Silent mode:
+ * It is needed for alert sending module to tell that the alert should be ignored 
+ * with Notifications module completely or partially. Available values: 
+ * 1. disabled (global, value = 0) - all notifications are available;
+ * 2. absolute (global, value = 1) - alert isn't registered which means that there is no notifications at all;
+ * 3. absolute (for Notifications only, value = 11) - the same as global absolute.
+ * 3. on-site only (value = 12) - alert is registered. It means that on-site notification is available while the others are disabled.
+ * 4. on-site + email (value = 13) - alert is registered (on-site) and notification via 'email' is enabled.
+ * 5. on-site + push (value = 14) - alert is registered (on-site) and notification via 'push' is enabled.
+ * 
+ * @see BxNtfsResponse::response - 'silent_mode' parameter in Alerts Extras array.
+ */
+define('BX_NTFS_SLTMODE_ABSOLUTE', 11);
+define('BX_NTFS_SLTMODE_SITE', 12);
+define('BX_NTFS_SLTMODE_SITE_EMAIL', 13);
+define('BX_NTFS_SLTMODE_SITE_PUSH', 14);
+
+class BxNtfsModule extends BxBaseModNotificationsModule
+{
+    /**
+     * Constructor
+     */
+    function __construct($aModule)
+    {
+        parent::__construct($aModule);
+
+        $this->_iOwnerId = $this->getUserId();
+    }
+
+    /**
+     * ACTION METHODS
+     */
+    function actionGetPosts()
+    {
+        $aParams = $this->_prepareParamsGet();
+        $sEvents = $this->_oTemplate->getPosts($aParams);
+
+        echoJson(array('events' => $sEvents));
+    }
+
+    /**
+     * SERVICE METHODS
+     */
+
+    public function serviceGetSafeServices()
+    {
+        return array (
+            'GetBlockView' => '',
+        );
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_notifications Invitations
+     * @subsection bx_notifications-other Other
+     * @subsubsection bx_notifications-get_include get_include
+     * 
+     * @code bx_srv('bx_notifications', 'get_include', [...]); @endcode
+     * 
+     * Get all necessary CSS and JS files to include in a page.
+     *
+     * @return string with all necessary CSS and JS files.
+     * 
+     * @see BxInvModule::serviceGetInclude
+     */
+    /** 
+     * @ref bx_notifications-get_include "get_include"
+     */
+    public function serviceGetInclude($bIncludeCss = true, $mixedIncludeJs = false)
+    {
+        return $this->_oTemplate->getInclude($bIncludeCss, $mixedIncludeJs);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_notifications Notifications
+     * @subsection bx_notifications-page_blocks Page Blocks
+     * @subsubsection bx_notifications-get_block_settings get_block_settings
+     * 
+     * @code bx_srv('bx_notifications', 'get_block_settings', [...]); @endcode
+     * 
+     * Get Settings block for a separate page.
+     *
+     * @return a string with block content to display on the site. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
+     * 
+     * @see BxNtfsModule::serviceGetBlockSettings
+     */
+    /** 
+     * @ref bx_notifications-get_block_settings "get_block_settings"
+     */
+    public function serviceGetBlockSettings($sDeliveryType = '', $aParams = array())
+    {
+        if(!isLogged())
+            return '';
+
+        if(empty($sDeliveryType) && bx_get('delivery') !== false)
+            $sDeliveryType = bx_process_input(bx_get('delivery'));
+
+        if(empty($sDeliveryType))
+            $sDeliveryType = BX_BASE_MOD_NTFS_DTYPE_SITE;
+
+        $iUserId = bx_get_logged_profile_id();
+        if(!empty($aParams['user_id']))
+            $iUserId = (int)$aParams['user_id'];
+        else
+            $aParams['user_id'] = $iUserId;
+
+        $this->_oDb->initSettingUser($iUserId);
+
+        return array(
+            'content' => $this->getBlockSettings($sDeliveryType, $aParams),
+        );
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_notifications Notifications
+     * @subsection bx_notifications-page_blocks Page Blocks
+     * @subsubsection bx_notifications-get_block_view get_block_view
+     * 
+     * @code bx_srv('bx_notifications', 'get_block_view', [...]); @endcode
+     * 
+     * Get View block for a separate page. Will return a block with "Empty" message if nothing found.
+     *
+     * @return an array describing a block to display on the site. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
+     * 
+     * @see BxNtfsModule::serviceGetBlockView
+     */
+    /** 
+     * @ref bx_notifications-get_block_view "get_block_view"
+     */
+    public function serviceGetBlockView($sType = '', $iStart = -1, $iPerPage = -1, $aModules = array())
+    {
+    	$aBrowseTypes = array(BX_NTFS_TYPE_OBJECT_OWNER_AND_CONNECTIONS, BX_BASE_MOD_NTFS_TYPE_CONNECTIONS, BX_BASE_MOD_NTFS_TYPE_OBJECT_OWNER);
+
+    	if(empty($sType)) {
+    		$mixedType = bx_get('type');
+    		if($mixedType !== false && in_array($mixedType, $aBrowseTypes))
+    			$sType = $mixedType;
+
+	    	if(empty($sType))
+    			$sType = BX_NTFS_TYPE_DEFAULT;
+    	}
+
+    	$iOwnerId = $this->getUserId();
+        if(!$iOwnerId)
+            return array('content' => MsgBox(_t('_bx_ntfs_txt_msg_no_results')));
+
+		$aParams = $this->_prepareParams($sType, $iOwnerId, $iStart, $iPerPage, $aModules);
+		$sContent = $this->_oTemplate->getViewBlock($aParams);
+
+		$aParams['browse'] = 'first';
+    	$aEvent = $this->_oDb->getEvents($aParams);
+    	if(!empty($aEvent))
+			$this->_oDb->markAsRead($iOwnerId, $aEvent['id']);
+
+		$sModule = $this->_oConfig->getName();
+		$sJsObject = $this->_oConfig->getJsObject('view');
+
+        return array('content' => $sContent); 
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_notifications Notifications
+     * @subsection bx_notifications-browsing Browsing
+     * @subsubsection bx_notifications-get_event_by_id get_event_by_id
+     * 
+     * @code bx_srv('bx_notifications', 'get_event_by_id', [...]); @endcode
+     * 
+     * Get event's data by event ID.
+     *
+     * @return an array with event's data.
+     * 
+     * @see BxNtfsModule::serviceGetEventById
+     */
+    /** 
+     * @ref bx_notifications-get_event_by_id "get_event_by_id"
+     */
+    public function serviceGetEventById($iId)
+    {
+        $aParams = array(
+            'browse' => 'id',
+            'value' => $iId,
+        );
+    	return $this->_oDb->getEvents($aParams);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_notifications Notifications
+     * @subsection bx_notifications-other Other
+     * @subsubsection bx_notifications-get_notifications get_notifications
+     * 
+     * @code bx_srv('bx_notifications', 'get_notifications', [...]); @endcode
+     * 
+     * Get notifications by params.
+     *
+     * @return array with notifications.
+     * 
+     * @see BxNtfsModule::serviceGetNotifications
+     */
+    /** 
+     * @ref bx_notifications-get_notifications "get_notifications"
+     */
+    public function serviceGetNotifications($iOwnerId = 0, $aBrowseParams = array())
+    {
+        if(!$iOwnerId)
+            $iOwnerId = $this->getUserId();
+
+        if(!$iOwnerId)
+            return 0;
+
+        $aParams = $this->_prepareParams(BX_NTFS_TYPE_DEFAULT, $iOwnerId);
+        if(!empty($aBrowseParams) && is_array($aBrowseParams))
+            $aParams = array_merge($aParams, $aBrowseParams);
+
+        $aEvents = $this->_oDb->getEvents($aParams);
+
+        // returns parsed content for React Jot
+        if (!is_array($aBrowseParams) && $aBrowseParams === 'return_parsed_content')
+            foreach ($aEvents as &$aContent)
+                $this->_oTemplate->getPost($aContent, array('return_parsed_content'));
+
+        return $aEvents;
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_notifications Notifications
+     * @subsection bx_notifications-other Other
+     * @subsubsection bx_notifications-get_unread_notifications get_unread_notifications
+     * 
+     * @code bx_srv('bx_notifications', 'get_unread_notifications', [...]); @endcode
+     * 
+     * Get unread notifications.
+     *
+     * @return array with unread notifications.
+     * 
+     * @see BxNtfsModule::serviceGetUnreadNotifications
+     */
+    /** 
+     * @ref bx_notifications-get_unread_notifications "get_unread_notifications"
+     */
+    public function serviceGetUnreadNotifications($iOwnerId = 0)
+    {
+        return $this->serviceGetNotifications($iOwnerId, array('new' => 1));
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_notifications Notifications
+     * @subsection bx_notifications-other Other
+     * @subsubsection bx_notifications-get_unread_notifications_num get_unread_notifications_num
+     * 
+     * @code bx_srv('bx_notifications', 'get_unread_notifications_num', [...]); @endcode
+     * 
+     * Get number of unread notifications.
+     *
+     * @return integer value with number of unread notifications.
+     * 
+     * @see BxNtfsModule::serviceGetUnreadNotificationsNum
+     */
+    /** 
+     * @ref bx_notifications-get_unread_notifications_num "get_unread_notifications_num"
+     */
+    public function serviceGetUnreadNotificationsNum($iOwnerId = 0)
+    {
+        if(!$iOwnerId)
+            $iOwnerId = $this->getUserId();
+
+        if(!$iOwnerId)
+            return 0;
+
+        $aParams = $this->_prepareParams(BX_NTFS_TYPE_DEFAULT, $iOwnerId);
+        $aParams = array_merge($aParams, array(
+            'new' => 1,
+        ));
+
+        $sParamCheck = 'perform_privacy_check';
+        $sParamCheckFor = 'perform_privacy_check_for';
+
+        $iEvents = 0;
+        $aEvents = $this->_oDb->getEvents($aParams);
+        foreach($aEvents as $aEvent) {
+            if(isset($aBrowseParams[$sParamCheck]) && $aBrowseParams[$sParamCheck] !== true) 
+                continue;
+
+            $iViewerId = !empty($aBrowseParams[$sParamCheckFor]) ? (int)$aBrowseParams[$sParamCheckFor] : 0;
+
+            $oPrivacyInt = BxDolPrivacy::getObjectInstance($this->_oConfig->getObject('privacy_view'));
+            if(!$oPrivacyInt->check($aEvent['id'], $iViewerId))
+                continue;
+
+            $oPrivacyExt = $this->_oConfig->getPrivacyObject($aEvent['type'] . '_' . $aEvent['action']);
+            if($oPrivacyExt !== false && !$oPrivacyExt->check($aEvent['id'], $iViewerId))
+                continue;
+
+            $sSrvModule = $this->_oConfig->getContentModule($aEvent);
+            $sSrvMethod = 'check_allowed_with_content_for_profile';
+            if($sSrvModule && BxDolRequest::serviceExists($sSrvModule, $sSrvMethod) && BxDolService::call($sSrvModule, $sSrvMethod, array('view', $this->_oConfig->getContentObjectId($aEvent), $iViewerId)) !== CHECK_ACTION_RESULT_ALLOWED)
+                continue;
+
+            $iEvents++;
+        }
+
+        return $iEvents;
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_notifications Notifications
+     * @subsection bx_notifications-other Other
+     * @subsubsection bx_notifications-get_live_updates get_live_updates
+     * 
+     * @code bx_srv('bx_notifications', 'get_live_updates', [...]); @endcode
+     * 
+     * Get data for Live Updates system.
+     *
+     * @return an array with special format.
+     * 
+     * @see BxNtfsModule::serviceGetLiveUpdates
+     */
+    /** 
+     * @ref bx_notifications-get_live_updates "get_live_updates"
+     */
+    public function serviceGetLiveUpdates($aMenuItemParent, $aMenuItemChild, $iCount = 0)
+    {
+        $iOwnerId = $this->getUserId();
+        $iCountNew = $this->serviceGetUnreadNotificationsNum($iOwnerId);
+        if($iCountNew == $iCount)
+			return false;
+
+        return array(
+    		'count' => $iCountNew, // required
+    		'method' => 'bx_menu_show_live_update(oData)', // required
+    		'data' => array(
+    			'code' => BxDolTemplate::getInstance()->parseHtmlByTemplateName('menu_item_addon', array(
+    				'content' => '{count}'
+                )),
+                'mi_parent' => $aMenuItemParent,
+                'mi_child' => $aMenuItemChild
+    		),  // optional, may have some additional data to be passed in JS method provided using 'method' param above.
+    	);
+    }
+
+    /*
+     * COMMON METHODS
+     */
+    public function getBlockSettings($sDeliveryType, $aParams = array())
+    {
+        return $this->_oTemplate->getSettingsBlock($sDeliveryType, $aParams);
+    }
+
+    public function setSubmenu($sSelected)
+    {
+    	$oSubmenuSystem = BxDolMenu::getObjectInstance('sys_site_submenu');
+        if(!$oSubmenuSystem)
+            return;
+
+        $CNF = &$this->_oConfig->CNF;
+
+        $oSubmenuSystem->setObjectSubmenu($CNF['OBJECT_MENU_SUBMENU'], array (
+            'title' => _t('_bx_ntfs'),
+            'link' => BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink($CNF['URL_HOME']),
+            'icon' => '',
+        ));
+
+        $oSubmenuModule = BxDolMenu::getObjectInstance($CNF['OBJECT_MENU_SUBMENU']);
+        if($oSubmenuModule)
+            $oSubmenuModule->setSelected($this->_oConfig->getName(), $sSelected);
+    }
+
+    public function onPost($iId)
+    {
+    	//--- Event -> Post for Alerts Engine ---//
+        $oAlert = new BxDolAlerts($this->_oConfig->getObject('alert'), 'post', $iId);
+        $oAlert->alert();
+        //--- Event -> Post for Alerts Engine ---//
+    }
+
+    public function enableSettingsLike($iId, $bValue, $bAdministration = false)
+    {
+        $aSetting = $this->_oDb->getSetting(array(
+            'by' => $bAdministration ? 'id' : 'tsu_id', 
+            'id' => (int)$iId
+        ));
+        if(empty($aSetting) || !is_array($aSetting))
+            return false;
+
+        $aSettingsIds = $this->_oDb->getSetting(array(
+            'by' => 'group_type_delivery', 
+            'group' => $aSetting['group'], 
+            'delivery' => $aSetting['delivery'], 
+            'type' => $aSetting['type'], 
+            'active' => !$bAdministration
+        ));
+        if(empty($aSettingsIds) || !is_array($aSettingsIds))
+            return false;
+
+        $iUserId = bx_get_logged_profile_id();
+
+        $mixedResult = false;
+        if($bAdministration)
+            $mixedResult =  $this->_oDb->activateSettingById($bValue, $aSettingsIds);
+        else
+            $mixedResult = $this->_oDb->activateSettingByIdUser($bValue, $iUserId, $aSettingsIds);
+
+        return $mixedResult;
+    }
+
+    public function _changeSettingsValueLike($iId, $sField, $mixedValue, $bAdministration = false)
+    {
+        $aSetting = $this->_oDb->getSetting(array(
+            'by' => $bAdministration ? 'id' : 'tsu_id', 
+            'id' => (int)$iId
+        ));
+        if(empty($aSetting) || !is_array($aSetting))
+            return false;
+
+        $aSettingsIds = $this->_oDb->getSetting(array(
+            'by' => 'group_type_delivery', 
+            'group' => $aSetting['group'], 
+            'delivery' => $aSetting['delivery'], 
+            'type' => $aSetting['type'], 
+            'active' => !$bAdministration
+        ));
+        if(empty($aSettingsIds) || !is_array($aSettingsIds))
+            return false;
+
+        $iUserId = bx_get_logged_profile_id();
+
+        $mixedResult = false;
+        if($bAdministration)
+            $mixedResult =  $this->_oDb->changeSettingById($sField, $mixedValue, $aSettingsIds);
+        else
+            $mixedResult = $this->_oDb->changeSettingByIdUser($sField, $mixedValue, $iUserId, $aSettingsIds);
+
+        return $mixedResult;
+    }
+
+    public function sendNotificationEmail($oProfile, $aNotification)
+    {
+        if(!$oProfile)
+            return false;
+
+        $oAccount = $oProfile->getAccountObject();
+        if(!$oAccount)
+            return false;
+
+        $aSettings = &$aNotification['settings'];
+
+        $sTemplate = !empty($aSettings['template']) ? $aSettings['template'] : 'bx_notifications_new_event';
+        $aTemplateMarkers = array('content' => $aNotification['content']);
+        if(!empty($aSettings['markers']) && is_array($aSettings['markers']))
+            $aTemplateMarkers = array_merge($aTemplateMarkers, $aSettings['markers']);              
+
+        $aTemplate = null;
+        bx_alert($this->_aModule['name'], 'before_parse_email_template', 0, 0, array('profile_id' => $oProfile->id(), 'account_id' => $oAccount->id(), 'template' => $sTemplate, 'markers' => $aTemplateMarkers, 'notification' => $aNotification, 'override_result' => &$aTemplate));
+        if (is_null($aTemplate))
+            $aTemplate = BxDolEmailTemplates::getInstance()->parseTemplate($sTemplate, $aTemplateMarkers, $oAccount->id(), $oProfile->id());
+        if(!$aTemplate)
+            return false;
+
+        $sSubject = !empty($aSettings['subject']) ? $aSettings['subject'] : $aTemplate['Subject'];
+        return sendMail($oAccount->getEmail(), $sSubject, $aTemplate['Body'], 0, array(), BX_EMAIL_NOTIFY, 'html', false, array(), true);
+    }
+
+    public function sendNotificationPush($oProfile, $aNotification)
+    {
+        if(!$oProfile)
+            return false;
+
+        $oAccount = $oProfile->getAccountObject();
+        if(!$oAccount)
+            return false;
+
+        $aContent = &$aNotification['content'];
+        $aSettings = &$aNotification['settings'];
+
+        $sSubject = !empty($aSettings['subject']) ? $aSettings['subject'] : _t('_bx_ntfs_push_new_event_subject', getParam('site_title'));
+        
+        bx_alert($this->_aModule['name'], 'before_send_notification_push', 0, 0, array('profile_id' => $oProfile->id(), 'account_id' => $oAccount->id(), 'content' => &$aContent, 'setting' => &$aSettings, 'subject' => &$sSubject));
+   
+        return BxDolPush::getInstance()->send($oProfile->id(), array(
+            'contents' => array(
+                'en' => $aContent['message']
+            ),
+            'headings' => array(
+                'en' => $sSubject
+            ),
+            'url' => $aContent['url'],
+            'icon' => $aContent['icon']
+        ), true);
+    }
+
+    /*
+     * INTERNAL METHODS
+     */
+    protected function _prepareParams($sType = '', $iOwnerId = 0, $iStart = -1, $iPerPage = -1, $aModules = array())
+    {
+        $aParams = array();
+        $aParams['browse'] = 'list';
+        $aParams['type'] = !empty($sType) ? $sType : BX_NTFS_TYPE_DEFAULT;
+        $aParams['owner_id'] = (int)$iOwnerId != 0 ? $iOwnerId : $this->getUserId();
+        $aParams['start'] = (int)$iStart > 0 ? $iStart : 0;
+        $aParams['per_page'] = (int)$iPerPage > 0 ? $iPerPage : $this->_oConfig->getPerPage();
+        $aParams['modules'] = is_array($aModules) && !empty($aModules) ? $aModules : array();
+        $aParams['last_read'] = $this->_oDb->getLastRead($aParams['owner_id']);
+        $aParams['active'] = 1;
+
+        return $aParams;
+    }
+
+    protected function _prepareParamsGet()
+    {
+        $aParams = array();
+        $aParams['browse'] = 'list';
+
+        $sType = bx_get('type');
+        $aParams['type'] = $sType !== false ? bx_process_input($sType, BX_DATA_TEXT) : BX_NTFS_TYPE_DEFAULT;
+
+        $aParams['owner_id'] = $sType !== false ? bx_process_input(bx_get('owner_id'), BX_DATA_INT) : $this->getUserId();
+
+        $iStart = bx_get('start');
+        $aParams['start'] = $iStart !== false ? bx_process_input($iStart, BX_DATA_INT) : 0;
+
+        $iPerPage = bx_get('per_page');
+        $aParams['per_page'] = $iPerPage !== false ? bx_process_input($iPerPage, BX_DATA_INT) : $this->_oConfig->getPerPage();
+
+        $aModules = bx_get('modules');
+        $aParams['modules'] = $aModules !== false ? bx_process_input($aModules, BX_DATA_TEXT) : array();
+
+        $aParams['active'] = 1;
+
+        return $aParams;
+    }
+}
+
+/** @} */

+ 256 - 0
modules/boonex/notifications/updates/12.0.2_12.0.3/source/classes/BxNtfsResponse.php

@@ -0,0 +1,256 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Notifications Notifications
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxNtfsResponse extends BxBaseModNotificationsResponse
+{
+    public function __construct()
+    {
+        parent::__construct();
+
+        $this->_oModule = BxDolModule::getInstance('bx_notifications');
+    }
+
+    /**
+     * Overwritten method of parent class.
+     *
+     * @param BxDolAlerts $oAlert an instance of alert.
+     */
+    public function response($oAlert)
+    {
+        bx_alert($this->_oModule->getName(), 'before_register_alert', 0, 0, array(
+            'unit' => $oAlert->sUnit,
+            'action' => $oAlert->sAction,
+            'alert' => &$oAlert,
+        ));
+
+    	$iObjectPrivacyView = $this->_getObjectPrivacyView($oAlert->aExtras);
+        if($iObjectPrivacyView == BX_DOL_PG_HIDDEN)
+            return;
+
+        $aHandler = $this->_oModule->_oConfig->getHandlers($oAlert->sUnit . '_' . $oAlert->sAction);
+        if(empty($aHandler) || !is_array($aHandler))
+            return;
+
+        $iSilentMode = $this->_oModule->getSilentMode($oAlert->aExtras);
+        if(in_array($iSilentMode, array(BX_BASE_MOD_NTFS_SLTMODE_ABSOLUTE, BX_NTFS_SLTMODE_ABSOLUTE)))
+            return;
+
+        switch($aHandler['type']) {
+            case BX_BASE_MOD_NTFS_HANDLER_TYPE_INSERT:
+            	$sMethod = 'getInsertData' . bx_gen_method_name($oAlert->sUnit . '_' . $oAlert->sAction);           	
+            	if(!method_exists($this, $sMethod))
+                    $sMethod = 'getInsertData';
+
+                $aDataItems = $this->$sMethod($oAlert, $aHandler);
+                foreach($aDataItems as $aDataItem) {
+                    $iId = $this->_oModule->_oDb->insertEvent($aDataItem);
+                    if(empty($iId))
+                        continue;
+
+                    $this->_oModule->onPost($iId);
+                }
+                break;
+
+            case BX_BASE_MOD_NTFS_HANDLER_TYPE_UPDATE:
+                $this->_oModule->_oDb->updateEvent(array('object_privacy_view' => $iObjectPrivacyView), array('type' => $oAlert->sUnit, 'object_id' => $oAlert->iObject));
+                break;
+
+            case BX_BASE_MOD_NTFS_HANDLER_TYPE_DELETE:
+                if($oAlert->sUnit == 'profile' && $oAlert->sAction == 'delete') {
+                    $this->_oModule->_oDb->deleteEvent(array('owner_id' => $oAlert->iObject));
+
+                    $this->_oModule->_oDb->deleteEvent(array('action' => 'connection_added', 'object_id' => $oAlert->iObject));
+                    break;
+            	}
+
+            	$sMethod = 'getDeleteData' . bx_gen_method_name($oAlert->sUnit . '_' . $oAlert->sAction);           	
+            	if(!method_exists($this, $sMethod))
+                    $sMethod = 'getDeleteData';
+
+                $aDataItems = $this->$sMethod($oAlert, $aHandler);
+                foreach($aDataItems as $aDataItem)
+                    $this->_oModule->_oDb->deleteEvent($aDataItem);
+                break;
+        }
+    }
+
+    protected function getInsertData(&$oAlert, &$aHandler)
+    {
+        $iOwnerId = $oAlert->iSender;
+        $iObjectPrivacyView = $this->_getObjectPrivacyView($oAlert->aExtras);
+
+        if($iObjectPrivacyView < 0)
+            $iOwnerId = abs($iObjectPrivacyView);
+        
+        $mixedSubobjectId = $this->_getSubObjectId($oAlert->aExtras);
+        if(!is_array($mixedSubobjectId))
+            $mixedSubobjectId = array($mixedSubobjectId);
+
+        $aResult = array();
+        foreach($mixedSubobjectId as $iSubobjectId)
+            $aResult[] = array(
+                'owner_id' => $iOwnerId,
+                'type' => $oAlert->sUnit,
+                'action' => $oAlert->sAction,
+                'object_id' => $oAlert->iObject,
+                'object_owner_id' => $this->_getObjectOwnerId($oAlert->aExtras),
+                'object_privacy_view' => $iObjectPrivacyView,
+                'subobject_id' => $iSubobjectId,
+                'content' => $this->_getContent($oAlert->aExtras),
+                'allow_view_event_to' => $this->_oModule->_oConfig->getPrivacyViewDefault('event'),
+                'processed' => 0
+    	    );
+
+    	return $aResult;
+    }
+
+    protected function getDeleteData(&$oAlert, &$aHandler)
+    {
+        $aHandlers = $this->_oModule->_oDb->getHandlers(array('type' => 'by_group_key_type', 'group' => $aHandler['group']));
+
+    	return array(
+    	    array(
+            	'type' => $oAlert->sUnit, 
+            	'action' => $aHandlers[BX_BASE_MOD_NTFS_HANDLER_TYPE_INSERT]['alert_action'], 
+            	'object_id' => $oAlert->iObject,
+            	'subobject_id' => $this->_getSubObjectId($oAlert->aExtras)
+            )
+        );
+    }
+
+    protected function getDeleteDataBxTimelineDelete(&$oAlert, &$aHandler)
+    {
+        $aHandlers = $this->_oModule->_oDb->getHandlers(array('type' => 'by_group_key_type', 'group' => $aHandler['group']));
+
+    	return array(
+    	    array(
+            	'type' => $oAlert->sUnit, 
+            	'action' => $aHandlers[BX_BASE_MOD_NTFS_HANDLER_TYPE_INSERT]['alert_action'], 
+            	'object_id' => $oAlert->iObject,
+            	'subobject_id' => $this->_getSubObjectId($oAlert->aExtras)
+            ),
+            array(
+            	'action' => 'timeline_post_common', 
+            	'subobject_id' => $oAlert->iObject
+            )
+        );
+    }
+
+	/**
+     * Custom insert data getter for sys_profiles_friends -> connection_added and connection_removed alerts. 
+     */
+    protected function getInsertDataSysProfilesFriendsConnectionAdded(&$oAlert, &$aHandler)
+    {
+        $iObjectPrivacyView = $this->_getObjectPrivacyView($oAlert->aExtras);
+        $iPrivacyView = $this->_oModule->_oConfig->getPrivacyViewDefault('event');
+
+    	return array(
+    	    array(
+                'owner_id' => $oAlert->aExtras['initiator'],
+                'type' => $oAlert->sUnit,
+                'action' => $oAlert->sAction,
+                'object_id' => $oAlert->aExtras['content'],
+                'object_owner_id' => $oAlert->aExtras['content'],
+                'object_privacy_view' => $iObjectPrivacyView,
+                'subobject_id' => 0,
+                'content' => $this->_getContent($oAlert->aExtras, array(
+                    'request' => empty($oAlert->aExtras['mutual']) ? 1 : 0
+                )),
+                'allow_view_event_to' => $iPrivacyView,
+                'processed' => 0
+    	    )
+        );
+    }
+    
+    protected function getDeleteDataSysProfilesFriendsConnectionRemoved(&$oAlert, &$aHandler)
+    {
+        $aHandlers = $this->_oModule->_oDb->getHandlers(array('type' => 'by_group_key_type', 'group' => $aHandler['group']));
+
+        $sAction = $aHandlers[BX_BASE_MOD_NTFS_HANDLER_TYPE_INSERT]['alert_action'];
+    	return array(
+    	    array(
+    	        'owner_id' => $oAlert->aExtras['initiator'],
+            	'type' => $oAlert->sUnit, 
+            	'action' => $sAction, 
+            	'object_id' => $oAlert->aExtras['content']
+            ),
+            array(
+            	'owner_id' => $oAlert->aExtras['content'],
+            	'type' => $oAlert->sUnit, 
+            	'action' => $sAction, 
+            	'object_id' => $oAlert->aExtras['initiator']
+            )
+        );
+    }
+
+    /**
+     * Custom insert data getter for sys_profiles_subscriptions -> connection_added and connection_removed alerts. 
+     */
+    protected function getInsertDataSysProfilesSubscriptionsConnectionAdded(&$oAlert, &$aHandler)
+    {
+    	return array(
+    	    array(
+                'owner_id' => $oAlert->aExtras['initiator'],
+                'type' => $oAlert->sUnit,
+                'action' => $oAlert->sAction,
+                'object_id' => $oAlert->aExtras['content'],
+                'object_owner_id' => $oAlert->aExtras['content'],
+                'object_privacy_view' => $this->_getObjectPrivacyView($oAlert->aExtras),
+                'subobject_id' => 0,
+                'content' => $this->_getContent($oAlert->aExtras),
+                'allow_view_event_to' => $this->_oModule->_oConfig->getPrivacyViewDefault('event'),
+                'processed' => 0
+    	    )
+        );
+    }
+
+    protected function getDeleteDataSysProfilesSubscriptionsConnectionRemoved(&$oAlert, &$aHandler)
+    {
+        $aHandlers = $this->_oModule->_oDb->getHandlers(array('type' => 'by_group_key_type', 'group' => $aHandler['group']));
+
+    	return array(
+    	    array(
+    	        'owner_id' => $oAlert->aExtras['initiator'],
+            	'type' => $oAlert->sUnit, 
+            	'action' => $aHandlers[BX_BASE_MOD_NTFS_HANDLER_TYPE_INSERT]['alert_action'], 
+            	'object_id' => $oAlert->aExtras['content']
+            )
+        );
+    }
+
+    protected function _getObjectOwnerId($aExtras)
+    {
+        $iResult = parent::_getObjectOwnerId($aExtras);
+        if(!empty($iResult))
+            return $iResult;
+
+        if(isset($aExtras['meta']))
+            return (int)$aExtras['meta'];
+
+        return 0;
+    }
+
+    protected function _getContent($aExtras, $aAdd = array())
+    {
+        $aResult = array();
+
+        $iSilentMode = $this->_oModule->getSilentMode($aExtras);
+        if($iSilentMode != BX_BASE_MOD_NTFS_SLTMODE_DISABLED)
+            $aResult['silent_mode'] = $iSilentMode;
+
+        if(!empty($aAdd) && is_array($aAdd))
+            $aResult = array_merge($aResult, $aAdd);
+
+        return !empty($aResult) && is_array($aResult) ? serialize($aResult) : '';
+    }
+}
+
+/** @} */

+ 398 - 0
modules/boonex/notifications/updates/12.0.2_12.0.3/source/classes/BxNtfsTemplate.php

@@ -0,0 +1,398 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Notifications Notifications
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+require_once(BX_DIRECTORY_PATH_INC . "design.inc.php");
+
+class BxNtfsTemplate extends BxBaseModNotificationsTemplate
+{
+    function __construct(&$oConfig, &$oDb)
+    {
+        parent::__construct($oConfig, $oDb);
+    }
+
+    public function getInclude($bIncludeCss = true, $mixedIncludeJs = false)
+    {
+        if($bIncludeCss)
+            $this->getAddedCss();
+
+        $sResult = '';
+        if(is_string($mixedIncludeJs) && !empty($mixedIncludeJs)) {
+            $this->getAddedJs();
+            
+            $sResult = $this->getJsCode($mixedIncludeJs);
+        }
+            
+        return $sResult;
+    }
+
+    public function getViewBlock($aParams)
+    {
+        return $this->parseHtmlByName('block_view.html', array(
+        	'html_id_view_block' => $this->_oConfig->getHtmlIds('view', 'block'),
+        	'html_id_events' => $this->_oConfig->getHtmlIds('view', 'events'),
+            'style_prefix' => $this->_oConfig->getPrefix('style'),
+            'content' => $this->getPosts($aParams),
+            'js_content' => $this->getJsCode('view', array(
+        		'oRequestParams' => array(
+	                'type' => $aParams['type'],
+	                'owner_id' => $aParams['owner_id'],
+	                'start' => $aParams['start'],
+	                'per_page' => $aParams['per_page'],
+	                'modules' => $aParams['modules']
+       			)
+            ))
+        ));
+    }
+
+    public function getSettingsBlock($sDeliveryType, $aParams = array())
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $iUserId = !empty($aParams['user_id']) ? (int)$aParams['user_id'] : bx_get_logged_profile_id();
+        $sGrid = !empty($aParams['grid']) ? $aParams['grid'] : $CNF['OBJECT_GRID_SETTINGS_COMMON'];
+        $oTemplate = !empty($aParams['template']) ? $aParams['template'] : $this;
+
+        $oGrid = BxDolGrid::getObjectInstance($sGrid, $oTemplate);
+        if(!$oGrid)
+            return '';
+
+        $oGrid->setDeliveryType($sDeliveryType);
+        if(method_exists($oGrid, 'setUserId'))
+            $oGrid->setUserId($iUserId);
+
+        return $oGrid->getCode();
+    }
+
+    public function getPosts($aParams)
+    {
+    	$sJsObject = $this->_oConfig->getJsObject('view');
+
+    	$aParamsDb = $aParams;
+    	$aParamsDb['per_page'] = 3 * $aParamsDb['per_page'];
+
+        $aEvents = $this->_oDb->getEvents($aParamsDb);
+        if(empty($aEvents))
+        	return $this->getEmpty();
+
+        $aTmplVarsEvents = array();
+        foreach($aEvents as $aEvent) {
+            $sEvent = $this->getPost($aEvent, $aParams);
+            if(empty($sEvent))
+                continue;
+
+            $aTmplVarsEvents[] = array('event' => $sEvent);
+            if(count($aTmplVarsEvents) >= ($aParams['per_page'] + 1))
+            	break;
+        }
+
+        $oPaginate = new BxTemplPaginate(array(
+        	'start' => $aParams['start'],
+            'per_page' => $aParams['per_page'],
+        	'page_url' => $this->_oConfig->getViewUrl(),
+        	'on_change_page' => $sJsObject . ".changePage(this, {start}, {per_page})"
+        ));
+        $oPaginate->setNumFromDataArray($aTmplVarsEvents);
+
+        return $this->parseHtmlByName('events.html', array(
+        	'style_prefix' => $this->_oConfig->getPrefix('style'),
+        	'bx_repeat:events' => $aTmplVarsEvents,
+        	'paginate' => $oPaginate->getSimplePaginate()
+        ));
+    }
+
+    /**
+     * Enter description here ...
+     * @example Available keys are:
+     * 1. owner_name and owner_link
+     * 2. entry_caption and entry_url
+     * 3. subentry_url and subentry_sample
+     * 
+     */
+    public function getPost(&$aEvent, $aBrowseParams = array())
+    {
+    	$oModule = $this->getModule();
+
+        if(!empty($aEvent['content']) && is_string($aEvent['content']))
+            $aEvent['content'] = unserialize($aEvent['content']);
+
+    	if((int)$aEvent['processed'] == 0)
+            $this->_processContent($aEvent);
+
+        if((int)$aEvent['processed'] == 0 || empty($aEvent['content']))
+            return '';
+
+        $sParamCheck = 'perform_privacy_check';
+        if(!isset($aBrowseParams[$sParamCheck]) || $aBrowseParams[$sParamCheck] === true) {
+            $sParamCheckFor = 'perform_privacy_check_for';
+            $iViewerId = !empty($aBrowseParams[$sParamCheckFor]) ? (int)$aBrowseParams[$sParamCheckFor] : 0;
+
+            $oPrivacyInt = BxDolPrivacy::getObjectInstance($this->_oConfig->getObject('privacy_view'));
+            if(!$oPrivacyInt->check($aEvent['id'], $iViewerId))
+                return '';
+
+            $oPrivacyExt = $this->_oConfig->getPrivacyObject($aEvent['type'] . '_' . $aEvent['action']);
+            if($oPrivacyExt !== false && !$oPrivacyExt->check($aEvent['id'], $iViewerId))
+                return '';
+
+            $sSrvModule = $this->_oConfig->getContentModule($aEvent);
+            $sSrvMethod = 'check_allowed_with_content_for_profile';
+            if($sSrvModule && BxDolRequest::serviceExists($sSrvModule, $sSrvMethod) && BxDolService::call($sSrvModule, $sSrvMethod, array('view', $this->_oConfig->getContentObjectId($aEvent), $iViewerId)) !== CHECK_ACTION_RESULT_ALLOWED)
+                return '';
+        }
+
+        $bShowRealProfile = !isset($aBrowseParams['show_real_profile']) || $aBrowseParams['show_real_profile'] === true;
+
+        $oOwner = $oModule->getObjectUser($aEvent['owner_id']);
+        if(!$bShowRealProfile && $oOwner instanceof BxDolProfileAnonymous)
+            $oOwner->setShowRealProfile($bShowRealProfile);
+
+        $aEvent['content']['owner_name'] = strmaxtextlen($oOwner->getDisplayName(), $this->_oConfig->getOwnerNameMaxLen());
+        $aEvent['content']['owner_link'] = $oOwner->getUrl();
+        $aEvent['content']['owner_icon'] = $oOwner->getThumb();
+
+        if(!empty($aEvent['content']['entry_caption'])) {
+            $sEntryCaption = bx_process_output($aEvent['content']['entry_caption'], BX_DATA_TEXT);
+            if(get_mb_substr($sEntryCaption, 0, 1) == '_')
+                $sEntryCaption = _t($sEntryCaption);
+
+            $aEvent['content']['entry_caption'] = strmaxtextlen($sEntryCaption, $this->_oConfig->getContentMaxLen());
+        }
+
+        $iObjectOwner = (int)$aEvent['object_owner_id'];
+        if(empty($iObjectOwner) && !empty($aEvent['content']['entry_author']))
+            $iObjectOwner = (int)$aEvent['content']['entry_author'];
+
+        $oObjectOwner = $oModule->getObjectUser($iObjectOwner);
+        if($oObjectOwner) {
+            if(!$bShowRealProfile && $oObjectOwner instanceof BxDolProfileAnonymous)
+                $oObjectOwner->setShowRealProfile($bShowRealProfile);
+
+            $aEvent['content']['object_owner_name'] = strmaxtextlen($oObjectOwner->getDisplayName(), $this->_oConfig->getOwnerNameMaxLen());
+            $aEvent['content']['object_owner_link'] = $oObjectOwner->getUrl();
+            $aEvent['content']['object_owner_icon'] = $oObjectOwner->getThumb();
+        }
+
+        foreach($aEvent['content'] as $sKey => $sValue) {
+            if(!is_string($sValue) || substr($sValue, 0, 1) != '_') 
+                continue;
+
+            $aCallParams = array($sValue);
+
+            $sKeyParams = $sKey . '_params';
+            if(isset($aEvent['content'][$sKeyParams]) && is_array($aEvent['content'][$sKeyParams])) {
+                foreach($aEvent['content'][$sKeyParams] as $iParamIndex => $sParamValue)
+                    if(is_string($sParamValue) && substr($sParamValue, 0, 1) == '_')
+                        $aEvent['content'][$sKeyParams][$iParamIndex] = _t($sParamValue);
+
+                $aCallParams = array_merge($aCallParams, $aEvent['content'][$sKeyParams]);
+                unset($aEvent['content'][$sKeyParams]);
+            }
+
+            $aEvent['content'][$sKey] = call_user_func_array('_t', $aCallParams);
+        }
+
+    	$bEventParsed = false;
+        bx_alert($this->_oConfig->getName(), 'get_notification', 0, 0, array('event' => &$aEvent, 'event_parsed' => &$bEventParsed, 'owner' => &$oOwner));
+        if(!$bEventParsed) {
+            $mLk = '';
+            if(!empty($aEvent['content']['lang_key'])) {
+                $mLk = $aEvent['content']['lang_key'];
+                if(!is_string($mLk) && !(is_array($mLk) && isset($mLk['site'], $mLk['email'], $mLk['push'])))
+                    $mLk = '';
+            }
+
+            if(empty($mLk))
+                $mLk = $this->_getContentLangKey($aEvent);
+
+            if(is_array($mLk))
+                foreach($mLk as $sDeliveryType => $sLangKey)
+                    $aEvent['content_parsed'][$sDeliveryType] = $this->_parseContentLangKey($sLangKey, $aEvent);
+            else
+                $aEvent['content_parsed'] = $this->_parseContentLangKey($mLk, $aEvent);
+        }
+
+        // returns parsed content for React Jot
+        if(isset($aBrowseParams['return_parsed_content']))
+            return $aEvent;
+
+        return $this->parseHtmlByName('event.html', array (
+            'html_id' => $this->_oConfig->getHtmlIds('view', 'event') . $aEvent['id'],
+            'style_prefix' => $this->_oConfig->getPrefix('style'),
+            'js_object' => $this->_oConfig->getJsObject('view'),
+            'class' => !empty($aBrowseParams['last_read']) && $aEvent['id'] > $aBrowseParams['last_read'] ? ' bx-def-color-bg-box-active' : '', 
+            'id' => $aEvent['id'],
+            'author_unit' => $this->_isInContext($aEvent) && $oObjectOwner ? $oObjectOwner->getUnit(0, array('template' => 'unit_wo_info_links')) : $oOwner->getUnit(0, array('template' => 'unit_wo_info_links')),
+            'link' => $this->_getContentLink($aEvent),
+            'content' => is_array($aEvent['content_parsed']) && isset($aEvent['content_parsed']['site']) ? $aEvent['content_parsed']['site'] : $aEvent['content_parsed'],
+            'date' => bx_time_js($aEvent['date']),
+        ));
+    }
+
+    public function getNotificationEmail($iRecipient, &$aEvent)
+    {
+        $sEvent = $this->getPost($aEvent, array('perform_privacy_check_for' => $iRecipient, 'show_real_profile' => false));
+        if(empty($sEvent) || empty($aEvent['content_parsed']))
+            return false;
+
+        $aContent = &$aEvent['content'];
+        return array(
+            'content' => $this->parseHtmlByName('et_new_event.html', array(
+                'icon_url' => !empty($aContent['owner_icon']) ? $aContent['owner_icon'] : $this->getIconUrl('std-icon.svg'),
+                'content_url' => $this->_getContentLink($aEvent),
+                'content' => is_array($aEvent['content_parsed']) && isset($aEvent['content_parsed']['email']) ? $aEvent['content_parsed']['email'] : $aEvent['content_parsed'],
+                'date' => bx_process_output($aEvent['date'], BX_DATA_DATE_TS),
+            )),
+            'settings' => !empty($aContent['settings']['email']) ? $aContent['settings']['email'] : array()
+        );
+    }
+
+    public function getNotificationPush($iRecipient, &$aEvent)
+    {
+        $sEvent = $this->getPost($aEvent, array('perform_privacy_check_for' => $iRecipient, 'show_real_profile' => false));
+        if(empty($sEvent) || empty($aEvent['content_parsed']))
+            return false;
+
+        $sMessage = is_array($aEvent['content_parsed']) && isset($aEvent['content_parsed']['push']) ? $aEvent['content_parsed']['push'] : $aEvent['content_parsed'];
+        $sMessage = preg_replace('/<\/?[a-zA-Z0-9=\'":;\(\)\s_-]+>/i', '"', $sMessage);
+        if($sMessage)
+            $sMessage = BxTemplFunctions::getInstance()->getStringWithLimitedLength(html_entity_decode($sMessage), $this->_oConfig->getPushMaxLen());
+
+        if(empty($sMessage))
+            return false;
+
+        $aContent = &$aEvent['content'];
+        return array(
+            'content' => array(
+                'url' => $this->_getContentLink($aEvent),
+                'message' => $sMessage,
+                'icon' => !empty($aContent['owner_icon']) ? $aContent['owner_icon'] : ''
+            ),
+            'settings' => !empty($aContent['settings']['push']) ? $aContent['settings']['push'] : array()
+        );
+    }
+
+    public function getEmpty($bVisible = true)
+    {
+        return $this->parseHtmlByName('empty.html', array(
+            'style_prefix' => $this->_oConfig->getPrefix('style'),
+            'visible' => $bVisible ? 'block' : 'none',
+            'content' => MsgBox(_t('_bx_ntfs_txt_msg_no_results'))
+        ));
+    }
+
+    protected function _processContent(&$aEvent)
+    {
+    	$aContent = $this->_getContent($aEvent);
+        if(empty($aContent) || !is_array($aContent)) 
+            return;
+
+        bx_alert($this->_oConfig->getName(), 'get_content', 0, 0, array(
+            'event' => $aEvent,
+            'override_result' => &$aContent
+        ));
+
+        $aSet = array();
+        if(!empty($aContent['entry_author'])) {
+            $aSet['object_owner_id'] = (int)$aContent['entry_author'];
+            unset($aContent['entry_author']);
+        }
+
+        if(!empty($aContent['entry_privacy'])) {
+            $aSet['allow_view_event_to'] = $aContent['entry_privacy'];
+            $aEvent['allow_view_event_to'] = $aContent['entry_privacy'];
+            unset($aContent['entry_privacy']);
+        }
+
+        if(!empty($aEvent['content'])) {
+            if(is_string($aEvent['content']))
+                $aEvent['content'] = unserialize($aEvent['content']);
+
+            if(is_array($aEvent['content']))
+                $aEvent['content'] = array_merge($aEvent['content'], $aContent);
+        }
+        else
+            $aEvent['content'] = $aContent;
+
+        $aEvent['processed'] = 1;
+
+        $aSet = array_merge($aSet, array(
+            'content' => serialize($aEvent['content']), 
+            'processed' => 1
+        ));
+
+        $this->_oDb->updateEvent($aSet, array('id' => $aEvent['id']));
+        return;
+    }
+
+    protected function _getContent(&$aEvent)
+    {
+        $sHandler = $aEvent['type'] . '_' . $aEvent['action'];
+        if(!$this->_oConfig->isHandler($sHandler))
+            return array();
+
+        $aHandler = $this->_oConfig->getHandlers($sHandler);
+        if(!empty($aHandler['module_name']) && !empty($aHandler['module_class']) && !empty($aHandler['module_method']))
+            return BxDolService::call($aHandler['module_name'], $aHandler['module_method'], array($aEvent), $aHandler['module_class']);
+
+        $sMethod = 'display' . bx_gen_method_name($aHandler['alert_unit'] . '_' . $aHandler['alert_action']);
+        if(!method_exists($this, $sMethod))
+            return array();
+
+        return $this->$sMethod($aEvent);
+    }
+
+    protected function _getContentLangKey(&$aEvent)
+    {
+        if(!empty($aEvent['subobject_id']))
+            return '_bx_ntfs_txt_subobject_added';
+
+        if($this->_isInContext($aEvent))
+            return '_bx_ntfs_txt_object_added_in_context';
+
+        $sKey = '';
+        switch($aEvent['action']) {
+            case 'publish_failed':
+                $sKey = '_bx_ntfs_txt_object_publish_failed';
+                break;
+
+            case 'publish_succeeded':
+                $sKey = '_bx_ntfs_txt_object_publish_succeeded';
+                break;
+
+            default:
+                $sKey = '_bx_ntfs_txt_object_added';
+        }
+
+    	return $sKey;
+    }
+
+    protected function _parseContentLangKey($sLangKey, &$aEvent)
+    {
+        $aExclude = array(
+            'lang_key' => 1,
+            'settings' => 1
+        );
+
+        return $this->parseHtmlByContent(_t($sLangKey), array_diff_key($aEvent['content'], $aExclude), array('{', '}'));
+    }
+
+    protected function _getContentLink(&$aEvent)
+    {
+        return !empty($aEvent['subobject_id']) && !empty($aEvent['content']['subentry_url']) ? $aEvent['content']['subentry_url'] : $aEvent['content']['entry_url'];
+    }
+
+    protected function _isInContext(&$aEvent)
+    {
+        return (int)$aEvent['object_privacy_view'] < 0;
+    }
+}
+
+/** @} */

+ 82 - 0
modules/boonex/notifications/updates/12.0.2_12.0.3/source/install/config.php

@@ -0,0 +1,82 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Notifications Notifications
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_notifications',
+    'title' => 'Notifications',
+    'note' => 'Notifications 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/notifications/',
+    'home_uri' => 'notifications',
+
+    'db_prefix' => 'bx_notifications_',
+    'class_prefix' => 'BxNtfs',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Notifications',
+
+    /**
+     * 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,
+    	'update_relations_for_all' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable' => array (
+        'execute_sql' => 1,
+    	'update_relations_for_all' => 1,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Dependencies Section
+     */
+    'dependencies' => array(),
+
+    /**
+     * Relations Section
+     */
+    'relation_handlers' => array(
+    	'on_install' => '',
+    	'on_uninstall' => 'delete_module_events',
+	    'on_enable' => 'add_handlers',
+	    'on_disable' => 'delete_handlers',
+    ),
+);
+
+/** @} */

+ 51 - 0
modules/boonex/organizations/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' => 'Organizations',
+    '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/organizations/updates/update_12.0.2_12.0.3/',
+    'home_uri' => 'orgs_update_1202_1203',
+
+    'module_dir' => 'boonex/organizations/',
+    'module_uri' => 'orgs',
+
+    'db_prefix' => 'bx_organizations_',
+    'class_prefix' => 'BxOrgs',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_files' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Organizations',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

+ 28 - 0
modules/boonex/organizations/updates/12.0.2_12.0.3/install/installer.php

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

+ 66 - 0
modules/boonex/organizations/updates/12.0.2_12.0.3/install/langs/en.xml

@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources name="en" flag="gb" title="English">
+	<string_add name="_bx_orgs_form_price"><![CDATA[Price]]></string_add>
+	<string_add name="_bx_orgs_form_price_display_add"><![CDATA[Add]]></string_add>
+	<string_add name="_bx_orgs_form_price_display_edit"><![CDATA[Edit]]></string_add>
+	<string_add name="_bx_orgs_form_price_input_sys_id"><![CDATA[ID]]></string_add>
+	<string_add name="_bx_orgs_form_price_input_sys_role_id"><![CDATA[Role ID]]></string_add>
+	<string_add name="_bx_orgs_form_price_input_sys_name"><![CDATA[Name]]></string_add>
+	<string_add name="_bx_orgs_form_price_input_name"><![CDATA[Name]]></string_add>
+	<string_add name="_bx_orgs_form_price_input_inf_name"><![CDATA[Unique value which will be used in back end and API calls]]></string_add>
+	<string_add name="_bx_orgs_form_price_input_err_name"><![CDATA[You need to enter a unique value here]]></string_add>
+	<string_add name="_bx_orgs_form_price_input_sys_period"><![CDATA[Period]]></string_add>
+	<string_add name="_bx_orgs_form_price_input_period"><![CDATA[Period]]></string_add>
+	<string_add name="_bx_orgs_form_price_input_inf_period"><![CDATA[Use 0 for lifetime]]></string_add>
+	<string_add name="_bx_orgs_form_price_input_sys_period_unit"><![CDATA[Period unit]]></string_add>
+	<string_add name="_bx_orgs_form_price_input_period_unit"><![CDATA[Period unit]]></string_add>
+	<string_add name="_bx_orgs_form_price_input_inf_period_unit"><![CDATA[Leave empty for lifetime level.]]></string_add>
+	<string_add name="_bx_orgs_form_price_input_err_period_unit"><![CDATA[You need to select a period unit here.]]></string_add>
+	<string_add name="_bx_orgs_form_price_input_sys_price"><![CDATA[Price]]></string_add>
+	<string_add name="_bx_orgs_form_price_input_price"><![CDATA[Price]]></string_add>
+	<string_add name="_bx_orgs_form_price_input_inf_price"><![CDATA[Use 0 or leave empty to create free level.]]></string_add>
+	<string_add name="_bx_orgs_form_price_input_sys_do_submit"><![CDATA[Submit]]></string_add>
+	<string_add name="_bx_orgs_form_price_input_do_submit"><![CDATA[Submit]]></string_add>
+	<string_add name="_bx_orgs_form_price_input_sys_do_cancel"><![CDATA[Cancel]]></string_add>
+	<string_add name="_bx_orgs_form_price_input_do_cancel"><![CDATA[Cancel]]></string_add>
+	<string_add name="_bx_orgs_acl_action_use_paid_join"><![CDATA[Use paid join]]></string_add>
+	<string_add name="_bx_orgs_page_title_sys_join_profile"><![CDATA[Join Organization]]></string_add>
+	<string_add name="_bx_orgs_page_title_join_profile"><![CDATA[Join Organization]]></string_add>
+	<string_add name="_bx_orgs_page_title_sys_profile_pricing"><![CDATA[Pricing]]></string_add>
+	<string_add name="_bx_orgs_page_title_profile_pricing"><![CDATA[Pricing]]></string_add>
+	<string_add name="_bx_orgs_page_block_title_join_profile"><![CDATA[Join Organization]]></string_add>
+	<string_add name="_bx_orgs_page_block_title_system_profile_pricing"><![CDATA[Pricing]]></string_add>
+	<string_add name="_bx_orgs_page_block_title_profile_pricing"><![CDATA[Pricing]]></string_add>
+	<string_add name="_bx_orgs_page_block_title_profile_pricing_link"><![CDATA[Pricing of <a href="{profile_link}">{display_name}</a>]]></string_add>
+	<string_add name="_bx_orgs_menu_item_title_system_edit_pricing"><![CDATA[Edit Pricing]]></string_add>
+	<string_add name="_bx_orgs_menu_item_title_edit_pricing"><![CDATA[Edit Pricing]]></string_add>
+	<string_add name="_bx_orgs_menu_item_title_system_pay_and_join"><![CDATA[Pay & Join]]></string_add>
+	<string_add name="_bx_orgs_menu_item_title_pay_and_join"><![CDATA[Pay & Join]]></string_add>
+	<string_add name="_bx_orgs_grid_column_title_name"><![CDATA[Name]]></string_add>
+	<string_add name="_bx_orgs_grid_column_title_role_id"><![CDATA[Role]]></string_add>
+	<string_add name="_bx_orgs_grid_column_title_period"><![CDATA[Period]]></string_add>
+	<string_add name="_bx_orgs_grid_column_title_price"><![CDATA[Price]]></string_add>
+	<string_add name="_bx_orgs_grid_action_title_add"><![CDATA[Add]]></string_add>
+	<string_add name="_bx_orgs_grid_action_title_edit"><![CDATA[Edit]]></string_add>
+	<string_add name="_bx_orgs_grid_action_title_delete"><![CDATA[Delete]]></string_add>
+	<string_add name="_bx_orgs_grid_action_title_buy"><![CDATA[Buy]]></string_add>
+	<string_add name="_bx_orgs_grid_action_title_buy_title"><![CDATA[One-time payment]]></string_add>
+	<string_add name="_bx_orgs_grid_action_title_subscribe"><![CDATA[Subscribe]]></string_add>
+	<string_add name="_bx_orgs_grid_action_title_subscribe_title"><![CDATA[Create a subscription with recurring billing]]></string_add>
+	<string_add name="_bx_orgs_grid_action_title_choose"><![CDATA[Choose]]></string_add>
+	<string_add name="_bx_orgs_grid_action_title_choose_title"><![CDATA[Switch to the level for free]]></string_add>
+	<string_add name="_bx_orgs_popup_title_price_add"><![CDATA[Add Pricing Plan]]></string_add>
+	<string_add name="_bx_orgs_popup_title_price_edit"><![CDATA[Edit Pricing Plan]]></string_add>
+	<string_add name="_bx_orgs_pre_lists_period_units"><![CDATA[Billing Interval]]></string_add>
+	<string_add name="_bx_orgs_period_unit_day"><![CDATA[day]]></string_add>
+	<string_add name="_bx_orgs_period_unit_week"><![CDATA[week]]></string_add>
+	<string_add name="_bx_orgs_period_unit_month"><![CDATA[month]]></string_add>
+	<string_add name="_bx_orgs_period_unit_year"><![CDATA[year]]></string_add>
+	<string_add name="_bx_orgs_txt_role_added"><![CDATA[Added]]></string_add>
+	<string_add name="_bx_orgs_txt_role_expired"><![CDATA[Expires]]></string_add>
+	<string_add name="_bx_orgs_txt_n_unit"><![CDATA[{0} ({1})]]></string_add>
+	<string_add name="_bx_orgs_txt_cart_item_title"><![CDATA[{0}: {1} ({2} {3})]]></string_add>
+	<string_add name="_bx_orgs_msg_performed"><![CDATA[The action was successfully performed.]]></string_add>
+	<string_add name="_bx_orgs_err_price_duplicate"><![CDATA[Similar pricing plan is already exists.]]></string_add>
+	<string_add name="_bx_orgs_err_cannot_perform"><![CDATA[An error appeared. Please report.]]></string_add>
+</resources>

+ 110 - 0
modules/boonex/organizations/updates/12.0.2_12.0.3/install/sql/enable.sql

@@ -0,0 +1,110 @@
+-- PAGES
+DELETE FROM `sys_objects_page` WHERE `object`='bx_organizations_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_organizations_join_profile', 'join-organization-profile', '_bx_orgs_page_title_sys_join_profile', '_bx_orgs_page_title_join_profile', 'bx_organizations', 5, 2147483647, 1, 'page.php?i=join-organization-profile', '', '', '', 0, 1, 0, 'BxOrgsPageEntry', 'modules/boonex/organizations/classes/BxOrgsPageEntry.php');
+
+DELETE FROM `sys_pages_blocks` WHERE `object`='bx_organizations_join_profile';
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `text`, `text_updated`, `deletable`, `copyable`, `order`) VALUES 
+('bx_organizations_join_profile', 1, 'bx_organizations', '', '_bx_orgs_page_block_title_join_profile', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:16:"bx_organizations";s:6:"method";s:11:"entity_join";s:6:"params";a:1:{i:0;s:12:"{profile_id}";}}', '', 0, 0, 0, 0);
+
+-- PAGE: manage profile pricing
+DELETE FROM `sys_objects_page` WHERE `object`='bx_organizations_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_organizations_profile_pricing', 'edit-organization-pricing', '_bx_orgs_page_title_sys_profile_pricing', '_bx_orgs_page_title_profile_pricing', 'bx_organizations', 5, 2147483647, 1, 'page.php?i=edit-organization-pricing', '', '', '', 0, 1, 0, 'BxOrgsPageEntry', 'modules/boonex/organizations/classes/BxOrgsPageEntry.php');
+
+DELETE FROM `sys_pages_blocks` WHERE `object`='bx_organizations_profile_pricing';
+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_organizations_profile_pricing', 1, 'bx_organizations', '_bx_orgs_page_block_title_system_profile_pricing', '_bx_orgs_page_block_title_profile_pricing_link', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:16:"bx_organizations";s:6:"method";s:14:"entity_pricing";s:6:"params";a:1:{i:0;s:12:"{profile_id}";}}', '', 0, 0, 0, 1, 1);
+
+
+-- MENUS
+DELETE FROM `sys_menu_items` WHERE `set_name`='bx_organizations_view_actions' AND `name`='join-organization-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_organizations_view_actions', 'bx_organizations', 'join-organization-profile', '_bx_orgs_menu_item_title_system_pay_and_join', '_bx_orgs_menu_item_title_pay_and_join', 'page.php?i=join-organization-profile&profile_id={profile_id}', '', '', 'sign-in-alt', '', '', '', 0, 2147483647, 'a:3:{s:6:"module";s:16:"bx_organizations";s:6:"method";s:22:"is_paid_join_avaliable";s:6:"params";a:1:{i:0;s:12:"{profile_id}";}}', 1, 0, 0, 4);
+
+DELETE FROM `sys_menu_items` WHERE `set_name`='bx_organizations_view_actions_more' AND `name`='edit-organization-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_organizations_view_actions_more', 'bx_organizations', 'edit-organization-pricing', '_bx_orgs_menu_item_title_system_edit_pricing', '_bx_orgs_menu_item_title_edit_pricing', 'page.php?i=edit-organization-pricing&profile_id={profile_id}', '', '', 'money-check-alt', '', '', '', 2147483647, 'a:3:{s:6:"module";s:16:"bx_organizations";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_organizations_view_actions_all' AND `name` IN ('join-organization-profile', 'edit-organization-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_organizations_view_actions_all', 'bx_organizations', 'join-organization-profile', '_bx_orgs_menu_item_title_system_pay_and_join', '', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 5),
+('bx_organizations_view_actions_all', 'bx_organizations', 'edit-organization-pricing', '_bx_orgs_menu_item_title_system_edit_pricing', '', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 415);
+
+DELETE FROM `sys_menu_items` WHERE `set_name`='bx_organizations_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_organizations_snippet_meta', 'bx_organizations', 'join-paid', '_sys_menu_item_title_system_sm_join_paid', '_sys_menu_item_title_sm_join_paid', '', '', '', '', '', '', '', 2147483647, 'a:3:{s:6:"module";s:16:"bx_organizations";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, 10);
+
+UPDATE `sys_menu_items` SET `link`='page.php?i=organization-profile-subscriptions&profile_id={member_id}#subscribers' WHERE `set_name`='sys_profile_stats' AND `name`='profile-stats-subscribed-me';
+
+
+-- ACL
+SET @iIdActionUsePaidJoin = (SELECT `ID` FROM `sys_acl_actions` WHERE `Module`='bx_organizations' 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_organizations', 'use paid join', NULL, '_bx_orgs_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);
+
+
+-- GRIDS
+UPDATE `sys_objects_grid` SET `responsive`='1' WHERE `object`='bx_organizations_fans';
+
+DELETE FROM `sys_grid_fields` WHERE `object`='bx_organizations_fans' AND `name` IN ('role_added', 'role_expired');
+INSERT INTO `sys_grid_fields` (`object`, `name`, `title`, `width`, `params`, `order`) VALUES
+('bx_organizations_fans', 'role_added', '_bx_orgs_txt_role_added', '10%', '', 16),
+('bx_organizations_fans', 'role_expired', '_bx_orgs_txt_role_expired', '10%', '', 17);
+
+UPDATE `sys_grid_fields` SET `width`='20%' WHERE `object`='bx_organizations_fans' AND `name`='actions';
+
+DELETE FROM `sys_objects_grid` WHERE `object` IN ('bx_organizations_prices_manage', 'bx_organizations_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_organizations_prices_manage', 'Sql', 'SELECT * FROM `bx_organizations_prices` WHERE 1 ', 'bx_organizations_prices', 'id', 'order', '', '', 100, NULL, 'start', '', 'period,period_unit,price', '', 'like', '', '', 2147483647, 'BxOrgsGridPricesManage', 'modules/boonex/organizations/classes/BxOrgsGridPricesManage.php'),
+('bx_organizations_prices_view', 'Sql', 'SELECT * FROM `bx_organizations_prices` WHERE 1 ', 'bx_organizations_prices', 'id', 'order', '', '', 100, NULL, 'start', '', 'period,period_unit,price', '', 'like', '', '', 2147483647, 'BxOrgsGridPricesView', 'modules/boonex/organizations/classes/BxOrgsGridPricesView.php');
+
+DELETE FROM `sys_grid_fields` WHERE `object` IN ('bx_organizations_prices_manage', 'bx_organizations_prices_view');
+INSERT INTO `sys_grid_fields` (`object`, `name`, `title`, `width`, `translatable`, `chars_limit`, `params`, `order`) VALUES
+('bx_organizations_prices_manage', 'checkbox', '_sys_select', '1%', 0, 0, '', 1),
+('bx_organizations_prices_manage', 'order', '', '1%', 0, 0, '', 2),
+('bx_organizations_prices_manage', 'name', '_bx_orgs_grid_column_title_name', '38%', 0, 32, '', 3),
+('bx_organizations_prices_manage', 'price', '_bx_orgs_grid_column_title_price', '20%', 0, 16, '', 4),
+('bx_organizations_prices_manage', 'period', '_bx_orgs_grid_column_title_period', '20%', 0, 16, '', 5),
+('bx_organizations_prices_manage', 'actions', '', '20%', 0, 0, '', 6),
+
+('bx_organizations_prices_view', 'role_id', '_bx_orgs_grid_column_title_role_id', '40%', 0, 32, '', 1),
+('bx_organizations_prices_view', 'price', '_bx_orgs_grid_column_title_price', '20%', 0, 16, '', 2),
+('bx_organizations_prices_view', 'period', '_bx_orgs_grid_column_title_period', '20%', 0, 16, '', 3),
+('bx_organizations_prices_view', 'actions', '', '20%', 0, 0, '', 4);
+
+DELETE FROM `sys_grid_actions` WHERE `object` IN ('bx_organizations_prices_manage', 'bx_organizations_prices_view');
+INSERT INTO `sys_grid_actions` (`object`, `type`, `name`, `title`, `icon`, `icon_only`, `confirm`, `order`) VALUES
+('bx_organizations_prices_manage', 'independent', 'add', '_bx_orgs_grid_action_title_add', '', 0, 0, 1),
+('bx_organizations_prices_manage', 'single', 'edit', '_bx_orgs_grid_action_title_edit', 'pencil-alt', 1, 0, 1),
+('bx_organizations_prices_manage', 'single', 'delete', '_bx_orgs_grid_action_title_delete', 'remove', 1, 1, 2),
+('bx_organizations_prices_manage', 'bulk', 'delete', '_bx_orgs_grid_action_title_delete', '', 0, 1, 1),
+
+('bx_organizations_prices_view', 'single', 'buy', '_bx_orgs_grid_action_title_buy', 'cart-plus', 0, 0, 1),
+('bx_organizations_prices_view', 'single', 'subscribe', '_bx_orgs_grid_action_title_subscribe', 'credit-card', 0, 0, 2),
+('bx_organizations_prices_view', 'single', 'choose', '_bx_orgs_grid_action_title_choose', 'far check-square', 0, 0, 3);
+
+-- CRON
+DELETE FROM `sys_cron_jobs` WHERE `name`='bx_organizations_pruning';
+INSERT INTO `sys_cron_jobs` (`name`, `time`, `class`, `file`, `service_call`) VALUES
+('bx_organizations_pruning', '0 0 * * *', 'BxOrgsCronPruning', 'modules/boonex/organizations/classes/BxOrgsCronPruning.php', '');

+ 72 - 0
modules/boonex/organizations/updates/12.0.2_12.0.3/install/sql/install.sql

@@ -0,0 +1,72 @@
+-- TABLES
+CREATE TABLE IF NOT EXISTS `bx_organizations_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_organizations_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_organizations_price', 'bx_organizations', '_bx_orgs_form_price', '', '', 'do_submit', 'bx_organizations_prices', 'id', '', '', '', 0, 1, 'BxOrgsFormPrice', 'modules/boonex/organizations/classes/BxOrgsFormPrice.php');
+
+DELETE FROM `sys_form_displays` WHERE `object`='bx_organizations_price';
+INSERT INTO `sys_form_displays` (`display_name`, `module`, `object`, `title`, `view_mode`) VALUES
+('bx_organizations_price_add', 'bx_organizations', 'bx_organizations_price', '_bx_orgs_form_price_display_add', 0),
+('bx_organizations_price_edit', 'bx_organizations', 'bx_organizations_price', '_bx_orgs_form_price_display_edit', 0);
+
+DELETE FROM `sys_form_inputs` WHERE `object`='bx_organizations_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_organizations_price', 'bx_organizations', 'id', '', '', 0, 'hidden', '_bx_orgs_form_price_input_sys_id', '', '', 1, 0, 0, '', '', '', '', '', '', 'Int', '', 1, 0),
+('bx_organizations_price', 'bx_organizations', 'role_id', '', '', 0, 'hidden', '_bx_orgs_form_price_input_sys_role_id', '', '', 1, 0, 0, '', '', '', '', '', '', 'Int', '', 1, 0),
+('bx_organizations_price', 'bx_organizations', 'name', '', '', 0, 'text', '_bx_orgs_form_price_input_sys_name', '_bx_orgs_form_price_input_name', '_bx_orgs_form_price_input_inf_name', 1, 0, 0, '', '', '', 'Avail', '', '_bx_orgs_form_price_input_err_name', 'Xss', '', 1, 0),
+('bx_organizations_price', 'bx_organizations', 'period', '', '', 0, 'text', '_bx_orgs_form_price_input_sys_period', '_bx_orgs_form_price_input_period', '_bx_orgs_form_price_input_inf_period', 1, 0, 0, '', '', '', '', '', '', 'Int', '', 1, 0),
+('bx_organizations_price', 'bx_organizations', 'period_unit', '', '#!bx_organizations_period_units', 0, 'select', '_bx_orgs_form_price_input_sys_period_unit', '_bx_orgs_form_price_input_period_unit', '_bx_orgs_form_price_input_inf_period_unit', 1, 0, 0, '', '', '', '', '', '', 'Xss', '', 1, 0),
+('bx_organizations_price', 'bx_organizations', 'price', '', '', 0, 'text', '_bx_orgs_form_price_input_sys_price', '_bx_orgs_form_price_input_price', '_bx_orgs_form_price_input_inf_price', 1, 0, 0, '', '', '', '', '', '', 'Float', '', 1, 0),
+('bx_organizations_price', 'bx_organizations', 'controls', '', 'do_submit,do_cancel', 0, 'input_set', '', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_organizations_price', 'bx_organizations', 'do_submit', '_bx_orgs_form_price_input_do_submit', '', 0, 'submit', '_bx_orgs_form_price_input_sys_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_organizations_price', 'bx_organizations', 'do_cancel', '_bx_orgs_form_price_input_do_cancel', '', 0, 'button', '_bx_orgs_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_organizations_price_add', 'bx_organizations_price_edit');
+INSERT INTO `sys_form_display_inputs` (`display_name`, `input_name`, `visible_for_levels`, `active`, `order`) VALUES
+('bx_organizations_price_add', 'id', 2147483647, 0, 1),
+('bx_organizations_price_add', 'role_id', 2147483647, 1, 2),
+('bx_organizations_price_add', 'name', 2147483647, 1, 3),
+('bx_organizations_price_add', 'price', 2147483647, 1, 4),
+('bx_organizations_price_add', 'period', 2147483647, 1, 5),
+('bx_organizations_price_add', 'period_unit', 2147483647, 1, 6),
+('bx_organizations_price_add', 'controls', 2147483647, 1, 7),
+('bx_organizations_price_add', 'do_submit', 2147483647, 1, 8),
+('bx_organizations_price_add', 'do_cancel', 2147483647, 1, 9),
+
+('bx_organizations_price_edit', 'id', 2147483647, 1, 1),
+('bx_organizations_price_edit', 'role_id', 2147483647, 1, 2),
+('bx_organizations_price_edit', 'name', 2147483647, 1, 3),
+('bx_organizations_price_edit', 'price', 2147483647, 1, 4),
+('bx_organizations_price_edit', 'period', 2147483647, 1, 5),
+('bx_organizations_price_edit', 'period_unit', 2147483647, 1, 6),
+('bx_organizations_price_edit', 'controls', 2147483647, 1, 7),
+('bx_organizations_price_edit', 'do_submit', 2147483647, 1, 8),
+('bx_organizations_price_edit', 'do_cancel', 2147483647, 1, 9);
+
+
+-- PRE-VALUES
+DELETE FROM `sys_form_pre_lists` WHERE `key`='bx_organizations_period_units';
+INSERT INTO `sys_form_pre_lists`(`key`, `title`, `module`, `use_for_sets`) VALUES
+('bx_organizations_period_units', '_bx_orgs_pre_lists_period_units', 'bx_organizations', '0');
+
+DELETE FROM `sys_form_pre_values` WHERE `Key`='bx_organizations_period_units';
+INSERT INTO `sys_form_pre_values`(`Key`, `Value`, `Order`, `LKey`, `LKey2`, `Data`) VALUES
+('bx_organizations_period_units', '', 0, '_sys_please_select', '', ''),
+('bx_organizations_period_units', 'day', 1, '_bx_orgs_period_unit_day', '', ''),
+('bx_organizations_period_units', 'week', 2, '_bx_orgs_period_unit_week', '', ''),
+('bx_organizations_period_units', 'month', 3, '_bx_orgs_period_unit_month', '', ''),
+('bx_organizations_period_units', 'year', 4, '_bx_orgs_period_unit_year', '', '');

+ 302 - 0
modules/boonex/organizations/updates/12.0.2_12.0.3/source/classes/BxOrgsConfig.php

@@ -0,0 +1,302 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Organizations Organizations
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxOrgsConfig extends BxBaseModGroupsConfig
+{
+    function __construct($aModule)
+    {
+        parent::__construct($aModule);
+
+        $this->_aMenuItems2MethodsSubmenu = array_merge($this->_aMenuItems2MethodsSubmenu, array(
+            'organization-profile-relations' => 'checkAllowedRelationsView',
+            'organization-profile-subscriptions' => 'checkAllowedSubscriptionsView'
+        ));
+
+        $this->_aMenuItems2MethodsActions = array_merge($this->_aMenuItems2MethodsActions, array(
+            'view-organization-profile' => 'checkAllowedView',
+            'edit-organization-profile' => 'checkAllowedEdit',
+            'edit-organization-cover' => 'checkAllowedChangeCover',
+            'invite-to-organization' => 'checkAllowedInvite',
+            'delete-organization-profile' => 'checkAllowedDelete',
+            'profile-friend-add' => 'checkAllowedFriendAdd',
+            'profile-friend-remove' => 'checkAllowedFriendRemove',
+            'profile-relation-add' => 'checkAllowedRelationAdd',
+            'profile-relation-remove' => 'checkAllowedRelationRemove',
+            'profile-set-acl-level' => 'checkAllowedSetMembership',
+            'messenger' => 'checkAllowedCompose',
+        ));
+
+        $this->CNF = array_merge($this->CNF, array (
+
+            // module icon
+            'ICON' => 'briefcase col-red2',
+
+            // database tables
+            'TABLE_ENTRIES' => $aModule['db_prefix'] . 'data',
+            'TABLE_ENTRIES_FULLTEXT' => 'search_fields',
+            'TABLE_ADMINS' => $aModule['db_prefix'] . 'admins',
+            'TABLE_PRICES' => $aModule['db_prefix'] . 'prices',
+
+            // database fields
+            'FIELD_ID' => 'id',
+            'FIELD_AUTHOR' => 'author',
+            'FIELD_ADDED' => 'added',
+            'FIELD_CHANGED' => 'changed',
+            'FIELD_NAME' => 'org_name',
+            'FIELD_TITLE' => 'org_name',
+            'FIELD_TEXT' => 'org_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_ALLOW_CONTACT_TO' => 'allow_contact_to',
+            'FIELD_VIEWS' => 'views',
+			'FIELD_STATUS' => 'status',
+            'FIELD_COMMENTS' => 'comments',
+            'FIELDS_QUICK_SEARCH' => array('org_name'),
+            'FIELD_LOCATION' => 'location',
+            'FIELD_LOCATION_PREFIX' => 'location',
+            'FIELD_LABELS' => 'labels',
+            'FIELD_MULTICAT' => 'multicat',
+            '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-organization-profile',
+            'URI_VIEW_FRIENDS' => 'organization-profile-friends',
+            'URI_VIEW_FRIEND_REQUESTS' => 'organization-friend-requests',
+            'URI_VIEW_FAVORITES' => 'organization-profile-favorites',
+            'URI_EDIT_ENTRY' => 'edit-organization-profile',
+            'URI_EDIT_COVER' => 'edit-organization-cover',
+            'URI_JOIN_ENTRY' => 'join-organization-profile',
+            'URI_JOINED_ENTRIES' => 'joined-organizations',
+            'URI_MANAGE_COMMON' => 'organizations-manage',
+            'URI_VIEW_SUBSCRIPTIONS' => 'organization-profile-subscriptions',
+            'URI_FAVORITES_LIST' => 'organizations-favorites',
+            
+            'URL_HOME' => 'page.php?i=organizations-home',
+            'URL_CREATE' => 'page.php?i=create-organization-profile',
+            'URL_ENTRY_FANS' => 'page.php?i=organization-profile-fans',
+            'URL_MANAGE_COMMON' => 'page.php?i=organizations-manage',
+            'URL_MANAGE_ADMINISTRATION' => 'page.php?i=organizations-administration',
+
+            // some params
+            'PARAM_AUTOAPPROVAL' => 'bx_organizations_autoapproval',
+            'PARAM_ENABLE_ACTIVATION_LETTER' => 'bx_organizations_enable_profile_activation_letter',
+            'PARAM_DEFAULT_ACL_LEVEL' => 'bx_organizations_default_acl_level',
+            'PARAM_NUM_RSS' => 'bx_organizations_num_rss',
+            'PARAM_NUM_CONNECTIONS_QUICK' => 'bx_organizations_num_connections_quick',
+            'PARAM_SEARCHABLE_FIELDS' => 'bx_organizations_searchable_fields',
+            'PARAM_PER_PAGE_BROWSE_SHOWCASE' => 'bx_organizations_per_page_browse_showcase',
+            'PARAM_PER_PAGE_BROWSE_RECOMMENDED' => 'bx_organizations_per_page_browse_recommended',
+            'PARAM_MMODE' => 'bx_organizations_members_mode',
+            'PARAM_PAID_JOIN_ENABLED' => true,
+            'PARAM_RECURRING_RESERVE' => 3, // 3 days for recurring payment to be registered
+            'PARAM_PUBLIC_SBSN' => 'bx_organizations_public_subscriptions',
+            'PARAM_PUBLIC_SBSD' => 'bx_organizations_public_subscribed_me',
+            'PARAM_SBS_WO_JOIN' => 'bx_organizations_enable_subscribe_wo_join',
+            'PARAM_REDIRECT_AADD' => 'bx_organizations_redirect_aadd',
+            'PARAM_REDIRECT_AADD_CUSTOM_URL' => 'bx_organizations_redirect_aadd_custom_url',
+            
+            'PARAM_MULTICAT_ENABLED' => true,
+            'PARAM_MULTICAT_AUTO_ACTIVATION_FOR_CATEGORIES' => 'bx_organizations_auto_activation_for_categories',
+            'PARAM_PER_PAGE_FOR_FAVORITES_LISTS' => 'bx_organizations_per_page_for_favorites_lists',
+            'PARAM_USE_IN' => 'bx_organizations_internal_notifications',
+
+            // objects
+            'OBJECT_STORAGE' => 'bx_organizations_pics',
+            'OBJECT_STORAGE_COVER' => 'bx_organizations_pics',
+            'OBJECT_IMAGES_TRANSCODER_THUMB' => 'bx_organizations_thumb',
+            'OBJECT_IMAGES_TRANSCODER_ICON' => 'bx_organizations_icon',
+            'OBJECT_IMAGES_TRANSCODER_AVATAR' => 'bx_organizations_avatar',
+            'OBJECT_IMAGES_TRANSCODER_AVATAR_BIG' => 'bx_organizations_avatar_big',
+            'OBJECT_IMAGES_TRANSCODER_PICTURE' => 'bx_organizations_picture',
+            'OBJECT_IMAGES_TRANSCODER_COVER' => 'bx_organizations_cover',
+            'OBJECT_IMAGES_TRANSCODER_COVER_THUMB' => 'bx_organizations_cover_thumb',
+            'OBJECT_IMAGES_TRANSCODER_GALLERY' => 'bx_organizations_gallery',
+            'OBJECT_VIEWS' => 'bx_organizations',
+            'OBJECT_VOTES' => 'bx_organizations',
+            'OBJECT_SCORES' => 'bx_organizations',
+            'OBJECT_FAVORITES' => 'bx_organizations',
+            'OBJECT_FEATURED' => 'bx_organizations',
+            'OBJECT_COMMENTS' => 'bx_organizations',
+            'OBJECT_NOTES' => 'bx_organizations_notes',
+            'OBJECT_REPORTS' => 'bx_organizations',
+            'OBJECT_METATAGS' => 'bx_organizations',
+            'OBJECT_FORM_ENTRY' => 'bx_organization',
+            'OBJECT_FORM_ENTRY_DISPLAY_VIEW' => 'bx_organization_view',
+            'OBJECT_FORM_ENTRY_DISPLAY_VIEW_FULL' => 'bx_organization_view_full', // for "info" tab on view profile page
+            'OBJECT_FORM_ENTRY_DISPLAY_ADD' => 'bx_organization_add',
+            'OBJECT_FORM_ENTRY_DISPLAY_EDIT' => 'bx_organization_edit',
+            'OBJECT_FORM_ENTRY_DISPLAY_EDIT_COVER' => 'bx_organization_edit_cover',
+            'OBJECT_FORM_ENTRY_DISPLAY_DELETE' => 'bx_organization_delete',
+            'OBJECT_FORM_ENTRY_DISPLAY_INVITE' => 'bx_organization_invite',
+            'OBJECT_FORM_PRICE' => 'bx_organizations_price',
+            'OBJECT_FORM_PRICE_DISPLAY_ADD' => 'bx_organizations_price_add',
+            'OBJECT_FORM_PRICE_DISPLAY_EDIT' => 'bx_organizations_price_edit',
+            'OBJECT_MENU_ACTIONS_VIEW_ENTRY' => 'bx_organizations_view_actions', // actions menu on view entry page
+            'OBJECT_MENU_ACTIONS_VIEW_ENTRY_MORE' => 'bx_organizations_view_actions_more', // actions menu on view entry page for "more" popup
+            'OBJECT_MENU_ACTIONS_VIEW_ENTRY_ALL' => 'bx_organizations_view_actions_all', // all actions menu on view entry page
+            'OBJECT_MENU_ACTIONS_MY_ENTRIES' => 'bx_organizations_my', // actions menu on profile entries page
+            'OBJECT_MENU_SUBMENU' => 'bx_organizations_submenu', // main module submenu
+            'OBJECT_MENU_SUBMENU_VIEW_ENTRY' => 'bx_organizations_view_submenu',  // view entry submenu
+            'OBJECT_MENU_SUBMENU_VIEW_ENTRY_COVER' => 'bx_organizations_view_submenu_cover',  // view entry submenu displayed in cover
+            'OBJECT_MENU_SUBMENU_VIEW_ENTRY_MAIN_SELECTION' => 'organizations-home', // first item in view entry submenu from main module submenu
+            'OBJECT_MENU_SNIPPET_META' => 'bx_organizations_snippet_meta', // menu for snippet meta info
+            'OBJECT_MENU_MANAGE_TOOLS' => 'bx_organizations_menu_manage_tools', //manage menu in content administration tools
+            'OBJECT_PAGE_VIEW_ENTRY' => 'bx_organizations_view_profile',
+            'OBJECT_PAGE_VIEW_ENTRY_CLOSED' => 'bx_organizations_view_profile_closed',
+            'OBJECT_PRIVACY_VIEW' => 'bx_organizations_allow_view_to',
+            'OBJECT_PRIVACY_LIST_VIEW' => 'bx_organizations_allow_view_favorite_list',
+            'OBJECT_PRIVACY_VIEW_NOTIFICATION_EVENT' => 'bx_organizations_allow_view_notification_to',
+            'OBJECT_PRIVACY_POST' => 'bx_organizations_allow_post_to',
+            'OBJECT_PRIVACY_CONTACT' => 'bx_organizations_allow_contact_to',
+            'OBJECT_GRID_ADMINISTRATION' => 'bx_organizations_administration',
+            'OBJECT_GRID_COMMON' => 'bx_organizations_common',
+            'OBJECT_GRID_CONNECTIONS' => 'bx_organizations_fans',
+            'OBJECT_GRID_PRICES_MANAGE' => 'bx_organizations_prices_manage',
+            'OBJECT_GRID_PRICES_VIEW' => 'bx_organizations_prices_view',
+            'OBJECT_CONNECTIONS' => 'bx_organizations_fans',
+            'OBJECT_UPLOADERS_COVER' => array('bx_organizations_cover_crop'),
+            'OBJECT_UPLOADERS_PICTURE' => array('bx_organizations_picture_crop'),
+            'OBJECT_PRE_LIST_ROLES' => 'bx_organizations_roles',
+            'OBJECT_PRE_LIST_PERIOD_UNITS' => 'bx_organizations_period_units',
+            
+            'BADGES_AVALIABLE' => true,
+
+            'EMAIL_FRIEND_REQUEST' => 'bx_organizations_friend_request',
+            'EMAIL_INVITATION' => 'bx_organizations_invitation',
+            'EMAIL_JOIN_REQUEST' => 'bx_organizations_join_request',
+            'EMAIL_JOIN_CONFIRM' => 'bx_organizations_join_confirm',
+            'EMAIL_FAN_BECOME_ADMIN' => 'bx_organizations_fan_become_admin',
+            'EMAIL_ADMIN_BECOME_FAN' => 'bx_organizations_admin_become_fan',
+            'EMAIL_FAN_SET_ROLE' => 'bx_organizations_set_role',
+            'EMAIL_FAN_REMOVE' => 'bx_organizations_fan_remove',
+            'EMAIL_JOIN_REJECT' => 'bx_organizations_join_reject',
+
+            'TRIGGER_MENU_PROFILE_VIEW_SUBMENU' => 'trigger_profile_view_submenu',
+            'TRIGGER_MENU_PROFILE_SNIPPET_META' => 'trigger_profile_snippet_meta',
+            'TRIGGER_MENU_PROFILE_VIEW_ACTIONS' => 'trigger_profile_view_actions',
+            'TRIGGER_PAGE_VIEW_ENTRY' => 'trigger_page_profile_view_entry',
+
+            // menu items which visibility depends on custom visibility checking
+            'MENU_ITEM_TO_METHOD' => array (
+                'bx_organizations_view_submenu' => $this->_aMenuItems2MethodsSubmenu,
+                'bx_organizations_view_actions' => $this->_aMenuItems2MethodsActions,
+                'bx_organizations_view_actions_more' => $this->_aMenuItems2MethodsActions,
+                'bx_organizations_view_actions_all' => $this->_aMenuItems2MethodsActions,
+            ),
+
+            // informer messages
+            'INFORMERS' => array (
+                'status' => array (
+                    'name' => 'bx-organizations-status-not-active',
+                    'map' => array (
+                        BX_PROFILE_STATUS_PENDING => '_bx_orgs_txt_account_pending',
+                        BX_PROFILE_STATUS_SUSPENDED => '_bx_orgs_txt_account_suspended',
+                    ),
+                ),
+                'status_moderation' => array (
+                    'name' => 'bx-organizations-status-not-active-moderation',
+                    'map' => array (
+                        BX_PROFILE_STATUS_PENDING => '_bx_orgs_txt_account_pending_moderation',
+                        BX_PROFILE_STATUS_SUSPENDED => '_bx_orgs_txt_account_suspended_moderation',
+                    ),
+                ),
+            ),
+
+            // some language keys
+            'T' => array (
+                'txt_sample_single' => '_bx_orgs_txt_sample_single',
+            	'txt_sample_comment_single' => '_bx_orgs_txt_sample_comment_single',
+                'txt_sample_vote_single' => '_bx_orgs_txt_sample_vote_single',
+                'txt_sample_score_up_single' => '_bx_orgs_txt_sample_score_up_single',
+                'txt_sample_score_down_single' => '_bx_orgs_txt_sample_score_down_single',
+            	'txt_sample_pp_single' => '_bx_orgs_txt_sample_pp_single',
+            	'txt_sample_pp_single_with_article' => '_bx_orgs_txt_sample_pp_single_with_article',
+                'txt_sample_pc_single' => '_bx_orgs_txt_sample_pc_single',
+            	'txt_sample_pc_single_with_article' => '_bx_orgs_txt_sample_pc_single_with_article',
+            	'txt_sample_pi_action' => '_bx_orgs_txt_sample_pi_action',
+            	'txt_sample_pi_action_user' => '_bx_orgs_txt_sample_pi_action_user',
+            	'txt_private_group' => '_bx_orgs_txt_private_organization',
+                'txt_group_participants' => '_bx_orgs_ps_group_title_participants',
+                'txt_N_fans' => '_bx_orgs_txt_N_friends',
+                'txt_ntfs_join_invitation' => '_bx_orgs_txt_ntfs_join_invitation',
+            	'txt_ntfs_join_request' => '_bx_orgs_txt_ntfs_join_request',
+                'txt_ntfs_fan_added' => '_bx_orgs_txt_ntfs_fan_added',
+            	'txt_ntfs_timeline_post_common' => '_bx_orgs_txt_ntfs_timeline_post_common',
+                'option_members_mode_multi_roles' => '_bx_orgs_option_members_mode_multi_roles',
+            	'txt_all_entries_by_author' => '_bx_orgs_page_title_browse_by_author',
+            	'form_field_picture' => '_bx_orgs_form_profile_input_picture_search',
+                'form_field_online' => '_bx_orgs_form_profile_input_online_search',
+                'menu_item_title_befriend_sent' => '_bx_orgs_menu_item_title_befriend_sent',
+                'menu_item_title_unfriend_cancel_request' => '_bx_orgs_menu_item_title_unfriend_cancel_request',
+                'menu_item_title_befriend_confirm' => '_bx_orgs_menu_item_title_befriend_confirm',
+                'menu_item_title_unfriend_reject_request' => '_bx_orgs_menu_item_title_unfriend_reject_request',
+                'menu_item_title_befriend' => '_bx_orgs_menu_item_title_befriend',
+                'menu_item_title_unfriend' => '_bx_orgs_menu_item_title_unfriend',
+            	'menu_item_title_become_fan_sent' => '_bx_orgs_menu_item_title_become_fan_sent',
+                'menu_item_title_leave_group_cancel_request' => '_bx_orgs_menu_item_title_leave_organization_cancel_request',
+                'menu_item_title_become_fan' => '_bx_orgs_menu_item_title_become_fan',
+                'menu_item_title_leave_group' => '_bx_orgs_menu_item_title_leave_organization',
+            	'menu_item_manage_my' => '_bx_orgs_menu_item_title_manage_my',
+            	'menu_item_manage_all' => '_bx_orgs_menu_item_title_manage_all',
+            	'grid_action_err_delete' => '_bx_orgs_grid_action_err_delete',
+            	'grid_txt_account_manager' => '_bx_orgs_grid_txt_account_manager',
+                'filter_item_active' => '_bx_orgs_grid_filter_item_title_adm_active',
+            	'filter_item_pending' => '_bx_orgs_grid_filter_item_title_adm_pending',
+            	'filter_item_suspended' => '_bx_orgs_grid_filter_item_title_adm_suspended',
+                'filter_item_unconfirmed' => '_bx_orgs_grid_filter_item_title_adm_unconfirmed',
+            	'filter_item_select_one_filter1' => '_bx_orgs_grid_filter_item_title_adm_select_one_filter1',
+                'filter_item_select_one_filter2' => '_bx_orgs_grid_filter_item_title_adm_select_one_filter2',
+            	'txt_browse_favorites' => '_bx_orgs_page_title_browse_favorites',
+            	'option_redirect_aadd_profile' => '_bx_orgs_option_redirect_aadd_profile',
+            	'option_redirect_aadd_last' => '_bx_orgs_option_redirect_aadd_last',
+            	'option_redirect_aadd_custom' => '_bx_orgs_option_redirect_aadd_custom',
+                'option_activation_on' => '_bx_orgs_option_activation_on',
+            	'option_activation_off' => '_bx_orgs_option_activation_off',
+            	'option_activation_add' => '_bx_orgs_option_activation_add',
+                'option_activation_edit' => '_bx_orgs_option_activation_edit',
+                'txt_n_unit' => '_bx_orgs_txt_n_unit',
+                'txt_buy_title' => '_bx_orgs_grid_action_title_buy_title',
+                'txt_cart_item_title' => '_bx_orgs_txt_cart_item_title',
+                'txt_subscribe_title' => '_bx_orgs_grid_action_title_subscribe_title',
+                'msg_performed' => '_bx_orgs_msg_performed',
+                'err_cannot_perform' => '_bx_orgs_err_cannot_perform',
+            ),
+        ));
+
+        $this->_aJsClasses = array(
+            'main' => 'BxOrgsMain',
+            'manage_tools' => 'BxOrgsManageTools',
+            'categories' => 'BxDolCategories',
+            'prices' => 'BxOrgsPrices'
+        );
+
+        $this->_aJsObjects = array(
+            'main' => 'oBxOrgsMain',
+            'manage_tools' => 'oBxOrgsManageTools',
+            'categories' => 'oBxDolCategories',
+            'prices' => 'oBxOrgsPrices'
+        );
+
+        $this->_aGridObjects = array(
+            'common' => $this->CNF['OBJECT_GRID_COMMON'],
+            'administration' => $this->CNF['OBJECT_GRID_ADMINISTRATION'],
+        );
+    }
+
+}
+
+/** @} */

+ 22 - 0
modules/boonex/organizations/updates/12.0.2_12.0.3/source/classes/BxOrgsCronPruning.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    Organizations Organizations
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxOrgsCronPruning extends BxBaseModGroupsCronPruning
+{
+    public function __construct()
+    {
+        $this->_sModule = 'bx_organizations';
+
+        parent::__construct();
+    }
+}
+
+/** @} */

+ 22 - 0
modules/boonex/organizations/updates/12.0.2_12.0.3/source/classes/BxOrgsFormPrice.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    Organizations Organizations
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxOrgsFormPrice extends BxBaseModGroupsFormPrice
+{
+    public function __construct($aInfo, $oTemplate = false)
+    {
+        $this->_sModule = 'bx_organizations';
+
+        parent::__construct($aInfo, $oTemplate);
+    }
+}
+
+/** @} */

+ 56 - 0
modules/boonex/organizations/updates/12.0.2_12.0.3/source/classes/BxOrgsFormsEntryHelper.php

@@ -0,0 +1,56 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Organizations Organizations
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+/**
+ * Organization profile forms functions
+ */
+class BxOrgsFormsEntryHelper extends BxBaseModGroupsFormsEntryHelper
+{
+    public function __construct($oModule)
+    {
+        parent::__construct($oModule);
+    }
+    
+    public function onDataAddAfter($iAccountId, $iContentId)
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        if($s = parent::onDataAddAfter($iAccountId, $iContentId))
+            return $s;
+
+        $aInvitedMembers = bx_get('initial_members');
+        if(empty($aInvitedMembers) || !is_array($aInvitedMembers))
+            return '';
+
+        $sGroupModule = $this->_oModule->_oConfig->getName();
+        $oGroupProfile = BxDolProfile::getInstanceByContentAndType($iContentId, $sGroupModule);
+        if(!$oGroupProfile)
+            return '';
+        
+        $aGroupContentInfo = bx_srv($sGroupModule, 'get_info', array($iContentId, false));
+        if(empty($aGroupContentInfo) || !is_array($aGroupContentInfo) || !in_array($aGroupContentInfo[$CNF['FIELD_AUTHOR']], $aInvitedMembers))
+            return '';
+
+        $oGroupAuthor = BxDolProfile::getInstance($aGroupContentInfo[$CNF['FIELD_AUTHOR']]);
+        if(!$oGroupAuthor)
+            return '';
+
+        $sGroupAuthorModule = $oGroupAuthor->getModule();
+        if(!BxDolRequest::serviceExists($sGroupAuthorModule, 'act_as_profile') || !bx_srv($sGroupAuthorModule, 'act_as_profile'))
+            return '';
+
+        $this->makeAdmin($oGroupAuthor->id(), $oGroupProfile, $aInvitedMembers);
+
+        return '';
+    }
+}
+
+/** @} */

+ 22 - 0
modules/boonex/organizations/updates/12.0.2_12.0.3/source/classes/BxOrgsGridPricesManage.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    Organizations Organizations
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxOrgsGridPricesManage extends BxBaseModGroupsGridPricesManage
+{
+    public function __construct ($aOptions, $oTemplate = false)
+    {
+        $this->_sModule = 'bx_organizations';
+
+        parent::__construct ($aOptions, $oTemplate);
+    }
+}
+
+/** @} */

+ 30 - 0
modules/boonex/organizations/updates/12.0.2_12.0.3/source/classes/BxOrgsGridPricesView.php

@@ -0,0 +1,30 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Organizations Organizations
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxOrgsGridPricesView extends BxBaseModGroupsGridPricesView
+{
+    public function __construct ($aOptions, $oTemplate = false)
+    {
+        $this->_sModule = 'bx_organizations';
+
+        parent::__construct ($aOptions, $oTemplate);
+    }
+    
+    public function setSellerId($iSellerId = 0)
+    {
+        if(empty($iSellerId) && !empty($this->_iGroupProfileId))
+            $iSellerId = $this->_iGroupProfileId;
+
+        parent::setSellerId($iSellerId);
+    }
+}
+
+/** @} */

+ 70 - 0
modules/boonex/organizations/updates/12.0.2_12.0.3/source/classes/BxOrgsMenuViewActionsAll.php

@@ -0,0 +1,70 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Organizations Organizations
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+/**
+ * View entry all actions menu
+ */
+class BxOrgsMenuViewActionsAll extends BxBaseModGroupsMenuViewActionsAll
+{
+    public function __construct($aObject, $oTemplate = false)
+    {
+        $this->_sModule = 'bx_organizations';
+
+        parent::__construct($aObject, $oTemplate);
+    }
+
+    protected function _getMenuItemJoinOrganizationProfile($aItem)
+    {
+        return $this->_getMenuItemByNameActions($aItem);
+    }
+
+    protected function _getMenuItemEditOrganizationCover($aItem)
+    {
+        return $this->_getMenuItemByNameActionsMore($aItem);
+    }
+
+    protected function _getMenuItemEditOrganizationProfile($aItem)
+    {
+        return $this->_getMenuItemByNameActionsMore($aItem);
+    }
+
+    protected function _getMenuItemEditOrganizationPricing($aItem)
+    {
+        return $this->_getMenuItemByNameActionsMore($aItem);
+    }
+
+    protected function _getMenuItemInviteToOrganization($aItem)
+    {
+        return $this->_getMenuItemByNameActionsMore($aItem);
+    }
+
+    protected function _getMenuItemDeleteOrganizationProfile($aItem)
+    {
+        return $this->_getMenuItemByNameActionDelete($aItem);
+    }
+
+    protected function _getMenuItemDeleteOrganizationAccount($aItem)
+    {
+        return $this->_getMenuItemByNameActionsMore($aItem);
+    }
+
+    protected function _getMenuItemDeleteOrganizationAccountContent($aItem)
+    {
+        return $this->_getMenuItemByNameActionsMore($aItem);
+    }
+    
+    protected function _getMenuItemProfileSetBadges($aItem)
+    {
+        return $this->_getMenuItemByNameActions($aItem);
+    }
+}
+
+/** @} */

+ 152 - 0
modules/boonex/organizations/updates/12.0.2_12.0.3/source/install/config.php

@@ -0,0 +1,152 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Organizations Organizations
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_organizations',
+    'title' => 'Organizations',
+    'note' => 'Basic organization profiles functionality.',
+    '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/organizations/',
+    'home_uri' => 'orgs',
+
+    'db_prefix' => 'bx_organizations_',
+    'class_prefix' => 'BxOrgs',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Organizations',
+
+    /**
+     * Connections.
+     */
+    'connections' => array(
+    	'sys_profiles_friends' => array ('type' => 'profiles'),
+        'sys_profiles_subscriptions' => array ('type' => 'profiles'),
+        'sys_profiles_relations' => array ('type' => 'profiles'),
+    ),
+
+    /**
+     * Menu triggers.
+     */
+    'menu_triggers' => array(
+        'trigger_profile_view_submenu',
+        'trigger_profile_snippet_meta',
+        'trigger_profile_view_actions',
+    ),
+
+    /**
+     * Page triggers.
+     */
+    'page_triggers' => array (
+    	'trigger_page_profile_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_organizations_pics'
+    ),
+
+	/**
+     * Transcoders.
+     */
+    'transcoders' => array(
+    	'bx_organizations_icon', 
+    	'bx_organizations_thumb', 
+    	'bx_organizations_avatar', 
+        'bx_organizations_avatar_big', 
+    	'bx_organizations_picture', 
+    	'bx_organizations_cover', 
+    	'bx_organizations_cover_thumb',
+    	'bx_organizations_gallery'
+    ),
+
+	/**
+     * Extended Search Forms.
+     */
+    'esearches' => array(
+        'bx_organizations',
+    	'bx_organizations_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',
+    ),
+);
+
+/** @} */

Alguns ficheiros não foram mostrados porque muitos ficheiros mudaram neste diff