AntonLV 4 anni fa
parent
commit
e2dbd80fdb
100 ha cambiato i file con 20256 aggiunte e 0 eliminazioni
  1. 51 0
      modules/boonex/accounts/updates/13.0.1_13.0.2/install/config.php
  2. 13 0
      modules/boonex/accounts/updates/13.0.1_13.0.2/install/installer.php
  3. 185 0
      modules/boonex/accounts/updates/13.0.1_13.0.2/source/classes/BxAccntModule.php
  4. 71 0
      modules/boonex/accounts/updates/13.0.1_13.0.2/source/install/config.php
  5. 51 0
      modules/boonex/ads/updates/13.0.2_13.0.3/install/config.php
  6. 13 0
      modules/boonex/ads/updates/13.0.2_13.0.3/install/installer.php
  7. 4 0
      modules/boonex/ads/updates/13.0.2_13.0.3/install/langs/en.xml
  8. 26 0
      modules/boonex/ads/updates/13.0.2_13.0.3/install/sql/enable.sql
  9. 2063 0
      modules/boonex/ads/updates/13.0.2_13.0.3/source/classes/BxAdsModule.php
  10. 151 0
      modules/boonex/ads/updates/13.0.2_13.0.3/source/install/config.php
  11. 586 0
      modules/boonex/ads/updates/13.0.2_13.0.3/source/install/langs/en.xml
  12. 655 0
      modules/boonex/ads/updates/13.0.2_13.0.3/source/install/sql/enable.sql
  13. 52 0
      modules/boonex/ads/updates/13.0.2_13.0.3/source/js/studio.js
  14. 51 0
      modules/boonex/attendant/updates/13.0.0_13.0.1/install/config.php
  15. 13 0
      modules/boonex/attendant/updates/13.0.0_13.0.1/install/installer.php
  16. 213 0
      modules/boonex/attendant/updates/13.0.0_13.0.1/source/classes/BxAttendantModule.php
  17. 77 0
      modules/boonex/attendant/updates/13.0.0_13.0.1/source/install/config.php
  18. 51 0
      modules/boonex/convos/updates/13.0.1_13.0.2/install/config.php
  19. 13 0
      modules/boonex/convos/updates/13.0.1_13.0.2/install/installer.php
  20. 565 0
      modules/boonex/convos/updates/13.0.1_13.0.2/source/classes/BxCnvModule.php
  21. 104 0
      modules/boonex/convos/updates/13.0.1_13.0.2/source/install/config.php
  22. 51 0
      modules/boonex/developer/updates/13.0.1_13.0.2/install/config.php
  23. 13 0
      modules/boonex/developer/updates/13.0.1_13.0.2/install/installer.php
  24. 111 0
      modules/boonex/developer/updates/13.0.1_13.0.2/source/classes/BxDevFunctions.php
  25. 69 0
      modules/boonex/developer/updates/13.0.1_13.0.2/source/install/config.php
  26. 51 0
      modules/boonex/donations/updates/13.0.1_13.0.2/install/config.php
  27. 13 0
      modules/boonex/donations/updates/13.0.1_13.0.2/install/installer.php
  28. 35 0
      modules/boonex/donations/updates/13.0.1_13.0.2/source/classes/BxDonationsAlertsResponse.php
  29. 71 0
      modules/boonex/donations/updates/13.0.1_13.0.2/source/install/config.php
  30. 51 0
      modules/boonex/elasticsearch/updates/12.0.0_13.0.0/install/config.php
  31. 13 0
      modules/boonex/elasticsearch/updates/12.0.0_13.0.0/install/installer.php
  32. 134 0
      modules/boonex/elasticsearch/updates/12.0.0_13.0.0/source/classes/BxElsResponse.php
  33. 71 0
      modules/boonex/elasticsearch/updates/12.0.0_13.0.0/source/install/config.php
  34. 51 0
      modules/boonex/events/updates/13.0.2_13.0.3/install/config.php
  35. 13 0
      modules/boonex/events/updates/13.0.2_13.0.3/install/installer.php
  36. 4 0
      modules/boonex/events/updates/13.0.2_13.0.3/install/langs/en.xml
  37. 14 0
      modules/boonex/events/updates/13.0.2_13.0.3/install/sql/enable.sql
  38. 340 0
      modules/boonex/events/updates/13.0.2_13.0.3/source/classes/BxEventsFormEntry.php
  39. 39 0
      modules/boonex/events/updates/13.0.2_13.0.3/source/classes/BxEventsMenuSnippetMeta.php
  40. 112 0
      modules/boonex/events/updates/13.0.2_13.0.3/source/classes/BxEventsMenuViewActionsAll.php
  41. 488 0
      modules/boonex/events/updates/13.0.2_13.0.3/source/classes/BxEventsModule.php
  42. 55 0
      modules/boonex/events/updates/13.0.2_13.0.3/source/classes/BxEventsTemplate.php
  43. 152 0
      modules/boonex/events/updates/13.0.2_13.0.3/source/install/config.php
  44. 586 0
      modules/boonex/events/updates/13.0.2_13.0.3/source/install/langs/en.xml
  45. 733 0
      modules/boonex/events/updates/13.0.2_13.0.3/source/install/sql/enable.sql
  46. 15 0
      modules/boonex/events/updates/13.0.2_13.0.3/source/template/timeline_post.html
  47. 51 0
      modules/boonex/files/updates/13.0.2_13.0.3/install/config.php
  48. 13 0
      modules/boonex/files/updates/13.0.2_13.0.3/install/installer.php
  49. 609 0
      modules/boonex/files/updates/13.0.2_13.0.3/source/classes/BxFilesModule.php
  50. 135 0
      modules/boonex/files/updates/13.0.2_13.0.3/source/install/config.php
  51. 155 0
      modules/boonex/files/updates/13.0.2_13.0.3/source/js/toolbar_tools.js
  52. 163 0
      modules/boonex/files/updates/13.0.2_13.0.3/source/template/css/main.css
  53. 73 0
      modules/boonex/files/updates/13.0.2_13.0.3/source/template/files_browser_toolbar.html
  54. 55 0
      modules/boonex/forum/updates/13.0.2_13.0.3/install/config.php
  55. 13 0
      modules/boonex/forum/updates/13.0.2_13.0.3/install/installer.php
  56. 6 0
      modules/boonex/forum/updates/13.0.2_13.0.3/install/langs/en.xml
  57. 38 0
      modules/boonex/forum/updates/13.0.2_13.0.3/install/sql/enable.sql
  58. 32 0
      modules/boonex/forum/updates/13.0.2_13.0.3/source/classes/BxForumCategory.php
  59. 702 0
      modules/boonex/forum/updates/13.0.2_13.0.3/source/classes/BxForumGrid.php
  60. 230 0
      modules/boonex/forum/updates/13.0.2_13.0.3/source/classes/BxForumMenuCategories.php
  61. 159 0
      modules/boonex/forum/updates/13.0.2_13.0.3/source/classes/BxForumMenuSnippetMeta.php
  62. 32 0
      modules/boonex/forum/updates/13.0.2_13.0.3/source/classes/BxForumMetatags.php
  63. 1034 0
      modules/boonex/forum/updates/13.0.2_13.0.3/source/classes/BxForumModule.php
  64. 259 0
      modules/boonex/forum/updates/13.0.2_13.0.3/source/classes/BxForumTemplate.php
  65. 149 0
      modules/boonex/forum/updates/13.0.2_13.0.3/source/install/config.php
  66. 445 0
      modules/boonex/forum/updates/13.0.2_13.0.3/source/install/langs/en.xml
  67. 652 0
      modules/boonex/forum/updates/13.0.2_13.0.3/source/install/sql/enable.sql
  68. 579 0
      modules/boonex/forum/updates/13.0.2_13.0.3/source/template/css/main.css
  69. 30 0
      modules/boonex/forum/updates/13.0.2_13.0.3/source/template/entry-preview.html
  70. 13 0
      modules/boonex/forum/updates/13.0.2_13.0.3/source/template/score_element_inline.html
  71. 4 0
      modules/boonex/forum/updates/13.0.2_13.0.3/source/template/status.html
  72. 28 0
      modules/boonex/forum/updates/13.0.2_13.0.3/source/template/unit_gallery.html
  73. 51 0
      modules/boonex/invites/updates/13.0.0_13.0.1/install/config.php
  74. 13 0
      modules/boonex/invites/updates/13.0.0_13.0.1/install/installer.php
  75. 566 0
      modules/boonex/invites/updates/13.0.0_13.0.1/source/classes/BxInvModule.php
  76. 279 0
      modules/boonex/invites/updates/13.0.0_13.0.1/source/classes/BxInvTemplate.php
  77. 80 0
      modules/boonex/invites/updates/13.0.0_13.0.1/source/install/config.php
  78. 51 0
      modules/boonex/market/updates/13.0.2_13.0.3/install/config.php
  79. 23 0
      modules/boonex/market/updates/13.0.2_13.0.3/install/installer.php
  80. 6 0
      modules/boonex/market/updates/13.0.2_13.0.3/install/langs/en.xml
  81. 13 0
      modules/boonex/market/updates/13.0.2_13.0.3/install/sql/install.sql
  82. 53 0
      modules/boonex/market/updates/13.0.2_13.0.3/source/classes/BxMarketAlertsResponse.php
  83. 273 0
      modules/boonex/market/updates/13.0.2_13.0.3/source/classes/BxMarketConfig.php
  84. 320 0
      modules/boonex/market/updates/13.0.2_13.0.3/source/classes/BxMarketFormEntry.php
  85. 1359 0
      modules/boonex/market/updates/13.0.2_13.0.3/source/classes/BxMarketModule.php
  86. 150 0
      modules/boonex/market/updates/13.0.2_13.0.3/source/classes/BxMarketSearchResult.php
  87. 467 0
      modules/boonex/market/updates/13.0.2_13.0.3/source/classes/BxMarketTemplate.php
  88. 140 0
      modules/boonex/market/updates/13.0.2_13.0.3/source/install/config.php
  89. 477 0
      modules/boonex/market/updates/13.0.2_13.0.3/source/install/langs/en.xml
  90. 633 0
      modules/boonex/market/updates/13.0.2_13.0.3/source/install/sql/install.sql
  91. 90 0
      modules/boonex/market/updates/13.0.2_13.0.3/source/js/form.js
  92. 27 0
      modules/boonex/market/updates/13.0.2_13.0.3/source/template/entry-text.html
  93. 87 0
      modules/boonex/market/updates/13.0.2_13.0.3/source/template/unit_gallery.html
  94. 51 0
      modules/boonex/massmailer/updates/13.0.0_13.0.1/install/config.php
  95. 13 0
      modules/boonex/massmailer/updates/13.0.0_13.0.1/install/installer.php
  96. 261 0
      modules/boonex/massmailer/updates/13.0.0_13.0.1/source/classes/BxMassMailerDb.php
  97. 680 0
      modules/boonex/massmailer/updates/13.0.0_13.0.1/source/classes/BxMassMailerModule.php
  98. 77 0
      modules/boonex/massmailer/updates/13.0.0_13.0.1/source/install/config.php
  99. 51 0
      modules/boonex/organizations/updates/13.0.1_13.0.2/install/config.php
  100. 13 0
      modules/boonex/organizations/updates/13.0.1_13.0.2/install/installer.php

+ 51 - 0
modules/boonex/accounts/updates/13.0.1_13.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' => 'Accounts Manager',
+    'version_from' => '13.0.1',
+    'version_to' => '13.0.2',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '13.0.0-B2'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/accounts/updates/update_13.0.1_13.0.2/',
+    'home_uri' => 'accounts_update_1301_1302',
+
+    'module_dir' => 'boonex/accounts/',
+    'module_uri' => 'accounts',
+
+    'db_prefix' => 'bx_accnt_',
+    'class_prefix' => 'BxAccnt',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 0,
+        'update_files' => 1,
+        'update_languages' => 0,
+        'clear_db_cache' => 0,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Accounts',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

+ 13 - 0
modules/boonex/accounts/updates/13.0.1_13.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 BxAccntUpdater extends BxDolStudioUpdater
+{
+    function __construct($aConfig)
+    {
+        parent::__construct($aConfig);
+    }
+}

+ 185 - 0
modules/boonex/accounts/updates/13.0.1_13.0.2/source/classes/BxAccntModule.php

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

+ 71 - 0
modules/boonex/accounts/updates/13.0.1_13.0.2/source/install/config.php

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

+ 51 - 0
modules/boonex/ads/updates/13.0.2_13.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' => 'Ads',
+    'version_from' => '13.0.2',
+    'version_to' => '13.0.3',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '13.0.0-B2'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/ads/updates/update_13.0.2_13.0.3/',
+    'home_uri' => 'ads_update_1302_1303',
+
+    'module_dir' => 'boonex/ads/',
+    'module_uri' => 'ads',
+
+    'db_prefix' => 'bx_ads_',
+    'class_prefix' => 'BxAds',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_files' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Ads',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

+ 13 - 0
modules/boonex/ads/updates/13.0.2_13.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 BxAdsUpdater extends BxDolStudioUpdater
+{
+    function __construct($aConfig)
+    {
+        parent::__construct($aConfig);
+    }
+}

+ 4 - 0
modules/boonex/ads/updates/13.0.2_13.0.3/install/langs/en.xml

@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources name="en" flag="gb" title="English">
+	<string_add name="_bx_ads_acl_action_make_offer"><![CDATA[Make Offer]]></string_add>
+</resources>

+ 26 - 0
modules/boonex/ads/updates/13.0.2_13.0.3/install/sql/enable.sql

@@ -0,0 +1,26 @@
+-- ACL
+SET @iIdActionMakeOffer = (SELECT `ID` FROM `sys_acl_actions` WHERE `Module`='bx_ads' AND `Name`='make offer' LIMIT 1);
+DELETE FROM `sys_acl_actions` WHERE `ID`=@iIdActionMakeOffer;
+DELETE FROM `sys_acl_matrix` WHERE `IDAction`=@iIdActionMakeOffer;
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_ads', 'make offer', NULL, '_bx_ads_acl_action_make_offer', '', 1, 3);
+SET @iIdActionMakeOffer = 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
+
+-- make offer
+(@iStandard, @iIdActionMakeOffer),
+(@iModerator, @iIdActionMakeOffer),
+(@iAdministrator, @iIdActionMakeOffer),
+(@iPremium, @iIdActionMakeOffer);

+ 2063 - 0
modules/boonex/ads/updates/13.0.2_13.0.3/source/classes/BxAdsModule.php

@@ -0,0 +1,2063 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Ads Ads
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+define('BX_ADS_STATUS_OFFER', 'offer');
+define('BX_ADS_STATUS_SOLD', 'sold');
+
+define('BX_ADS_OFFER_STATUS_ACCEPTED', 'accepted');
+define('BX_ADS_OFFER_STATUS_AWAITING', 'awaiting');
+define('BX_ADS_OFFER_STATUS_DECLINED', 'declined');
+define('BX_ADS_OFFER_STATUS_CANCELED', 'canceled');
+
+/**
+ * Ads module
+ */
+class BxAdsModule extends BxBaseModTextModule
+{
+    protected $_aOfferStatuses;
+
+    function __construct(&$aModule)
+    {
+        parent::__construct($aModule);
+
+        $this->_oConfig->init($this->_oDb);
+
+        $CNF = &$this->_oConfig->CNF;
+
+        $this->_aSearchableNamesExcept = array_merge($this->_aSearchableNamesExcept, array(
+            $CNF['FIELD_CATEGORY_VIEW'],
+            $CNF['FIELD_CATEGORY_SELECT']
+        ));
+
+        $this->_aOfferStatuses = array(
+            BX_ADS_OFFER_STATUS_ACCEPTED,
+            BX_ADS_OFFER_STATUS_AWAITING,
+            BX_ADS_OFFER_STATUS_DECLINED
+        );
+    }
+
+    public function actionGetCategoryForm()
+    {
+        if(bx_get('category') === false)
+            return echoJson(array());
+
+        return echoJson(array(
+            'content' => $this->serviceGetCreatePostForm(array(
+                'absolute_action_url' => true,
+                'dynamic_mode' => true
+            ))
+        ));
+    }
+
+    public function actionCheckName()
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $iId = (int)bx_get($CNF['FIELD_ID']);
+    	$sTitle = bx_process_input(bx_get($CNF['FIELD_TITLE']));
+
+    	echoJson($this->serviceCheckName($sTitle, $iId));
+    }
+
+    public function actionInterested()
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $iContentId = bx_process_input(bx_get('id'), BX_DATA_INT);
+
+        $aContentInfo = $this->_oDb->getContentInfoById($iContentId);
+        if(empty($aContentInfo) || !is_array($aContentInfo))
+            return echoJson(array());
+
+        $iViewer = bx_get_logged_profile_id();        
+        $oViewer = BxDolProfile::getInstance($iViewer);
+        if(!$oViewer)
+            return echoJson(array());
+
+        $iContentAuthor = (int)$aContentInfo[$CNF['FIELD_AUTHOR']];
+        if($iContentAuthor == $iViewer)
+            return echoJson(array('msg' => _t('_bx_ads_txt_err_your_own')));
+
+        if($this->_oDb->isInterested($iContentId, $iViewer))
+            return echoJson(array('msg' => _t('_bx_ads_txt_err_duplicate')));
+
+        $iInterestId = $this->_oDb->insertInterested(array('entry_id' => $iContentId, 'profile_id' => $iViewer));
+        if(!$iInterestId)
+            return echoJson(array('msg' => _t('_bx_ads_txt_err_cannot_perform_action')));
+
+        bx_alert($this->getName(), 'doInterest', $iContentId, $iViewer, array(
+            'subobject_id' => $iInterestId, 
+            'subobject_author_id' => $iViewer, 
+
+            'object_author_id' => $iContentAuthor
+        ));
+
+        if(getParam($CNF['PARAM_USE_IIN']) == 'on')
+            sendMailTemplate($CNF['ETEMPLATE_INTERESTED'], 0, $iContentAuthor, array(
+                'viewer_name' => $oViewer->getDisplayName(),
+                'viewer_url' => $oViewer->getUrl(),
+                'ad_name' => $aContentInfo[$CNF['FIELD_TITLE']],
+                'ad_url' => BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink('page.php', array(
+                    'i' => $CNF['URI_VIEW_ENTRY'], 
+                    $CNF['FIELD_ID'] => $iContentId
+                ))
+            ));
+
+        return echoJson(array('msg' => _t('_bx_ads_txt_msg_author_notified')));
+    }
+
+    public function actionShow()
+    {
+        return echoJson($this->_actionChangeStatus(BX_BASE_MOD_TEXT_STATUS_ACTIVE));
+    }
+
+    public function actionHide()
+    {
+        return echoJson($this->_actionChangeStatus(BX_BASE_MOD_TEXT_STATUS_HIDDEN));
+    }
+
+    public function actionMakeOffer()
+    {
+        $CNF = &$this->_oConfig->CNF;
+        $sJsObject = $this->_oConfig->getJsObject('entry');
+
+        $iAuthorId = bx_get_logged_profile_id();
+        $iContentId = bx_process_input(bx_get('id'), BX_DATA_INT);
+
+        if(empty($iAuthorId))
+            return echoJson(array('code' => 1, 'eval' => 'window.open("' . BxDolPermalinks::getInstance()->permalink('page.php?i=login') . '", "_self");'));
+
+        $aContentInfo = $this->_oDb->getContentInfoById($iContentId);
+        if(empty($aContentInfo) || !is_array($aContentInfo))
+            return echoJson(array());
+
+        if(($mixedCheck = $this->checkAllowedMakeOffer($aContentInfo)) !== CHECK_ACTION_RESULT_ALLOWED)
+            return echoJson(array('code' => 2, 'msg' => $mixedCheck));
+
+        $aOffer = $this->_oDb->getOffersBy(array(
+            'type' => 'content_and_author_ids', 
+            'content_id' => $iContentId, 
+            'author_id' => $iAuthorId, 
+            'status' => BX_ADS_OFFER_STATUS_AWAITING
+        ));
+
+        if(!empty($aOffer) && is_array($aOffer))
+            return echoJson(array('code' => 3, 'msg' => _t('_bx_ads_txt_err_duplicate')));
+
+        $aOffer = $this->_oDb->getOffersBy(array(
+            'type' => 'content_and_author_ids', 
+            'content_id' => $iContentId, 
+            'author_id' => $iAuthorId, 
+            'status' => BX_ADS_OFFER_STATUS_ACCEPTED
+        ));
+
+        if(!empty($aOffer) && is_array($aOffer))
+            return echoJson(array('code' => 4, 'msg' => _t('_bx_ads_txt_err_offer_accepted')));
+
+        $oForm = BxDolForm::getObjectInstance($CNF['OBJECT_FORM_OFFER'], $CNF['OBJECT_FORM_OFFER_DISPLAY_ADD']);
+        $oForm->aFormAttrs['action'] = BX_DOL_URL_ROOT . bx_append_url_params($this->_oConfig->getBaseUri() . 'make_offer', array('id' => $iContentId));
+        $oForm->initChecker();
+
+        if($oForm->isSubmittedAndValid()) {
+            $aValToAdd = array('content_id' => $iContentId, 'author_id' => $iAuthorId);
+
+            $iId = (int)$oForm->insert($aValToAdd);
+            if($iId != 0) {
+                $this->checkAllowedMakeOffer($aContentInfo, true);
+
+                $this->onOfferAdded($iId, $aResult);
+
+                $aResult = array('code' => 0, 'msg' => _t('_bx_ads_txt_msg_offer_added'), 'eval' => $sJsObject . '.onMakeOffer(oData);', 'id' => $iId);
+            }
+            else
+                $aResult = array('code' => 5, 'msg' => _t('_bx_ads_txt_err_cannot_perform_action'));
+
+            return echoJson($aResult);
+        }
+
+        $sContent = BxTemplFunctions::getInstance()->transBox($this->_oConfig->getHtmlIds('offer_popup'), $this->_oTemplate->parseHtmlByName('offer_popup.html', array(
+            'form_id' => $oForm->getId(),
+            'form' => $oForm->getCode(true)
+        )));
+
+        return echoJson(array('popup' => array('html' => $sContent, 'options' => array('closeOnOuterClick' => false, 'removeOnClose' => true))));
+    }
+
+    public function actionViewOffer()
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $iAuthorId = bx_get_logged_profile_id();
+        $iOfferId = bx_process_input(bx_get('id'), BX_DATA_INT);
+
+        $aOffer = $this->_oDb->getOffersBy(array('type' => 'id', 'id' => $iOfferId));
+        if(empty($aOffer) || !is_array($aOffer))
+            return echoJson(array());
+        
+        $oForm = BxDolForm::getObjectInstance($CNF['OBJECT_FORM_OFFER'], $CNF['OBJECT_FORM_OFFER_DISPLAY_VIEW']);
+        $oForm->initChecker($aOffer);
+
+        $sContent = BxTemplFunctions::getInstance()->transBox($this->_oConfig->getHtmlIds('offer_popup'), $this->_oTemplate->parseHtmlByName('offer_popup.html', array(
+            'form_id' => $oForm->getId(),
+            'form' => $oForm->getCode(true)
+        )));
+
+        return echoJson(array('popup' => array('html' => $sContent, 'options' => array('closeOnOuterClick' => true, 'removeOnClose' => true))));
+    }
+
+    public function actionAcceptOffer()
+    {
+        $iId = bx_process_input(bx_get('id'), BX_DATA_INT);
+
+        if(!$this->offerAccept($iId))
+            return echoJson(array('msg' => _t('_bx_ads_txt_err_cannot_perform_action')));
+
+        return echoJson(array('msg' => _t('_bx_ads_txt_msg_offer_accepted'), 'reload' => 1));
+    }
+
+    public function actionDeclineOffer()
+    {
+        $iId = bx_process_input(bx_get('id'), BX_DATA_INT);
+
+        if(!$this->offerDecline($iId))
+            return echoJson(array('msg' => _t('_bx_ads_txt_err_cannot_perform_action')));
+
+        return echoJson(array('msg' => _t('_bx_ads_txt_msg_offer_declined'), 'reload' => 1));
+    }
+            
+    public function actionCancelOffer()
+    {
+        $iId = bx_process_input(bx_get('id'), BX_DATA_INT);
+
+        if(!$this->offerCancel($iId))
+            return echoJson(array('msg' => _t('_bx_ads_txt_err_cannot_perform_action')));     
+
+        return echoJson(array('msg' => _t('_bx_ads_txt_msg_offer_canceled'), 'reload' => 1));
+    }
+    
+    public function actionPayOffer()
+    {
+        $iId = bx_process_input(bx_get('id'), BX_DATA_INT);
+
+        if(($mixedResult = $this->offerPay($iId)) !== false)
+            return echoJson($mixedResult);
+
+        return echoJson(array('msg' => _t('_bx_ads_txt_err_cannot_perform_action')));     
+    }
+
+    public function actionShipped()
+    {
+        return echoJson($this->_actionMarkAs('shipped'));
+    }
+
+    public function actionReceived()
+    {
+        return echoJson($this->_actionMarkAs('received'));
+    }
+
+    public function serviceGetSafeServices()
+    {
+        $a = parent::serviceGetSafeServices();
+        return array_merge($a, array (
+            'EntityReviews' => '',
+            'EntityReviewsRating' => '',
+            'CategoriesList' => '',
+            'BrowseCategory' => '',
+        ));
+    }
+
+    public function serviceCheckName($sTitle, $iId = 0)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+    	if(empty($sTitle))
+            return array();
+
+        $sName = '';
+        if(!empty($iId)) {
+            $aEntry = $this->_oDb->getContentInfoById($iId); 
+            if(strcmp($sTitle, $aEntry[$CNF['FIELD_NAME']]) == 0) 
+                $sName = $sTitle;
+        }
+
+        return array(
+            'title' => $sTitle,
+            'name' => !empty($sName) ? $sName : $this->_oConfig->getEntryName($sTitle, $iId)
+    	);
+    }
+
+    public function serviceUpdateCategoriesStats($mixedContentInfo = false)
+    {
+        $aContentInfo = [];
+        if(!empty($mixedContentInfo))
+            $aContentInfo = !is_array($mixedContentInfo) ? $this->_oDb->getContentInfoById((int)$mixedContentInfo) : $mixedContentInfo;
+
+        $iCategoryId = 0;
+        if($aContentInfo && !empty($aContentInfo['category']))
+            $iCategoryId = (int)$aContentInfo['category'];
+
+        return $this->serviceUpdateCategoriesStatsByCategory($iCategoryId);
+    }
+
+    public function serviceUpdateCategoriesStatsByCategory($iCategoryId = 0)
+    {
+        $aParams = ['type' => 'collect_stats'];
+        if($iCategoryId)
+            $aParams['category_id'] = (int)$iCategoryId;
+
+        $aStats = $this->_oDb->getCategories($aParams);
+        if(empty($aStats) || !is_array($aStats))
+            return true;
+
+        $iUpdated = 0;
+        foreach($aStats as $aStat)
+            if($this->_oDb->updateCategory(array('items' => $aStat['count']), array('id' => $aStat['id'])))
+                $iUpdated++;
+
+        return count($aStats) == $iUpdated;
+    }
+
+    public function serviceGetCategoryOptions($iParentId, $bPleaseSelect = false)
+    {
+        $aValues = array();
+        if($bPleaseSelect)
+            $aValues[] = array('key' => '', 'value' => _t('_sys_please_select'));
+
+        $this->_getCategoryOptions($iParentId, $aValues);
+
+        return $aValues;
+    }
+
+    public function serviceGetSearchableFields($aInputsAdd = array())
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $aResult = parent::serviceGetSearchableFields(array_merge($aInputsAdd, $this->_getSearchableFields()));
+        unset($aResult[$CNF['FIELD_NOTES_PURCHASED']]);
+        unset($aResult[$CNF['FIELD_CATEGORY_VIEW']], $aResult[$CNF['FIELD_CATEGORY_SELECT']]);
+        unset($aResult[$CNF['FIELD_PRICE']], $aResult[$CNF['FIELD_YEAR']]);
+
+        return $aResult;
+    }
+
+    public function serviceGetSearchableFieldsExtended($aInputsAdd = array())
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $aInputsAdd = array_merge($aInputsAdd, $this->_getSearchableFields());
+
+        if(isset($aInputsAdd[$CNF['FIELD_CATEGORY']])) {
+            $aInputsAdd[$CNF['FIELD_CATEGORY']]['type'] = 'select';
+            $aInputsAdd[$CNF['FIELD_CATEGORY']]['values_src'] = BxDolService::getSerializedService($this->_oConfig->getName(), 'get_category_options', array(0));
+        }
+
+        if(isset($aInputsAdd[$CNF['FIELD_PRICE']])) {
+            $aInputsAdd[$CNF['FIELD_PRICE']]['search_type'] = 'text_range';
+            $aInputsAdd[$CNF['FIELD_PRICE']]['search_operator'] = 'between';
+        }
+
+        if(isset($aInputsAdd[$CNF['FIELD_YEAR']])) {
+            $aInputsAdd[$CNF['FIELD_YEAR']]['search_type'] = 'text_range';
+            $aInputsAdd[$CNF['FIELD_YEAR']]['search_operator'] = 'between';
+        }
+
+        return parent::serviceGetSearchableFieldsExtended($aInputsAdd);
+    }
+
+    /**
+     * Mark an ad as shipped/received by seller/bauer accordingly.
+     * @param type $sAction - shipped/received action.
+     * @param type $iContentId - an ad the action will be performed with.
+     * @param integer $iProfileSrc - profile, who performed the action.
+     * @param integer $iProfileDst - profile, the action is pointed on.
+     * @return boolean - true or a string value with error message.
+     */
+    public function serviceMarkAs($sAction, $iContentId, $iProfileSrc = 0, $iProfileDst = 0)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        if(!$iProfileSrc)
+            $iProfileSrc = bx_get_logged_profile_id();
+
+        $sTxtError = '_bx_ads_txt_err_cannot_perform_action';
+        $aContentInfo = $this->_oDb->getContentInfoById($iContentId);
+
+        $sMethodCheck = 'checkAllowedMark' . bx_gen_method_name($sAction) . 'ForProfile';
+        if(!method_exists($this, $sMethodCheck))
+            return _t($sTxtError);
+
+        if(($mixedCheckResult = $this->$sMethodCheck($aContentInfo, false, $iProfileSrc)) !== CHECK_ACTION_RESULT_ALLOWED)
+            return $mixedCheckResult;
+
+        if((int)$this->_oDb->updateEntriesBy(array($CNF['FIELD_' . strtoupper($sAction)] => time()), array($CNF['FIELD_ID'] => $iContentId)) == 0)
+            return _t($sTxtError);
+
+        $this->$sMethodCheck($aContentInfo, true, $iProfileSrc);
+
+        $sMethodOnResult = 'on' . bx_gen_method_name($sAction);
+        if(method_exists($this, $sMethodOnResult))
+            $this->$sMethodOnResult($aContentInfo, $iProfileSrc, $iProfileDst);        
+
+        return true;
+    }
+
+    public function serviceEntityCreate ($sParams = false)
+    {
+        if(($sDisplay = $this->getCategoryDisplay('add')) !== false) {
+            if(empty($sParams) || !is_array($sParams))
+                $sParams = array();
+
+            $sParams['display'] = $sDisplay;
+        }
+
+        return parent::serviceEntityCreate($sParams);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_ads Ads 
+     * @subsection bx_ads-page_blocks Page Blocks
+     * @subsubsection bx_ads-entity_reviews entity_reviews
+     * 
+     * @code bx_srv('bx_ads', 'entity_reviews', [...]); @endcode
+     * 
+     * Get reviews for particular content
+     * @param $iContentId content ID
+     * 
+     * @see BxAdsModule::serviceEntityReviews
+     */
+    /** 
+     * @ref bx_ads-entity_reviews "entity_reviews"
+     */
+    public function serviceEntityReviews($iContentId = 0)
+    {
+        $CNF = &$this->_oConfig->CNF;
+        if(empty($CNF['OBJECT_REVIEWS']))
+            return false;
+
+        return $this->_entityComments($CNF['OBJECT_REVIEWS'], $iContentId);
+    }
+    
+    /**
+     * @page service Service Calls
+     * @section bx_ads Ads 
+     * @subsection bx_ads-page_blocks Page Blocks
+     * @subsubsection bx_ads-entity_reviews_rating entity_reviews_rating
+     * 
+     * @code bx_srv('bx_ads', 'entity_reviews_rating', [...]); @endcode
+     * 
+     * Get reviews rating for particular content
+     * @param $iContentId content ID
+     * 
+     * @see BxAdsModule::serviceEntityReviewsRating
+     */
+    /** 
+     * @ref bx_ads-entity_reviews_rating "entity_reviews_rating"
+     */
+    public function serviceEntityReviewsRating($iContentId = 0)
+    {
+        $CNF = &$this->_oConfig->CNF;
+        if(empty($CNF['OBJECT_REVIEWS']))
+            return false;
+
+        if(!$iContentId)
+            $iContentId = bx_process_input(bx_get('id'), BX_DATA_INT);
+
+        if(!$iContentId)
+            return false;
+
+        $oCmts = BxDolCmts::getObjectInstance($CNF['OBJECT_REVIEWS'], $iContentId);
+        if (!$oCmts || !$oCmts->isEnabled())
+            return false;
+
+        return $oCmts->getRatingBlock(array('in_designbox' => false));
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_ads Ads 
+     * @subsection bx_ads-page_blocks Page Blocks
+     * @subsubsection bx_ads-categories_list categories_list
+     * 
+     * @code bx_srv('bx_ads', 'categories_list', [...]); @endcode
+     * 
+     * Get reviews rating for particular content
+     * @param $aParams additional params array, such as 'show_empty'
+     * 
+     * @see BxAdsModule::serviceCategoriesList
+     */
+    /** 
+     * @ref bx_ads-categories_list "categories_list"
+     */
+    public function serviceCategoriesList($aParams = array())
+    {
+        if(!isset($aParams['show_empty']))
+            $aParams['show_empty'] = true;
+
+        return $this->_oTemplate->categoriesList($aParams);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_ads Ads 
+     * @subsection bx_ads-browse Browse
+     * @subsubsection bx_ads-browse_category browse_category
+     * 
+     * @code bx_srv('bx_ads', 'browse_category', [...]); @endcode
+     * 
+     * Get reviews rating for particular content
+     * @param $iCategoryId category ID
+     * @param $aParams additional params array, such as empty_message, ajax_paginate, etc
+     * 
+     * @see BxAdsModule::serviceBrowseCategory
+     */
+    /**
+     * @ref bx_ads-browse_category "browse_category"
+     */
+    public function serviceBrowseCategory($iCategoryId = 0, $aParams = array())
+    {
+        $sParamName = $sParamGet = 'category';
+
+        if(!$iCategoryId && bx_get($sParamGet) !== false)
+            $iCategoryId = bx_process_input(bx_get($sParamGet), BX_DATA_INT);
+
+        $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']);
+        }
+
+        $aBlock = $this->_serviceBrowse ($sParamName, array_merge(array($sParamName => $iCategoryId), $aParams), BX_DB_PADDING_DEF, $bEmptyMessage, $bAjaxPaginate);
+        if(!empty($aBlock['content'])) {
+            $aCategory = $this->_oDb->getCategories(array('type' => 'id', 'id' => $iCategoryId));
+            if(!empty($aCategory['title']))
+                $aBlock['title'] = _t('_bx_ads_page_block_title_entries_by_category_mask', _t($aCategory['title']));
+        }
+
+        return $aBlock;
+    }
+
+    public function serviceGetNotificationsData()
+    {
+        $sModule = $this->_aModule['name'];
+
+        $sEventPrivacy = $sModule . '_allow_view_event_to';
+        if(BxDolPrivacy::getObjectInstance($sEventPrivacy) === false)
+            $sEventPrivacy = '';
+
+        $aResult = parent::serviceGetNotificationsData();
+        $aResult['handlers'] = array_merge($aResult['handlers'], array(
+            array('group' => $sModule . '_interest', 'type' => 'insert', 'alert_unit' => $sModule, 'alert_action' => 'doInterest', 'module_name' => $sModule, 'module_method' => 'get_notifications_interest', 'module_class' => 'Module', 'module_event_privacy' => $sEventPrivacy),
+            array('group' => $sModule . '_paid', 'type' => 'insert', 'alert_unit' => $sModule, 'alert_action' => 'license_register', 'module_name' => $sModule, 'module_method' => 'get_notifications_license_register', 'module_class' => 'Module', 'module_event_privacy' => $sEventPrivacy),
+            //---> To Buyer
+            array('group' => $sModule . '_shipped', 'type' => 'insert', 'alert_unit' => $sModule, 'alert_action' => 'shipped', 'module_name' => $sModule, 'module_method' => 'get_notifications_shipped', 'module_class' => 'Module', 'module_event_privacy' => $sEventPrivacy),
+            //<---
+            array('group' => $sModule . '_received', 'type' => 'insert', 'alert_unit' => $sModule, 'alert_action' => 'received', 'module_name' => $sModule, 'module_method' => 'get_notifications_received', 'module_class' => 'Module', 'module_event_privacy' => $sEventPrivacy),
+
+            array('group' => $sModule . '_offer_added', 'type' => 'insert', 'alert_unit' => $sModule, 'alert_action' => 'offer_added', 'module_name' => $sModule, 'module_method' => 'get_notifications_offer_added', 'module_class' => 'Module', 'module_event_privacy' => $sEventPrivacy),
+            //---> To Offerer
+            array('group' => $sModule . '_offer_accepted', 'type' => 'insert', 'alert_unit' => $sModule, 'alert_action' => 'offer_accepted', 'module_name' => $sModule, 'module_method' => 'get_notifications_offer_accepted', 'module_class' => 'Module', 'module_event_privacy' => $sEventPrivacy),
+            array('group' => $sModule . '_offer_declined', 'type' => 'insert', 'alert_unit' => $sModule, 'alert_action' => 'offer_declined', 'module_name' => $sModule, 'module_method' => 'get_notifications_offer_declined', 'module_class' => 'Module', 'module_event_privacy' => $sEventPrivacy),
+            //<---
+            array('group' => $sModule . '_offer_canceled', 'type' => 'insert', 'alert_unit' => $sModule, 'alert_action' => 'offer_canceled', 'module_name' => $sModule, 'module_method' => 'get_notifications_offer_canceled', 'module_class' => 'Module', 'module_event_privacy' => $sEventPrivacy)
+        ));
+
+        $aResult['settings'] = array_merge($aResult['settings'], array(
+            array('group' => 'interest', 'unit' => $sModule, 'action' => 'doInterest', 'types' => array('personal')),
+
+            array('group' => 'usage', 'unit' => $sModule, 'action' => 'license_register', 'types' => array('personal')),
+            array('group' => 'usage', 'unit' => $sModule, 'action' => 'shipped', 'types' => array('personal')),
+            array('group' => 'usage', 'unit' => $sModule, 'action' => 'received', 'types' => array('personal')),
+            array('group' => 'usage', 'unit' => $sModule, 'action' => 'offer_added', 'types' => array('personal')),
+            array('group' => 'usage', 'unit' => $sModule, 'action' => 'offer_accepted', 'types' => array('personal')),
+            array('group' => 'usage', 'unit' => $sModule, 'action' => 'offer_declined', 'types' => array('personal')),
+            array('group' => 'usage', 'unit' => $sModule, 'action' => 'offer_canceled', 'types' => array('personal')),
+        ));
+
+        $aResult['alerts'] = array_merge($aResult['alerts'], array(
+            array('unit' => $sModule, 'action' => 'doInterest'),
+            array('unit' => $sModule, 'action' => 'license_register'),
+            array('unit' => $sModule, 'action' => 'shipped'),
+            array('unit' => $sModule, 'action' => 'received'),
+            array('unit' => $sModule, 'action' => 'offer_added'),
+            array('unit' => $sModule, 'action' => 'offer_accepted'),
+            array('unit' => $sModule, 'action' => 'offer_declined'),
+            array('unit' => $sModule, 'action' => 'offer_canceled'),
+        ));
+
+        return $aResult; 
+    }
+
+    public function serviceGetNotificationsInsertData($oAlert, $aHandler, $aDataItems)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $aResult = [];
+        switch($oAlert->sAction) {
+            case 'license_register':
+                $aContentInfo = $this->_oDb->getContentInfoById($oAlert->aExtras['product_id']);
+                if(empty($aContentInfo) || !is_array($aContentInfo)) {
+                    $aResult = $aDataItems;
+                    break;
+                }
+
+                foreach($aDataItems as $aDataItem) {
+                    $aDataItem = array_merge($aDataItem, [
+                        'owner_id' => $oAlert->aExtras['profile_id'],
+                        'object_id' => $aContentInfo[$CNF['FIELD_ID']],
+                        'object_owner_id' => $aContentInfo[$CNF['FIELD_AUTHOR']],
+                        'object_privacy_view' => BX_DOL_PG_ALL
+                    ]);
+
+                    $aResult[] = $aDataItem;
+                }
+                break;
+
+            case 'shipped':
+                foreach($aDataItems as $aDataItem) {
+                    $aLicense = $this->_oDb->getLicense(['type' => 'entry_id', 'entry_id' => $aDataItem['object_id'], 'newest' => true]);
+                    if(!empty($aLicense) && is_array($aLicense))
+                        $aDataItem['object_owner_id'] = $aLicense['profile_id'];
+
+                    $aResult[] = $aDataItem;
+                }
+                break;
+
+            case 'offer_added':
+            case 'offer_canceled':
+                foreach($aDataItems as $aDataItem) {
+                    $aDataItem['object_owner_id'] = $oAlert->aExtras['object_author_id'];
+
+                    $aResult[] = $aDataItem;
+                }
+                break;
+
+            case 'offer_accepted':
+            case 'offer_declined':
+                foreach($aDataItems as $aDataItem) {
+                    $aDataItem['object_owner_id'] = $oAlert->aExtras['offer_author_id'];
+
+                    $aResult[] = $aDataItem;
+                }
+                break;
+
+            default:
+                $aResult = $aDataItems;
+        }
+
+        return $aResult;
+    }
+
+    public function serviceGetNotificationsInterest($aEvent)
+    {
+    	$CNF = &$this->_oConfig->CNF;
+
+    	$iContentId = (int)$aEvent['object_id'];
+    	$aContentInfo = $this->_oDb->getContentInfoById($iContentId);
+        if(empty($aContentInfo) || !is_array($aContentInfo))
+            return array();
+
+        $iInterestedId = (int)$aEvent['subobject_id'];
+        $aInterestedInfo = $this->_oDb->getInterested(array('type' => 'id', 'id' => $iInterestedId));
+        if(empty($aInterestedInfo) || !is_array($aInterestedInfo))
+            return array();
+
+        $sEntryUrl = BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink('page.php?i=' . $CNF['URI_VIEW_ENTRY'] . '&id=' . $iContentId);
+
+        return array(
+            'entry_sample' => $CNF['T']['txt_sample_single'],
+            'entry_url' => $sEntryUrl,
+            'entry_caption' => $aContentInfo[$CNF['FIELD_TITLE']],
+            'entry_author' => $aContentInfo[$CNF['FIELD_AUTHOR']],
+            'subentry_sample' => $CNF['T']['txt_sample_interest_single'],
+            'subentry_url' => '',
+            'lang_key' => '_bx_ads_txt_ntfs_subobject_interested', //may be empty or not specified. In this case the default one from Notification module will be used.
+        );
+    }
+
+    public function serviceGetNotificationsLicenseRegister($aEvent)
+    {
+        return $this->_serviceGetNotificationsByEntryAndAction($aEvent, 'license_register');
+    }
+
+    public function serviceGetNotificationsShipped($aEvent)
+    {
+        $aResult = $this->_serviceGetNotificationsByEntryAndAction($aEvent, 'shipped');
+        $aResult['entry_author'] = $aEvent['object_owner_id'];
+
+        return $aResult;
+    }
+
+    public function serviceGetNotificationsReceived($aEvent)
+    {
+        return $this->_serviceGetNotificationsByEntryAndAction($aEvent, 'received');
+    }
+
+    public function serviceGetNotificationsOfferAdded($aEvent)
+    {
+        return $this->_serviceGetNotificationsByOfferAndAction($aEvent, 'offer_added');
+    }
+
+    public function serviceGetNotificationsOfferAccepted($aEvent)
+    {
+        $aResult = $this->_serviceGetNotificationsByOfferAndAction($aEvent, 'offer_accepted');
+        $aResult['entry_author'] = $aEvent['object_owner_id'];
+
+        return $aResult;
+    }
+
+    public function serviceGetNotificationsOfferDeclined($aEvent)
+    {
+        $aResult = $this->_serviceGetNotificationsByOfferAndAction($aEvent, 'offer_declined');
+        $aResult['entry_author'] = $aEvent['object_owner_id'];
+
+        return $aResult;
+    }
+
+    public function serviceGetNotificationsOfferCanceled($aEvent)
+    {
+        return $this->_serviceGetNotificationsByOfferAndAction($aEvent, 'offer_canceled');
+    }
+
+    protected function _serviceGetNotificationsByEntryAndAction($aEvent, $sAction)
+    {
+    	$CNF = &$this->_oConfig->CNF;
+
+    	$iContentId = (int)$aEvent['object_id'];
+    	$aContentInfo = $this->_oDb->getContentInfoById($iContentId);
+        if(empty($aContentInfo) || !is_array($aContentInfo))
+            return array();
+
+        $sEntryUrl = BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink('page.php?i=' . $CNF['URI_VIEW_ENTRY'] . '&id=' . $iContentId);
+
+        return array(
+            'entry_sample' => $CNF['T']['txt_sample_single'],
+            'entry_url' => $sEntryUrl,
+            'entry_caption' => $aContentInfo[$CNF['FIELD_TITLE']],
+            'entry_author' => $aContentInfo[$CNF['FIELD_AUTHOR']],
+            'subentry_sample' => '',
+            'subentry_url' => '',
+            'lang_key' => '_bx_ads_txt_ntfs_object_' . $sAction, //may be empty or not specified. In this case the default one from Notification module will be used.
+        );
+    }
+
+    protected function _serviceGetNotificationsByOfferAndAction($aEvent, $sAction)
+    {
+    	$CNF = &$this->_oConfig->CNF;
+
+    	$iOfferId = (int)$aEvent['object_id'];
+    	$aOfferInfo = $this->_oDb->getOffersBy(['type' => 'id', 'id' => $iOfferId]);
+        if(empty($aOfferInfo) || !is_array($aOfferInfo))
+            return array();
+
+        $iContentId = $aOfferInfo[$CNF['FIELD_OFR_CONTENT']];
+        $aContentInfo = $this->_oDb->getContentInfoById($iContentId);
+        if(empty($aContentInfo) || !is_array($aContentInfo))
+            return array();
+
+        $sEntryUrl = BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink('page.php?i=' . $CNF['URI_VIEW_ENTRY'] . '&id=' . $iContentId);
+
+        return array(
+            'object_id' => $iContentId,
+            'entry_sample' => $CNF['T']['txt_sample_single'],
+            'entry_url' => $sEntryUrl,
+            'entry_caption' => $aContentInfo[$CNF['FIELD_TITLE']],
+            'entry_author' => $aContentInfo[$CNF['FIELD_AUTHOR']],
+            'subentry_sample' => '',
+            'subentry_url' => '',
+            'lang_key' => '_bx_ads_txt_ntfs_' . $sAction, //may be empty or not specified. In this case the default one from Notification module will be used.
+        );
+    }
+    
+    /**
+     * @page service Service Calls
+     * @section bx_ads Ads
+     * @subsection bx_ads-page_blocks Page Blocks
+     * @subsubsection bx_ads-block_licenses block_licenses
+     * 
+     * @code bx_srv('bx_ads', 'block_licenses', [...]); @endcode
+     * 
+     * Get page block with a list of licenses purchased by currently logged member.
+     *
+     * @return an array describing a block to display on the site or false if there is no enough input data. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
+     * 
+     * @see BxAdsModule::serviceBlockLicenses
+     */
+    /** 
+     * @ref bx_ads-block_licenses "block_licenses"
+     */
+    public function serviceBlockLicenses() 
+    {
+        return $this->_getBlockLicenses();
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_ads Ads
+     * @subsection bx_ads-page_blocks Page Blocks
+     * @subsubsection bx_ads-block_licenses_administration block_licenses_administration
+     * 
+     * @code bx_srv('bx_ads', 'block_licenses_administration', [...]); @endcode
+     * 
+     * Get page block with a list of all licenses. It's needed for moderators/administrators.
+     *
+     * @return an array describing a block to display on the site or false if there is no enough input data. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
+     * 
+     * @see BxAdsModule::serviceBlockLicensesAdministration
+     */
+    /** 
+     * @ref bx_ads-block_licenses "block_licenses"
+     */
+    public function serviceBlockLicensesAdministration() 
+    {
+        return $this->_getBlockLicenses('administration');
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_ads Ads
+     * @subsection bx_ads-page_blocks Page Blocks
+     * @subsubsection bx_ads-block_licenses_note block_licenses_note
+     * 
+     * @code bx_srv('bx_ads', 'block_licenses_note', [...]); @endcode
+     * 
+     * Get page block with a notice for licenses usage.
+     *
+     * @return HTML string with block content to display on the site.
+     * 
+     * @see BxAdsModule::serviceBlockLicensesNote
+     */
+    /** 
+     * @ref bx_ads-block_licenses_note "block_licenses_note"
+     */
+    public function serviceBlockLicensesNote()
+    {
+        return MsgBox(_t('_bx_ads_page_block_content_licenses_note'));
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_ads Ads
+     * @subsection bx_ads-payments Payments
+     * @subsubsection bx_ads-get_payment_data get_payment_data
+     * 
+     * @code bx_srv('bx_ads', 'get_payment_data', [...]); @endcode
+     * 
+     * Get an array with module's description. Is needed for payments processing module.
+     * 
+     * @return an array with module's description.
+     * 
+     * @see BxAdsModule::serviceGetPaymentData
+     */
+    /** 
+     * @ref bx_ads-get_payment_data "get_payment_data"
+     */
+    public function serviceGetPaymentData()
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $oPermalink = BxDolPermalinks::getInstance();
+
+        $aResult = $this->_aModule;
+        $aResult['url_browse_order_common'] = BX_DOL_URL_ROOT . $oPermalink->permalink($CNF['URL_LICENSES_COMMON'], array('filter' => '{order}'));
+        $aResult['url_browse_order_administration'] = BX_DOL_URL_ROOT . $oPermalink->permalink($CNF['URL_LICENSES_ADMINISTRATION'], array('filter' => '{order}'));
+
+        return $aResult;
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_ads Ads
+     * @subsection bx_ads-payments Payments
+     * @subsubsection bx_ads-get_cart_item get_cart_item
+     * 
+     * @code bx_srv('bx_ads', 'get_cart_item', [...]); @endcode
+     * 
+     * Get an array with prodict's description. Is used in Shopping Cart in payments processing module.
+     * 
+     * @param $mixedItemId product's ID or Unique Name.
+     * @return an array with prodict's description. Empty array is returned if something is wrong.
+     * 
+     * @see BxAdsModule::serviceGetCartItem
+     */
+    /** 
+     * @ref bx_ads-get_cart_item "get_cart_item"
+     */
+    public function serviceGetCartItem($mixedItemId)
+    {
+    	$CNF = &$this->_oConfig->CNF;
+
+        if(!$mixedItemId)
+            return array();
+
+        if(is_numeric($mixedItemId))
+            $aItem = $this->_oDb->getContentInfoById((int)$mixedItemId);
+        else
+            $aItem = $this->_oDb->getContentInfoByName($mixedItemId);
+
+        if(empty($aItem) || !is_array($aItem))
+            return array();
+
+        $iItemId = (int)$aItem[$CNF['FIELD_ID']];
+        $fItemPrice = (float)$aItem[$CNF['FIELD_PRICE']];
+
+        if($this->isAuction($aItem)) {
+            $aOffer = $this->_oDb->getOffersBy(array(
+                'type' => 'accepted', 
+                'content_id' => $iItemId, 
+                'status' => BX_ADS_OFFER_STATUS_ACCEPTED
+            ));
+
+            if(!empty($aOffer) && is_array($aOffer))
+                $fItemPrice = (float)$aOffer[$CNF['FIELD_OFR_AMOUNT']];
+        }
+
+        return array (
+            'id' => $iItemId,
+            'author_id' => $aItem[$CNF['FIELD_AUTHOR']],
+            'name' => $aItem[$CNF['FIELD_NAME']],
+            'title' => $aItem[$CNF['FIELD_TITLE']],
+            'description' => $aItem[$CNF['FIELD_TEXT']],
+            'url' => BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink('page.php?i=' . $CNF['URI_VIEW_ENTRY'], array('id' => $aItem[$CNF['FIELD_ID']])),
+            'price_single' => $fItemPrice,
+            'price_recurring' => '',
+            'period_recurring' => 0,
+            'period_unit_recurring' => '',
+            'trial_recurring' => ''
+        );
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_ads Ads
+     * @subsection bx_ads-payments Payments
+     * @subsubsection bx_ads-get_cart_items get_cart_items
+     * 
+     * @code bx_srv('bx_ads', 'get_cart_items', [...]); @endcode
+     * 
+     * Get an array with prodicts' descriptions by seller. Is used in Manual Order Processing in payments processing module.
+     * 
+     * @param $iSellerId seller ID.
+     * @return an array with prodicts' descriptions. Empty array is returned if something is wrong or seller doesn't have any products.
+     * 
+     * @see BxAdsModule::serviceGetCartItems
+     */
+    /** 
+     * @ref bx_ads-get_cart_items "get_cart_items"
+     */
+    public function serviceGetCartItems($iSellerId)
+    {
+    	$CNF = &$this->_oConfig->CNF;
+
+        $iSellerId = (int)$iSellerId;
+        if(empty($iSellerId))
+            return array();
+
+        $aItems = $this->_oDb->getEntriesByAuthor($iSellerId);
+
+        $aResult = array();
+        foreach($aItems as $aItem) {
+            if($aItem[$CNF['FIELD_STATUS']] != BX_BASE_MOD_TEXT_STATUS_ACTIVE || empty($aItem[$CNF['FIELD_QUANTITY']]))
+                continue;
+
+            $aResult[] = array(
+                'id' => $aItem[$CNF['FIELD_ID']],
+                'author_id' => $aItem[$CNF['FIELD_AUTHOR']],
+                'name' => $aItem[$CNF['FIELD_NAME']],
+                'title' => $aItem[$CNF['FIELD_TITLE']],
+                'description' => $aItem[$CNF['FIELD_TEXT']],
+                'url' => BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink('page.php?i=' . $CNF['URI_VIEW_ENTRY'], array('id' => $aItem[$CNF['FIELD_ID']])),
+                'price_single' => $aItem[$CNF['FIELD_PRICE_SINGLE']],
+                'price_recurring' => '',
+                'period_recurring' => 0,
+                'period_unit_recurring' => '',
+                'trial_recurring' => ''
+            );
+        }
+
+        return $aResult;
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_ads Ads
+     * @subsection bx_ads-payments Payments
+     * @subsubsection bx_ads-authorize_cart_item authorize_cart_item
+     * 
+     * @code bx_srv('bx_ads', 'authorize_cart_item', [...]); @endcode
+     * 
+     * Authorize the order to process a single time payment inside the Ads module in future. Is called with payment processing module after the order was authorized there.
+     * 
+     * @param $iClientId client ID.
+     * @param $iSellerId seller ID
+     * @param $iItemId item ID.
+     * @param $iItemCount the number of purchased items.
+     * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
+     * @return an array with authorize prodict's description. Empty array is returned if something is wrong.
+     * 
+     * @see BxAdsModule::serviceAuthorizeCartItem
+     */
+    /** 
+     * @ref bx_ads-authorize_cart_item "authorize_cart_item"
+     */
+    public function serviceAuthorizeCartItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+    	$aItem = $this->serviceGetCartItem($iItemId);
+        if(empty($aItem) || !is_array($aItem))
+            return [];
+
+        $aEntry = $this->_oDb->getContentInfoById($iItemId);
+        if(empty($aEntry) || !is_array($aEntry))
+            return [];
+
+        bx_alert($this->getName(), 'order_authorize', 0, false, [
+            'product_id' => $iItemId,
+            'profile_id' => $iClientId,
+            'order' => $sOrder,
+            'count' => $iItemCount
+        ]);
+
+        return $aItem;
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_ads Ads
+     * @subsection bx_ads-payments Payments
+     * @subsubsection bx_ads-register_cart_item register_cart_item
+     * 
+     * @code bx_srv('bx_ads', 'register_cart_item', [...]); @endcode
+     * 
+     * Register a processed single time payment inside the Ads module. Is called with payment processing module after the payment was registered there.
+     * 
+     * @param $iClientId client ID.
+     * @param $iSellerId seller ID
+     * @param $iItemId item ID.
+     * @param $iItemCount the number of purchased items.
+     * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
+     * @param $sLicense license number genereted with payment processing module for internal usage
+     * @return an array with purchased prodict's description. Empty array is returned if something is wrong.
+     * 
+     * @see BxAdsModule::serviceRegisterCartItem
+     */
+    /** 
+     * @ref bx_ads-register_cart_item "register_cart_item"
+     */
+    public function serviceRegisterCartItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+    	$aItem = $this->serviceGetCartItem($iItemId);
+        if(empty($aItem) || !is_array($aItem))
+            return array();
+
+        $aEntry = $this->_oDb->getContentInfoById($iItemId);
+        $iEntryQnt = (int)$aEntry[$CNF['FIELD_QUANTITY']];
+        if(empty($aEntry) || !is_array($aEntry) || ($iEntryQnt - $iItemCount) < 0)
+            return array();
+
+        if(!$this->_oDb->registerLicense($iClientId, $iItemId, $iItemCount, $sOrder, $sLicense))
+            return array();
+
+        $iEntryQnt -= $iItemCount;
+        $this->_oDb->updateEntriesBy(array(
+            $CNF['FIELD_QUANTITY'] => $iEntryQnt,
+            $CNF['FIELD_STATUS'] => $iEntryQnt == 0 ? BX_ADS_STATUS_SOLD : BX_BASE_MOD_TEXT_STATUS_ACTIVE,
+            $CNF['FIELD_SOLD'] => $iEntryQnt == 0 ? time() : 0,
+        ), array($CNF['FIELD_ID'] => $iItemId));
+
+        bx_alert($this->getName(), 'license_register', 0, false, array(
+            'product_id' => $iItemId,
+            'profile_id' => $iClientId,
+            'order' => $sOrder,
+            'license' => $sLicense,
+            'count' => $iItemCount
+        ));
+
+        if($iEntryQnt == 0) {
+            $aParams = $this->_alertParams($aEntry);
+            bx_alert($this->getName(), 'sold', $iItemId, false, $aParams);
+        }
+
+        $oClient = BxDolProfile::getInstanceMagic($iClientId);
+        $oSeller = BxDolProfile::getInstanceMagic($iSellerId);
+        $sSellerUrl = $oSeller->getUrl();
+        $sSellerName = $oSeller->getDisplayName();
+
+        $sNote = $aEntry[$CNF['FIELD_NOTES_PURCHASED']];
+        if(empty($sNote))
+            $sNote = _t('_bx_ads_txt_purchased_note', $sSellerUrl, $sSellerName);
+
+        sendMailTemplate($CNF['ETEMPLATE_PURCHASED'], 0, $iClientId, array(
+            'client_name' => $oClient->getDisplayName(),
+            'entry_name' => $aEntry[$CNF['FIELD_TITLE']],
+            'entry_url' => BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink('page.php?i=' . $CNF['URI_VIEW_ENTRY'], array('id' => $aEntry[$CNF['FIELD_ID']])),
+            'vendor_url' => $sSellerUrl,
+            'vendor_name' => $sSellerName,
+            'count' => (int)$iItemCount,
+            'license' => $sLicense,
+            'notes' => $sNote,
+        ));
+
+        return $aItem;
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_ads Ads
+     * @subsection bx_ads-payments Payments
+     * @subsubsection bx_ads-authorize_subscription_item authorize_subscription_item
+     * 
+     * @code bx_srv('bx_ads', 'authorize_subscription_item', [...]); @endcode
+     * 
+     * Authorize the order to process a subscription (recurring payment) inside the Ads module in future. Is called with payment processing module after the order for subscription was authorized there.
+     * 
+     * @param $iClientId client ID.
+     * @param $iSellerId seller ID
+     * @param $iItemId item ID.
+     * @param $iItemCount the number of purchased items.
+     * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
+     * @return an array with authorize prodict's description. Empty array is returned if something is wrong.
+     * 
+     * @see BxAdsModule::serviceAuthorizeSubscriptionItem
+     */
+    /** 
+     * @ref bx_ads-authorize_subscription_item "authorize_subscription_item"
+     */
+    public function serviceAuthorizeSubscriptionItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder)
+    {
+        return [];
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_ads Ads
+     * @subsection bx_ads-payments Payments
+     * @subsubsection bx_ads-register_subscription_item register_subscription_item
+     * 
+     * @code bx_srv('bx_ads', 'register_subscription_item', [...]); @endcode
+     * 
+     * Register a processed subscription (recurring payment) inside the Ads module. Is called with payment processing module after the subscription was registered there.
+     * 
+     * @param $iClientId client ID.
+     * @param $iSellerId seller ID
+     * @param $iItemId item ID.
+     * @param $iItemCount the number of purchased items.
+     * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
+     * @param $sLicense license number genereted with payment processing module for internal usage
+     * @return an array with subscribed prodict's description. Empty array is returned if something is wrong.
+     * 
+     * @see BxAdsModule::serviceRegisterSubscriptionItem
+     */
+    /** 
+     * @ref bx_ads-register_subscription_item "register_subscription_item"
+     */
+    public function serviceRegisterSubscriptionItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense)
+    {
+        return [];
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_ads Ads
+     * @subsection bx_ads-payments Payments
+     * @subsubsection bx_ads-reregister_cart_item reregister_cart_item
+     * 
+     * @code bx_srv('bx_ads', 'reregister_cart_item', [...]); @endcode
+     * 
+     * Reregister a single time payment inside the Ads module. Is called with payment processing module after the payment was reregistered there.
+     * 
+     * @param $iClientId client ID.
+     * @param $iSellerId seller ID
+     * @param $iItemIdOld old item ID.
+     * @param $iItemIdNew new item ID.
+     * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
+     * @return an array with purchased prodict's description. Empty array is returned if something is wrong.
+     * 
+     * @see BxAdsModule::serviceReregisterCartItem
+     */
+    /** 
+     * @ref bx_ads-reregister_cart_item "reregister_cart_item"
+     */
+    public function serviceReregisterCartItem($iClientId, $iSellerId, $iItemIdOld, $iItemIdNew, $sOrder)
+    {
+        return array();
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_ads Ads
+     * @subsection bx_ads-payments Payments
+     * @subsubsection bx_ads-reregister_subscription_item reregister_subscription_item
+     * 
+     * @code bx_srv('bx_ads', 'reregister_subscription_item', [...]); @endcode
+     * 
+     * Reregister a subscription (recurring payment) inside the Ads module. Is called with payment processing module after the subscription was reregistered there.
+     * 
+     * @param $iClientId client ID.
+     * @param $iSellerId seller ID
+     * @param $iItemIdOld old item ID.
+     * @param $iItemIdNew new item ID.
+     * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
+     * @return an array with subscribed prodict's description. Empty array is returned if something is wrong.
+     * 
+     * @see BxAdsModule::serviceReregisterSubscriptionItem
+     */
+    /** 
+     * @ref bx_ads-reregister_subscription_item "reregister_subscription_item"
+     */
+    public function serviceReregisterSubscriptionItem($iClientId, $iSellerId, $iItemIdOld, $iItemIdNew, $sOrder)
+    {
+        return array();
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_ads Ads
+     * @subsection bx_ads-payments Payments
+     * @subsubsection bx_ads-unregister_cart_item unregister_cart_item
+     * 
+     * @code bx_srv('bx_ads', 'unregister_cart_item', [...]); @endcode
+     * 
+     * Unregister an earlier processed single time payment inside the Ads module. Is called with payment processing module after the payment was unregistered there.
+     * 
+     * @param $iClientId client ID.
+     * @param $iSellerId seller ID
+     * @param $iItemId item ID.
+     * @param $iItemCount the number of purchased items.
+     * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
+     * @param $sLicense license number genereted with payment processing module for internal usage
+     * @return boolean value determining where the payment was unregistered or not.
+     * 
+     * @see BxAdsModule::serviceUnregisterCartItem
+     */
+    /** 
+     * @ref bx_ads-unregister_cart_item "unregister_cart_item"
+     */
+    public function serviceUnregisterCartItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense)
+    {
+        if(!$this->_oDb->unregisterLicense($iClientId, $iItemId, $sOrder, $sLicense))
+            return false;
+
+        bx_alert($this->getName(), 'license_unregister', 0, false, array(
+            'product_id' => $iItemId,
+            'profile_id' => $iClientId,
+            'order' => $sOrder,
+            'license' => $sLicense,
+            'count' => $iItemCount
+        ));
+
+    	return true;;
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_ads Ads
+     * @subsection bx_ads-payments Payments
+     * @subsubsection bx_ads-unregister_subscription_item unregister_subscription_item
+     * 
+     * @code bx_srv('bx_ads', 'unregister_subscription_item', [...]); @endcode
+     * 
+     * Unregister an earlier processed subscription (recurring payment) inside the Ads module. Is called with payment processing module after the subscription was unregistered there.
+     * 
+     * @param $iClientId client ID.
+     * @param $iSellerId seller ID
+     * @param $iItemId item ID.
+     * @param $iItemCount the number of purchased items.
+     * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
+     * @param $sLicense license number genereted with payment processing module for internal usage
+     * @return boolean value determining where the subscription was unregistered or not.
+     * 
+     * @see BxAdsModule::serviceUnregisterSubscriptionItem
+     */
+    /** 
+     * @ref bx_ads-unregister_subscription_item "unregister_subscription_item"
+     */
+    public function serviceUnregisterSubscriptionItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense)
+    {
+    	return true; 
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_ads Ads
+     * @subsection bx_ads-payments Payments
+     * @subsubsection bx_ads-cancel_subscription_item cancel_subscription_item
+     * 
+     * @code bx_srv('bx_ads', 'cancel_subscription_item', [...]); @endcode
+     * 
+     * Cancel an earlier processed subscription (recurring payment) inside the Ads module. Is called with payment processing module after the subscription was canceled there.
+     * 
+     * @param $iClientId client ID.
+     * @param $iSellerId seller ID
+     * @param $iItemId item ID.
+     * @param $iItemCount the number of purchased items.
+     * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
+     * @return boolean value determining where the subscription was canceled or not.
+     * 
+     * @see BxAdsModule::serviceCancelSubscriptionItem
+     */
+    /** 
+     * @ref bx_ads-cancel_subscription_item "cancel_subscription_item"
+     */
+    public function serviceCancelSubscriptionItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder)
+    {
+    	return true;
+    }
+
+    public function serviceGetOffersCount($sStatus = '')
+    {
+        if(!$this->_oConfig->isAuction())
+            return 0;
+
+        if(empty($sStatus) || !in_array($sStatus, $this->_aOfferStatuses))
+            $sStatus = BX_ADS_OFFER_STATUS_AWAITING;
+
+        $iUserId = bx_get_logged_profile_id();
+        return $this->_oDb->getOffersBy(array('type' => 'content_author_id', 'author_id' => $iUserId, 'status' => $sStatus, 'count' => true));
+    }
+
+    public function serviceGetLiveUpdates($sStatus, $aMenuItemParent, $aMenuItemChild, $iCount = 0)
+    {
+        if(!in_array($sStatus, $this->_aOfferStatuses))
+            return false;
+
+        $iUserId = bx_get_logged_profile_id();
+        $iCountNew = $this->_oDb->getOffersBy(array('type' => 'content_author_id', 'author_id' => $iUserId, 'status' => $sStatus, 'count' => true));
+        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.
+    	);
+    }
+
+    public function serviceOffers()       
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        if(!$this->_oConfig->isAuction())
+            return '';
+
+        $oGrid = BxDolGrid::getObjectInstance($CNF['OBJECT_GRID_OFFERS_ALL']);
+        if(!$oGrid)
+            return '';
+
+        return $oGrid->getCode();
+    }
+
+    public function serviceEntityOffers($iContentId = 0)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        if(!$this->_oConfig->isAuction())
+            return '';
+
+        $oGrid = BxDolGrid::getObjectInstance($CNF['OBJECT_GRID_OFFERS']);
+        if(!$oGrid)
+            return '';
+
+        if(empty($iContentId) && ($_iContentId = bx_get('id')) !== false)
+            $iContentId = (int)$_iContentId;
+
+        $oGrid->setContentId($iContentId);
+        return $oGrid->getCode();
+    }
+
+    public function serviceEntityOfferAccepted($iContentId = 0)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        if(!$this->_oConfig->isAuction())
+            return '';
+
+        $iUserId = bx_get_logged_profile_id();
+
+        if(empty($iContentId) && ($_iContentId = bx_get('id')) !== false)
+            $iContentId = (int)$_iContentId;
+
+        $aContent = $this->_oDb->getContentInfoById($iContentId);
+        if(empty($aContent) || !is_array($aContent) || $aContent[$CNF['FIELD_QUANTITY']] <= 0)
+            return '';
+
+        $aOffer = $this->_oDb->getOffersBy(array(
+            'type' => 'content_and_author_ids', 
+            'content_id' => $iContentId, 
+            'author_id' => $iUserId,
+            'status' => BX_ADS_OFFER_STATUS_ACCEPTED
+        ));
+
+        if(empty($aOffer) || !is_array($aOffer))
+            return '';
+
+        return $this->_oTemplate->entryOfferAccepted($iUserId, $aContent, $aOffer);
+    }
+
+    public function isEntryActive($aContentInfo)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        if($aContentInfo[$CNF['FIELD_AUTHOR']] == bx_get_logged_profile_id() || $this->_isModerator())
+            return true;
+
+        if(isset($CNF['FIELD_STATUS']) && !in_array($aContentInfo[$CNF['FIELD_STATUS']], array(BX_BASE_MOD_TEXT_STATUS_ACTIVE, BX_ADS_STATUS_OFFER, BX_ADS_STATUS_SOLD)))
+            return false;
+
+        if(isset($CNF['FIELD_STATUS_ADMIN']) && $aContentInfo[$CNF['FIELD_STATUS_ADMIN']] != 'active')
+            return false;
+
+        return true;        
+    }
+
+    public function isAuction($aContentInfo)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        return $this->_oConfig->isAuction() && (int)$aContentInfo[$CNF['FIELD_AUCTION']] != 0;
+    }
+
+    public function isAllowedMakeOffer($mixedContent, $isPerformAction = false)
+    {
+        return $this->checkAllowedMakeOffer($mixedContent, $isPerformAction) === CHECK_ACTION_RESULT_ALLOWED;
+    }
+
+    public function checkAllowedMakeOffer($mixedContent, $isPerformAction = false)
+    {
+        $CNF = &$this->_oConfig->CNF;
+        $sTxtError = '_sys_txt_access_denied';
+
+        $iProfileId = bx_get_logged_profile_id();
+
+        if(!is_array($mixedContent))
+            $mixedContent = $this->_oDb->getContentInfoById((int)$mixedContent);
+
+        if(empty($mixedContent) || !is_array($mixedContent))
+            return _t($sTxtError);
+
+        if(!$this->isAuction($mixedContent) || (int)$mixedContent[$CNF['FIELD_QUANTITY']] <= 0)
+            return _t($sTxtError);
+
+        if($mixedContent[$CNF['FIELD_AUTHOR']] == $iProfileId)
+            return _t($sTxtError);
+
+        $aCheck = checkActionModule($iProfileId, 'make offer', $this->getName(), $isPerformAction);
+        if($aCheck[CHECK_ACTION_RESULT] !== CHECK_ACTION_RESULT_ALLOWED)
+            return $aCheck[CHECK_ACTION_MESSAGE];
+
+        return CHECK_ACTION_RESULT_ALLOWED;
+    }
+
+    public function isAllowedViewOffers($mixedContent, $isPerformAction = false)
+    {
+        return $this->checkAllowedViewOffers($mixedContent, $isPerformAction) === CHECK_ACTION_RESULT_ALLOWED;
+    }
+
+    public function checkAllowedViewOffers($mixedContent, $isPerformAction = false)
+    {
+        $CNF = &$this->_oConfig->CNF;
+        $sTxtError = '_sys_txt_access_denied';
+
+        if(!is_array($mixedContent))
+            $mixedContent = $this->_oDb->getContentInfoById((int)$mixedContent);
+
+        if(empty($mixedContent) || !is_array($mixedContent))
+            return _t($sTxtError);
+
+        if(!$this->isAuction($mixedContent))
+            return _t($sTxtError);
+
+        if($this->_isModerator())
+            return CHECK_ACTION_RESULT_ALLOWED;
+
+        if($mixedContent[$CNF['FIELD_AUTHOR']] == bx_get_logged_profile_id())
+            return CHECK_ACTION_RESULT_ALLOWED;
+
+        return _t($sTxtError);
+    }
+
+    public function isAllowedMarkShipped($mixedContent, $isPerformAction = false)
+    {
+        return $this->checkAllowedMarkShipped($mixedContent, $isPerformAction) === CHECK_ACTION_RESULT_ALLOWED;
+    }
+
+    public function checkAllowedMarkShipped($mixedContent, $isPerformAction = false)
+    {
+        return $this->checkAllowedMarkShippedForProfile($mixedContent, $isPerformAction);
+    }
+
+    public function checkAllowedMarkShippedForProfile($mixedContent, $isPerformAction = false, $iProfileId = false)
+    {
+        $CNF = &$this->_oConfig->CNF;
+        $sTxtError = '_sys_txt_access_denied';
+
+        if(!$iProfileId)
+            $iProfileId = bx_get_logged_profile_id();
+                
+        if(!is_array($mixedContent))
+            $mixedContent = $this->_oDb->getContentInfoById((int)$mixedContent);
+
+        if(empty($mixedContent) || !is_array($mixedContent))
+            return _t($sTxtError);
+
+        if((int)$mixedContent[$CNF['FIELD_SHIPPED']] != 0 || $mixedContent[$CNF['FIELD_AUTHOR']] != $iProfileId)
+            return _t($sTxtError);
+
+        return CHECK_ACTION_RESULT_ALLOWED;
+    }
+
+    public function isAllowedMarkReceived($mixedContent, $isPerformAction = false)
+    {
+        return $this->checkAllowedMarkReceived($mixedContent, $isPerformAction) === CHECK_ACTION_RESULT_ALLOWED;
+    }
+
+    public function checkAllowedMarkReceived($mixedContent, $isPerformAction = false)
+    {
+        return $this->checkAllowedMarkReceivedForProfile($mixedContent, $isPerformAction);
+    }
+
+    public function checkAllowedMarkReceivedForProfile($mixedContent, $isPerformAction = false, $iProfileId = false)
+    {
+        $CNF = &$this->_oConfig->CNF;
+        $sTxtError = '_sys_txt_access_denied';
+
+        if(!$iProfileId)
+            $iProfileId = bx_get_logged_profile_id();
+
+        if(!is_array($mixedContent))
+            $mixedContent = $this->_oDb->getContentInfoById((int)$mixedContent);
+
+        if(empty($mixedContent) || !is_array($mixedContent))
+            return _t($sTxtError);
+
+        if((int)$mixedContent[$CNF['FIELD_RECEIVED']] != 0 || !$this->_oDb->hasLicense($iProfileId, $mixedContent[$CNF['FIELD_ID']]))
+            return _t($sTxtError);
+
+        return CHECK_ACTION_RESULT_ALLOWED;
+    }
+
+    public function onPublished($iContentId)
+    {
+        $this->serviceUpdateCategoriesStats($iContentId);
+
+        parent::onPublished($iContentId);
+    }
+
+    public function onOfferAdded($iOfferId, &$aResult)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $aOfferInfo = $this->_oDb->getOffersBy(array('type' => 'id', 'id' => $iOfferId));
+        if(empty($aOfferInfo) || !is_array($aOfferInfo))
+            return;
+
+        $iContentId = (int)$aOfferInfo[$CNF['FIELD_OFR_CONTENT']];
+        $aContentInfo = $this->_oDb->getContentInfoById($iContentId);
+        if(empty($aContentInfo) || !is_array($aContentInfo))
+            return;
+
+        $iViewer = bx_get_logged_profile_id();        
+        $oViewer = BxDolProfile::getInstanceMagic($iViewer);
+
+        if(getParam($CNF['PARAM_USE_IIN']) == 'on')
+            sendMailTemplate($CNF['ETEMPLATE_OFFER_ADDED'], 0, $aContentInfo[$CNF['FIELD_AUTHOR']], array(
+                'viewer_name' => $oViewer->getDisplayName(),
+                'viewer_url' => $oViewer->getUrl(),
+                'entry_name' => $aContentInfo[$CNF['FIELD_TITLE']],
+                'entry_url' => BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink('page.php', array(
+                    'i' => $CNF['URI_VIEW_ENTRY'], 
+                    $CNF['FIELD_ID'] => $iContentId
+                ))
+            ));
+
+        $aParams = $this->_alertParamsOffer($aContentInfo, $aOfferInfo);
+        $aParams['override_result'] = &$aResult;
+        bx_alert($this->getName(), 'offer_added', $iOfferId, $aOfferInfo[$CNF['FIELD_OFR_AUTHOR']], $aParams);
+    }
+
+    public function onOfferAccepted($iOfferId)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $aOfferInfo = $this->_oDb->getOffersBy(array('type' => 'id', 'id' => $iOfferId));
+        if(empty($aOfferInfo) || !is_array($aOfferInfo))
+            return;
+
+        $iContentId = (int)$aOfferInfo[$CNF['FIELD_OFR_CONTENT']];
+        $aContentInfo = $this->_oDb->getContentInfoById($iContentId);
+        if(empty($aContentInfo) || !is_array($aContentInfo))
+            return;
+
+        if(!$this->_oDb->updateEntriesBy(array($CNF['FIELD_STATUS'] => BX_ADS_STATUS_OFFER), array($CNF['FIELD_ID'] => $iContentId)))
+            return;
+
+        $iOfferer = (int)$aOfferInfo[$CNF['FIELD_OFR_AUTHOR']];
+        $oOfferer = BxDolProfile::getInstanceMagic($iOfferer);
+
+        if(getParam($CNF['PARAM_USE_IIN']) == 'on')
+            sendMailTemplate($CNF['ETEMPLATE_OFFER_ACCEPTED'], 0, $iOfferer, array(
+                'offerer_name' => $oOfferer->getDisplayName(),
+                'offerer_url' => $oOfferer->getUrl(),
+                'entry_name' => $aContentInfo[$CNF['FIELD_TITLE']],
+                'entry_url' => BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink('page.php', array(
+                    'i' => $CNF['URI_VIEW_ENTRY'], 
+                    $CNF['FIELD_ID'] => $iContentId
+                ))
+            ));
+
+        $aParams = $this->_alertParamsOffer($aContentInfo, $aOfferInfo);
+        bx_alert($this->getName(), 'offer_accepted', $iOfferId, $aContentInfo[$CNF['FIELD_AUTHOR']], $aParams);
+    }
+
+    public function onOfferDeclined($iOfferId)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $aOfferInfo = $this->_oDb->getOffersBy(array('type' => 'id', 'id' => $iOfferId));
+        if(empty($aOfferInfo) || !is_array($aOfferInfo))
+            return;
+
+        $iContentId = (int)$aOfferInfo[$CNF['FIELD_OFR_CONTENT']];
+        $aContentInfo = $this->_oDb->getContentInfoById($iContentId);
+        if(empty($aContentInfo) || !is_array($aContentInfo))
+            return;
+
+        $iOfferer = (int)$aOfferInfo[$CNF['FIELD_OFR_AUTHOR']];
+        $oOfferer = BxDolProfile::getInstanceMagic($iOfferer);
+
+        if(getParam($CNF['PARAM_USE_IIN']) == 'on')
+            sendMailTemplate($CNF['ETEMPLATE_OFFER_DECLINED'], 0, $iOfferer, array(
+                'offerer_name' => $oOfferer->getDisplayName(),
+                'offerer_url' => $oOfferer->getUrl(),
+                'entry_name' => $aContentInfo[$CNF['FIELD_TITLE']],
+                'entry_url' => BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink('page.php', array(
+                    'i' => $CNF['URI_VIEW_ENTRY'], 
+                    $CNF['FIELD_ID'] => $iContentId
+                ))
+            ));
+
+        $aParams = $this->_alertParamsOffer($aContentInfo, $aOfferInfo);
+        bx_alert($this->getName(), 'offer_declined', $iOfferId, $aContentInfo[$CNF['FIELD_AUTHOR']], $aParams);
+    }
+
+    public function onOfferCanceled($iOfferId)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $aOfferInfo = $this->_oDb->getOffersBy(array('type' => 'id', 'id' => $iOfferId));
+        if(empty($aOfferInfo) || !is_array($aOfferInfo))
+            return;
+
+        $iContentId = (int)$aOfferInfo[$CNF['FIELD_OFR_CONTENT']];
+        $aContentInfo = $this->_oDb->getContentInfoById($iContentId);
+        if(empty($aContentInfo) || !is_array($aContentInfo))
+            return;
+
+        if(!$this->_oDb->updateEntriesBy(array($CNF['FIELD_STATUS'] => BX_BASE_MOD_TEXT_STATUS_ACTIVE), array($CNF['FIELD_ID'] => $iContentId)))
+            return;
+
+        $iOfferer = (int)$aOfferInfo[$CNF['FIELD_OFR_AUTHOR']];
+        $oOfferer = BxDolProfile::getInstanceMagic($iOfferer);
+
+        if(getParam($CNF['PARAM_USE_IIN']) == 'on')
+            sendMailTemplate($CNF['ETEMPLATE_OFFER_CANCELED'], 0, (int)$aContentInfo[$CNF['FIELD_AUTHOR']], array(
+                'offerer_name' => $oOfferer->getDisplayName(),
+                'offerer_url' => $oOfferer->getUrl(),
+                'entry_name' => $aContentInfo[$CNF['FIELD_TITLE']],
+                'entry_url' => BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink('page.php', array(
+                    'i' => $CNF['URI_VIEW_ENTRY'], 
+                    $CNF['FIELD_ID'] => $iContentId
+                ))
+            ));
+
+        $aParams = $this->_alertParamsOffer($aContentInfo, $aOfferInfo);
+        bx_alert($this->getName(), 'offer_canceled', $iOfferId, $aOfferInfo[$CNF['FIELD_OFR_AUTHOR']], $aParams);
+    }
+
+    /**
+     * Common methods.
+     */
+    public function onShipped($mixedContent, $iProfileSrc = 0, $iProfileDst = 0)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        if(!is_array($mixedContent))
+            $mixedContent = $this->_oDb->getContentInfoById((int)$mixedContent);
+        $iContentId = (int)$mixedContent[$CNF['FIELD_ID']];
+
+        if(empty($iProfileSrc))
+            $iProfileSrc = (int)$mixedContent[$CNF['FIELD_AUTHOR']];
+
+        $oProfileSrc = BxDolProfile::getInstanceMagic($iProfileSrc);
+
+        $aOffer = $this->_oDb->getOffersBy(array('type' => 'accepted', 'content_id' => $iContentId));
+        $bOffer = !empty($aOffer) && is_array($aOffer);
+
+        if(empty($iProfileDst) && $bOffer)
+            $iProfileDst = (int)$aOffer[$CNF['FIELD_OFR_AUTHOR']];        
+
+        if(!empty($oProfileSrc) && !empty($iProfileDst) && getParam($CNF['PARAM_USE_IIN']) == 'on')
+            sendMailTemplate($CNF['ETEMPLATE_SHIPPED'], 0, $iProfileDst, array(
+                'vendor_name' => $oProfileSrc->getDisplayName(),
+                'vendor_url' => $oProfileSrc->getUrl(),
+                'entry_name' => $mixedContent[$CNF['FIELD_TITLE']],
+                'entry_url' => BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink('page.php', array(
+                    'i' => $CNF['URI_VIEW_ENTRY'], 
+                    $CNF['FIELD_ID'] => $iContentId
+                ))
+            ));
+
+        $aParams = $this->_alertParams($mixedContent);
+        $aParams = array_merge($aParams, array(
+            'profile_src' => $iProfileSrc,
+            'profile_dst' => $iProfileDst,
+            'offer_id' => $bOffer ? (int)$aOffer[$CNF['FIELD_OFR_ID']] : 0,
+        ));
+
+        bx_alert($this->getName(), 'shipped', $iContentId, false, $aParams);
+    }
+
+    public function onReceived($mixedContent, $iProfileSrc = 0, $iProfileDst = 0)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        if(!is_array($mixedContent))
+            $mixedContent = $this->_oDb->getContentInfoById((int)$mixedContent);
+        $iContentId = (int)$mixedContent[$CNF['FIELD_ID']];
+
+        if(empty($iProfileDst))
+            $iProfileDst = (int)$mixedContent[$CNF['FIELD_AUTHOR']];
+
+        $aOffer = $this->_oDb->getOffersBy(array('type' => 'accepted', 'content_id' => $iContentId));
+        $bOffer = !empty($aOffer) && is_array($aOffer);
+
+        if(empty($iProfileSrc) && $bOffer)
+            $iProfileSrc = (int)$aOffer[$CNF['FIELD_OFR_AUTHOR']];
+        $oProfileSrc = BxDolProfile::getInstanceMagic($iProfileSrc);
+
+        if(!empty($iProfileSrc) && !empty($iProfileDst) && getParam($CNF['PARAM_USE_IIN']) == 'on')
+            sendMailTemplate($CNF['ETEMPLATE_RECEIVED'], 0, $iProfileDst, array(
+                'client_name' => $oProfileSrc->getDisplayName(),
+                'client_url' => $oProfileSrc->getUrl(),
+                'entry_name' => $mixedContent[$CNF['FIELD_TITLE']],
+                'entry_url' => BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink('page.php', array(
+                    'i' => $CNF['URI_VIEW_ENTRY'], 
+                    $CNF['FIELD_ID'] => $iContentId
+                ))
+            ));
+
+        $aParams = $this->_alertParams($mixedContent);
+        $aParams = array_merge($aParams, array(
+            'profile_src' => $iProfileSrc,
+            'profile_dst' => $iProfileDst,
+            'offer_id' => $bOffer ? (int)$aOffer[$CNF['FIELD_OFR_ID']] : 0,
+        ));
+
+        bx_alert($this->getName(), 'received', $iContentId, false, $aParams);
+    }
+
+    public function offerAccept($iId) 
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        if(!$this->_oDb->updateOffer(array($CNF['FIELD_OFR_STATUS'] => BX_ADS_OFFER_STATUS_ACCEPTED), array($CNF['FIELD_OFR_ID'] => $iId)))
+            return false;
+    
+        $this->onOfferAccepted($iId);
+        return true;        
+    }
+
+    public function offerDecline($iId) 
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        if(!$this->_oDb->updateOffer(array($CNF['FIELD_OFR_STATUS'] => BX_ADS_OFFER_STATUS_DECLINED), array($CNF['FIELD_OFR_ID'] => $iId)))
+            return false;
+    
+        $this->onOfferDeclined($iId);
+        return true;        
+    }
+
+    public function offerCancel($iId)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        if(!$this->_oDb->updateOffer(array($CNF['FIELD_OFR_STATUS'] => BX_ADS_OFFER_STATUS_CANCELED), array($CNF['FIELD_OFR_ID'] => $iId)))
+            return false;
+
+        $this->onOfferCanceled($iId);
+        return true;
+    }
+    
+    public function offerPay($iId)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $aOffer = $this->_oDb->getOffersBy(array('type' => 'id', 'id' => $iId));
+        if(empty($aOffer) || !is_array($aOffer))
+            return false;
+
+        $iContent = (int)$aOffer[$CNF['FIELD_OFR_CONTENT']];
+        $aContent = $this->_oDb->getContentInfoById($iContent);
+        $iContentAuthor = (int)$aContent[$CNF['FIELD_AUTHOR']];
+
+        $aReturn = array(
+            'redirect' => BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink('page.php', array(
+                'i' => $CNF['URI_VIEW_ENTRY'], 
+                $CNF['FIELD_ID'] => $aOffer[$CNF['FIELD_OFR_CONTENT']]
+            ))
+        );
+
+        $oPayments = BxDolPayments::getInstance();
+        $aResult = $oPayments->addToCart($iContentAuthor, $this->getName(), $iContent, $aOffer[$CNF['FIELD_OFR_QUANTITY']]);
+        if(!empty($aResult) && is_array($aResult)) {
+            if(!empty($aResult['message']))
+                $aReturn['msg'] = $aResult['message'];
+
+            if(isset($aResult['code']) && (int)$aResult['code'] == 0)
+                $aReturn['redirect'] = $oPayments->getCartUrl($iContentAuthor);
+        }
+
+        return $aReturn;
+    }
+
+    public function processMetasAdd($iContentId)
+    {
+        if(!parent::processMetasAdd($iContentId))
+            return false;
+
+        $CNF = &$this->_oConfig->CNF;
+
+        $oMetatags = BxDolMetatags::getObjectInstance($CNF['OBJECT_METATAGS']);
+        $aContentInfo = $this->_oDb->getContentInfoById($iContentId);
+
+        $aCategoryTypes = $this->_oDb->getCategoryTypes(array('type' => 'all'));
+        foreach($aCategoryTypes as $aCategoryType)
+            $oMetatags->metaAddAuto($iContentId, $aContentInfo, $CNF, $aCategoryType['display_add']);
+
+        return true;
+    }
+
+    public function processMetasEdit($iContentId, $oForm)
+    {
+        if(!parent::processMetasEdit($iContentId, $oForm))
+            return false;
+        
+        $CNF = &$this->_oConfig->CNF;
+
+        $oMetatags = BxDolMetatags::getObjectInstance($CNF['OBJECT_METATAGS']);
+        $aContentInfo = $this->_oDb->getContentInfoById($iContentId);
+        
+        $aCategoryTypes = $this->_oDb->getCategoryTypes(array('type' => 'all'));
+        foreach($aCategoryTypes as $aCategoryType)
+            $oMetatags->metaAddAuto($iContentId, $aContentInfo, $CNF, $aCategoryType['display_edit']);
+
+        return true;
+    }
+
+    public function getCategoryDisplay($sDisplayType, $iCategory = 0)
+    {
+        if(empty($iCategory) && bx_get('category') !== false)
+            $iCategory = (int)bx_get('category');
+
+        if(empty($iCategory))
+            return false;
+
+        $aCategory = $this->_oDb->getCategories(array('type' => 'id_full', 'id' => $iCategory));
+
+        $sKey = 'type_display_' . $sDisplayType;
+        if(empty($aCategory[$sKey]))
+            return false;
+
+        return $aCategory[$sKey];
+    }
+
+
+    /**
+     * Internal methods.
+     */
+    protected function _actionMarkAs($sAction)
+    {
+        $iContentId = bx_process_input(bx_get('id'), BX_DATA_INT);
+
+        if(($mixedResult = $this->serviceMarkAs($sAction, $iContentId)) !== true)
+            return array('msg' => $mixedResult); 
+
+        return array(
+            'reload' => 1
+        );
+    }
+
+    protected function _actionChangeStatus($sStatus)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $iContentId = bx_process_input(bx_get('id'), BX_DATA_INT);
+        $aContentInfo = $this->_oDb->getContentInfoById($iContentId);
+
+        if(($mixedResult = $this->checkAllowedEdit($aContentInfo)) !== CHECK_ACTION_RESULT_ALLOWED)
+            return array('msg' => $mixedResult);
+
+        if(!$this->_oDb->updateEntriesBy(array($CNF['FIELD_STATUS'] => $sStatus), array($CNF['FIELD_ID'] => $iContentId)))
+            return array('msg' => _t('_bx_ads_txt_err_cannot_perform_action'));
+
+        $this->serviceUpdateCategoriesStats($aContentInfo);
+
+        return array(
+            'reload' => 1
+        );
+    }
+
+    protected function _serviceEntityForm ($sFormMethod, $iContentId = 0, $sDisplay = false, $sCheckFunction = false, $bErrorMsg = true)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $mixedContent = $this->_getContent($iContentId, true);
+        if($mixedContent === false)
+            return false;
+
+        list($iContentId, $aContentInfo) = $mixedContent;
+
+        $sDisplayType = false;
+        switch($sFormMethod) {
+            case 'editDataForm':
+                $sDisplayType = 'edit';
+                break;
+            case 'viewDataForm':
+            case 'viewDataEntry':
+                $sDisplayType = 'view';
+                break;
+        }
+
+        if($sDisplayType !== false && ($sDisplayNew = $this->getCategoryDisplay($sDisplayType, $aContentInfo[$CNF['FIELD_CATEGORY']])) !== false)
+            $sDisplay = $sDisplayNew;
+
+        return parent::_serviceEntityForm ($sFormMethod, $iContentId, $sDisplay, $sCheckFunction, $bErrorMsg);
+    }
+
+    protected function _getCategoryOptions($iParentId, &$aValues)
+    {
+        $aCategories = $this->_oDb->getCategories(array('type' => 'parent_id', 'parent_id' => $iParentId, 'active' => true));
+        foreach($aCategories as $aCategory) {
+            $aValues[] = array('key' => $aCategory['id'], 'value' => str_repeat('--', (int)$aCategory['level']) . ' ' . _t($aCategory['title']));
+
+            $this->_getCategoryOptions($aCategory['id'], $aValues);
+        }
+    }
+
+    protected function _getSearchableFields($mixedDisplayType = '')
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        if(empty($mixedDisplayType))
+            $mixedDisplayType = array('add', 'edit');
+
+        $aResult = array();
+        $aDisplays = $this->_oDb->getDisplays($this->_oConfig->getName() . '_entry', $mixedDisplayType);
+        foreach($aDisplays as $aDisplay) {
+            if($aDisplay['display_name'] == $CNF['OBJECT_FORM_ENTRY_DISPLAY_ADD'])
+                continue;
+
+            $oForm = BxDolForm::getObjectInstance($CNF['OBJECT_FORM_ENTRY'], $aDisplay['display_name'], $this->_oTemplate);
+            if(!$oForm)
+                continue;
+
+            $aResult = array_merge($aResult, $oForm->aInputs);
+        }
+
+        return $aResult;
+    }
+    
+    protected function _getContentForTimelinePost($aEvent, $aContentInfo, $aBrowseParams = array())
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $bDynamic = isset($aBrowseParams['dynamic_mode']) && (bool)$aBrowseParams['dynamic_mode'] === true;
+
+        $sCategory = '';
+        if(!empty($CNF['FIELD_CATEGORY']) && !empty($aContentInfo[$CNF['FIELD_CATEGORY']])) {
+            $iCategory = (int)$aContentInfo[$CNF['FIELD_CATEGORY']];
+            $aCategory = $this->_oDb->getCategories(array('type' => 'id', 'id' => $iCategory));
+            $sCategory = _t($aCategory['title']);
+            $sCategoryLink = BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink($CNF['URL_CATEGORIES'], array($CNF['GET_PARAM_CATEGORY'] => $iCategory));
+        }
+
+        $sPrice = _t('_bx_ads_txt_free');
+        if(!empty($CNF['FIELD_PRICE']) && !empty($aContentInfo[$CNF['FIELD_PRICE']]))
+            $sPrice = _t_format_currency((float)$aContentInfo[$CNF['FIELD_PRICE']]);
+
+        $sInclude = $this->_oTemplate->addCss(array('timeline.css'), $bDynamic);
+
+        $aResult = parent::_getContentForTimelinePost($aEvent, $aContentInfo, $aBrowseParams);
+        $aResult['text'] = $this->_oTemplate->parseHtmlByName('timeline_post_text.html', array(
+            'category_link' => $sCategoryLink,
+            'category_title' => $sCategory,
+            'category_title_attr' => bx_html_attribute($sCategory),
+            'price' => $sPrice,
+            'text' => $aResult['text']
+        )) . ($bDynamic ? $sInclude : '');
+
+        
+        return $aResult;
+    }
+
+    protected function _getBlockLicenses($sType = '') 
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $sGrid = $CNF['OBJECT_GRID_LICENSES' . (!empty($sType) ? '_' . strtoupper($sType) : '')];
+        $oGrid = BxDolGrid::getObjectInstance($sGrid);
+        if(!$oGrid)
+            return '';
+
+        $this->_oDb->updateLicense(array('new' => 0), array('profile_id' => bx_get_logged_profile_id(), 'new' => 1));
+
+        $this->_oTemplate->addJs(array('licenses.js'));
+        return array(
+            'content' => $this->_oTemplate->getJsCode('licenses', array('sObjNameGrid' => $sGrid)) . $oGrid->getCode(),
+            'menu' => $CNF['OBJECT_MENU_LICENSES']
+        );
+    }
+
+    protected function _alertParamsOffer($aContentInfo, $aOfferInfo)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $aParams = array(
+            'object_id' => (int)$aContentInfo[$CNF['FIELD_ID']],
+            'object_author_id' => (int)$aContentInfo[$CNF['FIELD_AUTHOR']],
+
+            'offer_id' => (int)$aOfferInfo[$CNF['FIELD_OFR_ID']],
+            'offer_author_id' => (int)$aOfferInfo[$CNF['FIELD_OFR_AUTHOR']],
+        );
+        if(isset($aContentInfo[$CNF['FIELD_ALLOW_VIEW_TO']]))
+            $aParams['privacy_view'] = $aContentInfo[$CNF['FIELD_ALLOW_VIEW_TO']];
+
+        return $aParams;
+    }
+}
+
+/** @} */

+ 151 - 0
modules/boonex/ads/updates/13.0.2_13.0.3/source/install/config.php

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

+ 586 - 0
modules/boonex/ads/updates/13.0.2_13.0.3/source/install/langs/en.xml

@@ -0,0 +1,586 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources name="en" flag="gb" title="English">
+    <string name="_bx_ads"><![CDATA[Ads]]></string>
+    <string name="_bx_ads_cmts"><![CDATA[Ads' Comments]]></string>
+    <string name="_bx_ads_reactions"><![CDATA[Ads' Reactions]]></string>
+
+    <string name="_bx_ads_option_enable_auto_approve"><![CDATA[Auto approve an ad after creation]]></string>
+    <string name="_bx_ads_option_summary_chars"><![CDATA[Number of characters in auto-cropped ad summary]]></string>
+    <string name="_bx_ads_option_plain_summary_chars"><![CDATA[Number of characters in plain ad description when ad hasn't thumb]]></string>
+    <string name="_bx_ads_option_per_page_browse"><![CDATA[Number of items per page]]></string>
+    <string name="_bx_ads_option_per_page_profile"><![CDATA[Number of items on profile/group page]]></string>
+    <string name="_bx_ads_option_rss_num"><![CDATA[Number of items in RSS feed]]></string>
+    <string name="_bx_ads_option_searchable_fields"><![CDATA[Searchable fields for keyword search]]></string>
+    <string name="_bx_ads_option_lifetime"><![CDATA[Deactivate automatically after (in days)]]></string>
+    <string name="_bx_ads_option_offer_lifetime"><![CDATA[Decline offers automatically after (in hours)]]></string>
+    <string name="_bx_ads_option_internal_interested_notification"><![CDATA[Use internal notification about Interested action]]></string>
+    <string name="_bx_ads_option_enable_auction"><![CDATA[Enable Auction mode]]></string>
+
+    <string name="_bx_ads_form_category"><![CDATA[Category]]></string>
+    <string name="_bx_ads_form_category_display_add"><![CDATA[Add Category]]></string>
+    <string name="_bx_ads_form_category_display_edit"><![CDATA[Edit Category]]></string>
+    <string name="_bx_ads_form_category_display_delete"><![CDATA[Delete Category]]></string>
+    <string name="_bx_ads_form_category_input_sys_do_submit"><![CDATA[Submit]]></string>
+    <string name="_bx_ads_form_category_input_do_submit"><![CDATA[Submit]]></string>
+    <string name="_bx_ads_form_category_input_sys_do_cancel"><![CDATA[Cancel]]></string>
+    <string name="_bx_ads_form_category_input_do_cancel"><![CDATA[Cancel]]></string>
+    <string name="_bx_ads_form_category_input_sys_parent_id"><![CDATA[Parent]]></string>
+    <string name="_bx_ads_form_category_input_parent_id"><![CDATA[Parent category]]></string>
+    <string name="_bx_ads_form_category_input_parent_id_empty"><![CDATA[No parent]]></string>
+    <string name="_bx_ads_form_category_input_sys_title"><![CDATA[Title]]></string>
+    <string name="_bx_ads_form_category_input_title"><![CDATA[Title]]></string>
+    <string name="_bx_ads_form_category_input_title_err"><![CDATA[Title is essential. Please, fill in this field.]]></string>
+    <string name="_bx_ads_form_category_input_sys_text"><![CDATA[Text]]></string>
+    <string name="_bx_ads_form_category_input_text"><![CDATA[Text]]></string>
+    <string name="_bx_ads_form_category_input_sys_type"><![CDATA[Type]]></string>
+    <string name="_bx_ads_form_category_input_type"><![CDATA[Type]]></string>
+    <string name="_bx_ads_form_category_input_type_err"><![CDATA[Type is essential. Please, select a value for this field.]]></string>
+    <string name="_bx_ads_form_category_input_type_info"><![CDATA[Type determines a set of fields for entries in this category.]]></string>
+    <string name="_bx_ads_form_category_input_sys_type_clone"><![CDATA[Clone type]]></string>
+    <string name="_bx_ads_form_category_input_type_clone"><![CDATA[Clone type]]></string>
+    <string name="_bx_ads_form_category_input_sys_type_title"><![CDATA[Type title]]></string>
+    <string name="_bx_ads_form_category_input_type_title"><![CDATA[Type title]]></string>
+    <string name="_bx_ads_form_category_input_sys_icon"><![CDATA[Icon]]></string>
+    <string name="_bx_ads_form_category_input_icon"><![CDATA[Icon]]></string>
+    <string name="_bx_ads_form_category_input_sys_delete_confirm"><![CDATA[Delete confirmation]]></string>
+    <string name="_bx_ads_form_category_input_delete_confirm"><![CDATA[I am sure I want to delete this category]]></string>
+    <string name="_bx_ads_form_category_input_delete_confirm_info"><![CDATA[This action can not be undone]]></string>
+    <string name="_bx_ads_form_category_input_delete_confirm_error"><![CDATA[Please check this checkbox if you really want to delete the category]]></string>
+
+    <string name="_bx_ads_form_entry"><![CDATA[Ads]]></string>
+    <string name="_bx_ads_form_entry_display_add"><![CDATA[Add Ad]]></string>
+    <string name="_bx_ads_form_entry_display_delete"><![CDATA[Delete Ad]]></string>
+
+    <string name="_bx_ads_form_entry_price_display_add"><![CDATA[With Price: Add]]></string>
+    <string name="_bx_ads_form_entry_price_display_edit"><![CDATA[With Price: Edit]]></string>
+    <string name="_bx_ads_form_entry_price_display_view"><![CDATA[With Price: View]]></string>
+
+    <string name="_bx_ads_form_entry_price_year_display_add"><![CDATA[With Price and Year: Add]]></string>
+    <string name="_bx_ads_form_entry_price_year_display_edit"><![CDATA[With Price and Year: Edit]]></string>
+    <string name="_bx_ads_form_entry_price_year_display_view"><![CDATA[With Price and Year: View]]></string>
+
+    <string name="_bx_ads_form_entry_input_author"><![CDATA[Author]]></string>
+    <string name="_bx_ads_form_entry_input_sys_do_submit"><![CDATA[Submit]]></string>
+    <string name="_bx_ads_form_entry_input_do_submit"><![CDATA[Submit]]></string>
+    <string name="_bx_ads_form_entry_input_sys_title"><![CDATA[Title]]></string>
+    <string name="_bx_ads_form_entry_input_title"><![CDATA[Title]]></string>
+    <string name="_bx_ads_form_entry_input_title_err"><![CDATA[Title is essential. Please, fill in this field]]></string>
+    <string name="_bx_ads_form_entry_input_sys_name"><![CDATA[Name]]></string>
+    <string name="_bx_ads_form_entry_input_name"><![CDATA[Name]]></string>
+    <string name="_bx_ads_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_ads_form_entry_input_sys_price"><![CDATA[Price]]></string>
+    <string name="_bx_ads_form_entry_input_price"><![CDATA[Price]]></string>
+    <string name="_bx_ads_form_entry_input_sys_auction"><![CDATA[Auction]]></string>
+    <string name="_bx_ads_form_entry_input_auction"><![CDATA[Use auction]]></string>
+    <string name="_bx_ads_form_entry_input_auction_info"><![CDATA[Allow buyers not only to pay a defined price but to make offers too.]]></string>
+    <string name="_bx_ads_form_entry_input_sys_quantity"><![CDATA[Quantity]]></string>
+    <string name="_bx_ads_form_entry_input_quantity"><![CDATA[Quantity]]></string>
+    <string name="_bx_ads_form_entry_input_quantity_err"><![CDATA[Quantity is essential. Please, fill in this field]]></string>
+    <string name="_bx_ads_form_entry_input_sys_year"><![CDATA[Year]]></string>
+    <string name="_bx_ads_form_entry_input_year"><![CDATA[Year]]></string>
+    <string name="_bx_ads_form_entry_input_sys_category"><![CDATA[Category]]></string>
+    <string name="_bx_ads_form_entry_input_sys_category_view"><![CDATA[Category]]></string>
+    <string name="_bx_ads_form_entry_input_category_view"><![CDATA[Category]]></string>
+    <string name="_bx_ads_form_entry_input_sys_category_select"><![CDATA[Category]]></string>
+    <string name="_bx_ads_form_entry_input_category_select"><![CDATA[Category]]></string>
+    <string name="_bx_ads_form_entry_input_sys_text"><![CDATA[Text]]></string>
+    <string name="_bx_ads_form_entry_input_text"><![CDATA[Text]]></string>
+    <string name="_bx_ads_form_entry_input_text_err"><![CDATA[Text field can't be empty]]></string>
+    <string name="_bx_ads_form_entry_input_sys_notes_purchased"><![CDATA[After purchase notes]]></string>
+    <string name="_bx_ads_form_entry_input_notes_purchased"><![CDATA[After purchase notes]]></string>
+    <string name="_bx_ads_form_entry_input_notes_purchased_inf"><![CDATA[Will be attached to email message which is sent to buyer after purchase.]]></string>
+    <string name="_bx_ads_form_entry_input_sys_delete_confirm"><![CDATA[Delete confirmation]]></string>
+    <string name="_bx_ads_form_entry_input_delete_confirm"><![CDATA[I am sure I want to delete this ad]]></string>
+    <string name="_bx_ads_form_entry_input_delete_confirm_info"><![CDATA[This action can not be undone]]></string>
+    <string name="_bx_ads_form_entry_input_delete_confirm_error"><![CDATA[Please check this checkbox if you really want to delete the ad]]></string>
+    <string name="_bx_ads_form_entry_input_sys_covers"><![CDATA[Header Image]]></string>
+    <string name="_bx_ads_form_entry_input_covers"><![CDATA[Header Image]]></string>
+    <string name="_bx_ads_form_entry_input_covers_uploader_simple_title"><![CDATA[Upload]]></string>
+    <string name="_bx_ads_form_entry_input_covers_uploader_html5_title"><![CDATA[Upload]]></string>
+    <string name="_bx_ads_form_entry_input_sys_pictures"><![CDATA[Images]]></string>
+    <string name="_bx_ads_form_entry_input_pictures"><![CDATA[]]></string>
+    <string name="_bx_ads_form_entry_input_sys_videos"><![CDATA[Videos]]></string>
+    <string name="_bx_ads_form_entry_input_videos"><![CDATA[]]></string>
+    <string name="_bx_ads_form_entry_input_sys_files"><![CDATA[Files]]></string>
+    <string name="_bx_ads_form_entry_input_files"><![CDATA[]]></string>
+    <string name="_bx_ads_form_entry_input_sys_polls"><![CDATA[Polls]]></string>
+    <string name="_bx_ads_form_entry_input_sys_allow_view_to"><![CDATA[Visibility]]></string>
+    <string name="_bx_ads_form_entry_input_allow_view_to"><![CDATA[Visibility]]></string>
+    <string name="_bx_ads_form_entry_input_sys_date_added"><![CDATA[Created]]></string>
+    <string name="_bx_ads_form_entry_input_date_added"><![CDATA[Created]]></string>
+    <string name="_bx_ads_form_entry_input_sys_date_changed"><![CDATA[Updated]]></string>
+    <string name="_bx_ads_form_entry_input_date_changed"><![CDATA[Updated]]></string>
+    <string name="_bx_ads_form_entry_input_sys_attachments"><![CDATA[Attachments]]></string>
+
+    <string name="_bx_ads_form_poll"><![CDATA[Polls]]></string>
+    <string name="_bx_ads_form_poll_display_add"><![CDATA[Add Poll]]></string>
+    <string name="_bx_ads_form_poll_input_sys_text"><![CDATA[Question]]></string>
+    <string name="_bx_ads_form_poll_input_text"><![CDATA[Question]]></string>
+    <string name="_bx_ads_form_poll_input_text_err"><![CDATA[Question is essential. Please, fill in this field]]></string>
+    <string name="_bx_ads_form_poll_input_sys_answers"><![CDATA[Answers]]></string>
+    <string name="_bx_ads_form_poll_input_answers"><![CDATA[Answers]]></string>
+    <string name="_bx_ads_form_poll_input_answers_err"><![CDATA[Poll should have at least 2 non-empty answers.]]></string>
+    <string name="_bx_ads_form_poll_input_answers_add"><![CDATA[Add More]]></string>
+    <string name="_bx_ads_form_poll_input_sys_do_submit"><![CDATA[Add]]></string>
+    <string name="_bx_ads_form_poll_input_do_submit"><![CDATA[Add]]></string>
+    <string name="_bx_ads_form_poll_input_do_cancel"><![CDATA[Close]]></string>
+    
+    <string name="_bx_ads_form_offer"><![CDATA[Offer]]></string>
+    <string name="_bx_ads_form_offer_display_add"><![CDATA[Add Offer]]></string>
+    <string name="_bx_ads_form_offer_display_view"><![CDATA[View Offer]]></string>
+    <string name="_bx_ads_form_offer_input_sys_amount"><![CDATA[Amount]]></string>
+    <string name="_bx_ads_form_offer_input_amount"><![CDATA[Amount]]></string>
+    <string name="_bx_ads_form_offer_input_amount_err"><![CDATA[Amount is essential. Please, fill in this field.]]></string>
+    <string name="_bx_ads_form_offer_input_sys_quantity"><![CDATA[Quantity]]></string>
+    <string name="_bx_ads_form_offer_input_quantity"><![CDATA[Quantity]]></string>
+    <string name="_bx_ads_form_offer_input_quantity_err"><![CDATA[Quantity is essential. Please, fill in this field.]]></string>
+    <string name="_bx_ads_form_offer_input_sys_message"><![CDATA[Message]]></string>
+    <string name="_bx_ads_form_offer_input_message"><![CDATA[Message]]></string>
+    <string name="_bx_ads_form_offer_input_sys_do_submit"><![CDATA[Add]]></string>
+    <string name="_bx_ads_form_offer_input_do_submit"><![CDATA[Add]]></string>
+    <string name="_bx_ads_form_offer_input_sys_do_cancel"><![CDATA[Add]]></string>
+    <string name="_bx_ads_form_offer_input_do_cancel"><![CDATA[Close]]></string>
+
+    <string name="_bx_ads_acl_action_create_entry"><![CDATA[Create Ad]]></string>
+    <string name="_bx_ads_acl_action_delete_entry"><![CDATA[Delete Ad]]></string>
+    <string name="_bx_ads_acl_action_view_entry"><![CDATA[View Ad]]></string>
+    <string name="_bx_ads_acl_action_set_thumb"><![CDATA[Set Ad Header Image]]></string>
+    <string name="_bx_ads_acl_action_edit_any_entry"><![CDATA[Edit Any Ad]]></string>
+    <string name="_bx_ads_acl_action_delete_any_entry"><![CDATA[Delete Any Ad]]></string>
+    <string name="_bx_ads_acl_action_make_offer"><![CDATA[Make Offer]]></string>
+
+    <string name="_bx_ads_page_title_sys_create_entry"><![CDATA[New Ad]]></string>
+    <string name="_bx_ads_page_title_create_entry"><![CDATA[New Ad]]></string>
+    <string name="_bx_ads_page_block_title_create_entry"><![CDATA[New Ad]]></string>
+    <string name="_bx_ads_page_title_sys_edit_entry"><![CDATA[Edit]]></string>
+    <string name="_bx_ads_page_title_edit_entry"><![CDATA[Edit]]></string>
+    <string name="_bx_ads_page_block_title_edit_entry"><![CDATA[Edit]]></string>
+    <string name="_bx_ads_page_title_sys_delete_entry"><![CDATA[Delete]]></string>
+    <string name="_bx_ads_page_title_delete_entry"><![CDATA[Delete]]></string>
+    <string name="_bx_ads_page_block_title_delete_entry"><![CDATA[Delete]]></string>
+    <string name="_bx_ads_page_title_sys_view_entry"><![CDATA[View Ad]]></string>
+    <string name="_bx_ads_page_title_view_entry"><![CDATA[{title}]]></string>
+    <string name="_bx_ads_page_block_title_entry_breadcrumb"><![CDATA[Breadcrumb]]></string>
+    <string name="_bx_ads_page_block_title_entry_text"><![CDATA[Ad Text]]></string>
+    <string name="_bx_ads_page_title_browse"><![CDATA[Ads]]></string>
+    <string name="_bx_ads_page_title_search_results"><![CDATA[Ads matching "{0}"]]></string>
+    <string name="_bx_ads_page_title_browse_by_author"><![CDATA[Ads of {display_name}]]></string>
+    <string name="_bx_ads_page_title_browse_by_context"><![CDATA[Ads in {display_name}]]></string>
+    <string name="_bx_ads_page_title_browse_featured"><![CDATA[Featured Ads]]></string>
+    <string name="_bx_ads_page_title_browse_recent"><![CDATA[Latest Ads]]></string>
+    <string name="_bx_ads_page_title_browse_popular"><![CDATA[Popular Ads]]></string>
+    <string name="_bx_ads_page_title_browse_updated"><![CDATA[Updated Ads]]></string>
+    <string name="_bx_ads_page_title_browse_category"><![CDATA[Ads in {display_name}]]]]></string>
+    <string name="_bx_ads_page_title_sys_home"><![CDATA[Ads Home]]></string>
+    <string name="_bx_ads_page_title_home"><![CDATA[Ads]]></string>
+    <string name="_bx_ads_page_block_title_featured_entries_view_extended"><![CDATA[Featured Ads]]></string>
+    <string name="_bx_ads_page_block_title_recent_entries"><![CDATA[Latest Ads (Gallery View)]]></string>
+    <string name="_bx_ads_page_block_title_recent_entries_view_extended"><![CDATA[Latest Ads]]></string>
+    <string name="_bx_ads_page_block_title_recent_entries_view_full"><![CDATA[Latest Ads (Full View)]]></string>
+    <string name="_bx_ads_page_block_title_entry_social_sharing"><![CDATA[Share]]></string>
+    <string name="_bx_ads_page_block_title_entry_author"><![CDATA[Author]]></string>
+    <string name="_bx_ads_page_block_title_entry_actions"><![CDATA[Actions]]></string>
+    <string name="_bx_ads_page_block_title_entry_comments"><![CDATA[Comments]]></string>
+	<string name="_bx_ads_page_block_title_entry_reports"><![CDATA[Reports]]></string>
+    <string name="_bx_ads_page_block_title_entry_comments_link"><![CDATA[Comments to <a href="{entry_link}">{title}</a>]]></string>
+    <string name="_bx_ads_page_block_title_entry_reviews"><![CDATA[Reviews]]></string>
+    <string name="_bx_ads_page_block_title_entry_reviews_link"><![CDATA[Reviews to <a href="{entry_link}">{title}</a>]]></string>
+    <string name="_bx_ads_page_block_title_entry_reviews_rating"><![CDATA[Rating]]></string>
+    <string name="_bx_ads_page_block_title_entry_location"><![CDATA[Location]]></string>
+    <string name="_bx_ads_page_block_title_entry_attachments"><![CDATA[Attachments]]></string>
+    <string name="_bx_ads_page_block_title_entry_polls"><![CDATA[Polls]]></string>
+    <string name="_bx_ads_page_block_title_entry_all_actions"><![CDATA[All Actions]]></string>
+    <string name="_bx_ads_page_title_sys_entries_popular"><![CDATA[Popular Ads]]></string>
+    <string name="_bx_ads_page_title_entries_popular"><![CDATA[Popular Ads]]></string>
+    <string name="_bx_ads_page_title_sys_entries_updated"><![CDATA[Updated Ads]]></string>
+    <string name="_bx_ads_page_title_entries_updated"><![CDATA[Updated Ads]]></string>
+    <string name="_bx_ads_page_title_sys_entries_search"><![CDATA[Search]]></string>
+    <string name="_bx_ads_page_title_entries_search"><![CDATA[Search]]></string>
+    <string name="_bx_ads_page_block_title_search_form"><![CDATA[Search Form]]></string>
+    <string name="_bx_ads_page_block_title_search_results"><![CDATA[Search Results]]></string>
+    <string name="_bx_ads_page_block_title_search_form_cmts"><![CDATA[Comments Search Form]]></string>
+    <string name="_bx_ads_page_block_title_search_results_cmts"><![CDATA[Comments Search Results]]></string>
+    <string name="_bx_ads_page_block_title_popular_entries"><![CDATA[Popular Ads]]></string>
+    <string name="_bx_ads_page_block_title_popular_entries_view_extended"><![CDATA[Popular Ads (Extended View)]]></string>
+    <string name="_bx_ads_page_block_title_popular_entries_view_full"><![CDATA[Popular Ads (Full View)]]></string>
+    <string name="_bx_ads_page_block_title_updated_entries"><![CDATA[Updated Ads]]></string>
+    <string name="_bx_ads_page_title_sys_view_entry_comments"><![CDATA[Ad Comments]]></string>
+    <string name="_bx_ads_page_title_view_entry_comments"><![CDATA[Comments to {title}]]></string>
+    <string name="_bx_ads_page_title_sys_entries_of_author"><![CDATA[Ads of author]]></string>
+    <string name="_bx_ads_page_title_entries_of_author"><![CDATA[Ads by {display_name}]]></string>
+    <string name="_bx_ads_page_title_sys_entries_in_context"><![CDATA[Ads in context]]></string>
+    <string name="_bx_ads_page_title_entries_in_context"><![CDATA[Ads in {display_name}]]></string>
+    <string name="_bx_ads_page_block_title_favorites_of_author"><![CDATA[Favorites by <a href="{profile_link}">{display_name}</a>]]></string>
+    <string name="_bx_ads_page_block_title_sys_favorites_of_author"><![CDATA[Favorites of author]]></string>
+    <string name="_bx_ads_page_block_title_entries_of_author"><![CDATA[Ads by <a href="{profile_link}">{display_name}</a>]]></string>
+    <string name="_bx_ads_page_block_title_sys_entries_of_author"><![CDATA[Ads of author]]></string>
+    <string name="_bx_ads_page_block_title_entries_in_context"><![CDATA[Ads in <a href="{profile_link}">{display_name}</a>]]></string>
+    <string name="_bx_ads_page_block_title_sys_entries_in_context"><![CDATA[Ads in context]]></string>
+    <string name="_bx_ads_page_block_title_entries_actions"><![CDATA[Ads actions]]></string>
+    <string name="_bx_ads_page_block_title_browse_cmts"><![CDATA[Ads' Comments]]></string>
+    <string name="_bx_ads_page_title_sys_manage"><![CDATA[Manage Own]]></string>
+    <string name="_bx_ads_page_title_sys_manage_administration"><![CDATA[Manage All]]></string>
+    <string name="_bx_ads_page_title_manage"><![CDATA[Manage]]></string>
+    <string name="_bx_ads_page_block_title_system_manage"><![CDATA[Manage Own]]></string>
+    <string name="_bx_ads_page_block_title_system_manage_administration"><![CDATA[Manage All]]></string>
+    <string name="_bx_ads_page_block_title_manage"><![CDATA[Manage]]></string>    
+    <string name="_bx_ads_page_block_title_popular_keywords"><![CDATA[Popular Hashtags]]></string>
+    <string name="_bx_ads_page_block_title_categories"><![CDATA[Ads Categories]]></string>
+    <string name="_bx_ads_page_block_title_entry_info"><![CDATA[Info]]></string>
+    <string name="_bx_ads_page_block_title_sys_my_entries"><![CDATA[User Ads]]></string>
+    <string name="_bx_ads_page_block_title_my_entries"><![CDATA[{display_name} Ads]]></string>
+    <string name="_bx_ads_page_block_title_sys_recent_entries_view_showcase"><![CDATA[Latest Ads (Showcase View)]]></string>
+    <string name="_bx_ads_page_block_title_recent_entries_view_showcase"><![CDATA[Latest Ads]]></string>
+    <string name="_bx_ads_page_block_title_sys_popular_entries_view_showcase"><![CDATA[Popular Ads (Showcase View)]]></string>
+    <string name="_bx_ads_page_block_title_popular_entries_view_showcase"><![CDATA[Popular Ads]]></string>
+    <string name="_bx_ads_page_block_title_sys_featured_entries_view_showcase"><![CDATA[Featured Ads (Showcase View)]]></string>
+    <string name="_bx_ads_page_block_title_featured_entries_view_showcase"><![CDATA[Featured Ads]]></string>
+    <string name="_bx_ads_page_block_title_entry_offer_accepted"><![CDATA[Offer]]></string>
+    <string name="_bx_ads_page_block_title_sys_entry_context"><![CDATA[Posted in]]></string>
+    <string name="_bx_ads_page_block_title_entry_context"><![CDATA[Posted in]]></string>
+    <string name="_bx_ads_page_title_sys_entries_categories"><![CDATA[Ads Categories]]></string>
+    <string name="_bx_ads_page_title_entries_categories"><![CDATA[Ads Categories]]></string>
+    <string name="_bx_ads_page_block_title_entries_by_category"><![CDATA[Ads]]></string>
+    <string name="_bx_ads_page_block_title_entries_by_category_mask"><![CDATA[Ads in: {0}]]></string>
+    <string name="_bx_ads_page_title_sys_licenses_administration"><![CDATA[Licenses]]></string>
+    <string name="_bx_ads_page_title_licenses_administration"><![CDATA[Licenses]]></string>
+    <string name="_bx_ads_page_block_title_licenses_administration"><![CDATA[Licenses]]></string>
+    <string name="_bx_ads_page_title_sys_licenses"><![CDATA[Licenses]]></string>
+    <string name="_bx_ads_page_title_licenses"><![CDATA[Licenses]]></string>
+    <string name="_bx_ads_page_block_title_licenses"><![CDATA[Licenses]]></string>
+    <string name="_bx_ads_page_block_title_licenses_note"><![CDATA[Note]]></string>
+    <string name="_bx_ads_page_block_content_licenses_note"><![CDATA[The licenses are for reference only.]]></string>
+    <string name="_bx_ads_page_title_sys_offers"><![CDATA[Offers]]></string>
+    <string name="_bx_ads_page_title_offers"><![CDATA[Offers]]></string>
+    <string name="_bx_ads_page_block_title_offers"><![CDATA[Offers]]></string>
+    <string name="_bx_ads_page_title_sys_offers_all"><![CDATA[All Offers]]></string>
+    <string name="_bx_ads_page_title_offers_all"><![CDATA[All Offers]]></string>
+    <string name="_bx_ads_page_block_title_offers_all"><![CDATA[All Offers]]></string>
+
+    <string name="_bx_ads_menu_title_entry_attachments"><![CDATA[Form Attachments]]></string>
+    <string name="_bx_ads_menu_set_title_entry_attachments"><![CDATA[Form Attachments]]></string>
+    <string name="_bx_ads_menu_item_title_system_cpa_photo_simple"><![CDATA[Add Photo (simple)]]></string>
+    <string name="_bx_ads_menu_item_title_cpa_photo_simple"><![CDATA[Add Photo]]></string>
+    <string name="_bx_ads_menu_item_title_system_cpa_photo_html5"><![CDATA[Add Photo (html5)]]></string>
+    <string name="_bx_ads_menu_item_title_cpa_photo_html5"><![CDATA[Add Photos]]></string>
+    <string name="_bx_ads_menu_item_title_system_cpa_video_simple"><![CDATA[Add Video (simple)]]></string>
+    <string name="_bx_ads_menu_item_title_cpa_video_simple"><![CDATA[Add Video]]></string>
+    <string name="_bx_ads_menu_item_title_system_cpa_video_html5"><![CDATA[Add Video (html5)]]></string>
+    <string name="_bx_ads_menu_item_title_cpa_video_html5"><![CDATA[Add Videos]]></string>
+    <string name="_bx_ads_menu_item_title_system_cpa_video_record"><![CDATA[Record Video]]></string>
+    <string name="_bx_ads_menu_item_title_cpa_video_record"><![CDATA[Record Video]]></string>
+    <string name="_bx_ads_menu_item_title_system_cpa_file_simple"><![CDATA[Add File (simple)]]></string>
+    <string name="_bx_ads_menu_item_title_cpa_file_simple"><![CDATA[Add File]]></string>
+    <string name="_bx_ads_menu_item_title_system_cpa_file_html5"><![CDATA[Add File (html5)]]></string>
+    <string name="_bx_ads_menu_item_title_cpa_file_html5"><![CDATA[Add Files]]></string>
+    <string name="_bx_ads_menu_item_title_system_cpa_poll"><![CDATA[Add Poll]]></string>
+    <string name="_bx_ads_menu_item_title_cpa_poll"><![CDATA[Add Poll]]></string>
+
+    <string name="_bx_ads_menu_set_title_view_entry"><![CDATA[Ad Actions]]></string>
+    <string name="_bx_ads_menu_title_view_entry"><![CDATA[Ad Actions]]></string>
+    <string name="_bx_ads_menu_title_submenu"><![CDATA[Ads Submenu]]></string>
+    <string name="_bx_ads_menu_set_title_submenu"><![CDATA[Ads Submenu]]></string>
+    <string name="_bx_ads_menu_item_title_system_create_entry"><![CDATA[Ad]]></string>
+    <string name="_bx_ads_menu_item_title_create_entry"><![CDATA[Ad]]></string>
+    <string name="_bx_ads_menu_item_title_system_interested_entry"><![CDATA[Interested]]></string>
+    <string name="_bx_ads_menu_item_title_interested_entry"><![CDATA[I'm interested]]></string>
+    <string name="_bx_ads_menu_item_title_system_add_to_cart"><![CDATA[Add to Cart]]></string>
+    <string name="_bx_ads_menu_item_title_add_to_cart"><![CDATA[Buy for {0}{1}]]></string>
+    <string name="_bx_ads_menu_item_title_system_make_offer"><![CDATA[Make offer]]></string>
+    <string name="_bx_ads_menu_item_title_make_offer"><![CDATA[Make offer]]></string>
+    <string name="_bx_ads_menu_item_title_system_view_offers"><![CDATA[Оffers]]></string>
+    <string name="_bx_ads_menu_item_title_view_offers"><![CDATA[Оffers]]></string>
+    <string name="_bx_ads_menu_item_title_system_edit_entry"><![CDATA[Edit]]></string>
+    <string name="_bx_ads_menu_item_title_edit_entry"><![CDATA[Edit]]></string>
+    <string name="_bx_ads_menu_item_title_system_delete_entry"><![CDATA[Delete]]></string>
+    <string name="_bx_ads_menu_item_title_delete_entry"><![CDATA[Delete]]></string>
+    <string name="_bx_ads_menu_item_title_system_mark_shipped"><![CDATA[Shipped]]></string>
+    <string name="_bx_ads_menu_item_title_mark_shipped"><![CDATA[Shipped]]></string>
+    <string name="_bx_ads_menu_item_title_system_mark_received"><![CDATA[Received]]></string>
+    <string name="_bx_ads_menu_item_title_mark_received"><![CDATA[Received]]></string>
+    <string name="_bx_ads_menu_item_title_system_review_entry"><![CDATA[Review]]></string>
+    <string name="_bx_ads_menu_item_title_system_view_entry"><![CDATA[View Ad]]></string>
+    <string name="_bx_ads_menu_item_title_system_entries_home"><![CDATA[Ads]]></string>
+    <string name="_bx_ads_menu_item_title_entries_home"><![CDATA[Ads]]></string>
+    <string name="_bx_ads_menu_item_title_system_entries_public"><![CDATA[Latest]]></string>
+    <string name="_bx_ads_menu_item_title_entries_public"><![CDATA[Latest]]></string>
+    <string name="_bx_ads_menu_item_title_system_entries_manage"><![CDATA[Manage]]></string>
+    <string name="_bx_ads_menu_item_title_entries_manage"><![CDATA[Manage]]></string>
+    <string name="_bx_ads_menu_item_title_system_entries_popular"><![CDATA[Popular]]></string>
+    <string name="_bx_ads_menu_item_title_entries_popular"><![CDATA[Popular]]></string>
+    <string name="_bx_ads_menu_item_title_system_entries_search"><![CDATA[Search]]></string>
+    <string name="_bx_ads_menu_item_title_entries_search"><![CDATA[Search]]></string>
+    <string name="_bx_ads_menu_title_view_entry_submenu"><![CDATA[View Ad Submenu]]></string>
+    <string name="_bx_ads_menu_set_title_view_entry_submenu"><![CDATA[View Ad Submenu]]></string>
+    <string name="_bx_ads_menu_item_title_view_entry_submenu_entry"><![CDATA[Ad]]></string>
+    <string name="_bx_ads_menu_item_title_view_entry_submenu_comments"><![CDATA[Comments]]></string>
+    <string name="_bx_ads_menu_item_title_system_view_entry_comments"><![CDATA[Ad Comments]]></string>
+    <string name="_bx_ads_menu_item_title_system_view_entries_author"><![CDATA[Ads]]></string>
+    <string name="_bx_ads_menu_item_title_view_entries_author"><![CDATA[Ads]]></string>
+    <string name="_bx_ads_menu_item_title_system_view_entries_in_context"><![CDATA[Ads]]></string>
+    <string name="_bx_ads_menu_item_title_view_entries_in_context"><![CDATA[Ads]]></string>
+    <string name="_bx_ads_menu_title_entries_my"><![CDATA[My Ads Action Menu]]></string>
+    <string name="_bx_ads_menu_set_title_entries_my"><![CDATA[My Ads Menu]]></string>
+    <string name="_bx_ads_menu_item_title_system_manage_my_posts"><![CDATA[My ads]]></string>
+    <string name="_bx_ads_menu_item_title_manage_my_posts"><![CDATA[Ads]]></string>
+    <string name="_bx_ads_menu_set_title_manage_tools"><![CDATA[Manage Tools Submenu]]></string>
+    <string name="_bx_ads_menu_title_manage_tools"><![CDATA[Manage Tools Submenu]]></string>
+    <string name="_bx_ads_menu_item_title_system_manage_account"><![CDATA[Manage account]]></string>
+    <string name="_bx_ads_menu_item_title_manage_account"><![CDATA[Manage account]]></string>
+    <string name="_bx_ads_menu_item_title_system_admt_ads"><![CDATA[Ads]]></string>
+    <string name="_bx_ads_menu_item_title_admt_ads"><![CDATA[Ads]]></string>
+    <string name="_bx_ads_menu_item_title_manage_my"><![CDATA[My Ads]]></string>
+    <string name="_bx_ads_menu_item_title_manage_all"><![CDATA[All Ads]]></string>
+    <string name="_bx_ads_menu_item_title_categories"><![CDATA[Categories]]></string>
+    <string name="_bx_ads_menu_item_title_system_entries_categories"><![CDATA[Categories]]></string>
+    <string name="_bx_ads_menu_item_title_entries_categories"><![CDATA[Categories]]></string>
+    <string name="_bx_ads_menu_item_title_system_sm_price"><![CDATA[Price]]></string>
+    <string name="_bx_ads_menu_item_title_sm_price"><![CDATA[Price]]></string>
+    <string name="_bx_ads_menu_title_licenses_submenu"><![CDATA[Licenses Submenu]]></string>
+    <string name="_bx_ads_menu_set_title_licenses_submenu"><![CDATA[Licenses Submenu]]></string>
+    <string name="_bx_ads_menu_item_title_system_ads_licenses_administration"><![CDATA[All Licenses]]></string>
+    <string name="_bx_ads_menu_item_title_ads_licenses_administration"><![CDATA[All Licenses]]></string>
+    <string name="_bx_ads_menu_item_title_system_ads_licenses"><![CDATA[My Licenses]]></string>
+    <string name="_bx_ads_menu_item_title_ads_licenses"><![CDATA[My Licenses]]></string>
+    <string name="_bx_ads_menu_item_title_system_licenses"><![CDATA[Ads Licenses]]></string>
+    <string name="_bx_ads_menu_item_title_licenses"><![CDATA[Ads Licenses]]></string>
+    <string name="_bx_ads_menu_item_title_system_offers_all"><![CDATA[Ads Offers]]></string>
+    <string name="_bx_ads_menu_item_title_offers_all"><![CDATA[Offers]]></string>
+
+    <string name="_bx_ads_grid_column_title_icon"><![CDATA[Icon]]></string>
+    <string name="_bx_ads_grid_column_title_title"><![CDATA[Title]]></string>
+    <string name="_bx_ads_grid_column_title_subcategories"><![CDATA[Subcategories]]></string>
+    <string name="_bx_ads_grid_column_value_subcategories"><![CDATA[{0} subcategories]]></string>
+    <string name="_bx_ads_grid_column_info_subcategories"><![CDATA[View subcategories]]></string>
+    <string name="_bx_ads_grid_action_title_add"><![CDATA[Add New]]></string>
+    <string name="_bx_ads_grid_action_title_back"><![CDATA[Back]]></string>
+    <string name="_bx_ads_grid_action_title_delete"><![CDATA[Delete]]></string>
+    <string name="_bx_ads_grid_popup_title_add"><![CDATA[Add New Category]]></string>
+    <string name="_bx_ads_grid_popup_title_edit"><![CDATA[Edit '{0}' Category]]></string>
+    <string name="_bx_ads_grid_action_err_add_category"><![CDATA[Cannot add a category.]]></string>
+    <string name="_bx_ads_grid_action_err_edit_category"><![CDATA[Cannot edit the category.]]></string>
+
+    <string name="_bx_ads_grid_filter_item_title_adm_select_one_filter1"><![CDATA[All Statuses]]></string>
+    <string name="_bx_ads_grid_filter_item_title_adm_select_one_filter2"><![CDATA[Any Audience]]></string>
+    <string name="_bx_ads_grid_filter_item_title_adm_active"><![CDATA[Active]]></string>
+    <string name="_bx_ads_grid_filter_item_title_adm_hidden"><![CDATA[Hidden]]></string>
+    <string name="_bx_ads_grid_filter_item_title_adm_pending"><![CDATA[Pending]]></string>
+    <string name="_bx_ads_grid_column_title_adm_active"><![CDATA[Active]]></string>
+    <string name="_bx_ads_grid_column_title_adm_title"><![CDATA[Title]]></string>
+    <string name="_bx_ads_grid_column_title_adm_added"><![CDATA[Added]]></string>
+    <string name="_bx_ads_grid_column_title_adm_author"><![CDATA[Author]]></string>
+    <string name="_bx_ads_grid_action_title_adm_edit"><![CDATA[Edit]]></string>
+    <string name="_bx_ads_grid_action_title_adm_delete"><![CDATA[Delete]]></string>
+    <string name="_bx_ads_grid_action_title_adm_more_actions"><![CDATA[More Actions]]></string>
+    <string name="_bx_ads_grid_action_title_adm_audit_content"><![CDATA[Audit]]></string>
+    <string name="_bx_ads_grid_column_title_adm_status_admin"><![CDATA[Moderation]]></string>
+    <string name="_bx_ads_grid_action_err_delete"><![CDATA[Cannot delete the selected ad(s).]]></string>
+    <string name="_bx_ads_grid_txt_account_manager"><![CDATA[Redirect to manage account.]]></string>
+
+    <string name="_bx_ads_grid_column_title_lcs_profile_id"><![CDATA[Owner]]></string>
+    <string name="_bx_ads_grid_column_title_lcs_transaction"><![CDATA[Order]]></string>
+    <string name="_bx_ads_grid_column_title_lcs_entry"><![CDATA[Ad]]></string>
+    <string name="_bx_ads_grid_column_title_lcs_count"><![CDATA[Qt.]]></string>
+    <string name="_bx_ads_grid_column_title_lcs_license"><![CDATA[License]]></string>
+    <string name="_bx_ads_grid_column_title_lcs_added"><![CDATA[Date]]></string>
+
+    <string name="_bx_ads_grid_column_title_ofr_author_id"><![CDATA[Offerer]]></string>
+    <string name="_bx_ads_grid_column_title_ofr_amount"><![CDATA[Amount]]></string>
+    <string name="_bx_ads_grid_column_title_ofr_quantity"><![CDATA[Quantity]]></string>
+    <string name="_bx_ads_grid_column_title_ofr_message"><![CDATA[Message]]></string>
+    <string name="_bx_ads_grid_column_title_ofr_added"><![CDATA[Added]]></string>
+    <string name="_bx_ads_grid_column_title_ofr_status"><![CDATA[Status]]></string>
+    <string name="_bx_ads_grid_action_title_ofr_accept"><![CDATA[Accept the offer]]></string>
+    <string name="_bx_ads_grid_action_title_ofr_decline"><![CDATA[Decline the offer]]></string>
+
+    <string name="_bx_ads_grid_column_title_ofrs_content_id"><![CDATA[Ad]]></string>
+    <string name="_bx_ads_grid_column_title_ofrs_offers_awating"><![CDATA[Awating]]></string>
+    <string name="_bx_ads_grid_column_title_ofrs_offers_total"><![CDATA[Total]]></string>
+    <string name="_bx_ads_grid_action_title_ofr_view"><![CDATA[View offers]]></string>
+
+    <string name="_bx_ads_chart_growth"><![CDATA[Ads: Growth]]></string>
+    <string name="_bx_ads_chart_growth_speed"><![CDATA[Ads: Growth Speed]]></string>
+
+    <string name="_bx_ads_search_extended"><![CDATA[Ads Search]]></string>
+    <string name="_bx_ads_search_extended_cmts"><![CDATA[Ads Comments Search]]></string>
+    <string name="_bx_ads_search_extended_reviews"><![CDATA[Ads Reviews Search]]></string>
+
+    <!-- Ctegories -->
+    <string name="_bx_ads_cat_type_price"><![CDATA[With price]]></string>
+    <string name="_bx_ads_cat_type_price_year"><![CDATA[With price and year]]></string>
+
+    <string name="_bx_ads_cat_title_job"><![CDATA[Jobs]]></string>
+    <string name="_bx_ads_cat_title_accounting_finance"><![CDATA[Accounting / finance jobs]]></string>
+    <string name="_bx_ads_cat_title_education_nonprofit"><![CDATA[Education / nonprofit jobs]]></string>
+    <string name="_bx_ads_cat_title_government_legal"><![CDATA[Government / legal jobs]]></string>
+    <string name="_bx_ads_cat_title_programming_web_design"><![CDATA[Programming / web design jobs]]></string>
+
+    <string name="_bx_ads_cat_title_music"><![CDATA[Music Exchange]]></string>
+    <string name="_bx_ads_cat_title_instrument_sale"><![CDATA[Music instruments for sale]]></string>
+    <string name="_bx_ads_cat_title_instrument_wanted"><![CDATA[Music instruments wanted]]></string>
+    
+    <string name="_bx_ads_cat_title_housing"><![CDATA[Housing & Rentals]]></string>
+    <string name="_bx_ads_cat_title_apartments_housing"><![CDATA[Apartments / housing]]></string>
+    <string name="_bx_ads_cat_title_office_commercial"><![CDATA[Office / commercial]]></string>
+    <string name="_bx_ads_cat_title_real_estate_sale"><![CDATA[Real estate for sale]]></string>
+    <string name="_bx_ads_cat_title_roommate"><![CDATA[Roommates]]></string>
+    <string name="_bx_ads_cat_title_temporary_rental"><![CDATA[Temporary rental]]></string>
+    
+    <string name="_bx_ads_cat_title_service"><![CDATA[Services]]></string>
+    <string name="_bx_ads_cat_title_automotive"><![CDATA[Automotive services]]></string>
+    <string name="_bx_ads_cat_title_educational"><![CDATA[Educational services]]></string>
+    <string name="_bx_ads_cat_title_financial"><![CDATA[Financial services]]></string>
+    <string name="_bx_ads_cat_title_labor_move"><![CDATA[Labor / move services]]></string>
+    <string name="_bx_ads_cat_title_legal"><![CDATA[Legal services]]></string>
+
+    <string name="_bx_ads_cat_title_casting"><![CDATA[Casting Calls]]></string>
+    <string name="_bx_ads_cat_title_acting"><![CDATA[Acting castings]]></string>
+    <string name="_bx_ads_cat_title_dance"><![CDATA[Dance castings]]></string>
+    <string name="_bx_ads_cat_title_modeling"><![CDATA[Modeling castings]]></string>
+    <string name="_bx_ads_cat_title_musician"><![CDATA[Musicians castings]]></string>
+    <string name="_bx_ads_cat_title_reality_show"><![CDATA[Reality shows castings]]></string>
+
+    <string name="_bx_ads_cat_title_personal"><![CDATA[Personals]]></string>
+    <string name="_bx_ads_cat_title_men_women"><![CDATA[Men seeking women]]></string>
+    <string name="_bx_ads_cat_title_women_men"><![CDATA[Women seeking men]]></string>
+    <string name="_bx_ads_cat_title_missed_connection"><![CDATA[Missed connections]]></string>
+
+    <string name="_bx_ads_cat_title_sale"><![CDATA[For Sale]]></string>
+    <string name="_bx_ads_cat_title_barter"><![CDATA[Barter]]></string>
+    <string name="_bx_ads_cat_title_clothing"><![CDATA[Sale clothing]]></string>
+    <string name="_bx_ads_cat_title_collectible"><![CDATA[Sale collectibles]]></string>
+
+    <string name="_bx_ads_cat_title_sale_car"><![CDATA[Cars For Sale]]></string>
+    <string name="_bx_ads_cat_title_auto_part"><![CDATA[Sale auto parts]]></string>
+    <string name="_bx_ads_cat_title_auto_truck"><![CDATA[Sale autos / trucks]]></string>
+    <string name="_bx_ads_cat_title_motorcycle"><![CDATA[Sale motorcycles]]></string>
+
+    <string name="_bx_ads_et_txt_name_interested"><![CDATA[I'm interested.]]></string>
+    <string name="_bx_ads_et_txt_subject_interested"><![CDATA[{viewer_name} is interested in your ad.]]></string>
+    <string name="_bx_ads_et_txt_body_interested"><![CDATA[{email_header}
+<p>Hello, {profile_name}.</p>
+<p><b><a href="{viewer_url}">{viewer_name}</a></b> is interested in your ad <b><a href="{ad_url}">{ad_name}</a></b>.</p>
+{email_footer}]]></string>
+
+    <string name="_bx_ads_et_txt_name_purchased"><![CDATA[Ad was purchased.]]></string>
+    <string name="_bx_ads_et_txt_subject_purchased"><![CDATA[You've purchased {entry_name} ad.]]></string>
+    <string name="_bx_ads_et_txt_body_purchased"><![CDATA[{email_header}
+<p>Hello, {client_name}.</p>
+<p>You've purchased <a href="{entry_url}">{entry_name}</a> ad ({count} item(s)) from <a href="{vendor_url}">{vendor_name}</a>.<br />Your license is <b>{license}</b>.</p>
+<p>{notes}</p>
+{email_footer}]]></string>
+
+    <string name="_bx_ads_et_txt_name_shipped"><![CDATA[Ad was shipped.]]></string>
+    <string name="_bx_ads_et_txt_subject_shipped"><![CDATA[Ad {entry_name} was shipped.]]></string>
+    <string name="_bx_ads_et_txt_body_shipped"><![CDATA[{email_header}
+<p>Hello, {profile_name}.</p>
+<p>The <a href="{entry_url}">{entry_name}</a> ad was shipped by <a href="{vendor_url}">{vendor_name}</a>.</p>
+{email_footer}]]></string>
+
+    <string name="_bx_ads_et_txt_name_received"><![CDATA[Ad received.]]></string>
+    <string name="_bx_ads_et_txt_subject_received"><![CDATA[Ad {entry_name} was received.]]></string>
+    <string name="_bx_ads_et_txt_body_received"><![CDATA[{email_header}
+<p>Hello, {profile_name}.</p>
+<p>The <a href="{entry_url}">{entry_name}</a> ad was received by <a href="{client_url}">{client_name}</a>.</p>
+{email_footer}]]></string>
+
+    <string name="_bx_ads_et_txt_name_offer_added"><![CDATA[New offer was added.]]></string>
+    <string name="_bx_ads_et_txt_subject_offer_added"><![CDATA[{viewer_name} added an offer for your ad.]]></string>
+    <string name="_bx_ads_et_txt_body_offer_added"><![CDATA[{email_header}
+<p>Hello, {profile_name}.</p>
+<p><b><a href="{viewer_url}">{viewer_name}</a></b> added an offer for your ad <b><a href="{entry_url}">{entry_name}</a></b>.</p>
+{email_footer}]]></string>
+
+    <string name="_bx_ads_et_txt_name_offer_accepted"><![CDATA[The offer was accepted.]]></string>
+    <string name="_bx_ads_et_txt_subject_offer_accepted"><![CDATA[Your offer for {entry_name} ad was accepted.]]></string>
+    <string name="_bx_ads_et_txt_body_offer_accepted"><![CDATA[{email_header}
+<p>Hello, {offerer_name}.</p>
+<p>Your offer for <b><a href="{entry_url}">{entry_name}</a></b> ad was accepted.</p>
+{email_footer}]]></string>
+
+    <string name="_bx_ads_et_txt_name_offer_declined"><![CDATA[The offer was declined.]]></string>
+    <string name="_bx_ads_et_txt_subject_offer_declined"><![CDATA[Your offer for {entry_name} ad was declined.]]></string>
+    <string name="_bx_ads_et_txt_body_offer_declined"><![CDATA[{email_header}
+<p>Hello, {offerer_name}.</p>
+<p>Your offer for <b><a href="{entry_url}">{entry_name}</a></b> ad was declined.</p>
+{email_footer}]]></string>
+
+    <string name="_bx_ads_et_txt_name_offer_canceled"><![CDATA[The offer was canceled.]]></string>
+    <string name="_bx_ads_et_txt_subject_offer_canceled"><![CDATA[{offerer_name} canceled the offer for {entry_name} ad.]]></string>
+    <string name="_bx_ads_et_txt_body_offer_canceled"><![CDATA[{email_header}
+<p>Hello, {profile_name}.</p>
+<p><a href="{offerer_url}">{offerer_name}</a> canceled the offer for <b><a href="{entry_url}">{entry_name}</a></b> ad.</p>
+{email_footer}]]></string>
+
+    <string name="_bx_ads_txt_all_entries_in"><![CDATA[<a href="{0}">All Ads in {1} ({2})</a>]]></string>
+    <string name="_bx_ads_txt_all_entries_by"><![CDATA[{0} ads]]></string>
+    <string name="_bx_ads_txt_sample_single"><![CDATA[ad]]></string>
+    <string name="_bx_ads_txt_sample_single_with_article"><![CDATA[an ad]]></string>
+    <string name="_bx_ads_txt_sample_comment_single"><![CDATA[comment to ad]]></string>
+    <string name="_bx_ads_txt_sample_vote_single"><![CDATA[vote to ad]]></string>
+    <string name="_bx_ads_txt_sample_reaction_single"><![CDATA['{0}' reaction to ad]]></string>
+    <string name="_bx_ads_txt_sample_score_up_single"><![CDATA[score up vote to ad]]></string>
+    <string name="_bx_ads_txt_sample_score_down_single"><![CDATA[score down vote to ad]]></string>
+    <string name="_bx_ads_txt_sample_interest_single"><![CDATA[interested in ad]]></string>
+    <string name="_bx_ads_txt_display_title_add"><![CDATA[{0}: Add]]></string>
+    <string name="_bx_ads_txt_display_title_edit"><![CDATA[{0}: Edit]]></string>
+    <string name="_bx_ads_txt_display_title_view"><![CDATA[{0}: View]]></string>
+    <string name="_bx_ads_txt_processing_awaiting"><![CDATA[Ad will be published as soon as video is converted]]></string>
+    <string name="_bx_ads_txt_processing_failed"><![CDATA[Ad isn't published because video conversion failed, edit video to fix the issue.]]></string>
+    <string name="_bx_ads_txt_free"><![CDATA[Free]]></string>
+    <string name="_bx_ads_txt_purchased_note"><![CDATA[Contact <a href="{0}">{1}</a> if you have any questions or need support.]]></string>
+    <string name="_bx_ads_txt_offer_status_awaiting"><![CDATA[Awaiting]]></string>
+    <string name="_bx_ads_txt_offer_status_accepted"><![CDATA[Accepted]]></string>
+    <string name="_bx_ads_txt_offer_status_declined"><![CDATA[Declined]]></string>
+    <string name="_bx_ads_txt_offer_status_canceled"><![CDATA[Canceled]]></string>
+    <string name="_bx_ads_txt_your_offer"><![CDATA[Your offer]]></string>
+    <string name="_bx_ads_txt_accepted"><![CDATA[was accepted]]></string>
+    <string name="_bx_ads_txt_n_items"><![CDATA[{0} item(s)]]></string>
+    <string name="_bx_ads_txt_pay"><![CDATA[Pay]]></string>
+    <string name="_bx_ads_txt_cancel"><![CDATA[Cancel]]></string>
+
+    <string name="_bx_ads_txt_msg_status_hidden"><![CDATA[This ad was hidden.]]></string>
+    <string name="_bx_ads_txt_msg_status_pending"><![CDATA[This ad is pending approval.]]></string>
+    <string name="_bx_ads_txt_msg_auction_offer"><![CDATA[This ad is under offer.]]></string>
+    <string name="_bx_ads_txt_msg_auction_sold"><![CDATA[This ad was sold.]]></string>
+    <string name="_bx_ads_txt_msg_author_notified"><![CDATA[Advertiser was notified, that you're interested in his ad. Please wait.]]></string>
+    <string name="_bx_ads_txt_msg_offer_added"><![CDATA[Your offer was added. Advertiser will be notified about it. Please wait.]]></string>
+    <string name="_bx_ads_txt_msg_offer_accepted"><![CDATA[The offer was accepted.]]></string>
+    <string name="_bx_ads_txt_msg_offer_declined"><![CDATA[The offer was declined.]]></string>
+    <string name="_bx_ads_txt_msg_offer_canceled"><![CDATA[The offer was canceled.]]></string>
+    <string name="_bx_ads_txt_err_offer_duplicate"><![CDATA[You already made an offer. Please wait for the results.]]></string>
+    <string name="_bx_ads_txt_err_offer_accepted"><![CDATA[Your offer was already accepted.]]></string>
+    <string name="_bx_ads_txt_err_your_own"><![CDATA[You cannot do the action because it's your own ad.]]></string>
+    <string name="_bx_ads_txt_err_duplicate"><![CDATA[You already performed the action.]]></string>
+    <string name="_bx_ads_txt_err_cannot_perform_action"><![CDATA[Cannot perform action. Please report.]]></string>
+
+    <string name="_bx_ads_txt_poll_view_answers"><![CDATA[poll]]></string>
+    <string name="_bx_ads_txt_poll_view_results"><![CDATA[results]]></string>
+    <string name="_bx_ads_txt_poll_answer_vote_do_by"><![CDATA[Voted for]]></string>
+    <string name="_bx_ads_txt_poll_answer_vote_counter"><![CDATA[{0} votes]]></string>
+    <string name="_bx_ads_txt_poll_answer_vote_percent"><![CDATA[({0}%)]]></string>
+
+    <string name="_bx_ads_alert_action_doInterest_personal"><![CDATA[Someone interested in your ad]]></string>
+    <string name="_bx_ads_txt_ntfs_subobject_interested"><![CDATA[<b class="bx-ntfs-content-profile">{owner_name}</b> {subentry_sample} <b class="bx-ntfs-content-entry">{entry_caption}</b>]]></string>
+
+    <string name="_bx_ads_alert_action_license_register_personal"><![CDATA[Your ad was purchased]]></string>
+    <string name="_bx_ads_txt_ntfs_object_license_register"><![CDATA[<b class="bx-ntfs-content-profile">{owner_name}</b> purchased your ad <b class="bx-ntfs-content-entry">{entry_caption}</b>]]></string>
+
+    <string name="_bx_ads_alert_action_shipped_personal"><![CDATA[Ad was shipped]]></string>
+    <string name="_bx_ads_txt_ntfs_object_shipped"><![CDATA[<b class="bx-ntfs-content-profile">{owner_name}</b> shipped the ad <b class="bx-ntfs-content-entry">{entry_caption}</b>]]></string>
+
+    <string name="_bx_ads_alert_action_received_personal"><![CDATA[Ad was received]]></string>
+    <string name="_bx_ads_txt_ntfs_object_received"><![CDATA[<b class="bx-ntfs-content-profile">{owner_name}</b> received the ad <b class="bx-ntfs-content-entry">{entry_caption}</b>]]></string>
+
+    <string name="_bx_ads_alert_action_offer_added_personal"><![CDATA[Offer was added]]></string>
+    <string name="_bx_ads_txt_ntfs_offer_added"><![CDATA[<b class="bx-ntfs-content-profile">{owner_name}</b> added an offer to your ad <b class="bx-ntfs-content-entry">{entry_caption}</b>]]></string>
+
+    <string name="_bx_ads_alert_action_offer_accepted_personal"><![CDATA[Offer was accepted]]></string>
+    <string name="_bx_ads_txt_ntfs_offer_accepted"><![CDATA[<b class="bx-ntfs-content-profile">{owner_name}</b> accepted your offer for the ad <b class="bx-ntfs-content-entry">{entry_caption}</b>]]></string>
+
+    <string name="_bx_ads_alert_action_offer_declined_personal"><![CDATA[Offer was declined]]></string>
+    <string name="_bx_ads_txt_ntfs_offer_declined"><![CDATA[<b class="bx-ntfs-content-profile">{owner_name}</b> declined your offer for the ad <b class="bx-ntfs-content-entry">{entry_caption}</b>]]></string>
+
+    <string name="_bx_ads_alert_action_offer_canceled_personal"><![CDATA[Offer was canceled]]></string>
+    <string name="_bx_ads_txt_ntfs_offer_canceled"><![CDATA[<b class="bx-ntfs-content-profile">{owner_name}</b> canceled the offer for your ad <b class="bx-ntfs-content-entry">{entry_caption}</b>]]></string>
+</resources>

+ 655 - 0
modules/boonex/ads/updates/13.0.2_13.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_ads', '_bx_ads', 'bx_ads@modules/boonex/ads/|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_ads', '_bx_ads', 1);
+SET @iCategId = LAST_INSERT_ID();
+
+INSERT INTO `sys_options` (`name`, `value`, `category_id`, `caption`, `type`, `check`, `check_error`, `extra`, `order`) VALUES
+('bx_ads_enable_auto_approve', 'on', @iCategId, '_bx_ads_option_enable_auto_approve', 'checkbox', '', '', '', 0),
+('bx_ads_enable_auction', '', @iCategId, '_bx_ads_option_enable_auction', 'checkbox', '', '', '', 2),
+('bx_ads_internal_interested_notification', '', @iCategId, '_bx_ads_option_internal_interested_notification', 'checkbox', '', '', '', 3),
+
+('bx_ads_summary_chars', '700', @iCategId, '_bx_ads_option_summary_chars', 'digit', '', '', '', 10),
+('bx_ads_plain_summary_chars', '240', @iCategId, '_bx_ads_option_plain_summary_chars', 'digit', '', '', '', 12),
+
+('bx_ads_per_page_browse', '12', @iCategId, '_bx_ads_option_per_page_browse', 'digit', '', '', '', 20),
+('bx_ads_per_page_profile', '6', @iCategId, '_bx_ads_option_per_page_profile', 'digit', '', '', '', 22),
+('bx_ads_per_page_browse_showcase', '32', @iCategId, '_sys_option_per_page_browse_showcase', 'digit', '', '', '', 24),
+('bx_ads_rss_num', '10', @iCategId, '_bx_ads_option_rss_num', 'digit', '', '', '', 28),
+
+('bx_ads_searchable_fields', 'title,text', @iCategId, '_bx_ads_option_searchable_fields', 'list', '', '', 'a:2:{s:6:"module";s:6:"bx_ads";s:6:"method";s:21:"get_searchable_fields";}', 30),
+
+('bx_ads_lifetime', '30', @iCategId, '_bx_ads_option_lifetime', 'digit', '', '', '', 40),
+('bx_ads_offer_lifetime', '72', @iCategId, '_bx_ads_option_offer_lifetime', 'digit', '', '', '', 41);
+
+
+-- 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_ads_create_entry', '_bx_ads_page_title_sys_create_entry', '_bx_ads_page_title_create_entry', 'bx_ads', 5, 2147483647, 1, 'create-ad', 'page.php?i=create-ad', '', '', '', 0, 1, 0, 'BxAdsPageBrowse', 'modules/boonex/ads/classes/BxAdsPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks` (`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES
+('bx_ads_create_entry', 1, 'bx_ads', '_bx_ads_page_block_title_create_entry', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:6:"bx_ads";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_ads_edit_entry', '_bx_ads_page_title_sys_edit_entry', '_bx_ads_page_title_edit_entry', 'bx_ads', 5, 2147483647, 1, 'edit-ad', '', '', '', '', 0, 1, 0, 'BxAdsPageEntry', 'modules/boonex/ads/classes/BxAdsPageEntry.php');
+
+INSERT INTO `sys_pages_blocks` (`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES
+('bx_ads_edit_entry', 1, 'bx_ads', '_bx_ads_page_block_title_edit_entry', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:6:"bx_ads";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_ads_delete_entry', '_bx_ads_page_title_sys_delete_entry', '_bx_ads_page_title_delete_entry', 'bx_ads', 5, 2147483647, 1, 'delete-ad', '', '', '', '', 0, 1, 0, 'BxAdsPageEntry', 'modules/boonex/ads/classes/BxAdsPageEntry.php');
+
+INSERT INTO `sys_pages_blocks` (`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES
+('bx_ads_delete_entry', 1, 'bx_ads', '_bx_ads_page_block_title_delete_entry', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:6:"bx_ads";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_ads_view_entry', '_bx_ads_page_title_sys_view_entry', '_bx_ads_page_title_view_entry', 'bx_ads', 12, 2147483647, 1, 'view-ad', '', '', '', '', 0, 1, 0, 'BxAdsPageEntry', 'modules/boonex/ads/classes/BxAdsPageEntry.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_ads_view_entry', 1, 'bx_ads', '', '_bx_ads_page_block_title_entry_breadcrumb', 13, 2147483647, 'service', 'a:2:{s:6:"module";s:6:"bx_ads";s:6:"method";s:17:"entity_breadcrumb";}', 0, 0, 1, 1),
+('bx_ads_view_entry', 2, 'bx_ads', '', '_bx_ads_page_block_title_entry_comments', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:6:"bx_ads";s:6:"method";s:15:"entity_comments";}', 0, 0, 0, 0),
+('bx_ads_view_entry', 2, 'bx_ads', '', '_bx_ads_page_block_title_entry_author', 13, 2147483647, 'service', 'a:2:{s:6:"module";s:6:"bx_ads";s:6:"method";s:13:"entity_author";}', 0, 0, 1, 1),
+('bx_ads_view_entry', 2, 'bx_ads', '', '_bx_ads_page_block_title_entry_text', 13, 2147483647, 'service', 'a:2:{s:6:"module";s:6:"bx_ads";s:6:"method";s:17:"entity_text_block";}', 0, 0, 1, 10),
+('bx_ads_view_entry', 2, 'bx_ads', '', '_bx_ads_page_block_title_entry_all_actions', 13, 2147483647, 'service', 'a:2:{s:6:"module";s:6:"bx_ads";s:6:"method";s:18:"entity_all_actions";}', 0, 0, 1, 20),
+('bx_ads_view_entry', 2, 'bx_ads', '', '_bx_ads_page_block_title_entry_attachments', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:6:"bx_ads";s:6:"method";s:18:"entity_attachments";}', 0, 0, 1, 30),
+('bx_ads_view_entry', 2, 'bx_ads', '', '_bx_ads_page_block_title_entry_reviews', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:6:"bx_ads";s:6:"method";s:14:"entity_reviews";}', 0, 0, 1, 50),
+('bx_ads_view_entry', 3, 'bx_ads', '', '_bx_ads_page_block_title_entry_location', 13, 2147483647, 'service', 'a:2:{s:6:"module";s:6:"bx_ads";s:6:"method";s:15:"entity_location";}', 0, 0, 0, 0),
+('bx_ads_view_entry', 3, 'bx_ads', '', '_bx_ads_page_block_title_entry_offer_accepted', 13, 2147483647, 'service', 'a:3:{s:6:"module";s:6:"bx_ads";s:6:"method";s:21:"entity_offer_accepted";s:6:"params";a:1:{i:0;s:4:"{id}";}}', 0, 0, 1, 10),
+('bx_ads_view_entry', 3, 'bx_ads', '_bx_ads_page_block_title_sys_entry_context', '_bx_ads_page_block_title_entry_context', 13, 2147483647, 'service', 'a:2:{s:6:"module";s:6:"bx_ads";s:6:"method";s:14:"entity_context";}', 0, 0, 1, 20),
+('bx_ads_view_entry', 3, 'bx_ads', '', '_bx_ads_page_block_title_entry_info', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:6:"bx_ads";s:6:"method";s:11:"entity_info";}', 0, 0, 1, 30),
+('bx_ads_view_entry', 3, 'bx_ads', '', '_bx_ads_page_block_title_entry_reviews_rating', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:6:"bx_ads";s:6:"method";s:21:"entity_reviews_rating";}', 0, 0, 1, 40),
+('bx_ads_view_entry', 3, 'bx_ads', '', '_bx_ads_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:6:"bx_ads";i:1;s:4:"{id}";}s:5:"class";s:20:"TemplServiceMetatags";}', 0, 0, 1, 50),
+('bx_ads_view_entry', 2, 'bx_ads', '', '_bx_ads_page_block_title_entry_polls', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:6:"bx_ads";s:6:"method";s:12:"entity_polls";}', 0, 0, 1, 60),
+('bx_ads_view_entry', 3, 'bx_ads', '', '_bx_ads_page_block_title_featured_entries_view_extended', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:6:"bx_ads";s:6:"method";s:15:"browse_featured";s:6:"params";a:1:{i:0;s:8:"extended";}}', 0, 0, 1, 70),
+('bx_ads_view_entry', 4, 'bx_ads', '', '_bx_ads_page_block_title_entry_actions', 13, 2147483647, 'service', 'a:2:{s:6:"module";s:6:"bx_ads";s:6:"method";s:14:"entity_actions";}', 0, 0, 0, 0),
+('bx_ads_view_entry', 4, 'bx_ads', '', '_bx_ads_page_block_title_entry_social_sharing', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:6:"bx_ads";s:6:"method";s:21:"entity_social_sharing";}', 0, 0, 0, 0),
+('bx_ads_view_entry', 2, 'bx_ads', '', '_bx_ads_page_block_title_entry_reports', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:6:\"bx_ads\";s:6:\"method\";s:14:\"entity_reports\";}', 0, 0, 1, 6);
+
+-- 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_ads_view_entry_comments', '_bx_ads_page_title_sys_view_entry_comments', '_bx_ads_page_title_view_entry_comments', 'bx_ads', 5, 2147483647, 1, 'view-ad-comments', '', '', '', '', 0, 1, 0, 'BxAdsPageEntry', 'modules/boonex/ads/classes/BxAdsPageEntry.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_ads_view_entry_comments', 1, 'bx_ads', '_bx_ads_page_block_title_entry_comments', '_bx_ads_page_block_title_entry_comments_link', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:6:"bx_ads";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_ads_popular', '_bx_ads_page_title_sys_entries_popular', '_bx_ads_page_title_entries_popular', 'bx_ads', 5, 2147483647, 1, 'ads-popular', 'page.php?i=ads-popular', '', '', '', 0, 1, 0, 'BxAdsPageBrowse', 'modules/boonex/ads/classes/BxAdsPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_ads_popular', 1, 'bx_ads', '_bx_ads_page_block_title_popular_entries', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:6:"bx_ads";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: 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_ads_updated', '_bx_ads_page_title_sys_entries_updated', '_bx_ads_page_title_entries_updated', 'bx_ads', 5, 2147483647, 1, 'ads-updated', 'page.php?i=ads-updated', '', '', '', 0, 1, 0, 'BxAdsPageBrowse', 'modules/boonex/ads/classes/BxAdsPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_ads_updated', 1, 'bx_ads', '_bx_ads_page_block_title_updated_entries', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:6:"bx_ads";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' 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_ads_categories', '_bx_ads_page_title_sys_entries_categories', '_bx_ads_page_title_entries_categories', 'bx_ads', 1, 2147483647, 1, 'ads-categories', 'page.php?i=ads-categories', '', '', '', 0, 1, 0, 'BxAdsPageBrowse', 'modules/boonex/ads/classes/BxAdsPageBrowse.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_ads_categories', 1, 'bx_ads', '', '_bx_ads_page_block_title_categories', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:6:"bx_ads";s:6:"method";s:15:"categories_list";s:6:"params";a:1:{i:0;a:1:{s:10:"show_empty";b:1;}}}', 0, 0, 1, 1),
+('bx_ads_categories', 2, 'bx_ads', '', '_bx_ads_page_block_title_entries_by_category', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:6:"bx_ads";s:6:"method";s:15:"browse_category";s:6:"params";a:2:{i:0;i:0;i:1;a:3:{s:9:"unit_view";s:7:"gallery";s:13:"empty_message";b:1;s:13:"ajax_paginate";b:0;}}}', 0, 1, 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_ads_author', 'ads-author', '_bx_ads_page_title_sys_entries_of_author', '_bx_ads_page_title_entries_of_author', 'bx_ads', 5, 2147483647, 1, '', '', '', '', 0, 1, 0, 'BxAdsPageAuthor', 'modules/boonex/ads/classes/BxAdsPageAuthor.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_ads_author', 1, 'bx_ads', '', '_bx_ads_page_block_title_entries_actions', 13, 2147483647, 'service', 'a:2:{s:6:"module";s:6:"bx_ads";s:6:"method";s:18:"my_entries_actions";}', 0, 0, 1, 1),
+('bx_ads_author', 1, 'bx_ads', '_bx_ads_page_block_title_sys_favorites_of_author', '_bx_ads_page_block_title_favorites_of_author', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:6:"bx_ads";s:6:"method";s:15:"browse_favorite";s:6:"params";a:1:{i:0;s:12:"{profile_id}";}}', 0, 1, 1, 2),
+('bx_ads_author', 1, 'bx_ads', '_bx_ads_page_block_title_sys_entries_of_author', '_bx_ads_page_block_title_entries_of_author', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:6:"bx_ads";s:6:"method";s:13:"browse_author";}', 0, 0, 1, 3),
+('bx_ads_author', 1, 'bx_ads', '_bx_ads_page_block_title_sys_entries_in_context', '_bx_ads_page_block_title_entries_in_context', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:6:"bx_ads";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: 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_ads_context', 'ads-context', '_bx_ads_page_title_sys_entries_in_context', '_bx_ads_page_title_entries_in_context', 'bx_ads', 5, 2147483647, 1, '', '', '', '', 0, 1, 0, 'BxAdsPageAuthor', 'modules/boonex/ads/classes/BxAdsPageAuthor.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_ads_context', 1, 'bx_ads', '_bx_ads_page_block_title_sys_entries_in_context', '_bx_ads_page_block_title_entries_in_context', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:6:"bx_ads";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_ads_home', 'ads-home', '_bx_ads_page_title_sys_home', '_bx_ads_page_title_home', 'bx_ads', 2, 2147483647, 1, 'page.php?i=ads-home', '', '', '', 0, 1, 0, 'BxAdsPageBrowse', 'modules/boonex/ads/classes/BxAdsPageBrowse.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_ads_home', 1, 'bx_ads', '', '_bx_ads_page_block_title_featured_entries_view_extended', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:6:"bx_ads";s:6:"method";s:15:"browse_featured";s:6:"params";a:1:{i:0;s:8:"extended";}}', 0, 1, 1, 0),
+('bx_ads_home', 1, 'bx_ads', '', '_bx_ads_page_block_title_recent_entries_view_extended', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:6:"bx_ads";s:6:"method";s:13:"browse_public";s:6:"params";a:1:{i:0;s:8:"extended";}}', 0, 1, 1, 1),
+('bx_ads_home', 2, 'bx_ads', '', '_bx_ads_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:6:"bx_ads";i:1;s:6:"bx_ads";}s:5:"class";s:20:"TemplServiceMetatags";}', 0, 1, 1, 0),
+('bx_ads_home', 2, 'bx_ads', '', '_bx_ads_page_block_title_categories', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:6:"bx_ads";s:6:"method";s:15:"categories_list";s:6:"params";a:1:{i:0;a:1:{s:10:"show_empty";b:1;}}}', 0, 1, 1, 1);
+
+-- PAGE: search for entries
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_ads_search', '_bx_ads_page_title_sys_entries_search', '_bx_ads_page_title_entries_search', 'bx_ads', 5, 2147483647, 1, 'ads-search', 'page.php?i=ads-search', '', '', '', 0, 1, 0, 'BxAdsPageBrowse', 'modules/boonex/ads/classes/BxAdsPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_ads_search', 1, 'bx_ads', '_bx_ads_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:6:"bx_ads";}}s:5:"class";s:27:"TemplSearchExtendedServices";}', 0, 1, 1, 1),
+('bx_ads_search', 1, 'bx_ads', '_bx_ads_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:6:"bx_ads";s:10:"show_empty";b:1;}}s:5:"class";s:27:"TemplSearchExtendedServices";}', 0, 1, 1, 2),
+('bx_ads_search', 1, 'bx_ads', '_bx_ads_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:11:"bx_ads_cmts";}}s:5:"class";s:27:"TemplSearchExtendedServices";}', 0, 1, 0, 3),
+('bx_ads_search', 1, 'bx_ads', '_bx_ads_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:11:"bx_ads_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_ads_manage', '_bx_ads_page_title_sys_manage', '_bx_ads_page_title_manage', 'bx_ads', 5, 2147483647, 1, 'ads-manage', 'page.php?i=ads-manage', '', '', '', 0, 1, 0, 'BxAdsPageBrowse', 'modules/boonex/ads/classes/BxAdsPageBrowse.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_ads_manage', 1, 'bx_ads', '_bx_ads_page_block_title_system_manage', '_bx_ads_page_block_title_manage', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:6:"bx_ads";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_ads_administration', '_bx_ads_page_title_sys_manage_administration', '_bx_ads_page_title_manage', 'bx_ads', 5, 192, 1, 'ads-administration', 'page.php?i=ads-administration', '', '', '', 0, 1, 0, 'BxAdsPageBrowse', 'modules/boonex/ads/classes/BxAdsPageBrowse.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_ads_administration', 1, 'bx_ads', '_bx_ads_page_block_title_system_manage_administration', '_bx_ads_page_block_title_manage', 11, 192, 'service', 'a:3:{s:6:"module";s:6:"bx_ads";s:6:"method";s:12:"manage_tools";s:6:"params";a:1:{i:0;s:14:"administration";}}', 0, 1, 0);
+
+-- PAGE: manage own 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_ads_licenses', '_bx_ads_page_title_sys_licenses', '_bx_ads_page_title_licenses', 'bx_ads', 5, 2147483647, 1, 'ads-licenses', '', '', '', '', 0, 1, 0, 'BxAdsPageLicenses', 'modules/boonex/ads/classes/BxAdsPageLicenses.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_ads_licenses', 1, 'bx_ads', '', '_bx_ads_page_block_title_licenses_note', 13, 2147483647, 'service', 'a:2:{s:6:"module";s:6:"bx_ads";s:6:"method";s:19:"block_licenses_note";}', 0, 0, 1, 0),
+('bx_ads_licenses', 1, 'bx_ads', '', '_bx_ads_page_block_title_licenses', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:6:"bx_ads";s:6:"method";s:14:"block_licenses";}', 0, 0, 1, 1);
+
+-- PAGE: manage all 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_ads_licenses_administration', '_bx_ads_page_title_sys_licenses_administration', '_bx_ads_page_title_licenses_administration', 'bx_ads', 5, 192, 1, 'ads-licenses-administration', '', '', '', '', 0, 1, 0, 'BxAdsPageLicenses', 'modules/boonex/ads/classes/BxAdsPageLicenses.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_ads_licenses_administration', 1, 'bx_ads', '', '_bx_ads_page_block_title_licenses_administration', 11, 192, 'service', 'a:2:{s:6:"module";s:6:"bx_ads";s:6:"method";s:29:"block_licenses_administration";}', 0, 0, 1, 0);
+
+-- PAGE: view offers for 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_ads_offers', '_bx_ads_page_title_sys_offers', '_bx_ads_page_title_offers', 'bx_ads', 5, 2147483647, 1, 'view-ad-offers', '', '', '', '', 0, 1, 0, 'BxAdsPageOffers', 'modules/boonex/ads/classes/BxAdsPageOffers.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_ads_offers', 1, 'bx_ads', '', '_bx_ads_page_block_title_entry_breadcrumb', 13, 2147483647, 'service', 'a:3:{s:6:"module";s:6:"bx_ads";s:6:"method";s:17:"entity_breadcrumb";s:6:"params";a:1:{i:0;s:4:"{id}";}}', 0, 0, 1, 1),
+('bx_ads_offers', 1, 'bx_ads', '', '_bx_ads_page_block_title_offers', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:6:"bx_ads";s:6:"method";s:13:"entity_offers";s:6:"params";a:1:{i:0;s:4:"{id}";}}', 0, 0, 1, 2);
+
+-- PAGE: view all offers
+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_ads_offers_all', '_bx_ads_page_title_sys_offers_all', '_bx_ads_page_title_offers_all', 'bx_ads', 5, 2147483647, 1, 'ads-offers', '', '', '', '', 0, 1, 0, '', '');
+
+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_ads_offers_all', 1, 'bx_ads', '', '_bx_ads_page_block_title_offers_all', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:6:"bx_ads";s:6:"method";s:6:"offers";}', 0, 0, 1, 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`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('sys_home', 1, 'bx_ads', '_bx_ads_page_block_title_recent_entries', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:6:"bx_ads";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_ads', '_bx_ads_page_block_title_sys_my_entries', '_bx_ads_page_block_title_my_entries', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:6:"bx_ads";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:23:"bx_ads_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_ads', '', '_bx_ads_page_block_title_recent_entries', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:6:"bx_ads";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_ads', '', '_bx_ads_page_block_title_recent_entries_view_full', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:6:"bx_ads";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_ads', '', '_bx_ads_page_block_title_popular_entries_view_extended', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:6:"bx_ads";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_ads', '', '_bx_ads_page_block_title_popular_entries_view_full', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:6:"bx_ads";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_ads', '_bx_ads_page_block_title_sys_recent_entries_view_showcase', '_bx_ads_page_block_title_recent_entries_view_showcase', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:6:"bx_ads";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) + 5),
+('', 0, 'bx_ads', '_bx_ads_page_block_title_sys_popular_entries_view_showcase', '_bx_ads_page_block_title_popular_entries_view_showcase', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:6:"bx_ads";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) + 6),
+('', 0, 'bx_ads', '_bx_ads_page_block_title_sys_featured_entries_view_showcase', '_bx_ads_page_block_title_featured_entries_view_showcase', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:6:"bx_ads";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) + 7);
+
+
+-- 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_ads', 'ads-home', '_bx_ads_menu_item_title_system_entries_home', '_bx_ads_menu_item_title_entries_home', 'page.php?i=ads-home', '', '', 'ad col-green2', 'bx_ads_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_ads', 'ads-home', '_bx_ads_menu_item_title_system_entries_home', '_bx_ads_menu_item_title_entries_home', 'page.php?i=ads-home', '', '', 'ad col-green2', 'bx_ads_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_ads', 'create-ad', '_bx_ads_menu_item_title_system_create_entry', '_bx_ads_menu_item_title_create_entry', 'page.php?i=create-ad', '', '', 'ad col-green2', '', 2147483647, 1, 1, IFNULL(@iAddMenuOrder, 0) + 1);
+
+-- MENU: create ad form attachments (link, photo, video, etc)
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_ads_entry_attachments', '_bx_ads_menu_title_entry_attachments', 'bx_ads_entry_attachments', 'bx_ads', 23, 0, 1, 'BxAdsMenuAttachments', 'modules/boonex/ads/classes/BxAdsMenuAttachments.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_ads_entry_attachments', 'bx_ads', '_bx_ads_menu_set_title_entry_attachments', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `addon`, `submenu_object`, `visible_for_levels`, `visibility_custom`, `active`, `copyable`, `editable`, `order`) VALUES 
+('bx_ads_entry_attachments', 'bx_ads', 'photo_simple', '_bx_ads_menu_item_title_system_cpa_photo_simple', '_bx_ads_menu_item_title_cpa_photo_simple', 'javascript:void(0)', 'javascript:{js_object_uploader_photos_simple}.showUploaderForm();', '_self', 'camera', '', '', 2147483647, '', 0, 0, 1, 1),
+('bx_ads_entry_attachments', 'bx_ads', 'photo_html5', '_bx_ads_menu_item_title_system_cpa_photo_html5', '_bx_ads_menu_item_title_cpa_photo_html5', 'javascript:void(0)', 'javascript:{js_object_uploader_photos_html5}.showUploaderForm();', '_self', 'camera', '', '', 2147483647, '', 1, 0, 1, 2),
+('bx_ads_entry_attachments', 'bx_ads', 'video_simple', '_bx_ads_menu_item_title_system_cpa_video_simple', '_bx_ads_menu_item_title_cpa_video_simple', 'javascript:void(0)', 'javascript:{js_object_uploader_videos_simple}.showUploaderForm();', '_self', 'video', '', '', 2147483647, '', 0, 0, 1, 3),
+('bx_ads_entry_attachments', 'bx_ads', 'video_html5', '_bx_ads_menu_item_title_system_cpa_video_html5', '_bx_ads_menu_item_title_cpa_video_html5', 'javascript:void(0)', 'javascript:{js_object_uploader_videos_html5}.showUploaderForm();', '_self', 'video', '', '', 2147483647, '', 1, 0, 1, 4),
+('bx_ads_entry_attachments', 'bx_ads', 'record_video', '_bx_ads_menu_item_title_system_cpa_video_record', '_bx_ads_menu_item_title_cpa_video_record', 'javascript:void(0)', 'javascript:{js_object_uploader_videos_record_video}.showUploaderForm();', '_self', 'fas circle', '', '', 2147483647, '', 1, 0, 1, 5),
+('bx_ads_entry_attachments', 'bx_ads', 'file_simple', '_bx_ads_menu_item_title_system_cpa_file_simple', '_bx_ads_menu_item_title_cpa_file_simple', 'javascript:void(0)', 'javascript:{js_object_uploader_files_simple}.showUploaderForm();', '_self', 'file', '', '', 2147483647, '', 0, 0, 1, 6),
+('bx_ads_entry_attachments', 'bx_ads', 'file_html5', '_bx_ads_menu_item_title_system_cpa_file_html5', '_bx_ads_menu_item_title_cpa_file_html5', 'javascript:void(0)', 'javascript:{js_object_uploader_files_html5}.showUploaderForm();', '_self', 'file', '', '', 2147483647, '', 1, 0, 1, 7),
+('bx_ads_entry_attachments', 'bx_ads', 'poll', '_bx_ads_menu_item_title_system_cpa_poll', '_bx_ads_menu_item_title_cpa_poll', 'javascript:void(0)', 'javascript:{js_object}.showPollForm(this);', '_self', 'tasks', '', '', 2147483647, '', 1, 0, 1, 7);
+
+-- 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_ads_view', '_bx_ads_menu_title_view_entry', 'bx_ads_view', 'bx_ads', 9, 0, 1, 'BxAdsMenuView', 'modules/boonex/ads/classes/BxAdsMenuView.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_ads_view', 'bx_ads', '_bx_ads_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_ads_view', 'bx_ads', 'interested', '_bx_ads_menu_item_title_system_interested_entry', '_bx_ads_menu_item_title_interested_entry', 'javascript:void(0)', 'javascript:{js_object}.interested(this, {content_id})', '', 'map-marker', '', 2147483646, 1, 0, 10),
+('bx_ads_view', 'bx_ads', 'add-to-cart', '_bx_ads_menu_item_title_system_add_to_cart', '{add_to_cart_title}', 'javascript:void(0);', 'javascript:{add_to_cart_onclick}', '', 'cart-plus', '', 2147483647, 1, 0, 15),
+('bx_ads_view', 'bx_ads', 'make-offer', '_bx_ads_menu_item_title_system_make_offer', '_bx_ads_menu_item_title_make_offer', 'javascript:void(0);', 'javascript:{js_object}.makeOffer(this, {content_id})', '', 'hand-holding-usd', '', 2147483647, 1, 0, 16),
+('bx_ads_view', 'bx_ads', 'view-offers', '_bx_ads_menu_item_title_system_view_offers', '_bx_ads_menu_item_title_view_offers', 'page.php?i=view-ad-offers&id={content_id}', '', '', '', '', 2147483647, 1, 0, 17),
+('bx_ads_view', 'bx_ads', 'edit-ad', '_bx_ads_menu_item_title_system_edit_entry', '_bx_ads_menu_item_title_edit_entry', 'page.php?i=edit-ad&id={content_id}', '', '', 'pencil-alt', '', 2147483647, 1, 0, 20),
+('bx_ads_view', 'bx_ads', 'delete-ad', '_bx_ads_menu_item_title_system_delete_entry', '_bx_ads_menu_item_title_delete_entry', 'page.php?i=delete-ad&id={content_id}', '', '', 'remove', '', 2147483647, 1, 0, 30),
+('bx_ads_view', 'bx_ads', 'approve', '_sys_menu_item_title_system_va_approve', '_sys_menu_item_title_va_approve', 'javascript:void(0)', 'javascript:bx_approve(this,  ''{module_uri}'', {content_id});', '', 'check', '', 2147483647, 1, 0, 40),
+('bx_ads_view', 'bx_ads', 'shipped', '_bx_ads_menu_item_title_system_mark_shipped', '_bx_ads_menu_item_title_mark_shipped', 'javascript:void(0)', 'javascript:{js_object}.shipped(this, {content_id})', '', 'truck', '', 2147483647, 1, 0, 50),
+('bx_ads_view', 'bx_ads', 'received', '_bx_ads_menu_item_title_system_mark_received', '_bx_ads_menu_item_title_mark_received', 'javascript:void(0)', 'javascript:{js_object}.received(this, {content_id})', '', 'clipboard-check', '', 2147483647, 1, 0, 55);
+
+-- 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_ads_view_actions', '_sys_menu_title_view_actions', 'bx_ads_view_actions', 'bx_ads', 15, 0, 1, 'BxAdsMenuViewActions', 'modules/boonex/ads/classes/BxAdsMenuViewActions.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_ads_view_actions', 'bx_ads', '_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_ads_view_actions', 'bx_ads', 'interested', '_bx_ads_menu_item_title_system_interested_entry', '', '', '', '', '', '', '', 0, 2147483646, 1, 0, 10),
+('bx_ads_view_actions', 'bx_ads', 'add-to-cart', '_bx_ads_menu_item_title_system_add_to_cart', '', '', '', '', '', '', '', 0, 2147483647, 1, 0, 15),
+('bx_ads_view_actions', 'bx_ads', 'make-offer', '_bx_ads_menu_item_title_system_make_offer', '', '', '', '', '', '', '', 0, 2147483647, 1, 0, 16),
+('bx_ads_view_actions', 'bx_ads', 'view-offers', '_bx_ads_menu_item_title_system_view_offers', '', '', '', '', '', '', '', 0, 2147483647, 1, 0, 17),
+('bx_ads_view_actions', 'bx_ads', 'edit-ad', '_bx_ads_menu_item_title_system_edit_entry', '', '', '', '', '', '', '', 0, 2147483647, 1, 0, 20),
+('bx_ads_view_actions', 'bx_ads', 'delete-ad', '_bx_ads_menu_item_title_system_delete_entry', '', '', '', '', '', '', '', 0, 2147483647, 1, 0, 30),
+('bx_ads_view_actions', 'bx_ads', 'approve', '_sys_menu_item_title_system_va_approve', '', '', '', '', '', '', '', 0, 2147483647, 1, 0, 40),
+('bx_ads_view_actions', 'bx_ads', 'shipped', '_bx_ads_menu_item_title_system_mark_shipped', '', '', '', '', '', '', '', 0, 2147483647, 1, 0, 50),
+('bx_ads_view_actions', 'bx_ads', 'received', '_bx_ads_menu_item_title_system_mark_received', '', '', '', '', '', '', '', 0, 2147483647, 1, 0, 55),
+('bx_ads_view_actions', 'bx_ads', 'review', '_bx_ads_menu_item_title_system_review_entry', '', '', '', '', '', '', '', 0, 2147483647, 0, 0, 190),
+('bx_ads_view_actions', 'bx_ads', 'comment', '_sys_menu_item_title_system_va_comment', '', '', '', '', '', '', '', 0, 2147483647, 0, 0, 200),
+('bx_ads_view_actions', 'bx_ads', 'view', '_sys_menu_item_title_system_va_view', '', '', '', '', '', '', '', 0, 2147483647, 1, 0, 210),
+('bx_ads_view_actions', 'bx_ads', 'vote', '_sys_menu_item_title_system_va_vote', '', '', '', '', '', '', '', 0, 2147483647, 0, 0, 220),
+('bx_ads_view_actions', 'bx_ads', 'reaction', '_sys_menu_item_title_system_va_reaction', '', '', '', '', '', '', '', 0, 2147483647, 1, 0, 225),
+('bx_ads_view_actions', 'bx_ads', 'score', '_sys_menu_item_title_system_va_score', '', '', '', '', '', '', '', 0, 2147483647, 1, 0, 230),
+('bx_ads_view_actions', 'bx_ads', 'favorite', '_sys_menu_item_title_system_va_favorite', '', '', '', '', '', '', '', 0, 2147483647, 1, 0, 240),
+('bx_ads_view_actions', 'bx_ads', 'feature', '_sys_menu_item_title_system_va_feature', '', '', '', '', '', '', '', 0, 2147483647, 1, 0, 250),
+('bx_ads_view_actions', 'bx_ads', 'repost', '_sys_menu_item_title_system_va_repost', '', '', '', '', '', '', '', 0, 2147483647, 1, 0, 260),
+('bx_ads_view_actions', 'bx_ads', 'report', '_sys_menu_item_title_system_va_report', '', '', '', '', '', '', '', 0, 2147483647, 1, 0, 270),
+('bx_ads_view_actions', 'bx_ads', '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_ads_view_actions', 'bx_ads', 'audit', '_sys_menu_item_title_system_va_audit', '_sys_menu_item_title_va_audit', 'page.php?i=dashboard-audit&module=bx_courses&content_id={content_id}', '', '', 'history', '', '', 0, 192, 1, 0, 290),
+('bx_ads_view_actions', 'bx_ads', 'social-sharing', '_sys_menu_item_title_system_social_sharing', '_sys_menu_item_title_social_sharing', 'javascript:void(0)', 'oBxDolPage.share(this, \'{url_encoded}\')', '', 'share', '', '', 0, 2147483647, 1, 0, 300),
+('bx_ads_view_actions', 'bx_ads', '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_ads_my', '_bx_ads_menu_title_entries_my', 'bx_ads_my', 'bx_ads', 9, 0, 1, 'BxAdsMenu', 'modules/boonex/ads/classes/BxAdsMenu.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_ads_my', 'bx_ads', '_bx_ads_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_ads_my', 'bx_ads', 'create-ad', '_bx_ads_menu_item_title_system_create_entry', '_bx_ads_menu_item_title_create_entry', 'page.php?i=create-ad', '', '', '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_ads_submenu', '_bx_ads_menu_title_submenu', 'bx_ads_submenu', 'bx_ads', 8, 0, 1, '', '');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_ads_submenu', 'bx_ads', '_bx_ads_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_ads_submenu', 'bx_ads', 'ads-home', '_bx_ads_menu_item_title_system_entries_public', '_bx_ads_menu_item_title_entries_public', 'page.php?i=ads-home', '', '', '', '', 2147483647, 1, 1, 1),
+('bx_ads_submenu', 'bx_ads', 'ads-popular', '_bx_ads_menu_item_title_system_entries_popular', '_bx_ads_menu_item_title_entries_popular', 'page.php?i=ads-popular', '', '', '', '', 2147483647, 1, 1, 2),
+('bx_ads_submenu', 'bx_ads', 'ads-categories', '_bx_ads_menu_item_title_system_entries_categories', '_bx_ads_menu_item_title_entries_categories', 'page.php?i=ads-categories', '', '', '', '', 2147483647, 1, 1, 3),
+('bx_ads_submenu', 'bx_ads', 'ads-search', '_bx_ads_menu_item_title_system_entries_search', '_bx_ads_menu_item_title_entries_search', 'page.php?i=ads-search', '', '', '', '', 2147483647, 1, 1, 4),
+('bx_ads_submenu', 'bx_ads', 'ads-manage', '_bx_ads_menu_item_title_system_entries_manage', '_bx_ads_menu_item_title_entries_manage', 'page.php?i=ads-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_ads_view_submenu', '_bx_ads_menu_title_view_entry_submenu', 'bx_ads_view_submenu', 'bx_ads', 8, 0, 1, 'BxAdsMenuView', 'modules/boonex/ads/classes/BxAdsMenuView.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_ads_view_submenu', 'bx_ads', '_bx_ads_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_ads_view_submenu', 'bx_ads', 'view-ad', '_bx_ads_menu_item_title_system_view_entry', '_bx_ads_menu_item_title_view_entry_submenu_entry', 'page.php?i=view-ad&id={content_id}', '', '', '', '', 2147483647, 0, 0, 1),
+('bx_ads_view_submenu', 'bx_ads', 'view-ad-comments', '_bx_ads_menu_item_title_system_view_entry_comments', '_bx_ads_menu_item_title_view_entry_submenu_comments', 'page.php?i=view-ad-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_ads_snippet_meta', '_sys_menu_title_snippet_meta', 'bx_ads_snippet_meta', 'bx_ads', 15, 0, 1, 'BxAdsMenuSnippetMeta', 'modules/boonex/ads/classes/BxAdsMenuSnippetMeta.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_ads_snippet_meta', 'bx_ads', '_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_ads_snippet_meta', 'bx_ads', 'date', '_sys_menu_item_title_system_sm_date', '_sys_menu_item_title_sm_date', '', '', '', '', '', 2147483647, 1, 0, 1, 1),
+('bx_ads_snippet_meta', 'bx_ads', 'author', '_sys_menu_item_title_system_sm_author', '_sys_menu_item_title_sm_author', '', '', '', '', '', 2147483647, 1, 0, 1, 2),
+('bx_ads_snippet_meta', 'bx_ads', 'category', '_sys_menu_item_title_system_sm_category', '_sys_menu_item_title_sm_category', '', '', '', '', '', 2147483647, 1, 0, 1, 3),
+('bx_ads_snippet_meta', 'bx_ads', 'price', '_bx_ads_menu_item_title_system_sm_price', '_bx_ads_menu_item_title_sm_price', '', '', '', '', '', 2147483647, 1, 0, 1, 4),
+('bx_ads_snippet_meta', 'bx_ads', 'tags', '_sys_menu_item_title_system_sm_tags', '_sys_menu_item_title_sm_tags', '', '', '', '', '', 2147483647, 0, 0, 1, 5),
+('bx_ads_snippet_meta', 'bx_ads', 'views', '_sys_menu_item_title_system_sm_views', '_sys_menu_item_title_sm_views', '', '', '', '', '', 2147483647, 0, 0, 1, 6),
+('bx_ads_snippet_meta', 'bx_ads', 'comments', '_sys_menu_item_title_system_sm_comments', '_sys_menu_item_title_sm_comments', '', '', '', '', '', 2147483647, 0, 0, 1, 7);
+
+-- 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_ads_licenses_submenu', '_bx_ads_menu_title_licenses_submenu', 'bx_ads_licenses_submenu', 'bx_ads', 6, 0, 1, '', '');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_ads_licenses_submenu', 'bx_ads', '_bx_ads_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_ads_licenses_submenu', 'bx_ads', 'ads-licenses-administration', '_bx_ads_menu_item_title_system_ads_licenses_administration', '_bx_ads_menu_item_title_ads_licenses_administration', 'page.php?i=ads-licenses-administration', '', '_self', '', '', '', 192, 1, 0, 1, 1),
+('bx_ads_licenses_submenu', 'bx_ads', 'ads-licenses', '_bx_ads_menu_item_title_system_ads_licenses', '_bx_ads_menu_item_title_ads_licenses', 'page.php?i=ads-licenses', '', '_self', '', '', '', 2147483646, 1, 0, 1, 2);
+
+-- MENU: notifications menu in account popup
+SET @iNotifMenuOrder = (SELECT IFNULL(MAX(`order`), 0) FROM `sys_menu_items` WHERE `set_name` = 'sys_account_notifications' 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`, `addon`, `submenu_object`, `visible_for_levels`, `visibility_custom`, `active`, `copyable`, `order`) VALUES
+('sys_account_notifications', 'bx_ads', 'notifications-ads-offers', '_bx_ads_menu_item_title_system_offers_all', '_bx_ads_menu_item_title_offers_all', 'page.php?i=ads-offers&profile_id={member_id}', '', '', 'ad col-green2', 'a:3:{s:6:"module";s:6:"bx_ads";s:6:"method";s:16:"get_offers_count";s:6:"params";a:1:{i:0;s:8:"awaiting";}}', '', 2147483646, '', 1, 0, @iNotifMenuOrder + 1);
+
+-- 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_ads', 'profile-stats-my-ads', '_bx_ads_menu_item_title_system_manage_my_posts', '_bx_ads_menu_item_title_manage_my_posts', 'page.php?i=ads-author&profile_id={member_id}', '', '_self', 'ad col-green2', 'a:2:{s:6:"module";s:6:"bx_ads";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_ads_menu_manage_tools', '_bx_ads_menu_title_manage_tools', 'bx_ads_menu_manage_tools', 'bx_ads', 6, 0, 1, 'BxAdsMenuManageTools', 'modules/boonex/ads/classes/BxAdsMenuManageTools.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_ads_menu_manage_tools', 'bx_ads', '_bx_ads_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_ads_menu_manage_tools', 'bx_ads', 'delete-with-content', '_bx_ads_menu_item_title_system_delete_with_content', '_bx_ads_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_ads', 'ads-administration', '_bx_ads_menu_item_title_system_admt_ads', '_bx_ads_menu_item_title_admt_ads', 'page.php?i=ads-administration', '', '_self', 'ad', 'a:2:{s:6:"module";s:6:"bx_ads";s:6:"method";s:27:"get_menu_addon_manage_tools";}', '', 192, 1, 0, @iManageMenuOrder + 1);
+
+-- MENU: account dashboard
+SET @iDashboardMenuOrder = (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_ads', 'dashboard-ads-licenses', '_bx_ads_menu_item_title_system_licenses', '_bx_ads_menu_item_title_licenses', 'page.php?i=ads-licenses', '', '', 'ad col-green2', '', '', 2147483646, 1, 0, 1, @iDashboardMenuOrder + 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_ads', 'ads-author', '_bx_ads_menu_item_title_system_view_entries_author', '_bx_ads_menu_item_title_view_entries_author', 'page.php?i=ads-author&profile_id={profile_id}', '', '', 'ad col-green2', '', 2147483647, 1, 0, 0),
+('trigger_group_view_submenu', 'bx_ads', 'ads-context', '_bx_ads_menu_item_title_system_view_entries_in_context', '_bx_ads_menu_item_title_view_entries_in_context', 'page.php?i=ads-context&profile_id={profile_id}', '', '', 'ad col-green2', '', 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_ads_allow_view_to', 'bx_ads', 'view', '_bx_ads_form_entry_input_allow_view_to', '3', 'bx_ads_entries', 'id', 'author', '', '');
+
+
+-- ACL
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_ads', 'create entry', NULL, '_bx_ads_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_ads', 'delete entry', NULL, '_bx_ads_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_ads', 'view entry', NULL, '_bx_ads_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_ads', 'set thumb', NULL, '_bx_ads_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_ads', 'edit any entry', NULL, '_bx_ads_acl_action_edit_any_entry', '', 1, 3);
+SET @iIdActionEntryEditAny = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_ads', 'delete any entry', NULL, '_bx_ads_acl_action_delete_any_entry', '', 1, 3);
+SET @iIdActionEntryDeleteAny = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_ads', 'make offer', NULL, '_bx_ads_acl_action_make_offer', '', 1, 3);
+SET @iIdActionMakeOffer = 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),
+
+-- set entry thumb
+(@iStandard, @iIdActionSetThumb),
+(@iModerator, @iIdActionSetThumb),
+(@iAdministrator, @iIdActionSetThumb),
+(@iPremium, @iIdActionSetThumb),
+
+-- edit any entry
+(@iModerator, @iIdActionEntryEditAny),
+(@iAdministrator, @iIdActionEntryEditAny),
+
+-- delete any entry
+(@iAdministrator, @iIdActionEntryDeleteAny),
+
+-- make offer
+(@iStandard, @iIdActionMakeOffer),
+(@iModerator, @iIdActionMakeOffer),
+(@iAdministrator, @iIdActionMakeOffer),
+(@iPremium, @iIdActionMakeOffer);
+
+
+-- SEARCH
+SET @iSearchOrder = (SELECT IFNULL(MAX(`Order`), 0) FROM `sys_objects_search`);
+INSERT INTO `sys_objects_search` (`ObjectName`, `Title`, `Order`, `ClassName`, `ClassPath`) VALUES
+('bx_ads', '_bx_ads', @iSearchOrder + 1, 'BxAdsSearchResult', 'modules/boonex/ads/classes/BxAdsSearchResult.php'),
+('bx_ads_cmts', '_bx_ads_cmts', @iSearchOrder + 2, 'BxAdsCmtsSearchResult', 'modules/boonex/ads/classes/BxAdsCmtsSearchResult.php');
+
+
+-- METATAGS
+INSERT INTO `sys_objects_metatags` (`object`, `module`, `table_keywords`, `table_locations`, `table_mentions`, `override_class_name`, `override_class_file`) VALUES
+('bx_ads', 'bx_ads', 'bx_ads_meta_keywords', 'bx_ads_meta_locations', 'bx_ads_meta_mentions', '', '');
+
+
+-- STATS
+SET @iMaxOrderStats = (SELECT IFNULL(MAX(`order`), 0) FROM `sys_statistics`);
+INSERT INTO `sys_statistics` (`module`, `name`, `title`, `link`, `icon`, `query`, `order`) VALUES 
+('bx_ads', 'bx_ads', '_bx_ads', 'page.php?i=ads-home', 'ad col-green2', 'SELECT COUNT(*) FROM `bx_ads_entries` 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_ads_growth', '_bx_ads_chart_growth', 'bx_ads_entries', 'added', '', 'status,status_admin', '', 1, @iMaxOrderCharts + 1, 'BxDolChartGrowth', ''),
+('bx_ads_growth_speed', '_bx_ads_chart_growth_speed', 'bx_ads_entries', '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_ads_administration', 'Sql', 'SELECT * FROM `bx_ads_entries` WHERE 1 ', 'bx_ads_entries', 'id', 'added', 'status_admin', '', 20, NULL, 'start', '', 'title,text', '', 'like', 'reports', '', 192, 'BxAdsGridAdministration', 'modules/boonex/ads/classes/BxAdsGridAdministration.php'),
+('bx_ads_common', 'Sql', 'SELECT * FROM `bx_ads_entries` WHERE 1 ', 'bx_ads_entries', 'id', 'added', 'status', '', 20, NULL, 'start', '', 'title,text', '', 'like', '', '', 2147483647, 'BxAdsGridCommon', 'modules/boonex/ads/classes/BxAdsGridCommon.php');
+
+INSERT INTO `sys_grid_fields` (`object`, `name`, `title`, `width`, `translatable`, `chars_limit`, `params`, `order`) VALUES
+('bx_ads_administration', 'checkbox', '_sys_select', '2%', 0, '', '', 1),
+('bx_ads_administration', 'switcher', '_bx_ads_grid_column_title_adm_active', '8%', 0, '', '', 2),
+('bx_ads_administration', 'reports', '_sys_txt_reports_title', '5%', 0, '', '', 3),
+('bx_ads_administration', 'title', '_bx_ads_grid_column_title_adm_title', '25%', 0, '25', '', 4),
+('bx_ads_administration', 'added', '_bx_ads_grid_column_title_adm_added', '20%', 1, '25', '', 5),
+('bx_ads_administration', 'author', '_bx_ads_grid_column_title_adm_author', '20%', 0, '25', '', 6),
+('bx_ads_administration', 'actions', '', '20%', 0, '', '', 7),
+
+('bx_ads_common', 'checkbox', '_sys_select', '2%', 0, '', '', 1),
+('bx_ads_common', 'switcher', '_bx_ads_grid_column_title_adm_active', '8%', 0, '', '', 2),
+('bx_ads_common', 'title', '_bx_ads_grid_column_title_adm_title', '40%', 0, '35', '', 3),
+('bx_ads_common', 'added', '_bx_ads_grid_column_title_adm_added', '15%', 0, '25', '', 4),
+('bx_ads_common', 'status_admin', '_bx_ads_grid_column_title_adm_status_admin', '15%', 0, '16', '', 5),
+('bx_ads_common', 'actions', '', '20%', 0, '', '', 6);
+
+INSERT INTO `sys_grid_actions` (`object`, `type`, `name`, `title`, `icon`, `icon_only`, `confirm`, `order`) VALUES
+('bx_ads_administration', 'bulk', 'delete', '_bx_ads_grid_action_title_adm_delete', '', 0, 1, 1),
+('bx_ads_administration', 'single', 'edit', '_bx_ads_grid_action_title_adm_edit', 'pencil-alt', 1, 0, 1),
+('bx_ads_administration', 'single', 'delete', '_bx_ads_grid_action_title_adm_delete', 'remove', 1, 1, 2),
+('bx_ads_administration', 'single', 'settings', '_bx_ads_grid_action_title_adm_more_actions', 'cog', 1, 0, 3),
+('bx_ads_administration', 'single', 'audit_content', '_bx_ads_grid_action_title_adm_audit_content', 'search', 1, 0, 4),
+
+('bx_ads_common', 'bulk', 'delete', '_bx_ads_grid_action_title_adm_delete', '', 0, 1, 1),
+('bx_ads_common', 'single', 'edit', '_bx_ads_grid_action_title_adm_edit', 'pencil-alt', 1, 0, 1),
+('bx_ads_common', 'single', 'delete', '_bx_ads_grid_action_title_adm_delete', 'remove', 1, 1, 2),
+('bx_ads_common', 'single', 'settings', '_bx_ads_grid_action_title_adm_more_actions', 'cog', 1, 0, 3);
+
+-- GRIDS: licenses
+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_ads_licenses_administration', 'Sql', 'SELECT `tl`.`id` AS `id`, `tl`.`profile_id` AS `profile_id`, `tl`.`entry_id` AS `entry_id`, `te`.`title` AS `entry`, `tl`.`count` AS `count`, `tl`.`order` AS `transaction`, `tl`.`license` AS `license`, `tl`.`added` AS `added` FROM `bx_ads_licenses` AS `tl` LEFT JOIN `bx_ads_entries` AS `te` ON `tl`.`entry_id`=`te`.`id` WHERE 1 ', 'bx_ads_licenses', 'id', 'added', '', '', 20, NULL, 'start', '', 'te`.`title,tl`.`order,tl`.`license', '', 'like', '', '', 192, 'BxAdsGridLicensesAdministration', 'modules/boonex/ads/classes/BxAdsGridLicensesAdministration.php'),
+('bx_ads_licenses', 'Sql', 'SELECT `tl`.`id` AS `id`, `tl`.`profile_id` AS `profile_id`, `tl`.`entry_id` AS `entry_id`, `te`.`title` AS `entry`, `tl`.`count` AS `count`, `tl`.`order` AS `transaction`, `tl`.`license` AS `license`, `tl`.`added` AS `added` FROM `bx_ads_licenses` AS `tl` LEFT JOIN `bx_ads_entries` AS `te` ON `tl`.`entry_id`=`te`.`id` WHERE 1 ', 'bx_ads_licenses', 'id', 'added', '', '', 20, NULL, 'start', '', 'te`.`title,tl`.`order,tl`.`license', '', 'like', '', '', 2147483647, 'BxAdsGridLicenses', 'modules/boonex/ads/classes/BxAdsGridLicenses.php');
+
+INSERT INTO `sys_grid_fields` (`object`, `name`, `title`, `width`, `translatable`, `chars_limit`, `params`, `order`) VALUES
+('bx_ads_licenses_administration', 'profile_id', '_bx_ads_grid_column_title_lcs_profile_id', '20%', 0, '0', '', 1),
+('bx_ads_licenses_administration', 'entry', '_bx_ads_grid_column_title_lcs_entry', '20%', 0, '0', '', 2),
+('bx_ads_licenses_administration', 'count', '_bx_ads_grid_column_title_lcs_count', '5%', 0, '0', '', 3),
+('bx_ads_licenses_administration', 'transaction', '_bx_ads_grid_column_title_lcs_transaction', '20%', 0, '32', '', 4),
+('bx_ads_licenses_administration', 'license', '_bx_ads_grid_column_title_lcs_license', '15%', 0, '8', '', 5),
+('bx_ads_licenses_administration', 'added', '_bx_ads_grid_column_title_lcs_added', '10%', 1, '25', '', 6),
+('bx_ads_licenses_administration', 'actions', '', '10%', 0, '0', '', 7),
+
+('bx_ads_licenses', 'entry', '_bx_ads_grid_column_title_lcs_entry', '25%', 0, '0', '', 1),
+('bx_ads_licenses', 'count', '_bx_ads_grid_column_title_lcs_count', '5%', 0, '0', '', 2),
+('bx_ads_licenses', 'transaction', '_bx_ads_grid_column_title_lcs_transaction', '25%', 0, '32', '', 3),
+('bx_ads_licenses', 'license', '_bx_ads_grid_column_title_lcs_license', '15%', 0, '8', '', 4),
+('bx_ads_licenses', 'added', '_bx_ads_grid_column_title_lcs_added', '20%', 1, '25', '', 5),
+('bx_ads_licenses', 'actions', '', '10%', 0, '0', '', 6);
+
+-- GRIDS: offers
+INSERT INTO `sys_objects_grid` (`object`, `source_type`, `source`, `table`, `field_id`, `field_order`, `field_active`, `paginate_url`, `paginate_per_page`, `paginate_simple`, `paginate_get_start`, `paginate_get_per_page`, `filter_fields`, `filter_fields_translatable`, `filter_mode`, `sorting_fields`, `sorting_fields_translatable`, `visible_for_levels`, `show_total_count`, `override_class_name`, `override_class_file`) VALUES
+('bx_ads_offers', 'Sql', 'SELECT * FROM `bx_ads_offers` WHERE 1 ', 'bx_ads_offers', 'id', 'added', '', '', 20, NULL, 'start', '', 'message', '', 'like', '', '', 2147483647, 1, 'BxAdsGridOffers', 'modules/boonex/ads/classes/BxAdsGridOffers.php'),
+('bx_ads_offers_all', 'Sql', 'SELECT `to`.*, SUM(IF(`to`.`status`=''awaiting'', 1, 0)) AS `offers_awating`, COUNT(`to`.`id`) AS `offers_total`, `te`.`title` AS `content_title` FROM `bx_ads_offers` AS `to` LEFT JOIN `bx_ads_entries` AS `te` ON `to`.`content_id`=`te`.`id` WHERE 1 ', 'bx_ads_offers', 'id', 'added', '', '', 20, NULL, 'start', '', '', '', 'like', '', '', 2147483647, 0, 'BxAdsGridOffersAll', 'modules/boonex/ads/classes/BxAdsGridOffersAll.php');
+
+INSERT INTO `sys_grid_fields` (`object`, `name`, `title`, `width`, `translatable`, `chars_limit`, `params`, `order`) VALUES
+('bx_ads_offers', 'checkbox', '_sys_select', '2%', 0, 0, '', 1),
+('bx_ads_offers', 'author_id', '_bx_ads_grid_column_title_ofr_author_id', '20%', 0, 0, '', 2),
+('bx_ads_offers', 'amount', '_bx_ads_grid_column_title_ofr_amount', '14%', 0, 0, '', 3),
+('bx_ads_offers', 'quantity', '_bx_ads_grid_column_title_ofr_quantity', '5%', 0, 0, '', 4),
+('bx_ads_offers', 'message', '_bx_ads_grid_column_title_ofr_message', '24%', 0, '32', '', 5),
+('bx_ads_offers', 'added', '_bx_ads_grid_column_title_ofr_added', '10%', 0, 0, '', 6),
+('bx_ads_offers', 'status', '_bx_ads_grid_column_title_ofr_status', '5%', 0, 8, '', 7),
+('bx_ads_offers', 'actions', '', '20%', 0, '', '', 8),
+
+('bx_ads_offers_all', 'content_id', '_bx_ads_grid_column_title_ofrs_content_id', '60%', 0, 0, '', 1),
+('bx_ads_offers_all', 'offers_awating', '_bx_ads_grid_column_title_ofrs_offers_awating', '10%', 0, 0, '', 2),
+('bx_ads_offers_all', 'offers_total', '_bx_ads_grid_column_title_ofrs_offers_total', '10%', 0, 0, '', 3),
+('bx_ads_offers_all', 'actions', '', '20%', 0, '', '', 4);
+
+INSERT INTO `sys_grid_actions` (`object`, `type`, `name`, `title`, `icon`, `icon_only`, `confirm`, `order`) VALUES
+('bx_ads_offers', 'single', 'accept', '_bx_ads_grid_action_title_ofr_accept', 'check', 1, 1, 1),
+('bx_ads_offers', 'single', 'decline', '_bx_ads_grid_action_title_ofr_decline', 'times', 1, 1, 2),
+
+('bx_ads_offers_all', 'single', 'view', '_bx_ads_grid_action_title_ofr_view', 'share-square', 1, 0, 1);
+
+-- GRIDS: categories manager
+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_mode`, `sorting_fields`, `visible_for_levels`, `override_class_name`, `override_class_file`) VALUES
+('bx_ads_categories', 'Sql', 'SELECT * FROM `bx_ads_categories` WHERE 1 ', 'bx_ads_categories', 'id', 'order', 'active', '', 20, NULL, 'start', '', 'title,text', 'auto', '', 128, 'BxAdsGridCategories', 'modules/boonex/ads/classes/BxAdsGridCategories.php');
+
+INSERT INTO `sys_grid_fields` (`object`, `name`, `title`, `width`, `translatable`, `chars_limit`, `params`, `order`) VALUES
+('bx_ads_categories', 'order', '', '1%', 0, '', '', 1),
+('bx_ads_categories', 'checkbox', '_sys_select', '1%', 0, '', '', 2),
+('bx_ads_categories', 'switcher', '', '8%', 0, '', '', 3),
+('bx_ads_categories', 'icon', '_bx_ads_grid_column_title_icon', '5%', 0, '', '', 4),
+('bx_ads_categories', 'title', '_bx_ads_grid_column_title_title', '50%', 1, '32', '', 5),
+('bx_ads_categories', 'subcategories', '_bx_ads_grid_column_title_subcategories', '15%', 0, '16', '', 6),
+('bx_ads_categories', 'actions', '', '20%', 0, '', '', 7);
+
+INSERT INTO `sys_grid_actions` (`object`, `type`, `name`, `title`, `icon`, `confirm`, `order`) VALUES
+('bx_ads_categories', 'bulk', 'delete', '_bx_ads_grid_action_title_delete', '', 1, 1),
+('bx_ads_categories', 'single', 'edit', '', 'pencil-alt', 0, 1),
+('bx_ads_categories', 'single', 'delete', '', 'remove', 1, 2),
+('bx_ads_categories', 'independent', 'back', '_bx_ads_grid_action_title_back', '', 0, 1),
+('bx_ads_categories', 'independent', 'add', '_bx_ads_grid_action_title_add', '', 0, 2);
+
+
+-- UPLOADERS
+INSERT INTO `sys_objects_uploader` (`object`, `active`, `override_class_name`, `override_class_file`) VALUES
+('bx_ads_simple', 1, 'BxAdsUploaderSimple', 'modules/boonex/ads/classes/BxAdsUploaderSimple.php'),
+('bx_ads_html5', 1, 'BxAdsUploaderHTML5', 'modules/boonex/ads/classes/BxAdsUploaderHTML5.php'),
+('bx_ads_record_video', 1, 'BxAdsUploaderRecordVideo', 'modules/boonex/ads/classes/BxAdsUploaderRecordVideo.php'),
+('bx_ads_photos_simple', 1, 'BxAdsUploaderSimpleAttach', 'modules/boonex/ads/classes/BxAdsUploaderSimpleAttach.php'),
+('bx_ads_photos_html5', 1, 'BxAdsUploaderHTML5Attach', 'modules/boonex/ads/classes/BxAdsUploaderHTML5Attach.php'),
+('bx_ads_videos_simple', 1, 'BxAdsUploaderSimpleAttach', 'modules/boonex/ads/classes/BxAdsUploaderSimpleAttach.php'),
+('bx_ads_videos_html5', 1, 'BxAdsUploaderHTML5Attach', 'modules/boonex/ads/classes/BxAdsUploaderHTML5Attach.php'),
+('bx_ads_videos_record_video', 1, 'BxAdsUploaderRecordVideoAttach', 'modules/boonex/ads/classes/BxAdsUploaderRecordVideoAttach.php'),
+('bx_ads_files_simple', 1, 'BxAdsUploaderSimpleAttach', 'modules/boonex/ads/classes/BxAdsUploaderSimpleAttach.php'),
+('bx_ads_files_html5', 1, 'BxAdsUploaderHTML5Attach', 'modules/boonex/ads/classes/BxAdsUploaderHTML5Attach.php');
+
+
+-- LIVE UPDATES
+INSERT INTO `sys_objects_live_updates`(`name`, `frequency`, `service_call`, `active`) VALUES
+('bx_ads', 1, 'a:3:{s:6:"module";s:6:"bx_ads";s:6:"method";s:16:"get_live_updates";s:6:"params";a:4:{i:0;s:8:"awaiting";i:1;a:2:{s:11:"menu_object";s:18:"sys_toolbar_member";s:9:"menu_item";s:7:"account";}i:2;a:2:{s:11:"menu_object";s:25:"sys_account_notifications";s:9:"menu_item";s:24:"notifications-ads-offers";}i:3;s:7:"{count}";}}', 1);
+
+
+-- ALERTS
+INSERT INTO `sys_alerts_handlers` (`name`, `class`, `file`, `service_call`) VALUES 
+('bx_ads', 'BxAdsAlertsResponse', 'modules/boonex/ads/classes/BxAdsAlertsResponse.php', '');
+SET @iHandler := LAST_INSERT_ID();
+
+INSERT INTO `sys_alerts` (`unit`, `action`, `handler_id`) VALUES
+('system', 'save_setting', @iHandler),
+('profile', 'approve', @iHandler),
+('profile', 'activate', @iHandler),
+('profile', 'disapprove', @iHandler),
+('profile', 'suspend', @iHandler),
+('profile', 'delete', @iHandler),
+
+('bx_ads_videos_mp4', 'transcoded', @iHandler);
+
+
+-- CRON
+INSERT INTO `sys_cron_jobs` (`name`, `time`, `class`, `file`, `service_call`) VALUES
+('bx_ads_offers', '0 * * * *', 'BxAdsCronOffers', 'modules/boonex/ads/classes/BxAdsCronOffers.php', ''),
+('bx_ads_pruning', '0 0 * * *', 'BxAdsCronPruning', 'modules/boonex/ads/classes/BxAdsCronPruning.php', ''),
+('bx_ads_publishing', '* * * * *', 'BxAdsCronPublishing', 'modules/boonex/ads/classes/BxAdsCronPublishing.php', '');
+
+
+-- EMAIL TEMPLATES
+INSERT INTO `sys_email_templates` (`Module`, `NameSystem`, `Name`, `Subject`, `Body`) VALUES 
+('bx_ads', '_bx_ads_et_txt_name_interested', 'bx_ads_interested', '_bx_ads_et_txt_subject_interested', '_bx_ads_et_txt_body_interested'),
+('bx_ads', '_bx_ads_et_txt_name_purchased', 'bx_ads_purchased', '_bx_ads_et_txt_subject_purchased', '_bx_ads_et_txt_body_purchased'),
+('bx_ads', '_bx_ads_et_txt_name_shipped', 'bx_ads_shipped', '_bx_ads_et_txt_subject_shipped', '_bx_ads_et_txt_body_shipped'),
+('bx_ads', '_bx_ads_et_txt_name_received', 'bx_ads_received', '_bx_ads_et_txt_subject_received', '_bx_ads_et_txt_body_received'),
+('bx_ads', '_bx_ads_et_txt_name_offer_added', 'bx_ads_offer_added', '_bx_ads_et_txt_subject_offer_added', '_bx_ads_et_txt_body_offer_added'),
+('bx_ads', '_bx_ads_et_txt_name_offer_accepted', 'bx_ads_offer_accepted', '_bx_ads_et_txt_subject_offer_accepted', '_bx_ads_et_txt_body_offer_accepted'),
+('bx_ads', '_bx_ads_et_txt_name_offer_declined', 'bx_ads_offer_declined', '_bx_ads_et_txt_subject_offer_declined', '_bx_ads_et_txt_body_offer_declined'),
+('bx_ads', '_bx_ads_et_txt_name_offer_canceled', 'bx_ads_offer_canceled', '_bx_ads_et_txt_subject_offer_canceled', '_bx_ads_et_txt_body_offer_canceled');

+ 52 - 0
modules/boonex/ads/updates/13.0.2_13.0.3/source/js/studio.js

@@ -0,0 +1,52 @@
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Ads Ads
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+function BxAdsStudio(oOptions) {
+    this._sActionsUri = oOptions.sActionUri;
+    this._sActionsUrl = oOptions.sActionUrl;
+    this._sObjName = oOptions.sObjName == undefined ? 'oBxAdsStudio' : oOptions.sObjName;
+    this._sAnimationEffect = oOptions.sAnimationEffect == undefined ? 'slide' : oOptions.sAnimationEffect;
+    this._iAnimationSpeed = oOptions.iAnimationSpeed == undefined ? 'slow' : oOptions.iAnimationSpeed;
+    this._aHtmlIds = oOptions.aHtmlIds == undefined ? {} : oOptions.aHtmlIds;
+}
+
+BxAdsStudio.prototype.onChangeClone = function(oElement) {
+    var sClass = 'bx-form-element-wrapper';
+    var oName = $(oElement).parents('form:first').find("#bx-form-element-type_title input");
+
+    if($(oElement).prop('checked'))
+        oName.prop('disabled', false).parents('.' + sClass + ':first').show();
+    else
+        oName.prop('disabled', true).parents('.' + sClass + ':first').hide();
+};
+
+BxAdsStudio.prototype.loadingInButton = function(e, bShow) {
+    if($(e).length)
+        bx_loading_btn($(e), bShow);
+    else
+        bx_loading($('body'), bShow);	
+};
+
+BxAdsStudio.prototype.loadingInBox = function(e, bShow) {
+    var oParent = $(e).length ? $(e).parents('.bx-base-text-poll:first') : $('body'); 
+    bx_loading(oParent, bShow);
+};
+
+BxAdsStudio.prototype.loadingInBlock = function(e, bShow) {
+    var oParent = $(e).length ? $(e).parents('.bx-db-container:first') : $('body'); 
+    bx_loading(oParent, bShow);
+};
+
+BxAdsStudio.prototype._getDefaultData = function() {
+    var oDate = new Date();
+    return jQuery.extend({}, this._oRequestParams, {_t:oDate.getTime()});
+};
+
+/** @} */

+ 51 - 0
modules/boonex/attendant/updates/13.0.0_13.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' => 'Attendant',
+    'version_from' => '13.0.0',
+    'version_to' => '13.0.1',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '13.0.0-B2'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/attendant/updates/update_13.0.0_13.0.1/',
+    'home_uri' => 'attendant_update_1300_1301',
+
+    'module_dir' => 'boonex/attendant/',
+    'module_uri' => 'attendant',
+
+    'db_prefix' => 'bx_attendant_',
+    'class_prefix' => 'BxAttendant',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 0,
+        'update_files' => 1,
+        'update_languages' => 0,
+        'clear_db_cache' => 0,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Attendant',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

+ 13 - 0
modules/boonex/attendant/updates/13.0.0_13.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 BxAttendantUpdater extends BxDolStudioUpdater
+{
+    function __construct($aConfig)
+    {
+        parent::__construct($aConfig);
+    }
+}

+ 213 - 0
modules/boonex/attendant/updates/13.0.0_13.0.1/source/classes/BxAttendantModule.php

@@ -0,0 +1,213 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Attendant Attendant
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+define('BX_ATTENDANT_ON_PROFILE_CREATION_METHOD', 'browse_recommended');
+define('BX_ATTENDANT_ON_PROFILE_CREATION_EVENT_AFTER_REGISTRATION', 'registration');
+define('BX_ATTENDANT_ON_PROFILE_CREATION_EVENT_AFTER_CONFIRMATION', 'confirmation');
+
+class BxAttendantModule extends BxDolModule
+{
+    function __construct(&$aModule)
+    {
+        parent::__construct($aModule);
+    }
+
+    public function actionRecomendedPopup($sModule, $sEvent, $iObjectId)
+    {
+        $sRv = '';
+        $aModules = explode(',', getParam('bx_attendant_on_profile_creation_modules'));
+        $aModuleData = array();
+        foreach($aModules as $sModuleName){
+
+            if(BxDolRequest::serviceExists($sModuleName, BX_ATTENDANT_ON_PROFILE_CREATION_METHOD)){
+                $aTmp = BxDolService::call($sModuleName, BX_ATTENDANT_ON_PROFILE_CREATION_METHOD, ['unit_view' => 'showcase', 'empty_message' => false, "ajax_paginate" => false]);
+
+                if (isset($aTmp['content'])){
+                    $sTmp = $aTmp['content'];
+                    $sTmp = str_replace('bx_conn_action', 'bx_attendant_conn_action', $sTmp);
+                    $aModuleData[$sModuleName] = $sTmp;
+                }
+            }
+        }
+        $sRv = $this->_oTemplate->popup($aModuleData);
+        
+        bx_alert('bx_attendant', 'show_popup', bx_get_logged_profile_id(), 0, ['module' => $sModule, 'event' => $sEvent, 'object_id' => $iObjectId, 'result' => &$sRv]);
+        
+        echo $sRv;
+    }
+    
+    /**
+     * Service methods
+     */
+    
+    /**
+     * @page service Service Calls
+     * @section bx_attendant Attendant
+     * @subsection bx_attendant-other Other
+     * @subsubsection bx_attendant-on-profile get_profile_modules
+     * 
+     * @code bx_srv('bx_attendant', 'get_profile_modules', [...]); @endcode
+     * 
+     * Get list of avaliable modules for on_profile_creation event
+     * 
+     * @return an array with avaliable modules. 
+     * 
+     * @see BxAttendantModule::serviceGetProfileModules
+     */
+    /** 
+     * @ref bx_attendant-get_profile_modules "get_profile_modules"
+     */
+    public function serviceGetProfileModules()
+    {
+        $aResult = array();
+        $BxDolModuleQuery = BxDolModuleQuery::getInstance();
+        $aModules = $BxDolModuleQuery->getModulesBy(array('type' => 'modules', 'active' => 1));
+        foreach($aModules as $aModule){
+            if(BxDolRequest::serviceExists($aModule['name'], BX_ATTENDANT_ON_PROFILE_CREATION_METHOD)){
+                $aResult[$aModule['name']] = $aModule['title'];
+            }
+        }
+        return $aResult;
+    }
+    
+    
+    /**
+     * @page service Service Calls
+     * @section bx_attendant Attendant
+     * @subsection bx_attendant-other Other
+     * @subsubsection bx_attendant-on-profile get_options_redirect_after_show
+     * 
+     * @code bx_srv('bx_attendant', 'get_options_redirect_after_show', [...]); @endcode
+     * 
+     * Get list avaliable redirct pages
+     * 
+     * @return an array with avaliable redirct pages. 
+     * 
+     * @see BxAttendantModule::serviceGetOptionsRedirectAfterShow
+     */
+    /** 
+     * @ref bx_attendant-get_options_redirect_after_show "get_options_redirect_after_show"
+     */
+    public function serviceGetOptionsRedirectAfterShow()
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $aResult = [];
+        $aChoices = ['noredirect', 'homepage', 'profile', 'custom'];
+        foreach($aChoices as $sChoice) 
+            $aResult[] = array('key' => $sChoice, 'value' => _t('_bx_attendant_option_redirect_show_' . $sChoice));
+
+        return $aResult;
+    }
+    
+    /**
+     * @page service Service Calls
+     * @section bx_attendant Attendant
+     * @subsection bx_attendant-other Other
+     * @subsubsection bx_attendant-on-profile get_popup_with_recommended_on_event_show
+     * 
+     * @code bx_srv('bx_attendant', 'get_popup_with_recommended_on_event_show', [...]); @endcode
+     * 
+     * Get list of events for on_profile_creation show
+     * 
+     * @return an array with avaliable events. 
+     * 
+     * @see BxAttendantModule::serviceGetPopupWithRecommendedOnEventShow
+     */
+    /** 
+     * @ref bx_attendant-get_popup_with_recommended_on_event_show "get_popup_with_recommended_on_event_show"
+     */
+    public function serviceGetPopupWithRecommendedOnEventShow()
+    {
+        $aResult = array();
+        $aChoices = array(BX_ATTENDANT_ON_PROFILE_CREATION_EVENT_AFTER_CONFIRMATION, BX_ATTENDANT_ON_PROFILE_CREATION_EVENT_AFTER_REGISTRATION);
+        foreach($aChoices as $sChoice)
+            $aResult[$sChoice] = _t('_bx_attendant_popup_event_after_' . $sChoice);
+        
+        return $aResult;
+    }
+    
+    /**
+     * @page service Service Calls
+     * @section bx_attendant Attendant
+     * @subsection bx_attendant-other Other
+     * @subsubsection bx_attendant-get_profile_modules handle_action_view
+     * 
+     * @code bx_srv('bx_attendant', 'handle_action_view', [...]); @endcode
+     * 
+     * Get Include for injection
+     * 
+     * @return an include code
+     * 
+     * @see BxAttendantModule::HandleActionView
+     */
+    /** 
+     * @ref bx_attendant-handle_action_view "handle_action_view"
+     */
+    public function serviceHandleActionView()
+    {
+        $sRv = $this->_oTemplate->init();
+        
+        if (!isLogged())
+            return;
+        
+        $aEvents = $this->_oDb->getEvents(array('type' => 'active_by_action_and_profile_id', 'action' => 'view', 'profile_id' => bx_get_logged_profile_id()));
+        foreach($aEvents as $aEvent){
+            //$oRv = call_user_func_array(array($this, $aEvent['method']), array($aEvent['object_id']));
+            $oRv = $this->processPopupOnEvent($aEvent);
+            if ($oRv !== false){
+                $sRv .= $oRv;
+                $this->_oDb->setEventProcessed($aEvent['id']);
+            }
+        }
+        
+        return $sRv;
+    }
+    
+    public function serviceHandleActionNonView()
+    {
+       //for some other actions fex cron - not implemented
+    }
+    
+    public function addEvent($sAction, $iObjectId, $sModule, $sEvent, $iProfileId)
+    {
+        $this->_oDb->addEvent($sAction, $iObjectId, $sModule, $sEvent, $iProfileId);
+    }
+    
+    public function initPopupByEvent($iObjectId, $sModule, $sEvent, $iProfileId)
+    {
+        $this->addEvent('view', $iObjectId, $sModule, $sEvent, $iProfileId);
+    }
+    
+    public function processPopupOnEvent($aEvent)
+    {
+        $sRv = '';
+        $sDefaultEvent = getParam('bx_attendant_on_profile_event_list');
+        $oProfile = BxDolProfile::getInstance($aEvent['profile_id']);
+        $oAccount = $oProfile ? $oProfile->getAccountObject() : null;
+        $bNeedRaiseEvent = false;
+        if ($aEvent['event'] == 'add' && $aEvent['module'] == 'profile'){
+            if (getParam('bx_attendant_on_profile_creation_modules') != '' && ($sDefaultEvent == BX_ATTENDANT_ON_PROFILE_CREATION_EVENT_AFTER_REGISTRATION || ($sDefaultEvent == BX_ATTENDANT_ON_PROFILE_CREATION_EVENT_AFTER_CONFIRMATION  && $oAccount != null &&  $oAccount->isConfirmed()))){
+                if ($oProfile->getModule() != 'system'){
+                    $bNeedRaiseEvent = true;
+                }
+            }
+        }
+        else{
+            bx_alert('bx_attendant', 'before_show_popup', bx_get_logged_profile_id(), 0, ['module' => $aEvent['module'], 'event' => $aEvent['event'], 'object_id' => $aEvent['object_id'], 'result' => &$bNeedRaiseEvent]);
+        }
+        if ($bNeedRaiseEvent)
+            return getParam('bx_attendant_on_profile_creation_modules').'<script>oBxAttendant.showPopup("' . $aEvent['module'] . '", "' . $aEvent['event'] . '", ' . $aEvent['object_id'] . ')</script>';
+        else
+            return false;
+    }
+}
+
+/** @} */

+ 77 - 0
modules/boonex/attendant/updates/13.0.0_13.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    Attendant Attendant
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_attendant',
+    'title' => 'Attendant',
+    'note' => 'Attendant module.',
+    'version' => '13.0.1',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '13.0.0-B2'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/attendant/',
+    'home_uri' => 'attendant',
+
+    'db_prefix' => 'bx_attendant_',
+    'class_prefix' => 'BxAttendant',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Attendant',
+
+    /**
+     * 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(),
+);
+
+/** @} */

+ 51 - 0
modules/boonex/convos/updates/13.0.1_13.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' => 'Conversations',
+    'version_from' => '13.0.1',
+    'version_to' => '13.0.2',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '13.0.0-B2'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/convos/updates/update_13.0.1_13.0.2/',
+    'home_uri' => 'convos_update_1301_1302',
+
+    'module_dir' => 'boonex/convos/',
+    'module_uri' => 'convos',
+
+    'db_prefix' => 'bx_convos_',
+    'class_prefix' => 'BxCnv',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 0,
+        'update_files' => 1,
+        'update_languages' => 0,
+        'clear_db_cache' => 0,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Conversations',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

+ 13 - 0
modules/boonex/convos/updates/13.0.1_13.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 BxCnvUpdater extends BxDolStudioUpdater
+{
+    function __construct($aConfig)
+    {
+        parent::__construct($aConfig);
+    }
+}

+ 565 - 0
modules/boonex/convos/updates/13.0.1_13.0.2/source/classes/BxCnvModule.php

@@ -0,0 +1,565 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Convos Convos
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+define('BX_CNV_FOLDER_INBOX', 1);
+define('BX_CNV_FOLDER_DRAFTS', 2);
+define('BX_CNV_FOLDER_SPAM', 3);
+define('BX_CNV_FOLDER_TRASH', 4);
+
+/**
+ * Conversations module
+ */
+class BxCnvModule extends BxBaseModTextModule
+{
+    function __construct(&$aModule)
+    {
+        parent::__construct($aModule);
+    }
+
+    public function sortCollaborators ($aCollaborators, $iProfileIdLastComment, $iProfileIdAuthor, $iProfileIdCurrent = 0)
+    {
+        if (!$iProfileIdCurrent)
+            $iProfileIdCurrent = bx_get_logged_profile_id();
+
+        $aMoveUp = array($iProfileIdCurrent, $iProfileIdLastComment, $iProfileIdAuthor);
+
+        asort($aCollaborators, SORT_NUMERIC);
+
+        foreach ($aMoveUp as $iProfileId) {
+            if (!isset($aCollaborators[$iProfileId]))
+                continue;
+
+            $a = array($iProfileId => $aCollaborators[$iProfileId]);
+            unset($aCollaborators[$iProfileId]);
+            $aCollaborators = $a + $aCollaborators;
+        }
+
+        return $aCollaborators;
+    }
+
+    public function setModuleSubmenu ($iCurrentFolderId = 0)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $aMapFolderId2MenuName = array (
+            BX_CNV_FOLDER_INBOX => 'convos-folder-inbox',
+            BX_CNV_FOLDER_DRAFTS => 'convos-drafts',
+            BX_CNV_FOLDER_SPAM => 'convos-spam',
+            BX_CNV_FOLDER_TRASH => 'convos-trash',
+        );
+
+        $oMenuSubmenu = BxDolMenu::getObjectInstance('sys_site_submenu');
+        if (!$oMenuSubmenu)
+            return;
+
+        $oMenuSubmenu->setObjectSubmenu($CNF['OBJECT_MENU_SUBMENU'], array (
+            'title' => _t('_bx_cnv'),
+            'link' => BX_DOL_URL_ROOT . $CNF['URL_HOME'],
+            'icon' => '',
+        ));
+
+        $oMenuModule = BxDolMenu::getObjectInstance($CNF['OBJECT_MENU_SUBMENU']);
+        if ($oMenuModule && isset($aMapFolderId2MenuName[$iCurrentFolderId]))
+            $oMenuModule->setSelected($this->_aModule['name'], $aMapFolderId2MenuName[$iCurrentFolderId]);
+    }
+
+    /**
+     * Mark conversation as unread for the current user
+     * @return error string on error, or empty string on success
+     */
+    public function markUnread ($iContentId)
+    {
+        $aContentInfo = $this->_oDb->getContentInfoById($iContentId);
+        if (!$aContentInfo)
+            return _t('_sys_request_page_not_found_cpt');
+
+        if (CHECK_ACTION_RESULT_ALLOWED !== ($sMsg = $this->checkAllowedView($aContentInfo)))
+            return $sMsg;
+
+        if (!$this->_oDb->updateReadComments(bx_get_logged_profile_id(), (int)$iContentId, -1))
+            return _t('_error occured');
+
+        return '';
+    }
+
+    /**
+     * Delete conversation for current user by content id, before deletetion it checks user permission to delete convos
+     * @return error string on error, or empty string on success
+     */
+    public function deleteConvo ($iContentId)
+    {
+        $aContentInfo = $this->_oDb->getContentInfoById($iContentId);
+        if (!$aContentInfo)
+            return _t('_sys_request_page_not_found_cpt');
+
+        if (CHECK_ACTION_RESULT_ALLOWED !== ($sMsg = $this->checkAllowedDelete($aContentInfo)))
+            return $sMsg;
+
+        if (!$this->_oDb->moveConvo((int)$iContentId, bx_get_logged_profile_id(), BX_CNV_FOLDER_TRASH))
+            return _t('_error occured');
+
+        return '';
+    }
+
+    /**
+     * Delete whole conversation for all users by content id
+     * @return error string on error, or empty string on success
+     */
+    public function deleteConvoForever ($iContentId)
+    {
+        return $this->_oDb->deleteConvo((int)$iContentId);
+    }
+
+    public function actionMarkUnread($iContentId)
+    {
+        header('Content-Type:text/plain; charset=utf-8');
+
+        if ($s = $this->markUnread ($iContentId)) {
+            echo $s;
+            exit;
+        }
+
+        echo BX_DOL_URL_ROOT . $this->_oConfig->CNF['URL_HOME'];
+        exit;
+    }
+
+    public function actionDelete($iContentId)
+    {
+        header('Content-Type:text/plain; charset=utf-8');
+
+        if ($s = $this->deleteConvo ($iContentId)) {
+            echo $s;
+            exit;
+        }
+
+        echo BX_DOL_URL_ROOT . $this->_oConfig->CNF['URL_HOME'];
+        exit;
+    }
+
+    /**
+     * Display convos in folder
+     */
+    public function actionFolder ($iFolderId)
+    {
+        $oTemplate = BxDolTemplate::getInstance();
+
+        $aFolder = $this->_oDb->getFolder((int)$iFolderId);
+        $oPage = BxDolPage::getObjectInstance('bx_convos_home');
+
+        if (!$aFolder || !$oPage) {
+            $this->_oTemplate->displayPageNotFound();
+            exit;
+        }
+
+        // add replaceable markers
+        $oPage->addMarkers(array(
+            'folder_id' => (int)$iFolderId,
+            'folder' => _t($aFolder['name']),
+        ));
+
+        $s = $oPage->getCode();
+
+        $this->_oTemplate = BxDolTemplate::getInstance();
+        $this->_oTemplate->setPageNameIndex (BX_PAGE_DEFAULT);
+        $this->_oTemplate->setPageContent ('page_main_code', $s);
+        $_GET['i']='convos-folder'; //#1148
+        $this->_oTemplate->getPageCode();
+    }
+
+    /**
+     * Get possible recipients for start conversation form
+     */
+    public function actionAjaxGetRecipients ()
+    {
+        $sTerm = bx_get('term');
+
+        $a = BxDolService::call('system', 'profiles_search', array($sTerm), 'TemplServiceProfiles');
+
+        header('Content-Type:text/javascript; charset=utf-8');
+        echo(json_encode($a));
+    }
+
+    public function serviceGetSafeServices()
+    {
+        return array (
+            // other
+            'ModuleIcon' => '',
+            'GetLink' => '',
+            // forms
+            'GetCreatePostForm' => '',
+            'EntityEdit' => '',
+            'EntityDelete' => '',
+            // page blocks
+            'EntityTextBlock' => '',
+            'EntityInfo' => '',
+            'EntityComments' => '',
+            'EntityAttachments' => '',
+            // menu
+            'EntityAllActions' => '',
+            'EntityActions' => '',
+            'MyEntriesActions' => '',
+            // own methods
+            'ConversationsInFolder' => '',
+        );
+    }
+
+    public function serviceIsAllowedContact($iProfileId)
+    {
+        return $this->checkAllowedContact($iProfileId) === CHECK_ACTION_RESULT_ALLOWED;
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_convos Conversations
+     * @subsection bx_convos-page_blocks Page Blocks
+     * @subsubsection bx_convos-conversations_in_folder conversations_in_folder
+     * 
+     * @code bx_srv('bx_convos', 'conversations_in_folder', [...]); @endcode
+     * 
+     * Display conversations in particulr folder for currently logged-in user
+     * @param $iFolderId folder ID
+     * 
+     * @see BxCnvModule::serviceConversationsInFolder
+     */
+    /** 
+     * @ref bx_convos-conversations_in_folder "conversations_in_folder"
+     */
+    public function serviceConversationsInFolder ($iFolderId = BX_CNV_FOLDER_INBOX)
+    {
+        $oGrid = BxDolGrid::getObjectInstance($this->_oConfig->CNF['OBJECT_GRID']);
+        if (!$oGrid)
+            return false;
+
+        $aFolder = $this->_oDb->getFolder((int)$iFolderId);
+        if (!$aFolder)
+            return false;
+
+        $this->setModuleSubmenu ((int)$iFolderId);
+
+        // TODO: incorporate markers into custom class, so replace will work in search and so on
+        $oGrid->addMarkers(array(
+            'folder_id' => (int)$iFolderId,
+            'profile_id' => bx_get_logged_profile_id(),
+        ));
+
+        $this->_oTemplate->addCss(array('manage_tools.css'));
+        $this->_oTemplate->addJs(array('manage_tools.js'));
+        $this->_oTemplate->addJsTranslation(array('_sys_grid_search'));
+        
+        return $this->_oTemplate->getJsCode('manage_tools', array('sObjNameGrid' => $this->_oConfig->CNF['OBJECT_GRID'])) . $oGrid->getCode();
+    }
+
+    public function serviceMessagesPreviews ($iProfileId = 0, $bEmptyMessage = true)
+    {
+        if (!$iProfileId)
+            $iProfileId = bx_get_logged_profile_id();
+
+        $a = $this->_oDb->getMessagesPreviews($iProfileId, 0, (int)getParam('bx_convos_preview_messages_num'));
+        if((empty($a) || !is_array($a)) && !$bEmptyMessage)
+            return '';
+
+        return $this->_oTemplate->getMessagesPreviews($a);
+    }
+
+    /**
+     * Returns preview of profile's conversations with statistic for React Jot
+     * @param int $iProfileId
+     * @param int $iStart
+     * @param int $iPerPage
+     * @param int $iFolderId
+     * @return mixed
+     */
+    public function serviceGetMessagesPreviews ($iProfileId = 0, $iStart = 0, $iPerPage = 10, $iFolderId = BX_CNV_FOLDER_INBOX)
+    {
+        if (!$iProfileId)
+            $iProfileId = bx_get_logged_profile_id();
+
+        return $this->_oDb->getMessagesPreviews($iProfileId, (int)$iStart, (int)$iPerPage, $iFolderId);
+    }
+
+    /**
+     * Get number of unread messages for spme profile
+     * @param $iProfileId - profile to get unread messages for, if omitted then currently logged is profile is used
+     * @return integer
+     */
+    public function serviceGetUnreadMessagesNum ($iProfileId = 0)
+    {
+        if (!$iProfileId)
+            $iProfileId = bx_get_logged_profile_id();
+
+        return $this->_oDb->getUnreadMessagesNum((int)$iProfileId);
+    }
+
+    public function serviceGetLiveUpdates($aMenuItemParent, $aMenuItemChild, $iCount = 0)
+    {
+        $iProfileId = (int)bx_get_logged_profile_id();
+        $iCountNew = $this->_oDb->getUnreadMessagesNum($iProfileId);
+        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.
+    	);
+    }
+
+    /**
+     * Update last comment time and author
+     */
+    public function serviceTriggerCommentPost ($iContentId, $iProfileId, $iCommentId, $iTimestamp = 0, $sCommentText = '')
+    {
+        $CNF = &$this->_oConfig->CNF;
+        
+        if (!(int)$iContentId)
+            return false;
+        $aContentInfo = $this->_oDb->getContentInfoById((int)$iContentId);
+        if (!$aContentInfo)
+            return false;
+
+        // add author to the list of collaborators when somebody replies
+        // if author is removed from collaborators
+        // of if authot placed message to trash
+        $aCollaborators = $this->_oDb->getCollaborators($aContentInfo[$CNF['FIELD_ID']]);
+        if (!isset($aCollaborators[$aContentInfo[$CNF['FIELD_AUTHOR']]]) || BX_CNV_FOLDER_TRASH == $this->_oDb->getConversationFolder($aContentInfo[$CNF['FIELD_ID']], $aContentInfo[$CNF['FIELD_AUTHOR']])) {
+            $oFormsHelper = $this->serviceFormsHelper ();
+            $oForm = $oFormsHelper->getObjectFormEdit();
+            $oForm->updateParticipants($aContentInfo[$CNF['FIELD_ID']], BX_CNV_FOLDER_INBOX, false, array($aContentInfo[$CNF['FIELD_AUTHOR']]));
+        }
+
+
+        $oCmts = BxDolCmts::getObjectInstance($CNF['OBJECT_COMMENTS'], $iContentId);
+        if(!$oCmts)
+            return false;
+            
+        if (!$iTimestamp)
+            $iTimestamp = time();
+
+        if ($iProfileId == bx_get_logged_profile_id())
+            $this->_oDb->updateReadComments($iProfileId, $aContentInfo[$CNF['FIELD_ID']], $aContentInfo[$CNF['FIELD_COMMENTS']]);
+
+        if (!$this->_oDb->updateLastCommentTimeProfile((int)$iContentId, (int)$iProfileId, (int)$iCommentId, $iTimestamp))
+            return false;
+
+        // send notification to all collaborators
+        if ($oProfile = BxDolProfile::getInstance($iProfileId)) {
+            foreach ($aCollaborators as $iCollaborator => $iReadComments) {
+                if ($iCollaborator == $iProfileId)
+                    continue;
+                sendMailTemplate('bx_cnv_new_reply', 0, $iCollaborator, array(
+                    'SenderDisplayName' => $oProfile->getDisplayName(),
+                    'SenderUrl' => $oProfile->getUrl(),
+                    'PageUrl' => $oCmts->getItemUrl($iCommentId),
+                    'PageTitle' => $oCmts->getObjectTitle(),
+                    'Message' => $sCommentText,
+                ), BX_EMAIL_NOTIFY, true);
+            }
+        }
+
+        return true;
+    }
+
+    /**
+     * Create entry form
+     * @return HTML string
+     */
+    public function serviceEntityCreate ($sParams = false)
+    {
+        $sProfilesIds = bx_get('profiles');
+        if($sProfilesIds !== false) {
+            $sDiv = ',';
+            $aIds = explode($sDiv, $sProfilesIds);
+
+            $aIdsAllowed = array();
+            foreach($aIds as $iId)
+                if($this->checkAllowedContact($iId) === CHECK_ACTION_RESULT_ALLOWED)
+                    $aIdsAllowed[] = $iId;
+
+            if(empty($aIdsAllowed))
+                return MsgBox(_t('_sys_txt_access_denied'));
+            
+            bx_set('profiles', implode($sDiv, $aIdsAllowed));
+        }
+
+        return parent::serviceEntityCreate();
+    }
+
+    /**
+     * Entry collaborators block
+     */
+    public function serviceEntityCollaborators ($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->entryCollaborators ($aContentInfo, 5, 'right');
+    }
+
+    /**
+     * No social sharing for private conversations
+     */
+    public function serviceEntitySocialSharing ($mixedContent = false, $aParams = array())
+    {
+        return '';
+    }
+
+    /**
+     * Delete content entry
+     * @param $iContentId content id 
+     * @return error message or empty string on success
+     */
+    public function serviceDeleteEntity ($iContentId, $sFuncDelete = 'deleteData')
+    {
+        return $this->_oDb->deleteConvo($iContentId);
+    }
+    
+    /**
+     * Delete profile from all conversation (when profile is delete without content)
+     * @param $iProfileId profile id 
+     * @return number of deleted items
+     */    
+    public function serviceRemoveCollaboratorFromAllConversations ($iProfileId)
+    {
+        return $this->_oDb->removeCollaboratorFromAllConversations((int)$iProfileId);
+    }
+    
+    /**
+     * Delete all content by profile (when profile is delete with content)
+     * @param $iProfileId profile id 
+     * @return number of deleted items
+     */
+    public function serviceDeleteEntitiesByAuthor ($iProfileId)
+    {
+        $a = $this->_oDb->getEntriesByAuthor((int)$iProfileId);
+        if (!$a)
+            return 0;
+
+        $iCount = 0;
+        foreach ($a as $aContentInfo)
+            $iCount += ('' == $this->serviceDeleteEntity($aContentInfo[$this->_oConfig->CNF['FIELD_ID']]) ? 1 : 0);
+
+        return $iCount;
+    }
+    
+    /**
+     * No moderators for personal convos
+     */
+    public function _isModerator ($isPerformAction = false)
+    {
+        return false;
+    }
+
+    /**
+     * No thumbs for convos
+     */
+    public function checkAllowedSetThumb ($iContentId = 0)
+    {
+        return _t('_sys_txt_access_denied');
+    }
+
+    /**
+     * There is no 'moderator' access in convos
+     */
+    public function checkAllowedEditAnyEntry ($isPerformAction = false)
+    {
+    	return _t('_sys_txt_access_denied');
+    }
+
+    public function checkAllowedEditAnyEntryForProfile ($isPerformAction = false, $iProfileId = false)
+    {
+    	return _t('_sys_txt_access_denied');
+    }
+	
+	public function checkAllowedDeleteAnyEntryForProfile ($isPerformAction = false, $iProfileId = false)
+    {
+        return _t('_sys_txt_access_denied');
+    }
+
+    public function checkAllowedEdit ($aDataEntry, $isPerformAction = false)
+    {       
+        if ($aDataEntry[$this->_oConfig->CNF['FIELD_ALLOW_EDIT']] && $this->isCollaborator($aDataEntry, bx_get_logged_profile_id()))
+            return CHECK_ACTION_RESULT_ALLOWED;
+
+        return parent::checkAllowedEdit ($aDataEntry, $isPerformAction);
+    }
+    
+    /**
+     * Conversations can be deleted by author and/or collaborators only.
+     * Admins can't delete conversations, since it's designed for participant only, it's moved to trash actually, also it's private content.
+     */
+    public function checkAllowedDelete (&$aDataEntry, $isPerformAction = false)
+    {
+        if ($aDataEntry[$this->_oConfig->CNF['FIELD_AUTHOR']] == $this->_iProfileId || $this->isCollaborator($aDataEntry, bx_get_logged_profile_id()))
+            return CHECK_ACTION_RESULT_ALLOWED;
+
+        if ($this->_isModerator($isPerformAction))
+            return _t('_sys_txt_access_denied');
+
+        return parent::checkAllowedDelete ($aDataEntry, $isPerformAction);
+    }
+
+    /**
+     * Only collaborators can view convo
+     */
+    public function checkAllowedView ($aDataEntry, $isPerformAction = false)
+    {
+        return $this->serviceCheckAllowedViewForProfile ($aDataEntry, $isPerformAction);
+    }
+
+    /**
+     * Checks whether contact is allowed.
+     * @param integer $iProfileId - recipient profile ID
+     * @param boolean $isPerformAction - perform or just check the action
+     * @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 checkAllowedContact($iProfileId, $isPerformAction = false)
+    {
+        $oProfile = BxDolProfile::getInstance($iProfileId);
+        if(!$oProfile)
+            return _t('_sys_txt_access_denied');
+
+        $mixedResult = $oProfile->checkAllowedProfileContact();
+        if($mixedResult !== CHECK_ACTION_RESULT_ALLOWED)
+            return _t('_sys_txt_access_denied');
+
+        return $this->checkAllowedAdd($isPerformAction);
+    }
+
+    public function serviceCheckAllowedViewForProfile ($aDataEntry, $isPerformAction = false, $iProfileId = false)
+    {
+        if (CHECK_ACTION_RESULT_ALLOWED !== ($sMsg = parent::serviceCheckAllowedViewForProfile ($aDataEntry, $isPerformAction, $iProfileId)))
+            return $sMsg;
+
+        if (!$iProfileId)
+            $iProfileId = bx_get_logged_profile_id();
+
+        return $this->isCollaborator($aDataEntry, $iProfileId) ? CHECK_ACTION_RESULT_ALLOWED : _t('_sys_txt_access_denied');
+    }
+
+    protected function isCollaborator($aDataEntry, $iProfileId)
+    {
+        $aCollaborators = $this->_oDb->getCollaborators($aDataEntry[$this->_oConfig->CNF['FIELD_ID']]);
+        return isset($aCollaborators[$iProfileId]);
+    }
+}
+
+/** @} */

+ 104 - 0
modules/boonex/convos/updates/13.0.1_13.0.2/source/install/config.php

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

+ 51 - 0
modules/boonex/developer/updates/13.0.1_13.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' => 'Developer',
+    'version_from' => '13.0.1',
+    'version_to' => '13.0.2',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '13.0.0-B2'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/developer/updates/update_13.0.1_13.0.2/',
+    'home_uri' => 'developer_update_1301_1302',
+
+    'module_dir' => 'boonex/developer/',
+    'module_uri' => 'developer',
+
+    'db_prefix' => 'bx_dev_',
+    'class_prefix' => 'BxDev',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 0,
+        'update_files' => 1,
+        'update_languages' => 0,
+        'clear_db_cache' => 0,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'BoonEx Developer',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

+ 13 - 0
modules/boonex/developer/updates/13.0.1_13.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 BxDevUpdater extends BxDolStudioUpdater
+{
+    function __construct($aConfig)
+    {
+        parent::__construct($aConfig);
+    }
+}

+ 111 - 0
modules/boonex/developer/updates/13.0.1_13.0.2/source/classes/BxDevFunctions.php

@@ -0,0 +1,111 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Developer Developer
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxDevFunctions
+{
+    function __construct() {}
+
+    /*
+     * Is needed to change fields in "Form's Field" creation form.
+     *
+     * @see BxDevFormsField
+     */
+    public static function changeFormField($aParams, &$aInputs, &$oDb)
+    {
+        $aInputs['module']['type'] = 'select';
+        $aInputs['module']['values'] = array_merge(array('' => _t('_bx_dev_frm_txt_select_module')), BxDolStudioUtils::getModules());
+        $aInputs['module']['value'] = $aParams['module'];
+
+        $aInputs['object']['type'] = 'select';
+        $aInputs['object']['value'] = $aParams['object'];
+        $aInputs['object']['values'] = array();
+
+    	$aForms = array();
+        $oDb->getForms(array('type' => 'by_module', 'value' => $aParams['module']), $aForms, false);
+        if(!empty($aForms) && is_array($aForms)) {
+	        foreach($aForms as $aForm)
+	            $aInputs['object']['values'][$aForm['object']] = _t($aForm['title']);
+
+	        asort($aInputs['object']['values']);
+        }
+        $aInputs['object']['values'] = array_merge(array('' => _t('_bx_dev_frm_txt_select_object')), $aInputs['object']['values']);
+
+        $aInputs['name']['type'] = 'text';
+
+        $sTrlTypePostfix = '_translatable';
+        $sTrlCheckFuncPostfix = 'Translatable';
+        foreach($aInputs as $sName => $aInput)
+            if(isset($aInput['type']) && stripos($aInput['type'], $sTrlTypePostfix) !== false) {
+                $aInputs[$sName]['type'] = 'text';
+                $aInputs[$sName]['html'] = 0;
+
+                if(isset($aInput['checker']['func']) && stripos($aInput['checker']['func'], $sTrlCheckFuncPostfix) !== false)
+                    $aInputs[$sName]['checker']['func'] = str_ireplace($sTrlCheckFuncPostfix, '', $aInput['checker']['func']);
+            }
+
+        unset($aInputs['required']['attrs']['onchange']);
+        unset($aInputs['checker_func']['attrs']['disabled'], $aInputs['checker_func']['tr_attrs']['style']);
+        unset($aInputs['checker_error']['attrs']['disabled'], $aInputs['checker_error']['tr_attrs']['style']);
+
+        $aFields = array(
+            'editable' => array(
+                'type' => 'switcher',
+                'name' => 'editable',
+                'caption' => _t('_bx_dev_frm_txt_field_title_editable'),
+                'info' => _t('_bx_dev_frm_txt_field_info_editable'),
+                'value' => '1',
+                'required' => '0',
+                'db' => array (
+                    'pass' => 'Int',
+                )
+            ),
+            'deletable' => array(
+                'type' => 'switcher',
+                'name' => 'deletable',
+                'caption' => _t('_bx_dev_frm_txt_field_title_deletable'),
+                'info' => _t('_bx_dev_frm_txt_field_info_deletable'),
+                'value' => '1',
+                'required' => '0',
+                'db' => array (
+                    'pass' => 'Int',
+                )
+            ),
+        );
+        $aInputs = BxDolStudioUtils::addInArray($aInputs, 'controls', $aFields, false);
+    }
+
+    public static function serializeString($sValue)
+    {
+        if(empty($sValue))
+            return '';
+
+        $aValue = array();
+        @eval("\$aValue = " . $sValue . ";");
+        if(empty($aValue) || !is_array($aValue))
+            return '';
+
+        return serialize($aValue);
+    }
+
+    public static function unserializeString($sValue)
+    {
+        if(empty($sValue))
+            return '';
+
+        $aValue = @unserialize($sValue);
+        if(empty($aValue) || !is_array($aValue))
+            return '';
+
+        return var_export($aValue, true);
+    }
+}
+
+/** @} */

+ 69 - 0
modules/boonex/developer/updates/13.0.1_13.0.2/source/install/config.php

@@ -0,0 +1,69 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Developer Developer
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_developer',
+    'title' => 'Developer',
+    'note' => 'Developer tools...',
+    'version' => '13.0.2',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '13.0.0-B2'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/developer/',
+    'home_uri' => 'developer',
+
+    'db_prefix' => 'bx_dev_',
+    'class_prefix' => 'BxDev',
+
+	/**
+     * Category for language keys.
+     */
+    'language_category' => 'BoonEx Developer',
+
+    /**
+     * 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,
+    ),
+    'disable' => array(
+        'execute_sql' => 1,
+    ),
+
+    /**
+     * Dependencies Section
+     */
+    'dependencies' => array(),
+
+);
+
+/** @} */

+ 51 - 0
modules/boonex/donations/updates/13.0.1_13.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' => 'Donations',
+    'version_from' => '13.0.1',
+    'version_to' => '13.0.2',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '13.0.0-B2'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/donations/updates/update_13.0.1_13.0.2/',
+    'home_uri' => 'donations_update_1301_1302',
+
+    'module_dir' => 'boonex/donations/',
+    'module_uri' => 'donations',
+
+    'db_prefix' => 'bx_donations_',
+    'class_prefix' => 'BxDonations',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 0,
+        'update_files' => 1,
+        'update_languages' => 0,
+        'clear_db_cache' => 0,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Donations',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

+ 13 - 0
modules/boonex/donations/updates/13.0.1_13.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 BxDonationsUpdater extends BxDolStudioUpdater
+{
+    function __construct($aConfig)
+    {
+        parent::__construct($aConfig);
+    }
+}

+ 35 - 0
modules/boonex/donations/updates/13.0.1_13.0.2/source/classes/BxDonationsAlertsResponse.php

@@ -0,0 +1,35 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defdroup    Donations Donations
+ * @indroup     UnaModules
+ *
+ * @{
+ */
+
+class BxDonationsAlertsResponse extends BxDolAlertsResponse
+{
+    protected $_sModule;
+    protected $_oModule;
+
+    public function __construct()
+    {
+        parent::__construct();
+
+        $this->_sModule = 'bx_donations';
+        $this->_oModule = BxDolModule::getInstance($this->_sModule);
+    }
+
+    public function response($oAlert)
+    {
+        parent::response($oAlert);
+
+        $sMethod = '_process' . bx_gen_method_name($oAlert->sUnit . '_' . $oAlert->sAction);           	
+        if(method_exists($this, $sMethod))
+            $this->$sMethod($oAlert);
+    }
+}
+
+/** @} */

+ 71 - 0
modules/boonex/donations/updates/13.0.1_13.0.2/source/install/config.php

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

+ 51 - 0
modules/boonex/elasticsearch/updates/12.0.0_13.0.0/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' => 'ElasticSearch',
+    'version_from' => '12.0.0',
+    'version_to' => '13.0.0',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '13.0.0-B2'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/elasticsearch/updates/update_12.0.0_13.0.0/',
+    'home_uri' => 'elasticsearch_update_1200_1300',
+
+    'module_dir' => 'boonex/elasticsearch/',
+    'module_uri' => 'elasticsearch',
+
+    'db_prefix' => 'bx_els_',
+    'class_prefix' => 'BxEls',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 0,
+        'update_files' => 1,
+        'update_languages' => 0,
+        'clear_db_cache' => 0,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'ElasticSearch',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

+ 13 - 0
modules/boonex/elasticsearch/updates/12.0.0_13.0.0/install/installer.php

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

+ 134 - 0
modules/boonex/elasticsearch/updates/12.0.0_13.0.0/source/classes/BxElsResponse.php

@@ -0,0 +1,134 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    ElasticSearch ElasticSearch
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxElsResponse extends BxDolAlertsResponse
+{
+    protected $_sModule;
+    protected $_oModule;
+
+    public function __construct()
+    {
+        parent::__construct();
+
+        $this->_sModule = 'bx_elasticsearch';
+        $this->_oModule = BxDolModule::getInstance($this->_sModule);
+    }
+
+    public function response($oAlert)
+    {
+        if($oAlert->sUnit == 'grid' && $oAlert->sAction == 'get_data')
+            return $this->_processGridSearch($oAlert);
+
+        if($oAlert->sUnit == 'grid' && $oAlert->sAction == 'get_data_by_filter')
+            return $this->_processGridSearchFilter($oAlert);
+
+        return $this->_processManageActions($oAlert);
+    }
+
+    protected function _processManageActions(&$oAlert)
+    {
+        $aAlertTypes = array('add', 'update', 'delete');
+        foreach($aAlertTypes as $sAlertType) {
+            $sMethodType = bx_gen_method_name($sAlertType);
+
+            $sMethod = 'getObjectInstanceByAlert' . $sMethodType;
+            $oContentInfo = BxDolContentInfo::$sMethod($oAlert->sUnit, $oAlert->sAction);
+            if(!$oContentInfo)
+                continue;
+
+            $sMethod = 'service' . $sMethodType;
+            $iContentId = $oAlert->iObject;
+            if(in_array($oAlert->sAction, array('commentPost', 'commentUpdated', 'commentRemoved')))
+                $iContentId = $oAlert->aExtras['comment_id'];
+            
+            $this->_oModule->$sMethod($iContentId, $oContentInfo);
+        }
+    }
+
+    /**
+     * Note. This custom search is currently used in Forum Search only. 
+     */
+    protected function _processGridSearch(&$oAlert)
+    {
+        if(empty($oAlert->aExtras['browse_params']['where']))
+            return;
+
+        $aWhere = $oAlert->aExtras['browse_params']['where'];
+        $oContentInfo = BxDolContentInfo::getObjectInstanceByGrid($oAlert->aExtras['object']);
+        if(!$oContentInfo)
+            return;
+
+        $aSelection = array();
+        $aCondition = array('grp' => true, 'opr' => 'AND', 'cnds' => array());
+        if(isset($aWhere['grp']) && $aWhere['grp']) 
+            $aCondition['cnds'] = $aWhere['cnds'];
+        else
+            $aCondition['cnds'][] = $aWhere;
+
+        if(!empty($oAlert->aExtras['filter']))
+            $aCondition['cnds'][] = array('val' => $oAlert->aExtras['filter']);
+
+        $this->_updateSearchParamsByGrid($oContentInfo->getGrid(), $aCondition, $aSelection);
+
+        $aResults = $this->_oModule->serviceSearchExtended($aCondition, $aSelection, $oContentInfo->getName());
+        if(empty($aResults) || !is_array($aResults) || (int)$aResults['total'] == 0)
+            return;
+
+        $aItems = array();
+        foreach($aResults['hits'] as $aResult)
+            $aItems[] = $aResult['_source'];
+
+        $oAlert->aExtras['results'] = $aItems;
+    }
+
+    protected function _processGridSearchFilter(&$oAlert)
+    {
+        $oContentInfo = BxDolContentInfo::getObjectInstanceByGrid($oAlert->aExtras['object']);
+        if(!$oContentInfo)
+            return;
+
+        $aCondition = array('grp' => true, 'opr' => 'AND', 'cnds' => array());
+        $aSelection = array();
+
+        if(!empty($oAlert->aExtras['filter']))
+            $aCondition['cnds'][] = array('val' => $oAlert->aExtras['filter']);
+
+        $aGrid = $oContentInfo->getGrid();
+        $this->_updateSearchParamsByGrid($aGrid, $aCondition, $aSelection);
+
+        $aResults = $this->_oModule->serviceSearchExtended($aCondition, $aSelection, $oContentInfo->getName());
+
+        $aIds = array();
+        if($aResults && (int)$aResults['total'] > 0 && !empty($aResults['hits']))
+            foreach($aResults['hits'] as $aResult)
+                $aIds[] = $aResult['_id'];
+
+        $oAlert->aExtras['conditions'] = "`" . $aGrid['grid_field_id'] . "` IN (" . $this->_oModule->_oDb->implode_escape($aIds) . ")";
+    }
+
+    protected function _updateSearchParamsByGrid($aGrid, &$aCondition, &$aSelection)
+    {
+        if(empty($aGrid['condition']) && empty($aGrid['selection']))
+            return;
+
+        //--- Update Condition params
+        $aGridCondition = unserialize($aGrid['condition']);
+        if(!empty($aGridCondition) && is_array($aGridCondition))
+            $aCondition['cnds'] = array_merge($aCondition['cnds'], $aGridCondition);
+
+        //--- Update Selection params: from, size and sort 
+        $aGridSelection = unserialize($aGrid['selection']);
+        if(empty($aGridSelection) || !is_array($aGridSelection))
+            $aSelection = array_merge($aSelection, $aGridSelection);
+    } 
+}
+
+/** @} */

+ 71 - 0
modules/boonex/elasticsearch/updates/12.0.0_13.0.0/source/install/config.php

@@ -0,0 +1,71 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    ElasticSearch ElasticSearch
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_elasticsearch',
+    'title' => 'ElasticSearch',
+    'note' => 'Allows to translate content of the site on different languages',
+    'version' => '13.0.0',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '13.0.0-B2'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/elasticsearch/',
+    'home_uri' => 'elasticsearch',
+
+    'db_prefix' => 'bx_els_',
+    'class_prefix' => 'BxEls',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'ElasticSearch',
+
+    /**
+     * 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,
+    	'process_content_alerts' => 1,    //Note. It's essential to make this action AFTER 'execute_sql' one.
+        'clear_db_cache' => 1,
+    ),
+    'disable' => array (
+        'execute_sql' => 1,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Dependencies Section
+     */
+    'dependencies' => array(),
+);
+
+/** @} */

+ 51 - 0
modules/boonex/events/updates/13.0.2_13.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' => 'Events',
+    'version_from' => '13.0.2',
+    'version_to' => '13.0.3',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '13.0.0-B2'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/events/updates/update_13.0.2_13.0.3/',
+    'home_uri' => 'events_update_1302_1303',
+
+    'module_dir' => 'boonex/events/',
+    'module_uri' => 'events',
+
+    'db_prefix' => 'bx_events_',
+    'class_prefix' => 'BxEvents',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_files' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Events',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

+ 13 - 0
modules/boonex/events/updates/13.0.2_13.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 BxEventsUpdater extends BxDolStudioUpdater
+{
+    function __construct($aConfig)
+    {
+        parent::__construct($aConfig);
+    }
+}

+ 4 - 0
modules/boonex/events/updates/13.0.2_13.0.3/install/langs/en.xml

@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources name="en" flag="gb" title="English">
+	<string_add name="_bx_events_menu_item_title_ical_export"><![CDATA[Sync to Calendar]]></string_add>
+</resources>

+ 14 - 0
modules/boonex/events/updates/13.0.2_13.0.3/install/sql/enable.sql

@@ -0,0 +1,14 @@
+-- SETTINGS
+UPDATE `sys_options` SET `value`='H:i' WHERE `name`='bx_events_time_format';
+UPDATE `sys_options` SET `value`='j/n/Y' WHERE `name`='bx_events_short_date_format';
+UPDATE `sys_options` SET `value`='j/n/Y H:i' WHERE `name`='bx_events_datetime_format';
+
+
+-- MENUS
+DELETE FROM `sys_menu_items` WHERE `set_name`='bx_events_view_actions' AND `name`='ical-export';
+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_events_view_actions', 'bx_events', 'ical-export', '', '_bx_events_menu_item_title_ical_export', '{ical_url}', '', '', 'calendar-plus', '', 0, 2147483647, 'a:3:{s:6:"module";s:9:"bx_events";s:6:"method";s:24:"is_ical_export_avaliable";s:6:"params";a:1:{i:0;s:12:"{content_id}";}}', 1, 0, 1, 40);
+
+DELETE FROM `sys_menu_items` WHERE `set_name`='bx_events_view_actions_all' AND `name`='ical-export';
+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_events_view_actions_all', 'bx_events', 'ical-export', '', '_bx_events_menu_item_title_ical_export', '{ical_url}', '', '', 'calendar-plus', '', '', 0, 2147483647, 'a:3:{s:6:"module";s:9:"bx_events";s:6:"method";s:24:"is_ical_export_avaliable";s:6:"params";a:1:{i:0;s:12:"{content_id}";}}', 1, 0, 60);

+ 340 - 0
modules/boonex/events/updates/13.0.2_13.0.3/source/classes/BxEventsFormEntry.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    Events Events
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+/**
+ * Create/Edit Group Form.
+ */
+class BxEventsFormEntry extends BxBaseModGroupsFormEntry
+{
+    protected static $_isCssJsEventsAdded = false;
+    
+    protected $_iContentId = 0;
+
+    public function __construct($aInfo, $oTemplate = false)
+    {
+        $this->MODULE = 'bx_events';
+        parent::__construct($aInfo, $oTemplate);
+
+        if (isset($this->aInputs['reoccurring'])) {
+            $this->aInputs['reoccurring']['ghost_template'] = array (
+                
+                'params' => array(
+                    'nested_form_template' => 'form_ghost_template_wrapper.html',
+                    'db' => array(
+                        'table' => 'bx_events_intervals',
+                        'key' => 'interval_id',
+                        'submit_name' => 'interval_id',
+                    ),
+                ),
+                'inputs' => array (
+                    'interval_id' => array (
+                        'type' => 'hidden',
+                        'name' => 'interval_id[]',
+                        'value' => '{interval_id}',
+                        'caption' => _t('Interval ID'),
+                        'db' => array (
+                            'pass' => 'Int',
+                        ),
+                    ),                
+                    'repeat_year' => array (
+                        'type' => 'select',                    
+                        'name' => 'repeat_year[]',
+                        'value' => '{repeat_year}',
+                        'values' => BxDolForm::getDataItems('bx_events_repeat_year'),
+                        'caption' => _t('_bx_events_form_input_repeat_year'),
+                        'db' => array (
+                            'pass' => 'Int',
+                        ),
+                    ),
+                    'repeat_month' => array (
+                        'type' => 'select',
+                        'name' => 'repeat_month[]',
+                        'value' => '{repeat_month}',
+                        'values' => BxDolForm::getDataItems('bx_events_repeat_month'),
+                        'caption' => _t('_bx_events_form_input_repeat_month'),
+                        'db' => array (
+                            'pass' => 'Int',
+                        ),
+                    ),
+                    'repeat_week_of_month' => array (
+                        'type' => 'select',
+                        'name' => 'repeat_week_of_month[]',
+                        'value' => '{repeat_week_of_month}',
+                        'values' => BxDolForm::getDataItems('bx_events_repeat_week_of_month'),
+                        'caption' => _t('_bx_events_form_input_repeat_week_of_month'),
+                        'db' => array (
+                            'pass' => 'Int',
+                        ),
+                    ),                
+                    'repeat_day_of_month' => array (
+                        'type' => 'select',
+                        'name' => 'repeat_day_of_month[]',
+                        'value' => '{repeat_day_of_month}',
+                        'values' => BxDolForm::getDataItems('bx_events_repeat_day_of_month'),
+                        'caption' => _t('_bx_events_form_input_repeat_day_of_month'),
+                        'db' => array (
+                            'pass' => 'Int',
+                        ),
+                    ),
+                    'repeat_day_of_week' => array (
+                        'type' => 'select',
+                        'name' => 'repeat_day_of_week[]',
+                        'value' => '{repeat_day_of_week}',
+                        'values' => BxDolForm::getDataItems('bx_events_repeat_day_of_week'),
+                        'caption' => _t('_bx_events_form_input_repeat_day_of_week'),
+                        'db' => array (
+                            'pass' => 'Int',
+                        ),
+                    ),
+                    'repeat_stop' => array (
+                        'type' => 'datepicker',
+                        'name' => 'repeat_stop[]',
+                        'value' => '{repeat_stop}',
+                        'caption' => _t('_bx_events_form_input_stop_repeating'),
+                        'db' => array (
+                            'pass' => 'DateTs',
+                        ),
+                    ),
+                ),
+            );
+        }
+
+        if (isset($this->aInputs['timezone']) && !$this->aParams['view_mode']) {
+            $this->aInputs['timezone']['values'] = array_combine(timezone_identifiers_list(), timezone_identifiers_list());
+        }        
+    }
+
+    function getCode($bDynamicMode = false)
+    {
+        $sJsCode = '';
+        if(empty($this->aParams['view_mode']))
+            $sJsCode = $this->_oModule->_oTemplate->getJsCode('entry');
+
+        return $sJsCode . parent::getCode($bDynamicMode);
+    }
+
+    protected function fixTimezone(&$aValues, $bAdd = true)
+    {
+        $sTimezone = 'UTC';
+        if (isset($aValues['timezone']) && $aValues['timezone'])
+            $sTimezone = $aValues['timezone'];
+        elseif (isset($this->aInputs['timezone']['value']) && $this->aInputs['timezone']['value'])
+            $sTimezone = $this->aInputs['timezone']['value'];
+
+        $oTz = new DateTimeZone($sTimezone);
+        $oDateTz = new DateTime("now", $oTz);
+        $iTimeOffset = $oTz->getOffset($oDateTz);
+        $a = array('date_start', 'date_end');
+        foreach ($a as $sField) {
+            if (!isset($aValues[$sField]) && isset($this->aInputs[$sField]['value']) && $this->aInputs[$sField]['value']) {
+                $aValues[$sField] = $this->getCleanValue($sField);
+            }
+            if (isset($aValues[$sField]) && $aValues[$sField] && isset($this->aInputs[$sField]) && isset($this->aInputs[$sField]['db']['pass']) && 'DateTimeTs' == $this->aInputs[$sField]['db']['pass']) {
+                $aValues[$sField] += ($bAdd ? $iTimeOffset : -$iTimeOffset);
+            }
+        }
+    }
+
+    function initChecker ($aValues = array (), $aSpecificValues = array())
+    {        
+        $this->fixTimezone($aValues, true);
+
+        if (isset($aValues[$this->_oModule->_oConfig->CNF['FIELD_ID']]))
+            $this->_iContentId = $aValues[$this->_oModule->_oConfig->CNF['FIELD_ID']];
+        
+        parent::initChecker($aValues, $aSpecificValues);
+        
+        if ($this->isSubmitted ()) {
+            if (isset($this->aInputs['date_start']) && $this->aInputs['date_start']['value'] != '' && isset($this->aInputs['date_end'])){
+                if ($this->aInputs['date_end']['value'] != ''){
+                    if (strtotime($this->aInputs['date_end']['value']) < strtotime($this->aInputs['date_start']['value'])){
+                        $this->aInputs['date_end']['error'] = _t('_bx_events_form_profile_input_date_end_invalid_err');
+                        $this->_isValid = false;       
+                        
+                        $sSubmitName = false;
+                        foreach ($this->aInputs as $k => $a) {
+                            if (isset($a['visible_for_levels']) && !BxDolForm::isVisible($a))
+                                continue;
+
+                            if (empty($a['name']) || 'submit' == $a['type'] || 'reset' == $a['type'] || 'button' == $a['type'] || 'value' == $a['type']) {
+                                if (isset($a['type']) && 'submit' == $a['type'])
+                                    $sSubmitName = $k;
+                                continue;
+                            }
+
+                            if ('input_set' == $a['type'])
+                                foreach ($a as $r)
+                                    if (isset($r['type']) && 'submit' == $r['type'])
+                                        $sSubmitName = $k;
+
+                        }
+                        if ($sSubmitName)
+                            $this->aInputs[$sSubmitName]['error'] = _t('_sys_txt_form_submission_error');
+                        
+                    }
+                }
+                else{
+                    $this->setSubmittedValue('date_end', $this->aInputs['date_start']['value'], BX_DOL_FORM_METHOD_POST);
+                }
+            }
+        }
+        
+    }
+
+    protected function genCustomRowDateEnd (&$aInput)
+    {
+        if ($this->aParams['view_mode'])
+            return $this->_isSameDayEvent() ? '' : $this->genViewRowWrapped($aInput);
+
+        return $this->genRowStandard($aInput);
+    }
+
+    protected function _isSameDayEvent()
+    {
+        $aStartEnd = $this->_getStartEnd();
+        if($aStartEnd === false || (is_array($aStartEnd) && empty($aStartEnd)))
+            return false;
+        else
+            return $aStartEnd['start']->format('Y-m-d') == $aStartEnd['end']->format('Y-m-d');
+    }
+
+    protected function _getStartEnd()
+    {
+        if(!isset($this->aInputs['timezone']['value']) || !isset($this->aInputs['date_start']['value']) || !isset($this->aInputs['date_end']['value']))
+            return false;
+
+        if(empty($this->aInputs['date_start']['value']) && empty($this->aInputs['date_end']['value']))
+            return array();
+
+        $iTimeStart = bx_process_input ($this->aInputs['date_start']['value'], isset($this->aInputs['date_start']['date_filter']) ? $this->aInputs['date_start']['date_filter'] : BX_DATA_DATETIME_TS, false, false);
+        $iTimeEnd = bx_process_input ($this->aInputs['date_end']['value'], isset($this->aInputs['date_end']['date_filter']) ? $this->aInputs['date_end']['date_filter'] : BX_DATA_DATETIME_TS, false, false);
+
+        $oDateStart = date_create("@$iTimeStart");
+        $oDateEnd = date_create("@$iTimeEnd");
+
+        return array('start' => $oDateStart, 'end' => $oDateEnd);
+    }
+    
+    protected function genCustomRowTime (&$aInput)
+    {
+        if (!$this->aParams['view_mode'])
+            return '';
+
+        $aStartEnd = $this->_getStartEnd();
+
+        if ($aStartEnd === false)
+            $aInput['value'] = "Timezone, date start & date end fields are required to display this field";
+        else if(is_array($aStartEnd) && empty($aStartEnd))
+            $aInput['value'] = '';
+        else {
+            if ($aStartEnd['start']->format('Y-m-d') == $aStartEnd['end']->format('Y-m-d'))
+                $aInput['value'] = _t('_bx_events_txt_from_time_to_time', date(getParam('bx_events_time_format'), $aStartEnd['start']->getTimestamp()), date(getParam('bx_events_time_format'), $aStartEnd['end']->getTimestamp()));
+            else
+                $aInput['value'] = '';
+        }
+        return $this->genViewRowWrapped($aInput);
+    }
+ 
+    function genViewRowValue(&$aInput)
+    {
+        if (in_array($aInput['name'], array('date_start', 'date_end'))) {
+
+            $aStartEnd = $this->_getStartEnd();
+            if($aStartEnd === false)
+                return "Timezone, date start & date end fields are required to display this field";
+
+            if(is_array($aStartEnd) && empty($aStartEnd))
+                return null;
+
+            $sFormat = getParam($aStartEnd['start']->format('Y-m-d') == $aStartEnd['end']->format('Y-m-d') ? 'bx_events_short_date_format' : 'bx_events_datetime_format');
+            $oDate = 'date_start' == $aInput['name'] ? $aStartEnd['start'] : $aStartEnd['end'];
+            return date($sFormat, $oDate->getTimestamp());
+        }
+        return parent::genViewRowValue($aInput);
+    }
+
+    protected function genCustomRowReoccurring (&$aInput)
+    {
+        return $this->genRowCustom($aInput, 'genInputReoccurring');
+    }
+
+    protected function genInputReoccurring (&$aInput, $sInfo = '', $sError = '')
+    {
+        $sUniqId = genRndPwd (8, false);
+
+        return $this->oTemplate->parseHtmlByName('form_field_reoccurring.html', array(
+            'info' => $sInfo,
+            'error' => $sError,
+            'uniq_id' => $sUniqId,
+            'js_instance_name' => 'oBxEventsIntervals_' . $sUniqId,
+            'options' => json_encode(array(
+                'uniq_id' => $sUniqId,
+                'js_instance_name' => 'oBxEventsIntervals_' . $sUniqId,
+                'template_ghost' => $this->genGhostTemplate($aInput),
+                'content_id' => $this->_iContentId, 
+            )),
+        ));
+    }
+
+    protected function genCustomViewRowValueTimezone ($aInput)
+    {
+        return $aInput['value'];
+    }
+
+    public function insert ($aValsToAdd = array(), $isIgnore = false)
+    {
+        $this->fixTimezone($aValsToAdd, false);
+
+        $iContentId = parent::insert ($aValsToAdd, $isIgnore);
+
+        if (isset($this->aInputs['reoccurring']) && is_array($this->aInputs['reoccurring']['ghost_template']) && !isset($this->aInputs['reoccurring']['ghost_template']['inputs'])) {
+            foreach ($this->aInputs['reoccurring']['ghost_template'] as $oFormNested) {
+                $oFormNested->insert(array('event_id' => $iContentId));
+            }
+        }
+        
+        return $iContentId;
+    }
+
+    function update ($val, $aValsToAdd = array(), &$aTrackTextFieldsChanges = null)
+    {
+        $this->fixTimezone($aValsToAdd, false);
+
+        $iAffectedRows = parent::update($val, $aValsToAdd, $aTrackTextFieldsChanges);
+
+        if (isset($this->aInputs['reoccurring']) && is_array($this->aInputs['reoccurring']['ghost_template']) && !isset($this->aInputs['reoccurring']['ghost_template']['inputs'])) {
+            foreach ($this->aInputs['reoccurring']['ghost_template'] as $oFormNested) {
+                $aSpecificValues = $oFormNested->getSpecificValues();
+                $iIntervalId = $oFormNested->getSubmittedValue('interval_id', BX_DOL_FORM_METHOD_SPECIFIC, $aSpecificValues);
+                if ($iIntervalId) {
+                    $oFormNested->update($iIntervalId);
+                } else {
+                    $oFormNested->insert(array('event_id' => $this->_iContentId));
+                }
+            }
+        }
+        
+        return $iAffectedRows;
+    }
+    
+    function addCssJs ()
+    {
+        if ((!isset($this->aParams['view_mode']) || !$this->aParams['view_mode']) && !self::$_isCssJsEventsAdded) {
+            $this->oTemplate->addJs(array('moment-timezone-with-data.js', 'entry.js', 'intervals.js'));
+            $this->oTemplate->addCss('informer.css');
+            self::$_isCssJsEventsAdded = true;
+        }  
+
+        parent::addCssJs ();
+    }
+}
+
+/** @} */

+ 39 - 0
modules/boonex/events/updates/13.0.2_13.0.3/source/classes/BxEventsMenuSnippetMeta.php

@@ -0,0 +1,39 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Events Events
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxEventsMenuSnippetMeta extends BxBaseModGroupsMenuSnippetMeta
+{
+    public function __construct($aObject, $oTemplate = false)
+    {
+        $this->_sModule = 'bx_events';
+
+        parent::__construct($aObject, $oTemplate);
+
+        unset($this->_aConnectionToFunctionCheck['sys_profiles_friends']);
+        unset($this->_aConnectionToFunctionTitle['sys_profiles_friends']);
+    }
+
+    protected function _getMenuItemDateStart($aItem)
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        return $this->getUnitMetaItemText(bx_time_js($this->_aContentInfo[$CNF['FIELD_DATE_START']], BX_FORMAT_DATE_TIME, true));
+    }
+
+    protected function _getMenuItemDateEnd($aItem)
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        return $this->getUnitMetaItemText(bx_time_js($this->_aContentInfo[$CNF['FIELD_DATE_END']], BX_FORMAT_DATE_TIME, true));
+    }
+}
+
+/** @} */

+ 112 - 0
modules/boonex/events/updates/13.0.2_13.0.3/source/classes/BxEventsMenuViewActionsAll.php

@@ -0,0 +1,112 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Events Events
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+use Spatie\CalendarLinks\Link;
+
+/**
+ * View entry all actions menu
+ */
+class BxEventsMenuViewActionsAll extends BxBaseModGroupsMenuViewActionsAll
+{
+    public function __construct($aObject, $oTemplate = false)
+    {
+        $this->_sModule = 'bx_events';
+
+        parent::__construct($aObject, $oTemplate);
+    }
+
+    public function setContentId($iContentId)
+    {
+        parent::setContentId($iContentId);
+
+        $oDateStart = new DateTime('@' . $this->_aContentInfo['date_start']);
+        $oDateEnd = new DateTime('@' . ($this->_aContentInfo['date_end'] > $this->_aContentInfo['repeat_stop'] ? $this->_aContentInfo['date_end'] : $this->_aContentInfo['repeat_stop']));
+
+        $CNF = $this->_oModule->_oConfig->CNF;
+
+        if ($this->_aContentInfo[$CNF['FIELD_TIMEZONE']]) {
+            $oTz = new DateTimeZone($this->_aContentInfo[$CNF['FIELD_TIMEZONE']]);
+            $oDateStart->setTimezone($oTz);
+            $oDateEnd->setTimezone($oTz);
+        }
+
+        $oICalLink = $oDateStart && $oDateEnd ? Link::create(
+            $this->_aContentInfo[$CNF['FIELD_TITLE']],
+            $oDateStart,
+            $oDateEnd
+        ) : null;
+
+        if (!empty($CNF['OBJECT_METATAGS'])) {
+            $oMetatags = BxDolMetatags::getObjectInstance($CNF['OBJECT_METATAGS']);
+            if ($oMetatags->locationsIsEnabled()) {
+                $sLocation = $oMetatags->locationsString($this->_aContentInfo[$CNF['FIELD_ID']], false);
+                if ($sLocation)
+                    $oICalLink->address($sLocation);
+            }
+        }
+
+        $this->addMarkers([
+            'ical_url' => $oICalLink ? $oICalLink->ics() : '',
+        ]);
+    }
+
+    protected function _getMenuAttrs ($aMenuItem)
+    {
+        $s = parent::_getMenuAttrs ($aMenuItem);
+        if ('ical-export' == $aMenuItem['name']) {
+            $CNF = $this->_oModule->_oConfig->CNF;
+            $s .= ' download="' . title2uri($this->_aContentInfo[$CNF['FIELD_TITLE']]) . '.ics"';
+        }
+        return $s;
+    }
+
+    protected function _getMenuItemJoinEventProfile($aItem)
+    {
+        return $this->_getMenuItemByNameActions($aItem);
+    }
+
+    protected function _getMenuItemEditEventCover($aItem)
+    {
+        return $this->_getMenuItemByNameActionsMore($aItem);
+    }
+
+    protected function _getMenuItemEditEventProfile($aItem)
+    {
+        return $this->_getMenuItemByNameActionsMore($aItem);
+    }
+
+    protected function _getMenuItemEditEventPricing($aItem)
+    {
+        return $this->_getMenuItemByNameActionsMore($aItem);
+    }
+
+    protected function _getMenuItemInviteToEvent($aItem)
+    {
+        return $this->_getMenuItemByNameActionsMore($aItem);
+    }
+
+    protected function _getMenuItemDeleteEventProfile($aItem)
+    {
+        return $this->_getMenuItemByNameActionsMore($aItem);
+    }
+
+    protected function _getMenuItemApproveEventProfile($aItem)
+    {
+        return $this->_getMenuItemByNameActionsMore($aItem);
+    }
+
+    protected function _getMenuItemProfileSetBadges($aItem)
+    {
+        return $this->_getMenuItemByNameActions($aItem);
+    }
+}
+
+/** @} */

+ 488 - 0
modules/boonex/events/updates/13.0.2_13.0.3/source/classes/BxEventsModule.php

@@ -0,0 +1,488 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Events Events
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+/**
+ * Events profiles module.
+ */
+class BxEventsModule extends BxBaseModGroupsModule implements iBxDolCalendarService 
+{
+    function __construct(&$aModule)
+    {
+        parent::__construct($aModule);
+        
+        $CNF = &$this->_oConfig->CNF;
+        $this->_aSearchableNamesExcept = array_merge($this->_aSearchableNamesExcept, array(
+            $CNF['FIELD_TIMEZONE'],
+            $CNF['FIELD_JOIN_CONFIRMATION'],
+            $CNF['FIELD_REMINDER']
+        ));
+    }
+
+    public function actionCalendarData()
+    {
+        // check permissions
+        $aSQLPart = array();
+        $iContentId = (int)bx_get('event');
+        $iContextId = (int)bx_get('context_id');
+        
+        if ($iContentId) {
+            $aContentInfo = $this->_oDb->getContentInfoById($iContentId);
+            if (CHECK_ACTION_RESULT_ALLOWED !== $this->checkAllowedView($aContentInfo)) {
+                $this->_oTemplate->displayAccessDenied();
+                exit;
+            }
+            $aSQLPart = array();
+        }
+        else {
+            $oPrivacy = BxDolPrivacy::getObjectInstance($this->_oConfig->CNF['OBJECT_PRIVACY_VIEW']);
+            if($iContextId){
+                if (!$this->serviceIsEnableForContext($iContextId)){
+                    exit;
+                }
+                else{
+                    $aSQLPart = $oPrivacy ? $oPrivacy->getContentByGroupAsSQLPart(- $iContextId) : array();
+                }
+            }
+            else{
+                $aSQLPart = $oPrivacy ? $oPrivacy->getContentPublicAsSQLPart(0, $oPrivacy->getPartiallyVisiblePrivacyGroups()) : array();
+            }
+        }
+
+        // get entries
+        $aEntries = $this->_oDb->getEntriesByDate(bx_get('start'), bx_get('end'), bx_get('event'), $aSQLPart);
+        
+        bx_alert($this->getName(), 'calendar_data', 0, false, array(
+            'event' => $iContentId,
+            'context_id' => $iContextId,
+            'start' => bx_get('start'),
+            'end' =>  bx_get('end'),
+            'sql_part' => &$aSQLPart,
+            'data' => &$aEntries,
+        ));
+        
+        header('Content-Type: application/json; charset=utf-8');
+        echo json_encode($aEntries);
+    }
+    
+    public function serviceIsIcalExportAvaliable($iContentId)
+    {
+        return true;
+        $aContentInfo = $iContentId ? $this->_oDb->getContentInfoById($iContentId) : false;
+        if ($aContentInfo)
+            return false;
+        
+        return $aContentInfo['date_start'] && $aContentInfo['date_end'];
+    }
+
+    public function serviceGetCalendarEntries($iProfileId)
+    {
+        $CNF = &$this->_oConfig->CNF;
+        $oConn = BxDolConnection::getObjectInstance($CNF['OBJECT_CONNECTIONS']);
+        $aData = $oConn->getConnectedContent($iProfileId);
+        $aData2 = array(0);
+        foreach($aData as $iProfileId2){
+            $oProfile = BxDolProfile::getInstance($iProfileId2);
+            array_push($aData2, $oProfile->getContentId());
+        }
+        $aSQLPart['where'] = " AND `bx_events_data`.`id` IN(" . implode(',', $aData2) . ")";
+        return $this->_oDb->getEntriesByDate(bx_get('start'), bx_get('end'), null, $aSQLPart);
+	}
+
+    public function serviceGetSafeServices()
+    {
+        $a = parent::serviceGetSafeServices();
+        return array_merge($a, array (
+            'BrowsePastProfiles' => '',
+            'Calendar' => '',
+        ));
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_events Events
+     * @subsection bx_events-browse Browse
+     * @subsubsection bx_events-browse_upcoming_profiles browse_upcoming_profiles
+     * 
+     * @code bx_srv('bx_events', 'browse_upcoming_profiles', [...]); @endcode
+     * 
+     * Browse upcoming events
+     * 
+     * @param $bDisplayEmptyMsg show "empty" message or not if nothing found
+     * @param $bAjaxPaginate use AJAX paginate or not
+     *
+     * @see BxEventsModule::serviceBrowseUpcomingProfiles
+     */
+    /** 
+     * @ref bx_events-browse_upcoming_profiles "browse_upcoming_profiles"
+     */
+    public function serviceBrowseUpcomingProfiles ($aParams = false)
+    {
+        $bDisplayEmptyMsg = false;
+        if(isset($aParams['empty_message'])) {
+            $bDisplayEmptyMsg = (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->_serviceBrowse ('upcoming', $aParams, BX_DB_PADDING_DEF, $bDisplayEmptyMsg, $bAjaxPaginate);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_events Events
+     * @subsection bx_events-browse Browse
+     * @subsubsection bx_events-browse_upcoming_connected_profiles browse_upcoming_connected_profiles
+     * 
+     * @code bx_srv('bx_events', 'browse_upcoming_connected_profiles', [...]); @endcode
+     * 
+     * Browse upcoming connected (followed) events
+     * 
+     * @param $bDisplayEmptyMsg show "empty" message or not if nothing found
+     * @param $bAjaxPaginate use AJAX paginate or not
+     *
+     * @see BxEventsModule::serviceBrowseUpcomingConnectedProfiles
+     */
+    /** 
+     * @ref bx_events-browse_upcoming_connected_profiles "browse_upcoming_connected_profiles"
+     */
+    public function serviceBrowseUpcomingConnectedProfiles ($aParams = false)
+    {
+        if(!is_array($aParams) || empty($aParams['object']) || empty($aParams['profile']))
+            return '';
+
+        $bDisplayEmptyMsg = false;
+        if(isset($aParams['empty_message'])) {
+            $bDisplayEmptyMsg = (bool)$aParams['empty_message'];
+            unset($aParams['empty_message']);
+        }
+
+        $bAjaxPaginate = true;
+        if(isset($aParams['ajax_paginate'])) {
+            $bAjaxPaginate = (bool)$aParams['ajax_paginate'];
+            unset($aParams['ajax_paginate']);
+        }
+
+        $aDefaults = array(
+            'type' => 'content',
+            'mutual' => false,
+            'profile2' => 0
+        );
+
+        return $this->_serviceBrowse ('upcoming_connected', array_merge($aDefaults, $aParams), BX_DB_PADDING_DEF, $bDisplayEmptyMsg, $bAjaxPaginate);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_events Events
+     * @subsection bx_events-browse Browse
+     * @subsubsection bx_events-browse_past_profiles browse_past_profiles
+     * 
+     * @code bx_srv('bx_events', 'browse_past_profiles', [...]); @endcode
+     * 
+     * Browse past events
+     * 
+     * @param $bDisplayEmptyMsg show "empty" message or not if nothing found
+     * @param $bAjaxPaginate use AJAX paginate or not
+     *
+     * @see BxEventsModule::serviceBrowsePastProfiles
+     */
+    /** 
+     * @ref bx_events-browse_past_profiles "browse_past_profiles"
+     */
+    public function serviceBrowsePastProfiles ($bDisplayEmptyMsg = false, $bAjaxPaginate = true)
+    {
+        return $this->_serviceBrowse ('past', false, BX_DB_PADDING_DEF, $bDisplayEmptyMsg, $bAjaxPaginate);
+    }
+    
+    /**
+     * @page service Service Calls
+     * @section bx_events Events
+     * @subsection bx_events-browse Browse
+     * @subsubsection bx_events-browse_past_profiles browse_past_profiles_by_params
+     * 
+     * @code bx_srv('bx_events', 'browse_past_profiles_by_params', [...]); @endcode
+     * 
+     * Browse past events
+     * 
+     * @param $aParams array with all parameters
+     *
+     * @see BxEventsModule::serviceBrowsePastProfilesByParams
+     */
+    /** 
+     * @ref bx_events-browse_past_profiles_by_params "browse_past_profiles_by_params"
+     */
+    public function serviceBrowsePastProfilesByParams ($aParams)
+    {
+        $bDisplayEmptyMsg = false;
+        if(isset($aParams['empty_message'])) {
+            $bDisplayEmptyMsg = (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->_serviceBrowse ('past', $aParams, BX_DB_PADDING_DEF, $bDisplayEmptyMsg, $bAjaxPaginate);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_events Events
+     * @subsection bx_events-page_blocks Page Blocks
+     * @subsubsection bx_events-calendar calendar
+     * 
+     * @code bx_srv('bx_events', 'calendar', [...]); @endcode
+     * 
+     * Shows event or events calendar
+     * 
+     * @param $aData additional data to point which events to show, leave empty to show all events, specify event's ID in 'event' array key to show calendar for one event only, specify context's ID in 'context_id' array key to show calendar for one context events only. If only one event is specified then it will show calendar only if it's repeating event.
+     * @param $sTemplate template to use to show calendar, or leave empty for default template, possible options: calendar.html, calendar_compact.html
+     * @return HTML string with calendar to display on the site, all necessary CSS and JS files are automatically added to the HEAD section of the site HTML. On error empty string is returned.
+     *
+     * @see BxEventsModule::serviceCalendar
+     */
+    /** 
+     * @ref bx_events-calendar "calendar"
+     */
+    public function serviceCalendar($aData = array(), $sTemplate = 'calendar.html')
+    {
+        if (isset($aData['event'])) {
+            $aContentInfo = $this->_oDb->getContentInfoById ((int)$aData['event']);
+            if ('' == $aContentInfo['repeat_stop']) // don't display calendar for non repeating events
+                return '';
+        } 
+
+        if (isset($aData['context_id'])) {
+            if (!$this->serviceIsEnableForContext($aData['context_id'])){
+                return '';
+            }                
+        } 
+
+        $oCalendar = new BxTemplCalendar(array(
+            'eventSources' => array (
+                bx_append_url_params(BX_DOL_URL_ROOT . $this->_oConfig->getBaseUri() . 'calendar_data', $aData),
+            ),
+        ), $this->_oTemplate);
+
+        $this->_oTemplate->addCss(array('main.css'));
+        return $oCalendar->display($sTemplate);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_events Events
+     * @subsection bx_events-other Other
+     * @subsubsection bx_events-process_reminders process_reminders
+     * 
+     * @code bx_srv('bx_events', 'process_reminders'); @endcode
+     * 
+     * Send remiders to event's participants.
+     *
+     * It must be processed once every hour for the proper processing.
+     * @return nothing
+     *
+     * @see BxEventsModule::serviceProcessReminders
+     */
+    /** 
+     * @ref bx_events-process_reminders "process_reminders"
+     */
+    public function serviceProcessReminders()
+    {
+        $iNow = time();
+
+        // get all events for today and tomorrow, since the max reminder is 24 hours
+        $aEntries = $this->_oDb->getEntriesByDate('@' . time(), '@' . (time() + 3600 * getParam('bx_events_reminder_interval')));
+
+        foreach ($aEntries as $a) {
+            if (!$a['reminder'])
+                continue;
+            $iTimestamp = $a['start_utc'] - (3600 * $a['reminder']);
+            if ($iNow > ($iTimestamp - 3600) && $iNow < $iTimestamp)
+                $this->sendReminders($a);
+        }
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_events Events
+     * @subsection bx_events-internal Internal
+     * @subsubsection bx_events-get_timeline_post get_timeline_post
+     *
+     * @code bx_srv('bx_events', 'get_timeline_post', [...]); @endcode
+     * 
+     * Get Timeline post. It's needed for Timeline module.
+     * 
+     * @param $aEvent timeline event array from Timeline module
+     * @return array in special format which is needed specifically for Timeline module to display the data.
+     *
+     * @see BxEventsModule::serviceGetTimelinePost
+     */
+    /** 
+     * @ref bx_events-get_timeline_post "get_timeline_post"
+     */
+    public function serviceGetTimelinePost($aEvent, $aBrowseParams = array())
+    {
+        $a = parent::serviceGetTimelinePost($aEvent, $aBrowseParams);
+        if($a === false)
+            return false;
+
+        $aContentInfo = $this->_oDb->getContentInfoById($aEvent['object_id']);
+        if(empty($aContentInfo) || !is_array($aContentInfo))
+            return $a;
+
+        $CNF = $this->_oConfig->CNF;
+
+        $oDateStart = date_create('@' . $aContentInfo['date_start']);
+        if ($oDateStart)
+            $oDateStart->setTimezone(new DateTimeZone($aContentInfo['timezone'] ? $aContentInfo['timezone'] : 'UTC'));
+
+        $oMetatags = BxDolMetatags::getObjectInstance($CNF['OBJECT_METATAGS']);
+        $sLocationString = $oMetatags ? $oMetatags->locationsString($aContentInfo[$CNF['FIELD_ID']], false) : false;
+
+        $a['content']['raw'] = $this->_oTemplate->parseHtmlByName('timeline_post.html', [
+            'title' => $a['content']['title'],
+            'title_attr' => bx_html_attribute($a['content']['title']),
+            'url' => $a['content']['url'],
+            'bx_if:date' => [
+                'condition' => $oDateStart,
+                'content' => [
+                    'date' => $oDateStart ? bx_time_js($aContentInfo['date_start'], BX_FORMAT_DATE_TIME) : '',
+                    'date_c' => $oDateStart->format('c'),
+            ]],
+            'bx_if:location' => array(
+                'condition' => !!$sLocationString,
+                'content' => array('location' => $sLocationString),
+            ),
+        ]);
+
+        $a['content']['title'] = '';
+        $a['content']['text'] = '';
+
+        return $a;
+    }
+    
+    public function actionIntervals()
+    {
+        $sAction = bx_get('a');
+        $sMethodName = 'subaction' . ucfirst($sAction);
+        if (!method_exists($this, $sMethodName)) {
+            $this->_oTemplate->pageNotFound();
+            return;
+        }
+        $this->$sMethodName();
+    }
+
+    public function subactionRestore($iContentId = 0)
+    {
+        if (!$iContentId)
+            $iContentId = (int)bx_get('c');
+
+        $aContentInfo = $this->_oDb->getContentInfoById($iContentId);
+
+        if (
+            ($aContentInfo && CHECK_ACTION_RESULT_ALLOWED !== $this->checkAllowedEdit ($aContentInfo))
+            ||
+            (!$aContentInfo && CHECK_ACTION_RESULT_ALLOWED !== $this->checkAllowedAdd ())
+        ) {
+            $this->_oTemplate->displayAccessDenied();
+            exit;
+        }
+
+        $a = $this->_oDb->getIntervals($iContentId);
+        foreach ($a as $iIntervalId => $r) {
+            $a[$iIntervalId]['file_id'] = $r['interval_id'];
+            $a[$iIntervalId]['repeat_stop'] = bx_process_output ($r['repeat_stop'], BX_DATA_DATE_TS);
+        }
+
+        if ('json' == bx_get('f')) {
+            header('Content-type: text/html; charset=utf-8');
+            echo json_encode($a);
+        }
+    }
+
+    public function subactionDelete()
+    {
+        header('Content-type: text/html; charset=utf-8');
+
+        $iIntervalId = (int)bx_get('id');
+
+        if (!($aContentInfo = $this->_oDb->getContentInfoByIntervalId($iIntervalId))) {
+            echo _t('_sys_request_page_not_found_cpt');
+        }
+        elseif (CHECK_ACTION_RESULT_ALLOWED !== ($sMsg = $this->checkAllowedEdit ($aContentInfo))) {
+            echo $sMsg;
+        } 
+        elseif (!$this->_oDb->deleteIntervalById($iIntervalId)) {
+            echo _t('_sys_txt_error_occured');
+        } 
+        else {
+            echo 'ok';
+        }
+    }
+
+    /**
+     * Send reminder to event's paritcipants
+     * @param $aContentInfo content info
+     * @return number of sent reminders
+     */ 
+    protected function sendReminders($aContentInfo)
+    {
+        $CNF = $this->_oConfig->CNF;
+
+        $oConnection = BxDolConnection::getObjectInstance($CNF['OBJECT_CONNECTIONS']);
+        if (!$oConnection)
+            return false;
+
+        $oGroupProfile = BxDolProfile::getInstanceByContentAndType($aContentInfo[$CNF['FIELD_ID']], $this->getName());
+        if (!$oGroupProfile)
+            return false;
+
+        $aParticipants = $oConnection->getConnectedInitiators($oGroupProfile->id(), true);
+        if (!$aParticipants)
+            return true;
+
+        $oDateBegin = new DateTime();
+        $oDateBegin->setTimestamp($aContentInfo['start_utc']);
+        $oDateBegin->setTimezone(new DateTimeZone($aContentInfo['timezone'] ? $aContentInfo['timezone'] : 'UTC'));
+        $sEntryBegin = $oDateBegin->format('r');
+        $sEntryBeginShort = date(getParam('bx_events_short_date_format'), $oDateBegin->getTimestamp());
+        $oDateBegin->setTimezone(new DateTimeZone('UTC'));
+        $sEntryBeginUTC = $oDateBegin->format('c');
+
+        $oMetatags = BxDolMetatags::getObjectInstance($CNF['OBJECT_METATAGS']);
+        $sLocationString = $oMetatags->locationsString($aContentInfo[$CNF['FIELD_ID']], false);
+
+        $iCounter = 0;
+        foreach ($aParticipants as $iProfileId) {
+
+            $b = sendMailTemplate($CNF['EMAIL_REMINDER'], 0, $iProfileId, array(
+                'EntryUrl' => BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink('page.php?i=' . $CNF['URI_VIEW_ENTRY'] . '&id=' . $aContentInfo[$CNF['FIELD_ID']]),
+                'EntryTitle' => $aContentInfo['title'],
+                'EntryBegin' => $sEntryBegin,
+                'EntryBeginShort' => $sEntryBeginShort,
+                'EntryBeginUTC' => $sEntryBeginUTC,
+                'EntryLocation' => $sLocationString ? _t('_bx_events_email_reminder_location', $sLocationString) : '',
+            ), BX_EMAIL_NOTIFY);
+
+            $iCounter += $b ? 1 : 0;
+        }
+        return $iCounter;
+    }
+}
+
+/** @} */

+ 55 - 0
modules/boonex/events/updates/13.0.2_13.0.3/source/classes/BxEventsTemplate.php

@@ -0,0 +1,55 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Events Events
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+/*
+ * Groups module representation.
+ */
+class BxEventsTemplate extends BxBaseModGroupsTemplate
+{
+    function __construct(&$oConfig, &$oDb)
+    {
+        $this->MODULE = 'bx_events';
+        parent::__construct($oConfig, $oDb);
+    }
+
+    function unitVars ($aData, $isCheckPrivateContent = true, $mixedTemplate = false, $aParams = array())
+    {
+        $aVars = parent::unitVars ($aData, $isCheckPrivateContent, $mixedTemplate, $aParams);
+
+        $CNF = &$this->_oConfig->CNF;
+
+        $oPrivacy = BxDolPrivacy::getObjectInstance($CNF['OBJECT_PRIVACY_VIEW']);
+
+        $aContentInfo = $this->getModule()->_oDb->getContentInfoById($aData[$CNF['FIELD_ID']]);
+
+        $oDateStart = date_create('@' . $aContentInfo['date_start']);
+        if ($oDateStart)
+            $oDateStart->setTimezone(new DateTimeZone($aContentInfo['timezone'] ? $aContentInfo['timezone'] : 'UTC'));
+
+        $oDateEnd = date_create('@' . $aContentInfo['date_end']);
+        if ($oDateEnd)
+            $oDateEnd->setTimezone(new DateTimeZone($aContentInfo['timezone'] ? $aContentInfo['timezone'] : 'UTC'));
+
+        $isPublic = CHECK_ACTION_RESULT_ALLOWED === $this->getModule()->checkAllowedView($aData) || $oPrivacy->isPartiallyVisible($aData[$CNF['FIELD_ALLOW_VIEW_TO']]);        
+        if ($isPublic) {
+            $aVars['bx_if:info']['content']['members'] = $oDateStart->format(getParam('bx_events_short_date_format'));
+        }
+
+        return array_merge($aVars, array(
+			'date_start' => $aData['date_start'],
+			'date_start_f' => date(getParam('bx_events_short_date_format'), $oDateStart->getTimestamp()),
+			'date_end' => $aData['date_end'],
+			'date_end_f' => date(getParam('bx_events_short_date_format'), $oDateEnd->getTimestamp()),
+        ));
+    }
+}
+
+/** @} */

+ 152 - 0
modules/boonex/events/updates/13.0.2_13.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    Events Events
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_events',
+    'title' => 'Events',
+    'note' => 'Events functionality.',
+    'version' => '13.0.3',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '13.0.0-B2'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/events/',
+    'home_uri' => 'events',
+
+    'db_prefix' => 'bx_events_',
+    'class_prefix' => 'BxEvents',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Events',
+
+    /**
+     * 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_events_pics'
+    ),
+
+	/**
+     * Transcoders.
+     */
+    'transcoders' => array(
+    	'bx_events_icon', 
+    	'bx_events_thumb', 
+    	'bx_events_avatar', 
+        'bx_events_avatar_big', 
+    	'bx_events_picture', 
+    	'bx_events_cover', 
+    	'bx_events_cover_thumb',
+    	'bx_events_gallery'
+    ),
+
+    /**
+     * Extended Search Forms.
+     */
+    'esearches' => array(
+        'bx_events',
+    	'bx_events_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',
+    ),
+);
+
+/** @} */

+ 586 - 0
modules/boonex/events/updates/13.0.2_13.0.3/source/install/langs/en.xml

@@ -0,0 +1,586 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources name="en" flag="gb" title="English">
+    <string name="_bx_events"><![CDATA[Events]]></string>
+    <string name="_bx_events_cmts"><![CDATA[Events' Comments]]></string>
+
+    <string name="_bx_events_option_enable_auto_approve"><![CDATA[Auto approve an event after creation]]></string>
+    <string name="_bx_events_option_num_connections_quick"><![CDATA[Number of items in friends block]]></string>
+    <string name="_bx_events_option_per_page_browse"><![CDATA[Number of items per page]]></string>
+    <string name="_bx_events_option_num_rss"><![CDATA[Number of items in RSS feed]]></string>
+    <string name="_bx_events_option_time_format"><![CDATA[Time format]]></string>
+    <string name="_bx_events_option_short_date_format"><![CDATA[Short date format]]></string>
+    <string name="_bx_events_option_datetime_format"><![CDATA[Date and time format]]></string>
+    <string name="_bx_events_option_summary_chars"><![CDATA[Number of characters in auto-cropped event summary]]></string>
+    <string name="_bx_events_option_searchable_fields"><![CDATA[Searchable fields]]></string>
+    <string name="_bx_events_option_members_mode"><![CDATA[Special mode for event members]]></string>
+    <string name="_bx_events_option_members_mode_multi_roles"><![CDATA[Multi Roles]]></string>
+    <string name="_bx_events_option_public_subscribed_me"><![CDATA[Public list of interested members]]></string>
+    <string name="_bx_events_option_per_page_for_favorites_lists"><![CDATA[Number of favorite lists per page]]></string>
+    <string name="_bx_events_option_internal_notifications"><![CDATA[Use internal notifications]]></string>
+
+    <string name="_bx_events_form_profile"><![CDATA[Events]]></string>
+    <string name="_bx_events_form_profile_display_add"><![CDATA[Add Event]]></string>
+    <string name="_bx_events_form_profile_display_edit"><![CDATA[Edit Event]]></string>
+    <string name="_bx_events_form_profile_display_edit_cover"><![CDATA[Edit Cover]]></string>
+    <string name="_bx_events_form_profile_display_delete"><![CDATA[Delete Event]]></string>
+    <string name="_bx_events_form_profile_display_view"><![CDATA[View Event]]></string>
+    <string name="_bx_events_form_profile_display_view_full"><![CDATA[Full View Event]]></string>
+    <string name="_bx_events_form_profile_display_invite"><![CDATA[Invite to Event]]></string>
+    <string name="_bx_events_form_profile_input_author"><![CDATA[Author]]></string>
+    <string name="_bx_events_form_profile_input_sys_do_submit"><![CDATA[Submit]]></string>
+    <string name="_bx_events_form_profile_input_sys_join_confirm"><![CDATA[Join confirmation]]></string>
+    <string name="_bx_events_form_profile_input_join_confirm"><![CDATA[Approval required to join]]></string>
+    <string name="_bx_events_form_profile_input_sys_allow_view_to"><![CDATA[Visible to]]></string>
+    <string name="_bx_events_form_profile_input_allow_view_to"><![CDATA[Visible to]]></string>
+    <string name="_bx_events_form_profile_input_allow_view_favorite_list"><![CDATA[Visibility]]></string>
+    <string name="_bx_events_form_profile_input_allow_view_to_desc"><![CDATA[Closed - anyone can find the event and see who's in it, only members can see posts. Secret - only members can find the event and see posts.]]></string>
+    <string name="_bx_events_form_profile_input_sys_allow_post_to"><![CDATA[Who can post]]></string>
+    <string name="_bx_events_form_profile_input_allow_post_to"><![CDATA[Who can post]]></string>
+    <string name="_bx_events_form_profile_input_sys_initial_members"><![CDATA[Invite Members]]></string>
+    <string name="_bx_events_form_profile_input_initial_members"><![CDATA[Invite Members]]></string>
+    <string name="_bx_events_form_profile_input_sys_event_name"><![CDATA[Event Name]]></string>
+    <string name="_bx_events_form_profile_input_event_name"><![CDATA[Event Name]]></string>
+    <string name="_bx_events_form_profile_input_event_name_err"><![CDATA[This information is essential. Please, fill in this field.]]></string>
+    <string name="_bx_events_form_profile_input_sys_event_desc"><![CDATA[Description]]></string>
+    <string name="_bx_events_form_profile_input_event_desc"><![CDATA[Description]]></string>
+    <string name="_bx_events_form_profile_input_sys_event_cat"><![CDATA[Category]]></string>
+    <string name="_bx_events_form_profile_input_event_cat"><![CDATA[Category]]></string>
+    <string name="_bx_events_form_profile_input_event_cat_err"><![CDATA[Category field is mandatory]]></string>
+    <string name="_bx_events_form_profile_input_sys_picture"><![CDATA[Event Picture]]></string>
+    <string name="_bx_events_form_profile_input_picture"><![CDATA[Upload New Event Picture]]></string>
+    <string name="_bx_events_form_profile_input_picture_err"><![CDATA[Event picture is mandatory.]]></string>
+    <string name="_bx_events_form_profile_input_sys_cover"><![CDATA[Cover Picture]]></string>
+    <string name="_bx_events_form_profile_input_cover"><![CDATA[Upload New Cover Picture]]></string>
+    <string name="_bx_events_form_profile_input_sys_delete_confirm"><![CDATA[Delete confirmation]]></string>
+    <string name="_bx_events_form_profile_input_delete_confirm"><![CDATA[I am sure I want to delete this event]]></string>
+    <string name="_bx_events_form_profile_input_delete_confirm_info"><![CDATA[This action can not be undone.]]></string>
+    <string name="_bx_events_form_profile_input_delete_confirm_error"><![CDATA[Please check this checkbox if you really want to delete event.]]></string>
+    <string name="_bx_events_form_profile_input_sys_reoccurring"><![CDATA[Reoccurring]]></string>
+    <string name="_bx_events_form_profile_input_reoccurring"><![CDATA[Reoccurring]]></string>
+    <string name="_bx_events_form_profile_input_reoccurring_add_interval"><![CDATA[Add repeating interval]]></string>
+    <string name="_bx_events_form_profile_input_sys_date_added"><![CDATA[Created]]></string>
+    <string name="_bx_events_form_profile_input_date_added"><![CDATA[Created]]></string>
+    <string name="_bx_events_form_profile_input_sys_date_changed"><![CDATA[Updated]]></string>
+    <string name="_bx_events_form_profile_input_date_changed"><![CDATA[Updated]]></string>
+    <string name="_bx_events_form_profile_input_sys_date_published"><![CDATA[Publishing time]]></string>
+    <string name="_bx_events_form_profile_input_date_published"><![CDATA[Publishing time]]></string>
+    <string name="_bx_events_form_profile_input_date_published_info"><![CDATA[Leave empty to publish immediately.]]></string>
+    <string name="_bx_events_form_profile_input_sys_date_start"><![CDATA[Date start]]></string>
+    <string name="_bx_events_form_profile_input_date_start"><![CDATA[Date start]]></string>
+    <string name="_bx_events_form_profile_input_date_start_err"><![CDATA[Start date is mandatory]]></string>
+    <string name="_bx_events_form_profile_input_sys_date_end"><![CDATA[Date end]]></string>
+    <string name="_bx_events_form_profile_input_date_end"><![CDATA[Date end]]></string>    
+    <string name="_bx_events_form_profile_input_date_end_err"><![CDATA[End date is mandatory]]></string>
+    <string name="_bx_events_form_profile_input_date_end_invalid_err"><![CDATA[End date must be must be greater than start date]]></string>
+    <string name="_bx_events_form_profile_input_sys_timezone"><![CDATA[Timezone]]></string>
+    <string name="_bx_events_form_profile_input_timezone"><![CDATA[Timezone]]></string>
+    <string name="_bx_events_form_profile_input_sys_time"><![CDATA[Time]]></string>
+    <string name="_bx_events_form_profile_input_time"><![CDATA[Time]]></string>
+    <string name="_bx_events_form_profile_input_sys_reminder"><![CDATA[Reminder]]></string>
+    <string name="_bx_events_form_profile_input_reminder"><![CDATA[Reminder]]></string>
+
+    <string name="_bx_events_form_input_repeat_year"><![CDATA[Repeat year]]></string>
+    <string name="_bx_events_form_input_repeat_month"><![CDATA[Repeat month]]></string>
+    <string name="_bx_events_form_input_repeat_week_of_month"><![CDATA[Repeat week of month]]></string>
+    <string name="_bx_events_form_input_repeat_day_of_month"><![CDATA[Repeat day of month]]></string>
+    <string name="_bx_events_form_input_repeat_day_of_week"><![CDATA[Repeat day of week]]></string>
+    <string name="_bx_events_form_input_stop_repeating"><![CDATA[Stop repeating]]></string>
+
+<string name="_bx_events_form_price"><![CDATA[Price]]></string>
+    <string name="_bx_events_form_price_display_add"><![CDATA[Add]]></string>
+    <string name="_bx_events_form_price_display_edit"><![CDATA[Edit]]></string>
+    <string name="_bx_events_form_price_input_sys_id"><![CDATA[ID]]></string>
+    <string name="_bx_events_form_price_input_sys_role_id"><![CDATA[Role ID]]></string>
+    <string name="_bx_events_form_price_input_sys_name"><![CDATA[Name]]></string>
+    <string name="_bx_events_form_price_input_name"><![CDATA[Name]]></string>
+    <string name="_bx_events_form_price_input_inf_name"><![CDATA[Unique value which will be used in back end and API calls]]></string>
+    <string name="_bx_events_form_price_input_err_name"><![CDATA[You need to enter a unique value here]]></string>
+    <string name="_bx_events_form_price_input_sys_period"><![CDATA[Period]]></string>
+    <string name="_bx_events_form_price_input_period"><![CDATA[Period]]></string>
+    <string name="_bx_events_form_price_input_inf_period"><![CDATA[Use 0 for lifetime]]></string>
+    <string name="_bx_events_form_price_input_sys_period_unit"><![CDATA[Period unit]]></string>
+    <string name="_bx_events_form_price_input_period_unit"><![CDATA[Period unit]]></string>
+    <string name="_bx_events_form_price_input_inf_period_unit"><![CDATA[Leave empty for lifetime level.]]></string>
+    <string name="_bx_events_form_price_input_err_period_unit"><![CDATA[You need to select a period unit here.]]></string>
+    <string name="_bx_events_form_price_input_sys_price"><![CDATA[Price]]></string>
+    <string name="_bx_events_form_price_input_price"><![CDATA[Price]]></string>
+    <string name="_bx_events_form_price_input_inf_price"><![CDATA[Use 0 or leave empty to create free level.]]></string>
+    <string name="_bx_events_form_price_input_sys_do_submit"><![CDATA[Submit]]></string>
+    <string name="_bx_events_form_price_input_do_submit"><![CDATA[Submit]]></string>
+    <string name="_bx_events_form_price_input_sys_do_cancel"><![CDATA[Cancel]]></string>
+    <string name="_bx_events_form_price_input_do_cancel"><![CDATA[Cancel]]></string>
+
+    <string name="_bx_events_acl_action_create_profile"><![CDATA[Create Event]]></string>
+    <string name="_bx_events_acl_action_use_paid_join"><![CDATA[Use paid join]]></string>
+    <string name="_bx_events_acl_action_delete_profile"><![CDATA[Delete Event]]></string>
+    <string name="_bx_events_acl_action_view_profile"><![CDATA[View Event]]></string>
+    <string name="_bx_events_acl_action_edit_any_profile"><![CDATA[Edit Any Event]]></string>
+    <string name="_bx_events_acl_action_delete_any_profile"><![CDATA[Delete Any Event]]></string>
+    <string name="_bx_events_acl_action_delete_invites"><![CDATA[Delete Invites]]></string>
+
+    <string name="_bx_events_page_title_sys_joined"><![CDATA[Profile Events]]></string>
+    <string name="_bx_events_page_title_joined"><![CDATA[Profile Events]]></string>
+    <string name="_bx_events_page_title_sys_joined_entries"><![CDATA[Profile Events]]></string>
+    <string name="_bx_events_page_title_joined_entries"><![CDATA[Profile Events]]></string>
+    <string name="_bx_events_page_title_sys_entries_in_context"><![CDATA[Events in context]]></string>
+    <string name="_bx_events_page_title_entries_in_context"><![CDATA[Events in {display_name}]]></string>
+    <string name="_bx_events_page_title_sys_create_profile"><![CDATA[Create Event]]></string>
+    <string name="_bx_events_page_title_create_profile"><![CDATA[Create Event]]></string>
+    <string name="_bx_events_page_title_sys_edit_profile"><![CDATA[Edit Event]]></string>
+    <string name="_bx_events_page_title_edit_profile"><![CDATA[Edit Event]]></string>
+    <string name="_bx_events_page_title_sys_edit_profile_cover"><![CDATA[Edit Event Cover]]></string>
+    <string name="_bx_events_page_title_edit_profile_cover"><![CDATA[Edit Cover]]></string>
+    <string name="_bx_events_page_title_sys_delete_profile"><![CDATA[Delete Event]]></string>
+    <string name="_bx_events_page_title_delete_profile"><![CDATA[Delete Event]]></string>
+    <string name="_bx_events_page_title_sys_join_profile"><![CDATA[Join Course]]></string>
+    <string name="_bx_events_page_title_join_profile"><![CDATA[Join Course]]></string>
+    <string name="_bx_events_page_title_sys_view_profile_closed"><![CDATA[View Closed Event]]></string>
+    <string name="_bx_events_page_title_sys_view_profile"><![CDATA[View Event]]></string>
+    <string name="_bx_events_page_title_view_profile"><![CDATA[{display_name}]]></string>
+    <string name="_bx_events_page_title_browse"><![CDATA[Events]]></string>
+    <string name="_bx_events_page_title_browse_by_author"><![CDATA[Events of {display_name}]]></string>
+    <string name="_bx_events_page_title_browse_by_context"><![CDATA[Events in {display_name}]]></string>
+    <string name="_bx_events_page_title_browse_featured"><![CDATA[Featured Events]]></string>
+    <string name="_bx_events_page_title_browse_top"><![CDATA[Top Events]]></string>
+    <string name="_bx_events_page_title_browse_upcoming"><![CDATA[Upcoming Events]]></string>
+    <string name="_bx_events_page_title_browse_past"><![CDATA[Past Events]]></string>
+    <string name="_bx_events_page_title_browse_recent"><![CDATA[New Events]]></string>
+    <string name="_bx_events_page_title_browse_connections"><![CDATA[{0} connections]]></string>
+    <string name="_bx_events_page_title_browse_connections_mutual"><![CDATA[{0} and {1} mutual connections]]></string>
+    <string name="_bx_events_page_title_sys_profile_friends"><![CDATA[Friends]]></string>
+    <string name="_bx_events_page_title_profile_friends"><![CDATA[Friends]]></string>
+    <string name="_bx_events_page_title_sys_group_fans"><![CDATA[Guests]]></string>
+    <string name="_bx_events_page_title_group_fans"><![CDATA[Guests]]></string>
+    <string name="_bx_events_page_title_sys_profile_comments"><![CDATA[Comments]]></string>
+    <string name="_bx_events_page_title_profile_comments"><![CDATA[Comments]]></string>
+    <string name="_bx_events_page_title_sys_profile_info"><![CDATA[Event Info]]></string>
+    <string name="_bx_events_page_title_profile_info"><![CDATA[Info about {display_name}]]></string>
+    <string name="_bx_events_page_title_sys_profile_pricing"><![CDATA[Pricing]]></string>
+    <string name="_bx_events_page_title_profile_pricing"><![CDATA[Pricing]]></string>
+    <string name="_bx_events_page_title_sys_recent"><![CDATA[New Events]]></string>
+    <string name="_bx_events_page_title_recent"><![CDATA[New Events]]></string>
+    <string name="_bx_events_page_title_sys_manage"><![CDATA[Manage Own Events]]></string>
+    <string name="_bx_events_page_title_sys_manage_administration"><![CDATA[Manage All Events]]></string>
+    <string name="_bx_events_page_title_manage"><![CDATA[Manage Events]]></string>
+    <string name="_bx_events_page_title_sys_top"><![CDATA[Top Events]]></string>
+    <string name="_bx_events_page_title_top"><![CDATA[Top Events]]></string>
+    <string name="_bx_events_page_title_sys_upcoming"><![CDATA[Upcoming Events]]></string>
+    <string name="_bx_events_page_title_upcoming"><![CDATA[Upcoming Events]]></string>
+    <string name="_bx_events_page_title_sys_past"><![CDATA[Past Events]]></string>
+    <string name="_bx_events_page_title_past"><![CDATA[Past Events]]></string>
+    <string name="_bx_events_page_title_sys_calendar"><![CDATA[Events Calendar]]></string>
+    <string name="_bx_events_page_title_calendar"><![CDATA[Events Calendar]]></string>
+    <string name="_bx_events_page_title_sys_invite_to_group"><![CDATA[Invite Members to the Event]]></string>
+    <string name="_bx_events_page_title_invite_to_group"><![CDATA[Invite Members to the Event]]></string>
+    <string name="_bx_events_page_title_sys_entries_search"><![CDATA[Search]]></string>
+    <string name="_bx_events_page_title_entries_search"><![CDATA[Search]]></string>
+    <string name="_bx_events_page_title_sys_entries_favorites"><![CDATA[Favorites Events]]></string>
+    <string name="_bx_events_page_title_entries_favorites"><![CDATA[Favorites Events]]></string>
+
+    <string name="_bx_events_page_block_title_sys_entries_actions"><![CDATA[Events actions]]></string>
+    <string name="_bx_events_page_block_title_entries_actions"><![CDATA[Events actions]]></string>
+    <string name="_bx_events_page_block_title_entries_in_context"><![CDATA[Events in <a href="{profile_link}">{display_name}</a>]]></string>
+    <string name="_bx_events_page_block_title_sys_entries_in_context"><![CDATA[Events in context]]></string>
+    <string name="_bx_events_page_block_title_calendar_in_context"><![CDATA[Events Calendar in <a href="{profile_link}">{display_name}</a>]]></string>
+    <string name="_bx_events_page_block_title_sys_calendar_in_context"><![CDATA[Events Calendar]]></string>
+    <string name="_bx_events_page_block_title_calendar_for_context"><![CDATA[Events Calendar]]></string>
+    <string name="_bx_events_page_block_title_browse_for_context"><![CDATA[Events in context]]></string>
+    <string name="_bx_events_page_block_title_sys_favorites_entries"><![CDATA[Favorite List]]></string>
+    <string name="_bx_events_page_block_title_favorites_entries"><![CDATA["{title}" List]]></string>
+    <string name="_bx_events_page_block_title_favorites_entries_info"><![CDATA[Info]]></string>
+    <string name="_bx_events_page_block_title_favorites_entries_actions"><![CDATA[Favorites List Actions]]></string>
+    <string name="_bx_events_page_block_title_sys_entries_of_author"><![CDATA[Events of author]]></string>
+    <string name="_bx_events_page_block_title_entries_of_author"><![CDATA[Events by {display_name}]]></string>
+    <string name="_bx_events_page_block_title_favorites_of_author"><![CDATA[Favorite Events]]></string>
+    <string name="_bx_events_page_block_title_sys_favorites_of_author"><![CDATA[Favorite Events]]></string>
+    <string name="_bx_events_page_block_title_sys_joined_entries"><![CDATA[Joined Events]]></string>
+    <string name="_bx_events_page_block_title_joined_entries"><![CDATA[Joined Events]]></string>
+    <string name="_bx_events_page_block_title_create_profile"><![CDATA[Create Event]]></string>
+    <string name="_bx_events_page_block_title_edit_profile"><![CDATA[Edit Event]]></string>
+    <string name="_bx_events_page_block_title_edit_profile_cover"><![CDATA[Edit Cover]]></string>
+    <string name="_bx_events_page_block_title_delete_profile"><![CDATA[Delete Event]]></string>
+    <string name="_bx_events_page_block_title_join_profile"><![CDATA[Join Event]]></string>
+    <string name="_bx_events_page_block_title_profile_info_link"><![CDATA[About <a href="{profile_link}">{display_name}</a>]]></string>
+    <string name="_bx_events_page_block_title_profile_info"><![CDATA[Info]]></string>
+    <string name="_bx_events_page_block_title_system_profile_info"><![CDATA[Info]]></string>
+<string name="_bx_events_page_block_title_system_profile_pricing"><![CDATA[Pricing]]></string>
+        <string name="_bx_events_page_block_title_profile_pricing"><![CDATA[Pricing]]></string>
+        <string name="_bx_events_page_block_title_profile_pricing_link"><![CDATA[Pricing of <a href="{profile_link}">{display_name}</a>]]></string>
+    <string name="_bx_events_page_block_title_profile_description"><![CDATA[Description]]></string>
+    <string name="_bx_events_page_block_title_profile_friends_link"><![CDATA[Friends of <a href="{profile_link}">{display_name}</a>]]></string>
+    <string name="_bx_events_page_block_title_profile_friends"><![CDATA[Friends]]></string>
+    <string name="_bx_events_page_block_title_system_profile_friends"><![CDATA[Friends]]></string>
+    <string name="_bx_events_page_block_title_admins"><![CDATA[Administrators]]></string>
+    <string name="_bx_events_page_block_title_fans_link"><![CDATA[Going to <a href="{profile_link}">{display_name}</a>]]></string>
+    <string name="_bx_events_page_block_title_fans"><![CDATA[Going]]></string>
+    <string name="_bx_events_page_block_title_system_fans"><![CDATA[Going]]></string>
+    <string name="_bx_events_page_block_title_fans_invites"><![CDATA[Invites]]></string>
+    <string name="_bx_events_page_block_title_system_invites"><![CDATA[Invites]]></string>
+    <string name="_bx_events_page_block_title_subscribers_link"><![CDATA[Interested in <a href="{profile_link}">{display_name}</a>]]></string>
+    <string name="_bx_events_page_block_title_subscribers"><![CDATA[Interested]]></string>
+    <string name="_bx_events_page_block_title_system_subscribers"><![CDATA[Interested]]></string>
+    <string name="_bx_events_page_block_title_profile_comments"><![CDATA[Comments]]></string>
+	<string name="_bx_events_page_block_title_entry_reports"><![CDATA[Reports]]></string>
+    <string name="_bx_events_page_block_title_profile_comments_link"><![CDATA[Comments to <a href="{entry_link}">{title}</a>]]></string>
+    <string name="_bx_events_page_block_title_profile_actions"><![CDATA[Actions]]></string>
+    <string name="_bx_events_page_block_title_featured_profiles"><![CDATA[Featured Events]]></string>
+    <string name="_bx_events_page_block_title_latest_profiles"><![CDATA[New Events]]></string>
+    <string name="_bx_events_page_block_title_system_manage"><![CDATA[Manage Own Events]]></string>
+    <string name="_bx_events_page_block_title_system_manage_administration"><![CDATA[Manage All Events]]></string>
+    <string name="_bx_events_page_block_title_manage"><![CDATA[Manage Events]]></string>
+    <string name="_bx_events_page_block_title_top_profiles"><![CDATA[Top Events]]></string>
+    <string name="_bx_events_page_block_title_joined_profiles"><![CDATA[Joined Events]]></string>
+    <string name="_bx_events_page_block_title_upcoming_profiles"><![CDATA[Upcoming Events]]></string>
+    <string name="_bx_events_page_block_title_past_profiles"><![CDATA[Past Events]]></string>
+    <string name="_bx_events_page_block_title_entry_all_actions"><![CDATA[All Actions]]></string>
+    <string name="_bx_events_page_block_title_entry_social_sharing"><![CDATA[Share]]></string>
+    <string name="_bx_events_page_block_title_categories"><![CDATA[Event categories]]></string>
+    <string name="_bx_events_page_block_title_calendar"><![CDATA[Events calendar]]></string>
+    <string name="_bx_events_page_block_title_profile_calendar"><![CDATA[Calendar]]></string>
+    <string name="_bx_events_page_block_title_sys_entry_context"><![CDATA[Posted in]]></string>
+    <string name="_bx_events_page_block_title_entry_context"><![CDATA[Posted in]]></string>
+    <string name="_bx_events_page_block_title_entry_location"><![CDATA[Location]]></string>
+    <string name="_bx_events_page_block_title_invite_to_group"><![CDATA[Invite Members to the Event]]></string>
+    <string name="_bx_events_page_block_title_search_form"><![CDATA[Search Form]]></string>
+    <string name="_bx_events_page_block_title_search_results"><![CDATA[Search Results]]></string>
+    <string name="_bx_events_page_block_title_search_form_cmts"><![CDATA[Comments Search Form]]></string>
+    <string name="_bx_events_page_block_title_search_results_cmts"><![CDATA[Comments Search Results]]></string>
+    <string name="_bx_events_page_block_title_sys_featured_entries_view_showcase"><![CDATA[Featured Events (Showcase View)]]></string>
+    <string name="_bx_events_page_block_title_featured_entries_view_showcase"><![CDATA[Featured Events]]></string>
+    <string name="_bx_events_page_block_title_sys_recommended_entries_view_showcase"><![CDATA[Recommended Events (Showcase View)]]></string>
+    <string name="_bx_events_page_block_title_recommended_entries_view_showcase"><![CDATA[Recommended Events]]></string>
+    <string name="_bx_events_page_block_title_sys_cover_block"><![CDATA[Cover]]></string>
+    <string name="_bx_events_page_block_title_cover_block"><![CDATA[Cover]]></string>
+    
+    <string name="_bx_events_menu_title_submenu"><![CDATA[Events Submenu]]></string>
+    <string name="_bx_events_menu_set_title_submenu"><![CDATA[Events Submenu]]></string>
+    <string name="_bx_events_menu_set_title_view_profile_actions"><![CDATA[Event Actions]]></string>
+    <string name="_bx_events_menu_title_view_profile_actions"><![CDATA[Event Actions]]></string>
+    <string name="_bx_events_menu_set_title_view_profile_actions_more"><![CDATA[Event More Actions]]></string>
+    <string name="_bx_events_menu_title_view_profile_actions_more"><![CDATA[Event More Actions]]></string>
+    <string name="_bx_events_menu_title_view_profile_meta"><![CDATA[Event Meta]]></string>
+    <string name="_bx_events_menu_set_title_view_profile_meta"><![CDATA[Event Meta]]></string>
+    <string name="_bx_events_menu_set_title_view_profile_submenu"><![CDATA[View Event Submenu]]></string>
+    <string name="_bx_events_menu_title_view_profile_submenu"><![CDATA[View Event Submenu]]></string>
+    <string name="_bx_events_menu_title_entries_my"><![CDATA[Profile Events Action Menu]]></string>
+    <string name="_bx_events_menu_set_title_entries_my"><![CDATA[Profile Events Menu]]></string>
+    <string name="_bx_events_menu_set_title_manage_tools"><![CDATA[Manage Tools Submenu]]></string>
+    <string name="_bx_events_menu_title_manage_tools"><![CDATA[Manage Tools Submenu]]></string>
+    <string name="_bx_events_menu_item_title_system_delete"><![CDATA[Delete]]></string>
+    <string name="_bx_events_menu_item_title_delete"><![CDATA[Delete]]></string>
+    <string name="_bx_events_menu_item_title_system_delete_with_content"><![CDATA[Delete With Content]]></string>
+    <string name="_bx_events_menu_item_title_delete_with_content"><![CDATA[Delete With Content]]></string>
+    <string name="_bx_events_menu_item_title_system_clear_reports"><![CDATA[Clear reports]]></string>
+    <string name="_bx_events_menu_item_title_clear_reports"><![CDATA[Clear reports]]></string>
+    <string name="_bx_events_menu_item_title_system_edit_cover"><![CDATA[Edit Cover]]></string>
+    <string name="_bx_events_menu_item_title_edit_cover"><![CDATA[Edit Cover]]></string>
+    <string name="_bx_events_menu_item_title_system_edit_pricing"><![CDATA[Edit Pricing]]></string>
+    <string name="_bx_events_menu_item_title_edit_pricing"><![CDATA[Edit Pricing]]></string>
+    <string name="_bx_events_menu_item_title_system_edit_profile"><![CDATA[Edit Event]]></string>
+    <string name="_bx_events_menu_item_title_edit_profile"><![CDATA[Edit Event]]></string>
+    <string name="_bx_events_menu_item_title_system_delete_profile"><![CDATA[Delete Event]]></string>
+    <string name="_bx_events_menu_item_title_delete_profile"><![CDATA[Delete Event]]></string>
+    <string name="_bx_events_menu_item_title_system_delete_account"><![CDATA[Delete Account]]></string>
+    <string name="_bx_events_menu_item_title_delete_account"><![CDATA[Delete Account]]></string>
+    <string name="_bx_events_menu_item_title_system_profile_type"><![CDATA[Event]]></string>
+    <string name="_bx_events_menu_item_title_profile_type"><![CDATA[Event]]></string>
+    <string name="_bx_events_menu_item_title_system_create_profile"><![CDATA[Event]]></string>
+    <string name="_bx_events_menu_item_title_create_profile"><![CDATA[Event]]></string>
+    <string name="_bx_events_menu_item_title_system_view_profile_friends"><![CDATA[Friends]]></string>
+    <string name="_bx_events_menu_item_title_view_profile_friends"><![CDATA[Friends]]></string>
+    <string name="_bx_events_menu_item_title_system_view_joined_groups"><![CDATA[Events]]></string>
+    <string name="_bx_events_menu_item_title_view_joined_groups"><![CDATA[Events]]></string>
+    <string name="_bx_events_menu_item_title_system_view_fans"><![CDATA[Guests]]></string>
+    <string name="_bx_events_menu_item_title_view_fans"><![CDATA[Guests]]></string>
+    <string name="_bx_events_menu_item_title_system_view_profile_comments"><![CDATA[Comments]]></string>
+    <string name="_bx_events_menu_item_title_view_profile_comments"><![CDATA[Comments]]></string>
+    <string name="_bx_events_menu_item_title_system_view_profile_info"><![CDATA[Info]]></string>
+    <string name="_bx_events_menu_item_title_view_profile_info"><![CDATA[Info]]></string>
+    <string name="_bx_events_menu_item_title_system_view_profile_view"><![CDATA[Event]]></string>
+    <string name="_bx_events_menu_item_title_view_profile_view"><![CDATA[Event]]></string>
+    <string name="_bx_events_menu_item_title_system_view_profile_more_auto"><![CDATA[More]]></string>
+    <string name="_bx_events_menu_item_title_view_profile_more_auto"><![CDATA[More]]></string>
+    <string name="_bx_events_menu_item_title_system_invite"><![CDATA[Invite]]></string>
+    <string name="_bx_events_menu_item_title_invite"><![CDATA[Invite]]></string>
+
+    <string name="_bx_events_menu_item_title_system_befriend"><![CDATA[Add friend]]></string>
+    <string name="_bx_events_menu_item_title_befriend"><![CDATA[Add friend]]></string>
+    <string name="_bx_events_menu_item_title_befriend_sent"><![CDATA[Add friend (requested)]]></string>
+    <string name="_bx_events_menu_item_title_befriend_confirm"><![CDATA[Accept friend request]]></string>
+    <string name="_bx_events_menu_item_title_system_unfriend"><![CDATA[Unfriend]]></string>
+    <string name="_bx_events_menu_item_title_unfriend"><![CDATA[Unfriend]]></string>
+    <string name="_bx_events_menu_item_title_unfriend_cancel_request"><![CDATA[Cancel friend request]]></string>
+    <string name="_bx_events_menu_item_title_unfriend_reject_request"><![CDATA[Reject friend request]]></string>
+
+    <string name="_bx_events_menu_item_title_system_become_fan"><![CDATA[Join Event]]></string>
+    <string name="_bx_events_menu_item_title_become_fan"><![CDATA[Going]]></string>
+    <string name="_bx_events_menu_item_title_become_fan_sent"><![CDATA[Requested]]></string>
+    <string name="_bx_events_menu_item_title_become_fan_confirm"><![CDATA[Confirm]]></string>
+    <string name="_bx_events_menu_item_title_system_leave_group"><![CDATA[Leave Event]]></string>
+    <string name="_bx_events_menu_item_title_leave_group"><![CDATA[Not going]]></string>
+    <string name="_bx_events_menu_item_title_leave_group_cancel_request"><![CDATA[Cancel]]></string>
+    <string name="_bx_events_menu_item_title_leave_group_reject_request"><![CDATA[Decline]]></string>
+
+<string name="_bx_events_menu_item_title_system_pay_and_join"><![CDATA[Pay & Join]]></string>
+    <string name="_bx_events_menu_item_title_pay_and_join"><![CDATA[Pay & Join]]></string>
+
+    <string name="_bx_events_menu_item_title_system_subscribe"><![CDATA[Follow]]></string>
+    <string name="_bx_events_menu_item_title_subscribe"><![CDATA[Interested]]></string>
+    <string name="_bx_events_menu_item_title_system_view_entries_in_context"><![CDATA[Events]]></string>
+    <string name="_bx_events_menu_item_title_view_entries_in_context"><![CDATA[Events]]></string>
+    <string name="_bx_events_menu_item_title_system_unsubscribe"><![CDATA[Unfollow]]></string>
+    <string name="_bx_events_menu_item_title_unsubscribe"><![CDATA[Not interested]]></string>
+    <string name="_bx_events_menu_item_title_system_more_actions"><![CDATA[More Actions]]></string>
+    <string name="_bx_events_menu_item_title_more_actions"><![CDATA[]]></string>
+    <string name="_bx_events_menu_item_title_system_friends"><![CDATA[Friends]]></string>
+    <string name="_bx_events_menu_item_title_friends"><![CDATA[Friends]]></string>
+    <string name="_bx_events_menu_item_title_system_manage_my_groups"><![CDATA[My events]]></string>
+    <string name="_bx_events_menu_item_title_manage_my_groups"><![CDATA[Events]]></string>
+    <string name="_bx_events_menu_item_title_system_followings"><![CDATA[Events]]></string>
+    <string name="_bx_events_menu_item_title_followings"><![CDATA[Events]]></string>
+    <string name="_bx_events_menu_item_title_system_entries_recent"><![CDATA[New]]></string>
+    <string name="_bx_events_menu_item_title_entries_recent"><![CDATA[New]]></string>
+    <string name="_bx_events_menu_item_title_system_entries_search"><![CDATA[Search]]></string>
+    <string name="_bx_events_menu_item_title_entries_search"><![CDATA[Search]]></string>
+    <string name="_bx_events_menu_item_title_system_entries_joined"><![CDATA[Joined]]></string>
+    <string name="_bx_events_menu_item_title_entries_joined"><![CDATA[Joined]]></string>
+    <string name="_bx_events_menu_item_title_system_entries_manage"><![CDATA[Manage]]></string>
+    <string name="_bx_events_menu_item_title_entries_manage"><![CDATA[Manage]]></string>
+    <string name="_bx_events_menu_item_title_system_entries_home"><![CDATA[Events]]></string>
+    <string name="_bx_events_menu_item_title_entries_home"><![CDATA[Events]]></string>
+    <string name="_bx_events_menu_item_title_system_admt_groups"><![CDATA[Events]]></string>
+    <string name="_bx_events_menu_item_title_admt_groups"><![CDATA[Events]]></string>
+    <string name="_bx_events_menu_item_title_manage_my"><![CDATA[My Events]]></string>
+    <string name="_bx_events_menu_item_title_manage_all"><![CDATA[All Events]]></string>
+    <string name="_bx_events_menu_item_title_system_entries_top"><![CDATA[Top]]></string>
+    <string name="_bx_events_menu_item_title_entries_top"><![CDATA[Top]]></string>
+    <string name="_bx_events_menu_item_title_system_entries_upcoming"><![CDATA[Upcoming]]></string>
+    <string name="_bx_events_menu_item_title_entries_upcoming"><![CDATA[Upcoming]]></string>        
+    <string name="_bx_events_menu_item_title_system_entries_past"><![CDATA[Past]]></string>
+    <string name="_bx_events_menu_item_title_entries_past"><![CDATA[Past]]></string>
+    <string name="_bx_events_menu_item_title_system_calendar"><![CDATA[Calendar]]></string>
+    <string name="_bx_events_menu_item_title_calendar"><![CDATA[Calendar]]></string>
+
+    <string name="_bx_events_menu_item_title_system_sm_date_start"><![CDATA[Date start]]></string>
+    <string name="_bx_events_menu_item_title_sm_date_start"><![CDATA[Date start]]></string>
+    <string name="_bx_events_menu_item_title_system_sm_date_end"><![CDATA[Date end]]></string>
+    <string name="_bx_events_menu_item_title_sm_date_end"><![CDATA[Date end]]></string>
+    <string name="_bx_events_menu_item_title_ical_export"><![CDATA[Sync to Calendar]]></string>
+
+    <string name="_bx_events_grid_filter_item_title_adm_select_one_filter1"><![CDATA[All Statuses]]></string>
+    <string name="_bx_events_grid_filter_item_title_adm_select_one_filter2"><![CDATA[Any Audience]]></string>
+    <string name="_bx_events_grid_filter_item_title_adm_active"><![CDATA[Active]]></string>
+    <string name="_bx_events_grid_filter_item_title_adm_hidden"><![CDATA[Hidden]]></string>
+    <string name="_bx_events_grid_filter_item_title_adm_pending"><![CDATA[Pending]]></string>
+    <string name="_bx_events_grid_filter_item_title_adm_suspended"><![CDATA[Suspended]]></string>
+    <string name="_bx_events_grid_column_title_adm_active"><![CDATA[Active]]></string>
+    <string name="_bx_events_grid_column_title_adm_name"><![CDATA[Name]]></string>
+    <string name="_bx_events_grid_column_title_adm_added"><![CDATA[Created]]></string>
+    <string name="_bx_events_grid_column_title_adm_account"><![CDATA[Account]]></string>
+    <string name="_bx_events_grid_action_title_adm_delete"><![CDATA[Delete]]></string>
+    <string name="_bx_events_grid_action_title_adm_delete_with_content"><![CDATA[Delete With Content]]></string>
+    <string name="_bx_events_grid_action_title_adm_more_actions"><![CDATA[More Actions]]></string>
+    <string name="_bx_events_grid_action_title_adm_audit_content"><![CDATA[Audit actions with content]]></string>
+    <string name="_bx_events_grid_action_title_adm_audit_context"><![CDATA[Audit actions in context]]></string>
+    <string name="_bx_events_grid_action_title_adm_clear_reports"><![CDATA[Сlear reports]]></string>
+    <string name="_bx_events_grid_action_err_delete"><![CDATA[Cannot delete the selected event(s).]]></string>
+    <string name="_bx_events_grid_txt_account_manager"><![CDATA[Redirect to manage account.]]></string>
+
+    <string name="_bx_events_grid_column_title_name"><![CDATA[Name]]></string>
+    <string name="_bx_events_grid_column_title_role_id"><![CDATA[Role]]></string>
+    <string name="_bx_events_grid_column_title_period"><![CDATA[Period]]></string>
+    <string name="_bx_events_grid_column_title_price"><![CDATA[Price]]></string>
+    <string name="_bx_events_grid_action_title_add"><![CDATA[Add]]></string>
+    <string name="_bx_events_grid_action_title_edit"><![CDATA[Edit]]></string>
+    <string name="_bx_events_grid_action_title_delete"><![CDATA[Delete]]></string>
+    <string name="_bx_events_grid_action_title_buy"><![CDATA[Buy]]></string>
+    <string name="_bx_events_grid_action_title_buy_title"><![CDATA[One-time payment]]></string>
+    <string name="_bx_events_grid_action_title_subscribe"><![CDATA[Subscribe]]></string>
+    <string name="_bx_events_grid_action_title_subscribe_title"><![CDATA[Create a subscription with recurring billing]]></string>
+    <string name="_bx_events_grid_action_title_choose"><![CDATA[Choose]]></string>
+    <string name="_bx_events_grid_action_title_choose_title"><![CDATA[Switch to the level for free]]></string>
+    <string name="_bx_events_popup_title_price_add"><![CDATA[Add Pricing Plan]]></string>
+    <string name="_bx_events_popup_title_price_edit"><![CDATA[Edit Pricing Plan]]></string>
+
+    <string name="_bx_events_chart_growth"><![CDATA[Events: Growth]]></string>
+    <string name="_bx_events_chart_growth_speed"><![CDATA[Events: Growth Speed]]></string>
+
+    <string name="_bx_events_search_extended"><![CDATA[Events Search]]></string>
+    <string name="_bx_events_search_extended_cmts"><![CDATA[Events Comments Search]]></string>
+
+    <string name="_bx_events_txt_all_entries_in"><![CDATA[<a href="{0}">All Events in {1} ({2})</a>]]></string>
+    <string name="_bx_events_txt_account_pending"><![CDATA[This event is pending approval, please wait until it is activated.]]></string>
+    <string name="_bx_events_txt_account_suspended"><![CDATA[This event is suspended.]]></string>
+    <string name="_bx_events_txt_scheduled_awaiting"><![CDATA[Event publishing date is {date_publish_uf}]]></string>
+    <string name="_bx_events_txt_status_hidden"><![CDATA[This event was hidden.]]></string>
+    <string name="_bx_events_txt_N_fans"><![CDATA[{0} members]]></string>
+    <string name="_bx_events_txt_role"><![CDATA[Role]]></string>
+    <string name="_bx_events_txt_sample_single"><![CDATA[event]]></string>
+    <string name="_bx_events_txt_sample_single_with_article"><![CDATA[an event]]></string>
+    <string name="_bx_events_txt_sample_comment_single"><![CDATA[comment to event]]></string>
+    <string name="_bx_events_txt_sample_vote_single"><![CDATA[vote to event]]></string>
+    <string name="_bx_events_txt_sample_score_up_single"><![CDATA[score up vote to event]]></string>
+    <string name="_bx_events_txt_sample_score_down_single"><![CDATA[score down vote to event]]></string>
+    <string name="_bx_events_txt_set_role"><![CDATA[Set Role]]></string>
+    <string name="_bx_events_txt_private_group"><![CDATA[Private event]]></string>
+    <string name="_bx_events_txt_from_time_to_time"><![CDATA[{0} - {1}]]></string>
+    <string name="_bx_events_txt_invite_popup_text"><![CDATA[You have been invited to a event. Click the button below to accept the invitation.]]></string>
+    <string name="_bx_events_txt_invite_popup_title"><![CDATA[Invitation to a event]]></string>
+    <string name="_bx_events_txt_invite_popup_button_accept"><![CDATA[Accept]]></string>
+    <string name="_bx_events_txt_invite_popup_button_decline"><![CDATA[Decline]]></string>
+    <string name="_bx_events_txt_invite_popup_error_invitation_absent"><![CDATA[Sorry, an error has occurred. You can not join this event. The invitation is expired or deleted.]]></string>
+    <string name="_bx_events_txt_invite_popup_error_invitation_wrong_user"><![CDATA[Sorry, an error has occurred. You can not join this event. This invitation cannot be used by you.]]></string>
+    <string name="_bx_events_txt_n_unit"><![CDATA[{0} ({1})]]></string>
+    <string name="_bx_events_txt_cart_item_title"><![CDATA[{0}: {1} ({2} {3})]]></string>
+    <string name="_bx_events_txt_cart_item_title_lifetime"><![CDATA[{0}: {1} (lifetime)]]></string>    
+
+    <string name="_bx_events_msg_performed"><![CDATA[The action was successfully performed.]]></string>
+    <string name="_bx_events_err_price_duplicate"><![CDATA[Similar pricing plan is already exists.]]></string>
+    <string name="_bx_events_err_cannot_perform"><![CDATA[An error appeared. Please report.]]></string>
+
+    <string name="_bx_events_alert_action_fan_added"><![CDATA[member joined]]></string>
+    <string name="_bx_events_txt_ntfs_fan_added"><![CDATA[Event <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_events_alert_action_join_invitation_notif"><![CDATA[join invitation]]></string>
+    <string name="_bx_events_alert_action_join_request"><![CDATA[join request]]></string>
+    <string name="_bx_events_txt_ntfs_join_invitation"><![CDATA[<b class="bx-ntfs-content-profile">{owner_name}</b> event's representative invites <b class="bx-ntfs-content-entry">{subentry_sample}</b> to join event]]></string>
+    <string name="_bx_events_txt_ntfs_join_request"><![CDATA[Event <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_events_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> event timeline]]></string>
+
+    <string name="_bx_events_privacy_group_closed"><![CDATA[Closed]]></string>
+    <string name="_bx_events_privacy_group_secret"><![CDATA[Secret]]></string>
+
+    <string name="_bx_events_pre_lists_reminder"><![CDATA[Event reminder]]></string>
+    <string name="_bx_events_reminder_none"><![CDATA[Reminder is off]]></string>
+    <string name="_bx_events_reminder_1h"><![CDATA[1 hour]]></string>
+    <string name="_bx_events_reminder_2h"><![CDATA[2 hours]]></string>
+    <string name="_bx_events_reminder_3h"><![CDATA[3 hours]]></string>
+    <string name="_bx_events_reminder_6h"><![CDATA[6 hours]]></string>
+    <string name="_bx_events_reminder_12h"><![CDATA[12 hours]]></string>
+    <string name="_bx_events_reminder_24h"><![CDATA[24 hours]]></string>
+
+    <string name="_bx_events_pre_lists_cats"><![CDATA[Event categories]]></string>
+    <string name="_bx_events_cat_Conference"><![CDATA[Conference]]></string>
+    <string name="_bx_events_cat_Festival"><![CDATA[Festival]]></string>
+    <string name="_bx_events_cat_Fundraiser"><![CDATA[Fundraiser]]></string>
+    <string name="_bx_events_cat_Lecture"><![CDATA[Lecture]]></string>
+    <string name="_bx_events_cat_Market"><![CDATA[Market]]></string>
+    <string name="_bx_events_cat_Meal"><![CDATA[Meal]]></string>
+    <string name="_bx_events_cat_Social_Mixer"><![CDATA[Social Mixer]]></string>
+    <string name="_bx_events_cat_Tour"><![CDATA[Tour]]></string>
+    <string name="_bx_events_cat_Volunteering"><![CDATA[Volunteering]]></string>
+    <string name="_bx_events_cat_Workshop"><![CDATA[Workshop]]></string>
+    <string name="_bx_events_cat_Other"><![CDATA[Other]]></string>
+
+    <string name="_bx_events_pre_lists_roles"><![CDATA[Event roles]]></string>
+    <string name="_bx_events_role_regular"><![CDATA[Regular]]></string>
+    <string name="_bx_events_role_administrator"><![CDATA[Administrator]]></string>
+    <string name="_bx_events_role_moderator"><![CDATA[Moderator]]></string>
+
+    <string name="_bx_events_pre_lists_period_units"><![CDATA[Billing Interval]]></string>
+    <string name="_bx_events_period_unit_day"><![CDATA[day]]></string>
+    <string name="_bx_events_period_unit_week"><![CDATA[week]]></string>
+    <string name="_bx_events_period_unit_month"><![CDATA[month]]></string>
+    <string name="_bx_events_period_unit_year"><![CDATA[year]]></string>
+
+    <string name="_bx_events_pre_lists_repeat_year"><![CDATA[Repeat year]]></string>
+    <string name="_bx_events_cat_repeat_year_every_year"><![CDATA[Every year]]></string>
+    <string name="_bx_events_cat_repeat_year_every_2_years"><![CDATA[Every 2 years]]></string>
+    <string name="_bx_events_cat_repeat_year_every_3_years"><![CDATA[Every 3 years]]></string>
+    <string name="_bx_events_cat_repeat_year_every_4_years"><![CDATA[Every 4 years]]></string>
+
+    <string name="_bx_events_pre_lists_repeat_month"><![CDATA[Repeat month]]></string>
+    <string name="_bx_events_cat_repeat_month_every_month"><![CDATA[Every month]]></string>
+    <string name="_bx_events_cat_repeat_month_jan"><![CDATA[Every January]]></string>
+    <string name="_bx_events_cat_repeat_month_feb"><![CDATA[Every February]]></string>
+    <string name="_bx_events_cat_repeat_month_mar"><![CDATA[Every March]]></string>
+    <string name="_bx_events_cat_repeat_month_apr"><![CDATA[Every April]]></string>
+    <string name="_bx_events_cat_repeat_month_may"><![CDATA[Every May]]></string>
+    <string name="_bx_events_cat_repeat_month_jun"><![CDATA[Every June]]></string>
+    <string name="_bx_events_cat_repeat_month_jul"><![CDATA[Every July]]></string>
+    <string name="_bx_events_cat_repeat_month_aug"><![CDATA[Every August]]></string>
+    <string name="_bx_events_cat_repeat_month_sep"><![CDATA[Every September]]></string>
+    <string name="_bx_events_cat_repeat_month_oct"><![CDATA[Every October]]></string>
+    <string name="_bx_events_cat_repeat_month_nov"><![CDATA[Every November]]></string>
+    <string name="_bx_events_cat_repeat_month_dec"><![CDATA[Every December]]></string>
+
+    <string name="_bx_events_pre_lists_repeat_week_of_month"><![CDATA[Repeat week of the month]]></string>
+    <string name="_bx_events_cat_repeat_week_of_month_every_week"><![CDATA[Every week]]></string>
+    <string name="_bx_events_cat_repeat_week_of_month_first_week_of_month"><![CDATA[Every 1st week of the month]]></string>
+    <string name="_bx_events_cat_repeat_week_of_month_second_week_of_month"><![CDATA[Every 2nd week of the month]]></string>
+    <string name="_bx_events_cat_repeat_week_of_month_third_week_of_month"><![CDATA[Every 3rd week of the month]]></string>
+    <string name="_bx_events_cat_repeat_week_of_month_fourth_week_of_month"><![CDATA[Every 4th week of the month]]></string>
+    <string name="_bx_events_cat_repeat_week_of_month_fifth_week_of_month"><![CDATA[Every 5th week of the month]]></string>
+    <string name="_bx_events_cat_repeat_week_of_month_sixth_week_of_month"><![CDATA[Every 6th week of the month]]></string>
+
+    <string name="_bx_events_pre_lists_repeat_day_of_month"><![CDATA[Repeat day of the month]]></string>
+    <string name="_bx_events_cat_repeat_day_of_month_every_day"><![CDATA[Every day]]></string>
+
+    <string name="_bx_events_pre_lists_repeat_day_of_week"><![CDATA[Repeat day of the week]]></string>
+    <string name="_bx_events_cat_repeat_day_of_week_every_day"><![CDATA[Every day of the week]]></string>
+    <string name="_bx_events_cat_repeat_day_of_week_mon"><![CDATA[Every Monday]]></string>
+    <string name="_bx_events_cat_repeat_day_of_week_tue"><![CDATA[Every Tuesday]]></string>
+    <string name="_bx_events_cat_repeat_day_of_week_wed"><![CDATA[Every Wednesday]]></string>
+    <string name="_bx_events_cat_repeat_day_of_week_thu"><![CDATA[Every Thursday]]></string>
+    <string name="_bx_events_cat_repeat_day_of_week_fri"><![CDATA[Every Friday]]></string>
+    <string name="_bx_events_cat_repeat_day_of_week_sat"><![CDATA[Every Saturday]]></string>
+    <string name="_bx_events_cat_repeat_day_of_week_sun"><![CDATA[Every Sunday]]></string>
+
+    <string name="_bx_events_email_join_request"><![CDATA[Event join request]]></string>
+    <string name="_bx_events_email_join_request_subject"><![CDATA[Request to join your event]]></string>
+    <string name="_bx_events_email_join_request_body"><![CDATA[{email_header}
+<p>New request to join <a href="{EntryUrl}">{EntryTitle}</a> event from <a href="{NewMemberUrl}">{NewMemberDisplayName}</a></p>
+{email_footer}]]></string>
+
+    <string name="_bx_events_email_join_reject"><![CDATA[Event join request was rejected]]></string>
+    <string name="_bx_events_email_join_reject_subject"><![CDATA[Request to join an event was rejected]]></string>
+    <string name="_bx_events_email_join_reject_body"><![CDATA[{email_header}
+<p>Your request to join <a href="{EntryUrl}">{EntryTitle}</a> event was rejected by event admin.</p>
+{email_footer}]]></string>
+
+    <string name="_bx_events_email_join_confirm"><![CDATA[Event join request was confirmed]]></string>
+    <string name="_bx_events_email_join_confirm_subject"><![CDATA[Your request to join an event was confirmed]]></string>
+    <string name="_bx_events_email_join_confirm_body"><![CDATA[{email_header}
+<p>Your request to join <a href="{EntryUrl}">{EntryTitle}</a> event was confirmed by the event admin.</p>
+{email_footer}]]></string>
+
+    <string name="_bx_events_email_fan_remove"><![CDATA[Profile was removed from event participants]]></string>
+    <string name="_bx_events_email_fan_remove_subject"><![CDATA[Your profile was removed from the event]]></string>
+    <string name="_bx_events_email_fan_remove_body"><![CDATA[{email_header}
+<p>Your profile was removed from <a href="{EntryUrl}">{EntryTitle}</a> event by the event admin.</p>
+{email_footer}]]></string>
+
+    <string name="_bx_events_email_fan_become_admin"><![CDATA[Event admin status was granted]]></string>
+    <string name="_bx_events_email_fan_become_admin_subject"><![CDATA[You are an event admin now]]></string>
+    <string name="_bx_events_email_fan_become_admin_body"><![CDATA[{email_header}
+<p>You are an admin of <a href="{EntryUrl}">{EntryTitle}</a> event now.</p>
+{email_footer}]]></string>
+
+    <string name="_bx_events_email_admin_become_fan"><![CDATA[Event admin status was revoked]]></string>
+    <string name="_bx_events_email_admin_become_fan_subject"><![CDATA[Your event admin status was revoked]]></string>
+    <string name="_bx_events_email_admin_become_fan_body"><![CDATA[{email_header}
+<p>Your admin status was revoked from <a href="{EntryUrl}">{EntryTitle}</a> event.</p>
+{email_footer}]]></string>
+
+    <string name="_bx_events_email_invitation"><![CDATA[Invitation to event]]></string>
+    <string name="_bx_events_email_invitation_subject"><![CDATA[Invitation to "{EntryTitle}" event]]></string>
+    <string name="_bx_events_email_invitation_body"><![CDATA[{email_header}
+<p><a href="{InviterUrl}">{InviterDisplayName}</a> invited you to <a href="{EntryUrl}">{EntryTitle} event</a>.</p>
+{email_footer}]]></string>
+
+    <string name="_bx_events_email_set_role"><![CDATA[Event member status was changed]]></string>
+    <string name="_bx_events_email_set_role_subject"><![CDATA[Your event status was changed]]></string>
+    <string name="_bx_events_email_set_role_body"><![CDATA[{email_header}
+<p>Your status in <a href="{EntryUrl}">{EntryTitle}</a> event was changed to <b>{Role}</b>.</p>
+{email_footer}]]></string>
+
+    <string name="_bx_events_email_reminder"><![CDATA[Reminder for the event]]></string>
+    <string name="_bx_events_email_reminder_subject"><![CDATA["{EntryTitle}" event - {EntryBeginShort}]]></string>
+    <string name="_bx_events_email_reminder_body"><![CDATA[{email_header}
+<p class="vevent">
+    <a href="{EntryUrl}" class="summary">{EntryTitle}</a> event reminder:</a><br />
+    Date: <abbr class="dtstart" title="{EntryBeginUTC}">{EntryBegin}</abbr><br />
+    {EntryLocation}
+</p>
+{email_footer}]]></string>
+    <string name="_bx_events_email_reminder_location"><![CDATA[Location: <span class="location">{0}</span>]]></string>
+</resources>

+ 733 - 0
modules/boonex/events/updates/13.0.2_13.0.3/source/install/sql/enable.sql

@@ -0,0 +1,733 @@
+
+-- 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_events', '_bx_events', 'bx_events@modules/boonex/events/|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_events', '_bx_events', 1);
+SET @iCategId = LAST_INSERT_ID();
+
+INSERT INTO `sys_options` (`name`, `value`, `category_id`, `caption`, `type`, `extra`, `check`, `check_error`, `order`) VALUES
+('bx_events_enable_auto_approve', 'on', @iCategId, '_bx_events_option_enable_auto_approve', 'checkbox', '', '', '', 0),
+('bx_events_num_connections_quick', '6', @iCategId, '_bx_events_option_num_connections_quick', 'digit', '', '', '', 10),
+('bx_events_per_page_browse', '24', @iCategId, '_bx_events_option_per_page_browse', 'digit', '', '', '', 11),
+('bx_events_num_rss', '10', @iCategId, '_bx_events_option_num_rss', 'digit', '', '', '', 12),
+('bx_events_per_page_browse_showcase', '32', @iCategId, '_sys_option_per_page_browse_showcase', 'digit', '', '', '', 15),
+('bx_events_per_page_browse_recommended', '10', @iCategId, '_sys_option_per_page_browse_recommended', 'digit', '', '', '', 16),
+('bx_events_per_page_for_favorites_lists', '5', @iCategId, '_bx_events_option_per_page_for_favorites_lists', 'digit', '', '', '', 17),
+('bx_events_time_format', 'H:i', @iCategId, '_bx_events_option_time_format', 'digit', '', '', '', 20),
+('bx_events_short_date_format', 'j/n/Y', @iCategId, '_bx_events_option_short_date_format', 'digit', '', '', '', 22),
+('bx_events_datetime_format', 'j/n/Y H:i', @iCategId, '_bx_events_option_datetime_format', 'digit', '', '', '', 23),
+('bx_events_summary_chars', '700', @iCategId, '_bx_events_option_summary_chars', 'digit', '', '', '', 25),
+('bx_events_searchable_fields', 'event_name,event_desc', @iCategId, '_bx_events_option_searchable_fields', 'list', 'a:2:{s:6:"module";s:9:"bx_events";s:6:"method";s:21:"get_searchable_fields";}', '', '', 30),
+('bx_events_members_mode', '', @iCategId, '_bx_events_option_members_mode', 'select', 'a:2:{s:6:"module";s:9:"bx_events";s:6:"method";s:24:"get_options_members_mode";}', '', '', 40),
+('bx_events_public_subscribed_me', 'on', @iCategId, '_bx_events_option_public_subscribed_me', 'checkbox', '', '', '', 50),
+('bx_events_internal_notifications', '', @iCategId, '_bx_events_option_internal_notifications', 'checkbox', '', '', '', 60),
+('bx_events_reminder_interval', '24', @iCategId, '_bx_events_option_reminder_interval', 'select', '24,48', '', '', 70);
+
+-- 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_events_create_profile', 'create-event-profile', '_bx_events_page_title_sys_create_profile', '_bx_events_page_title_create_profile', 'bx_events', 5, 2147483647, 1, 'page.php?i=create-event-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_events_create_profile', 1, 'bx_events', '_bx_events_page_block_title_create_profile', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_events\";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_events_view_profile', 'view-event-profile', '_bx_events_page_title_sys_view_profile', '_bx_events_page_title_view_profile', 'bx_events', 10, 2147483647, 1, 'page.php?i=view-event-profile', '', '', '', 0, 1, 0, 'BxEventsPageEntry', 'modules/boonex/events/classes/BxEventsPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `hidden_on`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES
+('bx_events_view_profile', 4, 'bx_events', '', '_bx_events_page_block_title_profile_comments', 11, '', 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_events\";s:6:\"method\";s:15:\"entity_comments\";}', 0, 0, 0, 0),
+('bx_events_view_profile', 4, 'bx_events', '', '_bx_events_page_block_title_profile_description', 13, '', 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_events\";s:6:\"method\";s:17:\"entity_text_block\";}', 0, 0, 1, 0),
+('bx_events_view_profile', 2, 'bx_events', '', '_bx_events_page_block_title_profile_info', 11, '', 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_events\";s:6:\"method\";s:11:\"entity_info\";}', 0, 0, 1, 0),
+('bx_events_view_profile', 1, 'bx_events', '', '_bx_events_page_block_title_entry_social_sharing', 13, '', 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_events\";s:6:\"method\";s:21:\"entity_social_sharing\";}', 0, 0, 0, 0),
+('bx_events_view_profile', 1, 'bx_events', '', '_bx_events_page_block_title_entry_all_actions', 13, '', 2147483647, 'service', 'a:2:{s:6:"module";s:9:"bx_events";s:6:"method";s:18:"entity_all_actions";}', 0, 0, 0, 0),
+('bx_events_view_profile', 3, 'bx_events', '', '_bx_events_page_block_title_profile_calendar', 11, '', 2147483647, 'service', 'a:3:{s:6:\"module\";s:9:\"bx_events\";s:6:\"method\";s:8:\"calendar\";s:6:\"params\";a:2:{i:0;a:1:{s:5:\"event\";s:12:\"{content_id}\";}i:1;s:21:\"calendar_compact.html\";}}', 0, 0, 1, 0),
+('bx_events_view_profile', 3, 'bx_events', '_bx_events_page_block_title_sys_entry_context', '_bx_events_page_block_title_entry_context', 13, '', 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_events\";s:6:\"method\";s:14:\"entity_context\";}', 0, 0, 1, 1),
+('bx_events_view_profile', 4, 'bx_events', '', '_bx_events_page_block_title_fans', 11, '', 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_events\";s:6:\"method\";s:4:\"fans\";}', 0, 0, 1, 1),
+('bx_events_view_profile', 4, 'bx_events', '', '_bx_events_page_block_title_admins', 11, '', 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_events\";s:6:\"method\";s:6:\"admins\";}', 0, 0, 1, 2),
+('bx_events_view_profile', 2, 'bx_events', '', '_bx_events_page_block_title_entry_location', 11, '', 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_events\";i:1;s:12:\"{content_id}\";}s:5:\"class\";s:20:\"TemplServiceMetatags\";}', 0, 0, 1, 1),
+('bx_events_view_profile', 2, 'bx_events', '', '_bx_events_page_block_title_entry_reports', 11, '', 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"events\";s:6:\"method\";s:14:\"entity_reports\";}', 0, 0, 1, 6);
+-- 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_events_view_profile_closed', 'view-event-profile-closed', '_bx_events_page_title_sys_view_profile_closed', '_bx_events_page_title_view_profile', 'bx_events', 10, 2147483647, 1, 'page.php?i=view-event-profile', '', '', '', 0, 1, 0, 'BxEventsPageEntry', 'modules/boonex/events/classes/BxEventsPageEntry.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_events_view_profile_closed', 2, 'bx_events', '', '_bx_events_page_block_title_profile_info', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_events\";s:6:\"method\";s:11:\"entity_info\";}', 0, 0, 1, 0),
+('bx_events_view_profile_closed', 3, 'bx_events', '', '_bx_events_page_block_title_fans', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_events\";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_events_edit_profile', 'edit-event-profile', '_bx_events_page_title_sys_edit_profile', '_bx_events_page_title_edit_profile', 'bx_events', 5, 2147483647, 1, 'page.php?i=edit-event-profile', '', '', '', 0, 1, 0, 'BxEventsPageEntry', 'modules/boonex/events/classes/BxEventsPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_events_edit_profile', 1, 'bx_events', '_bx_events_page_block_title_edit_profile', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_events\";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_events_edit_profile_cover', 'edit-event-cover', '_bx_events_page_title_sys_edit_profile_cover', '_bx_events_page_title_edit_profile_cover', 'bx_events', 5, 2147483647, 1, 'page.php?i=edit-event-cover', '', '', '', 0, 1, 0, 'BxEventsPageEntry', 'modules/boonex/events/classes/BxEventsPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_events_edit_profile_cover', 1, 'bx_events', '_bx_events_page_block_title_edit_profile_cover', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_events\";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_events_invite', 'invite-to-event', '_bx_events_page_title_sys_invite_to_group', '_bx_events_page_title_invite_to_group', 'bx_events', 5, 2147483647, 1, 'page.php?i=invite-to-event', '', '', '', 0, 1, 0, 'BxEventsPageEntry', 'modules/boonex/events/classes/BxEventsPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_events_invite', 1, 'bx_events', '_bx_events_page_block_title_invite_to_group', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_events\";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_events_delete_profile', 'delete-event-profile', '_bx_events_page_title_sys_delete_profile', '_bx_events_page_title_delete_profile', 'bx_events', 5, 2147483647, 1, 'page.php?i=delete-event-profile', '', '', '', 0, 1, 0, 'BxEventsPageEntry', 'modules/boonex/events/classes/BxEventsPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_events_delete_profile', 1, 'bx_events', '_bx_events_page_block_title_delete_profile', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_events\";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_events_join_profile', 'join-event-profile', '_bx_events_page_title_sys_join_profile', '_bx_events_page_title_join_profile', 'bx_events', 5, 2147483647, 1, 'page.php?i=join-event-profile', '', '', '', 0, 1, 0, 'BxEventsPageEntry', 'modules/boonex/events/classes/BxEventsPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_events_join_profile', 1, 'bx_events', '_bx_events_page_block_title_join_profile', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:9:"bx_events";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_events_profile_info', 'event-profile-info', '_bx_events_page_title_sys_profile_info', '_bx_events_page_title_profile_info', 'bx_events', 5, 2147483647, 1, 'page.php?i=event-profile-info', '', '', '', 0, 1, 0, 'BxEventsPageEntry', 'modules/boonex/events/classes/BxEventsPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `hidden_on`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_events_profile_info', 1, 'bx_events', '', '_bx_events_page_block_title_profile_description', 13, '', 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_events\";s:6:\"method\";s:17:\"entity_text_block\";}', 0, 0, 1, 0),
+('bx_events_profile_info', 2, 'bx_events', '_bx_events_page_block_title_system_profile_info', '_bx_events_page_block_title_profile_info_link', 11, '', 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_events\";s:6:\"method\";s:16:\"entity_info_full\";}', 0, 0, 1, 0),
+('bx_events_profile_info', 3, 'bx_events', '', '_bx_events_page_block_title_profile_calendar', 11, '', 2147483647, 'service', 'a:3:{s:6:\"module\";s:9:\"bx_events\";s:6:\"method\";s:8:\"calendar\";s:6:\"params\";a:2:{i:0;a:1:{s:5:\"event\";s:12:\"{content_id}\";}i:1;s:21:\"calendar_compact.html\";}}', 0, 0, 1, 0),
+('bx_events_profile_info', 2, 'bx_events', '', '_bx_events_page_block_title_entry_location', 11, '', 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_events\";i:1;s:12:\"{content_id}\";}s:5:\"class\";s:20:\"TemplServiceMetatags\";}', 0, 0, 1, 1);
+
+-- 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_events_profile_pricing', 'edit-event-pricing', '_bx_events_page_title_sys_profile_pricing', '_bx_events_page_title_profile_pricing', 'bx_events', 5, 2147483647, 1, 'page.php?i=edit-event-pricing', '', '', '', 0, 1, 0, 'BxEventsPageEntry', 'modules/boonex/events/classes/BxEventsPageEntry.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_events_profile_pricing', 1, 'bx_events', '_bx_events_page_block_title_system_profile_pricing', '_bx_events_page_block_title_profile_pricing_link', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:9:"bx_events";s:6:"method";s:14:"entity_pricing";s:6:"params";a:1:{i:0;s:12:"{profile_id}";}}', 0, 0, 1, 1);
+
+-- PAGE: event 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_events_fans', 'event-fans', '_bx_events_page_title_sys_group_fans', '_bx_events_page_title_group_fans', 'bx_events', 5, 2147483647, 1, 'page.php?i=event-fans', '', '', '', 0, 1, 0, 'BxEventsPageEntry', 'modules/boonex/events/classes/BxEventsPageEntry.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_events_fans', 1, 'bx_events', '_bx_events_page_block_title_system_fans', '_bx_events_page_block_title_fans_link', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:9:"bx_events";s:6:"method";s:10:"fans_table";}', 0, 0, 1, 1),
+('bx_events_fans', 1, 'bx_events', '_bx_events_page_block_title_system_subscribers', '_bx_events_page_block_title_subscribers_link', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:6:"system";s:6:"method";s:19:"subscribed_me_table";s:5:"class";s:23:"TemplServiceConnections";}', 0, 0, 1, 2),
+('bx_events_fans', 1, 'bx_events', '_bx_events_page_block_title_system_invites', '_bx_events_page_block_title_fans_invites', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:9:"bx_events";s:6:"method";s:13:"invites_table";}', 0, 0, 1, 3);
+
+-- 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_events_profile_comments', '_bx_events_page_title_sys_profile_comments', '_bx_events_page_title_profile_comments', 'bx_events', 5, 2147483647, 1, 'event-profile-comments', '', '', '', '', 0, 1, 0, 'BxEventsPageEntry', 'modules/boonex/events/classes/BxEventsPageEntry.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_events_profile_comments', 1, 'bx_events', '_bx_events_page_block_title_profile_comments', '_bx_events_page_block_title_profile_comments_link', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_events\";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_events_home', '_bx_events_page_title_sys_recent', '_bx_events_page_title_recent', 'bx_events', 5, 2147483647, 1, 'events-home', 'page.php?i=events-home', '', '', '', 0, 1, 0, 'BxEventsPageBrowse', 'modules/boonex/events/classes/BxEventsPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES
+('bx_events_home', 1, 'bx_events', '_bx_events_page_block_title_featured_profiles', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:9:"bx_events";s:6:"method";s:15:"browse_featured";s:6:"params";a:1:{i:0;s:7:"gallery";}}', 0, 1, 0),
+('bx_events_home', 1, 'bx_events', '_bx_events_page_block_title_latest_profiles', 11, 2147483647, 'service', 'a:3:{s:6:\"module\";s:9:\"bx_events\";s:6:\"method\";s:22:\"browse_recent_profiles\";s:6:"params";a:1:{i:0;b:1;}}', 0, 1, 1),
+('bx_events_home', 1, 'bx_events', '_bx_events_page_block_title_past_profiles', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:9:"bx_events";s:6:"method";s:20:"browse_past_profiles";s:6:"params";a:1:{i:0;b:0;}}', 0, 1, 2);
+
+-- 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_events_top', '_bx_events_page_title_sys_top', '_bx_events_page_title_top', 'bx_events', 5, 2147483647, 1, 'events-top', 'page.php?i=events-top', '', '', '', 0, 1, 0, 'BxEventsPageBrowse', 'modules/boonex/events/classes/BxEventsPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_events_top', 1, 'bx_events', '_bx_events_page_block_title_top_profiles', 11, 2147483647, 'service', 'a:3:{s:6:\"module\";s:9:\"bx_events\";s:6:\"method\";s:19:\"browse_top_profiles\";s:6:"params";a:1:{i:0;b:1;}}', 0, 1, 0);
+
+-- 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_events_context', 'events-context', '_bx_events_page_title_sys_entries_in_context', '_bx_events_page_title_entries_in_context', 'bx_events', 5, 2147483647, 1, '', '', '', '', 0, 1, 0, 'BxEventsPageEntriesInContext', 'modules/boonex/events/classes/BxEventsPageEntriesInContext.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_events_context', 1, 'bx_events', '_bx_events_page_block_title_sys_entries_in_context', '_bx_events_page_block_title_entries_in_context', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_events\";s:6:\"method\";s:14:\"browse_context\";}', 0, 0, 1, 1),
+('bx_events_context', 1, 'bx_events', '_bx_events_page_block_title_sys_calendar_in_context', '_bx_events_page_block_title_calendar_in_context', 11, 2147483647, 'service', 'a:4:{s:6:"module";s:9:"bx_events";s:6:"method";s:8:"calendar";s:12:"ignore_cache";b:1;s:6:"params";a:1:{i:0;a:1:{s:10:"context_id";s:12:"{profile_id}";}}}', 0, 0, 1, 2);
+
+-- PAGE: upcoming 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_events_upcoming', '_bx_events_page_title_sys_upcoming', '_bx_events_page_title_upcoming', 'bx_events', 5, 2147483647, 1, 'events-upcoming', 'page.php?i=events-upcoming', '', '', '', 0, 1, 0, 'BxEventsPageBrowse', 'modules/boonex/events/classes/BxEventsPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_events_upcoming', 1, 'bx_events', '_bx_events_page_block_title_upcoming_profiles', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:9:"bx_events";s:6:"method";s:24:"browse_upcoming_profiles";s:6:"params";a:1:{i:0;a:1:{s:13:"empty_message";b:1;}}}', 0, 1, 0);
+
+-- PAGE: past 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_events_past', '_bx_events_page_title_sys_past', '_bx_events_page_title_past', 'bx_events', 5, 2147483647, 1, 'events-past', 'page.php?i=events-past', '', '', '', 0, 1, 0, 'BxEventsPageBrowse', 'modules/boonex/events/classes/BxEventsPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_events_past', 1, 'bx_events', '_bx_events_page_block_title_past_profiles', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:9:"bx_events";s:6:"method";s:20:"browse_past_profiles";s:6:"params";a:1:{i:0;b:1;}}', 0, 0, 0);
+
+-- PAGE: calendar
+
+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_events_calendar', '_bx_events_page_title_sys_calendar', '_bx_events_page_title_calendar', 'bx_events', 5, 2147483647, 1, 'events-calendar', 'page.php?i=events-calendar', '', '', '', 0, 1, 0, 'BxEventsPageCalendar', 'modules/boonex/events/classes/BxEventsPageCalendar.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_events_calendar', 1, 'bx_events', '_bx_events_page_block_title_calendar', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:9:"bx_events";s:6:"method";s:8:"calendar";s:12:"ignore_cache";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_events_search', '_bx_events_page_title_sys_entries_search', '_bx_events_page_title_entries_search', 'bx_events', 5, 2147483647, 1, 'events-search', 'page.php?i=events-search', '', '', '', 0, 1, 0, 'BxEventsPageBrowse', 'modules/boonex/events/classes/BxEventsPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_events_search', 1, 'bx_events', '_bx_events_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_events";}}s:5:"class";s:27:"TemplSearchExtendedServices";}', 0, 1, 1, 1),
+('bx_events_search', 1, 'bx_events', '_bx_events_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_events";s:10:"show_empty";b:1;}}s:5:"class";s:27:"TemplSearchExtendedServices";}', 0, 1, 1, 2),
+('bx_events_search', 1, 'bx_events', '_bx_events_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_events_cmts";}}s:5:"class";s:27:"TemplSearchExtendedServices";}', 0, 1, 0, 3),
+('bx_events_search', 1, 'bx_events', '_bx_events_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_events_cmts";s:10:"show_empty";b:1;}}s:5:"class";s:27:"TemplSearchExtendedServices";}', 0, 1, 0, 4);
+
+-- PAGE: joined profiles
+
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_joined_events', '_bx_events_page_title_sys_joined', '_bx_events_page_title_joined', 'bx_events', 5, 2147483647, 1, 'events-joined', 'page.php?i=events-joined', '', '', '', 0, 1, 0, 'BxEventsPageBrowse', 'modules/boonex/events/classes/BxEventsPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_joined_events', 1, 'bx_events', '_bx_events_page_block_title_joined_entries', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:9:"bx_events";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_events_manage', '_bx_events_page_title_sys_manage', '_bx_events_page_title_manage', 'bx_events', 5, 2147483647, 1, 'events-manage', 'page.php?i=events-manage', '', '', '', 0, 1, 0, 'BxEventsPageBrowse', 'modules/boonex/events/classes/BxEventsPageBrowse.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_events_manage', 1, 'bx_events', '_bx_events_page_block_title_system_manage', '_bx_events_page_block_title_manage', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_events\";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_events_administration', '_bx_events_page_title_sys_manage_administration', '_bx_events_page_title_manage', 'bx_events', 5, 192, 1, 'events-administration', 'page.php?i=events-administration', '', '', '', 0, 1, 0, 'BxEventsPageBrowse', 'modules/boonex/events/classes/BxEventsPageBrowse.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_events_administration', 1, 'bx_events', '_bx_events_page_block_title_system_manage_administration', '_bx_events_page_block_title_manage', 11, 192, 'service', 'a:3:{s:6:\"module\";s:9:\"bx_events\";s:6:\"method\";s:12:\"manage_tools\";s:6:\"params\";a:1:{i:0;s:14:\"administration\";}}', 0, 1, 0);
+
+-- PAGE: user's events
+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_events_joined', 'joined-events', '_bx_events_page_title_sys_joined_entries', '_bx_events_page_title_joined_entries', 'bx_events', 5, 2147483647, 1, '', '', '', '', 0, 1, 0, 'BxEventsPageJoinedEntries', 'modules/boonex/events/classes/BxEventsPageJoinedEntries.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_events_joined', 1, 'bx_events', '_bx_events_page_block_title_sys_entries_actions', '_bx_events_page_block_title_entries_actions', 13, 2147483647, 'service', 'a:2:{s:6:"module";s:9:"bx_events";s:6:"method";s:18:"my_entries_actions";}', 0, 0, 1, 1),
+('bx_events_joined', 1, 'bx_events', '_bx_events_page_block_title_sys_entries_of_author', '_bx_events_page_block_title_entries_of_author', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:9:"bx_events";s:6:"method";s:22:"browse_created_entries";}', 0, 0, 0, 2),
+('bx_events_joined', 1, 'bx_events', '_bx_events_page_block_title_sys_favorites_of_author', '_bx_events_page_block_title_favorites_of_author', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:9:"bx_events";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_events_joined', 1, 'bx_events', '_bx_events_page_block_title_sys_joined_entries', '_bx_events_page_block_title_joined_entries', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:9:"bx_events";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_events_favorites', '_bx_events_page_title_sys_entries_favorites', '_bx_events_page_title_entries_favorites', 'bx_events', 12, 2147483647, 1, 'events-favorites', 'page.php?i=events-favorites', '', '', '', 0, 1, 0, 'BxEventsPageListEntry', 'modules/boonex/events/classes/BxEventsPageListEntry.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_events_favorites', 2, 'bx_events', '_bx_events_page_block_title_sys_favorites_entries', '_bx_events_page_block_title_favorites_entries', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:9:"bx_events";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_events_favorites', 3, 'bx_events', '', '_bx_events_page_block_title_favorites_entries_info', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:9:"bx_events";s:6:"method";s:19:"favorites_list_info";}', 0, 0, 0),
+('bx_events_favorites', 3, 'bx_events', '', '_bx_events_page_block_title_favorites_entries_actions', 13, 2147483647, 'service', 'a:2:{s:6:"module";s:9:"bx_events";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_events', '', '_bx_events_page_block_title_latest_profiles', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:9:"bx_events";s:6:"method";s:22:"browse_recent_profiles";}', 1, 0, 0, IFNULL(@iBlockOrder, 0) + 1),
+('sys_home', 1, 'bx_events', '_bx_events_page_block_title_sys_recommended_entries_view_showcase', '_bx_events_page_block_title_recommended_entries_view_showcase', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:9:"bx_events";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`, `order`) VALUES
+('', 0, 'bx_events', '', '_bx_events_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_events_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, IFNULL(@iBlockOrder, 0) + 1),
+('', 0, 'bx_events', '_bx_events_page_block_title_sys_featured_entries_view_showcase', '_bx_events_page_block_title_featured_entries_view_showcase', 11, 2147483647, 'service', 'a:3:{s:6:\"module\";s:9:\"bx_events\";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) + 2),
+('', 0, 'bx_events', '_bx_events_page_block_title_sys_recommended_entries_view_showcase', '_bx_events_page_block_title_recommended_entries_view_showcase', 11, 2147483647, 'service', 'a:3:{s:6:\"module\";s:9:\"bx_events\";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, IFNULL(@iBlockOrder, 0) + 3),
+('', 0, 'bx_events', '_bx_events_page_block_title_sys_cover_block', '_bx_events_page_block_title_cover_block', 3, 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_events\";s:6:\"method\";s:12:\"entity_cover\";}', 0, 1, IFNULL(@iBlockOrder, 0) + 4);
+ 
+ -- 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', 2, 'bx_events', '_bx_events_page_block_title_calendar_for_context', 11, 2147483647, 'service', 'a:4:{s:6:"module";s:9:"bx_events";s:6:"method";s:8:"calendar";s:12:"ignore_cache";b:1;s:6:"params";a:1:{i:0;a:1:{s:10:"context_id";s:12:"{profile_id}";}}}', 0, 0, 0, 0),
+('trigger_page_group_view_entry', 4, 'bx_events', '_bx_events_page_block_title_browse_for_context', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:9:"bx_events";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_events', 'events-home', '_bx_events_menu_item_title_system_entries_home', '_bx_events_menu_item_title_entries_home', 'page.php?i=events-home', '', '', 'calendar col-red2', 'bx_events_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_events', 'events-home', '_bx_events_menu_item_title_system_entries_home', '_bx_events_menu_item_title_entries_home', 'page.php?i=events-home', '', '', 'calendar col-red2', 'bx_events_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_events', 'create-event-profile', '_bx_events_menu_item_title_system_create_profile', '_bx_events_menu_item_title_create_profile', 'page.php?i=create-event-profile', '', '', 'calendar 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_events_view_actions', '_bx_events_menu_title_view_profile_actions', 'bx_events_view_actions', 'bx_events', 9, 0, 1, 'BxEventsMenuViewActions', 'modules/boonex/events/classes/BxEventsMenuViewActions.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_events_view_actions', 'bx_events', '_bx_events_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_events_view_actions', 'bx_events', 'join-event-profile', '_bx_events_menu_item_title_system_pay_and_join', '_bx_events_menu_item_title_pay_and_join', 'page.php?i=join-event-profile&profile_id={profile_id}', '', '', 'sign-in-alt', '', 0, 2147483647, 'a:3:{s:6:"module";s:9:"bx_events";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_events_view_actions', 'bx_events', 'profile-fan-add', '_bx_events_menu_item_title_system_become_fan', '{title_add_fan}', 'javascript:void(0)', 'bx_conn_action(this, \'bx_events_fans\', \'add\', \'{profile_id}\')', '', 'sign-in-alt', '', 0, 2147483647, 'a:3:{s:6:"module";s:9:"bx_events";s:6:"method";s:22:"is_free_join_avaliable";s:6:"params";a:1:{i:0;s:12:"{profile_id}";}}', 1, 0, 0, 5),
+('bx_events_view_actions', 'bx_events', 'profile-subscribe-add', '_bx_events_menu_item_title_system_subscribe', '_bx_events_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_events_view_actions', 'bx_events', '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_events'', content_id: {content_id}});', '', 'check-circle', '', 0, 192, 'a:2:{s:6:"module";s:9:"bx_events";s:6:"method";s:19:"is_badges_avaliable";}', 1, 0, 1, 30),
+('bx_events_view_actions', 'bx_events', 'ical-export', '', '_bx_events_menu_item_title_ical_export', '{ical_url}', '', '', 'calendar-plus', '', 0, 2147483647, 'a:3:{s:6:"module";s:9:"bx_events";s:6:"method";s:24:"is_ical_export_avaliable";s:6:"params";a:1:{i:0;s:12:"{content_id}";}}', 1, 0, 1, 40),
+('bx_events_view_actions', 'bx_events', 'profile-actions-more', '_bx_events_menu_item_title_system_more_actions', '_bx_events_menu_item_title_more_actions', 'javascript:void(0)', 'bx_menu_popup(''bx_events_view_actions_more'', this, {}, {profile_id:{profile_id}});', '', 'cog', 'bx_events_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_events_view_actions_more', '_bx_events_menu_title_view_profile_actions_more', 'bx_events_view_actions_more', 'bx_events', 6, 0, 1, 'BxEventsMenuViewActions', 'modules/boonex/events/classes/BxEventsMenuViewActions.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_events_view_actions_more', 'bx_events', '_bx_events_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_events_view_actions_more', 'bx_events', 'profile-fan-remove', '_bx_events_menu_item_title_system_leave_group', '{title_remove_fan}', 'javascript:void(0)', 'bx_conn_action(this, \'bx_events_fans\', \'remove\', \'{profile_id}\')', '', 'sign-out-alt', '', 2147483647, '', 1, 0, 10),
+('bx_events_view_actions_more', 'bx_events', 'profile-subscribe-remove', '_bx_events_menu_item_title_system_unsubscribe', '_bx_events_menu_item_title_unsubscribe', 'javascript:void(0)', 'bx_conn_action(this, \'sys_profiles_subscriptions\', \'remove\', \'{profile_id}\')', '', 'check', '', 2147483647, '', 1, 0, 20),
+('bx_events_view_actions_more', 'bx_events', 'edit-event-cover', '_bx_events_menu_item_title_system_edit_cover', '_bx_events_menu_item_title_edit_cover', 'page.php?i=edit-event-cover&id={content_id}', '', '', 'edit', '', 2147483647, '', 1, 0, 30),
+('bx_events_view_actions_more', 'bx_events', 'edit-event-profile', '_bx_events_menu_item_title_system_edit_profile', '_bx_events_menu_item_title_edit_profile', 'page.php?i=edit-event-profile&id={content_id}', '', '', 'pencil-alt', '', 2147483647, '', 1, 0, 40),
+('bx_events_view_actions_more', 'bx_events', 'edit-event-pricing', '_bx_events_menu_item_title_system_edit_pricing', '_bx_events_menu_item_title_edit_pricing', 'page.php?i=edit-event-pricing&profile_id={profile_id}', '', '', 'money-check-alt', '', 2147483647, 'a:3:{s:6:"module";s:9:"bx_events";s:6:"method";s:20:"is_pricing_avaliable";s:6:"params";a:1:{i:0;s:12:"{profile_id}";}}', 1, 0, 41),
+('bx_events_view_actions_more', 'bx_events', 'invite-to-event', '_bx_events_menu_item_title_system_invite', '_bx_events_menu_item_title_invite', 'page.php?i=invite-to-event&id={content_id}', '', '', 'user-friends', '', 2147483647, '', 1, 0, 42),
+('bx_events_view_actions_more', 'bx_events', 'delete-event-profile', '_bx_events_menu_item_title_system_delete_profile', '_bx_events_menu_item_title_delete_profile', 'page.php?i=delete-event-profile&id={content_id}', '', '', 'remove', '', 2147483647, '', 1, 0, 50),
+('bx_events_view_actions_more', 'bx_events', 'approve-event-profile', '_sys_menu_item_title_system_va_approve', '_sys_menu_item_title_va_approve', 'javascript:void(0)', 'javascript:bx_approve(this, ''{module_uri}'', {content_id});', '', 'check', '', 2147483647, '', 1, 0, 60);
+
+-- 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_events_view_actions_all', '_sys_menu_title_view_actions', 'bx_events_view_actions_all', 'bx_events', 15, 0, 1, 'BxEventsMenuViewActionsAll', 'modules/boonex/events/classes/BxEventsMenuViewActionsAll.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_events_view_actions_all', 'bx_events', '_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_events_view_actions_all', 'bx_events', 'join-event-profile', '_bx_events_menu_item_title_system_pay_and_join', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 5),
+('bx_events_view_actions_all', 'bx_events', 'profile-fan-add', '_bx_events_menu_item_title_system_become_fan', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 10),
+('bx_events_view_actions_all', 'bx_events', 'profile-fan-remove', '_bx_events_menu_item_title_system_leave_group', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 20),
+('bx_events_view_actions_all', 'bx_events', 'profile-subscribe-add', '_bx_events_menu_item_title_system_subscribe', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 30),
+('bx_events_view_actions_all', 'bx_events', 'profile-subscribe-remove', '_bx_events_menu_item_title_system_unsubscribe', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 40),
+('bx_events_view_actions_all', 'bx_events', 'profile-set-badges', '_sys_menu_item_title_system_set_badges', '', '', '', '', '', '', '', 0, 192, 'a:2:{s:6:"module";s:9:"bx_events";s:6:"method";s:19:"is_badges_avaliable";}', 1, 0, 50),
+('bx_events_view_actions_all', 'bx_events', 'ical-export', '', '_bx_events_menu_item_title_ical_export', '{ical_url}', '', '', 'calendar-plus', '', '', 0, 2147483647, 'a:3:{s:6:"module";s:9:"bx_events";s:6:"method";s:24:"is_ical_export_avaliable";s:6:"params";a:1:{i:0;s:12:"{content_id}";}}', 1, 0, 60),
+('bx_events_view_actions_all', 'bx_events', 'comment', '_sys_menu_item_title_system_va_comment', '', '', '', '', '', '', '', 0, 2147483647, '', 0, 0, 200),
+('bx_events_view_actions_all', 'bx_events', 'view', '_sys_menu_item_title_system_va_view', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 210),
+('bx_events_view_actions_all', 'bx_events', 'vote', '_sys_menu_item_title_system_va_vote', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 220),
+('bx_events_view_actions_all', 'bx_events', 'score', '_sys_menu_item_title_system_va_score', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 230),
+('bx_events_view_actions_all', 'bx_events', 'favorite', '_sys_menu_item_title_system_va_favorite', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 240),
+('bx_events_view_actions_all', 'bx_events', 'feature', '_sys_menu_item_title_system_va_feature', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 250),
+('bx_events_view_actions_all', 'bx_events', 'repost', '_sys_menu_item_title_system_va_repost', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 260),
+('bx_events_view_actions_all', 'bx_events', 'report', '_sys_menu_item_title_system_va_report', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 270),
+('bx_events_view_actions_all', 'bx_events', '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_events_view_actions_all', 'bx_events', 'audit', '_sys_menu_item_title_system_va_audit', '_sys_menu_item_title_va_audit', 'page.php?i=dashboard-audit&module=bx_events&content_id={content_id}', '', '', 'history', '', '', 0, 192, '', 1, 0, 290),
+('bx_events_view_actions_all', 'bx_events', 'social-sharing', '_sys_menu_item_title_system_social_sharing', '_sys_menu_item_title_social_sharing', 'javascript:void(0)', 'oBxDolPage.share(this, \'{url_encoded}\')', '', 'share', '', '', 0, 2147483647, '', 1, 0, 300),
+('bx_events_view_actions_all', 'bx_events', 'edit-event-cover', '_bx_events_menu_item_title_system_edit_cover', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 400),
+('bx_events_view_actions_all', 'bx_events', 'edit-event-profile', '_bx_events_menu_item_title_system_edit_profile', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 410),
+('bx_events_view_actions_all', 'bx_events', 'edit-event-pricing', '_bx_events_menu_item_title_system_edit_pricing', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 415),
+('bx_events_view_actions_all', 'bx_events', 'invite-to-event', '_bx_events_menu_item_title_system_invite', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 420),
+('bx_events_view_actions_all', 'bx_events', 'delete-event-profile', '_bx_events_menu_item_title_system_delete_profile', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 430),
+('bx_events_view_actions_all', 'bx_events', 'approve-event-profile', '_sys_menu_item_title_system_va_approve', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 440),
+('bx_events_view_actions_all', 'bx_events', '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: meta (counters) 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_events_view_meta', '_bx_events_menu_title_view_profile_meta', 'bx_events_view_meta', 'bx_events', 15, 0, 1, 'BxEventsMenuViewMeta', 'modules/boonex/events/classes/BxEventsMenuViewMeta.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_events_view_meta', 'bx_events', '_bx_events_menu_set_title_view_profile_meta', 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`, `order`) VALUES 
+('bx_events_view_meta', 'bx_events', 'members', '_sys_menu_item_title_system_sm_members', '_sys_menu_item_title_sm_members', '', '', '', '', '', 0, 2147483647, '', 1, 0, 10),
+('bx_events_view_meta', 'bx_events', 'subscribers', '_sys_menu_item_title_system_sm_subscribers', '_sys_menu_item_title_sm_subscribers', '', '', '', '', '', 0, 2147483647, '', 1, 0, 20),
+('bx_events_view_meta', 'bx_events', 'views', '_sys_menu_item_title_system_sm_views', '_sys_menu_item_title_sm_views', '', '', '', '', '', 0, 2147483647, '', 1, 0, 30),
+('bx_events_view_meta', 'bx_events', 'votes', '_sys_menu_item_title_system_sm_votes', '_sys_menu_item_title_sm_votes', '', '', '', '', '', 0, 2147483647, '', 1, 0, 40),
+('bx_events_view_meta', 'bx_events', 'comments', '_sys_menu_item_title_system_sm_comments', '_sys_menu_item_title_sm_comments', '', '', '', '', '', 0, 2147483647, '', 1, 0, 50);
+
+-- 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_events_my', '_bx_events_menu_title_entries_my', 'bx_events_my', 'bx_events', 9, 0, 1, 'BxEventsMenu', 'modules/boonex/events/classes/BxEventsMenu.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_events_my', 'bx_events', '_bx_events_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_events_my', 'bx_events', 'create-event-profile', '_bx_events_menu_item_title_system_create_profile', '_bx_events_menu_item_title_create_profile', 'page.php?i=create-event-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_events_submenu', '_bx_events_menu_title_submenu', 'bx_events_submenu', 'bx_events', 8, 0, 1, '', '');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_events_submenu', 'bx_events', '_bx_events_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_events_submenu', 'bx_events', 'events-home', '_bx_events_menu_item_title_system_entries_recent', '_bx_events_menu_item_title_entries_recent', 'page.php?i=events-home', '', '', '', '', 2147483647, 1, 1, 1),
+('bx_events_submenu', 'bx_events', 'events-top', '_bx_events_menu_item_title_system_entries_top', '_bx_events_menu_item_title_entries_top', 'page.php?i=events-top', '', '', '', '', 2147483647, 1, 1, 2),
+('bx_events_submenu', 'bx_events', 'events-upcoming', '_bx_events_menu_item_title_system_entries_upcoming', '_bx_events_menu_item_title_entries_upcoming', 'page.php?i=events-upcoming', '', '', '', '', 2147483647, 1, 1, 3),
+('bx_events_submenu', 'bx_events', 'events-past', '_bx_events_menu_item_title_system_entries_past', '_bx_events_menu_item_title_entries_past', 'page.php?i=events-past', '', '', '', '', 2147483647, 1, 1, 4),
+('bx_events_submenu', 'bx_events', 'events-calendar', '_bx_events_menu_item_title_system_calendar', '_bx_events_menu_item_title_calendar', 'page.php?i=events-calendar', '', '', '', '', 2147483647, 1, 1, 5),
+('bx_events_submenu', 'bx_events', 'events-search', '_bx_events_menu_item_title_system_entries_search', '_bx_events_menu_item_title_entries_search', 'page.php?i=events-search', '', '', '', '', 2147483647, 1, 1, 6),
+('bx_events_submenu', 'bx_events', 'events-joined', '_bx_events_menu_item_title_system_entries_joined', '_bx_events_menu_item_title_entries_joined', 'page.php?i=events-joined', '', '', '', '', 2147483647, 1, 1, 7),
+('bx_events_submenu', 'bx_events', 'events-manage', '_bx_events_menu_item_title_system_entries_manage', '_bx_events_menu_item_title_entries_manage', 'page.php?i=events-manage', '', '', '', '', 2147483646, 1, 1, 8);
+
+-- 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_events_view_submenu', '_bx_events_menu_title_view_profile_submenu', 'bx_events_view_submenu', 'bx_events', 18, 0, 1, 'BxEventsMenuView', 'modules/boonex/events/classes/BxEventsMenuView.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_events_view_submenu', 'bx_events', '_bx_events_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_events_view_submenu', 'bx_events', 'view-event-profile', '_bx_events_menu_item_title_system_view_profile_view', '_bx_events_menu_item_title_view_profile_view', 'page.php?i=view-event-profile&id={content_id}', '', '', 'calendar col-red2', '', '', 0, 2147483647, 1, 0, 1),
+('bx_events_view_submenu', 'bx_events', 'event-profile-info', '_bx_events_menu_item_title_system_view_profile_info', '_bx_events_menu_item_title_view_profile_info', 'page.php?i=event-profile-info&id={content_id}', '', '', 'info-circle col-gray', '', '', 0, 2147483647, 1, 0, 2),
+('bx_events_view_submenu', 'bx_events', 'event-profile-comments', '_bx_events_menu_item_title_system_view_profile_comments', '_bx_events_menu_item_title_view_profile_comments', 'page.php?i=event-profile-comments&id={content_id}', '', '', '', '', '', 0, 2147483647, 0, 0, 3),
+('bx_events_view_submenu', 'bx_events', 'event-fans', '_bx_events_menu_item_title_system_view_fans', '_bx_events_menu_item_title_view_fans', 'page.php?i=event-fans&profile_id={profile_id}', '', '', 'calendar col-blue3', '', '', 0, 2147483647, 1, 0, 4),
+('bx_events_view_submenu', 'bx_events', 'more-auto', '_bx_events_menu_item_title_system_view_profile_more_auto', '_bx_events_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_events_snippet_meta', '_sys_menu_title_snippet_meta', 'bx_events_snippet_meta', 'bx_events', 15, 0, 1, 'BxEventsMenuSnippetMeta', 'modules/boonex/events/classes/BxEventsMenuSnippetMeta.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_events_snippet_meta', 'bx_events', '_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_events_snippet_meta', 'bx_events', 'date', '_sys_menu_item_title_system_sm_date', '_sys_menu_item_title_sm_date', '', '', '', '', '', 2147483647, '', 0, 0, 1, 1),
+('bx_events_snippet_meta', 'bx_events', 'date-start', '_bx_events_menu_item_title_system_sm_date_start', '_bx_events_menu_item_title_sm_date_start', '', '', '', '', '', 2147483647, '', 0, 0, 1, 2),
+('bx_events_snippet_meta', 'bx_events', 'date-end', '_bx_events_menu_item_title_system_sm_date_end', '_bx_events_menu_item_title_sm_date_end', '', '', '', '', '', 2147483647, '', 0, 0, 1, 3),
+('bx_events_snippet_meta', 'bx_events', 'category', '_sys_menu_item_title_system_sm_category', '_sys_menu_item_title_sm_category', '', '', '', '', '', 2147483647, '', 0, 0, 1, 5),
+('bx_events_snippet_meta', 'bx_events', 'tags', '_sys_menu_item_title_system_sm_tags', '_sys_menu_item_title_sm_tags', '', '', '', '', '', 2147483647, '', 0, 0, 1, 10),
+('bx_events_snippet_meta', 'bx_events', 'views', '_sys_menu_item_title_system_sm_views', '_sys_menu_item_title_sm_views', '', '', '', '', '', 2147483647, '', 0, 0, 1, 15),
+('bx_events_snippet_meta', 'bx_events', 'comments', '_sys_menu_item_title_system_sm_comments', '_sys_menu_item_title_sm_comments', '', '', '', '', '', 2147483647, '', 0, 0, 1, 20),
+('bx_events_snippet_meta', 'bx_events', 'members', '_sys_menu_item_title_system_sm_members', '_sys_menu_item_title_sm_members', '', '', '', '', '', 2147483647, '', 1, 0, 1, 25),
+('bx_events_snippet_meta', 'bx_events', 'subscribers', '_sys_menu_item_title_system_sm_subscribers', '_sys_menu_item_title_sm_subscribers', '', '', '', '', '', 2147483647, '', 0, 0, 1, 30),
+('bx_events_snippet_meta', 'bx_events', 'country', '_sys_menu_item_title_system_sm_country', '_sys_menu_item_title_sm_country', '', '', '', '', '', 2147483647, '', 0, 0, 1, 35),
+('bx_events_snippet_meta', 'bx_events', 'country-city', '_sys_menu_item_title_system_sm_country_city', '_sys_menu_item_title_sm_country_city', '', '', '', '', '', 2147483647, '', 0, 0, 1, 40),
+('bx_events_snippet_meta', 'bx_events', 'nl', '_sys_menu_item_title_system_sm_nl', '_sys_menu_item_title_sm_nl', '', '', '', '', '', 2147483647, '', 1, 0, 1, 45),
+('bx_events_snippet_meta', 'bx_events', '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_events";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, 50),
+('bx_events_snippet_meta', 'bx_events', 'join', '_sys_menu_item_title_system_sm_join', '_sys_menu_item_title_sm_join', '', '', '', '', '', 2147483647, 'a:3:{s:6:"module";s:9:"bx_events";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, 55),
+('bx_events_snippet_meta', 'bx_events', 'leave', '_sys_menu_item_title_system_sm_leave', '_sys_menu_item_title_sm_leave', '', '', '', '', '', 2147483647, '', 0, 0, 1, 60),
+('bx_events_snippet_meta', 'bx_events', 'subscribe', '_sys_menu_item_title_system_sm_subscribe', '_sys_menu_item_title_sm_subscribe', '', '', '', '', '', 2147483647, '', 0, 0, 1, 65),
+('bx_events_snippet_meta', 'bx_events', 'unsubscribe', '_sys_menu_item_title_system_sm_unsubscribe', '_sys_menu_item_title_sm_unsubscribe', '', '', '', '', '', 2147483647, '', 0, 0, 1, 70);
+
+-- 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_events', 'profile-stats-my-events', '_bx_events_menu_item_title_system_manage_my_groups', '_bx_events_menu_item_title_manage_my_groups', 'page.php?i=joined-events&profile_id={member_id}', '', '_self', 'calendar col-red2', 'a:2:{s:6:"module";s:9:"bx_events";s:6:"method";s:41:"get_menu_addon_manage_tools_profile_stats";}', '', 2147483646, 1, 0, @iNotifMenuOrder + 2);
+
+-- MENU: profile followings
+SET @iFollowingsMenuOrder = (SELECT IFNULL(MAX(`order`), 0) FROM `sys_menu_items` WHERE `set_name`='sys_profile_followings' LIMIT 1);
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `addon`, `submenu_object`, `visible_for_levels`, `collapsed`, `active`, `copyable`, `order`) VALUES 
+('sys_profile_followings', 'bx_events', 'events', '_bx_events_menu_item_title_system_followings', '_bx_events_menu_item_title_followings', 'javascript:void(0)', '', '_self', 'calendar col-red2', '', '', 2147483647, 0, 1, 0, @iFollowingsMenuOrder + 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_events_menu_manage_tools', '_bx_events_menu_title_manage_tools', 'bx_events_menu_manage_tools', 'bx_events', 6, 0, 1, 'BxEventsMenuManageTools', 'modules/boonex/events/classes/BxEventsMenuManageTools.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_events_menu_manage_tools', 'bx_events', '_bx_events_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_events_menu_manage_tools', 'bx_events', 'delete', '_bx_events_menu_item_title_system_delete', '_bx_events_menu_item_title_delete', 'javascript:void(0)', 'javascript:{js_object}.onClickDelete({content_id});', '_self', 'far trash-alt', '', 2147483647, 1, 0, 1),
+('bx_events_menu_manage_tools', 'bx_events', 'delete-with-content', '_bx_events_menu_item_title_system_delete_with_content', '_bx_events_menu_item_title_delete_with_content', 'javascript:void(0)', 'javascript:{js_object}.onClickDeleteWithContent({content_id});', '_self', 'far trash-alt', '', 2147483647, 1, 0, 2),
+('bx_events_menu_manage_tools', 'bx_events', 'clear-reports', '_bx_cevents_menu_item_title_system_clear_reports', '_bx_events_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_events', 'events-administration', '_bx_events_menu_item_title_system_admt_groups', '_bx_events_menu_item_title_admt_groups', 'page.php?i=events-administration', '', '_self', 'calendar', 'a:2:{s:6:"module";s:9:"bx_events";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_events', 'joined-events', '_bx_events_menu_item_title_system_view_joined_groups', '_bx_events_menu_item_title_view_joined_groups', 'page.php?i=joined-events&profile_id={profile_id}', '', '', 'calendar col-red2', '', 2147483647, '', 1, 0, 0),
+('trigger_group_view_submenu', 'bx_events', 'events-context', '_bx_events_menu_item_title_system_view_entries_in_context', '_bx_events_menu_item_title_view_entries_in_context', 'page.php?i=events-context&profile_id={profile_id}', '', '', 'calendar col-red2', '', 2147483647, 'a:3:{s:6:"module";s:9:"bx_events";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_events', 'create entry', NULL, '_bx_events_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_events', 'use paid join', NULL, '_bx_events_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_events', 'delete entry', NULL, '_bx_events_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_events', 'view entry', NULL, '_bx_events_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_events', 'edit any entry', NULL, '_bx_events_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_events', 'delete any entry', NULL, '_bx_events_acl_action_delete_any_profile', '', 1, 3);
+SET @iIdActionProfileDeleteAny = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_events', 'delete invites', NULL, '_bx_events_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 profile delete
+(@iAdministrator, @iIdActionProfileDeleteAny),
+
+-- any invites edit
+(@iModerator, @iIdActionProfileDeleteInvites),
+(@iAdministrator, @iIdActionProfileDeleteInvites);
+
+-- METATAGS
+INSERT INTO `sys_objects_metatags` (`object`, `module`, `table_keywords`, `table_locations`, `table_mentions`, `override_class_name`, `override_class_file`) VALUES
+('bx_events', 'bx_events', 'bx_events_meta_keywords', 'bx_events_meta_locations', 'bx_events_meta_mentions', '', '');
+
+-- CATEGORY
+INSERT INTO `sys_objects_category` (`object`, `module`, `search_object`, `form_object`, `list_name`, `table`, `field`, `join`, `where`, `override_class_name`, `override_class_file`) VALUES
+('bx_events_cats', 'bx_events', 'bx_events', 'bx_event', 'bx_events_cats', 'bx_events_data', 'event_cat', 'INNER JOIN `sys_profiles` ON (`sys_profiles`.`content_id` = `bx_events_data`.`id` AND `sys_profiles`.`type` = ''bx_events'')', '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_events', '_bx_events', @iSearchOrder + 1, 'BxEventsSearchResult', 'modules/boonex/events/classes/BxEventsSearchResult.php');
+
+-- CONNECTIONS
+INSERT INTO `sys_objects_connection` (`object`, `table`, `profile_initiator`, `profile_content`, `type`, `override_class_name`, `override_class_file`) VALUES
+('bx_events_fans', 'bx_events_fans', 1, 1, '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_events', 'bx_events', '_bx_events', 'page.php?i=events-home', 'calendar col-red2', 'SELECT COUNT(*) FROM `bx_events_data` AS `td` LEFT JOIN `sys_profiles` AS `tp` ON `td`.`id` = `tp`.`content_id` AND `tp`.`type`=''bx_events'' 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_events_growth', '_bx_events_chart_growth', 'bx_events_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_events'' WHERE 1 AND `tp`.`status`=''active'' {where_inteval} GROUP BY `period` ORDER BY {table}.{field_date} ASC', 1, @iMaxOrderCharts + 1, 'BxDolChartGrowth', ''),
+('bx_events_growth_speed', '_bx_events_chart_growth_speed', 'bx_events_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_events'' 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_events_fans', 'Sql', 'SELECT `p`.`id`, `c`.`added`, `c`.`mutual` FROM `sys_profiles` AS `p` INNER JOIN `sys_accounts` AS `a` ON (`a`.`id` = `p`.`account_id`) {join_connections}', 'sys_profiles', 'id', 'c`.`added', '', '', 10, NULL, 'start', '', 'name,email', '', 'auto', '', '', 2147483647, 0, 'BxEventsGridConnections', 'modules/boonex/events/classes/BxEventsGridConnections.php');
+
+INSERT INTO `sys_grid_fields` (`object`, `name`, `title`, `width`, `params`, `order`) VALUES
+('bx_events_fans', 'name', '_sys_name', '50%', '', 10),
+('bx_events_fans', 'role', '_bx_events_txt_role', '10%', '', 15),
+('bx_events_fans', 'role_added', '_bx_events_txt_role_added', '10%', '', 16),
+('bx_events_fans', 'role_expired', '_bx_events_txt_role_expired', '10%', '', 17),
+('bx_events_fans', 'actions', '', '20%', '', 20);
+
+INSERT INTO `sys_grid_actions` (`object`, `type`, `name`, `title`, `icon`, `confirm`, `order`) VALUES
+('bx_events_fans', 'single', 'accept', '_sys_accept', '', 0, 10),
+('bx_events_fans', 'single', 'set_role', '_bx_events_txt_set_role', '', 0, 20),
+('bx_events_fans', 'single', 'set_role_submit', '', '', 0, 21),
+('bx_events_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_events_invites', 'Sql', 'SELECT `bx_events_invites`.`id`, `bx_events_invites`.`invited_profile_id`, `bx_events_invites`.`added`, `bx_events_invites`.`author_profile_id` FROM `sys_profiles` AS `p` INNER JOIN `sys_accounts` AS `a` ON (`a`.`id` = `p`.`account_id`) INNER JOIN `bx_events_invites` ON `bx_events_invites`.`invited_profile_id` = `p`.`id` ', 'bx_events_invites', 'id', 'bx_events_invites`.`added', '', '', 10, NULL, 'start', '', 'name,email', '', 'auto', '', '', 2147483647, 0, 'BxEventsGridInvites', 'modules/boonex/events/classes/BxEventsGridInvites.php');
+
+INSERT INTO `sys_grid_fields` (`object`, `name`, `title`, `width`, `params`, `order`) VALUES
+('bx_events_invites', 'name', '_sys_name', '33%', '', 10),
+('bx_events_invites', 'added', '_sys_added', '33%', '', 20),
+('bx_events_invites', 'actions', '', '34%', '', 30);
+
+INSERT INTO `sys_grid_actions` (`object`, `type`, `name`, `title`, `icon`, `confirm`, `order`) VALUES
+('bx_events_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_events_administration', 'Sql', 'SELECT `td`.*, `td`.`event_name` AS `name`, `ta`.`email` AS `account`, `td`.`added` AS `added_ts`, `tp`.`status` AS `status` FROM `bx_events_data` AS `td` LEFT JOIN `sys_profiles` AS `tp` ON `td`.`id`=`tp`.`content_id` AND `tp`.`type`=''bx_events'' LEFT JOIN `sys_accounts` AS `ta` ON `tp`.`account_id`=`ta`.`id` WHERE 1 ', 'bx_events_data', 'id', 'added', 'status_admin', '', 20, NULL, 'start', '', 'event_name', '', 'like', 'reports', '', 192, 'BxEventsGridAdministration', 'modules/boonex/events/classes/BxEventsGridAdministration.php'),
+('bx_events_common', 'Sql', 'SELECT `td`.*, `td`.`event_name` AS `name`, `ta`.`email` AS `account`, `td`.`added` AS `added_ts`, `tp`.`status` AS `status` FROM `bx_events_data` AS `td` LEFT JOIN `sys_profiles` AS `tp` ON `td`.`id`=`tp`.`content_id` AND `tp`.`type`=''bx_events'' LEFT JOIN `sys_accounts` AS `ta` ON `tp`.`account_id`=`ta`.`id` WHERE 1 ', 'bx_events_data', 'id', 'added', 'status', '', 20, NULL, 'start', '', 'event_name', '', 'like', '', '', 2147483647, 'BxEventsGridCommon', 'modules/boonex/events/classes/BxEventsGridCommon.php');
+
+INSERT INTO `sys_grid_fields` (`object`, `name`, `title`, `width`, `translatable`, `chars_limit`, `params`, `order`) VALUES
+('bx_events_administration', 'checkbox', '_sys_select', '2%', 0, '', '', 1),
+('bx_events_administration', 'switcher', '_bx_events_grid_column_title_adm_active', '8%', 0, '', '', 2),
+('bx_events_administration', 'reports', '_sys_txt_reports_title', '5%', 0, '', '', 3),
+('bx_events_administration', 'name', '_bx_events_grid_column_title_adm_name', '25%', 0, '', '', 4),
+('bx_events_administration', 'added_ts', '_bx_events_grid_column_title_adm_added', '20%', 1, '25', '', 5),
+('bx_events_administration', 'account', '_bx_events_grid_column_title_adm_account', '20%', 0, '25', '', 6),
+('bx_events_administration', 'actions', '', '20%', 0, '', '', 7),
+
+('bx_events_common', 'checkbox', '_sys_select', '2%', 0, '', '', 1),
+('bx_events_common', 'switcher', '_bx_groups_grid_column_title_adm_active', '8%', 0, '', '', 2),
+('bx_events_common', 'name', '_bx_events_grid_column_title_adm_name', '40%', 0, '', '', 3),
+('bx_events_common', 'added_ts', '_bx_events_grid_column_title_adm_added', '30%', 1, '25', '', 4),
+('bx_events_common', 'actions', '', '20%', 0, '', '', 5);
+
+INSERT INTO `sys_grid_actions` (`object`, `type`, `name`, `title`, `icon`, `icon_only`, `confirm`, `order`) VALUES
+('bx_events_administration', 'bulk', 'delete', '_bx_events_grid_action_title_adm_delete', '', 0, 1, 2),
+('bx_events_administration', 'bulk', 'delete_with_content', '_bx_events_grid_action_title_adm_delete_with_content', '', 0, 1, 3),
+('bx_events_administration', 'bulk', 'clear_reports', '_bx_events_grid_action_title_adm_clear_reports', '', 0, 1, 3),
+('bx_events_administration', 'single', 'settings', '_bx_events_grid_action_title_adm_more_actions', 'cog', 1, 0, 2),
+('bx_events_administration', 'single', 'audit_content', '_bx_events_grid_action_title_adm_audit_content', 'search', 1, 0, 3),
+('bx_events_administration', 'single', 'audit_context', '_bx_events_grid_action_title_adm_audit_context', 'search-location', 1, 0, 4),
+
+('bx_events_common', 'bulk', 'delete', '_bx_events_grid_action_title_adm_delete', '', 0, 1, 1),
+('bx_events_common', 'bulk', 'delete_with_content', '_bx_events_grid_action_title_adm_delete_with_content', '', 0, 1, 2),
+('bx_events_common', 'single', 'settings', '_bx_events_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_events_prices_manage', 'Sql', 'SELECT * FROM `bx_events_prices` WHERE 1 ', 'bx_events_prices', 'id', 'order', '', '', 100, NULL, 'start', '', 'period,period_unit,price', '', 'like', '', '', 2147483647, 'BxEventsGridPricesManage', 'modules/boonex/events/classes/BxEventsGridPricesManage.php'),
+('bx_events_prices_view', 'Sql', 'SELECT * FROM `bx_events_prices` WHERE 1 ', 'bx_events_prices', 'id', 'order', '', '', 100, NULL, 'start', '', 'period,period_unit,price', '', 'like', '', '', 2147483647, 'BxEventsGridPricesView', 'modules/boonex/events/classes/BxEventsGridPricesView.php');
+
+INSERT INTO `sys_grid_fields` (`object`, `name`, `title`, `width`, `translatable`, `chars_limit`, `params`, `order`) VALUES
+('bx_events_prices_manage', 'checkbox', '_sys_select', '1%', 0, '', '', 1),
+('bx_events_prices_manage', 'order', '', '1%', 0, '', '', 2),
+('bx_events_prices_manage', 'name', '_bx_events_grid_column_title_name', '38%', 0, 32, '', 3),
+('bx_events_prices_manage', 'price', '_bx_events_grid_column_title_price', '20%', 0, 16, '', 4),
+('bx_events_prices_manage', 'period', '_bx_events_grid_column_title_period', '20%', 0, 16, '', 5),
+('bx_events_prices_manage', 'actions', '', '20%', 0, '', '', 6),
+
+('bx_events_prices_view', 'role_id', '_bx_events_grid_column_title_role_id', '40%', 0, 32, '', 1),
+('bx_events_prices_view', 'price', '_bx_events_grid_column_title_price', '20%', 0, 16, '', 2),
+('bx_events_prices_view', 'period', '_bx_events_grid_column_title_period', '20%', 0, 16, '', 3),
+('bx_events_prices_view', 'actions', '', '20%', 0, '', '', 4);
+
+INSERT INTO `sys_grid_actions` (`object`, `type`, `name`, `title`, `icon`, `icon_only`, `confirm`, `order`) VALUES
+('bx_events_prices_manage', 'independent', 'add', '_bx_events_grid_action_title_add', '', 0, 0, 1),
+('bx_events_prices_manage', 'single', 'edit', '_bx_events_grid_action_title_edit', 'pencil-alt', 1, 0, 1),
+('bx_events_prices_manage', 'single', 'delete', '_bx_events_grid_action_title_delete', 'remove', 1, 1, 2),
+('bx_events_prices_manage', 'bulk', 'delete', '_bx_events_grid_action_title_delete', '', 0, 1, 1),
+
+('bx_events_prices_view', 'single', 'buy', '_bx_events_grid_action_title_buy', 'cart-plus', 0, 0, 1),
+('bx_events_prices_view', 'single', 'subscribe', '_bx_events_grid_action_title_subscribe', 'credit-card', 0, 0, 2),
+('bx_events_prices_view', 'single', 'choose', '_bx_events_grid_action_title_choose', 'far check-square', 0, 0, 3);
+
+
+-- ALERTS
+INSERT INTO `sys_alerts_handlers` (`name`, `class`, `file`, `service_call`) VALUES 
+('bx_events', 'BxEventsAlertsResponse', 'modules/boonex/events/classes/BxEventsAlertsResponse.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_events_pics', 'file_deleted', @iHandler),
+('bx_events_fans', 'connection_added', @iHandler),
+('bx_events_fans', 'connection_removed', @iHandler),
+('profile', 'delete', @iHandler),
+('bx_events', 'fan_added', @iHandler),
+('bx_events', 'join_invitation', @iHandler),
+('bx_events', 'join_request', @iHandler),
+('bx_events', 'join_request_accepted', @iHandler),
+('bx_events', 'timeline_view', @iHandler),
+('bx_events', 'timeline_post', @iHandler),
+('bx_events', 'timeline_delete', @iHandler),
+('bx_events', 'timeline_comment', @iHandler),
+('bx_events', 'timeline_vote', @iHandler),
+('bx_events', 'timeline_score', @iHandler),
+('bx_events', 'timeline_report', @iHandler),
+('bx_events', 'timeline_repost', @iHandler),
+('bx_events', 'timeline_pin', @iHandler),
+('bx_events', '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_events_allow_view_to', 'bx_events', 'view', '_bx_events_form_profile_input_allow_view_to', '3', 'bx_groups,bx_spaces', 'bx_events_data', 'id', 'author', 'BxEventsPrivacy', 'modules/boonex/events/classes/BxEventsPrivacy.php'),
+('bx_events_allow_view_notification_to', 'bx_events', 'view_event', '_bx_events_form_profile_input_allow_view_notification_to', '3', '', 'bx_notifications_events', 'id', 'object_owner_id', 'BxEventsPrivacyNotifications', 'modules/boonex/events/classes/BxEventsPrivacyNotifications.php'),
+('bx_events_allow_post_to', 'bx_events', 'post', '_bx_events_form_profile_input_allow_post_to', 'p', '', 'bx_events_data', 'id', 'author', 'BxEventsPrivacyPost', 'modules/boonex/events/classes/BxEventsPrivacyPost.php'),
+('bx_events_allow_view_favorite_list', 'bx_events', 'view_favorite_list', '_bx_events_form_profile_input_allow_view_favorite_list', '3', '', 'bx_events_favorites_lists', 'id', 'author_id', 'BxEventsPrivacy', 'modules/boonex/events/classes/BxEventsPrivacy.php');
+
+
+-- EMAIL TEMPLATES
+INSERT INTO `sys_email_templates` (`Module`, `NameSystem`, `Name`, `Subject`, `Body`) VALUES
+('bx_events', '_bx_events_email_join_request', 'bx_events_join_request', '_bx_events_email_join_request_subject', '_bx_events_email_join_request_body'),
+('bx_events', '_bx_events_email_join_reject', 'bx_events_join_reject', '_bx_events_email_join_reject_subject', '_bx_events_email_join_reject_body'),
+('bx_events', '_bx_events_email_join_confirm', 'bx_events_join_confirm', '_bx_events_email_join_confirm_subject', '_bx_events_email_join_confirm_body'),
+('bx_events', '_bx_events_email_fan_remove', 'bx_events_fan_remove', '_bx_events_email_fan_remove_subject', '_bx_events_email_fan_remove_body'),
+('bx_events', '_bx_events_email_fan_become_admin', 'bx_events_fan_become_admin', '_bx_events_email_fan_become_admin_subject', '_bx_events_email_fan_become_admin_body'),
+('bx_events', '_bx_events_email_admin_become_fan', 'bx_events_admin_become_fan', '_bx_events_email_admin_become_fan_subject', '_bx_events_email_admin_become_fan_body'),
+('bx_events', '_bx_events_email_set_role', 'bx_events_set_role', '_bx_events_email_set_role_subject', '_bx_events_email_set_role_body'),
+('bx_events', '_bx_events_email_invitation', 'bx_events_invitation', '_bx_events_email_invitation_subject', '_bx_events_email_invitation_body'),
+('bx_events', '_bx_events_email_reminder', 'bx_events_reminder', '_bx_events_email_reminder_subject', '_bx_events_email_reminder_body');
+
+-- UPLOADERS
+INSERT INTO `sys_objects_uploader` (`object`, `active`, `override_class_name`, `override_class_file`) VALUES
+('bx_events_cover_crop', 1, 'BxEventsUploaderCoverCrop', 'modules/boonex/events/classes/BxEventsUploaderCoverCrop.php'),
+('bx_events_picture_crop', 1, 'BxEventsUploaderPictureCrop', 'modules/boonex/events/classes/BxEventsUploaderPictureCrop.php');
+
+-- CRON
+INSERT INTO `sys_cron_jobs` (`name`, `time`, `class`, `file`, `service_call`) VALUES
+('bx_events_process_reminders', '55 * * * *', 'BxEventsCronProcessReminders', 'modules/boonex/events/classes/BxEventsCronProcessReminders.php', ''),
+('bx_events_pruning', '0 0 * * *', 'BxEventsCronPruning', 'modules/boonex/events/classes/BxEventsCronPruning.php', ''),
+('bx_events_publishing', '* * * * *', 'BxEventsCronPublishing', 'modules/boonex/events/classes/BxEventsCronPublishing.php', '');

+ 15 - 0
modules/boonex/events/updates/13.0.2_13.0.3/source/template/timeline_post.html

@@ -0,0 +1,15 @@
+<div class="vevent bx-tl-item-text">
+    <div class="bx-tl-title bx-def-margin-sec-bottom bx-def-font-h3">
+        <a href="__url__" title="__title_attr__" class="summary url bx-tl-title">__title__</a>
+    </div>
+    <bx_if:date>
+    <div class="bx-tl-info bx-def-margin-sec-bottom bx-def-font-h3">
+        <i class="sys-icon calendar-alt bx-def-margin-thd-right"></i> <span class="dtstart" title="__date_c__">__date__</span>
+    </div>
+    </bx_if:date>
+    <bx_if:location>
+    <div class="bx-tl-info bx-def-margin-sec-bottom bx-def-font-h3">
+        <i class="sys-icon map-marker-alt bx-def-margin-thd-right"></i> <span class="location">__location__</span>
+    </div>
+    </bx_if:location>
+</div>

+ 51 - 0
modules/boonex/files/updates/13.0.2_13.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' => 'Files',
+    'version_from' => '13.0.2',
+    'version_to' => '13.0.3',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '13.0.0-B2'
+    ),
+
+    /**
+     * '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_13.0.2_13.0.3/',
+    'home_uri' => 'files_update_1302_1303',
+
+    'module_dir' => 'boonex/files/',
+    'module_uri' => 'files',
+
+    'db_prefix' => 'bx_files_',
+    'class_prefix' => 'BxFiles',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 0,
+        'update_files' => 1,
+        'update_languages' => 0,
+        'clear_db_cache' => 0,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Files',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

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

+ 609 - 0
modules/boonex/files/updates/13.0.2_13.0.3/source/classes/BxFilesModule.php

@@ -0,0 +1,609 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    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') . '" -Djava.awt.headless=true -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');
+                bx_set('cf', 1, '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);
+            }
+        }
+
+        echoJson(['success' => true]);
+    }
+
+    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);
+    }
+}
+
+/** @} */

+ 135 - 0
modules/boonex/files/updates/13.0.2_13.0.3/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' => '13.0.3',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '13.0.0-B2'
+    ),
+
+    /**
+     * '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',
+    ),
+
+);
+
+/** @} */

+ 155 - 0
modules/boonex/files/updates/13.0.2_13.0.3/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]').
+        prop('checked', $(el).prop('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');
+}

+ 163 - 0
modules/boonex/files/updates/13.0.2_13.0.3/source/template/css/main.css

@@ -0,0 +1,163 @@
+.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,
+.bx-media-desktop .bx-layout-column-thin .bx-files-text-unit-gallery {
+    max-width: 100%;
+}
+.bx-media-tablet2 .bx-files-text-unit-gallery,
+.bx-media-desktop .bx-layout-column-half .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;
+}
+
+/*--- 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;
+}
+.bx-files-input-checkbox-select-all {
+    display: inline-block!important;
+}

+ 73 - 0
modules/boonex/files/updates/13.0.2_13.0.3/source/template/files_browser_toolbar.html

@@ -0,0 +1,73 @@
+<div class="bx-def-padding-sec-leftright bx-def-border-bottom bx-files-border-thick bx-files-browser-toolbar bx-clearfix" id="bx-files-browser-toolbar-__unique_ident__">
+    <div class="bx-def-margin-bottom bx-files-folder-path">
+        <bx_repeat:folder_path>
+            <a href="#" onclick="__js_object__.folderNavigate(__folder__); return false;">__name__</a> <i class="sys-icon chevron-right"></i>
+        </bx_repeat:folder_path>
+    </div>
+    <bx_if:upload_visible>
+    <div class="bx-files-toolbar-controls-group">
+        __uploader_code__
+        <script>
+            function bx_files_inject_onupload_handler() {
+                if (typeof __uploader_js_object__ == 'undefined') {
+                    setTimeout(bx_files_inject_onupload_handler, 200);
+                    return;
+                }
+                __uploader_js_object__.onUploadCompletedDefault = __uploader_js_object__.onUploadCompleted;
+                __uploader_js_object__.onUploadCompleted = function (sErrorMsg) {
+                    __uploader_js_object__.onUploadCompletedDefault(sErrorMsg);
+                    __js_object__.onAfterUpload();
+                }
+            }
+            $(document).ready(function(){
+                //catch onUploadCompleted call here
+                setTimeout(bx_files_inject_onupload_handler, 200);
+            });
+        </script>
+        <button class="bx-btn" onclick="__js_object__.onBeforeUpload(); __uploader_js_object__.showUploaderForm();"><i class="sys-icon upload"></i>&nbsp;<bx_text:_bx_files_txt_upload /></button>
+        <bx_if:create_folder_allowed>
+        <button class="bx-btn" onclick="__js_object__.addFolder('__folder_name_message__');"><i class="sys-icon plus"></i>&nbsp;<bx_text:_bx_files_txt_add_folder /></button>
+        </bx_if:create_folder_allowed>
+    </div>
+    </bx_if:upload_visible>
+
+    <div class="bx-files-toolbar-controls-group">
+        <bx_if:table_layout_btn>
+            <button class="bx-btn bx-btn-disabled" title="<bx_text:_bx_files_toolbar_view_table />"><i class="sys-icon list"></i></button>
+            <button class="bx-btn" onclick="__js_object__.setView('gallery');" title="<bx_text:_bx_files_toolbar_view_gallery />"><i class="sys-icon th-large"></i></button>
+        </bx_if:table_layout_btn>
+        <bx_if:gallery_layout_btn>
+            <button class="bx-btn" onclick="__js_object__.setView('table');"  title="<bx_text:_bx_files_toolbar_view_table />"><i class="sys-icon list"></i></button>
+            <button class="bx-btn bx-btn-disabled" title="<bx_text:_bx_files_toolbar_view_gallery />"><i class="sys-icon th-large"></i></button>
+        </bx_if:gallery_layout_btn>
+    </div>
+
+    <bx_if:bookmarks_visible>
+    <div class="bx-files-toolbar-controls-group">
+        <button class="bx-btn" onclick="__js_object__.toggleBookmarks();" title="<bx_text:_bx_files_toolbar_view_bookmarks />"><i class="sys-icon __bookmark_enabled__ star"></i></button>
+    </div>
+    </bx_if:bookmarks_visible>
+
+    <div class="bx-files-toolbar-controls-group">
+        __sorting_dropdown__
+        __filter_box__
+    </div>
+    <div class="bx-files-bulk-actions bx-def-margin-bottom">
+        <bx_repeat:bulk_actions>
+            <button class="bx-btn" onclick="__js_object__.__handler__();" title="__title__"><i class="sys-icon __icon__"></i></button>
+        </bx_repeat:bulk_actions>
+    </div>
+</div>
+
+<div class="bx-files-toolbar-spacer"></div>
+
+<bx_if:select_all_checkbox>
+<div class="bx-def-padding-sec bx-files-text-unit-simple-row">
+    <div>
+        <input type="checkbox" class="bx-def-font-inputs bx-form-input-checkbox bx-files-input-checkbox-select-all bx-def-margin-right" id="bx-files-browser-select-all-__unique_ident__" onchange="__js_object__.onSelectAll(this);" />
+        <label for="bx-files-browser-select-all-__unique_ident__"><bx_text:_Select_all /></label>
+    </div>
+</div>
+</bx_if:select_all_checkbox>
+
+__js_code__

+ 55 - 0
modules/boonex/forum/updates/13.0.2_13.0.3/install/config.php

@@ -0,0 +1,55 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'title' => 'Discussions',
+    'version_from' => '13.0.2',
+    'version_to' => '13.0.3',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '13.0.0-B2'
+    ),
+
+    /**
+     * '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_13.0.2_13.0.3/',
+    'home_uri' => 'forum_update_1302_1303',
+
+    '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' => 1,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Discussions',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(
+        'template/images/icons/all-cat.svg',
+        'template/images/icons/default-cat.svg',
+        'template/category_list.html'
+    ),
+);

+ 13 - 0
modules/boonex/forum/updates/13.0.2_13.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 BxForumUpdater extends BxDolStudioUpdater
+{
+    function __construct($aConfig)
+    {
+        parent::__construct($aConfig);
+    }
+}

+ 6 - 0
modules/boonex/forum/updates/13.0.2_13.0.3/install/langs/en.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources name="en" flag="gb" title="English">
+	<string_add name="_bx_forum_option_visible_categories"><![CDATA[Number of visible categories]]></string_add>
+    <string_add name="_bx_forum_option_visible_hashtags"><![CDATA[Number of visible hashtags]]></string_add>
+	<string_add name="_bx_forum_menu_title_categories"><![CDATA[Categories]]></string_add>
+</resources>

+ 38 - 0
modules/boonex/forum/updates/13.0.2_13.0.3/install/sql/enable.sql

@@ -0,0 +1,38 @@
+SET @sName = 'bx_forum';
+
+
+-- SETTINGS
+SET @iCategId = (SELECT `id` FROM `sys_options_categories` WHERE `name`=@sName LIMIT 1);
+
+DELETE FROM `sys_options` WHERE `name`='bx_forum_visible_categories';
+INSERT INTO `sys_options` (`name`, `value`, `category_id`, `caption`, `type`, `check`, `check_error`, `extra`, `order`) VALUES
+('bx_forum_visible_categories', '10', @iCategId, '_bx_forum_option_visible_categories', 'digit', '', '', '', 40);
+
+
+-- PAGES
+UPDATE `sys_pages_blocks` SET `type`='menu', `content`='bx_forum_categories' WHERE `object`='bx_forum_category' AND `title`='_bx_forum_page_block_title_cats';
+
+UPDATE `sys_pages_blocks` SET `type`='menu', `content`='bx_forum_categories' WHERE `object`='bx_forum_home' AND `title`='_bx_forum_page_block_title_cats';
+UPDATE `sys_pages_blocks` SET `content`='a:4:{s:6:\"module\";s:6:\"system\";s:6:\"method\";s:14:\"keywords_cloud\";s:6:\"params\";a:3:{i:0;s:8:\"bx_forum\";i:1;s:8:\"bx_forum\";i:2;a:1:{s:9:\"menu_view\";b:1;}}s:5:\"class\";s:20:\"TemplServiceMetatags\";}' WHERE `object`='bx_forum_home' AND `title`='_bx_forum_page_block_title_popular_keywords';
+
+
+-- MENUS
+DELETE FROM `sys_menu_items` WHERE `set_name`='bx_forum_snippet_meta_main' AND `name` IN ('score', 'badges');
+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`, `hidden_on_col`) VALUES 
+('bx_forum_snippet_meta_main', 'bx_forum', 'score', '_bx_forum_menu_item_title_system_sm_vote', '_bx_forum_menu_item_title_sm_vote', '', '', '', '', '', 2147483647, 1, 0, 1, 0, 0);
+
+UPDATE `sys_menu_items` SET `hidden_on_col`='3' WHERE `set_name`='bx_forum_snippet_meta_main' AND `name`='comments';
+
+DELETE FROM `sys_objects_menu` WHERE `object`='bx_forum_categories';
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_forum_categories', '_bx_forum_menu_title_categories', '', 'bx_forum', 21, 0, 1, 'BxForumMenuCategories', 'modules/boonex/forum/classes/BxForumMenuCategories.php');
+
+
+-- GRIDS
+DELETE FROM `sys_grid_fields` WHERE `object`=@sName AND `name` IN ('category', 'participants', 'rating');
+UPDATE `sys_grid_fields` SET `width`='100%', `order`='1' WHERE `object`=@sName AND `name`='text';
+
+DELETE FROM `sys_grid_fields` WHERE `object`='bx_forum_favorite' AND `name` IN ('author');
+UPDATE `sys_grid_fields` SET `width`='100%' WHERE `object`='bx_forum_favorite' AND `name`='text';
+
+DELETE FROM `sys_grid_fields` WHERE `object`='bx_forum_feature';

+ 32 - 0
modules/boonex/forum/updates/13.0.2_13.0.3/source/classes/BxForumCategory.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    Forum Forum
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxForumCategory extends BxTemplCategory
+{
+	protected $MODULE;
+	protected $_oModule;
+
+	public function __construct($aObject, $oTemplate = null)
+    {
+    	$this->MODULE = 'bx_forum';
+    	$this->_oModule = BxDolModule::getInstance($this->MODULE);
+
+        parent::__construct($aObject, $oTemplate);
+
+        $CNF = $this->_oModule->_oConfig->CNF;
+
+        $this->_sBrowseUrl = bx_append_url_params(BxDolPermalinks::getInstance()->permalink('page.php?i=' . $CNF['URI_CATEGORY_ENTRIES']), array(
+			'category' => '{keyword}'
+		), true, ['{keyword}']);
+    }
+}
+
+/** @} */

+ 702 - 0
modules/boonex/forum/updates/13.0.2_13.0.3/source/classes/BxForumGrid.php

@@ -0,0 +1,702 @@
+<?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
+ *
+ * @{
+ */
+
+require_once(BX_DIRECTORY_PATH_INC . "design.inc.php");
+
+define('BX_FORUM_FILTER_STATUS_RESOLVED', 1);
+define('BX_FORUM_FILTER_STATUS_UNRESOLVED', 0);
+
+define('BX_FORUM_FILTER_ORDER_RECENT', 'latest');
+define('BX_FORUM_FILTER_ORDER_NEW', 'new');
+define('BX_FORUM_FILTER_ORDER_TOP', 'top');
+define('BX_FORUM_FILTER_ORDER_UPDATED', 'updated');
+define('BX_FORUM_FILTER_ORDER_POPULAR', 'popular');
+define('BX_FORUM_FILTER_ORDER_FEATURED', 'featured');
+define('BX_FORUM_FILTER_ORDER_FAVORITE', 'favorite');
+define('BX_FORUM_FILTER_ORDER_PARTAKEN', 'partaken');
+
+class BxForumGrid extends BxTemplGrid
+{
+    protected $_oModule;
+    protected $_sDefaultSource; 
+    
+    protected $_sFilter1Name;
+    protected $_sFilter1Value;
+    protected $_aFilter1Values;
+    
+    protected $_sFilter2Name;
+    protected $_sFilter2Value;
+    protected $_aFilter2Values;
+    
+    protected $_sFilter3Name;
+    protected $_sFilter3Value;
+    protected $_aFilter3Values;
+    
+    protected $_sParamsDivider;
+
+    public function __construct ($aOptions, $oTemplate = false)
+    {
+        $this->_oModule = BxDolModule::getInstance('bx_forum');
+
+        parent::__construct ($aOptions, $oTemplate);
+        
+        $this->_sFilter1Name = 'filter1';
+        $this->_aFilter1Values = array(
+            '' => _t('_bx_forum_grid_filter_resolved_all'),
+            BX_FORUM_FILTER_STATUS_RESOLVED => _t('_bx_forum_grid_filter_resolved_resolved'),
+            BX_FORUM_FILTER_STATUS_UNRESOLVED => _t('_bx_forum_grid_filter_resolved_unresolved'),
+        );
+        
+        $sFilter1 = bx_get($this->_sFilter1Name);
+        if(!empty($sFilter1)) {
+            $this->_sFilter1Value = bx_process_input($sFilter1);
+            $this->_aQueryAppend['filter1'] = $this->_sFilter1Value;
+        }
+        
+        $this->_sFilter2Name = 'filter2';
+        $aBadges = BxDolBadges::getInstance()->getData(['type' => 'by_module', 'module' => $this->_oModule->_aModule['name']]);
+        
+        $this->_aFilter2Values = [];
+        
+        if (count($aBadges) > 0){
+            $this->_aFilter2Values[''] = _t('_bx_forum_grid_filter_badges_all');
+        }
+        
+        foreach($aBadges as $aBadge) {
+            $this->_aFilter2Values[$aBadge['id']] = $aBadge['text'];
+        }
+        
+
+        $sFilter2 = bx_get($this->_sFilter1Name);
+        if(!empty($sFilter2)) {
+            $this->_sFilter2Value = bx_process_input($sFilter2);
+            $this->_aQueryAppend['filter2'] = $this->_sFilter2Value;
+        }
+        
+        $this->_sFilter3Name = 'filter3';
+        $this->_aFilter3Values = array(
+            BX_FORUM_FILTER_ORDER_RECENT => _t('_bx_forum_grid_filter_order_recent'),
+            BX_FORUM_FILTER_ORDER_NEW => _t('_bx_forum_grid_filter_order_new'),
+            BX_FORUM_FILTER_ORDER_TOP => _t('_bx_forum_grid_filter_order_top'),
+            BX_FORUM_FILTER_ORDER_UPDATED => _t('_bx_forum_grid_filter_order_updated'),
+            BX_FORUM_FILTER_ORDER_POPULAR => _t('_bx_forum_grid_filter_order_popular'),
+            BX_FORUM_FILTER_ORDER_FEATURED => _t('_bx_forum_grid_filter_order_featured'),
+            BX_FORUM_FILTER_ORDER_FAVORITE => _t('_bx_forum_grid_filter_order_favorite'),
+            BX_FORUM_FILTER_ORDER_PARTAKEN => _t('_bx_forum_grid_filter_order_partaken'),
+        );
+        
+        $sFilter3 = bx_get($this->_sFilter3Name);
+        if(!empty($sFilter3)) {
+            $this->_sFilter1Value = bx_process_input($sFilter3);
+            $this->_aQueryAppend['filter3'] = $this->_sFilter1Value;
+        }
+        
+        $this->_sParamsDivider = '#-#';
+
+        $this->_sDefaultSortingOrder = 'DESC';
+        $this->_sDefaultSource = $this->_aOptions['source'];
+    }
+
+    public function setBrowseParams($aParams)
+    {
+        if(isset($aParams['ajax_paginate'])) {
+            if(!$aParams['ajax_paginate']) {
+                list($sPageLink, $aPageParams) = bx_get_base_url_inline();
+
+                $aPageParams[$this->_aOptions['paginate_get_start']] = '{start}';
+                $this->_aOptions['paginate_url'] = BxDolPermalinks::getInstance()->permalink(bx_append_url_params($sPageLink, $aPageParams, true, ['{start}']));
+            }
+
+            unset($aParams['ajax_paginate']);
+        }
+        
+        if ($aParams['type'])
+            $this->_sFilter3Value = $aParams['type'];
+
+        parent::setBrowseParams($aParams);
+
+    	$sField = 'added';
+    	if(!empty($this->_aBrowseParams['type']))
+            switch($this->_aBrowseParams['type']) {
+                case 'new':
+                case 'index':
+                case 'author':
+                case 'favorite':
+                case 'category':
+                    $sField = 'added';
+                    break;
+
+                case 'featured':
+                    $sField = 'featured';
+                    break;
+
+                case 'updated':
+                    $sField = 'changed';
+                    break;
+
+                case 'latest':
+                    $sField = 'lr_timestamp';
+                    break;
+
+                case 'popular':
+                    $sField = 'views';
+                    break;
+            }
+
+        $this->_aOptions['field_order'] = $sField;
+        $this->_aOptions['paginate_per_page'] = !empty($this->_aBrowseParams['per_page']) ? (int)$this->_aBrowseParams['per_page'] : (int)$this->_oModule->_oDb->getParam('bx_forum_per_page_browse');
+    }
+
+    public function getCode ($isDisplayHeader = true)
+    {
+        $sCode = parent::getCode($isDisplayHeader);
+        if(empty($sCode))
+            return '';
+
+    	return $this->_oModule->_oTemplate->parseHtmlByName('units.html', array(
+            'code' => $sCode,
+            'js_code' => $this->_oModule->_oTemplate->getJsCode('main')
+        ));
+    }
+
+    protected function _getActionAdd ($sType, $sKey, $a, $isSmall = false, $isDisabled = false, $aRow = array())
+    {
+        if($this->_oModule->checkAllowedAdd() !== CHECK_ACTION_RESULT_ALLOWED)
+            return '';
+
+        $sUrl = BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink('page.php?i=' . $this->_oModule->_oConfig->CNF['URI_ADD_ENTRY']);
+
+        unset($a['attr']['bx_grid_action_independent']);
+        $a['attr'] = array_merge($a['attr'], array(
+    		"onclick" => "window.open('" . $sUrl . "','_self');"
+    	));
+
+        return parent::_getActionDefault ($sType, $sKey, $a, $isSmall, $isDisabled, $aRow);
+    }
+
+    protected function _getRowHead ()
+    {
+    	return array();
+    }
+
+    protected function _getCellDefault ($mixedValue, $sKey, $aField, $aRow)
+    {
+        $aField['attr_cell']['class'] = 'bx-grid-table-cell-' . $sKey;
+
+        return parent::_getCellDefault($mixedValue, $sKey, $aField, $aRow);
+    }
+
+    protected function _getCellAuthor($mixedValue, $sKey, $aField, $aRow)
+    {
+    	$mixedValue = $this->_oModule->_oTemplate->getEntryAuthor($aRow);
+
+        return self::_getCellDefault($mixedValue, $sKey, $aField, $aRow);
+    }
+    
+    protected function _getCellCategory($mixedValue, $sKey, $aField, $aRow)
+    {
+        $sIcon = $this->_oModule->_oTemplate->parseHtmlByName('default_category.html', []);
+        $o = BxDolCategory::getObjectInstance('bx_forum_cats');
+        
+        $aCategoryData = $this->_oModule->_oDb->getCategories(array('type' => 'by_category', 'category' => $aRow['cat']));
+
+        if(isset($aCategoryData['icon']))
+            $sIcon = $this->_oTemplate->getImage($aCategoryData['icon'], array('class' => 'sys-icon'));
+        
+        $mixedValue = $this->_oModule->_oTemplate->parseHtmlByName('thumb.html', ['icon' => $sIcon, 'title' => $o->getCategoryTitle($aRow['cat'])]);
+        return self::_getCellDefault($mixedValue, $sKey, $aField, $aRow);
+    }
+    
+    protected function _getCellRating($mixedValue, $sKey, $aField, $aRow)
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        $oObject = isset($CNF['OBJECT_SCORES']) ? BxDolScore::getObjectInstance($CNF['OBJECT_SCORES'], $aRow[$CNF['FIELD_ID']], true, $this->_oModule->_oTemplate) : null;
+        $mixedValue = $oObject ? $oObject->getElementInline() : '';
+        
+        return self::_getCellDefault($mixedValue, $sKey, $aField, $aRow);
+    }
+    
+    protected function _getCellParticipants($mixedValue, $sKey, $aField, $aRow)
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+    	$oObject = isset($CNF['OBJECT_COMMENTS']) ? BxDolCmts::getObjectInstance($CNF['OBJECT_COMMENTS'], $aRow[$CNF['FIELD_ID']]) : null;
+      
+        $mixedValue = $oObject ? $oObject->getCounter(['show_counter_empty' => true, 'show_counter' => false, 'show_counter_style' => 'simple', 'dynamic_mode' => true, 'show_icon' => false, 'caption_empty' => '']) : '';
+
+        return self::_getCellDefault($mixedValue, $sKey, $aField, $aRow);
+    }
+
+    protected function _getCellText($mixedValue, $sKey, $aField, $aRow)
+    {
+        $mixedValue = $this->_oModule->_oTemplate->getEntryPreview($aRow, ['show_meta_counters' => false, 'show_meta_reply' => false]);
+
+        return self::_getCellDefault($mixedValue, $sKey, $aField, $aRow);
+    }
+
+    protected function _addJsCss()
+    {
+        parent::_addJsCss();
+
+        $this->_oModule->_oTemplate->addJs(array('main.js'));
+        $this->_oModule->_oTemplate->addCss(array('main.css', 'main-media-phone.css', 'main-media-tablet.css', 'main-media-desktop.css'));
+    }
+
+    protected function _getDataSql($sFilter, $sOrderField, $sOrderDir, $iStart, $iPerPage)
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+        
+        if(strpos($sFilter, $this->_sParamsDivider) !== false)
+            list($this->_sFilter1Value, $this->_sFilter2Value, $this->_sFilter3Value, $sFilter) = explode($this->_sParamsDivider, $sFilter);
+        
+        // featured
+        if ($this->_sFilter3Value == BX_FORUM_FILTER_ORDER_FEATURED){
+            $this->_aBrowseParams['where'] = ['fld' => 'featured', 'val' => 0, 'opr' => '<>'];
+        }
+        
+        // partaken
+        if ($this->_sFilter3Value == BX_FORUM_FILTER_ORDER_PARTAKEN){
+            $this->_aBrowseParams['select'] = array(
+                'tbla' => 'tco', 
+                'fld' => 'cmt_author_id',
+            );
+
+            $this->_aBrowseParams['join'] = array(
+                'tp' => 'INNER',
+                'tbl1' => 'bx_forum_cmts',
+                'tbl1a' => 'tco',
+                'fld1' => 'cmt_object_id',
+                'tbl2' => 'bx_forum_discussions',
+                'fld2' => 'id'
+            );
+
+            $this->_aBrowseParams['where'] = array(
+                'tbl' => 'tco', 
+                'fld' => 'cmt_author_id', 
+                'val' => bx_get_logged_profile_id(), 
+                'opr' => '='
+            );
+
+            $this->_aBrowseParams['group_by'] = array(
+                'tbl' => 'bx_forum_discussions', 
+                'fld' => 'id',
+            );
+        }
+        
+        //FAVORITE
+        if ($this->_sFilter3Value == BX_FORUM_FILTER_ORDER_FAVORITE){
+            $oProfile = BxDolProfile:: getInstance(bx_process_input(bx_get('profile_id'), BX_DATA_INT));
+            if(!$oProfile)
+                $oProfile = BxDolProfile::getInstance();
+            if(!$oProfile)
+                return '';
+            
+            $iProfileId = $oProfile->id();
+            $iProfileAuthor = $oProfile->id();
+            $oFavorite = $this->_oModule->getObjectFavorite();
+            if(!$oFavorite->isPublic() && $iProfileAuthor != bx_get_logged_profile_id())
+                return '';
+            
+            $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']
+                    );
+            
+            $this->_aBrowseParams['author'] = $iProfileId; 
+            $this->_aBrowseParams['join'] = $aJoinGroup;
+            $this->_aBrowseParams['where'] = $aWhereGroup; 
+        }
+        
+        $CNF = $this->_oModule->_oConfig->CNF;
+        
+    	$sSelectClause = $sJoinClause = $sWhereClause = $sGroupByClause = '';
+
+    	//--- Check status
+    	$sWhereClause .= " AND `{$CNF['TABLE_ENTRIES']}`.`" . $this->_oModule->_oConfig->CNF['FIELD_STATUS'] . "`='active'";
+    	$sWhereClause .= " AND `{$CNF['TABLE_ENTRIES']}`.`" . $this->_oModule->_oConfig->CNF['FIELD_STATUS_ADMIN'] . "`='active'";
+
+    	//--- Check privacy
+    	$iAuthorId = 0;
+    	if(!empty($this->_aBrowseParams['author'])) {
+            $oProfileAuthor = BxDolProfile::getInstance((int)$this->_aBrowseParams['author']);
+            if($oProfileAuthor)
+                $iAuthorId = $oProfileAuthor->id();
+    	}
+
+        $sPrivacy = $this->_oModule->_oConfig->CNF['OBJECT_PRIVACY_VIEW'];
+        $oPrivacy = BxDolPrivacy::getObjectInstance($sPrivacy);
+        $aCondition = $oPrivacy ? $oPrivacy->getContentPublicAsSQLPart($iAuthorId) : array();
+        if(isset($aCondition['join']))
+            $sJoinClause .= $aCondition['join'];
+        if(isset($aCondition['where']))
+            $sWhereClause .= $aCondition['where'];
+
+        //--- Check browse params
+        if(!empty($this->_aBrowseParams['select']) && is_array($this->_aBrowseParams['select'])) {
+            $sSelectClauseBrowse = $this->_getSqlSelectFromGroup($this->_aBrowseParams['select']);
+            if(!empty($sSelectClauseBrowse))
+                $sSelectClause .= ", " . $sSelectClauseBrowse;
+        }
+
+        if(!empty($this->_aBrowseParams['join']) && is_array($this->_aBrowseParams['join'])) {
+            $sJoinClauseBrowse = $this->_getSqlJoinFromGroup($this->_aBrowseParams['join']);
+            if(!empty($sJoinClauseBrowse))
+                $sJoinClause .= " " . $sJoinClauseBrowse;
+        }
+
+        if(!empty($this->_aBrowseParams['where']) && is_array($this->_aBrowseParams['where'])) {
+            $sWhereClauseBrowse = $this->_getSqlWhereFromGroup($this->_aBrowseParams['where']);
+            if(!empty($sWhereClauseBrowse))
+                $sWhereClause .= " AND " . $sWhereClauseBrowse;
+        }
+
+        if(!empty($this->_aBrowseParams['group_by']) && is_array($this->_aBrowseParams['group_by'])) {
+            $sGroupByClauseBrowse = $this->_getSqlGroupByFromGroup($this->_aBrowseParams['group_by']);
+            if(!empty($sGroupByClauseBrowse))
+                $sGroupByClause .= " GROUP BY " . $sGroupByClauseBrowse;
+        }
+        
+        $sFilterSql = "";
+
+        // filter by resolved status
+        if(isset($this->_sFilter1Value) && $this->_sFilter1Value != ''){
+            $sWhereClause .= " AND `" . $CNF['TABLE_ENTRIES'] . "`.`" . $CNF['FIELD_RESOLVABLE'] . "` = 1 AND `" . $CNF['TABLE_ENTRIES'] . "`.`" . $CNF['FIELD_RESOLVE'] . "` = " . $this->_sFilter1Value;
+        }
+        
+        // filter out posts of suspended members
+        $sJoinClause .= " INNER JOIN `sys_profiles` AS `p` ON (`p`.`id` = `{$CNF['TABLE_ENTRIES']}`.`{$CNF['FIELD_AUTHOR']}` AND `p`.`status` = 'active') ";
+
+        // filter out posts by content filter
+        $oCf = BxDolContentFilter::getInstance();
+        if($oCf->isEnabled())
+            $sWhereClause .= $oCf->getSQLParts ($CNF['TABLE_ENTRIES'], $CNF['FIELD_CF']);
+
+        // filter by badges
+        if(isset($this->_sFilter2Value) && $this->_sFilter2Value != ''){
+            
+            $aObjects = BxDolBadges::getInstance()->getData(['type' => 'by_module&badge', 'badge_id' => $this->_sFilter2Value, 'module' => $this->_oModule->_aModule['name']]);
+            $sWhereClause .= " AND `" . $CNF['TABLE_ENTRIES'] . "`.`" . $CNF['FIELD_ID'] . "` IN (" . implode(',', $aObjects ) . ")";
+        }
+        $this->_aOptions['source'] = sprintf($this->_sDefaultSource, $sSelectClause, $sJoinClause, $sWhereClause, $sGroupByClause);
+        return parent::_getDataSql($sFilter, $sOrderField, $sOrderDir, $iStart, $iPerPage);
+    }
+
+    protected function _getDataSqlOrderClause($sOrderByFilter, $sOrderField, $sOrderDir, $bFieldsOnly = false)
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        if(isset($this->_sFilter3Value) && $this->_sFilter3Value != ''){
+            $sOrderField = $this->_aBrowseParams['type'] = $this->_sFilter3Value;
+            if (!empty($this->_aBrowseParams['type']) && $this->_aBrowseParams['type'] != 'partaken'){
+                $this->_aBrowseParams['type'] = $this->_aBrowseParams['type'] = $this->_sFilter3Value;
+            }
+        }
+        
+    	$sOrder = parent::_getDataSqlOrderClause($sOrderByFilter, $sOrderField, $sOrderDir, true);
+                
+        if(!empty($this->_aBrowseParams['type']))
+            switch($this->_aBrowseParams['type']) {
+                case 'top':
+                    $aPartsUp = $aPartsDown = array(0);
+                    if(($oVote = BxDolVote::getObjectInstance($CNF['OBJECT_VOTES'], 0, false)) !== false && $oVote->isEnabled()) {
+                        $aVote = $oVote->getSystemInfo();
+                        if(!empty($aVote['trigger_table']) && !empty($aVote['trigger_field_count']))
+                            $aPartsUp[] = '`' . $aVote['trigger_table'] . '`.`' . $aVote['trigger_field_count'] . '`';
+                    }
+
+                    if(($oReaction = BxDolVote::getObjectInstance($CNF['OBJECT_REACTIONS'], 0, false)) !== false && $oReaction->isEnabled()) {
+                        $aReaction = $oReaction->getSystemInfo();
+                        if(!empty($aReaction['trigger_table']) && !empty($aReaction['trigger_field_count']))
+                            $aPartsUp[] = '`' . $aReaction['trigger_table'] . '`.`' . $aReaction['trigger_field_count'] . '`';
+                    }
+
+                    if(($oScore = BxDolScore::getObjectInstance($CNF['OBJECT_SCORES'], 0, false)) !== false && $oScore->isEnabled()) {
+                        $aScore = $oScore->getSystemInfo();
+                        if(!empty($aScore['trigger_table']) && !empty($aScore['trigger_field_cup']) && !empty($aScore['trigger_field_cdown'])) {
+                            $aPartsUp[] = '`' . $aScore['trigger_table'] . '`.`' . $aScore['trigger_field_cup'] . '`';
+                            $aPartsDown[] = '`' . $aScore['trigger_table'] . '`.`' . $aScore['trigger_field_cdown'] . '`';
+                        }
+                    }
+
+                    $sOrder = pow(10, 8) . ' * ((' . implode(' + ', $aPartsUp) . ') - (' . implode(' + ', $aPartsDown) . ')) / (UNIX_TIMESTAMP() - `' . $this->_aOptions['table'] . '`.`' . $CNF['FIELD_ADDED'] . '`) ' . $this->_sDefaultSortingOrder;
+                    break;
+
+                case 'partaken':
+                    $sOrder = 'MAX(`tco`.`cmt_time`) ' . $this->_sDefaultSortingOrder;
+                    break;
+            }           
+
+    	return " ORDER BY `" . $CNF['FIELD_STICK'] . "` DESC, " . $sOrder;
+    }
+
+    protected function _getSqlSelectFromGroup($aGrp)
+    {
+        if(!isset($aGrp['grp']) || (bool)$aGrp['grp'] !== true)
+            return $this->_getSqlSelectFromCondition($aGrp);
+
+        $sResult = "";
+        if(empty($aGrp['cnds']) || !is_array($aGrp['cnds']))
+            return $sResult;
+
+        $sOprGrp = ", ";
+        foreach($aGrp['cnds'] as $aCnd) {
+            $sResultCnd = $this->_getSqlSelectFromCondition($aCnd);
+            if(!empty($sResultCnd))
+                $sResult .= $sOprGrp . $sResultCnd;
+        }
+
+        return trim($sResult, $sOprGrp);
+    }
+
+    protected function _getSqlSelectFromCondition($aCnd)
+    {
+    	$sResult = "";
+    	if(!isset($aCnd['fld']))
+            return $sResult;
+
+        $sResult = "`" . $aCnd['fld'] . "`";
+        if(!empty($aCnd['tbla']))
+            $sResult = "`" . $aCnd['tbla'] . "`." . $sResult;
+        else if(!empty($aCnd['tbl']))
+            $sResult = "`" . $aCnd['tbl'] . "`." . $sResult;
+
+        return $sResult;
+    }
+
+    protected function _getSqlJoinFromGroup($aGrp)
+    {
+        if(!isset($aGrp['grp']) || (bool)$aGrp['grp'] !== true)
+            return $this->_getSqlJoinFromCondition($aGrp);
+
+        $sResult = "";
+        if(empty($aGrp['cnds']) || !is_array($aGrp['cnds']))
+            return $sResult;
+
+        $sOprGrp = " ";
+        foreach($aGrp['cnds'] as $aCnd) {
+            $sResultCnd = $this->_getSqlJoinFromCondition($aCnd);
+            if(!empty($sResultCnd))
+                $sResult .= $sOprGrp . $sResultCnd;
+        }
+
+        return trim($sResult, $sOprGrp);
+    }
+
+    protected function _getSqlJoinFromCondition($aCnd)
+    {
+    	$sResult = "";
+    	if(!isset($aCnd['tp'], $aCnd['tbl1'], $aCnd['fld1'], $aCnd['fld2']))
+            return $sResult;
+
+        $sTbl1A = $aCnd['tbl1'];
+        if(!empty($aCnd['tbl1a']))
+            $sTbl1A = $aCnd['tbl1a'];
+
+        $sField1 = "`" . $sTbl1A . "`.`" . $aCnd['fld1'] . "`";
+
+        $sField2 = "`" . $aCnd['fld2'] . "`";
+        if(!empty($aCnd['tbl2a']))
+            $sField2 = "`" . $aCnd['tbl2a'] . "`." . $sField2;
+        else if(!empty($aCnd['tbl2']))
+            $sField2 = "`" . $aCnd['tbl2'] . "`." . $sField2;
+
+        return $aCnd['tp'] . " JOIN `" . $aCnd['tbl1'] . "` AS `" . $sTbl1A . "` ON (" . $sField1 . " = " . $sField2 . ")";
+    }
+
+    protected function _getSqlWhereFromGroup($aGrp)
+    {
+        if(!isset($aGrp['grp']) || (bool)$aGrp['grp'] !== true)
+            return $this->_getSqlWhereFromCondition($aGrp);
+
+        $sResult = "";
+        if(!isset($aGrp['opr'], $aGrp['cnds']) || empty($aGrp['cnds']) || !is_array($aGrp['cnds']))
+            return $sResult;
+
+        $sOprGrp = " " . $aGrp['opr'] . " ";
+        foreach($aGrp['cnds'] as $aCnd) {
+            $sMethod = '_getSqlWhereFrom' . (isset($aGrp['grp']) && (bool)$aGrp['grp'] === true ? 'Group' : 'Condition');
+            $sResultCnd = $this->$sMethod($aCnd);
+            if(!empty($sResultCnd))
+                $sResult .= $sOprGrp . $sResultCnd;
+        }
+
+        $sResult = trim($sResult, $sOprGrp);
+        if(!empty($sResult))
+            $sResult = "(" . $sResult . ")";
+
+    	return $sResult;
+    }
+
+    protected function _getSqlWhereFromCondition($aCnd)
+    {
+        $sResult = "";
+        if(!isset($aCnd['fld'], $aCnd['val'], $aCnd['opr']))
+            return $sResult;
+
+        $sMethod = '_getSqlWhereFromCondition' . bx_gen_method_name($aCnd['fld']);
+        if(method_exists($this, $sMethod)) {
+            $mixedResult = $this->$sMethod($aCnd);
+            if(is_array($mixedResult) && isset($mixedResult['fld'], $mixedResult['val'], $mixedResult['opr']))
+                $aCnd = $mixedResult;
+            else
+                return $mixedResult;
+        }
+        
+        $sField = "`" . $aCnd['fld'] . "`";
+        if(!empty($aCnd['tbl']))
+            $sField = "`" . $aCnd['tbl'] . "`." . $sField;
+
+        switch($aCnd['opr']) {
+            case 'IN':
+                if(empty($aCnd['val']) || !is_array($aCnd['val']))
+                    break;
+
+                $sResult .= $sField . " IN (" . $this->_oModule->_oDb->implode_escape($aCnd['val']) . ")";
+                break;
+
+            case 'LIKE':
+                $sResult .= $sField . " LIKE " . $this->_oModule->_oDb->escape('%' . $aCnd['val'] . '%');
+                break;
+
+            default:
+                $sResult .= $sField . " " . $aCnd['opr'] . " " . $this->_oModule->_oDb->escape($aCnd['val']);
+        }
+
+        return $sResult;
+    }
+
+    protected function _getSqlGroupByFromGroup($aGrp)
+    {
+        if(!isset($aGrp['grp']) || (bool)$aGrp['grp'] !== true)
+            return $this->_getSqlGroupByFromCondition($aGrp);
+
+        $sResult = "";
+        if(empty($aGrp['cnds']) || !is_array($aGrp['cnds']))
+            return $sResult;
+
+        $sOprGrp = ", ";
+        foreach($aGrp['cnds'] as $aCnd) {
+            $sResultCnd = $this->_getSqlGroupByFromCondition($aCnd);
+            if(!empty($sResultCnd))
+                $sResult .= $sOprGrp . $sResultCnd;
+        }
+
+        return trim($sResult, $sOprGrp);
+    }
+
+    protected function _getSqlGroupByFromCondition($aCnd)
+    {
+    	$sResult = "";
+    	if(!isset($aCnd['fld']))
+            return $sResult;
+
+        $sResult = "`" . $aCnd['fld'] . "`";
+        if(!empty($aCnd['tbla']))
+            $sResult = "`" . $aCnd['tbla'] . "`." . $sResult;
+        else if(!empty($aCnd['tbl']))
+            $sResult = "`" . $aCnd['tbl'] . "`." . $sResult;
+
+        return $sResult;
+    }
+
+    protected function _getSqlWhereFromConditionAuthorComment($aCnd)
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        $aEntriesIds = $this->_oModule->_oDb->getComments(array('type' => 'entries_author_search', 'author' => $aCnd['val']));
+        if(!empty($aEntriesIds) && is_array($aEntriesIds))
+            return array('tbl' => $CNF['TABLE_ENTRIES'], 'fld' => 'id', 'val' => $aEntriesIds, 'opr' => 'IN');
+
+        return '';
+    }
+
+    protected function _getSqlWhereFromConditionKeywordComment($aCnd)
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        $aEntriesIds = $this->_oModule->_oDb->getComments(array('type' => 'entries_keyword_search', 'keyword' => $aCnd['val']));
+        if(!empty($aEntriesIds) && is_array($aEntriesIds))
+            return array('tbl' => $CNF['TABLE_ENTRIES'], 'fld' => 'id', 'val' => $aEntriesIds, 'opr' => 'IN');
+
+        return '';
+    }
+    
+    protected function _getFilterControls ()
+    {
+        parent::_getFilterControls();
+        return  $this->_getFilterSelectOne($this->_sFilter3Name, $this->_sFilter3Value, $this->_aFilter3Values) . $this->_getFilterSelectOne($this->_sFilter1Name, $this->_sFilter1Value, $this->_aFilter1Values) . (count($this->_aFilter2Values) > 0 ? $this->_getFilterSelectOne($this->_sFilter2Name, $this->_sFilter2Value, $this->_aFilter2Values) : '') . $this->_getSearchInput();
+    }
+    
+    protected function _getSearchInput()
+    {
+        $sJsObject = $this->_oModule->_oConfig->getJsObject('main');
+        $aInputSearch = array(
+            'type' => 'text',
+            'name' => 'search',
+            'attrs' => array(
+                'id' => 'bx-grid-search-' . $this->_sObject,
+                'onKeyup' => 'javascript:$(this).off(\'keyup focusout\'); ' . $sJsObject . '.onChangeFilter(this)',
+                'onBlur' => 'javascript:' . $sJsObject . '.onChangeFilter(this)',
+            )
+        );
+
+        $oForm = new BxTemplFormView(array());
+        return $oForm->genRow($aInputSearch);
+    }
+    
+    protected function _getFilterSelectOne($sFilterName, $sFilterValue, $aFilterValues)
+    {
+        if(empty($sFilterName) || empty($aFilterValues))
+            return '';
+
+        $CNF = &$this->_oModule->_oConfig->CNF;
+        $sJsObject = $this->_oModule->_oConfig->getJsObject('main');
+
+        foreach($aFilterValues as $sKey => $sValue)
+            $aFilterValues[$sKey] = _t($sValue);
+
+        $aInputModules = array(
+            'type' => 'select',
+            'name' => $sFilterName,
+            'attrs' => array(
+                'id' => 'bx-grid-' . $sFilterName . '-' . $this->_sObject,
+                'onChange' => 'javascript:' . $sJsObject . '.onChangeFilter(this)'
+            ),
+            'value' => $sFilterValue,
+            'values' => $aFilterValues
+        );
+
+        $oForm = new BxTemplFormView(array());
+        return $oForm->genRow($aInputModules);
+    }
+}
+
+/** @} */

+ 230 - 0
modules/boonex/forum/updates/13.0.2_13.0.3/source/classes/BxForumMenuCategories.php

@@ -0,0 +1,230 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    UnaBaseView UNA Base Representation Classes
+ * @{
+ */
+
+/**
+ * Menu representation.
+ * @see BxDolMenu
+ */
+class BxForumMenuCategories extends BxTemplMenu
+{
+    protected $_iMenuItemsMin;
+    protected $_oModule;
+
+    public function __construct ($aObject, $oTemplate)
+    {
+        parent::__construct ($aObject, $oTemplate);
+
+        $this->_sModule = 'bx_forum';
+        $this->_oModule = BxDolModule::getInstance($this->_sModule);
+        $this->_bDisplayAddons = true;
+    }
+
+    public function getMenuItems ()
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+        
+        $aItems = [];
+        
+        $aCategoriest = bx_srv('system', 'categories_list', ['bx_forum_cats', ['show_empty' => true]], 'TemplServiceCategory');
+        
+        if (!($o = BxDolCategory::getObjectInstance('bx_forum_cats')))
+            return $aItems;
+
+		$aCategories = $o->getCategoriesList(false, true);
+        
+		if(!isset($aCategories['bx_repeat:cats']))
+			return $aItems;
+        
+        $iCount = 0;
+        foreach ($aCategories['bx_repeat:cats'] as $sKey => $aCategory) {
+            $iCount +=  $aCategories['bx_repeat:cats'][$sKey]['num'];
+        }
+        
+        $aItems[] =  [
+            'class_add' => 'bx-psmi-show-' . $aCategories['bx_repeat:cats'][$sKey]['value'] . (bx_get('category') == '' ? ' bx-menu-item-active' : ''),
+            'name' => 'show-0',
+            'title' => _t('_bx_forum_txt_all_categories'),
+            'link' => BxDolPermalinks::getInstance()->permalink($CNF['URL_HOME']),
+            'onclick' => 'javascript:',
+            'attrs' => '',
+            'bx_if:image' => array (
+                'condition' => false,
+                'content' => [],
+            ),
+            'bx_if:image_inline' => array (
+                'condition' => false,
+                'content' => [],
+            ),
+            'bx_if:icon' => array (
+                'condition' => true,
+                'content' => ['icon' => 'swatchbook'],
+            ),
+            'bx_if:icon-a' => array (
+                'condition' => false,
+                'content' => [],
+            ),
+            'bx_if:icon-html' => array (
+                'condition' => false,
+                'content' => [],
+            ),
+            'bx_if:addon' => [
+                'condition' => true,
+                'content' => ['addon' => $iCount]
+            ]
+        ];
+        
+        
+        foreach ($aCategories['bx_repeat:cats'] as $sKey => $aCategory) {    
+            $aCategoryData = $this->_oModule->_oDb->getCategories(array('type' => 'by_category', 'category' => $aCategory['value']));
+            if(
+                isset($aCategoryData['visible_for_levels']) && $aCategoryData['visible_for_levels'] != '' && 
+                BxDolAcl::getInstance()->isMemberLevelInSet($aCategoryData['visible_for_levels'])){
+                
+                $aCategories['bx_repeat:cats'][$sKey]['icon'] = $this->_oTemplate->getImage(isset($aCategoryData['icon']) ? $aCategoryData['icon'] : 'folder', array('class' => 'sys-icon sys-colored'));
+                
+                if (!isset($aCategoryData['icon']) || $aCategoryData['icon'] == '')
+                    $aCategoryData['icon'] = 'folder';
+                
+                list($sIcon, $sIconUrl, $sIconA, $sIconHtml) = BxTemplFunctions::getInstance()->getIcon($aCategoryData['icon']);
+                
+                $aItems[] =  [
+                    // TODO
+                    'class_add' => 'bx-psmi-show-' . $aCategories['bx_repeat:cats'][$sKey]['value'] . (bx_get('category') == $aCategories['bx_repeat:cats'][$sKey]['value'] ? ' bx-menu-item-active' : ''),
+                    'name' => 'show-' . $aCategories['bx_repeat:cats'][$sKey]['value'],
+                    'title' => $aCategories['bx_repeat:cats'][$sKey]['name'],
+                    'link' => $aCategories['bx_repeat:cats'][$sKey]['url'],
+                    'onclick' => 'javascript:',
+                    'attrs' => '',
+                    'bx_if:image' => array (
+                        'condition' => (bool)$sIconUrl,
+                        'content' => array('icon_url' => $sIconUrl),
+                    ),
+                    'bx_if:image_inline' => array (
+                        'condition' => false,
+                        'content' => array('image' => ''),
+                    ),
+                    'bx_if:icon' => array (
+                        'condition' => (bool)$sIcon,
+                        'content' => array('icon' => $sIcon),
+                    ),
+                    'bx_if:icon-a' => array (
+                        'condition' => (bool)$sIconA,
+                        'content' => array('icon-a' => $sIconA),
+                    ),
+                    'bx_if:icon-html' => array (
+                        'condition' => (bool)$sIconHtml,
+                        'content' => array('icon' => $sIconHtml),
+                    ),
+                    'bx_if:addon' => [
+                        'condition' => true,
+                        'content' => ['addon' => $aCategories['bx_repeat:cats'][$sKey]['num']]
+                    ]
+                ];
+            }
+        }
+        
+        if(empty($aItems) || !is_array($aItems))
+            return $aItems;
+
+        $iMaxNum = count($aItems);
+        $iMenuItemsMin = (int)getParam('bx_forum_visible_categories');
+        if($iMaxNum <= $iMenuItemsMin)
+            return $aItems;
+
+        $mixedCollpsed = $this->getUserChoiceCollapsed();
+        $bCollpsed = $mixedCollpsed === false || $mixedCollpsed == 1;
+
+        for($i = $iMenuItemsMin; $i < $iMaxNum; $i++)
+            $aItems[$i]['class_add'] .= ' bx-mi-aux' . ($bCollpsed ? ' bx-mi-hidden' : '');
+
+        $aShowMoreLinks = [
+            'more' => ['title' => '_sys_show_more', 'icon' => 'chevron-down', 'class' => $bCollpsed ? '' : 'bx-mi-hidden'],
+            'less' => ['title' => '_sys_show_less', 'icon' => 'chevron-up', 'class' => !$bCollpsed ? '' : 'bx-mi-hidden']
+        ];
+
+        foreach($aShowMoreLinks as $sLink => $aLink)
+            $aItems[] = array(
+                'class_add' => 'bx-psmi-show-' . $sLink . ' ' . $aLink['class'],
+                'name' => 'show-' . $sLink,
+                'title' => _t($aLink['title']),
+                'link' => 'javascript:void(0)',
+                'onclick' => 'bx_menu_show_more_less(this, \'' . $this->_sObject . '\', \'.bx-menu-object-' . $this->_sObject . '\')',
+                'attrs' => '',
+                'bx_if:image' => [
+                    'condition' => false,
+                    'content' => ['icon_url' => ''],
+                ],
+                'bx_if:image_inline' => [
+                    'condition' => false,
+                    'content' => ['image' => ''],
+                ],
+                'bx_if:icon' => [
+                    'condition' => true,
+                    'content' => ['icon' => $aLink['icon']],
+                ],
+                'bx_if:icon-html' => [
+                    'condition' => false,
+                    'content' => ['icon-a' => ''],
+                ],
+                'bx_if:icon-a' => [
+                    'condition' => false,
+                    'content' => ['icon-a' => ''],
+                ],
+                'bx_if:addon' => [
+                    'condition' => false,
+                    'content' => []
+                ]
+            );
+
+        return $aItems;
+    }
+
+    protected function getMenuItemsRaw ()
+    {
+        $aItems = $this->_oQuery->getMenuItemsBy(array(
+            'type' => 'set_name', 
+            'set_name' => $this->_aObject['set_name']
+        ));
+
+        $aDuplicates = $this->_oQuery->getMenuItemsBy(array(
+            'type' => 'set_name_duplicates', 
+            'set_name' => $this->_aObject['set_name']
+        ));
+
+        $oProfile = BxDolProfile::getInstance();
+        if(!$oProfile)
+            return array();
+
+        $sModule = $oProfile->getModule();
+
+        $aResult = array();
+        foreach($aItems as $aItem) {
+            if(in_array($aItem['name'], $aDuplicates) && $aItem['module'] != $sModule)
+                continue;
+            
+            $aResult[$aItem['name']] = $aItem;
+        }
+
+        return $aResult;
+    }
+    
+    protected function _getMenuItem($a)
+    {
+        $mixedResult = parent::_getMenuItem($a);
+
+        if($mixedResult !== false && !empty($mixedResult['link']) && strpos($mixedResult['link'], 'javascript:') === false)
+            $mixedResult['link'] = bx_append_url_params($mixedResult['link'], [
+                'owner' => 1
+            ]);
+
+        return $mixedResult;
+    }
+}
+
+/** @} */

+ 159 - 0
modules/boonex/forum/updates/13.0.2_13.0.3/source/classes/BxForumMenuSnippetMeta.php

@@ -0,0 +1,159 @@
+<?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 BxForumMenuSnippetMeta extends BxBaseModTextMenuSnippetMeta
+{
+    public function __construct($aObject, $oTemplate = false)
+    {
+        $this->_sModule = 'bx_forum';
+
+        parent::__construct($aObject, $oTemplate);
+    }
+
+    protected function _getMenuItemViews($aItem)
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        if(empty($CNF['FIELD_VIEWS']) || empty($CNF['FIELD_VIEWS']) || (empty($this->_aContentInfo[$CNF['FIELD_VIEWS']]) && !$this->_bShowZeros))
+            return false;
+
+        $oViews = BxDolView::getObjectInstance($CNF['OBJECT_VIEWS'], $this->_aContentInfo[$CNF['FIELD_ID']]);
+        if(!$oViews || !$oViews->isEnabled())
+            return false;
+
+        return $this->getUnitMetaItemCustom($oViews->getElementInline(array('show_counter' => true)));
+    }
+
+    protected function _getMenuItemVotes($aItem)
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        if(empty($CNF['OBJECT_VOTES']) || empty($CNF['FIELD_VOTES']) || (empty($this->_aContentInfo[$CNF['FIELD_VOTES']]) && !$this->_bShowZeros))
+            return false;
+
+        $oVotes = BxDolVote::getObjectInstance($CNF['OBJECT_VOTES'], $this->_aContentInfo[$CNF['FIELD_ID']]);
+        if(!$oVotes || !$oVotes->isEnabled())
+            return false;
+
+        return $this->getUnitMetaItemCustom($oVotes->getElementInline(array('show_counter' => true)));
+    }
+    
+    protected function _getMenuItemScore($aItem)
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+        
+        $oVotes = BxDolScore::getObjectInstance($CNF['OBJECT_SCORES'], $this->_aContentInfo[$CNF['FIELD_ID']], true, $this->_oModule->_oTemplate);
+        if(!$oVotes || !$oVotes->isEnabled())
+            return 'zxczx';
+
+        return $this->getUnitMetaItemCustom($oVotes->getElementInline());
+    }
+
+    protected function _getMenuItemReplyAuthor($aItem)
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+        if(empty($this->_aContentInfo[$CNF['FIELD_LR_COMMENT_ID']]))
+            return '';
+
+        $oProfile = BxDolProfile::getInstanceMagic($this->_aContentInfo[$CNF['FIELD_LR_AUTHOR']]);
+        return $this->getUnitMetaItemCustom($oProfile->getUnit(0, array('template' => array(
+            'name' => 'unit',
+            'size' => 'icon'
+        ))));
+    }
+
+    protected function _getMenuItemReplyDate($aItem)
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+        if(empty($this->_aContentInfo[$CNF['FIELD_LR_COMMENT_ID']]))
+            return '';
+
+        return $this->getUnitMetaItemText(bx_time_js($this->_aContentInfo[$CNF['FIELD_LR_ADDED']], BX_FORMAT_DATE));
+    }
+
+    protected function _getMenuItemReplyText($aItem)
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+        if(empty($this->_aContentInfo[$CNF['FIELD_LR_COMMENT_ID']]))
+            return '';
+
+        $iComment = $this->_aContentInfo[$CNF['FIELD_LR_COMMENT_ID']];
+        $aComment = BxDolCmts::getObjectInstance($CNF['OBJECT_COMMENTS'], $this->_aContentInfo[$CNF['FIELD_ID']])->getCommentRow($iComment);
+        if(empty($aComment) || !is_array($aComment))
+            return '';
+
+        return $this->getUnitMetaItemText(strmaxtextlen($aComment['cmt_text'], 100), array('class' => $this->_sModule . '-gpm-reply-text'));
+    }
+    
+    protected function _getMenuItemAuthor($aItem)
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+        $oProfile = BxDolProfile::getInstanceMagic($this->_aContentInfo[$CNF['FIELD_AUTHOR']]);
+        return $this->getUnitMetaItemExtended($oProfile->getDisplayName(), $oProfile->getThumb(), $oProfile->getUrl());
+    }
+    
+    protected function _getMenuItemCategory($aItem)
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        if(empty($CNF['OBJECT_CATEGORY']) || empty($CNF['FIELD_CATEGORY']) || empty($this->_aContentInfo[$CNF['FIELD_CATEGORY']]))
+            return false;
+
+        $oCategory = BxDolCategory::getObjectInstance($CNF['OBJECT_CATEGORY']);
+        if(!$oCategory)
+            return false;
+
+        $sTitle = $oCategory->getCategoryTitle($this->_aContentInfo[$CNF['FIELD_CATEGORY']]);
+        $aCategoryData = $this->_oModule->_oDb->getCategories(array('type' => 'by_category', 'category' => $this->_aContentInfo[$CNF['FIELD_CATEGORY']]));
+        
+        return $this->getUnitMetaItemExtended($sTitle, (isset($aCategoryData['icon']) ? $aCategoryData['icon'] : 'folder'), $oCategory->getCategoryUrl($this->_aContentInfo[$CNF['FIELD_CATEGORY']]));
+    }
+    
+    protected function _getMenuItemComments($aItem)
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        if(empty($CNF['OBJECT_COMMENTS']) || empty($CNF['FIELD_COMMENTS']) || (empty($this->_aContentInfo[$CNF['FIELD_COMMENTS']]) && !$this->_bShowZeros))
+            return false;
+
+        $oComments = BxDolCmts::getObjectInstance($CNF['OBJECT_COMMENTS'], $this->_aContentInfo[$CNF['FIELD_ID']]);
+        if(!$oComments || !$oComments->isEnabled())
+            return false;
+
+        return $this->getUnitMetaItemExtended(_t('_bx_forum_page_block_title_entry_comments', $oComments->getCommentsCountAll()), $aItem['icon'], '');
+    }
+    
+    protected function _getMenuItemBadges($aItem)
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+        return $this->getUnitMetaItemExtended($this->_oModule->serviceGetBadges($this->_aContentInfo[$CNF['FIELD_ID']], false, true), '', '', false, true); 
+    }
+    
+    protected function _getMenuItemStatus($aItem)
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        $sStatus = '';
+        if ($this->_aContentInfo['resolvable']){
+            if ($this->_aContentInfo['resolved']){
+                $sStatus .= _t('_bx_forum_grid_filter_resolved_resolved');
+            }
+            else{
+                $sStatus .= _t('_bx_forum_grid_filter_resolved_unresolved');
+            }  
+            
+            return $this->getUnitMetaItemExtended($this->_oModule->_oTemplate->parseHtmlByName('status.html', ['status' => $sStatus, 'status_class' => $this->_aContentInfo['resolved']]), '' ,'', true, true); 
+        }
+        return '';
+    }
+}
+
+/** @} */

+ 32 - 0
modules/boonex/forum/updates/13.0.2_13.0.3/source/classes/BxForumMetatags.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    Forum Forum
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxForumMetatags extends BxTemplMetatags
+{
+	protected $MODULE;
+	protected $_oModule;
+
+	public function __construct($aObject, $oTemplate = null)
+    {
+    	$this->MODULE = 'bx_forum';
+    	$this->_oModule = BxDolModule::getInstance($this->MODULE);
+
+        parent::__construct($aObject, $oTemplate);
+
+        $CNF = $this->_oModule->_oConfig->CNF;
+
+        $this->_sBrowseUrl = bx_append_url_params(BxDolPermalinks::getInstance()->permalink('page.php?i=' . $CNF['URI_KEYWORD_ENTRIES']), array(
+        	'keyword' => '{keyword}'
+        ), true, ['{keyword}']);
+    }
+}
+
+/** @} */

+ 1034 - 0
modules/boonex/forum/updates/13.0.2_13.0.3/source/classes/BxForumModule.php

@@ -0,0 +1,1034 @@
+<?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 = true)
+    {
+        $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(
+            '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_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 = true)
+    {
+        $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 = true)
+    {
+        $sType = 'partaken';
+
+        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_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']);
+        }
+        
+        if(isset($aParams['unit_view']) && $aParams['unit_view'] != 'table')
+            return $this->_serviceBrowse('author', array_merge(array('author' => $iProfileId), $aParams), BX_DB_PADDING_DEF, $bEmptyMessage, $bAjaxPaginate);
+
+        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;
+
+        $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']);
+        }
+
+        return $this->_serviceBrowseTable(array(
+            'type' => 'favorite', 
+            '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 = true)
+    {
+        $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_author entity_author
+     * 
+     * @code bx_srv('bx_forum', 'entity_author', [...]); @endcode
+     * 
+     * Get page block with author.
+     * 
+     * @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::serviceEntityAuthor
+     */
+    /** 
+     * @ref bx_forum-entity_author "entity_author"
+     */
+    public function serviceEntityAuthor ($iContentId = 0)
+    {
+        return bx_srv('system', 'get_block_author', ['bx_forum', $iContentId], 'TemplServices');
+    }
+
+    /**
+     * @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 checkAllowedResolveAnyEntry($aDataEntry, $isPerformAction = false)
+    {
+    	$CNF = &$this->_oConfig->CNF;
+
+    	if((int)$aDataEntry[$CNF['FIELD_RESOLVABLE']] != 1 || (int)$aDataEntry[$CNF['FIELD_RESOLVE']] != 0)
+    		return false;
+
+        if($aDataEntry[$CNF['FIELD_AUTHOR']] == bx_get_logged_profile_id())
+            return CHECK_ACTION_RESULT_ALLOWED;
+        
+		return $this->_checkAllowedAction('resolve any entry', $aDataEntry, $isPerformAction);
+    }
+
+    public function checkAllowedUnresolveAnyEntry($aDataEntry, $isPerformAction = false)
+    {
+    	$CNF = $this->_oConfig->CNF;
+        
+    	if((int)$aDataEntry[$CNF['FIELD_RESOLVABLE']] != 1 || (int)$aDataEntry[$CNF['FIELD_RESOLVE']] != 1)
+			return false;
+        
+        if($aDataEntry[$CNF['FIELD_AUTHOR']] == bx_get_logged_profile_id())
+            return CHECK_ACTION_RESULT_ALLOWED;
+
+    	return $this->_checkAllowedAction('resolve 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);
+        
+        $this->_oTemplate->addJsTranslation(array('_sys_grid_search'));
+        $this->_oTemplate->addCss(array('grid_tools.css'));
+       
+        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')
+        ));
+    }
+}
+
+/** @} */

+ 259 - 0
modules/boonex/forum/updates/13.0.2_13.0.3/source/classes/BxForumTemplate.php

@@ -0,0 +1,259 @@
+<?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
+ *
+ * @{
+ */
+
+/*
+ * Module representation.
+ */
+class BxForumTemplate extends BxBaseModTextTemplate
+{
+    /**
+     * Constructor
+     */
+    function __construct(&$oConfig, &$oDb)
+    {
+        $this->MODULE = 'bx_forum';
+        parent::__construct($oConfig, $oDb);
+    }
+
+    public function entryBreadcrumb($aContentInfo, $aTmplVarsItems = array())
+    {
+    	$CNF = &BxDolModule::getInstance($this->MODULE)->_oConfig->CNF;
+
+        $oPermalink = BxDolPermalinks::getInstance();
+        $oCategory = BxDolCategory::getObjectInstance($CNF['OBJECT_CATEGORY']);
+
+    	$aTmplVarsItems = array(array(
+        	'url' => bx_append_url_params($oPermalink->permalink('page.php?i=' . $CNF['URI_CATEGORY_ENTRIES']), array(
+        		'category' => $aContentInfo[$CNF['FIELD_CATEGORY']]
+        	)),
+        	'title' => $oCategory->getCategoryTitle($aContentInfo[$CNF['FIELD_CATEGORY']])
+        ), array(
+        	'url' => $oPermalink->permalink('page.php?i=' . $CNF['URI_VIEW_ENTRY'] . '&id=' . $aContentInfo[$CNF['FIELD_ID']]),
+        	'title' => bx_process_output($aContentInfo[$CNF['FIELD_TITLE']])
+        ));
+
+    	return parent::entryBreadcrumb($aContentInfo, $aTmplVarsItems);
+    }
+
+    public function entryParticipants($aContentInfo, $iMaxVisible = 2, $sFloat = 'left')
+    {
+        $oModule = BxDolModule::getInstance($this->MODULE);
+        $CNF = &$oModule->_oConfig->CNF;
+
+        $iAuthorId = $aContentInfo[$CNF['FIELD_AUTHOR']];
+        $aParticipants = $this->_oDb->getComments(array('type' => 'author_comments', 'object_id' => $aContentInfo[$CNF['FIELD_ID']]));
+        $aParticipants[$iAuthorId] = !empty($aParticipants[$iAuthorId]) ? $aParticipants[$iAuthorId] + 1 : 1;
+
+        // sort participants: first - current user, second - last replier, third - author, all others sorted by max number of posts
+        $aParticipants = $oModule->sortParticipants($aParticipants, $aContentInfo['lr_profile_id'], $iAuthorId);
+        $iParticipantsNum = count($aParticipants);
+
+        // prepare template variables
+        $aVarsPopup = array (
+            'float' => 'none',
+            'bx_repeat:participants' => array(),
+            'bx_if:participants_more' => array(
+                'condition' => false,
+                'content' => array(),
+            ),
+        );
+        $aVars = array (
+            'float' => $sFloat,
+            'bx_repeat:participants' => array(),
+            'bx_if:participants_more' => array(
+                'condition' => $iParticipantsNum > $iMaxVisible,
+                'content' => array(
+                    'popup' => '',
+                    'title_more' => _t('_bx_forum_more', $iParticipantsNum - $iMaxVisible),
+                    'float' => $sFloat,
+                    'id' => $this->MODULE . '-popup-' . $aContentInfo[$CNF['FIELD_ID']],
+                ),
+            ),
+        );
+        $i = 0;
+        foreach ($aParticipants as $iProfileId => $iComments) {
+            $oProfile = BxDolProfile::getInstanceMagic($iProfileId);
+
+            $aParticipant = array (
+                'id' => $oProfile->id(),
+                'unit' => $oProfile->getUnit(0, array('template' => 'unit_wo_info')),
+                'float' => $sFloat,
+                'class' => $iAuthorId == $iProfileId ? 'bx-forum-participant-author' : '',
+            	'bx_if:replies_count' => array(
+            		'condition' => $iComments > 0,
+            		'content' => array(
+            			'count' => $iComments
+            		)
+            	),
+                'bx_if:last_replier' => array (
+                    'condition' => ($aContentInfo['lr_profile_id'] == $iProfileId),
+                    'content' => array (
+                        'id' => $oProfile->id(),
+                        'title' => bx_html_attribute(_t('_bx_forum_participant_last_replier')),
+                    ),
+                ),
+                'bx_if:author'  => array (
+                    'condition' => $iAuthorId == $iProfileId,
+                    'content' => array (
+                        'id' => $oProfile->id(),
+                        'title' => bx_html_attribute(_t('_bx_forum_participant_author')),
+                    ),
+                ),
+            );
+
+            if ($i < $iMaxVisible)
+                $aVars['bx_repeat:participants'][] = $aParticipant;
+            if ($i >= $iMaxVisible)
+                $aVarsPopup['bx_repeat:participants'][] = $aParticipant;
+
+            ++$i;
+        }
+
+        if ($aVarsPopup['bx_repeat:participants']) {
+            $aVars['bx_if:participants_more']['content']['popup'] = BxTemplFunctions::getInstance()->transBox('', '<div class="bx-def-padding">' . $this->parseHtmlByName('participants.html', $aVarsPopup) . '</div>');
+        }
+
+        return $this->parseHtmlByName('participants.html', $aVars);
+    }
+
+	function getEntryAuthor($aRow)
+    {
+    	$oProfileAuthor = BxDolProfile::getInstanceMagic($aRow['author']);
+
+    	return $this->parseHtmlByName('entry-author.html', array(
+			'unit' => $oProfileAuthor->getUnit(0, array('template' => 'unit_wo_info')),
+    	));
+    }
+
+    function getEntryPreview($aRow, $aParams = [])
+    {
+        $oModule = BxDolModule::getInstance($this->MODULE);
+        $CNF = &$oModule->_oConfig->CNF;
+
+        $oProfileLast = BxDolProfile::getInstanceMagic($aRow['lr_profile_id']);
+
+        $sTitle = $aRow[$CNF['FIELD_TITLE']];
+
+        $aMetas = array('main' => false, 'counters' => false, 'reply' => false);
+        foreach(array_keys($aMetas) as $sMeta) {
+            $sKey = 'OBJECT_MENU_SNIPPET_META_' . strtoupper($sMeta);
+            if(empty($CNF[$sKey]))
+                continue;
+
+            $oMenuMeta = BxDolMenu::getObjectInstance($CNF[$sKey], $this);
+            if(!$oMenuMeta) 
+                continue;
+
+            $oMenuMeta->setContentId($aRow[$CNF['FIELD_ID']]);
+            $sMenuMeta = $oMenuMeta->getCode();
+            if(empty($sMenuMeta))
+                continue;
+
+            $aMetas[$sMeta] = array(
+                'content' => $sMenuMeta
+            );
+        }
+        
+        $oObject = isset($CNF['OBJECT_COMMENTS']) ? BxDolCmts::getObjectInstance($CNF['OBJECT_COMMENTS'], $aRow[$CNF['FIELD_ID']]) : null;
+        $sParticipants = $oObject ? $oObject->getCounter(['show_counter_empty' => true, 'show_counter' => false, 'show_counter_style' => 'simple', 'dynamic_mode' => true, 'caption' => '', 'show_icon' => false, 'caption_empty' => '']) : '';
+        
+        $sImage = '';
+        $mixedImage = $this->_getHeaderImage($aRow);
+        if($mixedImage !== false) {
+            if(!empty($mixedImage['object']))
+                $o = BxDolStorage::getObjectInstance($mixedImage['object']);
+            else if(!empty($mixedImage['transcoder']))
+                $o = BxDolTranscoder::getObjectInstance($mixedImage['transcoder']);
+
+            if($o)
+                $sImage = $o->getFileUrlById($mixedImage['id']);
+        }
+
+        return $this->parseHtmlByName('entry-preview.html', array(
+            'bx_if:show_stick' => array(
+                'condition' => (int)$aRow[$CNF['FIELD_STICK']] == 1,
+                'content' => array()
+            ),
+            'bx_if:show_lock' => array(
+                'condition' => (int)$aRow[$CNF['FIELD_LOCK']] == 1,
+                'content' => array()
+            ),
+            'url' => BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink('page.php?i=' . $oModule->_oConfig->CNF['URI_VIEW_ENTRY'] . '&id=' . $aRow[$CNF['FIELD_ID']]),
+            'title' => $sTitle ? $sTitle : _t('_Empty'),
+            'participants' => $sParticipants,
+            'badges' => $this->_oModule->serviceGetBadges($aRow[$CNF['FIELD_ID']]),
+            'image' => $sImage,
+            'bx_if:meta_main' => array(
+                'condition' => $aMetas['main'] !== false && (!isset($aParams['show_meta_main']) || $aParams['show_meta_main']),
+                'content' => $aMetas['main']
+            ),
+            'bx_if:image' => array(
+                'condition' => $sImage != '',
+                'content' => ['image' => $sImage]
+            ),
+            
+            'bx_if:meta_counters' => array(
+                'condition' => $aMetas['counters'] !== false && (!isset($aParams['show_meta_counters']) || $aParams['show_meta_counters']),
+                'content' => $aMetas['counters']
+            ),
+            'bx_if:meta_reply' => array(
+                'condition' => $aMetas['reply'] !== false && (!isset($aParams['show_meta_reply']) || $aParams['show_meta_reply']),
+                'content' => $aMetas['reply']
+            )
+        ));
+    }
+    
+    public function getJsCode($sType, $aParams = array(), $mixedWrap = true)
+    {
+        $CNF = $this->_oModule->_oConfig->CNF;
+        if ($sType == 'main'){
+            $aParams = array_merge(array(
+                'sObjNameGrid' => $CNF['OBJECT_GRID'],
+            ), $aParams);
+        }
+        return parent::getJsCode($sType, $aParams);
+    }
+
+    function getAuthorDesc ($aData, $oProfile)
+    {
+        return '';
+    }
+
+    function getAuthorAddon ($aData, $oProfile)
+    {
+        return '';
+    }
+    
+    protected function getUnit ($aData, $aParams = array())
+    {
+        $aTmplVars = parent::getUnit($aData, $aParams);
+        
+        $CNF = $this->_oModule->_oConfig->CNF;
+        
+        $oCategory = BxDolCategory::getObjectInstance($CNF['OBJECT_CATEGORY']);
+        
+        $sIcon = $this->_oModule->_oTemplate->parseHtmlByName('default_category.html', []);
+        
+        $aCategoryData = $this->_oModule->_oDb->getCategories(array('type' => 'by_category', 'category' => $aData[$CNF['FIELD_CATEGORY']]));
+
+        if(isset($aCategoryData['icon']))
+            $sIcon = $this->getImage($aCategoryData['icon'], array('class' => 'sys-icon'));
+        
+        $aTmplVars['category'] = $oCategory->getCategoryTitle($aData[$CNF['FIELD_CATEGORY']]);
+        $aTmplVars['category_icon'] = $sIcon;
+        $oProfile = BxDolProfile::getInstanceMagic($aData[$CNF['FIELD_AUTHOR']]);
+        $aTmplVars['author'] = $oProfile->getUnit();
+
+        return $aTmplVars;
+    }
+}
+
+/** @} */

+ 149 - 0
modules/boonex/forum/updates/13.0.2_13.0.3/source/install/config.php

@@ -0,0 +1,149 @@
+<?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' => '13.0.3',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '13.0.0-B2'
+    ),
+
+    /**
+     * '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_gallery',
+        'bx_forum_cover',
+        
+        'bx_forum_preview_photos',
+        'bx_forum_gallery_photos',
+        'bx_forum_view_photos',
+
+        'bx_forum_videos_poster',
+        'bx_forum_videos_poster_preview',
+        'bx_forum_videos_mp4',
+        'bx_forum_videos_mp4_hd',
+        
+        'bx_forum_preview_files',
+        'bx_forum_gallery_files',
+        
+        'bx_forum_preview_cmts',
+    ),
+
+    /**
+     * 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'
+    ),
+);
+
+/** @} */

+ 445 - 0
modules/boonex/forum/updates/13.0.2_13.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_forum"><![CDATA[Discussions]]></string>
+    <string name="_bx_forum_cmts"><![CDATA[Discussions's Comments]]></string>
+    <string name="_bx_forum_reactions"><![CDATA[Discussions's Reactions]]></string>
+
+    <string name="_bx_forum_option_enable_auto_approve"><![CDATA[Auto approve a discussion after creation]]></string>
+    <string name="_bx_forum_option_summary_chars"><![CDATA[Number of characters in auto-cropped discussion summary]]></string>
+    <string name="_bx_forum_option_plain_summary_chars"><![CDATA[Number of characters in plain discussion description when discussion hasn't thumb]]></string>
+    <string name="_bx_forum_option_per_page_browse"><![CDATA[Number of items per page]]></string>
+    <string name="_bx_forum_option_per_page_index"><![CDATA[Number of items on site home page]]></string>
+    <string name="_bx_forum_option_per_page_profile"><![CDATA[Number of items on profile page]]></string>
+    <string name="_bx_forum_option_rss_num"><![CDATA[Number of items in RSS feed]]></string>
+    <string name="_bx_forum_option_searchable_fields"><![CDATA[Searchable fields for keyword search]]></string>
+    <string name="_bx_forum_option_autosubscribe_created"><![CDATA[Autosubscribe to newly created discussions]]></string>
+    <string name="_bx_forum_option_autosubscribe_replied"><![CDATA[Autosubscribe to replied discussions]]></string>
+    <string name="_bx_forum_option_auto_activation_for_categories"><![CDATA[Auto-Activation For Categories]]></string>
+    <string name="_bx_forum_option_per_page_for_favorites_lists"><![CDATA[Number of favorite lists per page]]></string>
+    <string name="_bx_forum_option_visible_categories"><![CDATA[Number of visible categories]]></string>
+    <string name="_bx_forum_option_visible_hashtags"><![CDATA[Number of visible hashtags]]></string>
+
+    <string name="_bx_forum_form_entry"><![CDATA[Forum]]></string>
+    <string name="_bx_forum_form_entry_display_add"><![CDATA[New discussion]]></string>
+    <string name="_bx_forum_form_entry_display_delete"><![CDATA[Delete discussion]]></string>
+    <string name="_bx_forum_form_entry_display_edit"><![CDATA[Edit discussion]]></string>
+    <string name="_bx_forum_form_entry_display_view"><![CDATA[View discussion]]></string>
+    <string name="_bx_forum_form_entry_input_author"><![CDATA[Author]]></string>
+    <string name="_bx_forum_form_entry_input_sys_do_submit"><![CDATA[Submit]]></string>
+    <string name="_bx_forum_form_entry_input_do_submit"><![CDATA[Submit]]></string>
+    <string name="_bx_forum_form_entry_input_sys_text"><![CDATA[Text]]></string>
+    <string name="_bx_forum_form_entry_input_text"><![CDATA[Text]]></string>
+    <string name="_bx_forum_form_entry_input_text_err"><![CDATA[Text field can't be empty]]></string>
+    <string name="_bx_forum_form_entry_input_text_comments"><![CDATA[Comments Text]]></string>
+    <string name="_bx_forum_form_entry_input_sys_delete_confirm"><![CDATA[Delete confirmation]]></string>
+    <string name="_bx_forum_form_entry_input_delete_confirm"><![CDATA[I am sure I want to delete this discussion]]></string>
+    <string name="_bx_forum_form_entry_input_delete_confirm_info"><![CDATA[This action can not be undone]]></string>
+    <string name="_bx_forum_form_entry_input_delete_confirm_error"><![CDATA[Please check this checkbox if you really want to delete the discussion]]></string>
+    <string name="_bx_forum_form_entry_input_sys_attachments"><![CDATA[Attachments]]></string>
+    <string name="_bx_forum_form_entry_input_sys_covers"><![CDATA[Header Image]]></string>
+    <string name="_bx_forum_form_entry_input_covers"><![CDATA[Header Image]]></string>
+    <string name="_bx_forum_form_entry_input_covers_uploader_simple_title"><![CDATA[Upload]]></string>
+    <string name="_bx_forum_form_entry_input_covers_uploader_html5_title"><![CDATA[Upload]]></string>
+    <string name="_bx_forum_form_entry_input_sys_pictures"><![CDATA[Images]]></string>
+    <string name="_bx_forum_form_entry_input_pictures"><![CDATA[]]></string>
+    <string name="_bx_forum_form_entry_input_sys_videos"><![CDATA[Videos]]></string>
+    <string name="_bx_forum_form_entry_input_videos"><![CDATA[]]></string>
+    <string name="_bx_forum_form_entry_input_sys_files"><![CDATA[Files]]></string>
+    <string name="_bx_forum_form_entry_input_files"><![CDATA[]]></string>
+    <string name="_bx_forum_form_entry_input_sys_polls"><![CDATA[Polls]]></string>
+    <string name="_bx_forum_form_entry_input_media"><![CDATA[Media]]></string>
+    <string name="_bx_forum_form_entry_input_sys_allow_view_to"><![CDATA[Visibility]]></string>
+    <string name="_bx_forum_form_entry_input_allow_view_to"><![CDATA[Visibility]]></string>
+    <string name="_bx_forum_form_entry_input_allow_view_favorite_list"><![CDATA[Visibility]]></string>
+    <string name="_bx_forum_form_entry_input_picture_use_as_thumb"><![CDATA[Header Image]]></string>
+    <string name="_bx_forum_form_entry_input_sys_date_added"><![CDATA[Added]]></string>
+    <string name="_bx_forum_form_entry_input_date_added"><![CDATA[Added]]></string>
+    <string name="_bx_forum_form_entry_input_sys_date_changed"><![CDATA[Changed]]></string>
+    <string name="_bx_forum_form_entry_input_date_changed"><![CDATA[Changed]]></string>
+    <string name="_bx_forum_form_entry_input_sys_title"><![CDATA[Topic]]></string>
+    <string name="_bx_forum_form_entry_input_title"><![CDATA[Topic]]></string>
+    <string name="_bx_forum_form_entry_input_title_err"><![CDATA[Topic is mandatory]]></string>
+    <string name="_bx_forum_form_entry_input_sys_cat"><![CDATA[Category]]></string>
+    <string name="_bx_forum_form_entry_input_cat"><![CDATA[Category]]></string>
+    <string name="_bx_forum_form_entry_input_cat_err"><![CDATA[Please select category]]></string>
+    <string name="_bx_forum_form_entry_input_sys_multicat"><![CDATA[Categories]]></string>
+    <string name="_bx_forum_form_entry_input_multicat"><![CDATA[Categories]]></string>
+    <string name="_bx_forum_form_entry_input_multicat_err"><![CDATA[Please select category]]></string>
+    <string name="_bx_forum_form_entry_input_resolvable"><![CDATA[Resolvable]]></string>
+    <string name="_bx_forum_form_entry_input_sys_resolvable"><![CDATA[Resolvable]]></string>
+
+    <string name="_bx_forum_form_poll"><![CDATA[Polls]]></string>
+    <string name="_bx_forum_form_poll_display_add"><![CDATA[Add Poll]]></string>
+    <string name="_bx_forum_form_poll_input_sys_text"><![CDATA[Question]]></string>
+    <string name="_bx_forum_form_poll_input_text"><![CDATA[Question]]></string>
+    <string name="_bx_forum_form_poll_input_text_err"><![CDATA[Question is essential. Please, fill in this field]]></string>
+    <string name="_bx_forum_form_poll_input_sys_answers"><![CDATA[Answers]]></string>
+    <string name="_bx_forum_form_poll_input_answers"><![CDATA[Answers]]></string>
+    <string name="_bx_forum_form_poll_input_answers_err"><![CDATA[Poll should have at least 2 non-empty answers.]]></string>
+    <string name="_bx_forum_form_poll_input_answers_add"><![CDATA[Add More]]></string>
+    <string name="_bx_forum_form_poll_input_sys_do_submit"><![CDATA[Add]]></string>
+    <string name="_bx_forum_form_poll_input_do_submit"><![CDATA[Add]]></string>
+    <string name="_bx_forum_form_poll_input_do_cancel"><![CDATA[Close]]></string>
+
+    <string name="_bx_forum_form_search"><![CDATA[Search]]></string>
+    <string name="_bx_forum_form_search_display_full"><![CDATA[Full Search]]></string>
+    <string name="_bx_forum_form_search_input_sys_author"><![CDATA[Author]]></string>
+    <string name="_bx_forum_form_search_input_author"><![CDATA[Author]]></string>
+    <string name="_bx_forum_form_search_input_sys_category"><![CDATA[Category]]></string>
+    <string name="_bx_forum_form_search_input_category"><![CDATA[Category]]></string>
+    <string name="_bx_forum_form_search_input_sys_keyword"><![CDATA[Keyword]]></string>
+    <string name="_bx_forum_form_search_input_keyword"><![CDATA[Keyword]]></string>
+    <string name="_bx_forum_form_search_input_do_submit"><![CDATA[Search]]></string>
+    <string name="_bx_forum_form_search_input_sys_do_submit"><![CDATA[Search]]></string>
+
+	<string name="_bx_forum_acl_action_create_entry"><![CDATA[Create new discussion]]></string>
+	<string name="_bx_forum_acl_action_delete_entry"><![CDATA[Delete discussion]]></string>
+	<string name="_bx_forum_acl_action_view_entry"><![CDATA[View discussion]]></string>
+	<string name="_bx_forum_acl_action_set_thumb"><![CDATA[Set discussion's cover]]></string>
+	<string name="_bx_forum_acl_action_edit_any_entry"><![CDATA[Edit any discussion]]></string>
+	<string name="_bx_forum_acl_action_delete_any_entry"><![CDATA[Delete any discussion]]></string>
+	<string name="_bx_forum_acl_action_stick_any_entry"><![CDATA[Pin any discussion]]></string>
+	<string name="_bx_forum_acl_action_lock_any_entry"><![CDATA[Lock any discussion]]></string>
+	<string name="_bx_forum_acl_action_hide_any_entry"><![CDATA[Hide any discussion]]></string>
+    <string name="_bx_forum_acl_action_resolve_any_entry"><![CDATA[Mark as answered any discussion]]></string>
+
+	<string name="_bx_forum_page_title_sys_create_entry"><![CDATA[New discussion]]></string>
+	<string name="_bx_forum_page_title_create_entry"><![CDATA[New discussion]]></string>
+	<string name="_bx_forum_page_block_title_create_entry"><![CDATA[New discussion]]></string>
+	<string name="_bx_forum_page_title_sys_edit_entry"><![CDATA[Edit]]></string>
+	<string name="_bx_forum_page_title_edit_entry"><![CDATA[Edit]]></string>
+	<string name="_bx_forum_page_block_title_edit_entry"><![CDATA[Edit]]></string>
+    <string name="_bx_forum_page_title_sys_delete_entry"><![CDATA[Delete]]></string>
+    <string name="_bx_forum_page_title_delete_entry"><![CDATA[Delete]]></string>
+    <string name="_bx_forum_page_block_title_delete_entry"><![CDATA[Delete]]></string>
+	<string name="_bx_forum_page_title_sys_view_entry"><![CDATA[View discussion]]></string>
+	<string name="_bx_forum_page_title_view_entry"><![CDATA[{title}]]></string>
+	<string name="_bx_forum_page_block_title_entry_all_actions"><![CDATA[All Actions]]></string>
+	<string name="_bx_forum_page_block_title_entry_attachments"><![CDATA[Attachments]]></string>
+        <string name="_bx_forum_page_block_title_entry_polls"><![CDATA[Polls]]></string>
+	<string name="_bx_forum_page_block_title_entry_text"><![CDATA[Text]]></string>
+    <string name="_bx_forum_page_block_title_entry_author"><![CDATA[Author]]></string>
+    <string name="_bx_forum_page_block_title_entry_actions"><![CDATA[Actions]]></string>
+    <string name="_bx_forum_page_block_title_entry_breadcrumb"><![CDATA[Breadcrumb]]></string>
+    <string name="_bx_forum_page_block_title_entry_comments"><![CDATA[Replies ({0})]]></string>
+	<string name="_bx_forum_page_block_title_entry_reports"><![CDATA[Reports]]></string>
+    <string name="_bx_forum_page_block_title_entry_participants"><![CDATA[Participants]]></string>
+    <string name="_bx_forum_page_block_title_entry_info"><![CDATA[Info]]></string>
+    <string name="_bx_forum_page_title_browse"><![CDATA[Discussions]]></string>
+	<string name="_bx_forum_page_title_search_results"><![CDATA[Discussions matching "{0}"]]></string>
+	<string name="_bx_forum_page_title_browse_by_author"><![CDATA[Discussions of {display_name}]]></string>
+  <string name="_bx_forum_page_title_browse_by_context"><![CDATA[Discussions in {display_name}]]></string>
+	<string name="_bx_forum_page_title_browse_featured"><![CDATA[Featured Discussions]]></string>
+	<string name="_bx_forum_page_title_browse_by_category"><![CDATA[Discussions by {category_name}]]></string>
+	<string name="_bx_forum_page_title_browse_new"><![CDATA[New Discussions]]></string>
+    <string name="_bx_forum_page_title_browse_latest"><![CDATA[Latest Discussions]]></string>
+    <string name="_bx_forum_page_title_browse_top"><![CDATA[Top Discussions]]></string>
+    <string name="_bx_forum_page_title_browse_popular"><![CDATA[Popular Discussions]]></string>
+    <string name="_bx_forum_page_title_browse_updated"><![CDATA[Updated Discussions]]></string>
+    <string name="_bx_forum_page_title_browse_partaken"><![CDATA[Partaken Discussions]]></string>
+    <string name="_bx_forum_page_title_sys_home"><![CDATA[Discussions Home]]></string>
+    <string name="_bx_forum_page_title_home"><![CDATA[Discussions]]></string>
+    <string name="_bx_forum_page_block_title_featured_entries"><![CDATA[Featured Discussions]]></string>
+    <string name="_bx_forum_page_block_title_featured_entries_view_showcase"><![CDATA[Featured Discussions]]></string>
+    <string name="_bx_forum_page_block_title_sys_featured_entries_view_showcase"><![CDATA[Featured Discussions (Showcase view)]]></string>
+    
+    <string name="_bx_forum_page_title_sys_entries_new"><![CDATA[New Discussions]]></string>
+    <string name="_bx_forum_page_title_entries_new"><![CDATA[New Discussions]]></string>
+    <string name="_bx_forum_page_title_sys_entries_top"><![CDATA[Top Discussions]]></string>
+    <string name="_bx_forum_page_title_entries_top"><![CDATA[Top Discussions]]></string>
+    <string name="_bx_forum_page_title_sys_entries_popular"><![CDATA[Popular Discussions]]></string>
+    <string name="_bx_forum_page_title_entries_popular"><![CDATA[Popular Discussions]]></string>
+    <string name="_bx_forum_page_title_sys_entries_updated"><![CDATA[Updated Discussions]]></string>
+    <string name="_bx_forum_page_title_entries_updated"><![CDATA[Updated Discussions]]></string>
+    <string name="_bx_forum_page_block_title_new_entries"><![CDATA[New Discussions]]></string>
+    <string name="_bx_forum_page_block_title_new_entries_view_extended"><![CDATA[New Discussions (Extended View)]]></string>
+    <string name="_bx_forum_page_block_title_new_entries_view_full"><![CDATA[New Discussions (Full View)]]></string>
+    <string name="_bx_forum_page_block_title_latest_entries"><![CDATA[Discussions With Recent Posts]]></string>
+    <string name="_bx_forum_page_block_title_home"><![CDATA[Discussions List]]></string>
+    <string name="_bx_forum_page_block_title_latest_entries_view_extended"><![CDATA[Discussions With Recent Posts (Extended View)]]></string>
+    <string name="_bx_forum_page_block_title_latest_entries_view_full"><![CDATA[Discussions With Recent Posts (Full View)]]></string>
+    <string name="_bx_forum_page_block_title_top_entries"><![CDATA[Top Discussions]]></string>
+    <string name="_bx_forum_page_block_title_top_entries_view_extended"><![CDATA[Top Discussions (Extended View)]]></string>
+    <string name="_bx_forum_page_block_title_top_entries_view_full"><![CDATA[Top Discussions (Full View)]]></string>
+    <string name="_bx_forum_page_block_title_popular_entries"><![CDATA[Popular Discussions]]></string>
+    <string name="_bx_forum_page_block_title_popular_entries_view_extended"><![CDATA[Popular Discussions (Extended View)]]></string>
+    <string name="_bx_forum_page_block_title_popular_entries_view_full"><![CDATA[Popular Discussions (Full View)]]></string>
+    <string name="_bx_forum_page_block_title_updated_entries"><![CDATA[Updated Discussions]]></string>
+    <string name="_bx_forum_page_block_title_sys_favorites_entries"><![CDATA[Favorite List]]></string>
+    <string name="_bx_forum_page_block_title_favorites_entries"><![CDATA["{title}" List]]></string>
+    <string name="_bx_forum_page_block_title_favorites_entries_info"><![CDATA[Info]]></string>
+    <string name="_bx_forum_page_block_title_favorites_entries_actions"><![CDATA[Favorites List Actions]]></string>
+    <string name="_bx_forum_page_title_sys_entries_categories"><![CDATA[Discussions Categories]]></string>
+    <string name="_bx_forum_page_title_entries_categories"><![CDATA[Discussions Categories]]></string>
+    <string name="_bx_forum_page_block_title_entries_categories"><![CDATA[Discussions Categories]]></string>
+    <string name="_bx_forum_page_title_sys_entries_by_category"><![CDATA[Discussions by category]]></string>
+    <string name="_bx_forum_page_title_entries_by_category"><![CDATA[Discussions by {category_name}]]></string>
+    <string name="_bx_forum_page_block_title_sys_entries_by_category"><![CDATA[Discussions by category]]></string>
+    <string name="_bx_forum_page_block_title_entries_by_category"><![CDATA[{category_name}]]></string>
+    <string name="_bx_forum_page_title_sys_entries_by_keyword"><![CDATA[Discussions by keyword]]></string>
+    <string name="_bx_forum_page_title_entries_by_keyword"><![CDATA[Discussions by {keyword_name}]]></string>
+    <string name="_bx_forum_page_block_title_sys_entries_by_keyword"><![CDATA[Discussions by keyword]]></string>
+    <string name="_bx_forum_page_block_title_entries_by_keyword"><![CDATA[Discussions by {keyword_name}]]></string>
+    <string name="_bx_forum_page_title_sys_entries_of_author"><![CDATA[Discussions of author]]></string>
+    <string name="_bx_forum_page_title_entries_of_author"><![CDATA[Discussions by {display_name}]]></string>
+    <string name="_bx_forum_page_title_sys_entries_in_context"><![CDATA[Discussions in context]]></string>
+    <string name="_bx_forum_page_title_entries_in_context"><![CDATA[Discussions in {display_name}]]></string>
+    <string name="_bx_forum_page_block_title_favorites_of_author"><![CDATA[Favorites by <a href="{profile_link}">{display_name}</a>]]></string>
+    <string name="_bx_forum_page_block_title_sys_favorites_of_author"><![CDATA[Favorites of author]]></string>
+    <string name="_bx_forum_page_block_title_entries_of_author"><![CDATA[Discussions by <a href="{profile_link}">{display_name}</a>]]></string>
+    <string name="_bx_forum_page_block_title_sys_entries_of_author"><![CDATA[Discussions of author]]></string>
+    <string name="_bx_forum_page_block_title_entries_in_context"><![CDATA[Discussions in <a href="{profile_link}">{display_name}</a>]]></string>
+    <string name="_bx_forum_page_block_title_sys_entries_in_context"><![CDATA[Discussions in context]]></string>
+    <string name="_bx_forum_page_block_title_sys_multi_categories_in_context"><![CDATA[Multi categories in context]]></string>
+    <string name="_bx_forum_page_block_title_multi_categories_in_context"><![CDATA[Categories in <a href="{profile_link}">{display_name}</a>]]></string>
+    <string name="_bx_forum_page_block_title_entries_actions"><![CDATA[Discussions actions]]></string>
+    <string name="_bx_forum_page_block_title_sys_entry_context"><![CDATA[Posted in]]></string>
+    <string name="_bx_forum_page_block_title_entry_context"><![CDATA[Posted in]]></string>
+    <string name="_bx_forum_page_block_title_browse_cmts"><![CDATA[Forum's Comments]]></string>
+    <string name="_bx_forum_page_title_sys_manage"><![CDATA[Manage Own]]></string>
+    <string name="_bx_forum_page_title_sys_manage_administration"><![CDATA[Manage All]]></string>
+    <string name="_bx_forum_page_title_manage"><![CDATA[Manage]]></string>
+    <string name="_bx_forum_page_block_title_system_manage"><![CDATA[Manage Own]]></string>
+    <string name="_bx_forum_page_block_title_system_manage_administration"><![CDATA[Manage All]]></string>
+    <string name="_bx_forum_page_block_title_manage"><![CDATA[Manage]]></string>
+    <string name="_bx_forum_page_block_title_popular_keywords"><![CDATA[Popular Hashtags]]></string>
+    <string name="_bx_forum_page_block_title_cats"><![CDATA[Discussions Categories]]></string>
+    <string name="_bx_forum_page_block_title_browse_labels"><![CDATA[Browse Labels]]></string>
+    <string name="_bx_forum_page_block_title_sys_multicats"><![CDATA[Discussions Categories(Multi)]]></string>
+    <string name="_bx_forum_page_block_title_multicats"><![CDATA[Discussions Categories]]></string>
+    <string name="_bx_forum_page_block_title_sys_my_entries"><![CDATA[User Discussions]]></string>
+    <string name="_bx_forum_page_block_title_my_entries"><![CDATA[{display_name} Discussions]]></string>
+    <string name="_bx_forum_page_title_sys_entries_search"><![CDATA[Search]]></string>
+    <string name="_bx_forum_page_title_entries_search"><![CDATA[Search]]></string>
+    <string name="_bx_forum_page_title_sys_entries_favorites"><![CDATA[Favorites Discussions]]></string>
+    <string name="_bx_forum_page_title_entries_favorites"><![CDATA[Favorites Discussions]]></string>
+    <string name="_bx_forum_page_block_title_entries_search_form"><![CDATA[Search]]></string>
+    <string name="_bx_forum_page_block_title_entries_search_results"><![CDATA[Search Results]]></string>
+    <string name="_bx_forum_page_block_title_search_form"><![CDATA[Search Form]]></string>
+    <string name="_bx_forum_page_block_title_search_results"><![CDATA[Search Results]]></string>
+    <string name="_bx_forum_page_block_title_search_form_cmts"><![CDATA[Comments Search Form]]></string>
+    <string name="_bx_forum_page_block_title_search_results_cmts"><![CDATA[Comments Search Results]]></string>
+    <string name="_bx_forum_page_title_sys_entries_partaken"><![CDATA[Partaken]]></string>
+    <string name="_bx_forum_page_title_entries_partaken"><![CDATA[Partaken]]></string>
+    <string name="_bx_forum_page_block_title_partaken_entries"><![CDATA[Partaken]]></string>
+
+    <string name="_bx_forum_menu_title_entry_attachments"><![CDATA[Form Attachments]]></string>
+    <string name="_bx_forum_menu_set_title_entry_attachments"><![CDATA[Form Attachments]]></string>
+    <string name="_bx_forum_menu_item_title_system_cpa_photo_simple"><![CDATA[Add Photo (simple)]]></string>
+    <string name="_bx_forum_menu_item_title_cpa_photo_simple"><![CDATA[Add Photo]]></string>
+    <string name="_bx_forum_menu_item_title_system_cpa_photo_html5"><![CDATA[Add Photo (html5)]]></string>
+    <string name="_bx_forum_menu_item_title_cpa_photo_html5"><![CDATA[Add Photos]]></string>
+    <string name="_bx_forum_menu_item_title_system_cpa_video_simple"><![CDATA[Add Video (simple)]]></string>
+    <string name="_bx_forum_menu_item_title_cpa_video_simple"><![CDATA[Add Video]]></string>
+    <string name="_bx_forum_menu_item_title_system_cpa_video_html5"><![CDATA[Add Video (html5)]]></string>
+    <string name="_bx_forum_menu_item_title_cpa_video_html5"><![CDATA[Add Videos]]></string>
+    <string name="_bx_forum_menu_item_title_system_cpa_video_record"><![CDATA[Record Video]]></string>
+    <string name="_bx_forum_menu_item_title_cpa_video_record"><![CDATA[Record Video]]></string>
+    <string name="_bx_forum_menu_item_title_system_cpa_file_simple"><![CDATA[Add File (simple)]]></string>
+    <string name="_bx_forum_menu_item_title_cpa_file_simple"><![CDATA[Add File]]></string>
+    <string name="_bx_forum_menu_item_title_system_cpa_file_html5"><![CDATA[Add File (html5)]]></string>
+    <string name="_bx_forum_menu_item_title_cpa_file_html5"><![CDATA[Add Files]]></string>
+    <string name="_bx_forum_menu_item_title_system_cpa_poll"><![CDATA[Add Poll]]></string>
+    <string name="_bx_forum_menu_item_title_cpa_poll"><![CDATA[Add Poll]]></string>
+    
+    <string name="_bx_forum_menu_item_title_system_add_link"><![CDATA[Add Link]]></string>
+    <string name="_bx_forum_menu_item_title_add_link"><![CDATA[Add Link]]></string>
+    <string name="_bx_forum_form_post_input_link_err_delete"><![CDATA[Cannot remove the link. Please report.]]></string>
+    <string name="_bx_forum_form_post_input_sys_link"><![CDATA[Link]]></string>
+    <string name="_bx_forum_form_post_input_link_alt"><![CDATA[Add Link]]></string>
+    <string name="_bx_forum_form_attach_link"><![CDATA[Attach Link]]></string>
+    <string name="_bx_forum_form_attach_link_display_add"><![CDATA[Attach Link]]></string>
+    <string name="_bx_forum_form_attach_link_input_sys_content_id"><![CDATA[Content Id]]></string>
+    <string name="_bx_forum_form_attach_link_input_sys_url"><![CDATA[Add Link]]></string>
+    <string name="_bx_forum_form_attach_link_input_url_err"><![CDATA[Correct Link is essential. Please, fill in this field.]]></string>
+    <string name="_bx_forum_form_attach_link_input_url"><![CDATA[Add Link]]></string>
+    <string name="_bx_forum_form_attach_link_input_do_submit"><![CDATA[Add]]></string>
+    <string name="_bx_forum_form_attach_link_input_sys_do_submit"><![CDATA[Add]]></string>
+    <string name="_bx_forum_form_attach_link_input_do_cancel"><![CDATA[Close]]></string>
+    
+
+    <string name="_bx_forum_menu_title_submenu"><![CDATA[Forum Submenu]]></string>
+    <string name="_bx_forum_menu_set_title_submenu"><![CDATA[Forum Submenu]]></string>
+    <string name="_bx_forum_menu_item_title_system_create_entry"><![CDATA[Discussion]]></string>
+    <string name="_bx_forum_menu_item_title_create_entry"><![CDATA[Discussion]]></string>
+    <string name="_bx_forum_menu_item_title_system_edit_entry"><![CDATA[Edit]]></string>
+    <string name="_bx_forum_menu_item_title_edit_entry"><![CDATA[Edit]]></string>
+    <string name="_bx_forum_menu_item_title_system_delete_entry"><![CDATA[Delete]]></string>
+    <string name="_bx_forum_menu_item_title_delete_entry"><![CDATA[Delete]]></string>
+    <string name="_bx_forum_menu_item_title_resolve_entry"><![CDATA[Mark as Resolved]]></string>
+    <string name="_bx_forum_menu_item_title_unresolve_entry"><![CDATA[Mark as Unresolved]]></string>
+    <string name="_bx_forum_menu_item_title_system_resolve_entry"><![CDATA[Mark as Resolved]]></string>
+    <string name="_bx_forum_menu_item_title_system_unresolve_entry"><![CDATA[Mark as Unresolved]]></string>
+    <string name="_bx_forum_menu_item_title_system_stick_entry"><![CDATA[Pin]]></string>
+    <string name="_bx_forum_menu_item_title_stick_entry"><![CDATA[Pin]]></string>
+    <string name="_bx_forum_menu_item_title_system_unstick_entry"><![CDATA[Unpin]]></string>
+    <string name="_bx_forum_menu_item_title_unstick_entry"><![CDATA[Unpin]]></string>
+    <string name="_bx_forum_menu_item_title_system_lock_entry"><![CDATA[Lock]]></string>
+    <string name="_bx_forum_menu_item_title_lock_entry"><![CDATA[Lock]]></string>
+    <string name="_bx_forum_menu_item_title_system_unlock_entry"><![CDATA[Unlock]]></string>
+    <string name="_bx_forum_menu_item_title_unlock_entry"><![CDATA[Unlock]]></string>
+    <string name="_bx_forum_menu_item_title_system_hide_entry"><![CDATA[Hide]]></string>
+    <string name="_bx_forum_menu_item_title_hide_entry"><![CDATA[Hide]]></string>
+    <string name="_bx_forum_menu_item_title_system_unhide_entry"><![CDATA[Unhide]]></string>
+    <string name="_bx_forum_menu_item_title_unhide_entry"><![CDATA[Unhide]]></string>
+    <string name="_bx_forum_menu_item_title_system_subscribe"><![CDATA[Subscribe]]></string>
+    <string name="_bx_forum_menu_item_title_subscribe"><![CDATA[Subscribe]]></string>
+    <string name="_bx_forum_menu_item_title_system_unsubscribe"><![CDATA[Unsubscribe]]></string>
+    <string name="_bx_forum_menu_item_title_unsubscribe"><![CDATA[Unsubscribe]]></string>
+    <string name="_bx_forum_menu_item_title_system_more"><![CDATA[More Actions]]></string>
+    <string name="_bx_forum_menu_item_title_more"><![CDATA[]]></string>
+    <string name="_bx_forum_menu_item_title_system_entries_home"><![CDATA[Discussions]]></string>
+    <string name="_bx_forum_menu_item_title_entries_home"><![CDATA[Discussions]]></string>
+    <string name="_bx_forum_menu_item_title_system_entries_partaken"><![CDATA[Partaken]]></string>
+    <string name="_bx_forum_menu_item_title_entries_partaken"><![CDATA[Partaken]]></string>
+    <string name="_bx_forum_menu_item_title_system_entries_public"><![CDATA[Home]]></string>
+    <string name="_bx_forum_menu_item_title_entries_public"><![CDATA[Home]]></string>
+    <string name="_bx_forum_menu_item_title_system_entries_manage"><![CDATA[Manage]]></string>
+    <string name="_bx_forum_menu_item_title_entries_manage"><![CDATA[Manage]]></string>
+    <string name="_bx_forum_menu_item_title_system_entries_new"><![CDATA[New]]></string>
+    <string name="_bx_forum_menu_item_title_entries_new"><![CDATA[New]]></string>
+    <string name="_bx_forum_menu_item_title_system_entries_top"><![CDATA[Top]]></string>
+    <string name="_bx_forum_menu_item_title_entries_top"><![CDATA[Top]]></string>
+    <string name="_bx_forum_menu_item_title_system_entries_categories"><![CDATA[Сategories]]></string>
+    <string name="_bx_forum_menu_item_title_entries_categories"><![CDATA[Сategories]]></string>
+    <string name="_bx_forum_menu_item_title_system_entries_search"><![CDATA[Search]]></string>
+    <string name="_bx_forum_menu_item_title_entries_search"><![CDATA[Search]]></string>
+    <string name="_bx_forum_menu_set_title_view_entry"><![CDATA[Discussion Actions]]></string>
+    <string name="_bx_forum_menu_title_view_entry"><![CDATA[Discussion Actions]]></string>
+    <string name="_bx_forum_menu_set_title_view_more"><![CDATA[Discussion More Actions]]></string>
+    <string name="_bx_forum_menu_title_view_more"><![CDATA[Discussion More Actions]]></string>
+    <string name="_bx_forum_menu_item_title_system_view_entries_author"><![CDATA[Discussions]]></string>
+    <string name="_bx_forum_menu_item_title_view_entries_author"><![CDATA[Discussions]]></string>
+    <string name="_bx_forum_menu_item_title_system_view_entries_in_context"><![CDATA[Discussions]]></string>
+    <string name="_bx_forum_menu_item_title_view_entries_in_context"><![CDATA[Discussions]]></string>
+    <string name="_bx_forum_menu_title_entries_my"><![CDATA[My Discussions Action Menu]]></string>
+    <string name="_bx_forum_menu_set_title_entries_my"><![CDATA[My Discussions Menu]]></string>
+    <string name="_bx_forum_menu_set_title_manage_tools"><![CDATA[Manage Tools Submenu]]></string>
+    <string name="_bx_forum_menu_title_manage_tools"><![CDATA[Manage Tools Submenu]]></string>
+    <string name="_bx_forum_menu_item_title_system_manage_account"><![CDATA[Manage account]]></string>
+    <string name="_bx_forum_menu_item_title_manage_account"><![CDATA[Manage account]]></string>
+    <string name="_bx_forum_menu_item_title_system_admt_discussions"><![CDATA[Discussions]]></string>
+    <string name="_bx_forum_menu_item_title_admt_discussions"><![CDATA[Discussions]]></string>
+    <string name="_bx_forum_menu_item_title_manage_my"><![CDATA[My Discussions]]></string>
+    <string name="_bx_forum_menu_item_title_manage_all"><![CDATA[All Discussions]]></string>
+    <string name="_bx_forum_menu_item_title_system_discussions"><![CDATA[Discussions number]]></string>
+    <string name="_bx_forum_menu_item_title_discussions"><![CDATA[Discussions]]></string>
+    <string name="_bx_forum_lmi_cpt_categories"><![CDATA[Categories]]></string>
+    <string name="_bx_forum_menu_title_snippet_meta_main"><![CDATA[Snippet Meta Info: Main]]></string>
+    <string name="_bx_forum_menu_set_title_snippet_meta_main"><![CDATA[Snippet Meta Info: Main]]></string>
+    <string name="_bx_forum_menu_title_snippet_meta_counters"><![CDATA[Snippet Meta Info: Counters]]></string>
+    <string name="_bx_forum_menu_set_title_snippet_meta_counters"><![CDATA[Snippet Meta Info: Counters]]></string>
+    <string name="_bx_forum_menu_title_snippet_meta_reply"><![CDATA[Snippet Meta Info: Reply]]></string>
+    <string name="_bx_forum_menu_set_title_snippet_meta_reply"><![CDATA[Snippet Meta Info: Reply]]></string>
+    <string name="_bx_forum_menu_item_title_system_sm_reply_text"><![CDATA[Reply text]]></string>
+    <string name="_bx_forum_menu_item_title_sm_reply_text"><![CDATA[Reply text]]></string>
+    <string name="_bx_forum_menu_item_title_system_sm_status"><![CDATA[Status]]></string>
+    <string name="_bx_forum_menu_item_title_sm_status"><![CDATA[Status]]></string>
+    <string name="_bx_forum_menu_item_title_system_sm_badges"><![CDATA[Badges]]></string>
+    <string name="_bx_forum_menu_item_title_sm_badges"><![CDATA[Badges]]></string>
+    <string name="_bx_forum_menu_title_categories"><![CDATA[Categories]]></string>
+  
+
+    <string name="_bx_forum_grid_filter_item_title_adm_select_one_filter1"><![CDATA[All Statuses]]></string>
+    <string name="_bx_forum_grid_filter_item_title_adm_select_one_filter2"><![CDATA[Any Audience]]></string>
+    <string name="_bx_forum_grid_filter_item_title_adm_active"><![CDATA[Active]]></string>
+    <string name="_bx_forum_grid_filter_item_title_adm_hidden"><![CDATA[Hidden]]></string>
+    <string name="_bx_forum_grid_filter_item_title_adm_pending"><![CDATA[Pending]]></string>
+    <string name="_bx_forum_grid_column_title_adm_active"><![CDATA[Active]]></string>
+    <string name="_bx_forum_grid_column_title_adm_title"><![CDATA[Title]]></string>
+    <string name="_bx_forum_grid_column_title_adm_added"><![CDATA[Added]]></string>
+    <string name="_bx_forum_grid_column_title_adm_author"><![CDATA[Author]]></string>
+    <string name="_bx_forum_grid_column_title_title"><![CDATA[Category]]></string>
+    <string name="_bx_forum_grid_column_title_visible_for_levels"><![CDATA[Visible For]]></string>
+    <string name="_bx_forum_grid_column_title_icon"><![CDATA[Icon]]></string>
+    <string name="_bx_forum_grid_action_title_edit"><![CDATA[Edit]]></string>
+    <string name="_bx_forum_grid_action_title_adm_edit"><![CDATA[Edit]]></string>
+    <string name="_bx_forum_grid_action_title_adm_delete"><![CDATA[Delete]]></string>
+    <string name="_bx_forum_grid_action_title_adm_clear_reports"><![CDATA[Clear reports]]></string>
+    <string name="_bx_forum_grid_action_title_adm_more_actions"><![CDATA[More Actions]]></string>
+    <string name="_bx_forum_grid_action_title_adm_audit_content"><![CDATA[Audit actions]]></string>
+    <string name="_bx_forum_grid_action_title_add"><![CDATA[New discussion]]></string>
+    <string name="_bx_forum_grid_action_title_show_to"><![CDATA[Show To]]></string>
+    <string name="_bx_forum_grid_column_title_adm_status_admin"><![CDATA[Moderation]]></string>
+    <string name="_bx_forum_grid_action_err_delete"><![CDATA[Cannot delete the selected discussion(s).]]></string>
+    <string name="_bx_forum_grid_txt_account_manager"><![CDATA[Redirect to manage account.]]></string>
+    <string name="_bx_forum_grid_txt_manage_visibility"><![CDATA[Manage visibility settings.]]></string>
+    <string name="_bx_forum_grid_show_to_popup"><![CDATA[Show category to:]]></string>
+    <string name="_bx_forum_grid_txt_visible_for"><![CDATA[Visible For]]></string>
+    <string name="_bx_forum_grid_txt_visible_for_all"><![CDATA[Anyone]]></string>
+    <string name="_bx_forum_grid_txt_visible_for_levels"><![CDATA[Select Levels]]></string>
+    <string name="_bx_forum_grid_txt_visible_for_selected"><![CDATA[Selected levels]]></string>
+    <string name="_bx_forum_grid_inf_visible_for_levels"><![CDATA[Select user levels that can view this category]]></string>
+    <string name="_bx_forum_grid_err_show_to"><![CDATA[Cannot update category.]]></string>
+    <string name="_bx_forum_grid_edit_popup"><![CDATA[Edit category]]></string>
+    <string name="_bx_forum_grid_err_items_icon_image_remove"><![CDATA[Cannot remove icon image: ]]></string>
+    <string name="_bx_forum_grid_err_items_icon_image"><![CDATA[Cannot process image: ]]></string>
+    <string name="_bx_forum_grid_form_txt_badges_icon"><![CDATA[Icon]]></string>
+    <string name="_bx_forum_grid_form_txt_badges_icon_image"><![CDATA[]]></string>
+    <string name="_bx_forum_grid_form_txt_badges_icon_image_new"><![CDATA[]]></string>
+    <string name="_bx_forum_grid_form_txt_badges_icon_image_old"><![CDATA[Current Icon]]></string>
+    <string name="_bx_forum_grid_form_dsc_badges_icon"><![CDATA[You may use: 1) font icon, 2) Inline SVG code, 3) Emoji]]></string>
+    <string name="_bx_forum_grid_form_dsc_badges_icon_image"><![CDATA[or upload a small image to be displayed near the link.]]></string>
+    <string name="_bx_forum_grid_form_dsc_badges_icon_image_current"><![CDATA[No icon uploaded. Text is used in menu item.]]></string>
+    <string name="_bx_forum_grid_form_btn_badges_submit"><![CDATA[Submit]]></string>
+    <string name="_bx_forum_grid_form_btn_badges_cancel"><![CDATA[Cancel]]></string>
+    
+    <string name="_bx_forum_grid_filter_resolved_all"><![CDATA[Any status]]></string>
+    <string name="_bx_forum_grid_filter_badges_all"><![CDATA[All badges]]></string>
+    <string name="_bx_forum_grid_filter_resolved_resolved"><![CDATA[Resolved]]></string>
+    <string name="_bx_forum_grid_filter_resolved_unresolved"><![CDATA[Unresolved]]></string>
+    
+    <string name="_bx_forum_grid_filter_order_recent"><![CDATA[Recent Posts]]></string>
+    <string name="_bx_forum_grid_filter_order_new"><![CDATA[New]]></string>
+    <string name="_bx_forum_grid_filter_order_top"><![CDATA[Top]]></string>
+    <string name="_bx_forum_grid_filter_order_updated"><![CDATA[Updated]]></string>
+    <string name="_bx_forum_grid_filter_order_popular"><![CDATA[Popular]]></string>
+    <string name="_bx_forum_grid_filter_order_featured"><![CDATA[Featured]]></string>
+    <string name="_bx_forum_grid_filter_order_favorite"><![CDATA[Favorite]]></string>
+    <string name="_bx_forum_grid_filter_order_partaken"><![CDATA[Partaken]]></string>
+    
+    <string name="_bx_forum_grid_btn_save"><![CDATA[Save]]></string>
+    <string name="_bx_forum_grid_btn_cancel"><![CDATA[Cancel]]></string>
+
+    <string name="_bx_forum_pre_lists_cats"><![CDATA[Forum categories]]></string>
+    <string name="_bx_forum_cat_General"><![CDATA[General]]></string>
+
+    <string name="_bx_forum_chart_growth"><![CDATA[Discussions: Growth]]></string>
+    <string name="_bx_forum_chart_growth_speed"><![CDATA[Discussions: Growth Speed]]></string>
+
+    <string name="_bx_forum_search_extended"><![CDATA[Discussions Search]]></string>
+    <string name="_bx_forum_search_extended_cmts"><![CDATA[Discussions Comments Search]]></string>
+
+    <string name="_bx_forum_txt_all_categories"><![CDATA[All Categories]]></string>
+    <string name="_bx_forum_txt_msg_status_hidden"><![CDATA[This discussion was hidden.]]></string>
+    <string name="_bx_forum_txt_msg_status_pending"><![CDATA[This discussion is pending approval.]]></string>
+    <string name="_bx_forum_err_not_found"><![CDATA[Discussion wasn't found.]]></string>
+    <string name="_bx_forum_more"><![CDATA[{0} more]]></string>
+    <string name="_bx_forum_participant_author"><![CDATA[author]]></string>
+    <string name="_bx_forum_participant_last_replier"><![CDATA[last replier]]></string>
+    <string name="_bx_forum_txt_entry_locked"><![CDATA[Locked discussion]]></string>
+    <string name="_bx_forum_txt_entry_sticked"><![CDATA[Pinned discussion]]></string>
+    <string name="_bx_forum_txt_sample_comment_single"><![CDATA[comment to discussion]]></string>
+    <string name="_bx_forum_txt_sample_vote_single"><![CDATA[vote to discussion]]></string>
+    <string name="_bx_forum_txt_sample_reaction_single"><![CDATA['{0}' reaction to discussion]]></string>
+    <string name="_bx_forum_txt_sample_score_up_single"><![CDATA[score up vote to discussion]]></string>
+    <string name="_bx_forum_txt_sample_score_down_single"><![CDATA[score down vote to discussion]]></string>
+    <string name="_bx_forum_txt_sample_single"><![CDATA[discussion]]></string>
+    <string name="_bx_forum_txt_sample_single_with_article"><![CDATA[a discussion]]></string>
+
+    <string name="_bx_forum_txt_poll_view_answers"><![CDATA[poll]]></string>
+    <string name="_bx_forum_txt_poll_view_results"><![CDATA[results]]></string>
+    <string name="_bx_forum_txt_poll_answer_vote_do_by"><![CDATA[Voted for]]></string>
+    <string name="_bx_forum_txt_poll_answer_vote_counter"><![CDATA[{0} votes]]></string>
+    <string name="_bx_forum_txt_poll_answer_vote_percent"><![CDATA[({0}%)]]></string>
+
+    <string name="_bx_forum_txt_all_entries_in"><![CDATA[<a href="{0}">All Discussions in {1} ({2})</a>]]></string>
+    <string name="_bx_forum_email_new_reply"><![CDATA[New reply]]></string>
+    <string name="_bx_forum_email_new_reply_subject"><![CDATA[New reply in "{PageTitle}" discussion]]></string>
+    <string name="_bx_forum_email_new_reply_body"><![CDATA[{email_header}
+<p>New reply in <a href="{PageUrl}">{PageTitle}</a> discussion from <a href="{SenderUrl}">{SenderDisplayName}</a>:</p>
+<hr />
+<p>{Message}</p>
+{email_footer}]]></string>
+</resources>

+ 652 - 0
modules/boonex/forum/updates/13.0.2_13.0.3/source/install/sql/enable.sql

@@ -0,0 +1,652 @@
+SET @sName = 'bx_forum';
+
+
+-- SETTINGS
+SET @iTypeOrder = (SELECT MAX(`order`) FROM `sys_options_types` WHERE `group` = 'modules');
+INSERT INTO `sys_options_types`(`group`, `name`, `caption`, `icon`, `order`) VALUES 
+('modules', @sName, '_bx_forum', 'bx_forum@modules/boonex/forum/|std-icon.svg', IF(ISNULL(@iTypeOrder), 1, @iTypeOrder + 1));
+SET @iTypeId = LAST_INSERT_ID();
+
+INSERT INTO `sys_options_categories` (`type_id`, `name`, `caption`, `order`)
+VALUES (@iTypeId, @sName, '_bx_forum', 1);
+SET @iCategId = LAST_INSERT_ID();
+
+INSERT INTO `sys_options` (`name`, `value`, `category_id`, `caption`, `type`, `check`, `check_error`, `extra`, `order`) VALUES
+('bx_forum_enable_auto_approve', 'on', @iCategId, '_bx_forum_option_enable_auto_approve', 'checkbox', '', '', '', 0),
+('bx_forum_summary_chars', '700', @iCategId, '_bx_forum_option_summary_chars', 'digit', '', '', '', 1),
+('bx_forum_plain_summary_chars', '240', @iCategId, '_bx_forum_option_plain_summary_chars', 'digit', '', '', '', 2),
+('bx_forum_per_page_browse', '12', @iCategId, '_bx_forum_option_per_page_browse', 'digit', '', '', '', 10),
+('bx_forum_per_page_index', '6', @iCategId, '_bx_forum_option_per_page_index', 'digit', '', '', '', 11),
+('bx_forum_per_page_profile', '6', @iCategId, '_bx_forum_option_per_page_profile', 'digit', '', '', '', 12),
+('bx_forum_per_page_for_favorites_lists', '5', @iCategId, '_bx_forum_option_per_page_for_favorites_lists', 'digit', '', '', '', 17),
+('bx_forum_rss_num', '10', @iCategId, '_bx_forum_option_rss_num', 'digit', '', '', '', 20),
+('bx_forum_searchable_fields', 'title,text,text_comments', @iCategId, '_bx_forum_option_searchable_fields', 'list', '', '', 'a:2:{s:6:"module";s:8:"bx_forum";s:6:"method";s:21:"get_searchable_fields";}', 30),
+('bx_forum_auto_activation_for_categories', 'on', @iCategId, '_bx_forum_option_auto_activation_for_categories', 'checkbox', '', '', '', 35),
+('bx_forum_visible_categories', '10', @iCategId, '_bx_forum_option_visible_categories', 'digit', '', '', '', 40);
+-- ('bx_forum_autosubscribe_created', '', @iCategId, '_bx_forum_option_autosubscribe_created', 'checkbox', '', '', '', 40),
+-- ('bx_forum_autosubscribe_replied', '', @iCategId, '_bx_forum_option_autosubscribe_replied', 'checkbox', '', '', '', 41),
+
+
+
+-- 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_forum_create_entry', '_bx_forum_page_title_sys_create_entry', '_bx_forum_page_title_create_entry', @sName, 5, 2147483647, 1, 'create-discussion', 'page.php?i=create-discussion', '', '', '', 0, 1, 0, 'BxForumPageBrowse', 'modules/boonex/forum/classes/BxForumPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks` (`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES
+('bx_forum_create_entry', 1, @sName, '_bx_forum_page_block_title_create_entry', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:8:"bx_forum";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_forum_edit_entry', '_bx_forum_page_title_sys_edit_entry', '_bx_forum_page_title_edit_entry', @sName, 5, 2147483647, 1, 'edit-discussion', '', '', '', '', 0, 1, 0, 'BxForumPageEntry', 'modules/boonex/forum/classes/BxForumPageEntry.php');
+
+INSERT INTO `sys_pages_blocks` (`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES
+('bx_forum_edit_entry', 1, @sName, '_bx_forum_page_block_title_edit_entry', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:8:"bx_forum";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_forum_delete_entry', '_bx_forum_page_title_sys_delete_entry', '_bx_forum_page_title_delete_entry', @sName, 5, 2147483647, 1, 'delete-discussion', '', '', '', '', 0, 1, 0, 'BxForumPageEntry', 'modules/boonex/forum/classes/BxForumPageEntry.php');
+
+INSERT INTO `sys_pages_blocks` (`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES
+('bx_forum_delete_entry', 1, @sName, '_bx_forum_page_block_title_delete_entry', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:8:"bx_forum";s:6:"method";s:13:"entity_delete";}', 0, 0, 0);
+
+-- PAGE: view entry
+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_forum_view_entry', 'view-discussion', '_bx_forum_page_title_sys_view_entry', '_bx_forum_page_title_view_entry', @sName, 12, 2147483647, 1, '', '', '', '', 0, 1, 0, 'BxForumPageEntry', 'modules/boonex/forum/classes/BxForumPageEntry.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_forum_view_entry', 1, @sName,'', '_bx_forum_page_block_title_entry_breadcrumb', 13, 2147483647, 'service', 'a:2:{s:6:"module";s:8:"bx_forum";s:6:"method";s:17:"entity_breadcrumb";}', 0, 0, 1, 1),
+('bx_forum_view_entry', 3, @sName,'', '_bx_forum_page_block_title_entry_author', 13, 2147483647, 'service', 'a:2:{s:6:"module";s:8:"bx_forum";s:6:"method";s:13:"entity_author";}', 0, 0, 1, 1),
+('bx_forum_view_entry', 3, @sName, '_bx_forum_page_block_title_sys_entry_context', '_bx_forum_page_block_title_entry_context', 13, 2147483647, 'service', 'a:2:{s:6:\"module\";s:8:\"bx_forum\";s:6:\"method\";s:14:\"entity_context\";}', 0, 0, 1, 2),
+('bx_forum_view_entry', 3, @sName,'', '_bx_forum_page_block_title_entry_participants', 13, 2147483647, 'service', 'a:2:{s:6:"module";s:8:"bx_forum";s:6:"method";s:19:"entity_participants";}', 0, 0, 1, 3),
+('bx_forum_view_entry', 3, @sName, '', '_bx_forum_page_block_title_entry_info', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:8:\"bx_forum\";s:6:\"method\";s:11:\"entity_info\";}', 0, 0, 0, 0),
+('bx_forum_view_entry', 2, @sName,'', '_bx_forum_page_block_title_entry_text', 13, 2147483647, 'service', 'a:2:{s:6:"module";s:8:"bx_forum";s:6:"method";s:17:"entity_text_block";}', 0, 0, 1, 1),
+('bx_forum_view_entry', 1, @sName,'', '_bx_forum_page_block_title_entry_all_actions', 13, 2147483647, 'service', 'a:2:{s:6:"module";s:8:"bx_forum";s:6:"method";s:18:"entity_all_actions";}', 0, 0, 1, 2),
+('bx_forum_view_entry', 2, @sName,'', '_bx_forum_page_block_title_entry_attachments', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:8:"bx_forum";s:6:"method";s:18:"entity_attachments";}', 0, 0, 1, 2),
+('bx_forum_view_entry', 2, @sName, '', '_bx_forum_page_block_title_entry_polls', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:8:"bx_forum";s:6:"method";s:12:"entity_polls";}', 0, 0, 1, 3),
+('bx_forum_view_entry', 2, @sName,'', '_bx_forum_page_block_title_entry_comments', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:8:"bx_forum";s:6:"method";s:15:"entity_comments";}', 0, 0, 1, 4),
+('bx_forum_view_entry', 2, @sName, '', '_bx_forum_page_block_title_entry_reports', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:8:\"bx_forum\";s:6:\"method\";s:14:\"entity_reports\";}', 0, 0, 1, 6);
+
+
+
+-- PAGE: new 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_forum_new', '_bx_forum_page_title_sys_entries_new', '_bx_forum_page_title_entries_new', @sName, 5, 2147483647, 1, 'discussions-new', 'page.php?i=discussions-new', '', '', '', 0, 1, 0, 'BxForumPageBrowse', 'modules/boonex/forum/classes/BxForumPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_forum_new', 1, @sName, '_bx_forum_page_block_title_new_entries', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:8:"bx_forum";s:6:"method";s:10:"browse_new";s:6:"params";a:1:{i:0;s:5:"table";}}', 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_forum_top', '_bx_forum_page_title_sys_entries_top', '_bx_forum_page_title_entries_top', @sName, 5, 2147483647, 1, 'discussions-top', 'page.php?i=discussions-top', '', '', '', 0, 1, 0, 'BxForumPageBrowse', 'modules/boonex/forum/classes/BxForumPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_forum_top', 1, @sName, '_bx_forum_page_block_title_top_entries', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:8:"bx_forum";s:6:"method";s:10:"browse_top";s:6:"params";a:1:{i:0;s:5:"table";}}', 0, 1, 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_forum_popular', '_bx_forum_page_title_sys_entries_popular', '_bx_forum_page_title_entries_popular', @sName, 5, 2147483647, 1, 'discussions-popular', 'page.php?i=discussions-popular', '', '', '', 0, 1, 0, 'BxForumPageBrowse', 'modules/boonex/forum/classes/BxForumPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_forum_popular', 1, @sName, '_bx_forum_page_block_title_popular_entries', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:8:"bx_forum";s:6:"method";s:14:"browse_popular";s:6:"params";a:1:{i:0;s:5:"table";}}', 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_forum_updated', '_bx_forum_page_title_sys_entries_updated', '_bx_forum_page_title_entries_updated', @sName, 5, 2147483647, 1, 'discussions-updated', 'page.php?i=discussions-updated', '', '', '', 0, 1, 0, 'BxForumPageBrowse', 'modules/boonex/forum/classes/BxForumPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_forum_updated', 1, @sName, '_bx_forum_page_block_title_updated_entries', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:8:"bx_forum";s:6:"method";s:14:"browse_updated";s:6:"params";a:1:{i:0;s:5:"table";}}', 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_forum_partaken', '_bx_forum_page_title_sys_entries_partaken', '_bx_forum_page_title_entries_partaken', @sName, 5, 2147483647, 1, 'discussions-partaken', 'page.php?i=discussions-partaken', '', '', '', 0, 1, 0, 'BxForumPageBrowse', 'modules/boonex/forum/classes/BxForumPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_forum_partaken', 1, @sName, '_bx_forum_page_block_title_partaken_entries', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:8:"bx_forum";s:6:"method";s:15:"browse_partaken";s:6:"params";a:1:{i:0;s:5:"table";}}', 0, 1, 1);
+
+-- PAGE: categories
+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_forum_categories', 'discussions-categories', '_bx_forum_page_title_sys_entries_categories', '_bx_forum_page_title_entries_categories', @sName, 5, 2147483647, 1, 'page.php?i=discussions-categories', '', '', '', 0, 1, 0, 'BxForumPageBrowse', 'modules/boonex/forum/classes/BxForumPageBrowse.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_forum_categories', 1, @sName, '', '_bx_forum_page_block_title_entries_categories', 13, 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_forum_cats";i:1;a:1:{s:10:"show_empty";b:1;}}s:5:"class";s:20:"TemplServiceCategory";}', 0, 0, 1, 0);
+
+-- PAGE: entries by category
+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_forum_category', 'discussions-category', '_bx_forum_page_title_sys_entries_by_category', '_bx_forum_page_title_entries_by_category', @sName, 1, 2147483647, 1, 'page.php?i=discussions-category', '', '', '', 0, 1, 0, 'BxForumPageBrowse', 'modules/boonex/forum/classes/BxForumPageBrowse.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_forum_category', 2, @sName, '_bx_forum_page_block_title_sys_entries_by_category', '_bx_forum_page_block_title_entries_by_category', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:8:"bx_forum";s:6:"method";s:15:"browse_category";s:6:"params";a:1:{i:0;s:5:"table";}}', 0, 0, 1, 1),
+('bx_forum_category', 1, @sName, '', '_bx_forum_page_block_title_cats', 11, 2147483647, 'menu', 'bx_forum_categories', 0, 0, 1, 1);
+
+-- PAGE: entries by keyword
+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_forum_keyword', 'discussions-keyword', '_bx_forum_page_title_sys_entries_by_keyword', '_bx_forum_page_title_entries_by_keyword', @sName, 5, 2147483647, 1, 'page.php?i=discussions-keyword', '', '', '', 0, 1, 0, 'BxForumPageBrowse', 'modules/boonex/forum/classes/BxForumPageBrowse.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_forum_keyword', 1, @sName, '_bx_forum_page_block_title_sys_entries_by_keyword', '_bx_forum_page_block_title_entries_by_keyword', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:8:"bx_forum";s:6:"method";s:14:"browse_keyword";s:6:"params";a:1:{i:0;s:5:"table";}}', 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_forum_author', 'discussions-author', '_bx_forum_page_title_sys_entries_of_author', '_bx_forum_page_title_entries_of_author', @sName, 5, 2147483647, 1, 'page.php?i=discussions-author', '', '', '', 0, 1, 0, 'BxForumPageAuthor', 'modules/boonex/forum/classes/BxForumPageAuthor.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_forum_author', 1, @sName, '', '_bx_forum_page_block_title_entries_actions', 13, 2147483647, 'service', 'a:2:{s:6:"module";s:8:"bx_forum";s:6:"method";s:18:"my_entries_actions";}', 0, 0, 1, 1),
+('bx_forum_author', 1, @sName, '_bx_forum_page_block_title_sys_favorites_of_author', '_bx_forum_page_block_title_favorites_of_author', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:8:"bx_forum";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_forum_author', 1, @sName, '_bx_forum_page_block_title_sys_entries_of_author', '_bx_forum_page_block_title_entries_of_author', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:8:"bx_forum";s:6:"method";s:13:"browse_author";}', 0, 0, 1, 3),
+('bx_forum_author', 1, @sName, '_bx_forum_page_block_title_sys_entries_in_context', '_bx_forum_page_block_title_entries_in_context', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:8:"bx_forum";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_forum_favorites', '_bx_forum_page_title_sys_entries_favorites', '_bx_forum_page_title_entries_favorites', @sName, 12, 2147483647, 1, 'discussions-favorites', 'page.php?i=discussions-favorites', '', '', '', 0, 1, 0, 'BxForumPageListEntry', 'modules/boonex/forum/classes/BxForumPageListEntry.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_forum_favorites', 2, @sName, '_bx_forum_page_block_title_sys_favorites_entries', '_bx_forum_page_block_title_favorites_entries', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:8:"bx_forum";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_forum_favorites', 3, @sName, '', '_bx_forum_page_block_title_favorites_entries_info', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:8:"bx_forum";s:6:"method";s:19:"favorites_list_info";}', 0, 0, 0),
+('bx_forum_favorites', 3, @sName, '', '_bx_forum_page_block_title_favorites_entries_actions', 13, 2147483647, 'service', 'a:2:{s:6:"module";s:8:"bx_forum";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_forum_context', 'discussions-context', '_bx_forum_page_title_sys_entries_in_context', '_bx_forum_page_title_entries_in_context', 'bx_forum', 5, 2147483647, 1, '', '', '', '', 0, 1, 0, 'BxForumPageAuthor', 'modules/boonex/forum/classes/BxForumPageAuthor.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_forum_context', 1, @sName, '_bx_forum_page_block_title_sys_entries_in_context', '_bx_forum_page_block_title_entries_in_context', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:8:\"bx_forum\";s:6:\"method\";s:14:\"browse_context\";}', 0, 0, 1, 1),
+('bx_forum_context', 1, @sName, '_bx_forum_page_block_title_sys_multi_categories_in_context', '_bx_forum_page_block_title_multi_categories_in_context', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:8:\"bx_forum\";s:6:\"method\";s:29:\"categories_multi_list_context\";}', 0, 0, 0, 2);
+
+-- PAGE: module home
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `cover`, `cover_image`, `type_id`, `layout_id`, `submenu`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `inj_head`, `inj_footer`, `sticky_columns`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_forum_home', 'discussions-home', '_bx_forum_page_title_sys_home', '_bx_forum_page_title_home', @sName, 1, 0, 1, 6, '', 2147483647, 1, 'page.php?i=discussions-home', '', '', '', 0, 1, '', '', 0, 0, 'BxForumPageBrowse', 'modules/boonex/forum/classes/BxForumPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `async`, `cache_lifetime`, `submenu`, `tabs`, `hidden_on`, `visible_for_levels`, `type`, `content`, `help`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_forum_home', 1, @sName, '_bx_forum_page_block_title_sys_featured_entries_view_showcase', '_bx_forum_page_block_title_featured_entries_view_showcase', 0, 0, NULL, '', 0, '', 2147483647, 'service', 'a:3:{s:6:\"module\";s:8:\"bx_forum\";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;}}', NULL, 0, 1, 1, 0),
+('bx_forum_home', 2, @sName, '', '_bx_forum_page_block_title_cats', 11, 0, NULL, '', 0, 0, 2147483647, 'menu', 'bx_forum_categories', NULL, 0, 1, 1, 0),
+('bx_forum_home', 2, @sName, '_bx_forum_page_block_title_sys_multicats', '_bx_forum_page_block_title_multicats', 11, 0, NULL, '', 0, '', 2147483647, 'service', 'a:2:{s:6:\"module\";s:8:\"bx_forum\";s:6:\"method\";s:21:\"categories_multi_list\";}', NULL, 0, 1, 0, 1),
+('bx_forum_home', 3, @sName, '', '_bx_forum_page_block_title_home', 11, 0, NULL, '', 0, '', 2147483647, 'service', 'a:3:{s:6:\"module\";s:8:\"bx_forum\";s:6:\"method\";s:13:\"browse_latest\";s:6:\"params\";a:3:{i:0;s:5:\"table\";i:1;b:1;i:2;b:0;}}', NULL, 0, 1, 1, 1),
+('bx_forum_home', 2, @sName, '', '_bx_forum_page_block_title_browse_labels', 11, 0, NULL, '', 0, '', 2147483647, 'service', 'a:3:{s:6:\"module\";s:6:\"system\";s:6:\"method\";s:13:\"browse_labels\";s:5:\"class\";s:20:\"TemplServiceMetatags\";}', NULL, 0, 1, 0, 2),
+('bx_forum_home', 2, @sName, '', '_bx_forum_page_block_title_popular_keywords', 11, 0, NULL, '', 0, '', 2147483647, 'service', 'a:4:{s:6:\"module\";s:6:\"system\";s:6:\"method\";s:14:\"keywords_cloud\";s:6:\"params\";a:3:{i:0;s:8:\"bx_forum\";i:1;s:8:\"bx_forum\";i:2;a:1:{s:9:\"menu_view\";b:1;}}s:5:\"class\";s:20:\"TemplServiceMetatags\";}', NULL, 0, 1, 1, 3),
+('bx_forum_home', 2, @sName, '_bx_forum_page_block_title_popular_entries_view_extended', '_bx_forum_page_block_title_popular_entries', 11, 0, NULL, '', 0, '', 2147483647, 'service', 'a:3:{s:6:\"module\";s:8:\"bx_forum\";s:6:\"method\";s:14:\"browse_popular\";s:6:\"params\";a:1:{i:0;s:8:\"extended\";}}', NULL, 0, 1, 1, 3);
+
+
+
+-- PAGE: module search
+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_forum_search', 'discussions-search', '_bx_forum_page_title_sys_entries_search', '_bx_forum_page_title_entries_search', @sName, 5, 2147483647, 1, 'page.php?i=discussions-search', '', '', '', 0, 1, 0, 'BxForumPageBrowse', 'modules/boonex/forum/classes/BxForumPageBrowse.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_forum_search', 1, @sName, '', '_bx_forum_page_block_title_entries_search_form', 13, 2147483647, 'service', 'a:2:{s:6:"module";s:8:"bx_forum";s:6:"method";s:6:"search";}', 0, 0, 1, 0),
+('bx_forum_search', 1, @sName, '', '_bx_forum_page_block_title_entries_search_results', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:8:"bx_forum";s:6:"method";s:21:"browse_search_results";s:6:"params";a:1:{i:0;s:5:"table";}}', 0, 0, 1, 1),
+('bx_forum_search', 1, @sName, '', '_bx_forum_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_forum";}}s:5:"class";s:27:"TemplSearchExtendedServices";}', 0, 1, 0, 2),
+('bx_forum_search', 1, @sName, '', '_bx_forum_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_forum";s:10:"show_empty";b:1;}}s:5:"class";s:27:"TemplSearchExtendedServices";}', 0, 1, 0, 3),
+('bx_forum_search', 1, @sName, '', '_bx_forum_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_forum_cmts";}}s:5:"class";s:27:"TemplSearchExtendedServices";}', 0, 1, 0, 4),
+('bx_forum_search', 1, @sName, '', '_bx_forum_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_forum_cmts";s:10:"show_empty";b:1;}}s:5:"class";s:27:"TemplSearchExtendedServices";}', 0, 1, 0, 5);
+
+-- 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_forum_manage', '_bx_forum_page_title_sys_manage', '_bx_forum_page_title_manage', @sName, 5, 2147483647, 1, 'discussions-manage', 'page.php?i=discussions-manage', '', '', '', 0, 1, 0, 'BxForumPageBrowse', 'modules/boonex/forum/classes/BxForumPageBrowse.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_forum_manage', 1, @sName, '_bx_forum_page_block_title_system_manage', '_bx_forum_page_block_title_manage', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:8:"bx_forum";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_forum_administration', '_bx_forum_page_title_sys_manage_administration', '_bx_forum_page_title_manage', @sName, 5, 192, 1, 'discussions-administration', 'page.php?i=discussions-administration', '', '', '', 0, 1, 0, 'BxForumPageBrowse', 'modules/boonex/forum/classes/BxForumPageBrowse.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_forum_administration', 1, @sName, '_bx_forum_page_block_title_system_manage_administration', '_bx_forum_page_block_title_manage', 11, 192, 'service', 'a:3:{s:6:"module";s:8:"bx_forum";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, @sName, '_bx_forum_page_block_title_new_entries', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:8:"bx_forum";s:6:"method";s:12:"browse_index";s:6:"params";a:4:{i:0;s:5:"table";i:1;b:0;i:2;b:1;i:3;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 = 2;
+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, @sName, '_bx_forum_page_block_title_sys_my_entries', '_bx_forum_page_block_title_my_entries', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:8:"bx_forum";s:6:"method";s:13:"browse_author";s:6:"params";a:2:{i:0;s:12:"{profile_id}";i:1;a:1:{s:13:"empty_message";b:0;}}}', 0, 0, 0);
+
+-- 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`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('', 0, @sName, '_bx_forum_page_block_title_latest_entries', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:8:"bx_forum";s:6:"method";s:13:"browse_latest";s:6:"params";a:3:{i:0;s:7:"gallery";i:1;b:1;i:2;b:0;}}', 0, 1, IFNULL(@iBlockOrder, 0) + 1),
+('', 0, @sName, '_bx_forum_page_block_title_latest_entries_view_full', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:8:"bx_forum";s:6:"method";s:13:"browse_latest";s:6:"params";a:1:{i:0;s:4:"full";}}', 0, 1, IFNULL(@iBlockOrder, 0) + 2),
+('', 0, @sName, '_bx_forum_page_block_title_new_entries', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:8:"bx_forum";s:6:"method";s:10:"browse_new";s:6:"params";a:3:{i:0;s:7:"gallery";i:1;b:1;i:2;b:0;}}', 0, 1, IFNULL(@iBlockOrder, 0) + 3),
+('', 0, @sName, '_bx_forum_page_block_title_new_entries_view_full', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:8:"bx_forum";s:6:"method";s:10:"browse_new";s:6:"params";a:1:{i:0;s:4:"full";}}', 0, 1, IFNULL(@iBlockOrder, 0) + 4),
+('', 0, @sName, '_bx_forum_page_block_title_top_entries_view_extended', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:8:"bx_forum";s:6:"method";s:10:"browse_top";s:6:"params";a:1:{i:0;s:8:"extended";}}', 0, 1, IFNULL(@iBlockOrder, 0) + 5),
+('', 0, @sName, '_bx_forum_page_block_title_top_entries_view_full', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:8:"bx_forum";s:6:"method";s:10:"browse_top";s:6:"params";a:1:{i:0;s:4:"full";}}', 0, 1, IFNULL(@iBlockOrder, 0) + 6),
+('', 0, @sName, '_bx_forum_page_block_title_popular_entries_view_extended', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:8:"bx_forum";s:6:"method";s:14:"browse_popular";s:6:"params";a:1:{i:0;s:8:"extended";}}', 0, 1, IFNULL(@iBlockOrder, 0) + 7),
+('', 0, @sName, '_bx_forum_page_block_title_popular_entries_view_full', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:8:"bx_forum";s:6:"method";s:14:"browse_popular";s:6:"params";a:1:{i:0;s:4:"full";}}', 0, 1, IFNULL(@iBlockOrder, 0) + 8);
+
+
+-- 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', @sName, 'discussions-home', '_bx_forum_menu_item_title_system_entries_home', '_bx_forum_menu_item_title_entries_home', 'page.php?i=discussions-home', '', '', 'far comments col-blue2', 'bx_forum_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', @sName, 'discussions-home', '_bx_forum_menu_item_title_system_entries_home', '_bx_forum_menu_item_title_entries_home', 'page.php?i=discussions-home', '', '', 'far comments col-blue2', 'bx_forum_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', @sName, 'create-discussion', '_bx_forum_menu_item_title_system_create_entry', '_bx_forum_menu_item_title_create_entry', 'page.php?i=create-discussion', '', '', 'far comments col-blue2', '', 2147483647, 1, 1, IFNULL(@iAddMenuOrder, 0) + 1);
+
+-- MENU: create post form attachments (link, photo, video, etc)
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_forum_entry_attachments', '_bx_forum_menu_title_entry_attachments', 'bx_forum_entry_attachments', @sName, 23, 0, 1, 'BxForumMenuAttachments', 'modules/boonex/forum/classes/BxForumMenuAttachments.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_forum_entry_attachments', @sName, '_bx_forum_menu_set_title_entry_attachments', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `addon`, `submenu_object`, `visible_for_levels`, `visibility_custom`, `active`, `copyable`, `editable`, `order`) VALUES 
+('bx_forum_entry_attachments', @sName, 'photo_simple', '_bx_forum_menu_item_title_system_cpa_photo_simple', '_bx_forum_menu_item_title_cpa_photo_simple', 'javascript:void(0)', 'javascript:{js_object_uploader_photos_simple}.showUploaderForm();', '_self', 'camera', '', '', 2147483647, '', 0, 0, 1, 1),
+('bx_forum_entry_attachments', @sName, 'photo_html5', '_bx_forum_menu_item_title_system_cpa_photo_html5', '_bx_forum_menu_item_title_cpa_photo_html5', 'javascript:void(0)', 'javascript:{js_object_uploader_photos_html5}.showUploaderForm();', '_self', 'camera', '', '', 2147483647, '', 1, 0, 1, 2),
+('bx_forum_entry_attachments', @sName, 'video_simple', '_bx_forum_menu_item_title_system_cpa_video_simple', '_bx_forum_menu_item_title_cpa_video_simple', 'javascript:void(0)', 'javascript:{js_object_uploader_videos_simple}.showUploaderForm();', '_self', 'video', '', '', 2147483647, '', 0, 0, 1, 3),
+('bx_forum_entry_attachments', @sName, 'video_html5', '_bx_forum_menu_item_title_system_cpa_video_html5', '_bx_forum_menu_item_title_cpa_video_html5', 'javascript:void(0)', 'javascript:{js_object_uploader_videos_html5}.showUploaderForm();', '_self', 'video', '', '', 2147483647, '', 1, 0, 1, 4),
+('bx_forum_entry_attachments', @sName, 'video_record_video', '_bx_forum_menu_item_title_system_cpa_video_record', '_bx_forum_menu_item_title_cpa_video_record', 'javascript:void(0)', 'javascript:{js_object_uploader_videos_record_video}.showUploaderForm();', '_self', 'fas circle', '', '', 2147483647, '', 1, 0, 1, 5),
+('bx_forum_entry_attachments', @sName, 'file_simple', '_bx_forum_menu_item_title_system_cpa_file_simple', '_bx_forum_menu_item_title_cpa_file_simple', 'javascript:void(0)', 'javascript:{js_object_uploader_files_simple}.showUploaderForm();', '_self', 'file', '', '', 2147483647, '', 0, 0, 1, 6),
+('bx_forum_entry_attachments', @sName, 'file_html5', '_bx_forum_menu_item_title_system_cpa_file_html5', '_bx_forum_menu_item_title_cpa_file_html5', 'javascript:void(0)', 'javascript:{js_object_uploader_files_html5}.showUploaderForm();', '_self', 'file', '', '', 2147483647, '', 1, 0, 1, 7),
+('bx_forum_entry_attachments', @sName, 'poll', '_bx_forum_menu_item_title_system_cpa_poll', '_bx_forum_menu_item_title_cpa_poll', 'javascript:void(0)', 'javascript:{js_object}.showPollForm(this);', '_self', 'tasks', '', '', 2147483647, '', 1, 0, 1, 8),
+('bx_forum_entry_attachments', @sName, 'add-link', '_bx_forum_menu_item_title_system_add_link', '_bx_forum_menu_item_title_add_link', 'javascript:void(0)', 'javascript:{js_object_link}.showAttachLink(this);', '_self', 'link', '', '', 2147483647, '', 1, 0, 1, 10);
+
+-- 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_forum_view', '_bx_forum_menu_title_view_entry', 'bx_forum_view', @sName, 9, 0, 1, 'BxForumMenuView', 'modules/boonex/forum/classes/BxForumMenuView.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_forum_view', @sName, '_bx_forum_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_forum_view', @sName, 'subscribe-discussion', '_bx_forum_menu_item_title_system_subscribe', '_bx_forum_menu_item_title_subscribe', 'javascript:void(0)', 'bx_conn_action(this, \'bx_forum_subscribers\', \'add\', \'{content_id}\')', '', 'check', '', 0, 2147483647, 1, 0, 1),
+('bx_forum_view', @sName, 'resolve-discussion', '_bx_forum_menu_item_title_system_resolve_entry', '_bx_forum_menu_item_title_resolve_entry', 'javascript:void(0);', '{js_object}.updateStatus(this, \'resolve\', {content_id});', '', 'check-circle', '', 0, 2147483647, 1, 0, 1),
+('bx_forum_view', @sName, 'stick-discussion', '_bx_forum_menu_item_title_system_stick_entry', '_bx_forum_menu_item_title_stick_entry', 'javascript:void(0);', '{js_object}.updateStatus(this, \'stick\', {content_id});', '', 'thumbtack', '', 0, 2147483647, 1, 0, 2),
+('bx_forum_view', @sName, 'lock-discussion', '_bx_forum_menu_item_title_system_lock_entry', '_bx_forum_menu_item_title_lock_entry', 'javascript:void(0);', '{js_object}.updateStatus(this, \'lock\', {content_id});', '', 'lock', '', 0, 2147483647, 1, 0, 3),
+('bx_forum_view', @sName, 'hide-discussion', '_bx_forum_menu_item_title_system_hide_entry', '_bx_forum_menu_item_title_hide_entry', 'javascript:void(0);', '{js_object}.updateStatus(this, \'hide\', {content_id});', '', 'stop-circle', '', 0, 2147483647, 1, 0, 4),
+('bx_forum_view', @sName, 'approve', '_sys_menu_item_title_system_va_approve', '_sys_menu_item_title_va_approve', 'javascript:void(0)', 'javascript:bx_approve(this, ''{module_uri}'', {content_id});', '', 'check', '', 0, 2147483647, 1, 0, 5),
+('bx_forum_view', @sName, 'more', '_bx_forum_menu_item_title_system_more', '_bx_forum_menu_item_title_more', 'javascript:void(0)', 'bx_menu_popup(\'bx_forum_view_more\', this, {}, {id:{content_id}});', '', 'cog', 'bx_forum_view_more', 1, 2147483647, 1, 0, 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_forum_view_more', '_bx_forum_menu_title_view_more', 'bx_forum_view_more', @sName, 6, 0, 1, 'BxForumMenuView', 'modules/boonex/forum/classes/BxForumMenuView.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_forum_view_more', @sName, '_bx_forum_menu_set_title_view_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_forum_view_more', @sName, 'unsubscribe-discussion', '_bx_forum_menu_item_title_system_unsubscribe', '_bx_forum_menu_item_title_unsubscribe', 'javascript:void(0)', 'bx_conn_action(this, \'bx_forum_subscribers\', \'remove\', \'{content_id}\')', '', 'check', '', 2147483647, 1, 0, 1),
+('bx_forum_view_more', @sName, 'unresolve-discussion', '_bx_forum_menu_item_title_system_unresolve_entry', '_bx_forum_menu_item_title_unresolve_entry', 'javascript:void(0);', '{js_object}.updateStatus(this, \'unresolve\', {content_id});', '', 'check-circle', '', 2147483647, 1, 0, 1),
+('bx_forum_view_more', @sName, 'unstick-discussion', '_bx_forum_menu_item_title_system_unstick_entry', '_bx_forum_menu_item_title_unstick_entry', 'javascript:void(0);', '{js_object}.updateStatus(this, \'unstick\', {content_id});', '', 'thumbtack', '', 2147483647, 1, 0, 2),
+('bx_forum_view_more', @sName, 'unlock-discussion', '_bx_forum_menu_item_title_system_unlock_entry', '_bx_forum_menu_item_title_unlock_entry', 'javascript:void(0);', '{js_object}.updateStatus(this, \'unlock\', {content_id});', '', 'unlock', '', 2147483647, 1, 0, 3),
+('bx_forum_view_more', @sName, 'unhide-discussion', '_bx_forum_menu_item_title_system_unhide_entry', '_bx_forum_menu_item_title_unhide_entry', 'javascript:void(0);', '{js_object}.updateStatus(this, \'unhide\', {content_id});', '', 'play-circle', '', 2147483647, 1, 0, 4),
+('bx_forum_view_more', @sName, 'edit-discussion', '_bx_forum_menu_item_title_system_edit_entry', '_bx_forum_menu_item_title_edit_entry', 'page.php?i=edit-discussion&id={content_id}', '', '', 'pencil-alt', '', 2147483647, 1, 0, 5),
+('bx_forum_view_more', @sName, 'delete-discussion', '_bx_forum_menu_item_title_system_delete_entry', '_bx_forum_menu_item_title_delete_entry', 'page.php?i=delete-discussion&id={content_id}', '', '', 'remove', '', 2147483647, 1, 0, 6);
+
+-- 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_forum_view_actions', '_sys_menu_title_view_actions', 'bx_forum_view_actions', @sName, 15, 0, 1, 'BxForumMenuViewActions', 'modules/boonex/forum/classes/BxForumMenuViewActions.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_forum_view_actions', @sName, '_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_forum_view_actions', @sName, 'subscribe-discussion', '_bx_forum_menu_item_title_system_subscribe', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 10),
+-- ('bx_forum_view_actions', @sName, 'unsubscribe-discussion', '_bx_forum_menu_item_title_system_unsubscribe', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 20),
+('bx_forum_view_actions', @sName, 'resolve-discussion', '_bx_forum_menu_item_title_system_resolve_entry', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 20),
+('bx_forum_view_actions', @sName, 'unresolve-discussion', '_bx_forum_menu_item_title_system_unresolve_entry', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 25),
+('bx_forum_view_actions', @sName, 'stick-discussion', '_bx_forum_menu_item_title_system_stick_entry', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 30),
+('bx_forum_view_actions', @sName, 'unstick-discussion', '_bx_forum_menu_item_title_system_unstick_entry', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 40),
+('bx_forum_view_actions', @sName, 'lock-discussion', '_bx_forum_menu_item_title_system_lock_entry', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 50),
+('bx_forum_view_actions', @sName, 'unlock-discussion', '_bx_forum_menu_item_title_system_unlock_entry', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 60),
+('bx_forum_view_actions', @sName, 'hide-discussion', '_bx_forum_menu_item_title_system_hide_entry', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 70),
+('bx_forum_view_actions', @sName, 'unhide-discussion', '_bx_forum_menu_item_title_system_unhide_entry', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 80),
+('bx_forum_view_actions', @sName, 'edit-discussion', '_bx_forum_menu_item_title_system_edit_entry', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 90),
+('bx_forum_view_actions', @sName, 'delete-discussion', '_bx_forum_menu_item_title_system_delete_entry', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 100),
+('bx_forum_view_actions', @sName, 'approve', '_sys_menu_item_title_system_va_approve', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 100),
+('bx_forum_view_actions', @sName, '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_forum'', content_id: {content_id}});', '', 'check-circle', '', '', 0, 2147483647, 'a:2:{s:6:"module";s:8:"bx_forum";s:6:"method";s:19:"is_badges_avaliable";}', 1, 0, 110),
+('bx_forum_view_actions', @sName, 'comment', '_sys_menu_item_title_system_va_comment', '', '', '', '', '', '', '', 0, 2147483647, '', 0, 0, 200),
+('bx_forum_view_actions', @sName, 'view', '_sys_menu_item_title_system_va_view', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 210),
+('bx_forum_view_actions', @sName, 'vote', '_sys_menu_item_title_system_va_vote', '', '', '', '', '', '', '', 0, 2147483647, '', 0, 0, 220),
+('bx_forum_view_actions', @sName, 'reaction', '_sys_menu_item_title_system_va_reaction', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 225),
+('bx_forum_view_actions', @sName, 'score', '_sys_menu_item_title_system_va_score', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 230),
+('bx_forum_view_actions', @sName, 'favorite', '_sys_menu_item_title_system_va_favorite', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 240),
+('bx_forum_view_actions', @sName, 'feature', '_sys_menu_item_title_system_va_feature', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 250),
+('bx_forum_view_actions', @sName, 'repost', '_sys_menu_item_title_system_va_repost', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 260),
+('bx_forum_view_actions', @sName, 'report', '_sys_menu_item_title_system_va_report', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 270),
+('bx_forum_view_actions', @sName, '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_forum_view_actions', @sName, 'audit', '_sys_menu_item_title_system_va_audit', '_sys_menu_item_title_va_audit', 'page.php?i=dashboard-audit&module=bx_forum&content_id={content_id}', '', '', 'history', '', '', 0, 192, '', 1, 0, 290),
+('bx_forum_view_actions', @sName, 'social-sharing', '_sys_menu_item_title_system_social_sharing', '_sys_menu_item_title_social_sharing', 'javascript:void(0)', 'oBxDolPage.share(this, \'{url_encoded}\')', '', 'share', '', '', 0, 2147483647, '', 1, 0, 300),
+('bx_forum_view_actions', @sName, '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_forum_my', '_bx_forum_menu_title_entries_my', 'bx_forum_my', @sName, 9, 0, 1, 'BxForumMenu', 'modules/boonex/forum/classes/BxForumMenu.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_forum_my', @sName, '_bx_forum_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_forum_my', 'bx_forum', 'create-discussion', '_bx_forum_menu_item_title_system_create_entry', '_bx_forum_menu_item_title_create_entry', 'page.php?i=create-discussion', '', '', '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_forum_submenu', '_bx_forum_menu_title_submenu', 'bx_forum_submenu', @sName, 8, 0, 1, '', '');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_forum_submenu', @sName, '_bx_forum_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_forum_submenu', @sName, 'discussions-home', '_bx_forum_menu_item_title_system_entries_public', '_bx_forum_menu_item_title_entries_public', 'page.php?i=discussions-home', '', '', '', '', 2147483647, 1, 1, 1),
+('bx_forum_submenu', @sName, 'discussions-search', '_bx_forum_menu_item_title_system_entries_search', '_bx_forum_menu_item_title_entries_search', 'page.php?i=discussions-search', '', '', '', '', 2147483647, 1, 1, 5),
+('bx_forum_submenu', @sName, 'discussions-manage', '_bx_forum_menu_item_title_system_entries_manage', '_bx_forum_menu_item_title_entries_manage', 'page.php?i=discussions-manage', '', '', '', '', 2147483646, 1, 1, 7);
+
+-- MENU: custom menu for 'main' 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_forum_snippet_meta_main', '_bx_forum_menu_title_snippet_meta_main', 'bx_forum_snippet_meta_main', 'bx_forum', 15, 0, 1, 'BxForumMenuSnippetMeta', 'modules/boonex/forum/classes/BxForumMenuSnippetMeta.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_forum_snippet_meta_main', 'bx_forum', '_bx_forum_menu_set_title_snippet_meta_main', 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`, `hidden_on_col`) VALUES 
+('bx_forum_snippet_meta_main', 'bx_forum', 'score', '_bx_forum_menu_item_title_system_sm_vote', '_bx_forum_menu_item_title_sm_vote', '', '', '', '', '', 2147483647, 1, 0, 1, 0, 0),
+('bx_forum_snippet_meta_main', 'bx_forum', 'author', '_sys_menu_item_title_system_sm_author', '_sys_menu_item_title_sm_author', '', '', '', '', '', 2147483647, 1, 0, 1, 1, 0),
+('bx_forum_snippet_meta_main', 'bx_forum', 'date', '_sys_menu_item_title_system_sm_date', '_sys_menu_item_title_sm_date', '', '', '', 'clock', '', 2147483647, 1, 0, 1, 2, 0),
+('bx_forum_snippet_meta_main', 'bx_forum', 'category', '_sys_menu_item_title_system_sm_category', '_sys_menu_item_title_sm_category', '', '', '', '', '', 2147483647, 1, 0, 1, 3, 3),
+('bx_forum_snippet_meta_main', 'bx_forum', 'comments', '_sys_menu_item_title_system_sm_comments', '_sys_menu_item_title_sm_comments', '', '', '', 'comments', '', 2147483647, 1, 0, 1, 4, 3),
+('bx_forum_snippet_meta_main', 'bx_forum', 'status', '_bx_forum_menu_item_title_system_sm_status', '_bx_forum_menu_item_title_sm_status', '', '', '', '', '', 2147483647, 1, 0, 1, 5, 3);
+
+
+-- MENU: custom menu for 'counters' 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_forum_snippet_meta_counters', '_bx_forum_menu_title_snippet_meta_counters', 'bx_forum_snippet_meta_counters', 'bx_forum', 15, 0, 1, 'BxForumMenuSnippetMeta', 'modules/boonex/forum/classes/BxForumMenuSnippetMeta.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_forum_snippet_meta_counters', 'bx_forum', '_bx_forum_menu_set_title_snippet_meta_counters', 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_forum_snippet_meta_counters', 'bx_forum', 'views', '_sys_menu_item_title_system_sm_views', '_sys_menu_item_title_sm_views', '', '', '', '', '', 2147483647, 1, 0, 1, 1),
+('bx_forum_snippet_meta_counters', 'bx_forum', 'votes', '_sys_menu_item_title_system_sm_votes', '_sys_menu_item_title_sm_votes', '', '', '', '', '', 2147483647, 1, 0, 1, 2),
+('bx_forum_snippet_meta_counters', 'bx_forum', 'comments', '_sys_menu_item_title_system_sm_comments', '_sys_menu_item_title_sm_comments', '', '', '', '', '', 2147483647, 1, 0, 1, 3);
+
+-- MENU: custom menu for 'reply' 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_forum_snippet_meta_reply', '_bx_forum_menu_title_snippet_meta_reply', 'bx_forum_snippet_meta_reply', 'bx_forum', 15, 0, 1, 'BxForumMenuSnippetMeta', 'modules/boonex/forum/classes/BxForumMenuSnippetMeta.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_forum_snippet_meta_reply', 'bx_forum', '_bx_forum_menu_set_title_snippet_meta_reply', 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_forum_snippet_meta_reply', 'bx_forum', 'reply-author', '_sys_menu_item_title_system_sm_author', '_sys_menu_item_title_sm_author', '', '', '', '', '', 2147483647, 1, 0, 1, 1),
+('bx_forum_snippet_meta_reply', 'bx_forum', 'reply-date', '_sys_menu_item_title_system_sm_date', '_sys_menu_item_title_sm_date', '', '', '', '', '', 2147483647, 1, 0, 1, 2),
+('bx_forum_snippet_meta_reply', 'bx_forum', 'reply-text', '_bx_forum_menu_item_title_system_sm_reply_text', '_bx_forum_menu_item_title_sm_reply_text', '', '', '', '', '', 2147483647, 1, 0, 1, 3);
+
+
+-- 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_forum_menu_manage_tools', '_bx_forum_menu_title_manage_tools', 'bx_forum_menu_manage_tools', 'bx_forum', 6, 0, 1, 'BxForumMenuManageTools', 'modules/boonex/forum/classes/BxForumMenuManageTools.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_forum_menu_manage_tools', 'bx_forum', '_bx_forum_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_forum_menu_manage_tools', 'bx_forum', 'delete-with-content', '_bx_forum_menu_item_title_system_delete_with_content', '_bx_forum_menu_item_title_delete_with_content', 'javascript:void(0)', 'javascript:{js_object}.onClickDeleteWithContent({content_id});', '_self', 'far trash-alt', '', 128, 1, 0, 0);
+
+-- MENU: profile stats
+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', @sName, 'profile-stats-my-forum', '_bx_forum_menu_item_title_system_discussions', '_bx_forum_menu_item_title_discussions', 'page.php?i=discussions-author&profile_id={member_id}', '', '', 'far comments col-blue2', 'a:2:{s:6:"module";s:8:"bx_forum";s:6:"method";s:19:"get_discussions_num";}', '', 2147483646, 1, 0, 2);
+
+-- MENU: categories
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_forum_categories', '_bx_forum_menu_title_categories', '', 'bx_forum', 21, 0, 1, 'BxForumMenuCategories', 'modules/boonex/forum/classes/BxForumMenuCategories.php');
+
+
+-- MENU: dashboard manage tools
+SET @iManageMenuOrder = (SELECT IFNULL(MAX(`order`), 0) FROM `sys_menu_items` WHERE `set_name`='sys_account_dashboard_manage_tools' LIMIT 1);
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `addon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('sys_account_dashboard_manage_tools', @sName, 'discussions-administration', '_bx_forum_menu_item_title_system_admt_discussions', '_bx_forum_menu_item_title_admt_discussions', 'page.php?i=discussions-administration', '', '_self', 'far comments', 'a:2:{s:6:"module";s:8:"bx_forum";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', @sName, 'discussions-author', '_bx_forum_menu_item_title_system_view_entries_author', '_bx_forum_menu_item_title_view_entries_author', 'page.php?i=discussions-author&profile_id={profile_id}', '', '', 'far comments col-blue2', '', 2147483647, 1, 0, 0),
+('trigger_group_view_submenu', @sName, 'discussions-context', '_bx_forum_menu_item_title_system_view_entries_in_context', '_bx_forum_menu_item_title_view_entries_in_context', 'page.php?i=discussions-context&profile_id={profile_id}', '', '', 'far comments col-blue2', '', 2147483647, 1, 0, 0);
+
+-- GRIDS: main
+INSERT INTO `sys_objects_grid` (`object`, `source_type`, `source`, `table`, `field_id`, `field_order`, `paginate_url`, `paginate_per_page`, `paginate_simple`, `paginate_get_start`, `paginate_get_per_page`, `filter_fields`, `filter_mode`, `sorting_fields`, `visible_for_levels`, `override_class_name`, `override_class_file`) VALUES
+(@sName, 'Sql', 'SELECT `bx_forum_discussions`.*, `bx_forum_cmts`.`cmt_text` AS `cmt_text` %s FROM `bx_forum_discussions` LEFT JOIN `bx_forum_cmts` ON (`bx_forum_cmts`.`cmt_id` = `bx_forum_discussions`.`lr_comment_id`) %s WHERE 1 %s %s', 'bx_forum_discussions', 'id', 'lr_timestamp', '', 10, NULL, 'start', '', 'title,text,text_comments', 'auto', '', 2147483647, 'BxForumGrid', 'modules/boonex/forum/classes/BxForumGrid.php'),
+('bx_forum_favorite', 'Sql', 'SELECT `bx_forum_discussions`.*, `bx_forum_cmts`.`cmt_text` AS `cmt_text` %s FROM `bx_forum_discussions` LEFT JOIN `bx_forum_cmts` ON (`bx_forum_cmts`.`cmt_id` = `bx_forum_discussions`.`lr_comment_id`) %s WHERE 1 %s %s', 'bx_forum_discussions', 'id', 'lr_timestamp', '', 10, NULL, 'start', '', 'title,text,text_comments', 'auto', '', 2147483647, 'BxForumGrid', 'modules/boonex/forum/classes/BxForumGrid.php'),
+('bx_forum_feature', 'Sql', 'SELECT `bx_forum_discussions`.*, `bx_forum_cmts`.`cmt_text` AS `cmt_text` %s FROM `bx_forum_discussions` LEFT JOIN `bx_forum_cmts` ON (`bx_forum_cmts`.`cmt_id` = `bx_forum_discussions`.`lr_comment_id`) %s WHERE 1 %s %s', 'bx_forum_discussions', 'id', 'lr_timestamp', '', 10, NULL, 'start', '', 'title,text,text_comments', 'auto', '', 2147483647, 'BxForumGrid', 'modules/boonex/forum/classes/BxForumGrid.php');
+
+INSERT INTO `sys_grid_fields` (`object`, `name`, `title`, `width`, `params`, `order`) VALUES
+(@sName, 'text', '', '100%', '', 1),
+
+('bx_forum_favorite', 'text', '', '100%', '', 2);
+
+-- 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_forum_administration', 'Sql', 'SELECT * FROM `bx_forum_discussions` WHERE 1 ', 'bx_forum_discussions', 'id', 'added', 'status_admin', '', 20, NULL, 'start', '', 'title,text', '', 'like', 'reports', '', 192, 'BxForumGridAdministration', 'modules/boonex/forum/classes/BxForumGridAdministration.php'),
+('bx_forum_common', 'Sql', 'SELECT * FROM `bx_forum_discussions` WHERE 1 ', 'bx_forum_discussions', 'id', 'added', 'status', '', 20, NULL, 'start', '', 'title,text', '', 'like', '', '', 2147483647, 'BxForumGridCommon', 'modules/boonex/forum/classes/BxForumGridCommon.php');
+
+INSERT INTO `sys_grid_fields` (`object`, `name`, `title`, `width`, `translatable`, `chars_limit`, `params`, `order`) VALUES
+('bx_forum_administration', 'checkbox', '_sys_select', '2%', 0, '', '', 1),
+('bx_forum_administration', 'switcher', '_bx_forum_grid_column_title_adm_active', '8%', 0, '', '', 2),
+('bx_forum_administration', 'reports', '_sys_txt_reports_title', '5%', 0, '', '', 3),
+('bx_forum_administration', 'title', '_bx_forum_grid_column_title_adm_title', '25%', 0, '', '', 4),
+('bx_forum_administration', 'added', '_bx_forum_grid_column_title_adm_added', '20%', 1, '25', '', 5),
+('bx_forum_administration', 'author', '_bx_forum_grid_column_title_adm_author', '20%', 0, '25', '', 6),
+('bx_forum_administration', 'actions', '', '20%', 0, '', '', 7),
+
+('bx_forum_common', 'checkbox', '_sys_select', '2%', 0, '', '', 1),
+('bx_forum_common', 'switcher', '_bx_forum_grid_column_title_adm_active', '8%', 0, '', '', 2),
+('bx_forum_common', 'title', '_bx_forum_grid_column_title_adm_title', '40%', 0, '', '', 3),
+('bx_forum_common', 'added', '_bx_forum_grid_column_title_adm_added', '15%', 1, '25', '', 4),
+('bx_forum_common', 'status_admin', '_bx_forum_grid_column_title_adm_status_admin', '15%', 0, '16', '', 5),
+('bx_forum_common', 'actions', '', '20%', 0, '', '', 6);
+
+INSERT INTO `sys_grid_actions` (`object`, `type`, `name`, `title`, `icon`, `icon_only`, `confirm`, `order`) VALUES
+('bx_forum_administration', 'bulk', 'delete', '_bx_forum_grid_action_title_adm_delete', '', 0, 1, 1),
+('bx_forum_administration', 'bulk', 'clear_reports', '_bx_forum_grid_action_title_adm_clear_reports', '', 0, 1, 2),
+('bx_forum_administration', 'single', 'edit', '_bx_forum_grid_action_title_adm_edit', 'pencil-alt', 1, 0, 1),
+('bx_forum_administration', 'single', 'delete', '_bx_forum_grid_action_title_adm_delete', 'remove', 1, 1, 2),
+('bx_forum_administration', 'single', 'settings', '_bx_forum_grid_action_title_adm_more_actions', 'cog', 1, 0, 3),
+('bx_forum_administration', 'single', 'audit_content', '_bx_forum_grid_action_title_adm_audit_content', 'search', 1, 0, 4),
+('bx_forum_administration', 'single', 'clear_reports', '_bx_forum_grid_action_title_adm_clear_reports', 'eraser', 1, 0, 5),
+
+('bx_forum_common', 'bulk', 'delete', '_bx_forum_grid_action_title_adm_delete', '', 0, 1, 1),
+('bx_forum_common', 'single', 'edit', '_bx_forum_grid_action_title_adm_edit', 'pencil-alt', 1, 0, 1),
+('bx_forum_common', 'single', 'delete', '_bx_forum_grid_action_title_adm_delete', 'remove', 1, 1, 2),
+('bx_forum_common', 'single', 'settings', '_bx_forum_grid_action_title_adm_more_actions', 'cog', 1, 0, 3);
+
+-- GRIDS: categories manager
+INSERT INTO `sys_objects_grid` (`object`, `source_type`, `source`, `table`, `field_id`, `field_order`, `paginate_url`, `paginate_per_page`, `paginate_simple`, `paginate_get_start`, `paginate_get_per_page`, `filter_fields`, `filter_mode`, `sorting_fields`, `visible_for_levels`, `override_class_name`, `override_class_file`) VALUES
+('bx_forum_categories', 'Array', '', '', 'category', '', '', 10, NULL, 'start', '', 'title', 'auto', '', 128, 'BxForumGridCategories', 'modules/boonex/forum/classes/BxForumGridCategories.php');
+
+INSERT INTO `sys_grid_fields` (`object`, `name`, `title`, `width`, `params`, `order`) VALUES
+('bx_forum_categories', 'icon', '_bx_forum_grid_column_title_icon', '10%', '', 1),
+('bx_forum_categories', 'title', '_bx_forum_grid_column_title_title', '50%', '', 2),
+('bx_forum_categories', 'visible_for_levels', '_bx_forum_grid_column_title_visible_for_levels', '20%', '', 3),
+('bx_forum_categories', 'actions', '', '20%', '', 4);
+
+INSERT INTO `sys_grid_actions` (`object`, `type`, `name`, `title`, `icon`, `confirm`, `order`) VALUES
+('bx_forum_categories', 'single', 'show_to', '_bx_forum_grid_action_title_show_to', '', 0, 1),
+('bx_forum_categories', 'single', 'edit', '_bx_forum_grid_action_title_adm_edit', 'pencil-alt', 0, 2);
+
+
+-- ACL
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+(@sName, 'create entry', NULL, '_bx_forum_acl_action_create_entry', '', 1, 3);
+SET @iIdActionEntryCreate = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+(@sName, 'delete entry', NULL, '_bx_forum_acl_action_delete_entry', '', 1, 3);
+SET @iIdActionEntryDelete = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+(@sName, 'view entry', NULL, '_bx_forum_acl_action_view_entry', '', 1, 0);
+SET @iIdActionEntryView = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+(@sName, 'set thumb', NULL, '_bx_forum_acl_action_set_thumb', '', 1, 3);
+SET @iIdActionSetThumb = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+(@sName, 'edit any entry', NULL, '_bx_forum_acl_action_edit_any_entry', '', 1, 3);
+SET @iIdActionEntryEditAny = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+(@sName, 'delete any entry', NULL, '_bx_forum_acl_action_delete_any_entry', '', 1, 3);
+SET @iIdActionEntryDeleteAny = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+(@sName, 'stick any entry', NULL, '_bx_forum_acl_action_stick_any_entry', '', 1, 3);
+SET @iIdActionEntryStickAny = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+(@sName, 'lock any entry', NULL, '_bx_forum_acl_action_lock_any_entry', '', 1, 3);
+SET @iIdActionEntryLockAny = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+(@sName, 'hide any entry', NULL, '_bx_forum_acl_action_hide_any_entry', '', 1, 3);
+SET @iIdActionEntryHideAny = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+(@sName, 'resolve any entry', NULL, '_bx_forum_acl_action_resolve_any_entry', '', 1, 3);
+SET @iIdActionEntryResolveAny = 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),
+
+-- set entry thumb
+(@iStandard, @iIdActionSetThumb),
+(@iModerator, @iIdActionSetThumb),
+(@iAdministrator, @iIdActionSetThumb),
+(@iPremium, @iIdActionSetThumb),
+
+-- edit any entry
+(@iModerator, @iIdActionEntryEditAny),
+(@iAdministrator, @iIdActionEntryEditAny),
+
+-- delete any entry
+(@iAdministrator, @iIdActionEntryDeleteAny),
+
+-- stick any entry
+(@iModerator, @iIdActionEntryStickAny),
+(@iAdministrator, @iIdActionEntryStickAny),
+
+-- lock any entry
+(@iModerator, @iIdActionEntryLockAny),
+(@iAdministrator, @iIdActionEntryLockAny),
+
+-- hide any entry
+(@iModerator, @iIdActionEntryHideAny),
+(@iAdministrator, @iIdActionEntryHideAny),
+
+-- resolve any entry
+(@iModerator, @iIdActionEntryResolveAny),
+(@iAdministrator, @iIdActionEntryResolveAny);
+
+
+-- 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_forum_allow_view_to', @sName, 'view', '_bx_forum_form_entry_input_allow_view_to', '3', 'bx_forum_discussions', 'id', 'author', '', ''),
+('bx_forum_allow_view_favorite_list', @sName, 'view_favorite_list', '_bx_forum_form_entry_input_allow_view_favorite_list', '3', 'bx_forum_favorites_lists', 'id', 'author_id', '', '');
+
+
+
+-- SEARCH
+SET @iSearchOrder = (SELECT IFNULL(MAX(`Order`), 0) FROM `sys_objects_search`);
+INSERT INTO `sys_objects_search` (`ObjectName`, `Title`, `Order`, `ClassName`, `ClassPath`) VALUES
+(@sName, '_bx_forum', @iSearchOrder + 1, 'BxForumSearchResult', 'modules/boonex/forum/classes/BxForumSearchResult.php'),
+('bx_forum_cmts', '_bx_forum_cmts', @iSearchOrder + 2, 'BxForumCmtsSearchResult', 'modules/boonex/forum/classes/BxForumCmtsSearchResult.php');
+
+
+-- CONNECTIONS
+INSERT INTO `sys_objects_connection` (`object`, `table`, `profile_initiator`, `profile_content`, `type`, `override_class_name`, `override_class_file`) VALUES
+('bx_forum_subscribers', 'bx_forum_subscribers', 1, 0, 'one-way', '', '');
+
+
+-- METATAGS
+INSERT INTO `sys_objects_metatags` (`object`, `module`, `table_keywords`, `table_locations`, `table_mentions`, `override_class_name`, `override_class_file`) VALUES
+(@sName, @sName, 'bx_forum_meta_keywords', '', 'bx_forum_meta_mentions', 'BxForumMetatags', 'modules/boonex/forum/classes/BxForumMetatags.php');
+
+
+-- CATEGORY
+INSERT INTO `sys_objects_category` (`object`, `module`, `search_object`, `form_object`, `list_name`, `table`, `field`, `join`, `where`, `override_class_name`, `override_class_file`) VALUES
+('bx_forum_cats', @sName, @sName, @sName, 'bx_forum_cats', 'bx_forum_discussions', 'cat', 'INNER JOIN `sys_profiles` ON (`sys_profiles`.`id` = ABS(`bx_forum_discussions`.`author`))', 'AND `sys_profiles`.`status` = ''active''', 'BxForumCategory', 'modules/boonex/forum/classes/BxForumCategory.php');
+
+
+-- STATS
+SET @iMaxOrderStats = (SELECT IFNULL(MAX(`order`), 0) FROM `sys_statistics`);
+INSERT INTO `sys_statistics` (`module`, `name`, `title`, `link`, `icon`, `query`, `order`) VALUES 
+(@sName, @sName, '_bx_forum', 'page.php?i=discussions-home', 'far comments col-blue2', 'SELECT COUNT(*) FROM `bx_forum_discussions` 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_forum_growth', '_bx_forum_chart_growth', 'bx_forum_discussions', 'added', '', 'status,status_admin', '', 1, @iMaxOrderCharts + 1, 'BxDolChartGrowth', ''),
+('bx_forum_growth_speed', '_bx_forum_chart_growth_speed', 'bx_forum_discussions', 'added', '', 'status,status_admin', '', 1, @iMaxOrderCharts + 2, 'BxDolChartGrowthSpeed', '');
+
+
+-- UPLOADERS
+INSERT INTO `sys_objects_uploader` (`object`, `active`, `override_class_name`, `override_class_file`) VALUES
+('bx_forum_simple', 1, 'BxForumUploaderSimple', 'modules/boonex/forum/classes/BxForumUploaderSimple.php'),
+('bx_forum_html5', 1, 'BxForumUploaderHTML5', 'modules/boonex/forum/classes/BxForumUploaderHTML5.php'),
+('bx_forum_record_video', 1, 'BxForumUploaderRecordVideo', 'modules/boonex/forum/classes/BxForumUploaderRecordVideo.php'),
+('bx_forum_photos_simple', 1, 'BxForumUploaderSimpleAttach', 'modules/boonex/forum/classes/BxForumUploaderSimpleAttach.php'),
+('bx_forum_photos_html5', 1, 'BxForumUploaderHTML5Attach', 'modules/boonex/forum/classes/BxForumUploaderHTML5Attach.php'),
+('bx_forum_videos_simple', 1, 'BxForumUploaderSimpleAttach', 'modules/boonex/forum/classes/BxForumUploaderSimpleAttach.php'),
+('bx_forum_videos_html5', 1, 'BxForumUploaderHTML5Attach', 'modules/boonex/forum/classes/BxForumUploaderHTML5Attach.php'),
+('bx_forum_videos_record_video', 1, 'BxForumUploaderRecordVideoAttach', 'modules/boonex/forum/classes/BxForumUploaderRecordVideoAttach.php'),
+('bx_forum_files_simple', 1, 'BxForumUploaderSimpleAttach', 'modules/boonex/forum/classes/BxForumUploaderSimpleAttach.php'),
+('bx_forum_files_html5', 1, 'BxForumUploaderHTML5Attach', 'modules/boonex/forum/classes/BxForumUploaderHTML5Attach.php');
+
+
+-- ALERTS
+INSERT INTO `sys_alerts_handlers` (`name`, `class`, `file`, `service_call`) VALUES 
+(@sName, 'BxForumAlertsResponse', 'modules/boonex/forum/classes/BxForumAlertsResponse.php', '');
+SET @iHandler := LAST_INSERT_ID();
+
+INSERT INTO `sys_alerts` (`unit`, `action`, `handler_id`) VALUES
+('system', 'save_setting', @iHandler),
+('profile', 'delete', @iHandler),
+(@sName, 'commentPost', @iHandler),
+(@sName, 'commentUpdated', @iHandler),
+(@sName, 'commentRemoved', @iHandler),
+('bx_forum_files_cmts', 'file_deleted', @iHandler);
+
+
+-- EMAIL TEMPLATES
+INSERT INTO `sys_email_templates` (`Module`, `NameSystem`, `Name`, `Subject`, `Body`) VALUES
+(@sName, '_bx_forum_email_new_reply', 'bx_forum_new_reply', '_bx_forum_email_new_reply_subject', '_bx_forum_email_new_reply_body');

+ 579 - 0
modules/boonex/forum/updates/13.0.2_13.0.3/source/template/css/main.css

@@ -0,0 +1,579 @@
+/*-- Participants --*/
+.bx-forum-participants {
+    position:relative;
+}
+.bx-forum-participants.left,
+.bx-forum-participants.none {
+    float: left;
+}
+.bx-forum-participants.right {
+    float: right;
+}
+.bx-forum-participant {
+    position: relative;
+    display: block;
+}
+.bx-forum-participants.left .bx-forum-participant,
+.bx-forum-participants.none .bx-forum-participant {
+    float: left;
+    margin-right: 0.5rem;
+}
+.bx-forum-participants.left .bx-forum-participant:last-child,
+.bx-forum-participants.none .bx-forum-participant:last-child {
+    margin-right: 0;
+}
+.bx-forum-participants.right .bx-forum-participant {
+    float: right;
+    margin-left: 0.5rem;
+}
+.bx-forum-participants.right .bx-forum-participant:last-child {
+    margin-left: 0;
+}
+
+.bx-forum-participant-alert-last-replier {
+    left:0;
+    right:auto;
+}
+
+.bx-forum-participant-alert-author {
+    left:0;
+    right:auto;
+    top:auto;
+    bottom:0;
+}
+
+/*-- Replies --*/
+.cmt.bx-def-box .cmts.cmts-margin {
+    margin-top: 0px;
+}
+.cmt-attached-preview.bx-forum-attached-preview {
+    display: block;
+    float: none;
+
+    width: auto;
+    height: 2rem;
+    line-height: 2rem;
+    white-space: nowrap;
+
+    overflow: hidden;
+    text-overflow: ellipsis;
+}
+.cmt-attached-preview.bx-forum-attached-preview img,
+.cmt-attached-preview.bx-forum-attached-preview .sys-icon {
+    display: inline-block;
+    vertical-align: middle;
+
+    width: 2rem;
+    height: 2rem;
+}
+.cmt-attached-preview.bx-forum-attached-preview .sys-icon {
+    text-align: center;
+    font-size: 1.25rem;
+}
+
+/*-- Preview --*/
+.bx-forum-preview {
+    position:relative;
+}
+
+.bx-forum-title {    
+    padding-right:2em;
+    white-space:nowrap;    
+    text-overflow:ellipsis;
+    overflow:hidden;
+}
+
+/*-- Grid --*/
+.bx-forum-grid .bx-grid-table tr.bx-def-color-bg-hl {
+    background-color: transparent;
+}
+
+.bx-forum-grid-field-replies .bx-def-unit-alert-middle {
+    position:static;
+    display:inline-block;
+    vertical-align:middle;
+}
+
+.bx-forum-grid-field-replies > span {
+    vertical-align:middle;
+}
+
+.bx-forum-grid-field-replies {
+    white-space:nowrap;
+}
+
+.bx-forum-grid-field-label {
+    display:inline-block;
+}
+
+.bx-forum-preview .bx-forum-grid-field-label {
+    position: absolute;
+    right: 0;
+    top: 0;
+}
+#bx-forum-snippet-meta-main{
+    overflow: hidden;
+    display: flex;
+    grid-gap: 0.25rem;
+}
+.bx-forum-preview .bx-def-unit-info {
+    line-height:1.15em;
+}
+
+.bx-grid-table-cell-author {
+    vertical-align: top;
+}
+
+.bx-grid-table-cell-author .bx-base-pofile-unit-wo-info {
+	display: inline-block;
+}
+
+.bx-forum-grid-preview .bx-forum-gp-title {
+    display: -webkit-flex;
+    display: flex;
+    -webkit-align-items: center;
+    align-items: center;
+}
+
+.bx-forum-grid-preview .bx-forum-gp-title a {
+    display: inline-block;
+}
+
+.bx-forum-grid-preview .bx-forum-gp-title a,
+.bx-forum-grid-preview .bx-forum-gp-text {
+    font-size: 1rem; 
+    line-height: 125%; 
+    font-weight: 600; 
+}
+
+.bx-forum-grid-preview .bx-forum-gp-title .sys-icon,
+.bx-forum-grid-preview .bx-forum-gp-text .sys-icon {
+    margin-right:0.25rem;
+}
+
+.bx-forum-grid-preview .bx-forum-gp-meta {
+    display: -webkit-flex;
+    display: flex;
+    -webkit-align-items: center;
+    align-items: center;
+    -webkit-flex-wrap: wrap;
+    flex-wrap: wrap;
+}
+
+.bx-forum-grid-preview .bx-forum-gp-meta.bx-forum-gpm-top {
+    -webkit-justify-content: space-between;
+    justify-content: space-between;
+}
+
+.bx-forum-grid-preview .bx-forum-gp-meta .bx-menu-custom.bx-menu-custom-hor {
+    margin: 0;
+}
+.bx-forum-grid-preview .bx-forum-gp-meta.bx-forum-gpm-bottom .bx-menu-custom.bx-menu-custom-hor {
+    -webkit-align-items: center;
+    align-items: center;
+    -webkit-flex-wrap: nowrap;
+    flex-wrap: nowrap;
+
+    max-width: 100%;
+}
+.bx-forum-grid-preview .bx-forum-gp-meta.bx-forum-gpm-bottom .bx-menu-custom.bx-menu-custom-hor li {
+    -webkit-flex: 0 0 auto;
+    -ms-flex: 0 0 auto;
+    flex: 0 0 auto;
+    
+    text-overflow: ellipsis;
+    overflow: hidden;
+}
+.bx-forum-grid-preview .bx-forum-gp-meta.bx-forum-gpm-bottom .bx-menu-custom.bx-menu-custom-hor li.bx-menu-item-reply-text {
+    -webkit-flex-shrink: 1;
+    flex-shrink: 1;
+}
+.bx-forum-grid-preview .bx-forum-gp-meta.bx-forum-gpm-bottom .bx-menu-custom.bx-menu-custom-hor li .bx-base-general-unit-meta-item {
+    display: contents;
+}
+.bx-layout-col.bx-layout-column-thin .bx-forum-grid-preview .bx-forum-gp-meta .bx-def-media-phone-hide {
+    display: none;
+}
+.bx-forum-grid-preview .bx-forum-gp-meta.bx-forum-gpm-top .bx-forum-gpm-counters .sys-action {
+    display: inline-block;
+    margin-top: 0;
+    margin-bottom: 0;
+}
+.bx-forum-grid-preview .bx-forum-gp-meta.bx-forum-gpm-top .bx-forum-gpm-counters .cmt-counter div.cmt-counter-icon,
+.bx-forum-grid-preview .bx-forum-gp-meta.bx-forum-gpm-top .bx-forum-gpm-counters .cmt-counter div.bx-base-pofile-unit-wo-info {
+    margin-left: -4px;
+}
+
+.bx-forum-grid-preview .bx-forum-gp-meta.bx-forum-gpm-top .bx-forum-gpm-counters .cmt-counter .bx-def-icon-size {
+    width: 1.0rem;
+    height: 1.0rem;
+}
+.bx-forum-grid-preview .bx-forum-gp-meta.bx-forum-gpm-top .bx-forum-gpm-counters .cmt-counter .bx-def-icon-size,
+.bx-forum-grid-preview .bx-forum-gp-meta.bx-forum-gpm-top .bx-forum-gpm-counters .cmt-counter p.bx-base-pofile-unit-thumb.bx-def-icon-size {
+    line-height: normal;
+    font-size: 0.6rem;
+}
+.bx-forum-grid-preview .bx-forum-gp-meta.bx-forum-gpm-top .bx-forum-gpm-counters .cmt-counter div.cmt-counter-icon .sys-icon {
+    font-size: 0.6rem;
+}
+
+.bx-forum-grid-preview .bx-forum-gp-meta.bx-forum-gpm-bottom .bx-forum-gpm-reply {
+    display: -webkit-flex;
+    display: flex;
+    -webkit-align-items: center;
+    align-items: center;
+}
+
+.bx-forum-grid-preview .bx-forum-gp-meta.bx-forum-gpm-bottom .bx-forum-gpm-reply .bx-menu-item-reply-author .bx-base-pofile-unit {
+    width: auto;
+    margin: 0;
+}
+
+.bx-forum-grid-preview .bx-forum-gp-meta.bx-forum-gpm-bottom .bx-forum-gpm-reply .bx-menu-item-reply-author .bx-def-icon-size {
+    width: 1.0rem;
+    height: 1.0rem;
+
+    line-height: 0.875rem;
+    font-size: 0.6rem;
+}
+.bx-forum-grid-preview .bx-menu-item-date .text-sm{
+    font-size: 12px;
+    font-weight: 500;
+}
+
+.bx-forum-grid-preview .bx-forum-gp-meta.bx-forum-gpm-bottom .bx-forum-gpm-reply .bx-menu-item-reply-author .bx-def-icon-size-min-height {
+    min-height: 1.0rem;
+}
+
+.bx-forum-grid-preview .bx-forum-gp-meta.bx-forum-gpm-bottom .bx-forum-gpm-reply .bx-menu-item-reply-author .bx-def-icon-size-max-height {
+    max-height: 1.0rem;
+}
+
+.bx-forum-grid-preview .bx-forum-gp-meta.bx-forum-gpm-bottom .bx-forum-gpm-reply .bx-menu-item-reply-author .bx-def-icon-size-left-indent {
+    margin-left: 1.25rem;
+}
+
+.bx-forum-grid-preview .bx-forum-gp-meta.bx-forum-gpm-bottom .bx-forum-gpm-reply .bx-menu-item-reply-author .bx-def-unit-img .bx-base-pofile-unit-thumb {
+    display: block;
+    border-width: 1px;
+}
+
+.bx-forum-grid-preview .bx-forum-gp-meta.bx-forum-gpm-bottom .bx-forum-gpm-reply .bx-menu-item-reply-author .bx-base-pofile-unit-online {
+    display: none;
+}
+
+.bx-base-general-unit-meta ul.bx-menu-object-bx_forum_snippet_meta_counters li > span {
+    position: relative;
+    display: inline-block;
+    vertical-align: top;
+    height: 1.5rem;
+    margin-top: 0;
+    margin-bottom: 0;
+    border-width: 0px;
+    line-height: 1.5rem;
+}
+.bx-base-general-unit-meta ul.bx-menu-object-bx_forum_snippet_meta_counters li a {
+    display: inline-block;
+}
+.bx-base-general-unit-meta ul.bx-menu-object-bx_forum_snippet_meta_counters li .sys-icon:not(.cmt-counter-icon) {
+    width: 1.0rem;
+    height: 1.0rem;
+    text-align: center;
+    line-height: 1.0rem;
+    vertical-align: baseline;
+}
+.bx-base-general-unit-meta ul.bx-menu-object-bx_forum_snippet_meta_counters li .cmt-element-holder,
+.bx-base-general-unit-meta ul.bx-menu-object-bx_forum_snippet_meta_counters li .cmt-counter-holder {
+    line-height: normal;
+}
+
+.bx-forum-category-list-item a{
+    display: flex;
+    align-items: center;
+}
+.bx-forum-category{
+    display: flex;
+    line-height: initial;
+    font-weight: 500;
+    color: #111928;
+}
+.bx-forum-category-list-item-selected{
+    background:  #F3F4F6;
+    border-radius: 8px;
+}
+.dark .bx-forum-category-list-item-selected{
+	background-color: rgba(55, 65, 81, 0.5) !important;
+}
+.bx-forum-icon{
+    min-width: 1.5rem;
+    height: 1.5rem;
+    text-align: center;
+    line-height: 1.7rem;
+    font-size: 1.25rem;
+}
+.bx-forum-icon svg,
+.bx-forum-icon .sys-icon{
+    width: 1.5rem;
+    height: 1.5rem;
+    border-radius: 2rem;
+    display: block;
+}
+.bx-forum-icon img.sys-icon{
+    display: block !important;
+}
+.bx-forum-icon i.sys-icon{
+    display: flex;
+    align-items: center;
+    justify-content: space-around;
+}
+.bx-forum-thumb img{
+    border-radius: 500px;
+}
+.bx-forum-thumb .sys-icon{
+    color: #111928;
+    font-size: 1.25rem;
+}
+.dark .bx-forum-thumb .sys-icon{
+    color: rgb(209 213 219);
+}
+.bx-forum-thumb img.sys-icon {
+    width: 1.5rem;
+    height: 1.5rem;
+}
+.bx-forum-thumb .sys-icon-svg{
+    width: 1.5rem;
+    height: 1.5rem;
+}
+
+.bx-forum-grid-status{
+    display: flex;
+}
+.bx-forum-status-0{
+    color: rgb(239, 68, 68);
+    font-weight: 500;
+}
+.bx-forum-status-0:hover{
+    background-color: rgb(239, 68, 68, 0.2);
+}
+.bx-forum-status-1{
+    font-weight: 500;
+    color: rgb(34, 197, 94);
+}
+.bx-forum-status-1:hover{
+    background-color: rgba(34, 197, 94, 0.2);
+}
+#bx-grid-table-bx_forum tr{
+    border-bottom: 1px solid #F4F4F5
+}
+.dark #bx-grid-table-bx_forum tr{
+    border-bottom: 1px solid rgb(55 65 81 / 0.5);;
+}
+#bx-grid-table-bx_forum tr:last-child{
+	border-bottom: none;
+}
+.bx-forum-wrapper .bx-base-text-unit-gallery .bx-menu-item-score{
+    display: none;
+}
+.bx-grid-table-cell-participants .sys-action-counter-iconset .ml-2
+{
+    display: none;
+}
+.bx-grid-table-cell-participants .cmt-counter{
+    float: right;
+}
+#bx-grid-table-bx_forum td{
+    vertical-align: middle !important;
+}
+.bx-forum-grid td{
+    vertical-align: top;
+    padding: 0px !important;
+}
+.bx-forum-grid tr:hover{
+    cursor: pointer;
+}
+.bx-forum-grid .bx-grid-table-wrapper2{
+    margin-left: -1rem;
+    margin-right: -1rem;
+    width:calc(100% + 2rem);
+}
+.bx-forum-grid tr td:first-child{
+    padding-left: 0rem;
+}
+.bx-forum-grid tr td:last-child{
+    padding-right: 0rem;
+}
+.bx-forum-grid tr:hover td:first-child{
+    border-radius: 0.375rem 0 0 0.375rem;
+}
+.bx-forum-grid tr:hover td:last-child{
+    border-radius: 0 0.375rem 0.375rem 0;
+}
+.bx-media-phone .bx-forum-grid {
+    width: 100%;
+    min-width:inherit !important;
+}
+
+.bx-media-phone .bx-forum-grid tr{
+    display: grid;
+	grid-template-areas:
+    "text text"
+	"participants rating";
+	
+    grid-template-rows: auto auto;
+	grid-template-columns: auto auto;
+    margin-bottom: 0.5rem;
+}
+
+.bx-media-phone .bx-forum-grid table{
+    width: 100% !important;
+    min-width: inherit !important;
+    max-width: 100% !important;
+    overflow: hidden;
+    display: block;
+}
+.bx-media-phone .bx-forum-grid td{
+    width: auto !important;
+}
+
+.bx-media-phone .bx-forum-grid .bx-grid-table-cell-category{
+    grid-area: category;
+    display: none;
+}
+.bx-media-phone .bx-forum-grid .bx-grid-table-cell-text{
+    grid-area: text;
+    padding-bottom: 0px;
+    overflow: hidden;
+    padding-top: 0px;
+}
+.bx-media-phone .bx-forum-grid .bx-grid-table-cell-participants{
+    grid-area: participants;
+    padding-top: 0px;
+    display: flex;
+    align-items: center;
+}
+.bx-media-phone .bx-forum-grid .bx-grid-table-cell-rating{
+    grid-area: rating;
+    text-align: right;
+    margin-right: 1rem;
+    padding-top: 0px;
+}
+.bx-media-phone .bx-forum-gpm-main{
+    margin-bottom: 0.5rem;
+    width: 100%;
+}
+.bx-media-phone .bx-forum-gpm-main UL{
+    width: 100%;
+    justify-content: space-between;
+}
+.bx-media-phone .bx-forum-gpm-main UL LI:nth-child(n+4){
+    display: none;
+}
+
+.bx-media-phone .bx-grid-table-cell-participants .cmt-counter{
+    float:none
+}
+/* unit */
+.bx-forum-unit .bx-base-text-unit-title h2{
+    font-size: 1rem;
+    line-height: 1.5;
+    font-weight: 500;
+    color: rgb(17,24,29);
+}
+.bx-forum-unit .bx-base-general-unit-meta-item{
+    font-size: 0.875rem !important; 
+    color:rgb(107,114,128) !important;
+}
+.bx-forum-unit .bx-base-text-unit-no-thumb{
+    background: url("data:image/svg+xml,%3Csvg width='16' height='20' viewBox='0 0 16 20' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='%239C92AC' fill-opacity='0.4' fill-rule='evenodd'%3E%3Cpath d='M8 0v20L0 10M16 0v10L8 0M16 10v10H8'/%3E%3C/g%3E%3C/svg%3E"), linear-gradient(90deg, #3F83F8 0%, #0694A2 100%);
+    text-align: left;
+    color:#fff;
+    border-radius: 7px 7px 0 0;
+}
+.bx-forum-unit .bx-base-text-unit-title{
+    white-space: normal;
+}
+.bx-forum-grid .bx-grid-header-controls-counter{
+    display: none;
+}
+.bx-forum-grid .bx-grid-header-controls-filter{
+    display: flex;
+    width: 100%;
+}
+.bx-forum-grid #bx-form-element-search{
+    flex-grow: 3;
+}
+.bx-forum-unit.bx-base-text-unit-gallery .bx-base-text-unit-info .bx-base-pofile-unit A,
+.bx-forum-unit.bx-base-text-unit-gallery .bx-base-text-unit-title A{
+    color:#fff !important;
+}
+.bx-forum-unit .bx-base-text-unit-info .bx-base-pofile-unit .bx-def-unit-info{
+    text-align: left;
+}
+.bx-forum-unit .bx-base-pofile-unit{
+    margin-bottom: 0px;
+    margin-right: 0px;
+}
+.bx-base-unit-showcase.bx-forum-unit{
+    display: inline-block;
+}
+/* one item */
+.bx-base-unit-showcase-wrapper .bx-forum-unit:first-child:nth-last-child(1) {
+    width: 100% !important;
+}
+/* two items */
+.bx-base-unit-showcase-wrapper .bx-forum-unit:first-child:nth-last-child(2),
+.bx-base-unit-showcase-wrapper .bx-forum-unit:first-child:nth-last-child(2) ~ .bx-forum-unit {
+    width: 50%  !important;
+}
+/* 3 items or more */
+.bx-base-unit-showcase-wrapper .bx-forum-unit:first-child:nth-last-child(3),
+.bx-base-unit-showcase-wrapper .bx-forum-unit:first-child:nth-last-child(3) ~ .bx-forum-unit {
+    width: 33.3333%;
+}
+.bx-media-tablet .bx-base-unit-showcase-wrapper .bx-forum-unit:first-child:nth-last-child(3),
+.bx-media-tablet .bx-base-unit-showcase-wrapper .bx-forum-unit:first-child:nth-last-child(3) ~ .bx-forum-unit {
+    width: 50%;
+}
+.bx-media-phone .bx-base-unit-showcase-wrapper .bx-forum-unit:first-child:nth-last-child(3),
+.bx-media-phone .bx-base-unit-showcase-wrapper .bx-forum-unit:first-child:nth-last-child(3) ~ .bx-forum-unit {
+    width: 100%;
+}
+
+.bx-forum-grid .sys-action-counter-label.bx-score-counter-label{
+	padding: 0px !important;
+}
+.bx-forum-grid .sys-action-counter-iconset .sys-action-counter-text{
+    display: none;
+}
+
+
+/* ---------------new meta menu need to move incore*/
+
+.bx-menu-meta-icon img,
+.bx-menu-meta-icon svg{
+    width: 1rem ;
+    height: 1rem !important;
+    border-radius: 1rem ;
+    display: block;
+}
+.bx-menu-meta-icon .sys-icon-emoji{
+    font-size: 0.8rem ;
+}
+
+.bx-menu-meta-item-ex.bx-menu-meta-item-ex-no-bg{
+    background: none !important;
+}
+.bx-menu-meta-item-ex.bx-menu-meta-item-ex-no-pad{
+    padding: 0px !important;
+}
+.bx-menu-meta-item-ex{
+    margin-right: 0.5rem !important;
+}
+.bx-forum-category-list{
+	margin: -0.75rem !important;
+	margin-top: 0px !important;
+}
+.bx-menu-meta-item-ex span:nth-child(2) {
+    margin-left: 0.375rem;
+}
+

+ 30 - 0
modules/boonex/forum/updates/13.0.2_13.0.3/source/template/entry-preview.html

@@ -0,0 +1,30 @@
+<div class="group block hover:bg-gray-50 dark:hover:bg-gray-700/20" onClick="bx_click_area('__url__', event)">
+    <div class="p-4">
+        <div class="min-w-0 flex sm:items-top justify-between align-top">
+            <div class="pr-4 flex-1 grow">
+                <div class="flex flex-wrap space-y-2.5 px-0 items-start flex-col">                               
+                    <div class=" flex text-lg flex-wrap  font-semibold text-gray-600 group-hover:text-gray-900 dark:text-gray-300 dark:group-hover:text-white">
+                        <span class="leading-tight">                                    
+                            <a href="__url__">__title__</a>
+                                <span class="mr-1 inline-flex align-middle items-center -space-x-1 overflow-hidden">__participants__</span>
+                                __badges__
+                        </span>
+                    </div>
+                    <nav class="flex">
+                        <div class="inline-flex flex-wrap text-xs font-medium gap-2">
+                            <bx_if:meta_main>
+                                <div class="bx-base-general-unit-meta bx-forum-gpm-main items-center flex">__content__</div>
+                            </bx_if:meta_main>
+                            <bx_if:meta_counters>
+                                <div class="bx-base-general-unit-meta bx-forum-gpm-counters bx-def-media-phone-hide items-center flex">__content__</div>
+                            </bx_if:meta_counters>
+                        </div>
+                    </nav>
+                </div>
+            </div>
+            <bx_if:image>
+              <img src="__image__" class="bg-cover sm:flex aspect-video h-16 rounded-md text-4xl align-top bg-black/10 dark:bg-white/10">
+            </bx_if:image>  
+        </div>
+    </div>
+</div>

+ 13 - 0
modules/boonex/forum/updates/13.0.2_13.0.3/source/template/score_element_inline.html

@@ -0,0 +1,13 @@
+<span id="__html_id__" class="sys-action __style_prefix__ __class__ inline-flex items-center whitespace-nowrap" bx_score_data_score="__score__" bx_score_data_cup="__cup__" bx_score_data_cdown="__cdown__">
+    <span class="sys-action-cnt __style_prefix__-cnt relative z-0 inline-flex shadow-sm rounded-md">
+        <bx_if:show_do_vote_up>
+            <span class="sys-action-element-holder __style_prefix__-element-holder __style_prefix__-eh-up -mr-px border relative inline-flex items-center px-1.5 py-1 rounded-l-md shadow-sm hover:shadow active:shadow-none font-medium text-xs bg-gray-100 text-gray-600 hover:text-gray-900 active:text-gray-900 border-gray-300  active:bg-gray-300  active:border-gray-400 hover:bg-white dark:bg-gray-700 dark:border-gray-600 dark:hover:bg-gray-700/50  dark:active:bg-gray-800 dark:active:border-gray-700  dark:text-gray-300 dark:hover:text-white dark:active:text-gray-200">__do_vote__</span>
+        </bx_if:show_do_vote_up>
+        <bx_if:show_counter>
+            <span class="sys-action-counter-holder __style_prefix__-counter-holder  border relative inline-flex items-center px-1.5 py-1 shadow-sm hover:shadow active:shadow-none font-medium text-xs bg-gray-100 text-gray-600 hover:text-gray-900 active:text-gray-900 border-gray-300  active:bg-gray-300  active:border-gray-400 hover:bg-white dark:bg-gray-700 dark:border-gray-600 dark:hover:bg-gray-700/50  dark:active:bg-gray-800 dark:active:border-gray-700  dark:text-gray-300 dark:hover:text-white dark:active:text-gray-200"<bx_if:show_hidden> style="display:none"</bx_if:show_hidden>>__counter__</span>
+        </bx_if:show_counter>
+        <bx_if:show_do_vote_down>
+            <span class="sys-action-element-holder __style_prefix__-element-holder __style_prefix__-eh-down  -ml-px border relative inline-flex items-center px-1.5 py-1 rounded-r-md shadow-sm hover:shadow active:shadow-none font-medium text-xs bg-gray-100 text-gray-600 hover:text-gray-900 active:text-gray-900 border-gray-300  active:bg-gray-300  active:border-gray-400 hover:bg-white dark:bg-gray-700 dark:border-gray-600 dark:hover:bg-gray-700/50  dark:active:bg-gray-800 dark:active:border-gray-700  dark:text-gray-300 dark:hover:text-white dark:active:text-gray-200">__do_vote__</span>
+        </bx_if:show_do_vote_down>
+</span>__script__
+</span>

+ 4 - 0
modules/boonex/forum/updates/13.0.2_13.0.3/source/template/status.html

@@ -0,0 +1,4 @@
+<div class="bx-forum-status-__status_class__ rounded-md px-2 py-1 text-xs">
+    <span class="bx-menu-meta-icon"><i class="sys-icon circle sys-colored"></i></span>
+    <span>__status__</span>
+</div>

+ 28 - 0
modules/boonex/forum/updates/13.0.2_13.0.3/source/template/unit_gallery.html

@@ -0,0 +1,28 @@
+<div onclick="location.href='__content_url__'" class="__class__ bx-base-text-unit bx-forum-unit bx-base-text-unit-gallery bx-def-gal-unit-size flex flex-col w-full p-2 box-border relative inline-block cursor-pointer">
+    <div class="bg-white dark:bg-gray-800 shadow ring-1 ring-gray-300 dark:ring-gray-700 rounded-md xl:mx-auto h-full">
+        <div class="h-full space-y-4 p-1 pb-4 flex flex-col justify-between">
+            <bx_if:thumb>
+                <a href="__content_url__" title="__summary_attr__">   <img class="flex grow-0 w-full aspect-video overflow-y-auto align-top  object-cover rounded" src="__gallery_url__" alt=""></a>  
+            </bx_if:thumb>
+            <div class="grow-none px-3 mt-4 text-lg leading-tight font-semibold text-gray-700 group-hover:text-gray-900 dark:text-gray-200 dark:group-hover:text-white">
+                <a href="__content_url__" title="__summary_attr__" class=" text-lg leading-tight font-semibold text-gray-600 group-hover:text-gray-900 dark:text-gray-300 dark:group-hover:text-white">__title__</a>
+            </div>               
+            <bx_if:no_thumb>  
+                <div class="grow relative rounded w-full max-w-full sm:aspect-video overflow-hidden font-normal text-sm  text-gray-500 group-hover:text-gray-600 dark:text-gray-400 dark:group-hover:text-gray-300">
+                    <div class="absolute top-auto bottom-0  w-full h-1/4 bg-gradient-to-b from-white/0 to-white dark:from-gray-900/0 dark:to-gray-800"></div>
+                    <div class=" px-3">__summary_plain__</div>
+                </div>
+            </bx_if:no_thumb>
+            <div class="px-3">
+                __badges__
+            </div>
+            <bx_if:meta>
+                <div class="bx-base-general-unit-meta flex grow-0 px-2">
+                    <div class="inline-flex flex-wrap text-xs font-medium">
+                        __meta__
+                    </div>
+                </div>
+            </bx_if:meta>
+        </div>
+    </div>
+</div>

+ 51 - 0
modules/boonex/invites/updates/13.0.0_13.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' => 'Invitations',
+    'version_from' => '13.0.0',
+    'version_to' => '13.0.1',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '13.0.0-B2'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/invites/updates/update_13.0.0_13.0.1/',
+    'home_uri' => 'invites_update_1300_1301',
+
+    'module_dir' => 'boonex/invites/',
+    'module_uri' => 'invites',
+
+    'db_prefix' => 'bx_inv_',
+    'class_prefix' => 'BxInv',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 0,
+        'update_files' => 1,
+        'update_languages' => 0,
+        'clear_db_cache' => 0,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Invitations',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

+ 13 - 0
modules/boonex/invites/updates/13.0.0_13.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 BxInvUpdater extends BxDolStudioUpdater
+{
+    function __construct($aConfig)
+    {
+        parent::__construct($aConfig);
+    }
+}

+ 566 - 0
modules/boonex/invites/updates/13.0.0_13.0.1/source/classes/BxInvModule.php

@@ -0,0 +1,566 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Invites Invites
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+bx_import('BxDolAcl');
+
+define('BX_INV_TYPE_FROM_MEMBER', 'from_member');
+define('BX_INV_TYPE_FROM_SYSTEM', 'from_system');
+
+class BxInvModule extends BxDolModule
+{
+    /**
+     * Constructor
+     */
+    function __construct($aModule)
+    {
+        parent::__construct($aModule);
+
+        $this->_oConfig->init($this->_oDb);
+    }
+
+    /**
+     * ACTION METHODS
+     */
+    function actionGetLink()
+    {
+        $iProfileId = $this->getProfileId();
+        $iAccountId = $this->getAccountId($iProfileId);
+
+        $mixedAllowed = $this->isAllowedInvite($iProfileId);
+        if($mixedAllowed !== true)
+            return echoJson(array('message' => $mixedAllowed));
+
+        if(!isAdmin($iAccountId)) {
+            if($this->_oConfig->getCountPerUser() <= 0)
+                return echoJson(array('message' => _t('_bx_invites_err_limit_reached')));
+        }
+
+        $oKeys = BxDolKey::getInstance();
+        if(!$oKeys)
+            return  echoJson(array('message' => _t('_bx_invites_err_not_available')));
+
+        $sKey = $oKeys->getNewKey(false, $this->_oConfig->getKeyLifetime());
+
+        $oForm = $this->getFormObjectInvite();
+        $oForm->insert(array(
+            'account_id' => $iAccountId,
+            'profile_id' => $iProfileId,
+            'key' => $sKey,
+            'email' => '',
+            'date' => time()
+        ));
+        $this->onInvite($iProfileId);
+
+        echoJson(array('popup' => $this->_oTemplate->getLinkPopup(
+            $this->getJoinLink($sKey)
+        )));
+    }
+    
+    public function actionSetSeenMark($Code)
+    {
+        header('Content-Type: image/png');
+        if (isset($Code) && trim($Code) != "")
+            $this->_oDb->updateDateSeenForInvite($Code);
+    }
+
+    /**
+     * SERVICE METHODS
+     */
+    
+    public function serviceGetSafeServices()
+    {
+        return array (
+            'GetBlockInvite' => '',
+            'GetBlockFormInvite' => '',
+            'GetBlockFormRequest' => '',
+        );
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_invites Invitations
+     * @subsection bx_invites-other Other
+     * @subsubsection bx_invites-get_include get_include
+     * 
+     * @code bx_srv('bx_invites', '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_invites-get_include "get_include"
+     */
+    public function serviceGetInclude()
+    {
+        return $this->_oTemplate->getInclude();
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_invites Invitations
+     * @subsection bx_invites-page_blocks Page Blocks
+     * @subsubsection bx_invites-get_block_invite get_block_invite
+     * 
+     * @code bx_srv('bx_invites', 'get_block_invite', [...]); @endcode
+     * 
+     * Get page block for member's Dashboard which displays invitations related info and action(s).
+     *
+     * @return an array describing a block to display on the site or empty string if something is wrong. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
+     * 
+     * @see BxInvModule::serviceGetBlockInvite
+     */
+    /** 
+     * @ref bx_invites-get_block_invite "get_block_invite"
+     */
+    public function serviceGetBlockInvite()
+    {
+        $iProfileId = $this->getProfileId();
+        $iAccountId = $this->getAccountId($iProfileId);
+
+        $mixedAllowed = $this->isAllowedInvite($iProfileId);
+        if($mixedAllowed !== true)
+            return '';
+
+        if(!isAdmin($iAccountId) && $this->_oConfig->getCountPerUser() <= 0)
+            return '';
+
+        return array(
+            'content' => $this->_oTemplate->getBlockInvite($iAccountId, $iProfileId)
+        );
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_invites Invitations
+     * @subsection bx_invites-page_blocks Page Blocks
+     * @subsubsection bx_invites-get_block_form_invite get_block_form_invite
+     * 
+     * @code bx_srv('bx_invites', 'get_block_form_invite', [...]); @endcode
+     * 
+     * Get page block with invite form.
+     *
+     * @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 BxInvModule::serviceGetBlockFormInvite
+     */
+    /** 
+     * @ref bx_invites-get_block_form_invite "get_block_form_invite"
+     */
+    public function serviceGetBlockFormInvite()
+    {
+        $oForm = $this->getFormObjectInvite();
+        $oForm->aInputs['text']['value'] = _t('_bx_invites_msg_invitation');
+
+        $sResult = '';
+        $oForm->initChecker();
+        if($oForm->isSubmittedAndValid()) {
+            
+            $sResult = $this->processFormObjectInvite($oForm);
+            $sResult = MsgBox($sResult);
+        }
+
+        return array(
+            'content' => $sResult . $oForm->getCode()
+        );
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_invites Invitations
+     * @subsection bx_invites-page_blocks Page Blocks
+     * @subsubsection bx_invites-get_block_form_request get_block_form_request
+     * 
+     * @code bx_srv('bx_invites', 'get_block_form_request', [...]); @endcode
+     * 
+     * Get page block with request invitation form.
+     *
+     * @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 BxInvModule::serviceGetBlockFormRequest
+     */
+    /** 
+     * @ref bx_invites-get_block_form_request "get_block_form_request"
+     */
+    public function serviceGetBlockFormRequest()
+    {
+        $mixedResult = $this->_oTemplate->getBlockFormRequest();
+        if(is_array($mixedResult)) {
+            echoJson($mixedResult);
+            exit;
+        }
+
+        return array(
+            'content' => $mixedResult
+        );
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_invites Invitations
+     * @subsection bx_invites-page_blocks Page Blocks
+     * @subsubsection bx_invites-get_block_manage_requests get_block_manage_requests
+     * 
+     * @code bx_srv('bx_invites', 'get_block_manage_requests', [...]); @endcode
+     * 
+     * Get page block with manage invitation requests table.
+     *
+     * @return HTML string with block content to display on the site or empty string if something is wrong. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
+     * 
+     * @see BxInvModule::serviceGetBlockManageRequests
+     */
+    /** 
+     * @ref bx_invites-get_block_manage_requests "get_block_manage_requests"
+     */
+    public function serviceGetBlockManageRequests()
+    {
+        return $this->getBlockManage('requests');
+    }
+    
+    /**
+     * @page service Service Calls
+     * @section bx_invites Invitations
+     * @subsection bx_invites-page_blocks Page Blocks
+     * @subsubsection bx_invites-get_block_manage_invites get_block_manage_requests
+     * 
+     * @code bx_srv('bx_invites', 'get_block_manage_invites', [...]); @endcode
+     * 
+     * Get page block with manage invitations table.
+     *
+     * @return HTML string with block content to display on the site or empty string if something is wrong. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
+     * 
+     * @see BxInvModule::serviceGetBlockManageInvites
+     */
+    /** 
+     * @ref bx_invites-get_block_manage_invites "get_block_manage_invites"
+     */
+    public function serviceGetBlockManageInvites()
+    {
+        return $this->getBlockManage('invites');
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_invites Invitations
+     * @subsection bx_invites-other Other
+     * @subsubsection bx_invites-get_menu_addon_requests get_menu_addon_requests
+     * 
+     * @code bx_srv('bx_invites', 'get_menu_addon_requests', [...]); @endcode
+     * 
+     * Get number or invitation requests.
+     *
+     * @return integer value with number of invitation requests.
+     * 
+     * @see BxInvModule::serviceGetMenuAddonRequests
+     */
+    /** 
+     * @ref bx_invites-get_menu_addon_requests "get_menu_addon_requests"
+     */
+    public function serviceGetMenuAddonRequests()
+    {
+        return array('counter3_value' => $this->_oDb->getRequests(array('type' => 'count_all')));
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_invites Invitations
+     * @subsection bx_invites-other Other
+     * @subsubsection bx_invites-account_add_form_check account_add_form_check
+     * 
+     * @code bx_srv('bx_invites', 'account_add_form_check', [...]); @endcode
+     * 
+     * Perform neccessary checking on join form.
+     *
+     * @return empty string - if join is allowed and should be processed as usual, non-empty string - if join form need to be replaced with this code.
+     * 
+     * @see BxInvModule::serviceAccountAddFormCheck
+     */
+    /** 
+     * @ref bx_invites-account_add_form_check "account_add_form_check"
+     */
+    public function serviceAccountAddFormCheck()
+    {
+        $sReturn = '';
+
+        $oSession = BxDolSession::getInstance();
+        $sKeyCode = $this->_oConfig->getKeyCode();
+
+        $bKey = bx_get($sKeyCode) !== false;
+        if($bKey) {
+            $sKey = bx_process_input(bx_get($sKeyCode));
+
+            $oKeys = BxDolKey::getInstance();
+            if($oKeys && $oKeys->isKeyExists($sKey))
+                $oSession->setValue($sKeyCode, $sKey);
+        }
+
+        $sKey = $oSession->getValue($sKeyCode);
+        if($sKey !== false)
+            return $sReturn;
+
+        if($bKey)
+            $sReturn .= MsgBox(_t('_bx_invites_err_used'));
+        
+        if ($this->_oConfig->isRegistrationByInvitation())
+            $sReturn .= $this->_oTemplate->getBlockRequest();
+
+        return $sReturn;
+    }
+    
+    /**
+     * Data for Notifications module
+     */
+    public function serviceGetNotificationsData()
+    {
+    	$sModule = $this->_aModule['name'];
+
+    	$sEventPrivacy = $sModule . '_allow_view_event_to';
+		if(BxDolPrivacy::getObjectInstance($sEventPrivacy) === false)
+			$sEventPrivacy = '';
+
+        return array(
+            'handlers' => array(
+                array('group' => $sModule . '_object', 'type' => 'insert', 'alert_unit' => $sModule, 'alert_action' => 'request_notify', 'module_name' => $sModule, 'module_method' => 'get_notifications_request', 'module_class' => 'Module', 'module_event_privacy' => $sEventPrivacy),
+            ),
+            'settings' => array(
+                array('group' => 'request', 'unit' => $sModule, 'action' => 'request_notify', 'types' => array('personal')),
+            ),
+            'alerts' => array(
+                array('unit' => $sModule, 'action' => 'request_notify'),
+            )
+        );
+    }
+    
+    /**
+     * Entry post for Notifications module
+     */
+    public function serviceGetNotificationsRequest($aEvent)
+    {  
+        if (getParam('bx_invites_requests_notifications') != 'on')
+             return array();
+        
+        $aRequest = $this->_oDb->getRequests(array('type' => 'by_id', 'value' => $aEvent['object_id']));
+        if (!$aRequest)
+            return array();
+           
+        $CNF = &$this->_oConfig->CNF;
+        $sEntryUrl = BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink($CNF['URL_REQUESTS']);
+            
+		return array(
+			'entry_sample' => $aRequest['name'] . '(' . $aRequest['email'] . ')',
+			'entry_url' => $sEntryUrl,
+			'entry_caption' => $aRequest['text'],
+			'entry_author' => '',
+			'entry_privacy' => '', //may be empty or not specified. In this case Public privacy will be used.
+			'lang_key' => '_bx_invites_alert_action_request', //may be empty or not specified. In this case the default one from Notification module will be used.
+		);
+    }
+    
+    
+    public function attachAccountIdToInvite($iAccountId, $sKey)
+    {
+        $this->_oDb->attachAccountIdToInvite($iAccountId, $sKey);
+    }
+    
+    public function invite($sType, $sEmails, $sText, $mixedLimit = false, $oForm = null)
+    {
+        $iProfileId = $this->getProfileId();
+        $iAccountId = $this->getAccountId($iProfileId);
+
+        $oKeys = BxDolKey::getInstance();
+        if(!$oKeys || !in_array($sType, array(BX_INV_TYPE_FROM_MEMBER, BX_INV_TYPE_FROM_SYSTEM)))
+            return false;
+
+        $iKeyLifetime = $this->_oConfig->getKeyLifetime();
+
+        $sEmailTemplate = '';
+        switch($sType) {
+            case BX_INV_TYPE_FROM_MEMBER:
+                $sEmailTemplate = 'bx_invites_invite_form_message';
+                break;
+
+            case BX_INV_TYPE_FROM_SYSTEM:
+                $sEmailTemplate = 'bx_invites_invite_by_request_message';
+                break;
+        }
+
+        if(empty($oForm))
+            $oForm = $this->getFormObjectInvite();
+
+        $aMessage = BxDolEmailTemplates::getInstance()->parseTemplate($sEmailTemplate, array(
+            'text' => $sText
+        ), $iAccountId, $iProfileId);
+
+        $aAccountIds = array();
+        $iDate = time();
+        $aEmails = preg_split("/[\s\n,;]+/", $sEmails);
+        if(is_array($aEmails) && !empty($aEmails)){
+            foreach($aEmails as $sEmail) {
+                if($mixedLimit !== false && (int)$mixedLimit <= 0)
+                    break;
+
+                $sEmail = trim($sEmail);
+                if(empty($sEmail))
+                    continue;
+
+                $sKey = $oKeys->getNewKey(false, $iKeyLifetime);
+                if(sendMail($sEmail, $aMessage['Subject'], $aMessage['Body'], 0, array('join_url' => $this->getJoinLink($sKey), 'seen_image_url' => $this->getSeenImageUrl($sKey)), BX_EMAIL_SYSTEM)) {
+                    $iInviteId = (int)$this->_oDb->insertInvite($iAccountId, $iProfileId, $sKey, $sEmail, $iDate);
+                    array_push($aAccountIds, $iInviteId);
+                    
+                    $this->onInvite($iProfileId);
+                    
+                    if($mixedLimit !== false)
+                        $mixedLimit -= 1;
+                }
+            }
+        }
+        return $aAccountIds;
+    }
+    
+    public function processFormObjectInvite($oForm)
+    {
+        $iProfileId = $this->getProfileId();
+        $iAccountId = $this->getAccountId($iProfileId);
+
+        $mixedAllowed = $this->isAllowedInvite($iProfileId);
+        if($mixedAllowed !== true)
+            return $mixedAllowed;
+
+        $mixedInvites = false;
+        if(!isAdmin($iAccountId)) {
+            if( $this->_oConfig->getCountPerUser() <= 0)
+                return _t('_bx_invites_err_limit_reached');
+        }
+        
+        $sEmails = bx_process_input($oForm->getCleanValue('emails'));
+        $sText = bx_process_pass($oForm->getCleanValue('text'));
+        $mixedResult = $this->invite(BX_INV_TYPE_FROM_MEMBER, $sEmails, $sText, $mixedInvites, $oForm);
+        $this->onInvite($iProfileId);
+        if($mixedResult !== false)
+            $sResult = _t('_bx_invites_msg_invitation_sent', count($mixedResult));
+        else
+            $sResult = _t('_bx_invites_err_not_available');
+        
+        return  $sResult;
+    }
+
+    public function isAllowedInvite($iProfileId, $bPerform = false)
+    {
+        $aCheckResult = checkActionModule($iProfileId, 'invite', $this->getName(), $bPerform);
+        return $aCheckResult[CHECK_ACTION_RESULT] !== CHECK_ACTION_RESULT_ALLOWED ? $aCheckResult[CHECK_ACTION_MESSAGE] : true;
+    }
+
+    public function isAllowedRequest($iProfileId, $bPerform = false)
+    {
+        $aCheckResult = checkActionModule($iProfileId, 'request', $this->getName(), $bPerform);
+        return $aCheckResult[CHECK_ACTION_RESULT] !== CHECK_ACTION_RESULT_ALLOWED ? $aCheckResult[CHECK_ACTION_MESSAGE] : true;
+    }
+
+    public function isAllowedDeleteRequest($iProfileId, $bPerform = false)
+    {
+        $aCheckResult = checkActionModule($iProfileId, 'delete request', $this->getName(), $bPerform);
+        return $aCheckResult[CHECK_ACTION_RESULT] !== CHECK_ACTION_RESULT_ALLOWED ? $aCheckResult[CHECK_ACTION_MESSAGE] : true;
+    }
+    
+    public function isAllowedDeleteInvite($iProfileId, $bPerform = false)
+    {
+        $aCheckResult = checkActionModule($iProfileId, 'delete invite', $this->getName(), $bPerform);
+        return $aCheckResult[CHECK_ACTION_RESULT] !== CHECK_ACTION_RESULT_ALLOWED ? $aCheckResult[CHECK_ACTION_MESSAGE] : true;
+    }
+
+    public function getProfileId()
+    {
+        return isLogged() ? bx_get_logged_profile_id() : 0;
+    }
+
+    public function getProfileObject($iProfileId = 0)
+    {
+        $oProfile = BxDolProfile::getInstance($iProfileId);
+        if (!$oProfile)
+            $oProfile = BxDolProfileUndefined::getInstance();
+
+        return $oProfile;
+    }
+
+    public function getAccountId($iProfileId)
+    {
+        $oProfile = $this->getProfileObject($iProfileId);
+        if($oProfile->id() == 0)
+            return 0;
+
+        return $oProfile->getAccountId();
+    }
+
+    public function onRequest($iRequestId)
+    {
+        //--- Event -> Request for Alerts Engine ---//
+        bx_alert($this->_oConfig->getObject('alert'), 'request', $iRequestId);
+        $aProfiles = BxDolAclQuery::getInstance()->getProfilesByMembership(array(MEMBERSHIP_ID_MODERATOR, MEMBERSHIP_ID_ADMINISTRATOR));
+        foreach($aProfiles as $aProfile) {
+            bx_alert($this->_oConfig->getObject('alert'), 'request_notify', $iRequestId, 0, array('parent_author_id' => $aProfile['id']));
+        }
+        //--- Event -> Request for Alerts Engine ---//
+    }
+
+    public function getFormObjectInvite($sDisplay = '')
+    {
+        if(empty($sDisplay))
+            $sDisplay = $this->_oConfig->getObject('form_display_invite_send');
+
+        bx_import('FormCheckerHelper', $this->_aModule);
+        return BxDolForm::getObjectInstance($this->_oConfig->getObject('form_invite'), $sDisplay);
+    }
+    
+    protected function getBlockManage($sType)
+    {
+        $this->_oTemplate->addJs('jquery.form.min.js');
+        $this->_oTemplate->addJs('main.js');
+        $oGrid = BxDolGrid::getObjectInstance($this->_oConfig->getObject('grid_' . $sType));
+        if(!$oGrid)
+            return '';
+
+        $this->_oTemplate->addCss(array('main.css'));
+        $this->_oTemplate->addJsTranslation(array('_sys_grid_search'));
+       
+        return array(
+           'menu' => $this->_oTemplate->getMenuForManageBlocks($sType),
+           'content' => $this->_oTemplate->getJsCode('main', array('grid' => $sType)) . $oGrid->getCode()
+       );
+    }
+
+    public function onInvite($iProfileId)
+    {
+        $this->isAllowedInvite($iProfileId, true);
+
+        //--- Event -> Invite for Alerts Engine ---//
+        bx_alert($this->_oConfig->getObject('alert'), 'invite', 0, $iProfileId);
+        //--- Event -> Invite for Alerts Engine ---//
+    }
+    
+    public function getJoinLink($sKey)
+    {
+        $sKeyCode = $this->_oConfig->getKeyCode();
+
+        $sJoinUrl = BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink('page.php?i=create-account');
+        return bx_append_url_params($sJoinUrl, array($sKeyCode => $sKey));
+    }
+    
+    public function getSeenImageUrl($sKey)
+    {
+        return  BX_DOL_URL_ROOT . $this->_oConfig->getBaseUri() . 'SetSeenMark/' . $sKey . "/";
+    }
+
+}
+
+/** @} */

+ 279 - 0
modules/boonex/invites/updates/13.0.0_13.0.1/source/classes/BxInvTemplate.php

@@ -0,0 +1,279 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Invites Invites
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxInvTemplate extends BxBaseModGeneralTemplate
+{
+    function __construct(&$oConfig, &$oDb)
+    {
+        parent::__construct($oConfig, $oDb);
+    }
+
+    public function getCssJs()
+    {
+        $this->addCss(array(
+            'main.css',
+        ));
+
+        $this->addJs(array(
+            'clipboard.min.js',
+            'jquery.form.min.js',
+            'jquery.anim.js',
+            'main.js'
+        ));
+    }
+
+    public function getInclude()
+    {
+        $this->getCssJs();
+        return $this->getJsCode('main');
+    }
+
+    public function getBlockRequestText($aRequest)
+    {
+        return $this->parseHtmlByName('request_text.html', array(
+            'style_prefix' => $this->_oConfig->getPrefix('style'),
+            'text' => bx_process_output(nl2br($aRequest['text']), BX_DATA_TEXT_MULTILINE),
+        ));
+    }
+    
+    public function getBlockInviteInfo($aRequest)
+    {
+        $aVars = array(
+            'date_sent_title' => _t('_bx_invites_title_date_invite_sent'),
+            'date_seen_title' => _t('_bx_invites_title_date_invite_seen'),
+            'bx_repeat:items' => array()
+        );
+        foreach ($aRequest as $r) {
+            $aVars['bx_repeat:items'][] = array (
+                 'date_sent' => bx_time_js($r['date'], BX_FORMAT_DATE_TIME, true),
+                 'date_seen' => ($r['date_seen'] != '' ? bx_time_js($r['date_seen'], BX_FORMAT_DATE_TIME, true) : ' - ')
+            );
+        }
+        return $this->parseHtmlByName('invite_info.html', $aVars);
+    }
+    
+    public function getBlockInvite($iAccountId, $iProfileId)
+    {
+        $mInvitesRemain = $this->_oConfig->getCountPerUser();
+		if ($mInvitesRemain === true)
+			$mInvitesRemain = _t('_bx_invites_txt_unlimited');
+           
+        $sUrl = BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink($this->_oConfig->CNF['URL_INVITE']);
+
+        $this->getCssJs();
+        return $this->parseHtmlByName('block_invite.html', array(
+            'style_prefix' => $this->_oConfig->getPrefix('style'),
+            'js_object' => $this->_oConfig->getJsObject('main'),
+            'text' => _t('_bx_invites_txt_invite_block_text', $mInvitesRemain),
+            'url' => $sUrl,
+            'js_code' => $this->getJsCode('main')
+        ));
+    }
+
+    public function getBlockRequest()
+    {
+        $sUrl = BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink($this->_oConfig->CNF['URL_REQUEST']);
+
+        $this->getCssJs();
+        return $this->parseHtmlByName('block_request.html', array(
+            'style_prefix' => $this->_oConfig->getPrefix('style'),
+            'text' => _t('_bx_invites_txt_request_block_text'),
+            'bx_if:show_button_request' => array(
+                'condition' => $this->_oConfig->isRequestInvite(),
+                'content' => array(
+                    'url' => $sUrl
+                )
+            )
+        ));
+    }
+    public function getBlockFormRequest()
+    {
+        if(!$this->_oConfig->isRequestInvite())
+            return MsgBox(_t('_bx_invites_err_not_available'));
+
+        $mixedAllowed = $this->getModule()->isAllowedRequest(0);
+        if($mixedAllowed !== true)
+            return MsgBox($mixedAllowed);
+
+        $CNF = &$this->_oConfig->CNF;
+
+        $sJsObject = $this->_oConfig->getJsObject('main');
+        $oPermalink = BxDolPermalinks::getInstance();
+
+        $oForm = BxDolForm::getObjectInstance($this->_oConfig->getObject('form_request'), $this->_oConfig->getObject('form_display_request_send'));
+        $oForm->aFormAttrs['action'] = BX_DOL_URL_ROOT . $oPermalink->permalink($CNF['URL_REQUEST']);
+
+        $sFormId = $oForm->getId();
+        $sEval = $sJsObject . '.onRequestFormSubmit(oData)';
+
+        $oForm->initChecker();
+        if(!$oForm->isSubmittedAndValid()) {
+            $sForm = $oForm->getCode();
+            if(!$oForm->isSubmitted()) {
+                $this->getCssJs();
+                return $this->parseHtmlByName('block_request_form.html', array(
+                    'style_prefix' => $this->_oConfig->getPrefix('style'),
+                    'js_object' => $sJsObject,
+                    'js_code' => $this->getJsCode('main'),
+                    'form' => $sForm,
+                    'form_id' => $sFormId,
+                ));
+            }
+
+            if(!$oForm->isValid())
+                return array('content' => $sForm, 'content_id' => $sFormId, 'eval' => $sEval);
+        }
+        
+        $sEmail = $oForm->getCleanValue('email');
+        $oAccountQuery = BxDolAccountQuery::getInstance();
+        $iAccount = $oAccountQuery->getIdByEmail($sEmail);
+        if ($iAccount > 0)
+            return array('content' => MsgBox(_t('_bx_invites_err_already_registed', BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink('page.php?i=forgot-password'))), 'content_id' => $sFormId, 'eval' => $sEval);
+        $iCountByEmail = $this->_oDb->getRequests(array('type' => 'count_by_email', 'value' => $sEmail));
+        if ($iCountByEmail > 0)
+            return array('content' => MsgBox(_t('_bx_invites_err_already_send')), 'content_id' => $sFormId, 'eval' => $sEval);
+       
+        $sIp = getVisitorIP();
+        $iId = (int)$oForm->insert(array('nip' => ip2long($sIp),'date' => time()));
+        if(!$iId)
+            return array('content' => MsgBox(_t('_bx_invites_err_cannot_perform')), 'content_id' => $sFormId, 'eval' => $sEval);
+        $this->getModule()->onRequest($iId);
+        $sRequestsEmail = $this->_oConfig->getRequestsEmail();
+        if(!empty($sRequestsEmail)) {
+            $sManageUrl = BX_DOL_URL_ROOT . $oPermalink->permalink($CNF['URL_REQUESTS']);
+
+            $aMessage = BxDolEmailTemplates::getInstance()->parseTemplate('bx_invites_request_form_message', array(
+                'sender_name' => bx_process_output($oForm->getCleanValue('name')),
+                'sender_email' => bx_process_output($oForm->getCleanValue('email')),
+                'sender_ip' => $sIp,
+                'manage_url' => $sManageUrl
+            ));
+            
+            $aRequestsEmails = explode(',', $sRequestsEmail);
+            foreach ($aRequestsEmails as $s) {
+                sendMail(trim($s), $aMessage['Subject'], $aMessage['Body'], 0, array(), BX_EMAIL_SYSTEM);
+            }
+        }
+
+        return array('content' => MsgBox(_t('_bx_invites_msg_request_sent')), 'content_id' => $sFormId, 'eval' => $sEval);
+    }
+
+    public function getLinkPopup($sLink)
+    {
+        $sId = $this->_oConfig->getHtmlIds('link_popup');
+        $sTitle = _t('_bx_invites_txt_link_popup_title');
+        $sContent = $this->parseHtmlByName('popup_link.html', array(
+            'style_prefix' => $this->_oConfig->getPrefix('style'),
+            'html_id_link' => $this->_oConfig->getHtmlIds('link_input'),
+            'link' => $sLink
+        ));
+
+        return BxTemplFunctions::getInstance()->popupBox($sId, $sTitle, $sContent, true);
+    }
+    
+    public function getJsCode($sType, $aParams = array(), $mixedWrap = true)
+    {
+        $sGrid = 'requests';
+        if(!empty($aParams['grid'])) {
+            $sGrid = $aParams['grid'];
+            unset($aParams['grid']);
+        }
+
+        $aParams = array_merge(array(
+            'aHtmlIds' => $this->_oConfig->getHtmlIds(),
+            'sObjNameGrid' => $this->_oConfig->getObject('grid_' . $sGrid),
+        ), $aParams);
+
+        return parent::getJsCode($sType, $aParams);
+    }
+
+    public function getMenuForManageBlocks($sType)
+    {
+        $CNF = &$this->_oConfig->CNF;
+        
+        $sMenu = '';
+		$oPermalink = BxDolPermalinks::getInstance();
+
+		$aMenuItems = array();
+		$aMenuItems[] = array('id' => 'invites-requests', 'name' => 'invites-requests', 'class' => '', 'link' => $oPermalink->permalink($CNF['URL_REQUESTS']), 'target' => '_self', 'title' => _t('_bx_invites_menu_item_title_manage_requests'), 'active' => 1);
+		$aMenuItems[] = array('id' => 'invites-invites', 'name' => 'invites-invites', 'class' => '', 'link' => $oPermalink->permalink($CNF['URL_INVITES']), 'target' => '_self', 'title' => _t('_bx_invites_menu_item_title_manage_invites'), 'active' => 1);
+
+		if(count($aMenuItems) > 1) {
+	        $oMenu = new BxTemplMenu(array(
+	            'template' => 'menu_vertical.html', 
+	            'menu_items' => $aMenuItems
+	        ), $this);
+	        $oMenu->setSelected($this->getModule()->_aModule['name'], 'invites-' . $sType);
+	        $sMenu = $oMenu->getCode();
+		}
+        return $sMenu;
+    }
+    
+    public function getProfilesByAccount($iAccountId, $iMaxVisible = 2)
+    {
+        $aProfiles = BxDolAccount::getInstance($iAccountId)->getProfiles();
+        $iProfiles = count($aProfiles);
+
+        $aTmplVars = array (
+            'class_cnt' => '',
+            'bx_repeat:profiles' => array(),
+            'bx_if:profiles_more' => array(
+                'condition' => $iProfiles > $iMaxVisible,
+                'content' => array(
+                    'html_id' => $this->_oConfig->getHtmlIds('profile_more_popup') . $iAccountId,
+                    'more' => _t('_bx_accnt_txt_more', $iProfiles - $iMaxVisible),
+                    'more_attr' => bx_html_attribute(_t('_bx_accnt_txt_see_more')),
+                    'popup' => '',
+                ),
+            ),
+        );
+
+        $aTmplVarsPopup = array (
+            'class_cnt' => ' bx-def-padding',
+            'bx_repeat:profiles' => array(),
+            'bx_if:profiles_more' => array(
+                'condition' => false,
+                'content' => array(),
+            ),
+        );
+
+        $i = 0;
+        foreach ($aProfiles as $iProfileId => $aProfile) {
+            $oProfile = BxDolProfile::getInstance($iProfileId);
+            if(!$oProfile)
+                continue;
+
+            $sName = $oProfile->getDisplayName();
+            $aTmplVarsProfile = array (
+                'html_id' => $this->_oConfig->getHtmlIds('profile') . $aProfile['id'],
+                'id' => $oProfile->id(),
+                'url' => $oProfile->getUrl(),
+                'name' => $sName,
+                'name_attr' => bx_html_attribute($sName)
+            );
+
+            if($i < $iMaxVisible)
+                $aTmplVars['bx_repeat:profiles'][] = $aTmplVarsProfile;
+            if($i >= $iMaxVisible)
+                $aTmplVarsPopup['bx_repeat:profiles'][] = $aTmplVarsProfile;
+
+            ++$i;
+        }
+
+        if($aTmplVarsPopup['bx_repeat:profiles']) {
+            $aTmplVars['bx_if:profiles_more']['content']['popup'] = BxTemplFunctions::getInstance()->transBox('', $this->parseHtmlByName('profiles.html', $aTmplVarsPopup));
+        }
+
+        return $this->parseHtmlByName('profiles.html', $aTmplVars);
+    }
+}
+
+/** @} */

+ 80 - 0
modules/boonex/invites/updates/13.0.0_13.0.1/source/install/config.php

@@ -0,0 +1,80 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Invites Invites
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_invites',
+    'title' => 'Invitations',
+    'note' => 'Invitations module.',
+    'version' => '13.0.1',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '13.0.0-B2'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/invites/',
+    'home_uri' => 'invites',
+
+    'db_prefix' => 'bx_inv_',
+    'class_prefix' => 'BxInv',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Invitations',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'uninstall' => array (
+        '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,
+    ),
+    'disable' => array (
+        'execute_sql' => 1,
+        'update_relations' => 1,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Dependencies Section
+     */
+    'dependencies' => array(),
+    
+    /**
+      * Relations Section
+      */
+    'relations' => array(
+    	'bx_notifications'
+    ),
+);
+
+/** @} */

+ 51 - 0
modules/boonex/market/updates/13.0.2_13.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' => '13.0.2',
+    'version_to' => '13.0.3',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '13.0.0-B2'
+    ),
+
+    /**
+     * '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_13.0.2_13.0.3/',
+    'home_uri' => 'market_update_1302_1303',
+
+    '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(),
+);

+ 23 - 0
modules/boonex/market/updates/13.0.2_13.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 BxMarketUpdater extends BxDolStudioUpdater
+{
+    function __construct($aConfig)
+    {
+        parent::__construct($aConfig);
+    }
+
+    public function actionExecuteSql($sOperation)
+    {
+        if($sOperation == 'install') {
+            if(!$this->oDb->isFieldExists('bx_market_products', 'cover_raw'))
+                $this->oDb->query("ALTER TABLE `bx_market_products` ADD `cover_raw` text NOT NULL AFTER `cover`");
+        }
+
+        return parent::actionExecuteSql($sOperation);
+    }
+}

+ 6 - 0
modules/boonex/market/updates/13.0.2_13.0.3/install/langs/en.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources name="en" flag="gb" title="English">
+    <string_add name="_bx_market_form_entry_input_sys_cover_raw"><![CDATA[Header Image RAW]]></string_add>
+	<string_add name="_bx_market_form_entry_input_cover_raw"><![CDATA[Header Image RAW]]></string_add>
+    <string_add name="_bx_market_form_entry_input_cover_raw_inf"><![CDATA[If provided, it'll be used instead of image based variant.]]></string_add>
+</resources>

+ 13 - 0
modules/boonex/market/updates/13.0.2_13.0.3/install/sql/install.sql

@@ -0,0 +1,13 @@
+-- STORAGES & TRANSCODERS
+UPDATE `sys_objects_storage` SET `ext_allow`='jpg,jpeg,jpe,gif,png,svg' WHERE `object`='bx_market_photos';
+
+
+-- FORMS
+DELETE FROM `sys_form_inputs` WHERE `object`='bx_market' AND `name`='cover_raw';
+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_market', 'bx_market', 'cover_raw', '', '', 0, 'textarea', '_bx_market_form_entry_input_sys_cover_raw', '_bx_market_form_entry_input_cover_raw', '_bx_market_form_entry_input_cover_raw_inf', 0, 0, 0, '', '', '', '', '', '', 'XssHtml', '', 1, 0);
+
+DELETE FROM `sys_form_display_inputs` WHERE `display_name` IN ('bx_market_entry_add', 'bx_market_entry_edit') AND `input_name`='cover_raw';
+INSERT INTO `sys_form_display_inputs`(`display_name`, `input_name`, `visible_for_levels`, `active`, `order`) VALUES 
+('bx_market_entry_add', 'cover_raw', 2147483647, 0, 4),
+('bx_market_entry_edit', 'cover_raw', 2147483647, 0, 4);

+ 53 - 0
modules/boonex/market/updates/13.0.2_13.0.3/source/classes/BxMarketAlertsResponse.php

@@ -0,0 +1,53 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Market Market
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxMarketAlertsResponse extends BxBaseModTextAlertsResponse
+{
+    public function __construct()
+    {
+        $this->MODULE = 'bx_market';
+        parent::__construct();
+    }
+
+	public function response($oAlert)
+    {
+    	$sMethod = 'process' . bx_gen_method_name($oAlert->sUnit . '_' . $oAlert->sAction);
+    	if(method_exists($this, $sMethod))
+    		$this->$sMethod($oAlert);
+
+        parent::response($oAlert);
+    }
+
+    protected function processBxMarketFilesFileDeleted(&$oAlert)
+    {
+		BxDolModule::getInstance($this->MODULE)->_oDb->deassociateFileWithContent(0, $oAlert->iObject);
+    }
+
+    protected function processBxMarketFilesFileDownloaded(&$oAlert)
+    {
+    	$oModule = BxDolModule::getInstance($this->MODULE);
+
+    	$iFile = $oAlert->iObject;
+    	$aFile = $oModule->_oDb->getFile(array('type' => 'file_id', 'file_id' => $iFile));
+    	if(empty($aFile) || !is_array($aFile))
+    		return;
+
+    	$oModule->_oDb->updateFile(array('downloads' => $aFile['downloads'] + 1), array('file_id' => $iFile));
+    	$oModule->_oDb->insertDownload($iFile, $oAlert->iSender, bx_get_ip_hash($oAlert->aExtras['profile_ip']));
+    }
+
+    protected function processBxMarketPhotosFileDeleted(&$oAlert)
+    {
+    	BxDolModule::getInstance($this->MODULE)->_oDb->deassociatePhotoWithContent(0, $oAlert->iObject);
+    }
+}
+
+/** @} */

+ 273 - 0
modules/boonex/market/updates/13.0.2_13.0.3/source/classes/BxMarketConfig.php

@@ -0,0 +1,273 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Market Market
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxMarketConfig extends BxBaseModTextConfig
+{
+    protected $_aCurrency;
+
+    function __construct($aModule)
+    {
+        parent::__construct($aModule);
+
+        $aMenuItems2Methods = array (
+            'hide-product' => 'checkAllowedHide',
+            'unhide-product' => 'checkAllowedUnhide',
+            'approve' => 'checkAllowedApprove',
+            'edit-product' => 'checkAllowedEdit',
+            'delete-product' => 'checkAllowedDelete',
+            'product-more' => 'checkAllowedViewMoreMenu'
+        );
+
+        $this->CNF = array (
+
+            // module icon
+            'ICON' => 'shopping-cart col-green3',
+
+            // database tables
+            'TABLE_ENTRIES' => $aModule['db_prefix'] . 'products',
+            'TABLE_ENTRIES_FULLTEXT' => 'title_text',
+            'TABLE_PHOTOS2ENTRIES' => $aModule['db_prefix'] . 'photos2products',
+            'TABLE_FILES2ENTRIES' => $aModule['db_prefix'] . 'files2products',
+            'TABLE_FILES' => $aModule['db_prefix'] . 'files',
+            'TABLE_DOWNLOADS' => $aModule['db_prefix'] . 'downloads_track',
+            'TABLE_LICENSES' => $aModule['db_prefix'] . 'licenses',
+            'TABLE_LICENSES_DELETED' => $aModule['db_prefix'] . 'licenses_deleted',
+
+            // database fields
+            'FIELD_ID' => 'id',
+            'FIELD_AUTHOR' => 'author',
+            'FIELD_ADDED' => 'added',
+            'FIELD_CHANGED' => 'changed',
+            'FIELD_NAME' => 'name',
+            'FIELD_TITLE' => 'title',
+            'FIELD_TEXT' => 'text',
+            'FIELD_TEXT_ID' => 'product-text',
+            'FIELD_CATEGORY' => 'cat',
+            'FIELD_HEADER_BEG_SINGLE' => 'header_beg_single',
+            'FIELD_WARNING_SINGLE' => 'warning_single',
+            'FIELD_PRICE_SINGLE' => 'price_single',
+            'FIELD_HEADER_END_SINGLE' => 'header_end_single',
+            'FIELD_HEADER_BEG_RECURRING' => 'header_beg_recurring',
+            'FIELD_WARNING_RECURRING' => 'warning_recurring',
+            'FIELD_PRICE_RECURRING' => 'price_recurring',
+            'FIELD_DURATION_RECURRING' => 'duration_recurring',
+            'FIELD_TRIAL_RECURRING' => 'trial_recurring',
+            'FIELD_HEADER_END_RECURRING' => 'header_end_recurring',
+            'FIELD_ALLOW_VIEW_TO' => 'allow_view_to',
+            'FIELD_ALLOW_PURCHASE_TO' => 'allow_purchase_to',
+            'FIELD_ALLOW_COMMENT_TO' => 'allow_comment_to',
+            'FIELD_ALLOW_VOTE_TO' => 'allow_vote_to',
+            'FIELD_CF' => 'cf',
+            'FIELD_SUBENTRIES' => 'subentries',
+            'FIELD_PHOTO' => 'pictures',
+            'FIELD_THUMB' => 'thumb',
+            'FIELD_COVER_RAW' => 'cover_raw',
+            'FIELD_COVER' => 'cover',
+            'FIELD_FILE' => 'files',
+            'FIELD_PACKAGE' => 'package',
+            'FIELD_NOTES_PURCHASED' => 'notes_purchased',
+            'FIELD_VIEWS' => 'views',
+            'FIELD_COMMENTS' => 'comments',
+            'FIELD_FEATURED' => 'featured',
+            'FIELD_STATUS' => 'status',
+            'FIELD_STATUS_ADMIN' => 'status_admin',
+            'FIELD_LOCATION' => 'location',
+            'FIELD_LOCATION_PREFIX' => 'location',
+            'FIELD_LABELS' => 'labels',
+            'FIELDS_QUICK_SEARCH' => array('title'),
+            'FIELDS_WITH_KEYWORDS' => 'auto', // can be 'auto', array of fields or comma separated string of field names, works only when OBJECT_METATAGS is specified
+            
+            // page URIs
+            'URI_VIEW_ENTRY' => 'view-product',
+            'URI_AUTHOR_ENTRIES' => 'products-author',
+            'URI_ENTRIES_BY_CONTEXT' => 'products-context',
+            'URI_ADD_ENTRY' => 'create-product',
+            'URI_EDIT_ENTRY' => 'edit-product',
+            'URI_DOWNLOAD_ENTRY' => 'download-product',
+            'URI_MANAGE_COMMON' => 'products-manage',
+            'URI_FAVORITES_LIST' => 'products-favorites',
+
+            'URL_HOME' => 'page.php?i=products-home',
+            'URL_LATEST' => 'page.php?i=products-latest',
+            'URL_FEATURED' => 'page.php?i=products-featured',
+            'URL_POPULAR' => 'page.php?i=products-popular',
+            'URL_TOP' => 'page.php?i=products-top',
+            'URL_UPDATED' => 'page.php?i=products-updated',
+            'URL_MANAGE_COMMON' => 'page.php?i=products-manage',
+            'URL_MANAGE_ADMINISTRATION' => 'page.php?i=products-administration',
+            'URL_LICENSES_COMMON' => 'page.php?i=products-licenses',
+            'URL_LICENSES_ADMINISTRATION' => 'page.php?i=products-licenses-administration',
+            'URL_VIEW_ENTRY' => 'page.php?i=view-product&id=',
+
+            // some params
+            'PARAM_AUTO_APPROVE' => 'bx_market_enable_auto_approve',
+            'PARAM_CHARS_SUMMARY' => 'bx_market_summary_chars',
+            'PARAM_CHARS_SUMMARY_PLAIN' => 'bx_market_plain_summary_chars',
+            'PARAM_NUM_RSS' => 'bx_market_rss_num',
+            'PARAM_SEARCHABLE_FIELDS' => 'bx_market_searchable_fields',
+            'PARAM_PER_PAGE_FOR_FAVORITES_LISTS' => 'bx_market_per_page_for_favorites_lists',
+
+            // objects            
+            'OBJECT_STORAGE' => 'bx_market_photos',
+            'OBJECT_STORAGE_FILES' => 'bx_market_files',
+            'OBJECT_IMAGES_TRANSCODER_PREVIEW' => 'bx_market_preview',
+            'OBJECT_IMAGES_TRANSCODER_ICON' => 'bx_market_icon',
+            'OBJECT_IMAGES_TRANSCODER_THUMB' => 'bx_market_thumb',
+            'OBJECT_IMAGES_TRANSCODER_COVER' => 'bx_market_cover',
+            'OBJECT_IMAGES_TRANSCODER_SCREENSHOT' => 'bx_market_screenshot',
+            'OBJECT_IMAGES_TRANSCODER_GALLERY' => 'bx_market_gallery',
+            'OBJECT_VIDEOS_TRANSCODERS' => array(),
+            'OBJECT_REPORTS' => 'bx_market',
+            'OBJECT_VIEWS' => 'bx_market',
+            'OBJECT_VOTES' => 'bx_market',
+            'OBJECT_REACTIONS' => 'bx_market_reactions',
+            'OBJECT_SCORES' => 'bx_market',
+            'OBJECT_FAVORITES' => 'bx_market',
+            'OBJECT_FEATURED' => 'bx_market',
+            'OBJECT_METATAGS' => 'bx_market',
+            'OBJECT_COMMENTS' => 'bx_market',
+            'OBJECT_NOTES' => 'bx_market_notes',
+            'OBJECT_CATEGORY' => 'bx_market_cats',
+            'OBJECT_PRIVACY_VIEW' => 'bx_market_allow_view_to',
+            'OBJECT_PRIVACY_LIST_VIEW' => 'bx_market_allow_view_favorite_list',
+            'OBJECT_PRIVACY_PURCHASE' => 'bx_market_allow_purchase_to',
+            'OBJECT_PRIVACY_COMMENT' => 'bx_market_allow_comment_to',
+            'OBJECT_PRIVACY_VOTE' => 'bx_market_allow_vote_to',
+            'OBJECT_FORM_ENTRY' => 'bx_market',
+            'OBJECT_FORM_ENTRY_DISPLAY_VIEW' => 'bx_market_entry_view',
+            'OBJECT_FORM_ENTRY_DISPLAY_VIEW_FULL' => 'bx_market_entry_view_full',
+            'OBJECT_FORM_ENTRY_DISPLAY_ADD' => 'bx_market_entry_add',
+            'OBJECT_FORM_ENTRY_DISPLAY_EDIT' => 'bx_market_entry_edit',
+            'OBJECT_FORM_ENTRY_DISPLAY_DELETE' => 'bx_market_entry_delete',
+            'OBJECT_MENU_ACTIONS_VIEW_ENTRY' => 'bx_market_view', // actions menu on view entry page
+            'OBJECT_MENU_ACTIONS_VIEW_ENTRY_MORE' => 'bx_market_view_more', 
+            'OBJECT_MENU_ACTIONS_VIEW_ENTRY_ALL' => 'bx_market_view_actions', // all actions menu on view entry page
+            'OBJECT_MENU_ACTIONS_MY_ENTRIES' => 'bx_market_my', // actions menu on my entries page
+            'OBJECT_MENU_ACTIONS_SNIPPET' => 'bx_market_snippet', // actions menu for entry snippet
+            'OBJECT_MENU_ACTIONS_SNIPPET_MORE' => 'bx_market_snippet_more', // actions menu (short) from view entry page but created for snippet actions menu
+            'OBJECT_MENU_SUBMENU' => 'bx_market_submenu', // main module submenu
+            'OBJECT_MENU_SUBMENU_VIEW_ENTRY' => 'bx_market_view_submenu', // view entry submenu
+            'OBJECT_MENU_SUBMENU_VIEW_ENTRY_MAIN_SELECTION' => 'products-home', // first item in view entry submenu from main module submenu
+            'OBJECT_MENU_SNIPPET_META' => 'bx_market_snippet_meta', // menu for snippet meta info
+            'OBJECT_MENU_MANAGE_TOOLS' => 'bx_market_menu_manage_tools', //manage menu in content administration tools
+            'OBJECT_MENU_LICENSES' => 'bx_market_licenses_submenu',
+            'OBJECT_GRID_ADMINISTRATION' => 'bx_market_administration',
+            'OBJECT_GRID_COMMON' => 'bx_market_common',
+            'OBJECT_GRID_LICENSES_ADMINISTRATION' => 'bx_market_licenses_administration',
+            'OBJECT_GRID_LICENSES' => 'bx_market_licenses',
+            'OBJECT_UPLOADERS' => array('bx_market_simple', 'bx_market_html5'),
+            'OBJECT_CONNECTION_SUBENTRIES' => 'bx_market_subentries',
+            
+            'BADGES_AVALIABLE' => true,
+
+            // menu items which visibility depends on custom visibility checking
+            'MENU_ITEM_TO_METHOD' => array (
+                'bx_market_my' => array (
+                    'create-product' => 'checkAllowedAdd',
+                ),
+                'bx_market_view' => $aMenuItems2Methods,
+                'bx_market_view_more' => $aMenuItems2Methods,
+                'bx_market_snippet_more' => $aMenuItems2Methods,
+            ),
+
+            // informer messages
+            'INFORMERS' => array (
+                'approving' => array (
+                    'name' => 'bx-market-approving',
+                    'map' => array (
+                        'pending' => array('msg' => '_bx_market_txt_msg_status_pending', 'type' => BX_INFORMER_ALERT),
+                        'hidden' => array('msg' => '_bx_market_txt_msg_status_hidden', 'type' => BX_INFORMER_ERROR),
+                    ),
+                ),
+            ),
+
+            // global settings
+            'OPTION_ENABLE_RECURRING' => 'bx_market_enable_recurring',
+            'OPTION_RECURRING_RESERVE' => 'bx_market_recurring_reserve',
+
+            // email templates
+            'ETEMPLATE_PURCHASED' => 'bx_market_purchased',
+
+            // some language keys
+            'T' => array (
+                'txt_sample_single' => '_bx_market_txt_sample_single',
+            	'txt_sample_single_with_article' => '_bx_market_txt_sample_single_with_article',
+            	'txt_sample_comment_single' => '_bx_market_txt_sample_comment_single',
+            	'txt_sample_vote_single' => '_bx_market_txt_sample_vote_single',
+                'txt_sample_reaction_single' => '_bx_market_txt_sample_reaction_single',
+                'txt_sample_score_up_single' => '_bx_market_txt_sample_score_up_single',
+                'txt_sample_score_down_single' => '_bx_market_txt_sample_score_down_single',
+            	'form_field_author' => '_bx_market_form_entry_input_author',
+            	'grid_action_err_delete' => '_bx_market_grid_action_err_delete',
+            	'grid_txt_account_manager' => '_bx_market_grid_txt_account_manager',
+                'filter_item_active' => '_bx_market_grid_filter_item_title_adm_active',
+            	'filter_item_hidden' => '_bx_market_grid_filter_item_title_adm_hidden',
+                'filter_item_pending' => '_bx_market_grid_filter_item_title_adm_pending',
+            	'filter_item_select_one_filter1' => '_bx_market_grid_filter_item_title_adm_select_one_filter1',
+                'filter_item_select_one_filter2' => '_bx_market_grid_filter_item_title_adm_select_one_filter2',
+            	'menu_item_manage_my' => '_bx_market_menu_item_title_manage_my',
+            	'menu_item_manage_all' => '_bx_market_menu_item_title_manage_all',
+                'txt_all_entries_by' => '_bx_market_txt_all_entries_by',
+                'txt_all_entries_in' => '_bx_market_txt_all_entries_in',
+                'txt_all_entries_by_author' => '_bx_market_page_title_browse_by_author',
+                'txt_all_entries_by_context' => '_bx_market_page_title_browse_by_context',
+                'txt_per_day' => '_bx_market_txt_per_day',
+                'txt_per_day_short' => '_bx_market_txt_per_day_short',
+                'txt_per_week' => '_bx_market_txt_per_week',
+                'txt_per_week_short' => '_bx_market_txt_per_week_short',
+                'txt_per_month' => '_bx_market_txt_per_month',
+                'txt_per_month_short' => '_bx_market_txt_per_month_short',
+            	'txt_per_year' => '_bx_market_txt_per_year',
+                'txt_per_year_short' => '_bx_market_txt_per_year_short',
+                
+            ),
+        );
+
+        $this->_aJsClasses = array(
+        	'form' => 'BxMarketForm',
+        	'entry' => 'BxMarketEntry',
+        	'manage_tools' => 'BxMarketManageTools',
+        	'licenses' => 'BxMarketLicenses'
+        );
+
+        $this->_aJsObjects = array(
+        	'form' => 'oBxMarketForm',
+        	'entry' => 'oBxMarketEntry',
+        	'manage_tools' => 'oBxMarketManageTools',
+        	'licenses' => 'oBxMarketLicenses'
+        );
+
+        $this->_aGridObjects = array(
+        	'common' => $this->CNF['OBJECT_GRID_COMMON'],
+        	'administration' => $this->CNF['OBJECT_GRID_ADMINISTRATION'],
+                'licenses_administration' => $this->CNF['OBJECT_GRID_LICENSES_ADMINISTRATION'],
+        	'licenses' => $this->CNF['OBJECT_GRID_LICENSES'],
+        );
+
+        $oPayments = BxDolPayments::getInstance();
+        $this->_aCurrency = array(
+        	'code' => $oPayments->getOption('default_currency_code'),
+        	'sign' => $oPayments->getOption('default_currency_sign')
+        );
+    }
+
+    public function getCurrency()
+    {
+    	return $this->_aCurrency;
+    }
+
+    public function getEntryName($sName)
+    {
+        return uriGenerate($sName, $this->CNF['TABLE_ENTRIES'], $this->CNF['FIELD_NAME']);
+    }
+}
+
+/** @} */

+ 320 - 0
modules/boonex/market/updates/13.0.2_13.0.3/source/classes/BxMarketFormEntry.php

@@ -0,0 +1,320 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Market Market
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+/**
+ * Create/Edit entry form
+ */
+class BxMarketFormEntry extends BxBaseModTextFormEntry
+{
+    public function __construct($aInfo, $oTemplate = false)
+    {
+        $this->MODULE = 'bx_market';
+        parent::__construct($aInfo, $oTemplate);
+
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        $iProfileId = bx_get_logged_profile_id();
+
+        if(isset($this->aInputs[$CNF['FIELD_TITLE']], $this->aInputs[$CNF['FIELD_NAME']])) {
+            $sJsObject = $this->_oModule->_oConfig->getJsObject('form');
+
+            $aMask = array('mask' => "javascript:%s.checkName('%s', '%s');", $sJsObject, $CNF['FIELD_TITLE'], $CNF['FIELD_NAME']);
+            if($this->aParams['display'] == $CNF['OBJECT_FORM_ENTRY_DISPLAY_EDIT'] && bx_get('id') !== false) {
+                $aMask['mask'] = "javascript:%s.checkName('%s', '%s', %d);";
+                $aMask[] = (int)bx_get('id');
+            }
+
+            $sOnBlur = call_user_func_array('sprintf', array_values($aMask)); 
+            $this->aInputs[$CNF['FIELD_TITLE']]['attrs']['onblur'] = $sOnBlur;
+            $this->aInputs[$CNF['FIELD_NAME']]['attrs']['onblur'] = $sOnBlur;
+        }
+
+        if(isset($this->aInputs[$CNF['FIELD_COVER_RAW']]))
+            $this->aInputs[$CNF['FIELD_COVER_RAW']]['code'] = 1;
+
+        if(isset($this->aInputs[$CNF['FIELD_FILE']])) {
+            $this->aInputs[$CNF['FIELD_FILE']]['storage_object'] = $CNF['OBJECT_STORAGE_FILES'];
+            $this->aInputs[$CNF['FIELD_FILE']]['uploaders'] =  !empty($this->aInputs[$CNF['FIELD_FILE']]['value']) ? unserialize($this->aInputs[$CNF['FIELD_FILE']]['value']) : $CNF['OBJECT_UPLOADERS'];
+            $this->aInputs[$CNF['FIELD_FILE']]['images_transcoder'] = '';
+            $this->aInputs[$CNF['FIELD_FILE']]['storage_private'] = 1;
+            $this->aInputs[$CNF['FIELD_FILE']]['multiple'] = true;
+            $this->aInputs[$CNF['FIELD_FILE']]['content_id'] = 0;
+            $this->aInputs[$CNF['FIELD_FILE']]['ghost_template'] = '';
+        }
+
+        $bRecurring = $this->_oModule->_oDb->getParam($CNF['OPTION_ENABLE_RECURRING']) == 'on';
+        if(!$bRecurring) {
+            $this->aInputs[$CNF['FIELD_DURATION_RECURRING']]['type'] = 'hidden';
+            $this->aInputs[$CNF['FIELD_PRICE_RECURRING']]['type'] = 'hidden';
+            $this->aInputs[$CNF['FIELD_PRICE_RECURRING']]['value'] = 0;
+
+            unset($this->aInputs[$CNF['FIELD_HEADER_BEG_RECURRING']]);
+            unset($this->aInputs[$CNF['FIELD_HEADER_END_RECURRING']]);
+        }
+
+        $oPayment = BxDolPayments::getInstance();
+        if(isset($this->aInputs[$CNF['FIELD_WARNING_SINGLE']])) {
+            if(!$oPayment->isAcceptingPayments($iProfileId, BX_PAYMENT_TYPE_SINGLE)) 
+                $this->aInputs[$CNF['FIELD_WARNING_SINGLE']]['value'] = MsgBox(_t($this->aInputs[$CNF['FIELD_WARNING_SINGLE']]['value'], $oPayment->getDetailsUrl()));
+            else 
+                unset($this->aInputs[$CNF['FIELD_WARNING_SINGLE']]);
+        }
+
+        if(isset($this->aInputs[$CNF['FIELD_WARNING_RECURRING']])) {
+            if($bRecurring && !$oPayment->isAcceptingPayments($iProfileId, BX_PAYMENT_TYPE_RECURRING))
+                $this->aInputs[$CNF['FIELD_WARNING_RECURRING']]['value'] = MsgBox(_t($this->aInputs[$CNF['FIELD_WARNING_RECURRING']]['value'], $oPayment->getDetailsUrl()));
+            else 
+                unset($this->aInputs[$CNF['FIELD_WARNING_RECURRING']]);
+        }
+
+        if(isset($this->aInputs[$CNF['FIELD_ALLOW_PURCHASE_TO']]))
+            $this->aInputs[$CNF['FIELD_ALLOW_PURCHASE_TO']] = BxDolPrivacy::getGroupChooser($CNF['OBJECT_PRIVACY_PURCHASE']);
+
+        $aDynamicGroups = array(
+            array ('key' => '', 'value' => '----'),
+            array ('key' => 'c', 'value' => _t('_bx_market_privacy_group_customers'))
+        );
+
+        if(isset($this->aInputs[$CNF['FIELD_ALLOW_COMMENT_TO']])) {
+            $this->aInputs[$CNF['FIELD_ALLOW_COMMENT_TO']] = BxDolPrivacy::getGroupChooser($CNF['OBJECT_PRIVACY_COMMENT'], $iProfileId, array('dynamic_groups' => $aDynamicGroups));
+            $this->aInputs[$CNF['FIELD_ALLOW_COMMENT_TO']]['db']['pass'] = 'Xss';
+        }
+
+        if(isset($this->aInputs[$CNF['FIELD_ALLOW_VOTE_TO']])) {
+            $this->aInputs[$CNF['FIELD_ALLOW_VOTE_TO']] = BxDolPrivacy::getGroupChooser($CNF['OBJECT_PRIVACY_VOTE'], $iProfileId, array('dynamic_groups' => $aDynamicGroups));
+            $this->aInputs[$CNF['FIELD_ALLOW_VOTE_TO']]['db']['pass'] = 'Xss';
+        }
+
+        if(isset($this->aInputs[$CNF['FIELD_SUBENTRIES']]) && $this->_oModule->checkAllowedSetSubentries() !== CHECK_ACTION_RESULT_ALLOWED)
+            unset($this->aInputs[$CNF['FIELD_SUBENTRIES']]);
+    }
+
+    function getCode($bDynamicMode = false)
+    {
+        $sCss = $this->_oModule->_oTemplate->addCss([BX_DIRECTORY_PATH_PLUGINS_PUBLIC . 'codemirror/|codemirror.css'], $bDynamicMode);
+    	$sJs = $this->_oModule->_oTemplate->addJs([
+            'codemirror/codemirror.min.js',
+            'form.js'
+        ], $bDynamicMode);
+
+        $sCode = '';
+        if($bDynamicMode)
+            $sCode .= $sCss . $sJs;
+
+        $sCode .= $this->_oModule->_oTemplate->getJsCode('form');
+        $sCode .= $this->_oModule->_oTemplate->parseHtmlByName('form.html', array(
+            'content' => parent::getCode($bDynamicMode)
+        ));
+
+        return $sCode;
+    }
+
+    function initChecker ($aValues = array (), $aSpecificValues = array())
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        if(isset($this->aInputs[$CNF['FIELD_SUBENTRIES']]) && !empty($aValues[$CNF['FIELD_ID']])) {
+            $oConnection = BxDolConnection::getObjectInstance($CNF['OBJECT_CONNECTION_SUBENTRIES']);
+            if($oConnection)
+                $this->aInputs[$CNF['FIELD_SUBENTRIES']]['value'] = $oConnection->getConnectedContent((int)$aValues[$CNF['FIELD_ID']]);
+        }
+
+        return parent::initChecker($aValues, $aSpecificValues);
+    }
+
+	public function insert ($aValsToAdd = array(), $isIgnore = false)
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        if(isset($this->aInputs[$CNF['FIELD_NAME']])) {
+            $sName = BxDolForm::getSubmittedValue($CNF['FIELD_NAME'], $this->aFormAttrs['method'], $this->_aSpecificValues);
+            $sName = $this->_oModule->_oConfig->getEntryName($sName);
+            BxDolForm::setSubmittedValue($CNF['FIELD_NAME'], $sName, $this->aFormAttrs['method'], $this->_aSpecificValues);
+        }
+
+	    if($this->_oModule->checkAllowedSetCover() === CHECK_ACTION_RESULT_ALLOWED) {
+            $aCover = isset($_POST[$CNF['FIELD_COVER']]) ? bx_process_input ($_POST[$CNF['FIELD_COVER']], BX_DATA_INT) : false;
+
+            $aValsToAdd[$CNF['FIELD_COVER']] = 0;
+            if(!empty($aCover) && is_array($aCover) && ($iFileCover = array_pop($aCover)))
+                $aValsToAdd[$CNF['FIELD_COVER']] = $iFileCover;
+        }
+
+        $aPackage = bx_process_input(bx_get($CNF['FIELD_PACKAGE']), BX_DATA_INT);
+		$aValsToAdd[$CNF['FIELD_PACKAGE']] = 0;
+		if(!empty($aPackage) && is_array($aPackage) && ($iFilePackage = array_pop($aPackage)))
+			$aValsToAdd[$CNF['FIELD_PACKAGE']] = $iFilePackage;
+
+        $iContentId = parent::insert ($aValsToAdd, $isIgnore);
+        if(!empty($iContentId))
+            $this->processFiles($CNF['FIELD_FILE'], $iContentId, true, $CNF['OBJECT_STORAGE_FILES']);
+
+        return $iContentId;
+    }
+
+	function update ($iContentId, $aValsToAdd = array(), &$aTrackTextFieldsChanges = null)
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+        
+
+        $sNameKey = $CNF['FIELD_NAME'];
+        if(isset($this->aInputs[$sNameKey])) {
+            $sName = $this->getCleanValue($sNameKey);
+            $aContentInfo = $this->_oModule->_oDb->getContentInfoById($iContentId);
+
+            if($aContentInfo[$sNameKey] != $sName) {
+                $sName = $this->_oModule->_oConfig->getEntryName($sName);
+                BxDolForm::setSubmittedValue($sNameKey, $sName, $this->aFormAttrs['method'], $this->_aSpecificValues);
+            }
+        }
+
+	    if($this->_oModule->checkAllowedSetCover() === CHECK_ACTION_RESULT_ALLOWED) {
+            $aCover = bx_process_input (bx_get($CNF['FIELD_COVER']), BX_DATA_INT);
+
+            $aValsToAdd[$CNF['FIELD_COVER']] = 0;
+            if (!empty($aCover) && is_array($aCover) && ($iFileCover = array_pop($aCover)))
+                $aValsToAdd[$CNF['FIELD_COVER']] = $iFileCover;
+        }
+
+		$aPackage = bx_process_input(bx_get($CNF['FIELD_PACKAGE']), BX_DATA_INT);
+		$aValsToAdd[$CNF['FIELD_PACKAGE']] = 0;
+		if(!empty($aPackage) && is_array($aPackage) && ($iFilePackage = array_pop($aPackage)))
+			$aValsToAdd[$CNF['FIELD_PACKAGE']] = $iFilePackage;
+
+        $iResult = parent::update ($iContentId, $aValsToAdd, $aTrackTextFieldsChanges);
+
+        $this->processFiles($CNF['FIELD_FILE'], $iContentId, false, $CNF['OBJECT_STORAGE_FILES']);
+
+        return $iResult;
+    }
+
+	function delete ($iContentId, $aContentInfo = array())
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        $bResult = parent::delete($iContentId, $aContentInfo);
+        if(!$bResult)
+            return $bResult;
+
+        // delete associated files
+        if (!empty($CNF['OBJECT_STORAGE_FILES'])) {
+            $oStorage = BxDolStorage::getObjectInstance($CNF['OBJECT_STORAGE_FILES']);
+            if($oStorage)
+                $oStorage->queueFilesForDeletionFromGhosts($aContentInfo[$CNF['FIELD_AUTHOR']], $iContentId);
+        }
+
+        // delete associations
+        $bResult &= $this->_oModule->_oDb->deassociatePhotoWithContent($iContentId, 0);
+        $bResult &= $this->_oModule->_oDb->deassociateFileWithContent($iContentId, 0);
+
+        return $bResult;
+    }
+
+    protected function _associalFileWithContent($oStorage, $iFileId, $iProfileId, $iContentId, $sPictureField = '')
+    {
+        parent::_associalFileWithContent($oStorage, $iFileId, $iProfileId, $iContentId, $sPictureField);
+
+        $sStorage = $oStorage->getObject();
+        switch($sStorage) {
+        	case $this->_oModule->_oConfig->CNF['OBJECT_STORAGE']:
+        		$this->_oModule->_oDb->associatePhotoWithContent($iContentId, $iFileId, $this->getCleanValue('title-' . $iFileId));
+        		break;
+
+        	case $this->_oModule->_oConfig->CNF['OBJECT_STORAGE_FILES']:
+        		$aParams = array(
+        			'type' => $this->getCleanValue('type-' . $iFileId)        			
+        		);
+
+        		switch ($aParams['type']) {
+        			case BX_MARKET_FILE_TYPE_VERSION:
+        				$aParams = array_merge($aParams, array(
+        					'version' => $this->getCleanValue('version-' . $iFileId),
+        				));
+        				break;
+        				
+        			case BX_MARKET_FILE_TYPE_UPDATE:
+        				$aParams = array_merge($aParams, array(
+        					'version' => $this->getCleanValue('version-from-' . $iFileId),
+        					'version_to' => $this->getCleanValue('version-to-' . $iFileId),
+        				));
+        				break;
+        		}
+
+        		$this->_oModule->_oDb->associateFileWithContent($iContentId, $iFileId, $aParams);
+        		break;
+        }
+    }
+
+    protected function _getPhotoGhostTmplVars($aContentInfo = array())
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        $aResult = parent::_getPhotoGhostTmplVars($aContentInfo);
+        $aResult = array_merge($aResult, array(
+            'cover_id' => isset($aContentInfo[$CNF['FIELD_COVER']]) ? $aContentInfo[$CNF['FIELD_COVER']] : 0,
+            'bx_if:set_cover' => array (
+                'condition' => CHECK_ACTION_RESULT_ALLOWED === $this->_oModule->checkAllowedSetCover(),
+                'content' => array (
+                    'name_cover' => $CNF['FIELD_COVER'],
+                ),
+            ),
+        ));
+
+        return $aResult;
+    }
+
+    protected function _getFileGhostTmplVars($aContentInfo = array())
+    {
+    	$CNF = &$this->_oModule->_oConfig->CNF;
+
+        $aResult = parent::_getFileGhostTmplVars($aContentInfo);
+        $aResult = array_merge($aResult, array(
+            'thumb_id' => isset($aContentInfo[$CNF['FIELD_PACKAGE']]) ? $aContentInfo[$CNF['FIELD_PACKAGE']] : 0,
+            'bx_if:set_thumb' => array (
+                'condition' => true,
+                'content' => array(
+                    'name_thumb' => $CNF['FIELD_PACKAGE'],
+                ),
+            ),
+        ));
+
+    	return $aResult;
+    }
+
+    protected function genCustomInputSubentries ($aInput)
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        $aInput['ajax_get_suggestions'] = BX_DOL_URL_ROOT . $this->_oModule->_oConfig->getBaseUri() . 'get_subentries';
+        $aInput['placeholder'] = _t('_bx_market_form_entry_input_subentries_placeholder');
+
+        $sVals = '';
+        if(!empty($aInput['value']) && is_array($aInput['value'])) {
+            foreach($aInput['value'] as $iValue) {
+                $iValue = (int)$iValue;
+                if(!$iValue)
+                    continue;
+
+                $aContentInfo = $this->_oModule->_oDb->getContentInfoById($iValue);
+                if(empty($aContentInfo) || !is_array($aContentInfo))
+                    continue;
+                
+               $sVals .= '<b class="val bx-def-color-bg-hl bx-def-round-corners">' . $aContentInfo[$CNF['FIELD_TITLE']] . '<input type="hidden" name="' . $aInput['name'] . '[]" value="' . $iValue . '" /></b>';
+            }
+            $sVals = trim($sVals, ',');
+        }
+        $aInput['value'] = $sVals;
+
+        return $this->genCustomInputUsernamesSuggestions($aInput);
+    }
+}
+
+/** @} */

+ 1359 - 0
modules/boonex/market/updates/13.0.2_13.0.3/source/classes/BxMarketModule.php

@@ -0,0 +1,1359 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Market Market
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+define('BX_MARKET_LICENSE_TYPE_SINGLE', 'single'); //--- one-time payment license
+define('BX_MARKET_LICENSE_TYPE_RECURRING', 'recurring'); //--- recurring payment license
+
+define('BX_MARKET_FILE_TYPE_VERSION', 'version');
+define('BX_MARKET_FILE_TYPE_UPDATE', 'update');
+
+/**
+ * Market module
+ */
+class BxMarketModule extends BxBaseModTextModule
+{
+    function __construct(&$aModule)
+    {
+        parent::__construct($aModule);
+
+        $CNF = &$this->_oConfig->CNF;
+        $this->_aSearchableNamesExcept = array_merge($this->_aSearchableNamesExcept, array(
+            $CNF['FIELD_NAME'],
+            $CNF['FIELD_DURATION_RECURRING'],
+            $CNF['FIELD_TRIAL_RECURRING'],
+            $CNF['FIELD_ALLOW_PURCHASE_TO'],
+            $CNF['FIELD_ALLOW_COMMENT_TO'],
+            $CNF['FIELD_ALLOW_VOTE_TO'],
+            $CNF['FIELD_NOTES_PURCHASED']
+        ));
+    }
+
+    public function actionPerform()
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $aContentInfo = $this->_getContentInfo();
+        if(empty($aContentInfo) || !is_array($aContentInfo))
+            return echoJson(array('code' => 1));
+
+        $sAction = bx_process_input(bx_get('action'));
+        if(empty($CNF['MENU_ITEM_TO_METHOD'][$CNF['OBJECT_MENU_ACTIONS_VIEW_ENTRY']][$sAction])) 
+            return echoJson(array('code' => 2));
+
+        $sMethodCheck = $CNF['MENU_ITEM_TO_METHOD'][$CNF['OBJECT_MENU_ACTIONS_VIEW_ENTRY']][$sAction];
+        $sMethodPerform = '_perform' . bx_gen_method_name($sAction, array('-', '_'));
+        if(!method_exists($this, $sMethodCheck) || $this->$sMethodCheck($aContentInfo) !== CHECK_ACTION_RESULT_ALLOWED || !method_exists($this, $sMethodPerform))
+            return echoJson(array('code' => 3, 'msg' => _t('_sys_txt_access_denied')));
+
+        return $this->$sMethodPerform($aContentInfo);
+    }
+
+    public function actionCheckName()
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $sName = '';
+
+    	$sTitle = bx_process_input(bx_get('title'));
+    	if(empty($sTitle))
+    		return echoJson(array());
+
+        $iId = (int)bx_get('id');
+        if(!empty($iId)) {
+            $aEntry = $this->_oDb->getContentInfoById($iId); 
+            if(strcmp($sTitle, $aEntry[$CNF['FIELD_NAME']]) == 0) 
+                $sName = $sTitle;
+        }
+
+    	echoJson(array(
+    		'title' => $sTitle,
+    		'name' => !empty($sName) ? $sName : $this->_oConfig->getEntryName($sTitle, $iId)
+    	));
+    }
+
+    public function actionGetSubentries()
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $sTerm = bx_get('term');
+        $iLimit = (int)bx_get('limit');
+        if(empty($iLimit))
+            $iLimit = 10;
+
+        $aResult = array();
+        $aEntries = $this->_oDb->searchByAuthorTerm($this->_iProfileId, $sTerm, $iLimit);
+        foreach ($aEntries as $aEntry)
+            $aResult[] = array('value' => $aEntry[$CNF['FIELD_ID']], 'label' => $aEntry[$CNF['FIELD_TITLE']]);
+
+        // sort result
+        usort($aResult, function($r1, $r2) {
+            return strcmp($r1['label'], $r2['label']);
+        });
+
+        echoJson(array_slice($aResult, 0, $iLimit));
+    }
+
+    public function serviceGetSafeServices()
+    {
+        $a = parent::serviceGetSafeServices();
+        return array_merge($a, array (
+            'EntityDownload' => '',
+            'EntityAuthorEntities' => '',
+            'BlockLicenses' => '',
+        ));
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_market Market
+     * @subsection bx_market-other Other
+     * @subsubsection bx_market-get_searchable_fields get_searchable_fields
+     * 
+     * @code bx_srv('bx_market', 'get_searchable_fields', [...]); @endcode
+     * 
+     * Get a list of searchable fields. Is used in common search engine. 
+     *
+     * @return an array with a list of searchable fields.
+     * 
+     * @see BxMarketModule::serviceGetSearchableFields
+     */
+    /** 
+     * @ref bx_market-get_searchable_fields "get_searchable_fields"
+     */
+    public function serviceGetSearchableFields ($aInputsAdd = array())
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $aResult = parent::serviceGetSearchableFields($aInputsAdd);
+        unset($aResult[$CNF['FIELD_PRICE_SINGLE']], $aResult[$CNF['FIELD_TRIAL_RECURRING']]);
+
+        return $aResult;
+    }
+    
+    /**
+     * @page service Service Calls
+     * @section bx_market Market
+     * @subsection bx_market-page_blocks Page Blocks
+     * @subsubsection bx_market-entity_create entity_create
+     * 
+     * @code bx_srv('bx_market', 'entity_create', [...]); @endcode
+     * 
+     * Get page block with product creation form or an error message if something wasn't configured correctly.
+     *
+     * @param $sDisplay form display name to use
+     * @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 BxMarketModule::serviceEntityCreate
+     */
+    /** 
+     * @ref bx_market-entity_create "entity_create"
+     */
+    public function serviceEntityCreate ($sDisplay = false)
+    {
+    	$oPayments = BxDolPayments::getInstance();
+    	if(!$oPayments->isActive())
+    		return MsgBox(_t('_bx_market_err_no_payments'));
+
+    	if(!$oPayments->isAcceptingPayments($this->_iProfileId))
+    		return MsgBox(_t('_bx_market_err_not_accept_payments', $oPayments->getDetailsUrl()));
+
+    	return parent::serviceEntityCreate($sDisplay);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_market Market
+     * @subsection bx_market-page_blocks Page Blocks
+     * @subsubsection bx_market-entity_download entity_download
+     * 
+     * @code bx_srv('bx_market', 'entity_download', [...]); @endcode
+     * 
+     * Get page block with a list of downloadable packages attached to the product. If something is wrong an error message is returned.
+     *
+     * @param $iContentId (optional) product's ID. If empty value is provided, an attempt to get it from GET/POST arrays will be performed.
+     * @return an array describing a block to display on the site or false if there is no enough input data. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
+     * 
+     * @see BxMarketModule::serviceEntityDownload
+     */
+    /** 
+     * @ref bx_market-entity_download "entity_download"
+     */
+    public function serviceEntityDownload ($iContentId = 0)
+    {
+    	$CNF = &$this->_oConfig->CNF;
+
+    	if(!$iContentId)
+            $iContentId = bx_process_input(bx_get('id'), BX_DATA_INT);
+
+        if(!$iContentId)
+            return false;
+
+		$aContentInfo = $this->_oDb->getContentInfoById($iContentId);
+		if(empty($aContentInfo) || !is_array($aContentInfo))
+            return MsgBox(_t('_sys_txt_error_occured'));
+
+    	if($this->checkAllowedDownload($aContentInfo) !== CHECK_ACTION_RESULT_ALLOWED)
+    		return MsgBox(_t('_bx_market_err_access_denied'));
+
+        $sJsObject = $this->_oConfig->getJsObject('entry');
+        $oMenu = new BxTemplMenu(array('template' => 'menu_vertical.html', 'menu_id'=> 'bx-market-downloads', 'menu_items' => array(
+            array('id' => 'bx-market-show-more', 'name' => 'bx-market-show-more', 'class' => '', 'link' => 'javascript:void(0)', 'target' => '_self', 'onclick' => 'javascript:' . $sJsObject . '.showMore();', 'title' => _t('_bx_market_menu_item_title_downloads_more')),
+        )));
+
+        return array(
+            'menu' => $oMenu,
+            'content' => $this->_oTemplate->entryAttachmentsByStorage($CNF['OBJECT_STORAGE_FILES'], $aContentInfo, array(
+                'filter_field' => ''
+            ))
+        );
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_market Market
+     * @subsection bx_market-page_blocks Page Blocks
+     * @subsubsection bx_market-entity_rating entity_rating
+     * 
+     * @code bx_srv('bx_market', 'entity_rating', [...]); @endcode
+     * 
+     * Get page block with Stars based product's rating.
+     *
+     * @param $iContentId (optional) product's 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 there is no enough input data. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
+     * 
+     * @see BxMarketModule::serviceEntityRating
+     */
+    /** 
+     * @ref bx_market-entity_rating "entity_rating"
+     */
+    public function serviceEntityRating($iContentId = 0)
+    {
+    	return $this->_serviceTemplateFunc ('entryRating', $iContentId);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_market Market
+     * @subsection bx_market-page_blocks Page Blocks
+     * @subsubsection bx_market-entity_author_entities entity_author_entities
+     * 
+     * @code bx_srv('bx_market', 'entity_author_entities', [...]); @endcode
+     * 
+     * Get page block with a list of other products of the same author.
+     *
+     * @param $iContentId (optional) product's ID. If empty value is provided, an attempt to get it from GET/POST arrays will be performed.
+     * @return an array describing a block to display on the site or false if there is no enough input data. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
+     * 
+     * @see BxMarketModule::serviceEntityAuthorEntities
+     */
+    /** 
+     * @ref bx_market-entity_author_entities "entity_author_entities"
+     */
+	public function serviceEntityAuthorEntities($iContentId = 0)
+    {
+    	$CNF = &$this->_oConfig->CNF;
+
+    	$aContentInfo = $this->_getContentInfo($iContentId);
+    	if($aContentInfo === false)
+    		return false;
+
+		$oProfile = BxDolProfile::getInstance($aContentInfo[$CNF['FIELD_AUTHOR']]);
+        if (!$oProfile)
+            $oProfile = BxDolProfileUndefined::getInstance();
+
+		$aBlock = $this->_serviceBrowse ('author', array('author' => $aContentInfo[$CNF['FIELD_AUTHOR']], 'except' => array($iContentId), 'per_page' => 2), BX_DB_PADDING_DEF, true);
+		$aBlock['title'] = _t('_bx_market_page_block_title_entry_author_entries', $oProfile->getDisplayName());
+
+    	return $aBlock;
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_market Market
+     * @subsection bx_market-page_blocks Page Blocks
+     * @subsubsection bx_market-block_licenses block_licenses
+     * 
+     * @code bx_srv('bx_market', 'block_licenses', [...]); @endcode
+     * 
+     * Get page block with a list of licenses purchased by currently logged member.
+     *
+     * @return an array describing a block to display on the site or false if there is no enough input data. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
+     * 
+     * @see BxMarketModule::serviceBlockLicenses
+     */
+    /** 
+     * @ref bx_market-block_licenses "block_licenses"
+     */
+    public function serviceBlockLicenses() 
+    {
+        return $this->_getBlockLicenses();
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_market Market
+     * @subsection bx_market-page_blocks Page Blocks
+     * @subsubsection bx_market-block_licenses_administration block_licenses_administration
+     * 
+     * @code bx_srv('bx_market', 'block_licenses_administration', [...]); @endcode
+     * 
+     * Get page block with a list of all licenses. It's needed for moderators/administrators.
+     *
+     * @return an array describing a block to display on the site or false if there is no enough input data. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
+     * 
+     * @see BxMarketModule::serviceBlockLicensesAdministration
+     */
+    /** 
+     * @ref bx_market-block_licenses "block_licenses"
+     */
+    public function serviceBlockLicensesAdministration() 
+    {
+        return $this->_getBlockLicenses('administration');
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_market Market
+     * @subsection bx_market-page_blocks Page Blocks
+     * @subsubsection bx_market-block_licenses_note block_licenses_note
+     * 
+     * @code bx_srv('bx_market', 'block_licenses_note', [...]); @endcode
+     * 
+     * Get page block with a notice for licenses usage.
+     *
+     * @return HTML string with block content to display on the site.
+     * 
+     * @see BxMarketModule::serviceBlockLicensesNote
+     */
+    /** 
+     * @ref bx_market-block_licenses_note "block_licenses_note"
+     */
+	public function serviceBlockLicensesNote()
+	{
+	    return MsgBox(_t('_bx_market_page_block_content_licenses_note'));
+	}
+
+	/**
+     * @page service Service Calls
+     * @section bx_market Market
+     * @subsection bx_market-licenses Licenses
+     * @subsubsection bx_market-get_unused_licenses_num get_unused_licenses_num
+     * 
+     * @code bx_srv('bx_market', 'get_unused_licenses_num', [...]); @endcode
+     * 
+     * Get number of unused licenses for some profile. It can be used in menus with "alert" counters.
+     *
+     * @param $iProfileId profile to get unused licenses for, if omitted then currently logged in profile is used
+     * @return an integer value with a number of unused licenses.
+     * 
+     * @see BxMarketModule::serviceGetUnusedLicensesNum
+     */
+    /** 
+     * @ref bx_market-get_unused_licenses_num "get_unused_licenses_num"
+     */
+    public function serviceGetUnusedLicensesNum ($iProfileId = 0)
+    {
+        if(!$iProfileId)
+			$iProfileId = bx_get_logged_profile_id();
+
+        $aLicenses = $this->_oDb->getLicense(array('type' => 'new', 'profile_id' => (int)$iProfileId));
+        return !empty($aLicenses) && is_array($aLicenses) ? count($aLicenses) : 0;
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_market Market
+     * @subsection bx_market-licenses Licenses
+     * @subsubsection bx_market-has_license has_license
+     * 
+     * @code bx_srv('bx_market', 'has_license', [...]); @endcode
+     * 
+     * Check whether a profile has a license for specified product. Domain on which the license is used can be attached to checking.
+     *
+     * @param $iProfileId profile which ownership will be checked.
+     * @param $iProductId product which the license(s) will be searched for.  
+     * @param $sDomain (optional) domain name on which the license is used.
+     * @return boolean value determining where the license is available or not.
+     * 
+     * @see BxMarketModule::serviceHasLicense
+     */
+    /** 
+     * @ref bx_market-has_license "has_license"
+     */
+	public function serviceHasLicense ($iProfileId, $iProductId, $sDomain = '')
+    {
+    	return $this->_oDb->hasLicense($iProfileId, $iProductId, $sDomain);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_market Market
+     * @subsection bx_market-licenses Licenses
+     * @subsubsection bx_market-get_license get_license
+     * 
+     * @code bx_srv('bx_market', 'has_license', [...]); @endcode
+     * 
+     * Get a list of licenses which meet requirements provided in the input array.
+     *
+     * @param $aParams array of requirements which will be used for searching.
+     * @return an array of licenses which meet requirements.
+     * 
+     * @see BxMarketModule::serviceGetLicense
+     */
+    /** 
+     * @ref bx_market-get_license "get_license"
+     */
+    public function serviceGetLicense ($aParams)
+    {
+    	return $this->_oDb->getLicense($aParams);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_market Market
+     * @subsection bx_market-licenses Licenses
+     * @subsubsection bx_market-update_license update_license
+     * 
+     * @code bx_srv('bx_market', 'update_license', [...]); @endcode
+     * 
+     * Update license(s) changing necessary fields. Updatable license(s) should meet requirements provided in the input array.
+     *
+     * @param $aSet an array of data to be saved  
+     * @param $aWhere an array of requirements which will be used for searching.
+     * @return an array of licenses which meet requirements.
+     * 
+     * @see BxMarketModule::serviceUpdateLicense
+     */
+    /** 
+     * @ref bx_market-update_license "update_license"
+     */
+    public function serviceUpdateLicense ($aSet, $aWhere)
+    {
+    	return $this->_oDb->updateLicense($aSet, $aWhere);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_market Market
+     * @subsection bx_market-browsing Browsing
+     * @subsubsection bx_market-get_entry_by get_entry_by
+     * 
+     * @code bx_srv('bx_market', 'get_entry_by', [...]); @endcode
+     * 
+     * Get entry (product) which meets requirements.
+     *
+     * @param $sType string with search type.  
+     * @param $mixedValue mixed value to be used for searching.
+     * @return an array describing a product which meets requirements.
+     * 
+     * @see BxMarketModule::serviceGetEntryBy
+     */
+    /** 
+     * @ref bx_market-get_entry_by "get_entry_by"
+     */
+    public function serviceGetEntryBy($sType, $mixedValue)
+    {
+    	return $this->_oDb->getContentInfoBy(array('type' => $sType, 'value' => $mixedValue));
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_market Market
+     * @subsection bx_market-browsing Browsing
+     * @subsubsection bx_market-get_entries_by get_entries_by
+     * 
+     * @code bx_srv('bx_market', 'get_entries_by', [...]); @endcode
+     * 
+     * Get an array of entries (products) which meet requirements.
+     * 
+     * @param $aParams an array of requirements which will be used for searching.
+     * @return an array of products which meets requirements.
+     * 
+     * @see BxMarketModule::serviceGetEntriesBy
+     */
+    /** 
+     * @ref bx_market-get_entries_by "get_entries_by"
+     */
+    public function serviceGetEntriesBy($aParams)
+    {
+    	return $this->_oDb->getContentInfoBy($aParams);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_market Market
+     * @subsection bx_market-browsing Browsing
+     * @subsubsection bx_market-get_products_names get_products_names
+     * 
+     * @code bx_srv('bx_market', 'get_products_names', [...]); @endcode
+     * 
+     * Get an array of products names.
+     * 
+     * @param $iVendorId return products of 1 vendor only
+     * @param $iLimit limit the result artay
+     * @return an array of products names
+     * 
+     * @see BxMarketModule::serviceGetProductsNames
+     */
+    /** 
+     * @ref bx_market-get_products_names "get_products_names"
+     */
+    public function serviceGetProductsNames($iVendorId, $iLimit = 1000)
+    {
+    	return $this->_oDb->getProductsNames($iVendorId, $iLimit);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_market Market
+     * @subsection bx_market-entry Entry
+     * @subsubsection bx_market-get_thumbnail get_thumbnail
+     * 
+     * @code bx_srv('bx_market', 'get_thumbnail', [...]); @endcode
+     * 
+     * Get an array of image URLs for the product's thumbnail. Returned images have different dimensions ('small' and 'big').
+     * 
+     * @param $iPhotoId photo ID which is attached to a product as thumbnail.
+     * @return an array of image URLs.
+     * 
+     * @see BxMarketModule::serviceGetThumbnail
+     */
+    /** 
+     * @ref bx_market-get_thumbnail "get_thumbnail"
+     */
+    public function serviceGetThumbnail($iPhotoId)
+    {
+    	$CNF = &$this->_oConfig->CNF;
+
+    	$oStorage = BxDolStorage::getObjectInstance($CNF['OBJECT_STORAGE']);
+    	$oImagesTranscoder = BxDolTranscoderImage::getObjectInstance($CNF['OBJECT_IMAGES_TRANSCODER_GALLERY']);
+
+    	return array(
+    		'small' => $oImagesTranscoder ? $oImagesTranscoder->getFileUrl($iPhotoId) : '',
+    		'big' => $oStorage ? $oStorage->getFileUrlById($iPhotoId) : ''
+    	);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_market Market
+     * @subsection bx_market-entry Entry
+     * @subsubsection bx_market-get_cover get_cover
+     * 
+     * @code bx_srv('bx_market', 'get_cover', [...]); @endcode
+     * 
+     * Get an array of image URLs for the product's cover. Returned images have different dimensions ('small', 'large' and 'big').
+     * 
+     * @param $iPhotoId photo ID which is attached to a product as cover.
+     * @return an array of image URLs.
+     * 
+     * @see BxMarketModule::serviceGetCover
+     */
+    /** 
+     * @ref bx_market-get_cover "get_cover"
+     */
+    public function serviceGetCover($iPhotoId)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $oTiGallery = BxDolTranscoderImage::getObjectInstance($CNF['OBJECT_IMAGES_TRANSCODER_GALLERY']);
+        $oTiPage = BxDolTranscoderImage::getObjectInstance($CNF['OBJECT_IMAGES_TRANSCODER_COVER']);
+        $oStorage = BxDolStorage::getObjectInstance($CNF['OBJECT_STORAGE']);
+
+        return array(
+            'medium' => $oTiGallery ? $oTiGallery->getFileUrl($iPhotoId) : '',
+            'large' => $oTiPage ? $oTiPage->getFileUrl($iPhotoId) : '',
+            'big' => $oStorage ? $oStorage->getFileUrlById($iPhotoId) : ''
+        );
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_market Market
+     * @subsection bx_market-entry Entry
+     * @subsubsection bx_market-get_file get_file
+     * 
+     * @code bx_srv('bx_market', 'get_file', [...]); @endcode
+     * 
+     * Get an array with file's description.
+     * 
+     * @param $iFileId file ID which is attached to a product as package (version, update, etc).
+     * @return an array with file's description.
+     * 
+     * @see BxMarketModule::serviceGetFile
+     */
+    /** 
+     * @ref bx_market-get_file "get_file"
+     */
+    public function serviceGetFile($iFileId)
+    {
+    	$CNF = &$this->_oConfig->CNF;
+
+    	$aFile = $this->_oDb->getFile(array(
+            'type' => 'file_id_ext', 
+            'file_id' => $iFileId
+    	));
+
+    	if(!empty($aFile) && is_array($aFile)) {
+            $oStorage = BxDolStorage::getObjectInstance($CNF['OBJECT_STORAGE_FILES']);
+            $aFile['file_url'] = $oStorage ? $oStorage->getFileUrlById($iFileId) : '';
+    	}
+
+    	return $aFile;
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_market Market
+     * @subsection bx_market-entry Entry
+     * @subsubsection bx_market-get_files get_files
+     * 
+     * @code bx_srv('bx_market', 'get_files', [...]); @endcode
+     * 
+     * Get an array with files attached to the entry.
+     * 
+     * @param $iEntryId product ID.
+     * @param $sType file type ('version', 'update')
+     * @return an array with files.
+     * 
+     * @see BxMarketModule::serviceGetFiles
+     */
+    /** 
+     * @ref bx_market-get_files "get_files"
+     */
+    public function serviceGetFiles($iEntryId, $sType)
+    {
+    	return $this->_oDb->getFile(array(
+            'type' => 'content_id_and_type', 
+            'content_id' => $iEntryId,
+            'file_type' => $sType,
+            'ordered' => true
+    	));
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_market Market
+     * @subsection bx_market-entry Entry
+     * @subsubsection bx_market-get_updates get_updates
+     * 
+     * @code bx_srv('bx_market', 'get_updates', [...]); @endcode
+     * 
+     * Get an array with update(s)' description(s).
+     * 
+     * @param $iContentId product's ID.
+     * @param $sVersion (optional) if version is specified then it will be used for searching as 'Version From'.
+     * @return an array with update(s)' description(s).
+     * 
+     * @see BxMarketModule::serviceGetUpdates
+     */
+    /** 
+     * @ref bx_market-get_updates "get_updates"
+     */
+    public function serviceGetUpdates($iContentId, $sVersion = '')
+    {
+    	$CNF = &$this->_oConfig->CNF;
+
+    	$aFile = $this->_oDb->getFile(array(
+            'type' => 'content_id_and_type', 
+            'content_id' => $iContentId, 
+            'file_type' => 'update',
+            'version' => $sVersion
+    	));
+
+    	if(!empty($aFile) && is_array($aFile)) {
+            $oStorage = BxDolStorage::getObjectInstance($CNF['OBJECT_STORAGE_FILES']);
+            $aFile['file_url'] = $oStorage ? $oStorage->getFileUrlById($aFile['file_id']) : '';
+    	}
+
+    	return $aFile;
+    }
+
+	/**
+     * @page service Service Calls
+     * @section bx_market Market
+     * @subsection bx_market-entry Entry
+     * @subsubsection bx_market-get_screenshots get_screenshots
+     * 
+     * @code bx_srv('bx_market', 'get_screenshots', [...]); @endcode
+     * 
+     * Get an array with screenshots' descriptions.
+     * 
+     * @param $iItemId product's ID.
+     * @return an array with screenshots' descriptions.
+     * 
+     * @see BxMarketModule::serviceGetScreenshots
+     */
+    /** 
+     * @ref bx_market-get_screenshots "get_screenshots"
+     */
+    public function serviceGetScreenshots($iItemId)
+    {
+    	$CNF = &$this->_oConfig->CNF;
+
+        if(!$iItemId)
+            return [];
+
+    	$aData = $this->_oDb->getContentInfoById($iItemId);
+
+    	$aPhotos = $this->_oDb->getPhoto(array('type' => 'content_id', 'content_id' => $aData[$CNF['FIELD_ID']], 'except' => array($aData[$CNF['FIELD_THUMB']], $aData[$CNF['FIELD_COVER']])));
+    	if(empty($aPhotos) || !is_array($aPhotos))
+            return [];
+
+        $oStorage = BxDolStorage::getObjectInstance($CNF['OBJECT_STORAGE']);
+        if(!$oStorage)
+            return [];
+
+    	$oImagesTranscoder = BxDolTranscoderImage::getObjectInstance($CNF['OBJECT_IMAGES_TRANSCODER_SCREENSHOT']);
+
+    	$aResult = [];
+    	foreach($aPhotos as $aPhoto) {
+            $sUrlSm = '';
+            $sUrlBg = $oStorage->getFileUrlById($aPhoto['file_id']);
+
+            $aPhotoInfo = $oStorage->getFile($aPhoto['file_id']);
+            if(strpos($aPhotoInfo['mime_type'], 'svg') !== false)
+                $sUrlSm = $sUrlBg;
+            else
+                $sUrlSm = $oImagesTranscoder ? $oImagesTranscoder->getFileUrl($aPhoto['file_id']) : '';
+
+            $aResult[] = [
+                'id' => $aPhoto['file_id'],
+                'url_sm' => $sUrlSm,
+                'url_bg' => $sUrlBg
+            ];
+        }
+
+        return $aResult;
+    }
+
+	/**
+     * @page service Service Calls
+     * @section bx_market Market
+     * @subsection bx_market-payments Payments
+     * @subsubsection bx_market-get_payment_data get_payment_data
+     * 
+     * @code bx_srv('bx_market', 'get_payment_data', [...]); @endcode
+     * 
+     * Get an array with module's description. Is needed for payments processing module.
+     * 
+     * @return an array with module's description.
+     * 
+     * @see BxMarketModule::serviceGetPaymentData
+     */
+    /** 
+     * @ref bx_market-get_payment_data "get_payment_data"
+     */
+    public function serviceGetPaymentData()
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $oPermalink = BxDolPermalinks::getInstance();
+
+        $aResult = $this->_aModule;
+        $aResult['url_browse_order_common'] = BX_DOL_URL_ROOT . $oPermalink->permalink($CNF['URL_LICENSES_COMMON'], array('filter' => '{order}'));
+        $aResult['url_browse_order_administration'] = BX_DOL_URL_ROOT . $oPermalink->permalink($CNF['URL_LICENSES_ADMINISTRATION'], array('filter' => '{order}'));
+
+        return $aResult;
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_market Market
+     * @subsection bx_market-payments Payments
+     * @subsubsection bx_market-get_cart_item get_cart_item
+     * 
+     * @code bx_srv('bx_market', 'get_cart_item', [...]); @endcode
+     * 
+     * Get an array with prodict's description. Is used in Shopping Cart in payments processing module.
+     * 
+     * @param $mixedItemId product's ID or Unique Name.
+     * @return an array with prodict's description. Empty array is returned if something is wrong.
+     * 
+     * @see BxMarketModule::serviceGetCartItem
+     */
+    /** 
+     * @ref bx_market-get_cart_item "get_cart_item"
+     */
+    public function serviceGetCartItem($mixedItemId)
+    {
+    	$CNF = &$this->_oConfig->CNF;
+
+        if(!$mixedItemId)
+            return array();
+
+        if(is_numeric($mixedItemId))
+            $aItem = $this->_oDb->getContentInfoById((int)$mixedItemId);
+        else
+            $aItem = $this->_oDb->getContentInfoByName($mixedItemId);
+
+        if(empty($aItem) || !is_array($aItem))
+            return array();
+
+        return array (
+            'id' => $aItem[$CNF['FIELD_ID']],
+            'author_id' => $aItem[$CNF['FIELD_AUTHOR']],
+            'name' => $aItem[$CNF['FIELD_NAME']],
+            'title' => $aItem[$CNF['FIELD_TITLE']],
+            'description' => $aItem[$CNF['FIELD_TEXT']],
+            'url' => BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink('page.php?i=view-product&id=' . $aItem[$CNF['FIELD_ID']]),
+            'price_single' => $aItem[$CNF['FIELD_PRICE_SINGLE']],
+            'price_recurring' => $aItem[$CNF['FIELD_PRICE_RECURRING']],
+            'period_recurring' => 1,
+            'period_unit_recurring' => $aItem[$CNF['FIELD_DURATION_RECURRING']],
+            'trial_recurring' => $aItem[$CNF['FIELD_TRIAL_RECURRING']]
+        );
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_market Market
+     * @subsection bx_market-payments Payments
+     * @subsubsection bx_market-get_cart_items get_cart_items
+     * 
+     * @code bx_srv('bx_market', 'get_cart_items', [...]); @endcode
+     * 
+     * Get an array with prodicts' descriptions by seller. Is used in Manual Order Processing in payments processing module.
+     * 
+     * @param $iSellerId seller ID.
+     * @return an array with prodicts' descriptions. Empty array is returned if something is wrong or seller doesn't have any products.
+     * 
+     * @see BxMarketModule::serviceGetCartItems
+     */
+    /** 
+     * @ref bx_market-get_cart_items "get_cart_items"
+     */
+    public function serviceGetCartItems($iSellerId)
+    {
+    	$CNF = &$this->_oConfig->CNF;
+
+        $iSellerId = (int)$iSellerId;
+        if(empty($iSellerId))
+            return array();
+
+        $aItems = $this->_oDb->getEntriesByAuthor($iSellerId);
+
+        $aResult = array();
+        foreach($aItems as $aItem)
+            $aResult[] = array(
+                'id' => $aItem[$CNF['FIELD_ID']],
+                'author_id' => $aItem[$CNF['FIELD_AUTHOR']],
+                'name' => $aItem[$CNF['FIELD_NAME']],
+                'title' => $aItem[$CNF['FIELD_TITLE']],
+                'description' => $aItem[$CNF['FIELD_TEXT']],
+                'url' => BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink('page.php?i=view-product&id=' . $aItem[$CNF['FIELD_ID']]),
+                'price_single' => $aItem[$CNF['FIELD_PRICE_SINGLE']],
+                'price_recurring' => $aItem[$CNF['FIELD_PRICE_RECURRING']],
+                'period_recurring' => 1,
+                'period_unit_recurring' => $aItem[$CNF['FIELD_DURATION_RECURRING']],
+                'trial_recurring' => $aItem[$CNF['FIELD_TRIAL_RECURRING']]
+            );
+
+        return $aResult;
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_market Market
+     * @subsection bx_market-payments Payments
+     * @subsubsection bx_market-register_cart_item register_cart_item
+     * 
+     * @code bx_srv('bx_market', 'register_cart_item', [...]); @endcode
+     * 
+     * Register a processed single time payment inside the Market module. Is called with payment processing module after the payment was registered there.
+     * 
+     * @param $iClientId client ID.
+     * @param $iSellerId seller ID
+     * @param $iItemId item ID.
+     * @param $iItemCount the number of purchased items.
+     * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
+     * @param $sLicense license number genereted with payment processing module for internal usage
+     * @return an array with purchased prodict's description. Empty array is returned if something is wrong.
+     * 
+     * @see BxMarketModule::serviceRegisterCartItem
+     */
+    /** 
+     * @ref bx_market-register_cart_item "register_cart_item"
+     */
+    public function serviceRegisterCartItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense)
+    {
+        return $this->_serviceRegisterItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense, BX_MARKET_LICENSE_TYPE_SINGLE);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_market Market
+     * @subsection bx_market-payments Payments
+     * @subsubsection bx_market-register_subscription_item register_subscription_item
+     * 
+     * @code bx_srv('bx_market', 'register_subscription_item', [...]); @endcode
+     * 
+     * Register a processed subscription (recurring payment) inside the Market module. Is called with payment processing module after the subscription was registered there.
+     * 
+     * @param $iClientId client ID.
+     * @param $iSellerId seller ID
+     * @param $iItemId item ID.
+     * @param $iItemCount the number of purchased items.
+     * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
+     * @param $sLicense license number genereted with payment processing module for internal usage
+     * @return an array with subscribed prodict's description. Empty array is returned if something is wrong.
+     * 
+     * @see BxMarketModule::serviceRegisterSubscriptionItem
+     */
+    /** 
+     * @ref bx_market-register_subscription_item "register_subscription_item"
+     */
+    public function serviceRegisterSubscriptionItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense)
+    {
+		return $this->_serviceRegisterItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense, BX_MARKET_LICENSE_TYPE_RECURRING);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_market Market
+     * @subsection bx_market-payments Payments
+     * @subsubsection bx_market-reregister_cart_item reregister_cart_item
+     * 
+     * @code bx_srv('bx_market', 'reregister_cart_item', [...]); @endcode
+     * 
+     * Reregister a single time payment inside the Market module. Is called with payment processing module after the payment was reregistered there.
+     * 
+     * @param $iClientId client ID.
+     * @param $iSellerId seller ID
+     * @param $iItemIdOld old item ID.
+     * @param $iItemIdNew new item ID.
+     * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
+     * @return an array with purchased prodict's description. Empty array is returned if something is wrong.
+     * 
+     * @see BxMarketModule::serviceReregisterCartItem
+     */
+    /** 
+     * @ref bx_market-reregister_cart_item "reregister_cart_item"
+     */
+    public function serviceReregisterCartItem($iClientId, $iSellerId, $iItemIdOld, $iItemIdNew, $sOrder)
+    {
+        return $this->_serviceReregisterItem($iClientId, $iSellerId, $iItemIdOld, $iItemIdNew, $sOrder, BX_MARKET_LICENSE_TYPE_SINGLE);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_market Market
+     * @subsection bx_market-payments Payments
+     * @subsubsection bx_market-reregister_subscription_item reregister_subscription_item
+     * 
+     * @code bx_srv('bx_market', 'reregister_subscription_item', [...]); @endcode
+     * 
+     * Reregister a subscription (recurring payment) inside the Market module. Is called with payment processing module after the subscription was reregistered there.
+     * 
+     * @param $iClientId client ID.
+     * @param $iSellerId seller ID
+     * @param $iItemIdOld old item ID.
+     * @param $iItemIdNew new item ID.
+     * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
+     * @return an array with subscribed prodict's description. Empty array is returned if something is wrong.
+     * 
+     * @see BxMarketModule::serviceReregisterSubscriptionItem
+     */
+    /** 
+     * @ref bx_market-reregister_subscription_item "reregister_subscription_item"
+     */
+    public function serviceReregisterSubscriptionItem($iClientId, $iSellerId, $iItemIdOld, $iItemIdNew, $sOrder)
+    {
+		return $this->_serviceReregisterItem($iClientId, $iSellerId, $iItemIdOld, $iItemIdNew, $sOrder, BX_MARKET_LICENSE_TYPE_RECURRING);
+    }
+
+	/**
+     * @page service Service Calls
+     * @section bx_market Market
+     * @subsection bx_market-payments Payments
+     * @subsubsection bx_market-unregister_cart_item unregister_cart_item
+     * 
+     * @code bx_srv('bx_market', 'unregister_cart_item', [...]); @endcode
+     * 
+     * Unregister an earlier processed single time payment inside the Market module. Is called with payment processing module after the payment was unregistered there.
+     * 
+     * @param $iClientId client ID.
+     * @param $iSellerId seller ID
+     * @param $iItemId item ID.
+     * @param $iItemCount the number of purchased items.
+     * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
+     * @param $sLicense license number genereted with payment processing module for internal usage
+     * @return boolean value determining where the payment was unregistered or not.
+     * 
+     * @see BxMarketModule::serviceUnregisterCartItem
+     */
+    /** 
+     * @ref bx_market-unregister_cart_item "unregister_cart_item"
+     */
+    public function serviceUnregisterCartItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense)
+    {
+        return $this->_serviceUnregisterItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense, BX_MARKET_LICENSE_TYPE_SINGLE);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_market Market
+     * @subsection bx_market-payments Payments
+     * @subsubsection bx_market-unregister_subscription_item unregister_subscription_item
+     * 
+     * @code bx_srv('bx_market', 'unregister_subscription_item', [...]); @endcode
+     * 
+     * Unregister an earlier processed subscription (recurring payment) inside the Market module. Is called with payment processing module after the subscription was unregistered there.
+     * 
+     * @param $iClientId client ID.
+     * @param $iSellerId seller ID
+     * @param $iItemId item ID.
+     * @param $iItemCount the number of purchased items.
+     * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
+     * @param $sLicense license number genereted with payment processing module for internal usage
+     * @return boolean value determining where the subscription was unregistered or not.
+     * 
+     * @see BxMarketModule::serviceUnregisterSubscriptionItem
+     */
+    /** 
+     * @ref bx_market-unregister_subscription_item "unregister_subscription_item"
+     */
+    public function serviceUnregisterSubscriptionItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense)
+    {
+    	return $this->_serviceUnregisterItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense, BX_MARKET_LICENSE_TYPE_RECURRING); 
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_market Market
+     * @subsection bx_market-payments Payments
+     * @subsubsection bx_market-cancel_subscription_item cancel_subscription_item
+     * 
+     * @code bx_srv('bx_market', 'cancel_subscription_item', [...]); @endcode
+     * 
+     * Cancel an earlier processed subscription (recurring payment) inside the Market module. Is called with payment processing module after the subscription was canceled there.
+     * 
+     * @param $iClientId client ID.
+     * @param $iSellerId seller ID
+     * @param $iItemId item ID.
+     * @param $iItemCount the number of purchased items.
+     * @param $sOrder order number received from payment provider (PayPal, Stripe, etc)
+     * @return boolean value determining where the subscription was canceled or not.
+     * 
+     * @see BxMarketModule::serviceCancelSubscriptionItem
+     */
+    /** 
+     * @ref bx_market-cancel_subscription_item "cancel_subscription_item"
+     */
+	public function serviceCancelSubscriptionItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder)
+    {
+    	//TODO: Do something if it's necessary.
+    	return true;
+    }
+
+    protected function _serviceRegisterItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense, $sType)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+    	$aItem = $this->serviceGetCartItem($iItemId);
+        if(empty($aItem) || !is_array($aItem))
+            return array();
+
+        $aProduct = $this->_oDb->getContentInfoById($iItemId);
+        if(empty($aProduct) || !is_array($aProduct))
+            return array();
+
+        if(!BxDolPrivacy::getObjectInstance($CNF['OBJECT_PRIVACY_PURCHASE'])->check((int)$iItemId, $iClientId))
+            return array();
+
+        $iTrial = 0;
+        $sDuration = '';
+        $sAction = 'register';
+        if($sType == BX_MARKET_LICENSE_TYPE_RECURRING) {
+            $iTrial = $aProduct[$this->_oConfig->CNF['FIELD_TRIAL_RECURRING']];
+            $sDuration = $aProduct[$this->_oConfig->CNF['FIELD_DURATION_RECURRING']];
+            
+            if($this->_oDb->hasLicenseByOrder($iClientId, $iItemId, $sOrder))
+                $sAction = 'prolong';
+        }
+
+        if(!$this->_oDb->{$sAction . 'License'}($iClientId, $iItemId, $iItemCount, $sOrder, $sLicense, $sType, $sDuration, $iTrial))
+            return array();
+
+        bx_alert($this->getName(), 'license_' . $sAction, 0, false, array(
+            'product_id' => $iItemId,
+            'profile_id' => $iClientId,
+            'order' => $sOrder,
+            'license' => $sLicense,
+            'type' => $sType,
+            'count' => $iItemCount,
+            'duration' => $sDuration,
+            'trial' => $iTrial
+        ));
+
+        $oClient = BxDolProfile::getInstanceMagic($iClientId);
+        $oSeller = BxDolProfile::getInstanceMagic($iSellerId);
+        $sSellerUrl = $oSeller->getUrl();
+        $sSellerName = $oSeller->getDisplayName();
+
+        $sNote = $aProduct[$CNF['FIELD_NOTES_PURCHASED']];
+        if(empty($sNote))
+            $sNote = _t('_bx_market_txt_purchased_note', $sSellerUrl, $sSellerName);
+
+        sendMailTemplate($CNF['ETEMPLATE_PURCHASED'], 0, $iClientId, array(
+            'client_name' => $oClient->getDisplayName(),
+            'product_name' => $aProduct[$CNF['FIELD_TITLE']],
+            'product_url' => BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink('page.php?i=view-product&id=' . $aProduct[$CNF['FIELD_ID']]),
+            'vendor_url' => $sSellerUrl,
+            'vendor_name' => $sSellerName,
+            'license' => $sLicense,
+            'notes' => $sNote,
+        ));
+
+        return $aItem;
+    }
+
+    protected function _serviceReregisterItem($iClientId, $iSellerId, $iItemIdOld, $iItemIdNew, $sOrder, $sType)
+    {
+        $aItemNew = $this->serviceGetCartItem($iItemIdNew);
+        if(empty($aItemNew) || !is_array($aItemNew))
+            return array();
+
+        if(!$this->_oDb->hasLicenseByOrder($iClientId, $iItemIdOld, $sOrder))
+            return array();
+
+        if(!$this->_oDb->updateLicense(array('product_id' => $iItemIdNew), array('profile_id' => $iClientId, 'product_id' => $iItemIdOld, 'order' => $sOrder)))
+            return array();
+
+        bx_alert($this->getName(), 'license_reregister', 0, false, array(
+            'product_id_old' => $iItemIdOld,
+            'product_id_new' => $iItemIdNew,
+            'profile_id' => $iClientId,
+            'order' => $sOrder,
+            'type' => $sType
+        ));
+
+        return $aItemNew;
+    }
+
+    protected function _serviceUnregisterItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense, $sType)
+    {
+    	if(!$this->_oDb->unregisterLicense($iClientId, $iItemId, $sOrder, $sLicense, $sType))
+    		return false;
+
+        bx_alert($this->getName(), 'license_unregister', 0, false, array(
+            'product_id' => $iItemId,
+            'profile_id' => $iClientId,
+            'order' => $sOrder,
+            'license' => $sLicense,
+            'type' => $sType,
+            'count' => $iItemCount
+        ));
+
+    	return true;
+    }
+
+    public function getGhostTemplateVars($aFile, $iProfileId, $iContentId, $oStorage, $oImagesTranscoder)
+    {
+    	$CNF = &$this->_oConfig->CNF;
+
+    	$sMethod = '';
+    	$sStorage = $oStorage->getObject();
+        switch($sStorage) {
+        	case $CNF['OBJECT_STORAGE']:
+        		$sMethod = 'getPhoto';
+        		break;
+
+			case $CNF['OBJECT_STORAGE_FILES']:
+				$sMethod = 'getFile';
+				break;
+        }
+
+		$aFileInfo = $this->_oDb->$sMethod(array('type' => 'file_id', 'file_id' => $aFile['id']));
+        $bFileInfo = !empty($aFileInfo) && is_array($aFileInfo);
+
+        $bFileInfoTitle = $bFileInfo && isset($aFileInfo['title']);
+
+		$aTmplVars = array(
+			'file_title' => $bFileInfoTitle ? $aFileInfo['title'] : '',
+			'file_title_attr' => $bFileInfoTitle ? bx_html_attribute($aFileInfo['title']) : '',
+		);
+
+		if($sStorage == $CNF['OBJECT_STORAGE'])
+			return $aTmplVars;
+
+		$bFileInfoVersion = $bFileInfo && isset($aFileInfo['version']);
+
+        $bFileInfoTypeVersion = !$bFileInfo || ($bFileInfo && isset($aFileInfo['type']) && $aFileInfo['type'] == BX_MARKET_FILE_TYPE_VERSION);
+        $bFileInfoTypeUpdate = $bFileInfo && isset($aFileInfo['type']) && $aFileInfo['type'] == BX_MARKET_FILE_TYPE_UPDATE;
+
+        $aVersions = $this->_oDb->$sMethod(array('type' => 'content_id', 'content_id' => $iContentId));
+
+		$aTmplVars = array_merge($aTmplVars, array(
+			'file_version' => $bFileInfoVersion ? $aFileInfo['version'] : '',
+			'file_version_attr' => $bFileInfoVersion ? bx_html_attribute($aFileInfo['version']) : '',
+
+			'file_type_version_selected' => $bFileInfoTypeVersion ? ' selected="selected"' : '',
+			'file_type_update_selected' => $bFileInfoTypeUpdate ? ' selected="selected"' : '',
+
+			'file_type_version_elements' => !$bFileInfoTypeVersion ? ' style="display:none;"' : '',
+			'file_type_update_elements' => !$bFileInfoTypeUpdate ? ' style="display:none;"' : '',
+
+			'file_version_from_options' => $this->_oTemplate->getGhostTemplateFileOptions('version', $aFileInfo, $aVersions),
+			'file_version_to_options' => $this->_oTemplate->getGhostTemplateFileOptions('version_to', $aFileInfo, $aVersions)
+		));
+
+		return $aTmplVars;
+    }
+
+    public function checkAllowedDelete (&$aDataEntry, $isPerformAction = false)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        if($aDataEntry[$CNF['FIELD_AUTHOR']] == $this->_iProfileId) {
+            $aLicenses = $this->_oDb->getLicense(array('type' => 'product_id', 'product_id' => $aDataEntry[$CNF['FIELD_ID']]));
+            if(is_array($aLicenses) && count($aLicenses) > 0)
+                return _t('_sys_txt_access_denied');
+        }
+
+        return parent::checkAllowedDelete($aDataEntry, $isPerformAction);
+    }
+
+    public function checkAllowedSetCover ()
+    {
+        $aCheck = checkActionModule($this->_iProfileId, 'set cover', $this->getName(), false);
+        if($aCheck[CHECK_ACTION_RESULT] !== CHECK_ACTION_RESULT_ALLOWED)
+            return $aCheck[CHECK_ACTION_MESSAGE];
+
+        return CHECK_ACTION_RESULT_ALLOWED;
+    }
+
+    public function checkAllowedSetSubentries ()
+    {
+        $aCheck = checkActionModule($this->_iProfileId, 'set subentries', $this->getName(), false);
+        if($aCheck[CHECK_ACTION_RESULT] !== CHECK_ACTION_RESULT_ALLOWED)
+            return $aCheck[CHECK_ACTION_MESSAGE];
+
+        return CHECK_ACTION_RESULT_ALLOWED;
+    }
+
+	public function checkAllowedDownload($aDataEntry, $isPerformAction = false)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        // moderator and owner always have access
+        if ($aDataEntry[$CNF['FIELD_AUTHOR']] == $this->_iProfileId || $this->_isModerator($isPerformAction))
+            return CHECK_ACTION_RESULT_ALLOWED;
+
+        // check ACL
+        $aCheck = checkActionModule($this->_iProfileId, 'download entry', $this->getName(), $isPerformAction);
+        if($aCheck[CHECK_ACTION_RESULT] !== CHECK_ACTION_RESULT_ALLOWED)
+			return $aCheck[CHECK_ACTION_MESSAGE];
+
+        if((float)$aDataEntry[$CNF['FIELD_PRICE_SINGLE']] == 0 && (float)$aDataEntry[$CNF['FIELD_PRICE_RECURRING']] == 0)
+            return CHECK_ACTION_RESULT_ALLOWED;
+
+		if(!$this->_oDb->hasLicense($this->_iProfileId, $aDataEntry[$CNF['FIELD_ID']]))
+            return CHECK_ACTION_RESULT_NOT_ALLOWED;
+
+        return CHECK_ACTION_RESULT_ALLOWED;
+    }
+
+    public function checkAllowedHide($aDataEntry, $isPerformAction = false)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        if($aDataEntry[$CNF['FIELD_STATUS']] != 'active')
+            return CHECK_ACTION_RESULT_NOT_ALLOWED;
+
+        // moderator and owner always have access
+        if ($aDataEntry[$CNF['FIELD_AUTHOR']] == $this->_iProfileId || $this->_isModerator($isPerformAction))
+            return CHECK_ACTION_RESULT_ALLOWED;
+
+        return CHECK_ACTION_RESULT_NOT_ALLOWED;
+    }
+
+    public function checkAllowedUnhide($aDataEntry, $isPerformAction = false)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        if($aDataEntry[$CNF['FIELD_STATUS']] == 'active')
+            return CHECK_ACTION_RESULT_NOT_ALLOWED;
+
+        // moderator and owner always have access
+        if ($aDataEntry[$CNF['FIELD_AUTHOR']] == $this->_iProfileId || $this->_isModerator($isPerformAction))
+            return CHECK_ACTION_RESULT_ALLOWED;
+
+        return CHECK_ACTION_RESULT_NOT_ALLOWED;
+    }
+
+    public function checkAllowedViewMoreMenu (&$aDataEntry, $isPerformAction = false)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $oMenu = BxTemplMenu::getObjectInstance($CNF['OBJECT_MENU_ACTIONS_VIEW_ENTRY_MORE']);
+        $oMenu->setContentId($aDataEntry[$CNF['FIELD_ID']]);
+        if(!$oMenu || !$oMenu->isVisible())
+            return CHECK_ACTION_RESULT_NOT_ALLOWED;
+
+        return CHECK_ACTION_RESULT_ALLOWED;
+    }
+
+    protected function _getBlockLicenses($sType = '') 
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $sGrid = $this->_oConfig->getGridObject('licenses' . (!empty($sType) ? '_' . $sType : ''));
+        $oGrid = BxDolGrid::getObjectInstance($sGrid);
+        if(!$oGrid)
+            return '';
+
+        $this->_oDb->updateLicense(array('new' => 0), array('profile_id' => bx_get_logged_profile_id(), 'new' => 1));
+
+        $this->_oTemplate->addJs(array('licenses.js'));
+        return array(
+            'content' => $this->_oTemplate->getJsCode('licenses', array('sObjNameGrid' => $sGrid)) . $oGrid->getCode(),
+            'menu' => $CNF['OBJECT_MENU_LICENSES']
+        );
+    }
+
+    protected function _getContentInfo($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 $aContentInfo;
+    }
+
+    protected function _performHideProduct($aDataEntry) {
+        $CNF = &$this->_oConfig->CNF;
+
+        if(!$this->_oDb->updateContentInfoBy(array($CNF['FIELD_STATUS'] => 'hidden'), array($CNF['FIELD_ID'] => $aDataEntry[$CNF['FIELD_ID']]))) 
+            return echoJson(array());
+
+        $this->checkAllowedHide($aDataEntry, true);
+        return echoJson(array('reload' => 1));
+    }
+
+    protected function _performUnhideProduct($aDataEntry) {
+        $CNF = &$this->_oConfig->CNF;
+
+        if(!$this->_oDb->updateContentInfoBy(array($CNF['FIELD_STATUS'] => 'active'), array($CNF['FIELD_ID'] => $aDataEntry[$CNF['FIELD_ID']]))) 
+            return echoJson(array());
+
+        $this->checkAllowedHide($aDataEntry, true);
+        return echoJson(array('reload' => 1));
+    }
+}
+
+/** @} */

+ 150 - 0
modules/boonex/market/updates/13.0.2_13.0.3/source/classes/BxMarketSearchResult.php

@@ -0,0 +1,150 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Market Market
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxMarketSearchResult extends BxBaseModTextSearchResult
+{
+    function __construct($sMode = '', $aParams = array())
+    {
+        parent::__construct($sMode, $aParams);
+
+        $this->aCurrent = array(
+            'name' => 'bx_market',
+            'module_name' => 'bx_market',
+            'object_metatags' => 'bx_market',
+            'title' => _t('_bx_market_page_title_browse'),
+            'table' => 'bx_market_products',
+            'ownFields' => array('id', 'title', 'text', 'price_single', 'price_recurring', 'duration_recurring', 'thumb', 'cover', 'cover_raw', 'author', 'added'),
+            'searchFields' => array(),
+            'restriction' => array(
+                'author' => array('value' => '', 'field' => 'author', 'operator' => '='),
+                'featured' => array('value' => '', 'field' => 'featured', 'operator' => '<>'),
+                'except' => array('value' => '', 'field' => 'id', 'operator' => 'not in'),
+                'status' => array('value' => 'active', 'field' => 'status', 'operator' => '='),
+                'statusAdmin' => array('value' => 'active', 'field' => 'status_admin', 'operator' => '='),
+            ),
+            'paginate' => array('perPage' => getParam('bx_market_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' => 'text',
+            		'Image' => 'thumb'
+                ),
+            ),
+            'ident' => 'id',
+        );
+
+        $this->sFilterName = 'bx_market_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;
+                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_LATEST']);
+                $this->aCurrent['title'] = _t('_bx_market_page_title_browse_latest');
+                $this->aCurrent['rss']['link'] = 'modules/?r=market/rss/' . $sMode;
+                break;
+
+            case 'featured':
+                $this->sBrowseUrl = BxDolPermalinks::getInstance()->permalink($CNF['URL_FEATURED']);
+                $this->aCurrent['title'] = _t('_bx_market_page_title_browse_featured');
+                $this->aCurrent['restriction']['featured']['value'] = '0';
+                $this->aCurrent['rss']['link'] = 'modules/?r=market/rss/' . $sMode;
+                $this->aCurrent['sorting'] = 'featured';
+                break;
+
+            case 'popular':
+                $this->sBrowseUrl = BxDolPermalinks::getInstance()->permalink($CNF['URL_POPULAR']);
+                $this->aCurrent['title'] = _t('_bx_market_page_title_browse_popular');
+                $this->aCurrent['rss']['link'] = 'modules/?r=market/rss/' . $sMode;
+                $this->aCurrent['sorting'] = 'popular';
+                break;
+
+            case 'top':
+                $this->sBrowseUrl = BxDolPermalinks::getInstance()->permalink($CNF['URL_TOP']);
+                $this->aCurrent['title'] = _t('_bx_market_page_title_browse_top');
+                $this->aCurrent['rss']['link'] = 'modules/?r=market/rss/' . $sMode;
+                $this->aCurrent['sorting'] = 'top';
+                break;
+
+            case 'updated':
+                $this->sBrowseUrl = BxDolPermalinks::getInstance()->permalink($CNF['URL_UPDATED']);
+                $this->aCurrent['title'] = _t('_bx_market_page_title_browse_updated');
+                $this->aCurrent['rss']['link'] = 'modules/?r=market/rss/' . $sMode;
+                $this->aCurrent['sorting'] = 'updated';
+                break;
+
+            case '': // search results
+                $this->sBrowseUrl = BX_DOL_SEARCH_KEYWORD_PAGE;
+                unset($this->aCurrent['paginate']['perPage'], $this->aCurrent['rss']);
+                break;
+
+            default:
+                $sMode = '';
+                $this->isError = true;
+        }
+
+        $this->processReplaceableMarkers($oProfileAuthor);
+
+        $this->addConditionsForPrivateContent($CNF, $oProfileAuthor);
+        $this->addCustomConditions($CNF, $oProfileAuthor, $sMode, $aParams);
+    }
+
+    public function setMetaType($s)
+    {
+        $this->_sMetaType = $s;
+        if(!empty($this->_sMetaType) && $this->_sMetaType == 'keyword')
+            $this->aCurrent['title'] = _t('_bx_market_page_title_browse_keyword', bx_process_pass(bx_get('keyword')));
+    }
+
+    public function setCategoryObject($s)
+    {
+        $this->_sCategoryObject = $s;
+        if(!empty($this->_sCategoryObject) && $o = BxDolCategory::getObjectInstance($this->_sCategoryObject))
+            $this->aCurrent['title'] = _t('_bx_market_page_title_browse_category', $o->getCategoryTitle((int)bx_get('keyword')));
+    }
+
+    function displayResultBlock ()
+    {
+    	return BxDolPayments::getInstance()->getCartJs() . parent::displayResultBlock();
+    }
+}
+
+/** @} */

+ 467 - 0
modules/boonex/market/updates/13.0.2_13.0.3/source/classes/BxMarketTemplate.php

@@ -0,0 +1,467 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Market Market
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+/*
+ * Module representation.
+ */
+class BxMarketTemplate extends BxBaseModTextTemplate
+{
+	protected $_aCurrency;
+
+    /**
+     * Constructor
+     */
+    function __construct(&$oConfig, &$oDb)
+    {
+        $this->MODULE = 'bx_market';
+
+        parent::__construct($oConfig, $oDb);
+
+        $this->_aCurrency = $this->_oConfig->getCurrency();
+    }
+
+    public function entryRating($aData)
+    {
+        $CNF = &$this->getModule()->_oConfig->CNF;
+
+        $sVotes = '';
+        $oVotes = BxDolVote::getObjectInstance($CNF['OBJECT_VOTES'], $aData['id']);
+        if($oVotes) {
+            $sVotes = $oVotes->getElementBlock(array('show_counter' => true, 'show_legend' => true));
+            if(!empty($sVotes))
+                $sVotes = $this->parseHtmlByName('entry-rating.html', array(
+                'content' => $sVotes,
+            ));
+        }
+
+        return $sVotes; 
+    }
+
+    public function getTmplVarsText($aData)
+    {
+        $oModule = $this->getModule();
+        $CNF = &$oModule->_oConfig->CNF;
+
+        $aVars = parent::getTmplVarsText($aData);
+
+        //--- Process Cover
+        $bCoverRaw = !empty($CNF['FIELD_COVER_RAW']) && !empty($aData[$CNF['FIELD_COVER_RAW']]);
+
+        $aVars['bx_if:show_image_raw'] = [
+            'condition' => $bCoverRaw,
+            'content' => [
+                'image_raw' => $aData[$CNF['FIELD_COVER_RAW']]
+            ]
+        ];
+
+        $aVars['bx_if:show_image']['condition'] = !$bCoverRaw && $aVars['bx_if:show_image']['condition'];
+
+        //--- Process Thumb
+        $sIcon = '';
+        $mixedIcon = $oModule->getEntryImageData($aData, 'FIELD_THUMB', array('OBJECT_IMAGES_TRANSCODER_THUMB', 'OBJECT_IMAGES_TRANSCODER_GALLERY'));
+        if($mixedIcon !== false) {
+            if(!empty($mixedIcon['object']))
+                $o = BxDolStorage::getObjectInstance($mixedIcon['object']);
+            else if(!empty($mixedIcon['transcoder']))
+                $o = BxDolTranscoder::getObjectInstance($mixedIcon['transcoder']);
+
+            if($o)
+                $sIcon = $o->getFileUrlById($mixedIcon['id']);
+        }
+
+        $aVars['bx_if:show_icon'] = array(
+            'condition' => !empty($sIcon),
+            'content' => array(
+                'entry_icon' => $sIcon
+            )
+        );
+
+        //--- Process Screenshots
+        $sScreenshots = $this->getScreenshots($aData);
+        $bScreenshots = !empty($sScreenshots);
+        if($bScreenshots) {
+            $this->addCss(BX_DIRECTORY_PATH_PLUGINS_PUBLIC . 'flickity/|flickity.css');
+            $this->addJs('flickity/flickity.pkgd.min.js');
+        }
+
+        $aVars['bx_if:show_screenshots'] = array(
+            'condition' => $bScreenshots,
+            'content' => array(
+                'screenshots' => $sScreenshots
+            )
+        );
+        
+        return $aVars;
+    }
+
+    public function getScreenshots($aData)
+    {
+    	$oModule = $this->getModule();
+
+    	$CNF = &$oModule->_oConfig->CNF;
+    	$aPhotos = $oModule->serviceGetScreenshots($aData[$CNF['FIELD_ID']]);
+        if(empty($aPhotos) || !is_array($aPhotos))
+            return '';
+
+        return $this->parseHtmlByName('entry-screenshots.html', array(
+            'bx_repeat:items' => $aPhotos
+    	));
+    }
+    
+    public function getAuthorAddon ($aData, $oProfile)
+    {
+        $aAccount = $oProfile->getAccountObject()->getInfo();
+
+        $sContent = $this->parseHtmlByName('entry-author.html', array(
+    		'joined' => bx_time_js($aAccount['added']),
+	    	'last_active' => bx_time_js($aAccount['logged']),
+	    	'installs' => '?',
+    	));
+
+    	return $sContent . parent::getAuthorAddon ($aData, $oProfile);
+    }
+
+    public function getGhostTemplateFileOptions($sField, $aFile, $aVersions)
+    {
+    	$bField = !empty($aFile) && is_array($aFile) && isset($aFile[$sField]);
+    	
+    	$aTmplVarsVersions = array();
+    	foreach ($aVersions as $aVersion) {
+    		if($aVersion['type'] != 'version' || empty($aVersion['version']))
+    			continue;
+
+			$aTmplVarsVersions[] = array(
+				'value' => $aVersion['version'],
+				'title' =>  $aVersion['version'],
+				'bx_if:selected' => array(
+					'condition' => $bField && $aFile[$sField] == $aVersion['version'],
+					'content' => array()
+				)
+			);
+    	}
+
+    	return $this->parseHtmlByName('form_ghost_template_file_options.html', array(
+    		'bx_repeat:versions' => $aTmplVarsVersions
+    	));    	
+    }
+
+    protected function getUnit ($aData, $aParams = array())
+    {
+        $bTmplVarsSectionAuthor = true;
+        $bTmplVarsSectionPricing = false;
+        $bTmplVarsSectionVoting = true;
+
+        $oModule = $this->getModule();
+    	$CNF = &$oModule->_oConfig->CNF;
+
+    	$aUnit = parent::getUnit($aData, $aParams);
+        $oPayment = BxDolPayments::getInstance();
+        $oPermalinks = BxDolPermalinks::getInstance();
+
+        list($sAuthorName, $sAuthorUrl, $sAuthorIcon, $sAuthorUnit, $sAuthorUnitShort) = $oModule->getUserInfo($aData[$CNF['FIELD_AUTHOR']]);
+
+        $aTmplVarsSectionAuthor = array();
+        if($bTmplVarsSectionAuthor) {
+            //--- Author Info
+            $bAuthorIcon = !empty($sAuthorIcon);
+            $sAuthorName = $this->parseHtmlByName('author_link.html', array(
+                'href' => $sAuthorUrl,
+                'title' => bx_html_attribute($sAuthorName),
+                'content' => $sAuthorName,
+                'bx_if:show_account' => array(
+                    'condition' => false,
+                    'content' => array()
+                )
+            ));
+
+            //--- Actions
+            $sActions = '';
+            $oActions = BxDolMenu::getObjectInstance($CNF['OBJECT_MENU_ACTIONS_SNIPPET']);
+            if($oActions) {
+                $oActions->setContentId($aData[$CNF['FIELD_ID']]);
+                $sActions = $oActions->getCode();
+            }
+
+            $sDate = $this->parseHtmlByName('snippet-date.html', array(
+                'date' => bx_time_js($aData[$CNF['FIELD_ADDED']])
+            ));
+
+            $aTmplVarsSectionAuthor = array(
+                'actions' => $sActions,
+                'author_unit' => $sAuthorUnitShort,
+                'author_width_date' => _t('_bx_market_txt_author_added_product', $sAuthorName, $sDate),
+            );
+        }
+
+        //--- Main Info
+        $sUrl = BX_DOL_URL_ROOT . $oPermalinks->permalink('page.php?i=' . $CNF['URI_VIEW_ENTRY'] . '&id=' . $aData[$CNF['FIELD_ID']]);
+        $sLinkMore = ' <a title="' . bx_html_attribute(_t('_sys_read_more', $aData[$CNF['FIELD_TITLE']])) . '" href="' . $sUrl . '"><i class="sys-icon ellipsis-h"></i></a>';
+        $sSummary = strmaxtextlen($aData[$CNF['FIELD_TEXT']], (int)getParam($CNF['PARAM_CHARS_SUMMARY']), $sLinkMore);
+        $sSummaryPlain = BxTemplFunctions::getInstance()->getStringWithLimitedLength(strip_tags($sSummary), (int)getParam($CNF['PARAM_CHARS_SUMMARY_PLAIN']));
+        
+
+        //--- Icon Info
+        $sIconUrl = '';
+        if(!empty($CNF['FIELD_THUMB']) && $aData[$CNF['FIELD_THUMB']]) {
+            $iThumb = (int)$aData[$CNF['FIELD_THUMB']];
+
+            $oStorage = BxDolStorage::getObjectInstance($CNF['OBJECT_STORAGE']);
+            $aThumb = $oStorage->getFile($iThumb);
+
+            if(strpos($aThumb['mime_type'], 'svg') !== false)
+                $sIconUrl = $oStorage->getFileUrlById($iThumb);
+
+            if(empty($sIconUrl)) {
+                $oImagesTranscoder = BxDolTranscoderImage::getObjectInstance($CNF['OBJECT_IMAGES_TRANSCODER_ICON']);
+                if($oImagesTranscoder)
+                    $sIconUrl = $oImagesTranscoder->getFileUrl($iThumb);
+            }
+
+            if(empty($sIconUrl)) {
+                $oImagesTranscoder = BxDolTranscoderImage::getObjectInstance($CNF['OBJECT_IMAGES_TRANSCODER_THUMB']);
+                if($oImagesTranscoder)
+                    $sIconUrl = $oImagesTranscoder->getFileUrl($iThumb);
+            }
+        }
+
+        //--- Cover Info
+        $bCoverRaw = !empty($CNF['FIELD_COVER_RAW']) && !empty($aData[$CNF['FIELD_COVER_RAW']]);
+
+        $sCoverUrl = '';
+        if(!$bCoverRaw && !empty($CNF['FIELD_COVER']) && $aData[$CNF['FIELD_COVER']]) {
+            $oImagesTranscoder = BxDolTranscoderImage::getObjectInstance($CNF['OBJECT_IMAGES_TRANSCODER_GALLERY']);
+            if($oImagesTranscoder)
+                $sCoverUrl = $oImagesTranscoder->getFileUrl($aData[$CNF['FIELD_COVER']]);
+
+            if(empty($sCoverUrl)) {
+                $oImagesTranscoder = BxDolTranscoderImage::getObjectInstance($CNF['OBJECT_IMAGES_TRANSCODER_COVER']);
+                if($oImagesTranscoder)
+                    $sCoverUrl = $oImagesTranscoder->getFileUrl($aData[$CNF['FIELD_COVER']]);
+            }
+        }
+
+        $aTmplVarsSectionPricing = array();
+        if($bTmplVarsSectionPricing) {
+            //--- Price Single
+            $bTmplVarsSingle = (float)$aData[$CNF['FIELD_PRICE_SINGLE']] != 0;
+            $aTmplVarsSingle = array();
+            if($bTmplVarsSingle) {
+                $aJsSingle = $oPayment->getAddToCartJs($aData[$CNF['FIELD_AUTHOR']], $this->_oConfig->getName(), $aData[$CNF['FIELD_ID']], 1, true);
+                if(!empty($aJsSingle) && is_array($aJsSingle)) {
+                    list($sJsCode, $sSingleOnclick) = $aJsSingle;
+
+                    $aTmplVarsSingle = array(
+                        'price_single_onclick' => $sSingleOnclick,
+                        'price_single' => _t('_bx_market_txt_price_single', $this->_aCurrency['sign'], $aData[$CNF['FIELD_PRICE_SINGLE']])
+                    );
+                }
+                else 
+                    $bTmplVarsSingle = false;
+            }
+
+            //--- Price Recurring
+            $bTmplVarsRecurring = !$oPayment->isCreditsOnly() && (float)$aData[$CNF['FIELD_PRICE_RECURRING']] != 0;
+            $aTmplVarsRecurring = array();
+            if($bTmplVarsRecurring) {
+                $aJsRecurring = $oPayment->getSubscribeJs($aData[$CNF['FIELD_AUTHOR']], '', $this->_oConfig->getName(), $aData[$CNF['FIELD_ID']], 1);
+                if(!empty($aJsRecurring) && is_array($aJsRecurring)) {
+                    list($sJsCode, $sRecurringOnclick) = $aJsRecurring;
+
+                    $aTmplVarsRecurring = array(
+                        'price_recurring_onclick' => $sRecurringOnclick,
+                        'price_recurring' => _t('_bx_market_txt_price_recurring', $this->_aCurrency['sign'], $aData[$CNF['FIELD_PRICE_RECURRING']], _t($CNF['T']['txt_per_' . $aData[$CNF['FIELD_DURATION_RECURRING']] . '_short']))
+                    );
+                }
+                else 
+                    $bTmplVarsRecurring = false;
+            }
+
+            $aTmplVarsSectionPricing = array(
+                'bx_if:show_single' => array(
+                    'condition' => $bTmplVarsSingle,
+                    'content' => $aTmplVarsSingle
+                ),
+                'bx_if:show_recurring' => array(
+                    'condition' => $bTmplVarsRecurring,
+                    'content' => $aTmplVarsRecurring
+                ),
+                'bx_if:show_free' => array(
+                    'condition' => !$bTmplVarsSingle && !$bTmplVarsRecurring,
+                    'content' => array(
+                        'price_free_href' => $oPermalinks->permalink('page.php?i=' . $CNF['URI_DOWNLOAD_ENTRY'] . '&id=' . $aData[$CNF['FIELD_ID']])
+                    )
+                )
+            );
+        }
+
+        $aTmplVarsSectionVoting = array();
+        if($bTmplVarsSectionVoting) {
+            $sVoting = '';
+            $oVoting = BxDolVote::getObjectInstance($CNF['OBJECT_VOTES'], $aData[$CNF['FIELD_ID']]);
+            if($oVoting)
+                $sVoting = $oVoting->getElementBlock(array('show_counter' => false));
+
+            $sPricing = "";
+            if((float)$aData[$CNF['FIELD_PRICE_RECURRING']] != 0) {
+                $sDuration = 'txt_per_' . $aData[$CNF['FIELD_DURATION_RECURRING']] . '_short';
+                $sDuration = _t(!empty($CNF['T'][$sDuration]) ? $CNF['T'][$sDuration] : '_bx_market_txt_per_' . $aData[$CNF['FIELD_DURATION_RECURRING']] . '_short');
+
+                $sPricing = _t('_bx_market_txt_price_recurring_short', $this->_aCurrency['sign'], $aData[$CNF['FIELD_PRICE_RECURRING']], $sDuration);
+            }
+
+            if(empty($sPricing) && (float)$aData[$CNF['FIELD_PRICE_SINGLE']] != 0)
+                $sPricing = _t('_bx_market_txt_price_single_short', $this->_aCurrency['sign'], $aData[$CNF['FIELD_PRICE_SINGLE']]);
+
+            if(empty($sPricing))
+                 $sPricing = _t('_bx_market_txt_price_free');
+
+            $aTmplVarsSectionVoting = array(
+                'voting' => $sVoting,
+                'pricing' => $sPricing
+            );
+        }
+
+    	$aUnit = array_merge($aUnit, array(
+    	    'bx_if:show_section_author' => array(
+    	        'condition' => $bTmplVarsSectionAuthor,
+    	        'content' => $aTmplVarsSectionAuthor
+    	    ),
+            'bx_if:show_icon' => array (
+                'condition' => $sIconUrl,
+                'content' => array(
+                	'icon_url' => $sIconUrl,
+                ),
+            ),
+            'bx_if:show_icon_empty' => array (
+                'condition' => !$sIconUrl,
+                'content' => array(
+                    'icon' => $CNF['ICON']
+                ),
+            ),
+            'bx_if:show_cover_raw' => array (
+                'condition' => $bCoverRaw,
+                'content' => array (
+                    'summary_attr' => bx_html_attribute($sSummaryPlain),
+                    'content_url' => $sUrl,
+                    'cover_raw' => $aData[$CNF['FIELD_COVER_RAW']],
+                ),
+            ),
+            'bx_if:show_cover' => array (
+                'condition' => $sCoverUrl,
+                'content' => array (
+                    'summary_attr' => bx_html_attribute($sSummaryPlain),
+                    'content_url' => $sUrl,
+                    'cover_url' => $sCoverUrl,
+                    'strecher' => str_repeat('&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ', 40),
+                ),
+            ),
+            'bx_if:show_cover_empty' => array (
+                'condition' => !$bCoverRaw && !$sCoverUrl,
+                'content' => array (
+                    'summary_plain' => $sSummaryPlain,
+                    'strecher' => mb_strlen($sSummaryPlain) > 240 ? '' : str_repeat('&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ', round((240 - mb_strlen($sSummaryPlain)) / 6)),
+                ),
+            ),
+            'author_name' => $sAuthorName,
+            'content_url' => $sUrl,
+    		'bx_if:show_section_pricing' => array(
+                'condition' => $bTmplVarsSectionPricing,
+                'content' => $aTmplVarsSectionPricing
+            ),
+            'bx_if:show_section_voting' => array(
+            	'condition' => $bTmplVarsSectionVoting,
+                'content' => $aTmplVarsSectionVoting
+            )
+    	));
+
+    	return $aUnit;
+    }
+
+    protected function getAttachments($sStorage, $aData, $aParams = array())
+    {
+        $mixedAttachments = parent::getAttachments($sStorage, $aData, $aParams);
+        if(empty($mixedAttachments) || !is_array($mixedAttachments))
+            return $mixedAttachments;
+
+        $aAttachments = [];
+        foreach($mixedAttachments as $aAttachment)
+            $aAttachments[(int)$aAttachment['id']] = $aAttachment;       
+
+        $aFiles = $this->_oDb->getFile(['type' => 'content_id_key_file_id', 'content_id' => $aData['id']]);
+
+        $aResults = [];
+        $sCaptionType = "";
+        foreach($aFiles as $iAttachmentId => $aFile) {
+            $aAttachments[$iAttachmentId]['class'] = (int)$aData['package'] == $iAttachmentId ? ' bx-market-attachment-main' : '';
+            $aAttachments[$iAttachmentId]['bx_if:main'] = [
+                'condition' => (int)$aData['package'] == $iAttachmentId,
+                'content' => []
+            ];
+
+            $bSeparatorNeeded = false;
+            if ($aFiles[$iAttachmentId]['type'] != $sCaptionType){
+                $bSeparatorNeeded = true;
+                $sCaptionType = $aFiles[$iAttachmentId]['type'];
+            }
+
+            if ((int)$aData['package'] == $iAttachmentId){
+                $bSeparatorNeeded = true;
+                $sCaptionType = 'latest';
+            }
+
+            $bAttachment = !empty($aFiles[$iAttachmentId]);
+            $aAttachments[$iAttachmentId]['bx_if:not_image']['content'] = array_merge($aAttachments[$iAttachmentId]['bx_if:not_image']['content'], [
+                'file_type' => $bAttachment ? _t('_bx_market_form_entry_input_files_type_' . $aFiles[$iAttachmentId]['type']) : '',
+                'file_name_attr' => bx_html_attribute($aAttachments[$iAttachmentId]['file_name']),
+                'bx_if:show_version' => [
+                    'condition' => $bAttachment && $aFiles[$iAttachmentId]['type'] == BX_MARKET_FILE_TYPE_VERSION,
+                    'content' => [
+                        'file_version' => $bAttachment ? $aFiles[$iAttachmentId]['version'] : ''
+                    ]
+                ],
+                'bx_if:show_update' => [
+                    'condition' => $bAttachment && $aFiles[$iAttachmentId]['type'] == BX_MARKET_FILE_TYPE_UPDATE,
+                    'content' => [
+                        'file_version_from_to' => $bAttachment ? _t('_bx_market_form_entry_input_files_version_from_x_to_y', $aFiles[$iAttachmentId]['version'], $aFiles[$iAttachmentId]['version_to']) : ''
+                    ]
+                ]
+            ]);
+            $aAttachments[$iAttachmentId]['bx_if:show_separator'] = [
+                'condition' => $bSeparatorNeeded, 
+                'content' => [
+                    'type' => _t('_bx_market_form_entry_input_files_version_caption_' . $sCaptionType)
+                ]
+            ];
+
+            $aFiles[$iAttachmentId] = $aAttachments[$iAttachmentId];
+            $aResults[$iAttachmentId] = $aAttachments[$iAttachmentId];
+        }
+
+        return array_intersect_key($aFiles, $aResults);
+    }
+
+    protected function getAttachmentsImagesTranscoders ($sStorage = '')
+    {
+        $CNF = &$this->getModule()->_oConfig->CNF;
+
+        $oTranscoder = BxDolTranscoderImage::getObjectInstance($CNF['OBJECT_IMAGES_TRANSCODER_PREVIEW']);
+        $oTranscoderPreview = isset($CNF['OBJECT_IMAGES_TRANSCODER_PICTURE']) && $CNF['OBJECT_IMAGES_TRANSCODER_PICTURE'] ? BxDolTranscoderImage::getObjectInstance($CNF['OBJECT_IMAGES_TRANSCODER_PICTURE']) : null;
+
+        return array($oTranscoder, $oTranscoderPreview);
+    }
+
+    protected function _getHeaderImage($aData)
+    {
+        return $this->getModule()->getEntryImageData($aData, 'FIELD_COVER');
+    }
+}
+
+/** @} */

+ 140 - 0
modules/boonex/market/updates/13.0.2_13.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' => '13.0.3',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '13.0.0-B2'
+    ),
+
+    /**
+     * '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'
+    ),
+
+);
+
+/** @} */

+ 477 - 0
modules/boonex/market/updates/13.0.2_13.0.3/source/install/langs/en.xml

@@ -0,0 +1,477 @@
+<?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_auto_approve"><![CDATA[Auto approve a product after creation]]></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_cover_raw"><![CDATA[Header Image RAW]]></string>
+	<string name="_bx_market_form_entry_input_cover_raw"><![CDATA[Header Image RAW]]></string>
+        <string name="_bx_market_form_entry_input_cover_raw_inf"><![CDATA[If provided, it'll be used instead of image based variant.]]></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_acl_action_delete_any_entry"><![CDATA[Delete 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_reports"><![CDATA[Reports]]></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[Favorites Products]]></string>
+    <string name="_bx_market_page_title_entries_favorites"><![CDATA[Favorites 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_select_one_filter2"><![CDATA[Any Audience]]></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_filter_item_title_adm_pending"><![CDATA[Pending]]></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_column_title_adm_status_admin"><![CDATA[Moderation]]></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_txt_msg_status_hidden"><![CDATA[This product was hidden.]]></string>
+    <string name="_bx_market_txt_msg_status_pending"><![CDATA[This product is pending approval.]]></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>

+ 633 - 0
modules/boonex/market/updates/13.0.2_13.0.3/source/install/sql/install.sql

@@ -0,0 +1,633 @@
+
+SET @sStorageEngine = (SELECT `value` FROM `sys_options` WHERE `name` = 'sys_storage_default');
+
+-- TABLE: entries
+CREATE TABLE IF NOT EXISTS `bx_market_products` (
+  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
+  `author` int(11) unsigned NOT NULL default '0',
+  `added` int(11) NOT NULL default '0',
+  `changed` int(11) NOT NULL default '0',
+  `thumb` int(11) NOT NULL default '0',
+  `cover` int(11) NOT NULL default '0',
+  `cover_raw` text NOT NULL,
+  `package` int(11) NOT NULL default '0',
+  `name` varchar(255) NOT NULL,
+  `title` varchar(255) NOT NULL,
+  `text` text NOT NULL,
+  `notes` text NOT NULL,
+  `notes_purchased` text NOT NULL,
+  `cat` int(11) NOT NULL,
+  `price_single` float NOT NULL default '0',
+  `price_recurring` float NOT NULL default '0',
+  `duration_recurring` varchar(16) NOT NULL default 'month',
+  `trial_recurring` int(11) 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',
+  `cf` int(11) NOT NULL default '1',
+  `allow_view_to` varchar(32) NOT NULL DEFAULT '3',
+  `allow_purchase_to` varchar(32) NOT NULL DEFAULT '3',
+  `allow_comment_to` varchar(32) NOT NULL DEFAULT 'c',
+  `allow_vote_to` varchar(32) NOT NULL DEFAULT 'c',
+  `status` enum('active','hidden') NOT NULL DEFAULT 'active',
+  `status_admin` enum('active','hidden','pending') NOT NULL DEFAULT 'active',
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `name` (`name`(191)),
+  FULLTEXT KEY `title_text` (`title`,`text`)
+);
+
+-- TABLE: subentries
+CREATE TABLE IF NOT EXISTS `bx_market_subproducts` (
+  `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: licenses
+CREATE TABLE IF NOT EXISTS `bx_market_licenses` (
+  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
+  `profile_id` int(11) unsigned NOT NULL default '0',
+  `product_id` int(11) unsigned NOT NULL default '0',
+  `count` int(11) unsigned NOT NULL default '0',
+  `order` varchar(32) NOT NULL default '',
+  `license` varchar(32) NOT NULL default '',
+  `type` varchar(16) NOT NULL default '',
+  `domain` varchar(128) NOT NULL default '',
+  `added` int(11) unsigned NOT NULL default '0',
+  `expired` int(11) unsigned NOT NULL default '0',
+  `new` tinyint(1) NOT NULL default '1',
+  PRIMARY KEY (`id`),
+  KEY `product_id` (`product_id`, `profile_id`),
+  KEY `license` (`license`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_market_licenses_deleted` (
+  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
+  `profile_id` int(11) unsigned NOT NULL default '0',
+  `product_id` int(11) unsigned NOT NULL default '0',
+  `count` int(11) unsigned NOT NULL default '0',
+  `order` varchar(32) NOT NULL default '',
+  `license` varchar(32) NOT NULL default '',
+  `type` varchar(16) NOT NULL default '',
+  `domain` varchar(128) NOT NULL default '',
+  `added` int(11) unsigned NOT NULL default '0',
+  `expired` int(11) unsigned NOT NULL default '0',
+  `new` tinyint(1) NOT NULL default '1',
+  `reason` varchar(16) NOT NULL default '',
+  `deleted` int(11) unsigned NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `product_id` (`product_id`,`profile_id`),
+  KEY `license` (`license`)
+);
+
+-- TABLE: storages & transcoders
+CREATE TABLE IF NOT EXISTS `bx_market_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_market_files2products` (
+  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
+  `content_id` int(11) unsigned NOT NULL,
+  `file_id` int(11) NOT NULL,
+  `type` enum('version','update') NOT NULL DEFAULT 'version',
+  `version` varchar(255) NOT NULL,
+  `version_to` varchar(255) NOT NULL,
+  `downloads` int(11) NOT NULL,
+  `order` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `file_content` (`file_id`,`content_id`),
+  KEY `content_id` (`content_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_market_downloads_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `file_id` int(11) NOT NULL default '0',
+  `profile_id` int(11) NOT NULL default '0',
+  `profile_nip` int(11) unsigned NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_market_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_market_photos2products` (
+  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
+  `content_id` int(11) unsigned NOT NULL,
+  `file_id` int(11) NOT NULL,
+  `title` varchar(255) NOT NULL,
+  `order` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `file_content` (`file_id`,`content_id`),
+  KEY `content_id` (`content_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_market_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_market_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',
+  `cmt_cf` int(11) NOT NULL default '1',
+  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_market_cmts_notes` (
+  `cmt_id` int(11) NOT NULL AUTO_INCREMENT,
+  `cmt_parent_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_vparent_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_object_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_author_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_level` int(11) NOT NULL DEFAULT '0',
+  `cmt_text` text NOT NULL,
+  `cmt_mood` tinyint(4) NOT NULL DEFAULT '0',
+  `cmt_rate` int(11) NOT NULL DEFAULT '0',
+  `cmt_rate_count` int(11) NOT NULL DEFAULT '0',
+  `cmt_time` int(11) unsigned NOT NULL DEFAULT '0',
+  `cmt_replies` int(11) NOT NULL DEFAULT '0',
+  `cmt_pinned` int(11) NOT NULL default '0',
+  PRIMARY KEY (`cmt_id`),
+  KEY `cmt_object_id` (`cmt_object_id`,`cmt_parent_id`),
+  FULLTEXT KEY `search_fields` (`cmt_text`)
+);
+
+-- TABLE: votes
+CREATE TABLE IF NOT EXISTS `bx_market_votes` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `count` int(11) NOT NULL default '0',
+  `sum` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `object_id` (`object_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_market_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_market_reactions` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `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',
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `reaction` (`object_id`, `reaction`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_market_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_market_views_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `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',
+  PRIMARY KEY (`id`),
+  KEY `id` (`object_id`,`viewer_id`,`viewer_nip`)
+);
+
+-- TABLE: metas
+CREATE TABLE `bx_market_meta_keywords` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(10) unsigned NOT NULL,
+  `keyword` varchar(255) NOT NULL,
+  PRIMARY KEY (`id`),
+  KEY `object_id` (`object_id`),
+  KEY `keyword` (`keyword`)
+);
+
+CREATE TABLE `bx_market_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_market_meta_mentions` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(10) unsigned NOT NULL,
+  `profile_id` int(10) unsigned NOT NULL,
+  PRIMARY KEY (`id`),
+  KEY `object_id` (`object_id`),
+  KEY `profile_id` (`profile_id`)
+);
+
+-- TABLE: reports
+CREATE TABLE IF NOT EXISTS `bx_market_reports` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `count` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `object_id` (`object_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_market_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',
+  `checked_by` int(11) NOT NULL default '0',
+  `status` tinyint(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `report` (`object_id`, `author_nip`)
+);
+
+-- TABLE: favorites
+CREATE TABLE `bx_market_favorites_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `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',
+  PRIMARY KEY (`id`),
+  KEY `id` (`object_id`,`author_id`)
+);
+
+CREATE TABLE `bx_market_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_market_scores` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `count_up` int(11) NOT NULL default '0',
+  `count_down` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `object_id` (`object_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_market_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_market_files', @sStorageEngine, '', 360, 2592000, 3, 'bx_market_files', 'allow-deny', 'zip', '', 0, 0, 0, 0, 0, 0),
+('bx_market_photos', @sStorageEngine, '', 360, 2592000, 3, 'bx_market_photos', 'allow-deny', 'jpg,jpeg,jpe,gif,png,svg', '', 0, 0, 0, 0, 0, 0),
+('bx_market_photos_resized', @sStorageEngine, '', 360, 2592000, 3, 'bx_market_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_market_preview', 'bx_market_photos_resized', 'Storage', 'a:1:{s:6:"object";s:16:"bx_market_photos";}', 'no', '1', '2592000', '0'),
+('bx_market_icon', 'bx_market_photos_resized', 'Storage', 'a:1:{s:6:"object";s:16:"bx_market_photos";}', 'no', '1', '2592000', '0'),
+('bx_market_thumb', 'bx_market_photos_resized', 'Storage', 'a:1:{s:6:"object";s:16:"bx_market_photos";}', 'no', '1', '2592000', '0'),
+('bx_market_cover', 'bx_market_photos_resized', 'Storage', 'a:1:{s:6:"object";s:16:"bx_market_photos";}', 'no', '1', '2592000', '0'),
+('bx_market_screenshot', 'bx_market_photos_resized', 'Storage', 'a:1:{s:6:"object";s:16:"bx_market_photos";}', 'no', '1', '2592000', '0'),
+('bx_market_gallery', 'bx_market_photos_resized', 'Storage', 'a:1:{s:6:"object";s:16:"bx_market_photos";}', 'no', '1', '2592000', '0');
+
+INSERT INTO `sys_transcoder_filters` (`transcoder_object`, `filter`, `filter_params`, `order`) VALUES 
+('bx_market_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_market_gallery', 'Resize', 'a:1:{s:1:"w";s:3:"500";}', '0'),
+('bx_market_icon', 'Resize', 'a:3:{s:1:"w";s:2:"50";s:1:"h";s:2:"50";s:13:"square_resize";s:1:"1";}', '0'),
+('bx_market_thumb', 'Resize', 'a:3:{s:1:"w";s:3:"100";s:1:"h";s:3:"100";s:13:"square_resize";s:1:"1";}', '0'),
+('bx_market_cover', 'Resize', 'a:1:{s:1:"w";s:4:"2000";}', '0'),
+('bx_market_screenshot', 'Resize', 'a:3:{s:1:"w";s:3:"200";s:1:"h";s:3:"120";s:11:"crop_resize";s:1:"1";}', '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_market', 'bx_market', '_bx_market_form_entry', '', 'a:1:{s:7:"enctype";s:19:"multipart/form-data";}', 'bx_market_products', 'id', '', '', 'a:2:{i:0;s:9:"do_submit";i:1;s:10:"do_publish";}', '', 0, 1, 'BxMarketFormEntry', 'modules/boonex/market/classes/BxMarketFormEntry.php');
+
+INSERT INTO `sys_form_displays`(`object`, `display_name`, `module`, `view_mode`, `title`) VALUES 
+('bx_market', 'bx_market_entry_add', 'bx_market', 0, '_bx_market_form_entry_display_add'),
+('bx_market', 'bx_market_entry_delete', 'bx_market', 0, '_bx_market_form_entry_display_delete'),
+('bx_market', 'bx_market_entry_edit', 'bx_market', 0, '_bx_market_form_entry_display_edit'),
+('bx_market', 'bx_market_entry_view', 'bx_market', 1, '_bx_market_form_entry_display_view'),
+('bx_market', 'bx_market_entry_view_full', 'bx_market', 1, '_bx_market_form_entry_display_view_full');
+
+INSERT INTO `sys_form_inputs`(`object`, `module`, `name`, `value`, `values`, `checked`, `type`, `caption_system`, `caption`, `info`, `required`, `collapsed`, `html`, `attrs`, `attrs_tr`, `attrs_wrapper`, `checker_func`, `checker_params`, `checker_error`, `db_pass`, `db_params`, `editable`, `deletable`) VALUES 
+('bx_market', 'bx_market', 'cf', '1', '#!sys_content_filter', 0, 'select', '_sys_form_entry_input_sys_cf', '_sys_form_entry_input_cf', '', 0, 0, 0, '', '', '', '', '', '', 'Int', '', 1, 0),
+('bx_market', 'bx_market', 'allow_view_to', '', '', 0, 'custom', '_bx_market_form_entry_input_sys_allow_view_to', '_bx_market_form_entry_input_allow_view_to', '', 1, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_market', 'bx_market', 'allow_purchase_to', '', '', 0, 'custom', '_bx_market_form_entry_input_sys_allow_purchase_to', '_bx_market_form_entry_input_allow_purchase_to', '', 1, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_market', 'bx_market', 'allow_comment_to', '', '', 0, 'custom', '_bx_market_form_entry_input_sys_allow_comment_to', '_bx_market_form_entry_input_allow_comment_to', '', 1, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_market', 'bx_market', 'allow_vote_to', '', '', 0, 'custom', '_bx_market_form_entry_input_sys_allow_vote_to', '_bx_market_form_entry_input_allow_vote_to', '', 1, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_market', 'bx_market', 'delete_confirm', 1, '', 0, 'checkbox', '_bx_market_form_entry_input_sys_delete_confirm', '_bx_market_form_entry_input_delete_confirm', '_bx_market_form_entry_input_delete_confirm_info', 1, 0, 0, '', '', '', 'Avail', '', '_bx_market_form_entry_input_delete_confirm_error', '', '', 1, 0),
+('bx_market', 'bx_market', 'do_publish', '_bx_market_form_entry_input_do_publish', '', 0, 'submit', '_bx_market_form_entry_input_sys_do_publish', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_market', 'bx_market', 'do_submit', '_bx_market_form_entry_input_do_submit', '', 0, 'submit', '_bx_market_form_entry_input_sys_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_market', 'bx_market', 'location', '', '', 0, 'location', '_sys_form_input_sys_location', '_sys_form_input_location', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_market', 'bx_market', 'cover_raw', '', '', 0, 'textarea', '_bx_market_form_entry_input_sys_cover_raw', '_bx_market_form_entry_input_cover_raw', '_bx_market_form_entry_input_cover_raw_inf', 0, 0, 0, '', '', '', '', '', '', 'XssHtml', '', 1, 0),
+('bx_market', 'bx_market', 'pictures', 'a:1:{i:0;s:15:"bx_market_html5";}', 'a:2:{s:16:"bx_market_simple";s:26:"_sys_uploader_simple_title";s:15:"bx_market_html5";s:25:"_sys_uploader_html5_title";}', 0, 'files', '_bx_market_form_entry_input_sys_pictures', '_bx_market_form_entry_input_pictures', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_market', 'bx_market', 'files', 'a:1:{i:0;s:15:"bx_market_html5";}', 'a:2:{s:16:"bx_market_simple";s:26:"_sys_uploader_simple_title";s:15:"bx_market_html5";s:25:"_sys_uploader_html5_title";}', 0, 'files', '_bx_market_form_entry_input_sys_files', '_bx_market_form_entry_input_files', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_market', 'bx_market', 'text', '', '', 0, 'textarea', '_bx_market_form_entry_input_sys_text', '_bx_market_form_entry_input_text', '', 1, 0, 2, '', '', '', 'Avail', '', '_bx_market_form_entry_input_text_err', 'XssHtml', '', 1, 0),
+('bx_market', 'bx_market', 'notes', '', '', 0, 'textarea', '_bx_market_form_entry_input_sys_notes', '_bx_market_form_entry_input_notes', '_bx_market_form_entry_input_notes_inf', 0, 0, 0, '', '', '', '', '', '', 'Xss', '', 1, 0),
+('bx_market', 'bx_market', 'notes_purchased', '', '', 0, 'textarea', '_bx_market_form_entry_input_sys_notes_purchased', '_bx_market_form_entry_input_notes_purchased', '_bx_market_form_entry_input_notes_purchased_inf', 0, 0, 3, '', '', '', '', '', '', 'XssHtml', '', 1, 0),
+('bx_market', 'bx_market', 'title', '', '', 0, 'text', '_bx_market_form_entry_input_sys_title', '_bx_market_form_entry_input_title', '', 1, 0, 0, '', '', '', 'Avail', '', '_bx_market_form_entry_input_title_err', 'Xss', '', 1, 0),
+('bx_market', 'bx_market', 'name', '', '', 0, 'text', '_bx_market_form_entry_input_sys_name', '_bx_market_form_entry_input_name', '', 1, 0, 0, '', '', '', 'Avail', '', '_bx_market_form_entry_input_name_err', 'Xss', '', 1, 0),
+('bx_market', 'bx_market', 'cat', '', '#!bx_market_cats', 0, 'select', '_bx_market_form_entry_input_sys_cat', '_bx_market_form_entry_input_cat', '', 1, 0, 0, '', '', '', 'avail', '', '_bx_market_form_entry_input_cat_err', 'Xss', '', 1, 0),
+('bx_market', 'bx_market', 'price_single', '', '', 0, 'price', '_bx_market_form_entry_input_sys_price_single', '_bx_market_form_entry_input_price_single', '_bx_market_form_entry_input_price_single_inf', 0, 0, 0, '', '', '', '', '', '', 'Float', '', 1, 0),
+('bx_market', 'bx_market', 'price_recurring', '', '', 0, 'price', '_bx_market_form_entry_input_sys_price_recurring', '_bx_market_form_entry_input_price_recurring', '_bx_market_form_entry_input_price_recurring_inf', 0, 0, 0, '', '', '', '', '', '', 'Float', '', 1, 0),
+('bx_market', 'bx_market', 'duration_recurring', 'month', '#!bx_market_durations', 0, 'select', '_bx_market_form_entry_input_sys_duration_recurring', '_bx_market_form_entry_input_duration_recurring', '', 0, 0, 0, '', '', '', '', '', '', 'Xss', '', 1, 0),
+('bx_market', 'bx_market', 'trial_recurring', '', '', 0, 'text', '_bx_market_form_entry_input_sys_trial_recurring', '_bx_market_form_entry_input_trial_recurring', '_bx_market_form_entry_input_trial_recurring_inf', 0, 0, 0, '', '', '', '', '', '', 'Int', '', 1, 0),
+('bx_market', 'bx_market', 'added', '', '', 0, 'datetime', '_bx_market_form_entry_input_sys_added', '_bx_market_form_entry_input_added', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_market', 'bx_market', 'changed', '', '', 0, 'datetime', '_bx_market_form_entry_input_sys_changed', '_bx_market_form_entry_input_changed', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_market', 'bx_market', 'header_beg_single', '', '', 0, 'block_header', '_bx_market_form_entry_input_sys_header_beg_single', '_bx_market_form_entry_input_header_beg_single', '', 0, 1, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_market', 'bx_market', 'header_beg_recurring', '', '', 0, 'block_header', '_bx_market_form_entry_input_sys_header_beg_recurring', '_bx_market_form_entry_input_header_beg_recurring', '', 0, 1, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_market', 'bx_market', 'header_beg_privacy', '', '', 0, 'block_header', '_bx_market_form_entry_input_sys_header_beg_privacy', '_bx_market_form_entry_input_header_beg_privacy', '', 0, 1, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_market', 'bx_market', 'header_beg_notes', '', '', 0, 'block_header', '_bx_market_form_entry_input_sys_header_beg_notes', '_bx_market_form_entry_input_header_beg_notes', '', 0, 1, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_market', 'bx_market', 'header_beg_other', '', '', 0, 'block_header', '_bx_market_form_entry_input_sys_header_beg_other', '_bx_market_form_entry_input_header_beg_other', '', 0, 1, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_market', 'bx_market', 'header_end_single', '', '', 0, 'block_end', '_bx_market_form_entry_input_sys_header_end_single', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
+('bx_market', 'bx_market', 'header_end_recurring', '', '', 0, 'block_end', '_bx_market_form_entry_input_sys_header_end_recurring', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
+('bx_market', 'bx_market', 'header_end_privacy', '', '', 0, 'block_end', '_bx_market_form_entry_input_sys_header_end_privacy', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
+('bx_market', 'bx_market', 'header_end_notes', '', '', 0, 'block_end', '_bx_market_form_entry_input_sys_header_end_notes', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
+('bx_market', 'bx_market', 'header_end_other', '', '', 0, 'block_end', '_bx_market_form_entry_input_sys_header_end_other', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
+('bx_market', 'bx_market', 'warning_single', '_bx_market_err_not_accept_payments_single', '', 0, 'value', '_bx_market_form_entry_input_sys_warning_single', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_market', 'bx_market', 'warning_recurring', '_bx_market_err_not_accept_payments_recurring', '', 0, 'value', '_bx_market_form_entry_input_sys_warning_recurring', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_market', 'bx_market', 'subentries', '', '', 0, 'custom', '_bx_market_form_entry_input_sys_subentries', '_bx_market_form_entry_input_subentries', '_bx_market_form_entry_input_subentries_inf', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_market', 'bx_market', '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_market_entry_add', 'title', 2147483647, 1, 1),
+('bx_market_entry_add', 'name', 2147483647, 1, 2),
+('bx_market_entry_add', 'cat', 2147483647, 1, 3),
+('bx_market_entry_add', 'text', 2147483647, 1, 4),
+('bx_market_entry_add', 'cover_raw', 2147483647, 0, 5),
+('bx_market_entry_add', 'pictures', 2147483647, 1, 6),
+('bx_market_entry_add', 'files', 2147483647, 1, 7),
+('bx_market_entry_add', 'header_beg_single', 2147483647, 1, 8),
+('bx_market_entry_add', 'warning_single', 2147483647, 1, 9),
+('bx_market_entry_add', 'price_single', 2147483647, 1, 10),
+('bx_market_entry_add', 'header_end_single', 2147483647, 1, 11),
+('bx_market_entry_add', 'header_beg_recurring', 2147483647, 1, 12),
+('bx_market_entry_add', 'warning_recurring', 2147483647, 1, 13),
+('bx_market_entry_add', 'duration_recurring', 2147483647, 1, 14),
+('bx_market_entry_add', 'price_recurring', 2147483647, 1, 15),
+('bx_market_entry_add', 'trial_recurring', 2147483647, 1, 16),
+('bx_market_entry_add', 'header_end_recurring', 2147483647, 1, 17),
+('bx_market_entry_add', 'header_beg_privacy', 2147483647, 1, 18),
+('bx_market_entry_add', 'allow_view_to', 2147483647, 1, 19),
+('bx_market_entry_add', 'allow_purchase_to', 2147483647, 1, 20),
+('bx_market_entry_add', 'allow_comment_to', 2147483647, 1, 21),
+('bx_market_entry_add', 'allow_vote_to', 2147483647, 1, 22),
+('bx_market_entry_add', 'cf', 2147483647, 1, 23),
+('bx_market_entry_add', 'header_end_privacy', 2147483647, 1, 24),
+('bx_market_entry_add', 'header_beg_notes', 2147483647, 1, 25),
+('bx_market_entry_add', 'notes', 2147483647, 1, 26),
+('bx_market_entry_add', 'notes_purchased', 2147483647, 1, 27),
+('bx_market_entry_add', 'header_end_notes', 2147483647, 1, 28),
+('bx_market_entry_add', 'header_beg_other', 2147483647, 1, 29),
+('bx_market_entry_add', 'location', 2147483647, 1, 30),
+('bx_market_entry_add', 'subentries', 2147483647, 1, 31),
+('bx_market_entry_add', 'header_end_other', 2147483647, 1, 32),
+('bx_market_entry_add', 'do_publish', 2147483647, 1, 33),
+
+('bx_market_entry_delete', 'delete_confirm', 2147483647, 1, 1),
+('bx_market_entry_delete', 'do_submit', 2147483647, 1, 2),
+
+('bx_market_entry_edit', 'title', 2147483647, 1, 1),
+('bx_market_entry_edit', 'name', 2147483647, 1, 2),
+('bx_market_entry_edit', 'cat', 2147483647, 1, 3),
+('bx_market_entry_edit', 'text', 2147483647, 1, 4),
+('bx_market_entry_edit', 'cover_raw', 2147483647, 0, 5),
+('bx_market_entry_edit', 'pictures', 2147483647, 1, 6),
+('bx_market_entry_edit', 'files', 2147483647, 1, 7),
+('bx_market_entry_edit', 'header_beg_single', 2147483647, 1, 8),
+('bx_market_entry_edit', 'warning_single', 2147483647, 1, 9),
+('bx_market_entry_edit', 'price_single', 2147483647, 1, 10),
+('bx_market_entry_edit', 'header_end_single', 2147483647, 1, 11),
+('bx_market_entry_edit', 'header_beg_recurring', 2147483647, 1, 12),
+('bx_market_entry_edit', 'warning_recurring', 2147483647, 1, 13),
+('bx_market_entry_edit', 'duration_recurring', 2147483647, 1, 14),
+('bx_market_entry_edit', 'price_recurring', 2147483647, 1, 15),
+('bx_market_entry_edit', 'trial_recurring', 2147483647, 1, 16),
+('bx_market_entry_edit', 'header_end_recurring', 2147483647, 1, 17),
+('bx_market_entry_edit', 'header_beg_privacy', 2147483647, 1, 18),
+('bx_market_entry_edit', 'allow_view_to', 2147483647, 1, 19),
+('bx_market_entry_edit', 'allow_purchase_to', 2147483647, 1, 20),
+('bx_market_entry_edit', 'allow_comment_to', 2147483647, 1, 21),
+('bx_market_entry_edit', 'allow_vote_to', 2147483647, 1, 22),
+('bx_market_entry_edit', 'cf', 2147483647, 1, 23),
+('bx_market_entry_edit', 'header_end_privacy', 2147483647, 1, 24),
+('bx_market_entry_edit', 'header_beg_notes', 2147483647, 1, 25),
+('bx_market_entry_edit', 'notes', 2147483647, 1, 26),
+('bx_market_entry_edit', 'notes_purchased', 2147483647, 1, 27),
+('bx_market_entry_edit', 'header_end_notes', 2147483647, 1, 28),
+('bx_market_entry_edit', 'header_beg_other', 2147483647, 1, 29),
+('bx_market_entry_edit', 'location', 2147483647, 1, 30),
+('bx_market_entry_edit', 'subentries', 2147483647, 1, 31),
+('bx_market_entry_edit', 'header_end_other', 2147483647, 1, 32),
+('bx_market_entry_edit', 'do_submit', 2147483647, 1, 33),
+
+('bx_market_entry_view', 'cat', 2147483647, 1, 1),
+('bx_market_entry_view', 'added', 2147483647, 1, 2),
+('bx_market_entry_view', 'changed', 2147483647, 1, 3),
+
+('bx_market_entry_view_full', 'cat', 2147483647, 1, 1),
+('bx_market_entry_view_full', 'added', 2147483647, 1, 2),
+('bx_market_entry_view_full', 'changed', 2147483647, 1, 3),
+('bx_market_entry_view_full', 'notes', 2147483647, 1, 4);
+
+-- PRE-VALUES
+INSERT INTO `sys_form_pre_lists`(`key`, `title`, `module`, `use_for_sets`) VALUES
+('bx_market_cats', '_bx_market_pre_lists_cats', 'bx_market', '0'),
+('bx_market_durations', '_bx_market_pre_lists_durations', 'bx_market', '0');
+
+INSERT INTO `sys_form_pre_values`(`Key`, `Value`, `Order`, `LKey`, `LKey2`) VALUES
+('bx_market_cats', '', 0, '_sys_please_select', ''),
+('bx_market_cats', '1', 1, '_bx_market_cat_administration', ''),
+('bx_market_cats', '2', 2, '_bx_market_cat_adult', ''),
+('bx_market_cats', '3', 3, '_bx_market_cat_advertisement', ''),
+('bx_market_cats', '4', 4, '_bx_market_cat_affiliates', ''),
+('bx_market_cats', '5', 5, '_bx_market_cat_authentication', ''),
+('bx_market_cats', '6', 6, '_bx_market_cat_calendars', ''),
+('bx_market_cats', '7', 7, '_bx_market_cat_communication', ''),
+('bx_market_cats', '8', 8, '_bx_market_cat_content', ''),
+('bx_market_cats', '9', 9, '_bx_market_cat_conversion', ''),
+('bx_market_cats', '10', 10, '_bx_market_cat_core_changes', ''),
+('bx_market_cats', '11', 11, '_bx_market_cat_dating', ''),
+('bx_market_cats', '12', 12, '_bx_market_cat_documentation', ''),
+('bx_market_cats', '13', 13, '_bx_market_cat_ecommerce', ''),
+('bx_market_cats', '14', 14, '_bx_market_cat_events', ''),
+('bx_market_cats', '15', 15, '_bx_market_cat_feedback', ''),
+('bx_market_cats', '16', 16, '_bx_market_cat_flash', ''),
+('bx_market_cats', '17', 17, '_bx_market_cat_games', ''),
+('bx_market_cats', '18', 18, '_bx_market_cat_graphics', ''),
+('bx_market_cats', '19', 19, '_bx_market_cat_hosting', ''),
+('bx_market_cats', '20', 20, '_bx_market_cat_integrations', ''),
+('bx_market_cats', '21', 21, '_bx_market_cat_location', ''),
+('bx_market_cats', '22', 22, '_bx_market_cat_management', ''),
+('bx_market_cats', '23', 23, '_bx_market_cat_mobile', ''),
+('bx_market_cats', '24', 24, '_bx_market_cat_multimedia', ''),
+('bx_market_cats', '25', 25, '_bx_market_cat_music', ''),
+('bx_market_cats', '26', 26, '_bx_market_cat_navigation', ''),
+('bx_market_cats', '27', 27, '_bx_market_cat_other', ''),
+('bx_market_cats', '28', 28, '_bx_market_cat_performance', ''),
+('bx_market_cats', '29', 29, '_bx_market_cat_photos', ''),
+('bx_market_cats', '30', 30, '_bx_market_cat_search', ''),
+('bx_market_cats', '31', 31, '_bx_market_cat_security', ''),
+('bx_market_cats', '32', 32, '_bx_market_cat_services', ''),
+('bx_market_cats', '33', 33, '_bx_market_cat_social', ''),
+('bx_market_cats', '34', 34, '_bx_market_cat_spam_prevention', ''),
+('bx_market_cats', '35', 35, '_bx_market_cat_statistics', ''),
+('bx_market_cats', '36', 36, '_bx_market_cat_templates', ''),
+('bx_market_cats', '37', 37, '_bx_market_cat_tools', ''),
+('bx_market_cats', '38', 38, '_bx_market_cat_translations', ''),
+('bx_market_cats', '39', 39, '_bx_market_cat_video', ''),
+
+('bx_market_durations', 'day', 1, '_bx_market_cat_duration_day', ''),
+('bx_market_durations', 'week', 2, '_bx_market_cat_duration_week', ''),
+('bx_market_durations', 'month', 3, '_bx_market_cat_duration_month', ''),
+('bx_market_durations', 'year', 4, '_bx_market_cat_duration_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_market', 'bx_market', 'bx_market_cmts', 1, 5000, 1000, 3, 5, 3, 'tail', 1, 'bottom', 1, 1, 1, -3, 1, 'cmt', 'page.php?i=view-product&id={object_id}', '', 'bx_market_products', 'id', 'author', 'title', 'comments', 'BxMarketCmts', 'modules/boonex/market/classes/BxMarketCmts.php'),
+('bx_market_notes', 'bx_market', 'bx_market_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_market_products', 'id', 'author', 'title', '', 'BxTemplCmtsNotes', '');
+
+-- VOTES
+INSERT INTO `sys_objects_vote` (`Name`, `TableMain`, `TableTrack`, `PostTimeout`, `MinValue`, `MaxValue`, `IsUndo`, `IsOn`, `TriggerTable`, `TriggerFieldId`, `TriggerFieldAuthor`, `TriggerFieldRate`, `TriggerFieldRateCount`, `ClassName`, `ClassFile`) VALUES 
+('bx_market', 'bx_market_votes', 'bx_market_votes_track', '604800', '1', '5', '0', '1', 'bx_market_products', 'id', 'author', 'rate', 'votes', 'BxMarketVoteStars', 'modules/boonex/market/classes/BxMarketVoteStars.php'),
+('bx_market_reactions', 'bx_market_reactions', 'bx_market_reactions_track', '604800', '1', '1', '1', '1', 'bx_market_products', 'id', 'author', 'rrate', 'rvotes', 'BxMarketVoteReactions', 'modules/boonex/market/classes/BxMarketVoteReactions.php');
+
+-- SCORES
+INSERT INTO `sys_objects_score` (`name`, `module`, `table_main`, `table_track`, `post_timeout`, `is_on`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_score`, `trigger_field_cup`, `trigger_field_cdown`, `class_name`, `class_file`) VALUES 
+('bx_market', 'bx_market', 'bx_market_scores', 'bx_market_scores_track', '604800', '0', 'bx_market_products', 'id', 'author', 'score', 'sc_up', 'sc_down', 'BxMarketScore', 'modules/boonex/market/classes/BxMarketScore.php');
+
+-- 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_market', 'bx_market', 'bx_market_reports', 'bx_market_reports_track', '1', 'page.php?i=view-product&id={object_id}', 'bx_market_notes', 'bx_market_products', '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_market', 'bx_market_views_track', '86400', '1', 'bx_market_products', 'id', 'author', 'views', '', '');
+
+-- FAFORITES
+INSERT INTO `sys_objects_favorite` (`name`, `table_track`, `table_lists`, `is_on`, `is_undo`, `is_public`, `base_url`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_count`, `class_name`, `class_file`) VALUES 
+('bx_market', 'bx_market_favorites_track', 'bx_market_favorites_lists', '1', '1', '1', 'page.php?i=view-product&id={object_id}', 'bx_market_products', '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_market', 'bx_market', '1', '1', 'page.php?i=view-product&id={object_id}', 'bx_market_products', '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_market', '_bx_market', 'bx_market', 'added', 'edited', 'deleted', '', ''),
+('bx_market_cmts', '_bx_market_cmts', 'bx_market', 'commentPost', 'commentUpdated', 'commentRemoved', 'BxDolContentInfoCmts', '');
+
+INSERT INTO `sys_content_info_grids` (`object`, `grid_object`, `grid_field_id`, `condition`, `selection`) VALUES
+('bx_market', 'bx_market_administration', 'id', '', ''),
+('bx_market', 'bx_market_common', 'id', '', '');
+
+-- SEARCH EXTENDED
+INSERT INTO `sys_objects_search_extended` (`object`, `object_content_info`, `module`, `title`, `active`, `class_name`, `class_file`) VALUES
+('bx_market', 'bx_market', 'bx_market', '_bx_market_search_extended', 1, '', ''),
+('bx_market_cmts', 'bx_market_cmts', 'bx_market', '_bx_market_search_extended_cmts', 1, 'BxTemplSearchExtendedCmts', '');
+
+-- STUDIO: page & widget
+INSERT INTO `sys_std_pages`(`index`, `name`, `header`, `caption`, `icon`) VALUES
+(3, 'bx_market', '_bx_market', '_bx_market', 'bx_market@modules/boonex/market/|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_market', 'content', '{url_studio}module.php?name=bx_market', '', 'bx_market@modules/boonex/market/|std-icon.svg', '_bx_market', '', '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));

+ 90 - 0
modules/boonex/market/updates/13.0.2_13.0.3/source/js/form.js

@@ -0,0 +1,90 @@
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Market Market
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+function BxMarketForm(oOptions) {
+    this._sActionsUri = oOptions.sActionUri;
+    this._sActionsUrl = oOptions.sActionUrl;
+    this._sObjName = oOptions.sObjName == undefined ? 'oBxMarketForm' : 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;
+    jQuery(document).ready(function() {
+        $this.init();
+    });
+}
+
+BxMarketForm.prototype.init = function() {
+    jQuery("textarea[name='cover_raw']").each(function() {
+        CodeMirror.fromTextArea(this, {
+            lineNumbers: true,
+            mode: "htmlmixed",
+            htmlMode: true,
+            matchBrackets: true
+        });
+    });
+};
+
+BxMarketForm.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);
+	}
+
+	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'
+	);
+};
+
+BxMarketForm.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');
+
+        jQuery(oSelect).parents('.bx-form-input-files-result:first').bx_show_more_check_overflow();
+    });
+};
+
+/** @} */

+ 27 - 0
modules/boonex/market/updates/13.0.2_13.0.3/source/template/entry-text.html

@@ -0,0 +1,27 @@
+<div class="bx-content-description-before">__content_description_before__</div>
+<div class="bx-content-description">
+    <bx_if:show_image_raw>
+        <div class="bx-base-text-entity-image bx-def-margin-bottom bx-def-font-align-center">__image_raw__</div>
+    </bx_if:show_image_raw>
+    <bx_if:show_image>
+        <div class="bx-base-text-entity-image bx-def-margin-bottom bx-def-font-align-center">
+            <img class="bx-def-border-radius-block" src="__entry_image__" />
+        </div>
+    </bx_if:show_image>
+    <div class="bx-base-text-entity-content bx-market-entity-content bx-def-constraint-list bx-def-constraint-pre bx-def-constraint-object bx-def-constraint-iframe bx-def-constraint-img bx-def-vanilla-html prose dark:prose-invert">
+        <div class="bx-market-ec-title flex">
+            <bx_if:show_icon>
+                <div class="bx-market-ect-icon flex-none mr-4 not-prose"><img class="bx-def-thumb-size bx-def-round-corners" src="__entry_icon__"/></div>
+            </bx_if:show_icon>
+            <div class="bx-market-ect-title bx-base-text-title-bages flex-1">
+                <h1>__entry_title__</h1>
+                <div class="bx-base-bages-container absolute flex -translate-y-5/4">__badges__</div>
+            </div>
+        </div>
+        <div class="bx-market-ec-description">__entry_text__</div>
+    </div>
+    <bx_if:show_screenshots>
+        <div class="bx-market-ec-slideshow bx-def-margin-top">__screenshots__</div>
+    </bx_if:show_screenshots>
+</div>
+<div class="bx-content-description-after">__content_description_after__</div>

+ 87 - 0
modules/boonex/market/updates/13.0.2_13.0.3/source/template/unit_gallery.html

@@ -0,0 +1,87 @@
+<div class="__class__  bx-base-text-unit bx-base-text-unit-gallery bx-def-gal-unit-size bx-def-padding-sec">
+	<div class="bx-market-unit-gallery-cnt bx-def-round-corners bx-def-box bx-def-color-bg-box bx-def-shadow">
+        <!-- Author section -->
+        <bx_if:show_section_author>
+	        <div class="bx-market-unit-cnt bx-def-padding">
+	            <div class="bx-market-unit-author">
+			        <div class="bx-market-unit-author-avatar bx-def-thumb bx-def-thumb-size">__author_unit__</div>
+			        <div class="bx-market-unit-author-info bx-def-thumb-size-min-height bx-def-thumb-size-left-indent">
+			            <div class="bx-market-unit-author-name bx-def-font-middle bx-def-font-light bx-def-font-grayed">__author_width_date__</div>
+			        </div>
+			        <div class="bx-market-unit-actions">__actions__</div>
+	            </div>
+	        </div>
+        </bx_if:show_section_author>
+
+        <!-- Main section -->
+        <div class="bx-market-unit-cnt bx-market-unit-cover">
+            <bx_if:show_cover_raw>
+                <a href="__content_url__" title="__summary_attr__">
+                    <div class="bx-base-text-unit-thumb bx-base-text-unit-thumb-raw">__cover_raw__</div>
+                </a>
+            </bx_if:show_cover_raw>
+            <bx_if:show_cover>
+                <a href="__content_url__" title="__summary_attr__">
+                    <div class="bx-base-text-unit-thumb bx-def-gal-div-size bx-def-font-middle" style="background-image:url(__cover_url__)">
+                        <div class="bx-base-text-unit-strecher">__strecher__</div>
+                    </div>
+                </a>
+            </bx_if:show_cover>
+            <bx_if:show_cover_empty>
+                <div class="bx-base-text-unit-no-thumb bx-def-gal-div-size bx-def-font-middle bx-def-font-grayed bx-def-padding bx-def-border bx-def-box-sizing">
+                    __summary_plain__
+                    <div class="bx-base-text-unit-strecher">__strecher__</div>
+                </div>
+            </bx_if:show_cover_empty>
+        </div>
+		<div class="bx-market-unit-cnt bx-def-padding">
+            <div class="bx-market-unit-info">
+                <div class="bx-market-unit-icon bx-def-thumb-size bx-def-round-corners">
+                    <a href="__content_url__"> 
+		                <bx_if:show_icon>
+		                    <img class="bx-market-unit-icon bx-def-thumb-size bx-def-round-corners" src="__icon_url__" />
+		                </bx_if:show_icon>
+		                <bx_if:show_icon_empty>
+		                    <div class="bx-market-unit-icon-empty bx-def-thumb-size bx-def-round-corners">
+                                <i class="sys-icon __icon__"></i>
+                            </div>
+		                </bx_if:show_icon_empty>
+		            </a>
+                </div>
+			    <div class="bx-market-unit-title bx-def-thumb-size-min-height bx-def-thumb-size-left-indent">
+                    <div class="bx-market-unit-title-badges">
+                        <a class=" bx-def-font-h3" href="__content_url__" title="__title_attr__">
+                        __title__</a> 
+                        __badges__
+                    </div>
+                        <bx_if:meta><div class="bx-base-general-unit-meta">__meta__</div></bx_if:meta>
+                    </div>
+		    </div>
+		</div>
+
+        <!-- Pricing section -->
+        <bx_if:show_section_pricing>
+			<div class="bx-market-unit-cnt bx-def-padding-leftright bx-def-padding-bottom">
+	            <div class="bx-def-font-align-center">
+	                <bx_if:show_single>
+	                    <a class="bx-market-ui-price bx-btn bx-btn-small bx-def-margin-sec-top-auto" href="javascript:void(0)" onclick="javascript:__price_single_onclick__">__price_single__</a>
+	                </bx_if:show_single>
+	                <bx_if:show_recurring>
+	                    <a class="bx-market-ui-price bx-btn bx-btn-small bx-def-margin-sec-top-auto" href="javascript:void(0)" onclick="javascript:__price_recurring_onclick__">__price_recurring__</a>
+	                </bx_if:show_recurring>
+	                <bx_if:show_free>
+	                    <a class="bx-market-ui-price bx-btn bx-btn-small bx-def-margin-sec-top-auto" href="__price_free_href__"><bx_text:_bx_market_txt_get_for_free /></a>
+	                </bx_if:show_free>
+	            </div>
+			</div>
+        </bx_if:show_section_pricing>
+
+        <!-- Voting section -->
+        <bx_if:show_section_voting>
+            <div class="bx-market-unit-cnt bx-def-padding-leftright bx-def-padding-bottom bx-clearfix">
+                <div class="bx-market-fcell fc-left">__voting__</div>
+                <div class="bx-market-fcell fc-right bx-def-font-bold">__pricing__</div>
+            </div>
+        </bx_if:show_section_voting>
+	</div>
+</div>

+ 51 - 0
modules/boonex/massmailer/updates/13.0.0_13.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' => '13.0.0',
+    'version_to' => '13.0.1',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '13.0.0-B2'
+    ),
+
+    /**
+     * '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_13.0.0_13.0.1/',
+    'home_uri' => 'massmailer_update_1300_1301',
+
+    '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/13.0.0_13.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);
+    }
+}

+ 261 - 0
modules/boonex/massmailer/updates/13.0.0_13.0.1/source/classes/BxMassMailerDb.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    MassMailer Mass Mailer
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxMassMailerDb extends BxBaseModGeneralDb
+{
+    function __construct(&$oConfig)
+    {
+        parent::__construct($oConfig);
+    }
+    
+    public function copyCampaign($iCampaignId)
+    {
+        $CNF = &$this->_oConfig->CNF;
+        $aBindings = array(
+            'campaign_id' => $iCampaignId,
+            'date_created' => time(),
+            'copy_title' => _t('_bx_massmailer_txt_copy_title')
+        );
+        $this->query("INSERT INTO `" . $CNF['TABLE_CAMPAIGNS'] . "` (`" . $CNF['FIELD_AUTHOR'] . "`, `" . $CNF['FIELD_TITLE'] . "`, `" . $CNF['FIELD_BODY'] . "`, `" . $CNF['FIELD_SEGMENTS'] . "`, `" . $CNF['FIELD_ADDED'] . "`, `" . $CNF['FIELD_SUBJECT'] . "`, `" . $CNF['FIELD_FROM_NAME'] . "`, `" . $CNF['FIELD_REPLY_TO'] . "`, `" . $CNF['FIELD_PER_ACCOUNT'] . "`) SELECT `" . $CNF['FIELD_AUTHOR'] . "`, CONCAT(`" . $CNF['FIELD_TITLE'] . "`, :copy_title), `" . $CNF['FIELD_BODY'] . "`, `" . $CNF['FIELD_SEGMENTS'] . "`, :date_created, `" . $CNF['FIELD_SUBJECT'] . "`, `" . $CNF['FIELD_FROM_NAME'] . "`, `" . $CNF['FIELD_REPLY_TO'] . "`, `" . $CNF['FIELD_PER_ACCOUNT'] . "` FROM `" . $CNF['TABLE_CAMPAIGNS'] . "` WHERE `" . $CNF['FIELD_ID'] . "` = :campaign_id", $aBindings);
+        return $this->lastId();
+    }
+        
+    public function sendCampaign($iCampaignId)
+    {
+        $CNF = &$this->_oConfig->CNF;
+        $aBindings = array(
+            'campaign_id' => $iCampaignId,
+            'date_sent' => time()
+        );
+        $this->query("UPDATE `" . $CNF['TABLE_CAMPAIGNS'] . "` SET `" . $CNF['FIELD_DATE_SENT'] . "` = :date_sent WHERE `" . $CNF['FIELD_ID'] . "` = :campaign_id", $aBindings);
+    }
+    
+    public function addEmailToSentListForCampaign($iCampaignId, $sEmailList)
+    {
+        $CNF = &$this->_oConfig->CNF;
+        $aBindings = array(
+            'campaign_id' => $iCampaignId,
+            'email_list' => $sEmailList
+        );
+        $this->query("UPDATE `" . $CNF['TABLE_CAMPAIGNS'] . "` SET `" . $CNF['FIELD_EMAIL_LIST'] . "` = CONCAT(IFNULL(`" . $CNF['FIELD_EMAIL_LIST'] . "`, ''), ',', :email_list) WHERE `" . $CNF['FIELD_ID'] . "` = :campaign_id", $aBindings);
+    }
+    
+    public function getCampaignInfoById ($iCampaignId)
+    {
+        $CNF = &$this->_oConfig->CNF;
+        $sQuery = $this->prepare ("SELECT * FROM `" . $CNF['TABLE_CAMPAIGNS'] . "` WHERE `" . $CNF['FIELD_ID'] . "` = ?", $iCampaignId);
+        return $this->getRow($sQuery);
+    }
+    
+    public function getSegmentInfoById ($iSegmentId)
+    {
+        $CNF = &$this->_oConfig->CNF;
+        $sQuery = $this->prepare ("SELECT * FROM `" . $CNF['TABLE_SEGMENTS'] . "` WHERE `" . $CNF['FIELD_ID'] . "` = ?", $iSegmentId);
+        return $this->getRow($sQuery);
+    }
+    
+    public function getSegments()
+    {
+        $CNF = &$this->_oConfig->CNF;
+        $sQuery = $this->prepare ("SELECT `" . $CNF['FIELD_ID'] . "`, `" . $CNF['FIELD_TITLE'] . "` FROM `" . $CNF['TABLE_SEGMENTS'] . "`");
+        return $this->getPairs($sQuery, $CNF['FIELD_ID'], $CNF['FIELD_TITLE']);
+    }
+    
+    public function getAccountsByTerms($sTerms = "")
+    {
+        $sSql = "SELECT `ta`.`email`, `tp`.`id` AS `profile_id`, `ta`.`id` as `account_id` FROM `sys_accounts` AS `ta` " . $sTerms . "  WHERE `ta`.`receive_news` <> 0 AND `ta`.`email_confirmed` = 1";
+        return $this->getAll($sSql);
+    }
+    
+    public function getAccountsByTermsStat($iDateFrom, $iDateTo, $sTerms = "")
+    {
+        $aBindings = array(
+           'datefrom' => $iDateFrom,
+           'dateto' => $iDateTo
+       );
+        $sSql = "SELECT DATE(FROM_UNIXTIME(`ta`.`added`)) AS `period`, YEAR(FROM_UNIXTIME(`ta`.`added`)) AS `year`, COUNT(*) AS `count` FROM `sys_accounts` AS `ta` " . $sTerms . " WHERE `ta`.`receive_news` <> 0  AND `ta`.`email_confirmed` = 1 AND `ta`.`added` >= :datefrom AND `ta`.`added` <= :dateto GROUP BY `period`, `year` ORDER BY `year`, `period` ASC";
+        return $this->getAll($sSql, $aBindings);
+    }
+    
+    public function getAccountsByTermsStatUnsubscribe($iDateFrom, $iDateTo, $sTerms = "")
+    {
+        $CNF = &$this->_oConfig->CNF;
+        $aBindings = array(
+           'datefrom' => $iDateFrom,
+           'dateto' => $iDateTo
+       );
+        $sSql = "SELECT DATE(FROM_UNIXTIME(`tu`.`unsubscribed`)) AS `period`, YEAR(FROM_UNIXTIME(`tu`.`unsubscribed`)) AS `year`, COUNT(*) AS `count` FROM `sys_accounts` AS `ta` INNER JOIN `" . $CNF['TABLE_UNSUBSCRIBE'] . "` AS `tu` ON `tu`.`account_id`=`ta`.`id` " . $sTerms . " WHERE `tu`.`unsubscribed` >= :datefrom AND `tu`.`unsubscribed` <= :dateto GROUP BY `period`, `year` ORDER BY `year`, `period` ASC";
+        return $this->getAll($sSql, $aBindings);
+    }
+    
+    public function getAccountsByTermsStatInitValue($iDateFrom, $sTerms)
+    {
+        $aBindings = array(
+            'datefrom' => $iDateFrom
+        );
+        $sQuery = "SELECT COUNT(`ta`.`id`) AS `count` FROM `sys_accounts` AS `ta` " . $sTerms . " WHERE `ta`.`added` < :datefrom ";
+        return $this->getOne($sQuery, $aBindings);
+    }
+    
+    public function getAccountsByTermsStatInitValueUnsubscribe($iDateFrom, $sTerms)
+    {
+        $CNF = &$this->_oConfig->CNF;
+        $aBindings = array(
+            'datefrom' => $iDateFrom
+        );
+        $sQuery = "SELECT COUNT(`tu`.`id`) AS `count` FROM `sys_accounts` AS `ta` INNER JOIN `" . $CNF['TABLE_UNSUBSCRIBE'] . "` AS `tu` ON `tu`.`account_id`=`ta`.`id` " . $sTerms . " WHERE `tu`.`unsubscribed` < :datefrom ";
+        return $this->getOne($sQuery, $aBindings);
+    }
+    
+    public function addLetter($iCampaignId, $sEmail)
+    {
+        $iTime = time();
+        $sCode = md5($iCampaignId . $sEmail . $iTime);
+        $CNF = &$this->_oConfig->CNF;
+        $aBindings = array(
+            'campaign_id' => $iCampaignId,
+            'email' => $sEmail,
+            'date_sent' => $iTime,
+            'code' => $sCode,
+        );
+        $this->query("INSERT INTO `" . $CNF['TABLE_LETTERS'] . "` (`" . $CNF['FIELD_CAMPAIGN_ID'] . "`, `" . $CNF['FIELD_EMAIL'] . "`, `" . $CNF['FIELD_DATE_SENT'] . "`, `" . $CNF['FIELD_HASH'] . "`) VALUES (:campaign_id, :email, :date_sent, :code)", $aBindings);
+        return $sCode;
+    }
+    
+    public function updateDateSeenForLetter($sCode)
+    {
+        $CNF = &$this->_oConfig->CNF;
+        $aBindings = array(
+            'code' => $sCode,
+            'date_seen' => time()
+        );
+        $this->query("UPDATE `" . $CNF['TABLE_LETTERS'] . "` SET `" . $CNF['FIELD_DATE_SEEN'] . "` = :date_seen WHERE `" . $CNF['FIELD_HASH'] . "` = :code", $aBindings);
+    }
+    
+    public function deleteCampaignData($iCampaignId)
+    {
+        $CNF = &$this->_oConfig->CNF;
+        $aBindings = array(
+            'campaign_id' => $iCampaignId
+        );
+        $this->query("DELETE FROM `" . $CNF['TABLE_LETTERS'] . "` WHERE `" . $CNF['FIELD_CAMPAIGN_ID'] . "` = :campaign_id", $aBindings);
+        $this->query("DELETE FROM `" . $CNF['TABLE_LINKS'] . "` WHERE `" . $CNF['FIELD_CAMPAIGN_ID'] . "` = :campaign_id", $aBindings);
+        $this->query("DELETE FROM `" . $CNF['TABLE_UNSUBSCRIBE'] . "` WHERE `" . $CNF['FIELD_CAMPAIGN_ID'] . "` = :campaign_id", $aBindings);
+    }
+    
+    public function getLettersByCampaignId ($iCampaignId)
+    {
+        $CNF = &$this->_oConfig->CNF;
+        $sQuery = $this->prepare ("SELECT * FROM `" . $CNF['TABLE_LETTERS'] . "` WHERE `" . $CNF['FIELD_CAMPAIGN_ID'] . "` = ?", $iCampaignId);
+        return $this->getAll($sQuery);
+    }
+    
+    public function getClicksByCampaignId ($iCampaignId)
+    {
+        $CNF = &$this->_oConfig->CNF;
+        $sQuery = $this->prepare ("SELECT `" . $CNF['FIELD_LINK'] . "`, `" . $CNF['FIELD_TITLE'] . "`, COUNT( `" . $CNF['FIELD_ID'] . "`) AS `click_count`, MAX( `" . $CNF['FIELD_DATE_CLICK'] . "`) AS `last_click` FROM `" . $CNF['TABLE_LINKS'] . "` WHERE `" . $CNF['FIELD_CAMPAIGN_ID'] . "` = ? AND `" . $CNF['FIELD_DATE_CLICK'] . "` > 0 GROUP BY `" . $CNF['FIELD_LINK'] . "`, `" . $CNF['FIELD_TITLE'] . "` ORDER BY COUNT( `" . $CNF['FIELD_ID'] . "`)  DESC", $iCampaignId);
+        return $this->getAll($sQuery);
+    }
+    
+    public function getStatByCampaignId ($iCampaignId)
+    {
+        $CNF = &$this->_oConfig->CNF;
+         $aBindings = array(
+            'campaign_id' => $iCampaignId
+        );
+        $q = "
+        SELECT COUNT(*) AS `count`, 'total' AS `title` FROM `" . $CNF['TABLE_LETTERS'] . "` WHERE `" . $CNF['FIELD_CAMPAIGN_ID'] . "` = :campaign_id UNION
+        SELECT COUNT(*), 'seen' FROM `" . $CNF['TABLE_LETTERS'] . "` WHERE `" . $CNF['FIELD_CAMPAIGN_ID'] . "` = :campaign_id AND `" . $CNF['FIELD_DATE_SEEN'] . "` > 0 UNION
+        SELECT COUNT(*), 'clicked' FROM `" . $CNF['TABLE_LETTERS'] . "` WHERE `" . $CNF['FIELD_CAMPAIGN_ID'] . "` = :campaign_id AND `" . $CNF['FIELD_DATE_CLICK'] . "` > 0 UNION 
+        SELECT COUNT(*), 'unsubscribed' FROM `" . $CNF['TABLE_UNSUBSCRIBE'] . "` WHERE `" . $CNF['FIELD_CAMPAIGN_ID'] . "` = :campaign_id 
+        ";
+        return $this->getPairs($q, 'title', 'count', $aBindings);
+    }
+    
+    public function getLetterByCode ($sCode)
+    {
+        $CNF = &$this->_oConfig->CNF;
+        $sQuery = $this->prepare ("SELECT * FROM `" . $CNF['TABLE_LETTERS'] . "` WHERE `" . $CNF['FIELD_HASH'] . "` = ?", $sCode);
+        return $this->getRow($sQuery);
+    }
+    
+    public function addLink($sLetterHash, $sLink, $sTitle, $iCampaignId)
+    {
+        $CNF = &$this->_oConfig->CNF;
+        $sCode = md5($sLetterHash . $sLink . $sTitle);
+        $aBindings = array(
+            'letter_hash' => $sLetterHash,
+            'hash' => $sCode,
+            'link' => $sLink,
+            'title' => $sTitle,
+            'campaign_id' => $iCampaignId,
+        );
+        $this->query("INSERT INTO `" . $CNF['TABLE_LINKS'] . "` (`" . $CNF['FIELD_LETTER_HASH'] . "`, `" . $CNF['FIELD_HASH'] . "`, `" . $CNF['FIELD_LINK'] . "`, `" . $CNF['FIELD_TITLE'] . "`, `" . $CNF['FIELD_CAMPAIGN_ID'] . "`) VALUES (:letter_hash, :hash, :link, :title, :campaign_id)", $aBindings);
+        return $sCode;
+    }
+    
+    public function updateDateClickForLink($sCode)
+    {
+        $CNF = &$this->_oConfig->CNF;
+        $aBindings = array(
+            'code' => $sCode,
+            'date_click' => time()
+        );
+        $this->query("UPDATE `" . $CNF['TABLE_LINKS'] . "` SET `" . $CNF['FIELD_DATE_CLICK'] . "` = :date_click WHERE `" . $CNF['FIELD_HASH'] . "` = :code", $aBindings);
+        $aData = $this->getRow("SELECT * FROM `" . $CNF['TABLE_LINKS'] . "` WHERE `" . $CNF['FIELD_HASH'] . "` = :code", array('code' => $sCode));
+        if (isset($aData[$CNF['FIELD_LETTER_HASH']]) && isset($aData[$CNF['FIELD_LINK']])){
+            $aBindings['code'] = $aData[$CNF['FIELD_LETTER_HASH']];
+            if ($aData[$CNF['FIELD_LETTER_HASH']] != '')
+                $this->query("UPDATE `" . $CNF['TABLE_LETTERS'] . "` SET `" . $CNF['FIELD_DATE_CLICK'] . "` = :date_click WHERE `" . $CNF['FIELD_HASH'] . "` = :code", $aBindings);
+
+            return $aData[$CNF['FIELD_LINK']];
+        }
+        return '';
+    }
+    
+    
+    public function updateUnsubscribe($iAccountId, $iValue, $iCampaignId)
+    {
+        $CNF = &$this->_oConfig->CNF;
+        if ($iValue != 1){
+            $aBindings = array(
+                'account_id' => $iAccountId,
+                'campaign_id' => $iCampaignId,
+                'date_unsubscribed' => time()
+            );
+            $this->query("INSERT INTO `" . $CNF['TABLE_UNSUBSCRIBE'] . "` (`" . $CNF['FIELD_DATE_UNSUBSCRIBED'] . "`, `" . $CNF['FIELD_ACCOUNT_ID'] . "`, `" . $CNF['FIELD_CAMPAIGN_ID'] . "`) VALUES (:date_unsubscribed, :account_id, :campaign_id)", $aBindings);
+        }
+        else{
+            $aBindings = array(
+                'account_id' => $iAccountId
+            );
+            $this->query("DELETE FROM `" . $CNF['TABLE_UNSUBSCRIBE'] . "` WHERE `" . $CNF['FIELD_ACCOUNT_ID'] . "` = :account_id", $aBindings);
+        }
+    }
+    
+    public function deleteOldCampagns($iDayBefore)
+    {
+        $CNF = &$this->_oConfig->CNF;
+        $aBindings = array(
+            'time_from' => (time() - $iDayBefore * 86400)
+        );
+        $aTmp = $this->getColumn("SELECT `" . $CNF['FIELD_ID'] . "` FROM `" . $CNF['TABLE_CAMPAIGNS'] . "` WHERE `" . $CNF['FIELD_DATE_SENT'] . "` < :time_from AND `" . $CNF['FIELD_DATE_SENT'] . "` > 0", $aBindings);
+        if (count($aTmp) > 0){
+            $sIdList = $this->implode_escape($aTmp);
+            $this->query("DELETE FROM `" . $CNF['TABLE_LETTERS'] . "` WHERE `" . $CNF['FIELD_CAMPAIGN_ID'] . "` IN (" . $sIdList . ")", $aBindings);
+            $this->query("DELETE FROM `" . $CNF['TABLE_LINKS'] . "` WHERE `" . $CNF['FIELD_CAMPAIGN_ID'] . "` IN (" . $sIdList . ")", $aBindings);
+            $this->query("DELETE FROM `" . $CNF['TABLE_UNSUBSCRIBE'] . "` WHERE `" . $CNF['FIELD_CAMPAIGN_ID'] . "` IN (" . $sIdList . ")", $aBindings);
+            $this->query("DELETE FROM `" . $CNF['TABLE_CAMPAIGNS'] . "` WHERE `" . $CNF['FIELD_ID'] . "` IN (" . $sIdList . ")", $aBindings);
+        }
+    }
+}
+
+/** @} */

+ 680 - 0
modules/boonex/massmailer/updates/13.0.0_13.0.1/source/classes/BxMassMailerModule.php

@@ -0,0 +1,680 @@
+<?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, getLoggedId(), $aTemplate, false);
+    }
+          
+    public function sendAll($iCampaignId)
+    {
+        $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){
+            $this->sendLetter($aAccountInfo['email'], $iCampaignId, $aCustomHeaders, $aAccountInfo['account_id'], $aTemplate, true);
+            $this->_oDb->addEmailToSentListForCampaign($iCampaignId, $aAccountInfo['email']);
+            unset($GLOBALS['bxDolClasses']['BxDolAccount_' . $aAccountInfo['account_id']]);
+            if (1 == rand(1,100)) {
+                BxDolDb::getInstance()->cleanMemoryAll();
+                unset($GLOBALS['bxDolClasses']);
+            }
+        }
+              
+        $this->_oDb->sendCampaign($iCampaignId);
+        return true;
+    }
+    
+    private function sendLetter($sEmail, $iCampaignId, $aCustomHeaders, $iAccountId, $aTemplate, $bAddToQueue)
+    {
+        $sLetterCode = $this->_oDb->addLetter($iCampaignId, $sEmail);
+        
+        $aMarkers = $this->addMarkers($iAccountId, $sLetterCode);
+        bx_alert($this->_aModule['name'], 'user_fields', $iCampaignId, $iAccountId, 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']);
+        
+        $aMarkersInLetter = [];
+        preg_match_all("/\{[^\}]*\}/i", $aTemplate['Body'], $aMarkersInLetter);
+        if ($aMarkersInLetter[0]>0){
+            foreach ($aMarkersInLetter[0] as $sMarker){
+                $sMarker = str_replace(['{', '}'], '', $sMarker);
+                if (!array_key_exists($sMarker, $aMarkers)) {
+                    $aMarkers[$sMarker] = '';
+                }
+            }
+        }
+        
+        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($iAccountId, $sLetterCode)
+    {
+        $CNF = &$this->_oConfig->CNF;
+        $aMarkers = array();
+        
+        $oAccount = BxDolAccount::getInstance($iAccountId);
+        $aAccountInfo = $oAccount->getInfo();
+        $sAccountEmail = $oAccount->getEmail();
+        
+        $aMarkers['email'] = $sAccountEmail;
+        $aMarkers['account_name'] = $oAccount->getDisplayName();
+        $aMarkers['account_id'] = $oAccount->id();
+        
+        if ($aAccountInfo['profile_id'] > 0){
+            $oProfile = BxDolProfile::getInstance($aAccountInfo['profile_id']);
+            $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/13.0.0_13.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' => '13.0.1',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '13.0.0-B2'
+    ),
+
+    /**
+     * '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(),
+);
+
+/** @} */

+ 51 - 0
modules/boonex/organizations/updates/13.0.1_13.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' => 'Organizations',
+    'version_from' => '13.0.1',
+    'version_to' => '13.0.2',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '13.0.0-B2'
+    ),
+
+    /**
+     * '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_13.0.1_13.0.2/',
+    'home_uri' => 'orgs_update_1301_1302',
+
+    '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(),
+);

+ 13 - 0
modules/boonex/organizations/updates/13.0.1_13.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 BxOrgsUpdater extends BxDolStudioUpdater
+{
+    function __construct($aConfig)
+    {
+        parent::__construct($aConfig);
+    }
+}

Some files were not shown because too many files changed in this diff