AntonLV 5 лет назад
Родитель
Сommit
2820d25220
100 измененных файлов с 16243 добавлено и 0 удалено
  1. 51 0
      modules/boonex/accounts/updates/12.0.0_12.0.1/install/config.php
  2. 13 0
      modules/boonex/accounts/updates/12.0.0_12.0.1/install/installer.php
  3. 4 0
      modules/boonex/accounts/updates/12.0.0_12.0.1/install/langs/en.xml
  4. 97 0
      modules/boonex/accounts/updates/12.0.0_12.0.1/source/classes/BxAccntConfig.php
  5. 587 0
      modules/boonex/accounts/updates/12.0.0_12.0.1/source/classes/BxAccntGridAdministration.php
  6. 71 0
      modules/boonex/accounts/updates/12.0.0_12.0.1/source/install/config.php
  7. 93 0
      modules/boonex/accounts/updates/12.0.0_12.0.1/source/install/langs/en.xml
  8. 51 0
      modules/boonex/acl/updates/12.0.0_12.0.1/install/config.php
  9. 13 0
      modules/boonex/acl/updates/12.0.0_12.0.1/install/installer.php
  10. 4 0
      modules/boonex/acl/updates/12.0.0_12.0.1/install/langs/en.xml
  11. 9 0
      modules/boonex/acl/updates/12.0.0_12.0.1/install/sql/enable.sql
  12. 144 0
      modules/boonex/acl/updates/12.0.0_12.0.1/source/classes/BxAclConfig.php
  13. 135 0
      modules/boonex/acl/updates/12.0.0_12.0.1/source/classes/BxAclGridView.php
  14. 70 0
      modules/boonex/acl/updates/12.0.0_12.0.1/source/install/config.php
  15. 101 0
      modules/boonex/acl/updates/12.0.0_12.0.1/source/install/langs/en.xml
  16. 40 0
      modules/boonex/acl/updates/12.0.0_12.0.1/source/install/sql/enable.sql
  17. 51 0
      modules/boonex/albums/updates/12.00_12.0.1/install/config.php
  18. 13 0
      modules/boonex/albums/updates/12.00_12.0.1/install/installer.php
  19. 4 0
      modules/boonex/albums/updates/12.00_12.0.1/install/langs/en.xml
  20. 143 0
      modules/boonex/albums/updates/12.00_12.0.1/source/install/config.php
  21. 295 0
      modules/boonex/albums/updates/12.00_12.0.1/source/install/langs/en.xml
  22. 51 0
      modules/boonex/api/updates/12.0.0_12.0.1/install/config.php
  23. 13 0
      modules/boonex/api/updates/12.0.0_12.0.1/install/installer.php
  24. 11 0
      modules/boonex/api/updates/12.0.0_12.0.1/install/langs/en.xml
  25. 5 0
      modules/boonex/api/updates/12.0.0_12.0.1/install/sql/enable.sql
  26. 602 0
      modules/boonex/api/updates/12.0.0_12.0.1/source/classes/BxApiModule.php
  27. 70 0
      modules/boonex/api/updates/12.0.0_12.0.1/source/install/config.php
  28. 15 0
      modules/boonex/api/updates/12.0.0_12.0.1/source/install/langs/en.xml
  29. 3 0
      modules/boonex/api/updates/12.0.0_12.0.1/source/install/sql/disable.sql
  30. 4 0
      modules/boonex/api/updates/12.0.0_12.0.1/source/install/sql/enable.sql
  31. 8 0
      modules/boonex/api/updates/12.0.0_12.0.1/source/template/images/icons/std-icon.svg
  32. 51 0
      modules/boonex/events/updates/12.0.0_12.0.1/install/config.php
  33. 13 0
      modules/boonex/events/updates/12.0.0_12.0.1/install/installer.php
  34. 4 0
      modules/boonex/events/updates/12.0.0_12.0.1/install/langs/en.xml
  35. 152 0
      modules/boonex/events/updates/12.0.0_12.0.1/source/install/config.php
  36. 495 0
      modules/boonex/events/updates/12.0.0_12.0.1/source/install/langs/en.xml
  37. 51 0
      modules/boonex/files/updates/12.0.0_12.0.1/install/config.php
  38. 13 0
      modules/boonex/files/updates/12.0.0_12.0.1/install/installer.php
  39. 4 0
      modules/boonex/files/updates/12.0.0_12.0.1/install/langs/en.xml
  40. 135 0
      modules/boonex/files/updates/12.0.0_12.0.1/source/install/config.php
  41. 293 0
      modules/boonex/files/updates/12.0.0_12.0.1/source/install/langs/en.xml
  42. 51 0
      modules/boonex/forum/updates/12.0.0_12.0.1/install/config.php
  43. 13 0
      modules/boonex/forum/updates/12.0.0_12.0.1/install/installer.php
  44. 4 0
      modules/boonex/forum/updates/12.0.0_12.0.1/install/langs/en.xml
  45. 4 0
      modules/boonex/forum/updates/12.0.0_12.0.1/install/sql/install.sql
  46. 136 0
      modules/boonex/forum/updates/12.0.0_12.0.1/source/install/config.php
  47. 369 0
      modules/boonex/forum/updates/12.0.0_12.0.1/source/install/langs/en.xml
  48. 561 0
      modules/boonex/forum/updates/12.0.0_12.0.1/source/install/sql/install.sql
  49. 51 0
      modules/boonex/glossary/updates/12.0.0_12.0.1/install/config.php
  50. 13 0
      modules/boonex/glossary/updates/12.0.0_12.0.1/install/installer.php
  51. 4 0
      modules/boonex/glossary/updates/12.0.0_12.0.1/install/langs/en.xml
  52. 136 0
      modules/boonex/glossary/updates/12.0.0_12.0.1/source/install/config.php
  53. 244 0
      modules/boonex/glossary/updates/12.0.0_12.0.1/source/install/langs/en.xml
  54. 51 0
      modules/boonex/groups/updates/12.0.0_12.0.1/install/config.php
  55. 13 0
      modules/boonex/groups/updates/12.0.0_12.0.1/install/installer.php
  56. 4 0
      modules/boonex/groups/updates/12.0.0_12.0.1/install/langs/en.xml
  57. 152 0
      modules/boonex/groups/updates/12.0.0_12.0.1/source/install/config.php
  58. 441 0
      modules/boonex/groups/updates/12.0.0_12.0.1/source/install/langs/en.xml
  59. 51 0
      modules/boonex/market/updates/12.0.0_12.0.1/install/config.php
  60. 13 0
      modules/boonex/market/updates/12.0.0_12.0.1/install/installer.php
  61. 708 0
      modules/boonex/market/updates/12.0.0_12.0.1/source/classes/BxMarketDb.php
  62. 1346 0
      modules/boonex/market/updates/12.0.0_12.0.1/source/classes/BxMarketModule.php
  63. 140 0
      modules/boonex/market/updates/12.0.0_12.0.1/source/install/config.php
  64. 51 0
      modules/boonex/notifications/updates/12.0.0_12.0.1/install/config.php
  65. 13 0
      modules/boonex/notifications/updates/12.0.0_12.0.1/install/installer.php
  66. 236 0
      modules/boonex/notifications/updates/12.0.0_12.0.1/source/classes/BxNtfsConfig.php
  67. 186 0
      modules/boonex/notifications/updates/12.0.0_12.0.1/source/classes/BxNtfsCronNotify.php
  68. 48 0
      modules/boonex/notifications/updates/12.0.0_12.0.1/source/classes/BxNtfsCronQueue.php
  69. 341 0
      modules/boonex/notifications/updates/12.0.0_12.0.1/source/classes/BxNtfsDb.php
  70. 250 0
      modules/boonex/notifications/updates/12.0.0_12.0.1/source/classes/BxNtfsGridSettingsAdministration.php
  71. 543 0
      modules/boonex/notifications/updates/12.0.0_12.0.1/source/classes/BxNtfsModule.php
  72. 82 0
      modules/boonex/notifications/updates/12.0.0_12.0.1/source/install/config.php
  73. 51 0
      modules/boonex/organizations/updates/12.0.0_12.0.1/install/config.php
  74. 13 0
      modules/boonex/organizations/updates/12.0.0_12.0.1/install/installer.php
  75. 4 0
      modules/boonex/organizations/updates/12.0.0_12.0.1/install/langs/en.xml
  76. 152 0
      modules/boonex/organizations/updates/12.0.0_12.0.1/source/install/config.php
  77. 488 0
      modules/boonex/organizations/updates/12.0.0_12.0.1/source/install/langs/en.xml
  78. 51 0
      modules/boonex/payment/updates/12.0.0_12.0.1/install/config.php
  79. 13 0
      modules/boonex/payment/updates/12.0.0_12.0.1/install/installer.php
  80. 85 0
      modules/boonex/payment/updates/12.0.0_12.0.1/install/langs/en.xml
  81. 31 0
      modules/boonex/payment/updates/12.0.0_12.0.1/install/sql/enable.sql
  82. 137 0
      modules/boonex/payment/updates/12.0.0_12.0.1/install/sql/install.sql
  83. 49 0
      modules/boonex/payment/updates/12.0.0_12.0.1/source/classes/BxPaymentCommissions.php
  84. 325 0
      modules/boonex/payment/updates/12.0.0_12.0.1/source/classes/BxPaymentConfig.php
  85. 31 0
      modules/boonex/payment/updates/12.0.0_12.0.1/source/classes/BxPaymentCronCommissions.php
  86. 776 0
      modules/boonex/payment/updates/12.0.0_12.0.1/source/classes/BxPaymentDb.php
  87. 36 0
      modules/boonex/payment/updates/12.0.0_12.0.1/source/classes/BxPaymentFormCommissions.php
  88. 34 0
      modules/boonex/payment/updates/12.0.0_12.0.1/source/classes/BxPaymentFormInvoices.php
  89. 140 0
      modules/boonex/payment/updates/12.0.0_12.0.1/source/classes/BxPaymentGridCommissions.php
  90. 81 0
      modules/boonex/payment/updates/12.0.0_12.0.1/source/classes/BxPaymentGridInvoices.php
  91. 90 0
      modules/boonex/payment/updates/12.0.0_12.0.1/source/classes/BxPaymentGridPending.php
  92. 257 0
      modules/boonex/payment/updates/12.0.0_12.0.1/source/classes/BxPaymentGridProcessed.php
  93. 1608 0
      modules/boonex/payment/updates/12.0.0_12.0.1/source/classes/BxPaymentModule.php
  94. 200 0
      modules/boonex/payment/updates/12.0.0_12.0.1/source/classes/BxPaymentOrders.php
  95. 26 0
      modules/boonex/payment/updates/12.0.0_12.0.1/source/classes/BxPaymentPageInvoices.php
  96. 49 0
      modules/boonex/payment/updates/12.0.0_12.0.1/source/classes/BxPaymentStudioPage.php
  97. 476 0
      modules/boonex/payment/updates/12.0.0_12.0.1/source/classes/BxPaymentTemplate.php
  98. 70 0
      modules/boonex/payment/updates/12.0.0_12.0.1/source/install/config.php
  99. 690 0
      modules/boonex/payment/updates/12.0.0_12.0.1/source/install/langs/en.xml
  100. 43 0
      modules/boonex/payment/updates/12.0.0_12.0.1/source/install/sql/disable.sql

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

@@ -0,0 +1,51 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'title' => 'Accounts Manager',
+    'version_from' => '12.0.0',
+    'version_to' => '12.0.1',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '12.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_12.0.0_12.0.1/',
+    'home_uri' => 'accounts_update_1200_1201',
+
+    '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' => 1,
+        'clear_db_cache' => 0,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Accounts',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

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

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

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

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

+ 97 - 0
modules/boonex/accounts/updates/12.0.0_12.0.1/source/classes/BxAccntConfig.php

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

+ 587 - 0
modules/boonex/accounts/updates/12.0.0_12.0.1/source/classes/BxAccntGridAdministration.php

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

+ 71 - 0
modules/boonex/accounts/updates/12.0.0_12.0.1/source/install/config.php

@@ -0,0 +1,71 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Accounts Accounts
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_accounts',
+    'title' => 'Accounts Manager',
+    'note' => 'Accounts Manager module.',
+    'version' => '12.0.1',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '12.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(),
+
+);
+
+/** @} */

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

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

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

@@ -0,0 +1,51 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'title' => 'Paid Levels',
+    'version_from' => '12.0.0',
+    'version_to' => '12.0.1',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '12.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/acl/updates/update_12.0.0_12.0.1/',
+    'home_uri' => 'acl_update_1200_1201',
+
+    'module_dir' => 'boonex/acl/',
+    'module_uri' => 'acl',
+
+    'db_prefix' => 'bx_acl_',
+    'class_prefix' => 'BxAcl',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_files' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Paid Levels',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

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

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

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

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

+ 9 - 0
modules/boonex/acl/updates/12.0.0_12.0.1/install/sql/enable.sql

@@ -0,0 +1,9 @@
+SET @sName = 'bx_acl';
+
+
+-- SETTINGS
+SET @iCategId = (SELECT `id` FROM `sys_options_categories` WHERE `name`=@sName LIMIT 1);
+
+DELETE FROM `sys_options` WHERE `name`='bx_acl_recurring_prioritize';
+INSERT INTO `sys_options` (`name`, `value`, `category_id`, `caption`, `type`, `check`, `check_params`, `check_error`, `extra`, `order`) VALUES
+('bx_acl_recurring_prioritize', 'on', @iCategId, '_bx_acl_option_recurring_prioritize', 'checkbox', '', '', '', '', 2);

+ 144 - 0
modules/boonex/acl/updates/12.0.0_12.0.1/source/classes/BxAclConfig.php

@@ -0,0 +1,144 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    PaidLevels Paid Levels
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxAclConfig extends BxBaseModGeneralConfig
+{
+    protected $_oDb;
+    protected $_aHtmlIds;
+    protected $_aCurrency;
+    protected $_iOwner;
+
+    protected $_iExpireNotificationDays;
+    protected $_bExpireNotifyOnce;
+    protected $_iRemoveExpiredFor;
+
+    /**
+     * Constructor
+     */
+    public function __construct($aModule)
+    {
+        parent::__construct($aModule);
+
+        $this->CNF = array (
+            // database tables
+            'TABLE_PRICES' => $aModule['db_prefix'] . 'level_prices',
+
+            // database fields
+            'FIELD_ID' => 'id',
+            'FIELD_LEVEL_ID' => 'level_id',
+            'FIELD_NAME' => 'name',
+
+            // page URIs
+            'URL_ADMINISTRATION' => 'page.php?i=acl-administration',
+            'URL_VIEW' => 'page.php?i=acl-view',
+
+            // some params
+            'PARAM_RECURRING_RESERVE' => 'bx_acl_recurring_reserve',
+            'PARAM_RECURRING_PRIORITIZE' => 'bx_acl_recurring_prioritize',
+
+            // objects 
+            'OBJECT_GRID_ADMINISTRATION' => 'bx_acl_administration',
+            'OBJECT_GRID_VIEW' => 'bx_acl_view',
+            'OBJECT_FORM_PRICE' => 'bx_acl_price',
+            'OBJECT_FORM_PRICE_DISPLAY_ADD' => 'bx_acl_price_add',
+            'OBJECT_FORM_PRICE_DISPLAY_EDIT' => 'bx_acl_price_edit',
+            'OBJECT_FORM_PRELISTS_PERIOD_UNITS' => 'bx_acl_period_units',
+        );
+
+        $this->_aGridObjects = array(
+            'administration' => $this->CNF['OBJECT_GRID_ADMINISTRATION'],
+            'view' => $this->CNF['OBJECT_GRID_VIEW'],
+        );
+
+        $this->_aPrefixes = array(
+            'style' => 'bx-acl',
+            'option' => 'bx_acl_',
+        );
+
+        $this->_aJsClasses = array(
+            'main' => 'BxAclMain',
+            'form' => 'BxAclForm',
+            'administration' => 'BxAclAdministration',
+        );
+        $this->_aJsObjects = array(
+            'main' => 'oAclMain',
+            'form' => 'oAclForm',
+            'administration' => 'oAclAdministration',
+        );
+
+        $sHtmlPrefix = str_replace('_', '-', $this->_sName);
+        $this->_aHtmlIds = array(
+            'popup_price' => $sHtmlPrefix . '-popup-price'
+        );
+
+        $oPayments = BxDolPayments::getInstance();
+        $this->_iOwner = (int)$oPayments->getOption('site_admin');
+        $this->_aCurrency = array(
+            'code' => $oPayments->getOption('default_currency_code'),
+            'sign' => $oPayments->getOption('default_currency_sign')
+        );
+
+        $this->_bExpireNotifyOnce = true;
+        $this->_iExpireNotificationDays = 1;
+        $this->_iRemoveExpiredFor = 30;
+    }
+
+    public function init(&$oDb)
+    {
+        $this->_oDb = &$oDb;
+
+        $sOptionPrefix = $this->getPrefix('option');
+
+        $this->_iExpireNotificationDays = (int)getParam($sOptionPrefix . 'expire_notification_days');
+        $this->_bExpireNotifyOnce = getParam($sOptionPrefix . 'expire_notify_once') == 'on';
+        $this->_iRemoveExpiredFor = (int)getParam($sOptionPrefix . 'remove_expired_for');
+    }
+
+    public function getExpireNotificationDays()
+    {
+        return $this->_iExpireNotificationDays;
+    }
+
+    public function isExpireNotifyOnce()
+    {
+        return $this->_bExpireNotifyOnce;
+    }
+
+    public function getRemoveExpiredFor()
+    {
+        return $this->_iRemoveExpiredFor;
+    }
+
+    public function getHtmlIds($sKey = '')
+    {
+        if(empty($sKey))
+            return $this->_aHtmlIds;
+
+        return isset($this->_aHtmlIds[$sKey]) ? $this->_aHtmlIds[$sKey] : '';
+    }
+
+    public function getOwner()
+    {
+    	return $this->_iOwner;
+    }
+
+    public function getCurrency()
+    {
+    	return $this->_aCurrency;
+    }
+
+    public function getPriceName($sName)
+    {
+        return uriGenerate($sName, $this->CNF['TABLE_PRICES'], $this->CNF['FIELD_NAME']);
+    }
+}
+
+/** @} */

+ 135 - 0
modules/boonex/acl/updates/12.0.0_12.0.1/source/classes/BxAclGridView.php

@@ -0,0 +1,135 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    PaidLevels Paid Levels
+ * @ingroup     UnaModules
+ * 
+ * @{
+ */
+
+require_once('BxAclGridLevels.php');
+
+class BxAclGridView extends BxAclGridLevels
+{
+    /**
+     * Array with check_sum => JS_code pairs of all JS codes 
+     * which should be added to the page.
+     */
+    protected $_aJsCodes;
+
+    protected $_iOwner;
+    protected $_oPayment;
+    protected $_bTypeSingle;
+    protected $_bTypeRecurring;
+
+    public function __construct ($aOptions, $oTemplate = false)
+    {
+        parent::__construct ($aOptions, $oTemplate);
+
+        $this->_aJsCodes = array();
+
+        $this->_iOwner = $this->_oModule->_oConfig->getOwner();
+        $this->_oPayment = BxDolPayments::getInstance();
+        $this->_bTypeSingle = $this->_oPayment->isAcceptingPayments($this->_iOwner, BX_PAYMENT_TYPE_SINGLE);
+        $this->_bTypeRecurring = !$this->_oPayment->isCreditsOnly() && $this->_oPayment->isAcceptingPayments($this->_iOwner, BX_PAYMENT_TYPE_RECURRING);
+    }
+
+    public function performActionChoose()
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        $aIds = $this->_getIds();
+        if($aIds === false)
+            return echoJson(array());
+
+        $aItem = $this->_oModule->_oDb->getPrices(array('type' => 'by_id', 'value' => $aIds[0]));
+        if(!is_array($aItem) || empty($aItem) || (float)$aItem['price'] != 0)
+        	return echoJson(array());
+
+        $aResult = array();
+        $iUserId = bx_get_logged_profile_id();
+        if(BxDolAcl::getInstance()->setMembership($iUserId, $aItem['level_id'], array('period' => $aItem['period'], 'period_unit' => $aItem['period_unit']), true))
+            $aResult = array('grid' => $this->getCode(false), 'blink' => $aItem['id'], 'msg' => _t('_bx_acl_msg_performed'));
+        else
+            $aResult = array('msg' => _t('_bx_acl_err_cannot_perform'));
+
+        return echoJson($aResult);
+    }
+
+    public function getCode($isDisplayHeader = true)
+    {
+    	return parent::getCode($isDisplayHeader) . $this->getJsCode();
+    }
+
+    public function getJsCode()
+    {
+        if(empty($this->_aJsCodes) || !is_array($this->_aJsCodes))
+            return '';
+
+        return implode('', $this->_aJsCodes);
+    }
+
+    protected function _getCellLevelIcon($mixedValue, $sKey, $aField, $aRow)
+    {
+        $mixedValue = $this->_oModule->_oTemplate->displayLevelIcon($mixedValue);
+    	return parent::_getCellDefault($mixedValue, $sKey, $aField, $aRow);
+    }
+
+    protected function _getActionChoose ($sType, $sKey, $a, $isSmall = false, $isDisabled = false, $aRow = array())
+    {
+        if((float)$aRow['price'] != 0 || BxDolAcl::getInstance()->isMemberLevelInSet(array($aRow['level_id'])))
+            return '';
+
+        return  parent::_getActionDefault($sType, $sKey, $a, false, $isDisabled, $aRow);
+    }
+
+    protected function _getActionBuy ($sType, $sKey, $a, $isSmall = false, $isDisabled = false, $aRow = array())
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        if((float)$aRow['price'] == 0 || !$this->_bTypeSingle || ($this->_bTypeRecurring && getParam($CNF['PARAM_RECURRING_PRIORITIZE']) == 'on'))
+            return '';
+
+    	$aJs = $this->_oPayment->getAddToCartJs($this->_iOwner, $this->MODULE, $aRow['id'], 1, true);
+    	if(!empty($aJs) && is_array($aJs)) {
+            list($sJsCode, $sJsMethod) = $aJs;
+
+            $sJsCodeCheckSum = md5($sJsCode);
+            if(!isset($this->_aJsCodes[$sJsCodeCheckSum]))
+                $this->_aJsCodes[$sJsCodeCheckSum] = $sJsCode;
+
+            $a['attr'] = array(
+                'title' => bx_html_attribute(_t('_bx_acl_grid_action_buy_title')),
+                'onclick' => $sJsMethod
+            );
+    	}
+
+        return  parent::_getActionDefault($sType, $sKey, $a, false, $isDisabled, $aRow);
+    }
+
+    protected function _getActionSubscribe ($sType, $sKey, $a, $isSmall = false, $isDisabled = false, $aRow = array())
+    {
+        if((float)$aRow['price'] == 0 || !$this->_bTypeRecurring)
+            return '';
+
+    	$aJs = $this->_oPayment->getSubscribeJs($this->_iOwner, '', $this->MODULE, $aRow['id'], 1);
+        if(!empty($aJs) && is_array($aJs)) {
+            list($sJsCode, $sJsMethod) = $aJs;
+
+            $sJsCodeCheckSum = md5($sJsCode);
+            if(!isset($this->_aJsCodes[$sJsCodeCheckSum]))
+                $this->_aJsCodes[$sJsCodeCheckSum] = $sJsCode;
+
+            $a['attr'] = array(
+                'title' => bx_html_attribute(_t('_bx_acl_grid_action_subscribe_title')),
+                'onclick' => $sJsMethod
+            );
+        }
+
+    	return parent::_getActionDefault($sType, $sKey, $a, false, $isDisabled, $aRow);
+    }
+}
+
+/** @} */

+ 70 - 0
modules/boonex/acl/updates/12.0.0_12.0.1/source/install/config.php

@@ -0,0 +1,70 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    PaidLevels Paid Levels
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_acl',
+    'title' => 'Paid Levels',
+    'note' => 'Paid Levels module.',
+    'version' => '12.0.1',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '12.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/acl/',
+    'home_uri' => 'acl',
+
+    'db_prefix' => 'bx_acl_',
+    'class_prefix' => 'BxAcl',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Paid Levels',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'uninstall' => array (
+        'execute_sql' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'enable' => array(
+        'execute_sql' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable' => array (
+        'execute_sql' => 1,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Dependencies Section
+     */
+    'dependencies' => array(),
+);
+
+/** @} */

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

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

+ 40 - 0
modules/boonex/acl/updates/12.0.0_12.0.1/source/install/sql/enable.sql

@@ -0,0 +1,40 @@
+SET @sName = 'bx_acl';
+
+
+-- 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_acl', 'bx_acl@modules/boonex/acl/|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_acl', 1);
+SET @iCategId = LAST_INSERT_ID();
+
+INSERT INTO `sys_options` (`name`, `value`, `category_id`, `caption`, `type`, `check`, `check_error`, `extra`, `order`) VALUES
+('bx_acl_recurring_reserve', '2', @iCategId, '_bx_acl_option_recurring_reserve', 'digit', '', '', '', 1),
+('bx_acl_recurring_prioritize', 'on', @iCategId, '_bx_acl_option_recurring_prioritize', 'checkbox', '', '', '', 2);
+
+
+-- PAGE: view levels
+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_acl_view', '_bx_acl_page_title_sys_view', '_bx_acl_page_title_view', @sName, 5, 2147483647, 1, 'acl-view', 'page.php?i=acl-view', '', '', '', 0, 1, 0, 'BxAclPageView', 'modules/boonex/acl/classes/BxAclPageView.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_acl_view', 1, @sName, '_bx_acl_page_block_title_system_view', '_bx_acl_page_block_title_view', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:6:\"bx_acl\";s:6:\"method\";s:14:\"get_block_view\";}', 0, 1, 0);
+
+
+-- MENU: account settings menu
+SET @iMoAccountSettings = (SELECT IFNULL(MAX(`order`), 0) FROM `sys_menu_items` WHERE `set_name`='sys_account_settings' AND `order` < 9999 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_settings', 'bx_acl', 'acl-view', '_bx_acl_menu_item_title_system_acl_view', '_bx_acl_menu_item_title_acl_view', 'page.php?i=acl-view', '', '', 'shield-alt col-red2', '', '', 2147483646, 1, 0, 1, @iMoAccountSettings + 1);
+
+
+-- ALERTS
+INSERT INTO `sys_alerts_handlers`(`name`, `class`, `file`, `service_call`) VALUES 
+(@sName, 'BxAclResponse', 'modules/boonex/acl/classes/BxAclResponse.php', '');
+SET @iHandler := LAST_INSERT_ID();
+
+INSERT INTO `sys_alerts` (`unit`, `action`, `handler_id`) VALUES
+('system', 'page_output_block_acl_level', @iHandler),
+('acl', 'deleted', @iHandler);

+ 51 - 0
modules/boonex/albums/updates/12.00_12.0.1/install/config.php

@@ -0,0 +1,51 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'title' => 'Albums',
+    'version_from' => '12.0.0',
+    'version_to' => '12.0.1',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '12.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/albums/updates/update_12.0.0_12.0.1/',
+    'home_uri' => 'albums_update_1200_1201',
+
+    'module_dir' => 'boonex/albums/',
+    'module_uri' => 'albums',
+
+    'db_prefix' => 'bx_albums_',
+    'class_prefix' => 'BxAlbums',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 0,
+        'update_files' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 0,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Albums',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

+ 13 - 0
modules/boonex/albums/updates/12.00_12.0.1/install/installer.php

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

+ 4 - 0
modules/boonex/albums/updates/12.00_12.0.1/install/langs/en.xml

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

+ 143 - 0
modules/boonex/albums/updates/12.00_12.0.1/source/install/config.php

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

+ 295 - 0
modules/boonex/albums/updates/12.00_12.0.1/source/install/langs/en.xml

@@ -0,0 +1,295 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources name="en" flag="gb" title="English">
+
+	<string name="_bx_albums"><![CDATA[Albums]]></string>
+	<string name="_bx_albums_cmts"><![CDATA[Albums' Comments]]></string>
+        <string name="_bx_albums_reactions"><![CDATA[Albums' Reactions]]></string>
+	<string name="_bx_albums_media"><![CDATA[Images]]></string>
+	<string name="_bx_albums_media_cmts"><![CDATA[Images' Comments]]></string>
+
+	<string name="_bx_albums_option_summary_chars"><![CDATA[Number of characters in auto-cropped album summary]]></string>
+	<string name="_bx_albums_option_plain_summary_chars"><![CDATA[Number of characters in plain album description when album hasn't thumb]]></string>
+	<string name="_bx_albums_option_per_page_browse"><![CDATA[Number of items per page]]></string>
+	<string name="_bx_albums_option_per_page_profile"><![CDATA[Number of items on profile page]]></string>
+	<string name="_bx_albums_option_album_browsing_unit"><![CDATA[Number of items in album card]]></string>
+	<string name="_bx_albums_option_rss_num"><![CDATA[Number of items in RSS feed]]></string>
+	<string name="_bx_albums_option_searchable_fields"><![CDATA[Searchable fields for keyword search]]></string>
+  <string name="_bx_albums_option_per_page_for_favorites_lists"><![CDATA[Number of favorite lists per page]]></string>
+
+	<string name="_bx_albums_form_entry"><![CDATA[Albums]]></string>
+	<string name="_bx_albums_form_entry_display_add"><![CDATA[Add Album]]></string>
+    <string name="_bx_albums_form_entry_display_edit"><![CDATA[Edit Album]]></string>
+	<string name="_bx_albums_form_entry_display_add_images"><![CDATA[Add Images To Album]]></string>
+	<string name="_bx_albums_form_entry_display_delete"><![CDATA[Delete Album]]></string>
+	<string name="_bx_albums_form_entry_display_view"><![CDATA[View Album]]></string>
+	<string name="_bx_albums_form_entry_input_author"><![CDATA[Author]]></string>
+	<string name="_bx_albums_form_entry_input_sys_do_submit"><![CDATA[Submit]]></string>
+	<string name="_bx_albums_form_entry_input_do_submit"><![CDATA[Submit]]></string>
+	<string name="_bx_albums_form_entry_input_sys_title"><![CDATA[Caption]]></string>
+	<string name="_bx_albums_form_entry_input_title"><![CDATA[Caption]]></string>
+	<string name="_bx_albums_form_entry_input_title_err"><![CDATA[Caption is essential. Please, fill in this field]]></string>
+	<string name="_bx_albums_form_entry_input_sys_text"><![CDATA[Album Description]]></string>
+	<string name="_bx_albums_form_entry_input_text"><![CDATA[Album Description]]></string>
+	<string name="_bx_albums_form_entry_input_sys_delete_confirm"><![CDATA[Delete confirmation]]></string>
+	<string name="_bx_albums_form_entry_input_delete_confirm"><![CDATA[I am sure I want to delete this album]]></string>
+	<string name="_bx_albums_form_entry_input_delete_confirm_info"><![CDATA[This action can not be undone]]></string>
+	<string name="_bx_albums_form_entry_input_delete_confirm_error"><![CDATA[Please check this checkbox if you really want to delete the album]]></string>
+	<string name="_bx_albums_form_entry_input_sys_pictures"><![CDATA[Pictures]]></string>
+	<string name="_bx_albums_form_entry_input_pictures"><![CDATA[Pictures]]></string>
+    <string name="_bx_albums_form_entry_input_sys_allow_view_to"><![CDATA[Visibility]]></string>
+    <string name="_bx_albums_form_entry_input_allow_view_to"><![CDATA[Visibility]]></string>
+    <string name="_bx_albums_form_entry_input_allow_view_favorite_list"><![CDATA[Visibility]]></string>
+    <string name="_bx_albums_form_entry_file_title"><![CDATA[Caption]]></string>
+	<string name="_bx_albums_form_entry_input_sys_date_added"><![CDATA[Created]]></string>
+	<string name="_bx_albums_form_entry_input_date_added"><![CDATA[Created]]></string>
+	<string name="_bx_albums_form_entry_input_sys_date_changed"><![CDATA[Updated]]></string>
+    <string name="_bx_albums_form_entry_input_date_changed"><![CDATA[Updated]]></string>
+
+        <string name="_bx_albums_form_media"><![CDATA[Medias]]></string>
+        <string name="_bx_albums_form_media_display_edit"><![CDATA[Edit Media]]></string>
+        <string name="_bx_albums_form_media_input_sys_title"><![CDATA[Caption]]></string>
+	<string name="_bx_albums_form_media_input_title"><![CDATA[Caption]]></string>
+        <string name="_bx_albums_form_media_input_sys_do_submit"><![CDATA[Submit]]></string>
+	<string name="_bx_albums_form_media_input_do_submit"><![CDATA[Submit]]></string>
+        <string name="_bx_albums_form_media_input_sys_do_cancel"><![CDATA[Cancel]]></string>
+	<string name="_bx_albums_form_media_input_do_cancel"><![CDATA[Cancel]]></string>
+
+	<string name="_bx_albums_acl_action_create_entry"><![CDATA[Create Album]]></string>
+	<string name="_bx_albums_acl_action_delete_entry"><![CDATA[Delete Album]]></string>
+	<string name="_bx_albums_acl_action_view_entry"><![CDATA[View Album]]></string>
+	<string name="_bx_albums_acl_action_set_thumb"><![CDATA[Set Album Cover]]></string>
+	<string name="_bx_albums_acl_action_edit_any_entry"><![CDATA[Edit Any Album]]></string>
+
+	<string name="_bx_albums_page_title_sys_create_entry"><![CDATA[New Album]]></string>
+	<string name="_bx_albums_page_title_create_entry"><![CDATA[New Album]]></string>
+	<string name="_bx_albums_page_block_title_create_entry"><![CDATA[New Album]]></string>
+	<string name="_bx_albums_page_title_sys_edit_entry"><![CDATA[Edit]]></string>
+    <string name="_bx_albums_page_title_edit_entry"><![CDATA[Edit]]></string>
+	<string name="_bx_albums_page_title_sys_add_images"><![CDATA[Add/Edit Pictures]]></string>
+	<string name="_bx_albums_page_title_add_images"><![CDATA[Add/Edit Pictures]]></string>
+    <string name="_bx_albums_page_block_title_edit_entry"><![CDATA[Edit]]></string>
+	<string name="_bx_albums_page_block_title_add_images"><![CDATA[Add/Edit Pictures]]></string>
+    <string name="_bx_albums_page_title_sys_delete_entry"><![CDATA[Delete]]></string>
+    <string name="_bx_albums_page_title_delete_entry"><![CDATA[Delete]]></string>
+    <string name="_bx_albums_page_block_title_delete_entry"><![CDATA[Delete]]></string>
+	<string name="_bx_albums_page_title_sys_view_entry"><![CDATA[View Album]]></string>
+	<string name="_bx_albums_page_title_view_entry"><![CDATA[{title}]]></string>
+	<string name="_bx_albums_page_title_sys_view_media"><![CDATA[View Image]]></string>
+	<string name="_bx_albums_page_title_view_media"><![CDATA[{title}]]></string>
+	<string name="_bx_albums_page_block_title_entry_view_media"><![CDATA[View Image]]></string>
+	<string name="_bx_albums_page_block_title_entry_view_media_exif"><![CDATA[EXIF]]></string>
+	<string name="_bx_albums_page_block_title_entry_attachments"><![CDATA[Attachments]]></string>
+	<string name="_bx_albums_page_block_title_entry_text"><![CDATA[Album Description]]></string>
+	<string name="_bx_albums_page_title_browse"><![CDATA[Albums]]></string>
+	<string name="_bx_albums_page_title_search_results"><![CDATA[Albums matching "{0}"]]></string>
+	<string name="_bx_albums_page_title_browse_by_author"><![CDATA[{display_name}'s Albums]]></string>
+  <string name="_bx_albums_page_title_browse_by_context"><![CDATA[Albums in {display_name}]]></string>
+	<string name="_bx_albums_page_title_browse_featured"><![CDATA[Featured Albums]]></string>
+	<string name="_bx_albums_page_title_browse_featured_media"><![CDATA[Featured Media]]></string>
+    <string name="_bx_albums_page_title_browse_recent"><![CDATA[Latest Albums]]></string>
+    <string name="_bx_albums_page_title_browse_popular"><![CDATA[Popular Albums]]></string>
+    <string name="_bx_albums_page_title_browse_popular_media"><![CDATA[Popular Images]]></string>
+    <string name="_bx_albums_page_title_browse_top"><![CDATA[Top Albums]]></string>
+    <string name="_bx_albums_page_title_browse_top_media"><![CDATA[Top Images]]></string>
+    <string name="_bx_albums_page_title_browse_recent_media"><![CDATA[Recent Images]]></string>
+    <string name="_bx_albums_page_title_browse_media_in_album"><![CDATA[Images]]></string>
+    <string name="_bx_albums_page_title_browse_updated"><![CDATA[Updated Albums]]></string>
+    <string name="_bx_albums_page_title_sys_home"><![CDATA[Albums Home]]></string>
+    <string name="_bx_albums_page_title_home"><![CDATA[Albums]]></string>
+    <string name="_bx_albums_page_block_title_featured_entries_view_extended"><![CDATA[Featured Albums]]></string>
+    <string name="_bx_albums_page_block_title_featured_entries_view_gallery_media"><![CDATA[Featured Media]]></string>
+    <string name="_bx_albums_page_block_title_recent_entries"><![CDATA[Latest Albums]]></string>
+    <string name="_bx_albums_page_block_title_entry_all_actions"><![CDATA[All Actions]]></string>
+    <string name="_bx_albums_page_block_title_entry_social_sharing"><![CDATA[Share]]></string>
+    <string name="_bx_albums_page_block_title_entry_author"><![CDATA[Author]]></string>
+    <string name="_bx_albums_page_block_title_entry_info"><![CDATA[Info]]></string>
+    <string name="_bx_albums_page_block_title_entry_actions"><![CDATA[Actions]]></string>
+    <string name="_bx_albums_page_block_title_entry_comments"><![CDATA[Comments]]></string>
+    <string name="_bx_albums_page_block_title_entry_comments_link"><![CDATA[Comments to <a href="{entry_link}">{title}</a>]]></string>
+    <string name="_bx_albums_page_block_title_entry_location"><![CDATA[Location]]></string>
+    <string name="_bx_albums_page_title_sys_entries_popular"><![CDATA[Popular]]></string>
+    <string name="_bx_albums_page_title_entries_popular"><![CDATA[Popular]]></string>
+    <string name="_bx_albums_page_title_sys_entries_popular_media"><![CDATA[Popular Images]]></string>
+    <string name="_bx_albums_page_title_entries_popular_media"><![CDATA[Popular Images]]></string>
+    <string name="_bx_albums_page_block_title_popular_entries"><![CDATA[Popular]]></string>
+    <string name="_bx_albums_page_block_title_popular_media"><![CDATA[Popular Images]]></string>
+    <string name="_bx_albums_page_title_sys_entries_top"><![CDATA[Top]]></string>
+    <string name="_bx_albums_page_title_entries_top"><![CDATA[Top]]></string>
+    <string name="_bx_albums_page_title_sys_entries_top_media"><![CDATA[Top Images]]></string>
+    <string name="_bx_albums_page_title_entries_top_media"><![CDATA[Top Images]]></string>
+    <string name="_bx_albums_page_block_title_top_entries"><![CDATA[Top]]></string>
+    <string name="_bx_albums_page_block_title_top_media"><![CDATA[Top Images]]></string>
+    <string name="_bx_albums_page_block_title_recent_media"><![CDATA[Recent Images]]></string>
+    <string name="_bx_albums_page_block_title_updated_entries"><![CDATA[Updated Albums]]></string>
+    <string name="_bx_albums_page_block_title_favorites_entries"><![CDATA["{title}" List]]></string>
+    <string name="_bx_albums_page_block_title_favorites_entries_info"><![CDATA[Info]]></string>
+    <string name="_bx_albums_page_block_title_favorites_entries_actions"><![CDATA[Favorites List Actions]]></string>
+    <string name="_bx_albums_page_title_sys_view_entry_comments"><![CDATA[Comments]]></string>
+    <string name="_bx_albums_page_title_view_entry_comments"><![CDATA[Comments to {title}]]></string>
+    <string name="_bx_albums_page_title_sys_entries_of_author"><![CDATA[Albums of author]]></string>
+    <string name="_bx_albums_page_title_entries_of_author"><![CDATA[{display_name}'s albums]]></string>
+    <string name="_bx_albums_page_title_sys_entries_in_context"><![CDATA[Albums in context]]></string>
+    <string name="_bx_albums_page_title_entries_in_context"><![CDATA[Albums in {display_name}]]></string>
+    <string name="_bx_albums_page_block_title_favorites_of_author"><![CDATA[Favorite albums by <a href="{profile_link}">{display_name}</a>]]></string>
+    <string name="_bx_albums_page_block_title_sys_favorites_of_author"><![CDATA[Favorite albums of author]]></string>
+    <string name="_bx_albums_page_block_title_favorites_of_author_media"><![CDATA[Favorite media by <a href="{profile_link}">{display_name}</a>]]></string>
+    <string name="_bx_albums_page_block_title_sys_favorites_of_author_media"><![CDATA[Favorite media of author]]></string>
+    <string name="_bx_albums_page_block_title_entries_of_author"><![CDATA[Albums by <a href="{profile_link}">{display_name}</a>]]></string>   
+    <string name="_bx_albums_page_block_title_sys_entries_of_author"><![CDATA[Albums of author]]></string>
+    <string name="_bx_albums_page_block_title_entries_in_context"><![CDATA[Albums in <a href="{profile_link}">{display_name}</a>]]></string>
+    <string name="_bx_albums_page_block_title_sys_entries_in_context"><![CDATA[Albums in context]]></string>
+    <string name="_bx_albums_page_block_title_entries_actions"><![CDATA[Albums actions]]></string>
+    <string name="_bx_albums_page_block_title_browse_cmts"><![CDATA[Albums' Comments]]></string>
+    <string name="_bx_albums_page_block_title_browse_cmts_media"><![CDATA[Images Comments]]></string>
+	<string name="_bx_albums_page_title_sys_manage"><![CDATA[Manage Own Albums]]></string>
+	<string name="_bx_albums_page_title_sys_manage_administration"><![CDATA[Manage All Albums]]></string>
+	<string name="_bx_albums_page_title_manage"><![CDATA[Manage]]></string>
+	<string name="_bx_albums_page_block_title_system_manage"><![CDATA[Manage Own Albums]]></string>
+	<string name="_bx_albums_page_block_title_system_manage_administration"><![CDATA[Manage All Albums]]></string>  
+	<string name="_bx_albums_page_block_title_manage"><![CDATA[Manage]]></string>
+	<string name="_bx_albums_page_block_title_popular_keywords_albums"><![CDATA[Popular Albums Hashtags]]></string>
+	<string name="_bx_albums_page_block_title_popular_keywords_media"><![CDATA[Popular Media Hashtags]]></string>
+	<string name="_bx_albums_page_block_title_popular_keywords_media_camera"><![CDATA[Popular Cameras]]></string>
+	<string name="_bx_albums_page_block_title_sys_my_entries"><![CDATA[User Albums]]></string>
+        <string name="_bx_albums_page_block_title_my_entries"><![CDATA[{display_name} Albums]]></string>
+  	<string name="_bx_albums_page_title_sys_entries_search"><![CDATA[Search]]></string>
+    <string name="_bx_albums_page_title_entries_search"><![CDATA[Search]]></string>
+    <string name="_bx_albums_page_title_sys_entries_favorites"><![CDATA[Favorives Media]]></string>
+    <string name="_bx_albums_page_title_entries_favorites"><![CDATA[Favorives Media]]></string>
+    <string name="_bx_albums_page_block_title_search_form"><![CDATA[Search Form]]></string>
+    <string name="_bx_albums_page_block_title_search_results"><![CDATA[Search Results]]></string>
+    <string name="_bx_albums_page_block_title_search_form_media"><![CDATA[Images Search Form]]></string>
+    <string name="_bx_albums_page_block_title_search_results_media"><![CDATA[Images Search Results]]></string>
+    <string name="_bx_albums_page_block_title_search_form_cmts"><![CDATA[Comments Search Form]]></string>
+    <string name="_bx_albums_page_block_title_search_results_cmts"><![CDATA[Comments Search Results]]></string>
+    <string name="_bx_albums_page_block_title_search_form_media_cmts"><![CDATA[Images Comments Search Form]]></string>
+    <string name="_bx_albums_page_block_title_search_results_media_cmts"><![CDATA[Images Comments Search Results]]></string>
+    <string name="_bx_albums_page_block_title_sys_recent_media_view_showcase"><![CDATA[Recent Images (Showcase View)]]></string>
+    <string name="_bx_albums_page_block_title_recent_media_view_showcase"><![CDATA[Recent Images]]></string>
+    <string name="_bx_albums_page_block_title_sys_popular_media_view_showcase"><![CDATA[Top Images (Showcase View)]]></string>
+    <string name="_bx_albums_page_block_title_popular_media_view_showcase"><![CDATA[Top Images]]></string>
+    <string name="_bx_albums_page_block_title_sys_featured_media_view_showcase"><![CDATA[Featured Images (Showcase View)]]></string>
+    <string name="_bx_albums_page_block_title_featured_media_view_showcase"><![CDATA[Featured Images]]></string>
+	<string name="_bx_albums_page_block_title_sys_entry_context"><![CDATA[Posted in]]></string>
+  	<string name="_bx_albums_page_block_title_entry_context"><![CDATA[Posted in]]></string>
+
+    <string name="_bx_albums_menu_set_title_view_entry"><![CDATA[Album Actions]]></string>
+    <string name="_bx_albums_menu_title_view_entry"><![CDATA[Album Actions]]></string>
+    <string name="_bx_albums_menu_set_title_view_media"><![CDATA[Media Actions]]></string>
+    <string name="_bx_albums_menu_title_view_media"><![CDATA[Media Actions]]></string>
+    <string name="_bx_albums_menu_set_title_view_actions_media"><![CDATA[Media All Actions]]></string>
+    <string name="_bx_albums_menu_title_view_actions_media"><![CDATA[Media All Actions]]></string>
+    <string name="_bx_albums_menu_set_title_view_actions_media_unit"><![CDATA[Media Card Actions]]></string>
+    <string name="_bx_albums_menu_title_view_actions_media_unit"><![CDATA[Media Card Actions]]></string>
+    <string name="_bx_albums_menu_title_submenu"><![CDATA[Albums Submenu]]></string>
+    <string name="_bx_albums_menu_set_title_submenu"><![CDATA[Albums Submenu]]></string>
+    <string name="_bx_albums_menu_item_title_system_create_entry"><![CDATA[Album]]></string>
+    <string name="_bx_albums_menu_item_title_create_entry"><![CDATA[Album]]></string>
+    <string name="_bx_albums_menu_item_title_system_edit_entry"><![CDATA[Edit]]></string>
+    <string name="_bx_albums_menu_item_title_edit_entry"><![CDATA[Edit]]></string>
+    <string name="_bx_albums_menu_item_title_system_edit_album"><![CDATA[Edit Album]]></string>
+    <string name="_bx_albums_menu_item_title_edit_album"><![CDATA[Edit Album]]></string>
+    <string name="_bx_albums_menu_item_title_system_add_images"><![CDATA[Add/Edit Pictures]]></string>
+    <string name="_bx_albums_menu_item_title_add_images"><![CDATA[Add/Edit Pictures]]></string>
+    <string name="_bx_albums_menu_item_title_system_edit_image"><![CDATA[Edit Image]]></string>
+    <string name="_bx_albums_menu_item_title_edit_image"><![CDATA[Edit Image]]></string>
+    <string name="_bx_albums_menu_item_title_system_delete_entry"><![CDATA[Delete]]></string>
+    <string name="_bx_albums_menu_item_title_delete_entry"><![CDATA[Delete]]></string>
+    <string name="_bx_albums_menu_item_title_system_view_entry"><![CDATA[View Album]]></string>
+    <string name="_bx_albums_menu_item_title_system_entries_home"><![CDATA[Albums]]></string>
+    <string name="_bx_albums_menu_item_title_entries_home"><![CDATA[Albums]]></string>
+    <string name="_bx_albums_menu_item_title_system_entries_recent"><![CDATA[Latest]]></string>
+    <string name="_bx_albums_menu_item_title_entries_recent"><![CDATA[Latest]]></string>
+    <string name="_bx_albums_menu_item_title_system_entries_search"><![CDATA[Search]]></string>
+    <string name="_bx_albums_menu_item_title_entries_search"><![CDATA[Search]]></string>
+    <string name="_bx_albums_menu_item_title_system_entries_manage"><![CDATA[Manage]]></string>
+    <string name="_bx_albums_menu_item_title_entries_manage"><![CDATA[Manage]]></string>
+    <string name="_bx_albums_menu_item_title_system_entries_popular"><![CDATA[Popular]]></string>
+    <string name="_bx_albums_menu_item_title_entries_popular"><![CDATA[Popular]]></string>
+    <string name="_bx_albums_menu_item_title_system_entries_popular_media"><![CDATA[Popular Images]]></string>
+    <string name="_bx_albums_menu_item_title_entries_popular_media"><![CDATA[Popular Images]]></string>
+    <string name="_bx_albums_menu_item_title_system_entries_top"><![CDATA[Top]]></string>
+    <string name="_bx_albums_menu_item_title_entries_top"><![CDATA[Top]]></string>
+    <string name="_bx_albums_menu_item_title_system_entries_top_media"><![CDATA[Top Images]]></string>
+    <string name="_bx_albums_menu_item_title_entries_top_media"><![CDATA[Top Images]]></string>    
+    <string name="_bx_albums_menu_title_view_entry_submenu"><![CDATA[View Album Submenu]]></string>
+    <string name="_bx_albums_menu_set_title_view_entry_submenu"><![CDATA[View Album Submenu]]></string>
+    <string name="_bx_albums_menu_item_title_view_entry_submenu_entry"><![CDATA[Album]]></string>
+    <string name="_bx_albums_menu_item_title_view_entry_submenu_comments"><![CDATA[Comments]]></string>
+    <string name="_bx_albums_menu_item_title_system_view_entry_comments"><![CDATA[Comments]]></string>
+    <string name="_bx_albums_menu_item_title_system_view_entries_author"><![CDATA[Albums]]></string>
+    <string name="_bx_albums_menu_item_title_view_entries_author"><![CDATA[Albums]]></string>
+    <string name="_bx_albums_menu_item_title_system_view_entries_in_context"><![CDATA[Albums]]></string>
+    <string name="_bx_albums_menu_item_title_view_entries_in_context"><![CDATA[Albums]]></string>
+    <string name="_bx_albums_menu_title_entries_my"><![CDATA[My Albums Action Menu]]></string>
+    <string name="_bx_albums_menu_set_title_entries_my"><![CDATA[My Albums Menu]]></string>
+	<string name="_bx_albums_menu_item_title_system_manage_my_albums"><![CDATA[My albums]]></string>
+    <string name="_bx_albums_menu_item_title_manage_my_albums"><![CDATA[Albums]]></string>
+    <string name="_bx_albums_menu_set_title_manage_tools"><![CDATA[Manage Tools Submenu]]></string>
+    <string name="_bx_albums_menu_title_manage_tools"><![CDATA[Manage Tools Submenu]]></string>
+	<string name="_bx_albums_menu_item_title_system_admt_albums"><![CDATA[Albums]]></string>
+	<string name="_bx_albums_menu_item_title_admt_albums"><![CDATA[Albums]]></string>
+	<string name="_bx_albums_menu_item_title_manage_my"><![CDATA[My Albums]]></string>
+	<string name="_bx_albums_menu_item_title_manage_all"><![CDATA[All Albums]]></string>
+        <string name="_bx_albums_menu_item_title_system_sm_items"><![CDATA[Items]]></string>
+        <string name="_bx_albums_menu_item_title_sm_items"><![CDATA[{0} items]]></string>
+
+	<string name="_bx_albums_grid_filter_item_title_adm_select_one_filter1"><![CDATA[All Statuses]]></string>
+	<string name="_bx_albums_grid_filter_item_title_adm_active"><![CDATA[Active]]></string>
+	<string name="_bx_albums_grid_filter_item_title_adm_hidden"><![CDATA[Hidden]]></string>
+	<string name="_bx_albums_grid_column_title_adm_active"><![CDATA[Active]]></string>
+    <string name="_bx_albums_grid_column_title_adm_title"><![CDATA[Caption]]></string>
+    <string name="_bx_albums_grid_column_title_adm_added"><![CDATA[Added]]></string>
+    <string name="_bx_albums_grid_column_title_adm_author"><![CDATA[Author]]></string>
+    <string name="_bx_albums_grid_action_title_adm_edit"><![CDATA[Edit]]></string>
+    <string name="_bx_albums_grid_action_title_adm_delete"><![CDATA[Delete]]></string>
+    <string name="_bx_albums_grid_action_title_adm_clear_reports"><![CDATA[Сlear reports]]></string>
+    <string name="_bx_albums_grid_action_title_adm_more_actions"><![CDATA[More Actions]]></string>
+    <string name="_bx_albums_grid_action_title_adm_audit_content"><![CDATA[Audit actions]]></string>
+    <string name="_bx_albums_grid_action_err_delete"><![CDATA[Cannot delete the selected album(s).]]></string>
+    <string name="_bx_albums_grid_txt_account_manager"><![CDATA[Redirect to manage account.]]></string>
+
+    <string name="_bx_albums_chart_growth"><![CDATA[Albums: Growth]]></string>
+    <string name="_bx_albums_chart_growth_speed"><![CDATA[Albums: Growth Speed]]></string>
+    <string name="_bx_albums_chart_growth_media"><![CDATA[Images: Growth]]></string>
+    <string name="_bx_albums_chart_growth_speed_media"><![CDATA[Images: Growth Speed]]></string>
+
+    <string name="_bx_albums_search_extended"><![CDATA[Albums Search]]></string>
+    <string name="_bx_albums_search_extended_media"><![CDATA[Images Search]]></string>
+    <string name="_bx_albums_search_extended_cmts"><![CDATA[Albums Comments Search]]></string>
+    <string name="_bx_albums_search_extended_media_cmts"><![CDATA[Images Comments Search]]></string>
+
+    <string name="_bx_albums_txt_all_entries_by"><![CDATA[{0} albums]]></string>
+    <string name="_bx_albums_txt_all_entries_in"><![CDATA[<a href="{0}">All Albums in {1} ({2})</a>]]></string>
+    <string name="_bx_albums_txt_sample_single"><![CDATA[album]]></string>
+    <string name="_bx_albums_txt_sample_single_with_article"><![CDATA[an album]]></string>
+    <string name="_bx_albums_txt_sample_comment_single"><![CDATA[comment to album]]></string>
+    <string name="_bx_albums_txt_sample_vote_single"><![CDATA[vote to album]]></string>
+    <string name="_bx_albums_txt_sample_reaction_single"><![CDATA['{0}' reaction to album]]></string>
+    <string name="_bx_albums_txt_sample_score_up_single"><![CDATA[score up vote to album]]></string>
+    <string name="_bx_albums_txt_sample_score_down_single"><![CDATA[score down vote to album]]></string>
+    <string name="_bx_albums_txt_sample_action_changed"><![CDATA[changed {0}]]></string>
+    <string name="_bx_albums_txt_media_single"><![CDATA[image]]></string>
+    <string name="_bx_albums_txt_media_comment_single"><![CDATA[image's comment]]></string>
+    <string name="_bx_albums_txt_media_vote_single"><![CDATA[image's vote]]></string>
+    <string name="_bx_albums_txt_media_score_up_single"><![CDATA[image's score up vote]]></string>
+    <string name="_bx_albums_txt_media_score_down_single"><![CDATA[image's score down vote]]></string>
+    <string name="_bx_albums_txt_media_title_alt"><![CDATA[{0}'s media]]></string>
+    <string name="_bx_albums_txt_media_title_empty"><![CDATA[No Caption]]></string>
+    <string name="_bx_albums_txt_media_album_link"><![CDATA[<a href="{0}">{1}</a> album by <a href="{2}">{3}</a>]]></string>
+    <string name="_bx_albums_txt_media_album_camera"><![CDATA[Camera]]></string>
+    <string name="_bx_albums_txt_media_album_focal_length"><![CDATA[Focal length]]></string>
+    <string name="_bx_albums_txt_media_album_focal_length_value"><![CDATA[{0}mm]]></string>
+    <string name="_bx_albums_txt_media_album_aperture"><![CDATA[Aperture]]></string>
+    <string name="_bx_albums_txt_media_album_shutter_speed"><![CDATA[Exposure time]]></string>
+    <string name="_bx_albums_txt_media_album_shutter_speed_value"><![CDATA[{0}s]]></string>
+    <string name="_bx_albums_txt_media_album_iso"><![CDATA[ISO]]></string>
+    <string name="_bx_albums_txt_processing_awaiting"><![CDATA[Scheduled for publishing as soon as video conversion is complete.]]></string>
+    <string name="_bx_albums_txt_processing_failed"><![CDATA[Album isn't published because video conversion failed, edit video to fix the issue.]]></string>
+
+    <string name="_bx_albums_txt_err_cannot_perform_action"><![CDATA[Cannot perform the action. Please report.]]></string>
+
+    <string name="_bx_albums_alert_action_medias_added"><![CDATA[add images]]></string>
+    <string name="_bx_albums_alert_action_medias_added_follow_member"><![CDATA[New media]]></string>
+    <string name="_bx_albums_alert_action_medias_added_follow_context"><![CDATA[New media]]></string>
+</resources>

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

@@ -0,0 +1,51 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'title' => 'API',
+    'version_from' => '12.0.0',
+    'version_to' => '12.0.1',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '12.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/api/updates/update_12.0.0_12.0.1/',
+    'home_uri' => 'api_update_1200_1201',
+
+    'module_dir' => 'boonex/api/',
+    'module_uri' => 'api',
+
+    'db_prefix' => 'bx_api_',
+    'class_prefix' => 'BxApi',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_files' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'API',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

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

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

+ 11 - 0
modules/boonex/api/updates/12.0.0_12.0.1/install/langs/en.xml

@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources name="en" flag="gb" title="English">
+    <string_add name="_bx_api_et_txt_name_password_reset"><![CDATA[New password message]]></string_add>
+    <string_add name="_bx_api_et_txt_subject_password_reset"><![CDATA[Your new password]]></string_add>
+    <string_add name="_bx_api_et_txt_body_password_reset"><![CDATA[{email_header}
+<p>Your new password is:</p>
+<p> </p>
+<p><b>{password}</b></p>
+<p> </p>
+{email_footer}]]></string_add>
+</resources>

+ 5 - 0
modules/boonex/api/updates/12.0.0_12.0.1/install/sql/enable.sql

@@ -0,0 +1,5 @@
+
+-- EMAIL TEMPLATES
+DELETE FROM `sys_email_templates` WHERE `Name`='bx_api_password_reset';
+INSERT INTO `sys_email_templates` (`Module`, `NameSystem`, `Name`, `Subject`, `Body`) VALUES 
+('bx_api', '_bx_api_et_txt_name_password_reset', 'bx_api_password_reset', '_bx_api_et_txt_subject_password_reset', '_bx_api_et_txt_body_password_reset');

+ 602 - 0
modules/boonex/api/updates/12.0.0_12.0.1/source/classes/BxApiModule.php

@@ -0,0 +1,602 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    API API to the UNA backend
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxApiModule extends BxDolModule
+{
+    function __construct(&$aModule)
+    {
+        parent::__construct($aModule);
+    }
+
+    public function serviceGetSafeServices()
+    {
+        $a = parent::serviceGetSafeServices();
+        return array_merge($a, array (
+            'DeletePage' => '',
+            'ChangeAccountPassword' => '',
+            'SwitchProfile' => ''
+        ));
+    }
+
+    public function serviceGetPublicServices()
+    {
+        $a = parent::serviceGetPublicServices();
+        return array_merge($a, array (
+            'Test' => '',
+            'GetPage' => '',
+            'ResetPasswordSendRequest' => '',
+            'ResetPasswordCheckCode' => '',
+            'CreateAccount' => '',
+        ));
+    }
+
+    /**
+     * @page public_api API Public
+     * @section public_api_api_test /m/oauth2/com/test
+     * 
+     * Test method to check public API
+     * 
+     * **HTTP Method:** 
+     * `GET`
+     *
+     * **Request params:**
+     * n/a
+     *
+     * **Response (success):**
+     * @code
+     * {  
+     *    "result": "Test passed."
+     * }
+     * @endcode
+     */
+    public function serviceTest()
+    {
+        return array('result' => 'Test passed.');
+    }
+
+    /**
+     * @page public_api API Public
+     * @section public_api_api_get_page /m/oauth2/com/get_page
+     * 
+     * Get page with cells and blocks as array
+     * 
+     * **HTTP Method:** 
+     * `GET`
+     *
+     * **Request params:**
+     * - `uri` - page URI
+     *
+     * **Response (success):**
+     * @code
+     * {  
+     *     "id": "123", // page ID
+     *     "layout": "5", // page layout, 5 is simplest page with one cell
+     *     "module": "system", // module which this page 
+     *     "title": "Test page", // page title
+     *     "type": 1, // page type, 1 is for default page with header and footer
+     *     "uri": "test", // page URI, which is part of page URL
+     *     "elements": {
+     *         "cell_1": [
+     *             {
+     *                 "content": "test content", // block content, it can be array as well
+     *                 "designbox_id": "11", // block design, such as padding, border, title
+     *                 "hidden_on": "", // not empty block need to be hidden on mobile, or desktop
+     *                 "id": "321",
+     *                 "module": "system", // module name this block is related to
+     *                 "order": "1", // block order
+     *                 "title": "Test block", // block title
+     *                 "type": "raw" // block type
+     *             }
+     *      ]
+     * }
+     * @endcode
+     *
+     * **Response (error):**
+     * @code
+     * {  
+     *    "error":"short error description here",
+     *    "error_description":"long error description here"
+     * }
+     * @endcode
+     */
+    public function serviceGetPage()
+    {
+        $sUri = bx_get('uri');
+        $oPage = BxDolPage::getObjectInstanceByURI($sUri);
+        if (!$oPage) {
+            return array(
+                'code' => 404,
+                'error' => 'Not Found',
+                'desc' => 'This page doesn\'t exist',
+            );
+        }
+        if (!$oPage->isVisiblePage()) {
+            return array(
+                'code' => 403,
+                'error' => 'Forbidden',
+                'desc' => 'This page requires special right to be viewed',
+            );
+        }
+
+        return $oPage->getPage ();
+    }
+
+    /**
+     * @page private_api API Private
+     * @section private_api_api_delete_page /m/oauth2/com/delete_page
+     * 
+     * Delete page with all blocks
+     * 
+     * **Scopes:** 
+     * `api`
+     *
+     * **HTTP Method:** 
+     * `POST`
+     *
+     * **Request params:**
+     * - `uri` - page URI
+     *
+     * **Request header:**
+     * @code
+     * Authorization: Bearer 9802c4a34e1535d8c3b721604ee0e7fb04116c49
+     * @endcode
+     *
+     * **Response (success):**
+     * @code
+     * {  
+     *     "code": 200,
+     * }
+     * @endcode
+     *
+     * **Response (error):**
+     * @code
+     * {  
+     *    "error":"short error description here",
+     *    "error_description":"long error description here"
+     * }
+     * @endcode
+     */
+    public function serviceDeletePage()
+    {        
+        $sUri = bx_get('uri');
+        $oPage = BxDolPage::getObjectInstanceByURI($sUri);
+        if (!$oPage) {
+            return array(
+                'code' => 404,
+                'error' => 'No Content',
+                'desc' => 'Such page doesn\'t exist',
+            );
+        }
+
+        if (!$oPage->isDeleteAllowed()) {
+            return array(
+                'code' => 403,
+                'error' => 'Forbidden',
+                'desc' => 'Not enough rights to delete this page',
+            );
+        }
+
+        $oPageBuilder = new BxTemplStudioBuilderPage($oPage->getModule(), $oPage->getName());
+        $mixed = $oPageBuilder->processAction('page_delete');
+        if (is_array($mixed) && (isset($mixed['msg']) || isset($mixed['message']))) {
+            return array(
+                'code' => 500,
+                'error' => 'Internal Error',
+                'desc' => isset($mixed['msg']) ? $mixed['msg'] : $mixed['message'],
+            );
+        }
+
+        return array('code' => 200);
+    }
+    
+    /**
+     * @page private_api API Private
+     * @section private_api_api_change_account_password /m/oauth2/com/change_account_password
+     * 
+     * Change account password
+     * 
+     * **Scopes:** 
+     * `api`
+     *
+     * **HTTP Method:** 
+     * `POST`
+     *
+     * **Request params:**
+     * - `password` - new password
+     *
+     * **Request header:**
+     * @code
+     * Authorization: Bearer 9802c4a34e1535d8c3b721604ee0e7fb04116c49
+     * @endcode
+     *
+     * **Response (success):**
+     * @code
+     * {  
+     *     "code": 200,
+     * }
+     * @endcode
+     *
+     * **Response (error):**
+     * @code
+     * {  
+     *    "error":"short error description here",
+     *    "error_description":"long error description here"
+     * }
+     * @endcode
+     */
+    public function serviceChangeAccountPassword()
+    {        
+        $sPassword = bx_get('password');
+        
+        if ($sPassword == '') {
+            return array(
+                'code' => 404,
+                'error' => 'No Content',
+                'desc' => 'Password can\'t be empty',
+            );
+        }
+        
+        $oAccount = BxDolAccount::getInstance();
+        if (!$oAccount->updatePassword($sPassword)){
+            return array(
+                'code' => 500,
+                'error' => 'Internal Error',
+            );
+        }
+
+        return array('code' => 200);
+    }
+    
+    /**
+     * @page private_api API Private
+     * @section private_api_api_switch_profile /m/oauth2/com/switch_profile
+     * 
+     * Switch account active profile
+     * 
+     * **Scopes:** 
+     * `api`
+     *
+     * **HTTP Method:** 
+     * `POST`
+     *
+     * **Request params:**
+     * - `profile_id` - profile id
+     *
+     * **Request header:**
+     * @code
+     * Authorization: Bearer 9802c4a34e1535d8c3b721604ee0e7fb04116c49
+     * @endcode
+     *
+     * **Response (success):**
+     * @code
+     * {  
+     *     "code": 200,
+     * }
+     * @endcode
+     *
+     * **Response (error):**
+     * @code
+     * {  
+     *    "error":"short error description here",
+     *    "error_description":"long error description here"
+     * }
+     * @endcode
+     */
+    public function serviceSwitchProfile()
+    {
+        $mixedProfileIdToSwitch = bx_get('profile_id');
+        
+        if ($mixedProfileIdToSwitch == '') {
+            return array(
+                'code' => 404,
+                'error' => 'No Content',
+                'desc' => 'Profile_id can\'t be empty',
+            );
+        }
+        
+		if (bx_get_logged_profile_id() == (int)$mixedProfileIdToSwitch){
+            return array(
+                'code' => 404,
+                'error' => 'Not Allowed',
+                'desc' => 'Requested profile_id equal with current profile_id',
+            );
+		}
+        
+        $mixedRes = bx_srv('system', 'switch_profile', [$mixedProfileIdToSwitch], 'TemplServiceAccount');
+        
+        if (true === $mixedRes) {
+            return array('code' => 200);
+        } 
+        else {
+            return array(
+                'code' => 500,
+                'error' => 'Internal Error',
+                'desc' => $mixedRes,
+            );
+        }
+    }
+    
+    /**
+     * @page public_api API Public
+     * @section public_api_api_reset_password_send_request /m/oauth2/com/reset_password_send_request
+     * 
+     * Send email with reset password code
+     * 
+     * **Scopes:** 
+     * `api`
+     *
+     * **HTTP Method:** 
+     * `POST`
+     *
+     * **Request params:**
+     * - `email` - email address
+     *
+     * **Request header:**
+     * @code
+     * Authorization: Bearer 9802c4a34e1535d8c3b721604ee0e7fb04116c49
+     * @endcode
+     *
+     * **Response (success):**
+     * @code
+     * {  
+     *     "code": 200,
+     * }
+     * @endcode
+     *
+     * **Response (error):**
+     * @code
+     * {  
+     *    "error":"short error description here",
+     *    "error_description":"long error description here"
+     * }
+     * @endcode
+     */
+    public function serviceResetPasswordSendRequest(){
+		$sEmail = bx_get('email');
+        if ($sEmail == ''){
+			return array(
+                'code' => 404,
+                'error' => 'No Content',
+                'desc' => 'Email can\'t be empty',
+            );
+		}
+		
+		$oAccountQuery = BxDolAccountQuery::getInstance();
+		$iAccountId = $oAccountQuery->getIdByEmail($sEmail);
+		if (!$iAccountId){
+			return array(
+                'code' => 404,
+                'error' => 'No Content',
+                'desc' => 'Email is not valid',
+            );
+		}
+		
+		$oKey = BxDolKey::getInstance();
+		$aPlus['key'] = $oKey->getNewKey(array('email' => $sEmail));
+		$aPlus['forgot_password_url'] = BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink('page.php?i=forgot-password', array('key' => $aPlus['key']));
+        $aTemplate = BxDolEmailTemplates::getInstance() -> parseTemplate('t_Forgot', $aPlus, $iAccountId);
+        if ($aTemplate && sendMail($sEmail, $aTemplate['Subject'], $aTemplate['Body'], 0, $aPlus, BX_EMAIL_SYSTEM)){
+            return array('code' => 200);
+		}
+		
+		return array(
+            'code' => 500,
+            'error' => 'Internal Error'
+        );
+	}
+    
+    /**
+     * @page public_api API Public
+     * @section public_api_api_reset_password_check_code /m/oauth2/com/reset_password_check_code
+     * 
+     * Check validation code & set new password 
+     * 
+     * **Scopes:** 
+     * `api`
+     *
+     * **HTTP Method:** 
+     * `POST`
+     *
+     * **Request params:**
+     * - `code` - validation code
+     * - `email` - email address
+     *
+     * **Request header:**
+     * @code
+     * Authorization: Bearer 9802c4a34e1535d8c3b721604ee0e7fb04116c49
+     * @endcode
+     *
+     * **Response (success):**
+     * @code
+     * {  
+     *     "code": 200,
+     *     "password" : "[NEW PASSWORD]"
+     * }
+     * @endcode
+     *
+     * **Response (error):**
+     * @code
+     * {  
+     *    "error":"short error description here",
+     *    "error_description":"long error description here"
+     * }
+     * @endcode
+     */
+    public function serviceResetPasswordCheckCode() {
+        $sKey = bx_get('code');
+
+        if ($sKey == '') {
+            return array(
+                'code' => 404,
+                'error' => 'No Content',
+                'desc' => 'Validation code can\'t be empty',
+            );
+        }
+
+        $oKey = BxDolKey::getInstance();
+        if (!$oKey || !$oKey->isKeyExists($sKey)) {
+            return array(
+                'code' => 404,
+                'error' => 'Wrong code',
+                'desc' => 'Validation code is not exist or expired',
+            );
+        }
+
+        $aData = $oKey->getKeyData($sKey);
+        if (!isset($aData['email'])){
+            return array(
+                'code' => 404,
+                'error' => 'Wrong code',
+                'desc' => 'Validation code is not exist or expired',
+            );
+        }
+
+        $oAccountQuery = BxDolAccountQuery::getInstance();
+        $iAccountId = $oAccountQuery->getIdByEmail($aData['email']);
+        if (!$iAccountId) {
+            return array(
+                'code' => 404,
+                'error' => 'Wrong code',
+                'desc' => 'Validation code is not exist or expired',
+            );
+        }
+
+        $oBxTemplServiceAccount = new BxTemplServiceAccount();
+        $sPassword = $oBxTemplServiceAccount->generateUserNewPwd($iAccountId);
+
+        $oKey->removeKey($sKey);
+
+        $aPlus = array ('password' => $sPassword);
+        $aTemplate = BxDolEmailTemplates::getInstance() -> parseTemplate('bx_api_password_reset', $aPlus, $iAccountId);
+
+        $oAccountQuery->unlockAccount($iAccountId);
+
+        if ($aTemplate && sendMail($aData['email'], $aTemplate['Subject'], $aTemplate['Body'], 0, $aPlus, BX_EMAIL_SYSTEM)) {
+            return array(
+                'code' => 200,
+                'password' => $sPassword,
+            );
+        }
+    }
+    
+    /**
+     * @page public_api API Public
+     * @section public_api_api_create_account /m/oauth2/com/create_account
+     * 
+     * Create account
+     * 
+     * **Scopes:** 
+     * `api`
+     *
+     * **HTTP Method:** 
+     * `POST`
+     *
+     * **Request params:**
+     * - `name` - account name
+     * - `email` - email address
+     * - `password` - password
+     *
+     * **Request header:**
+     * @code
+     * Authorization: Bearer 9802c4a34e1535d8c3b721604ee0e7fb04116c49
+     * @endcode
+     *
+     * **Response (success):**
+     * @code
+     * {  
+     *     "code": 200,
+     *     "profile_id" : "[PROFILE ID]"
+     * }
+     * @endcode
+     *
+     * **Response (error):**
+     * @code
+     * {  
+     *    "error":"short error description here",
+     *    "error_description":"long error description here"
+     * }
+     * @endcode
+     */
+    public function serviceCreateAccount()
+	{
+		
+		$sAccountName = bx_get('name');
+		$sEmail = bx_get('email');
+		$sPassword = bx_get('password');
+		
+        if (!($sAccountName && $sEmail && $sPassword)){
+			return array(
+                'code' => 404,
+                'error' => 'No Content',
+                'desc' => 'Account name, email, password code can\'t be empty',
+            );
+		}
+		
+		$oAccQuery = BxDolAccountQuery::getInstance();;
+		$iId = $oAccQuery->getIdByEmail($sEmail);
+		if ($iId > 0){
+			return array(
+                'code' => 404,
+                'error' => 'Already exists',
+                'desc' => 'Account with requested email already exists',
+            );
+		}
+
+		$_POST['name'] = $sAccountName;
+		$_POST['email'] = $sEmail;
+		$_POST['password'] = $sPassword;
+		$_POST['email_confirmed'] = false;
+		$_POST['do_submit'] = 'Submit';
+
+		$oForm = BxDolForm::getObjectInstance('bx_accounts_account', 'bx_accounts_account_create');
+		$oForm->aParams['csrf']['disable'] = true;
+		$oForm->initChecker();
+		
+		if($oForm->isSubmittedAndValid()) {
+			$iAccountId = $oForm->insert();			
+			if (!$iAccountId) {
+				return $this->_error(_t('_sg_wtv_error_account_creation_failed'), 150);
+			}
+
+			$oBxTemplAccountForms = new BxTemplAccountForms();
+
+			$iProfileId = $oBxTemplAccountForms->onAccountCreated($iAccountId, $oForm->isSetPendingApproval(), BX_PROFILE_ACTION_MANUAL, false);
+
+			$sProfileModule = getParam('sys_account_default_profile_type');
+			if (getParam('sys_account_auto_profile_creation') && !empty($sProfileModule)) {
+				$oAccount = BxDolAccount::getInstance($iAccountId);
+				$aProfileInfo = BxDolService::call($sProfileModule, 'prepare_fields', array(array(
+					'author' => $iProfileId,
+					'name' => $oAccount->getDisplayName(),
+					)));
+				$a = BxDolService::call($sProfileModule, 'entity_add', array($iProfileId, $aProfileInfo));
+				if ($a['code'] != 0)
+					return $this->_error($a['message']);
+				$iProfileId = $a['content']['profile_id'];
+			}
+            
+			return array(
+				'code' => 200,
+				'profile_id' => $iProfileId
+			);
+		}
+		else{
+			$s = $oForm->getFormErrors();
+			return array(
+                'code' => 500,
+                'error' => 'Internal Error',
+                'desc' => $s,
+            );
+		}
+	}
+}
+
+/** @} */

+ 70 - 0
modules/boonex/api/updates/12.0.0_12.0.1/source/install/config.php

@@ -0,0 +1,70 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    API API to the UNA backend
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_api',
+    'title' => 'API',
+    'note' => 'API for backend.',
+    'version' => '12.0.1',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '12.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/api/',
+    'home_uri' => 'api',
+
+    'db_prefix' => 'bx_api_',
+    'class_prefix' => 'BxApi',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'API',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_languages' => 1,
+    ),
+    'uninstall' => array (
+        'execute_sql' => 1,
+        'update_languages' => 1,
+    ),
+    'enable' => array(
+        'execute_sql' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable' => array(
+        'execute_sql' => 1,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Dependencies Section
+     */
+    'dependencies' => array(
+        'oauth2' => 'BoonEx OAuth2 Server Module'
+    ),
+);
+
+/** @} */

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

@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources name="en" flag="gb" title="English">
+    <string name="_sys_module_api"><![CDATA[API]]></string>
+    <string name="_bx_api"><![CDATA[API]]></string>
+
+    <!-- EMAIL TEMPLATES -->
+    <string name="_bx_api_et_txt_name_password_reset"><![CDATA[New password message]]></string>
+    <string name="_bx_api_et_txt_subject_password_reset"><![CDATA[Your new password]]></string>
+    <string name="_bx_api_et_txt_body_password_reset"><![CDATA[{email_header}
+<p>Your new password is:</p>
+<p> </p>
+<p><b>{password}</b></p>
+<p> </p>
+{email_footer}]]></string>
+</resources>

+ 3 - 0
modules/boonex/api/updates/12.0.0_12.0.1/source/install/sql/disable.sql

@@ -0,0 +1,3 @@
+
+-- EMAIL TEMPLATES
+DELETE FROM `sys_email_templates` WHERE `Module` = 'bx_api';

+ 4 - 0
modules/boonex/api/updates/12.0.0_12.0.1/source/install/sql/enable.sql

@@ -0,0 +1,4 @@
+
+-- EMAIL TEMPLATES
+INSERT INTO `sys_email_templates` (`Module`, `NameSystem`, `Name`, `Subject`, `Body`) VALUES 
+('bx_api', '_bx_api_et_txt_name_password_reset', 'bx_api_password_reset', '_bx_api_et_txt_subject_password_reset', '_bx_api_et_txt_body_password_reset');

Разница между файлами не показана из-за своего большого размера
+ 8 - 0
modules/boonex/api/updates/12.0.0_12.0.1/source/template/images/icons/std-icon.svg


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

@@ -0,0 +1,51 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'title' => 'Events',
+    'version_from' => '12.0.0',
+    'version_to' => '12.0.1',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '12.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_12.0.0_12.0.1/',
+    'home_uri' => 'events_update_1200_1201',
+
+    'module_dir' => 'boonex/events/',
+    'module_uri' => 'events',
+
+    'db_prefix' => 'bx_events_',
+    'class_prefix' => 'BxEvents',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 0,
+        'update_files' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 0,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Events',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

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

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

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

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

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

@@ -0,0 +1,152 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Events Events
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_events',
+    'title' => 'Events',
+    'note' => 'Events functionality.',
+    'version' => '12.0.1',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '12.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',
+    ),
+);
+
+/** @} */

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

@@ -0,0 +1,495 @@
+<?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_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[Join confirmation]]></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_entry_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_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_acl_action_create_profile"><![CDATA[Create Event]]></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_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_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_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_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[Favorives Events]]></string>
+    <string name="_bx_events_page_title_entries_favorites"><![CDATA[Favorives 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_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_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_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_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_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_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_view_profile_submenu_cover"><![CDATA[Event Cover 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_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_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_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_grid_filter_item_title_adm_select_one_filter1"><![CDATA[All Statuses]]></string>
+    <string name="_bx_events_grid_filter_item_title_adm_active"><![CDATA[Active]]></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_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_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_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_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 />
+    Location: <span class="location">{EntryLocation}</span>
+</p>
+{email_footer}]]></string>
+</resources>

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

@@ -0,0 +1,51 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'title' => 'Files',
+    'version_from' => '12.0.0',
+    'version_to' => '12.0.1',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '12.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_12.0.0_12.0.1/',
+    'home_uri' => 'files_update_1200_1201',
+
+    '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' => 1,
+        'clear_db_cache' => 0,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Files',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

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

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

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

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

+ 135 - 0
modules/boonex/files/updates/12.0.0_12.0.1/source/install/config.php

@@ -0,0 +1,135 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Files Files
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_files',
+    'title' => 'Files',
+    'note' => 'Basic blogging module.',
+    'version' => '12.0.1',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '12.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',
+    ),
+
+);
+
+/** @} */

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

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

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

@@ -0,0 +1,51 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'title' => 'Discussions',
+    'version_from' => '12.0.0',
+    'version_to' => '12.0.1',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '12.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_12.0.0_12.0.1/',
+    'home_uri' => 'forum_update_1200_1201',
+
+    '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(),
+);

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

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

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

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

+ 4 - 0
modules/boonex/forum/updates/12.0.0_12.0.1/install/sql/install.sql

@@ -0,0 +1,4 @@
+SET @sName = 'bx_forum';
+
+-- STORAGES & TRANSCODERS
+UPDATE `sys_objects_storage` SET `ext_mode`='allow-deny', `ext_allow`='jpg,jpeg,jpe,gif,png', `ext_deny`='' WHERE `object`='bx_forum_covers';

+ 136 - 0
modules/boonex/forum/updates/12.0.0_12.0.1/source/install/config.php

@@ -0,0 +1,136 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Forum Forum
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_forum',
+    'title' => 'Discussions',
+    'note' => 'Discussions module.',
+    'version' => '12.0.1',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '12.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_preview_cmts',
+        'bx_forum_gallery',
+        'bx_forum_cover'
+    ),
+
+    /**
+     * Extended Search Forms.
+     */
+    'esearches' => array(
+        'bx_forum',
+    	'bx_forum_cmts',
+    ),
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'uninstall' => array (
+    	'process_esearches' => 1,
+        'execute_sql' => 1,
+        'update_languages' => 1,
+    	'update_relations' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'enable' => array(
+        'execute_sql' => 1,
+    	'update_relations' => 1,
+        'clear_db_cache' => 1,
+    ),
+	'enable_success' => array(
+    	'process_menu_triggers' => 1,
+        'process_page_triggers' => 1,
+    	'process_esearches' => 1,
+    	'register_transcoders' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable' => array (
+        'execute_sql' => 1,
+    	'update_relations' => 1,
+    	'unregister_transcoders' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable_failed' => array (
+    	'register_transcoders' => 1,
+    	'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Dependencies Section
+     */
+    'dependencies' => array(),
+
+    /**
+     * Relations Section
+     */
+    'relations' => array(
+    	'bx_timeline',
+    	'bx_notifications'
+    ),
+);
+
+/** @} */

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

@@ -0,0 +1,369 @@
+<?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_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_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_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_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_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_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_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_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_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_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[Favorives Discussions]]></string>
+    <string name="_bx_forum_page_title_entries_favorites"><![CDATA[Favorives 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_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_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[Latest]]></string>
+    <string name="_bx_forum_menu_item_title_entries_public"><![CDATA[Latest]]></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_grid_filter_item_title_adm_select_one_filter1"><![CDATA[All Statuses]]></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_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_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_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_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_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>

+ 561 - 0
modules/boonex/forum/updates/12.0.0_12.0.1/source/install/sql/install.sql

@@ -0,0 +1,561 @@
+SET @sName = 'bx_forum';
+SET @sStorageEngine = (SELECT `value` FROM `sys_options` WHERE `name` = 'sys_storage_default');
+
+-- TABLE: entries
+CREATE TABLE IF NOT EXISTS `bx_forum_discussions` (
+  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+  `author` int(11) NOT NULL,
+  `added` int(11) NOT NULL,
+  `changed` int(11) NOT NULL,
+  `thumb` int(11) NOT NULL,
+  `title` varchar(255) NOT NULL,
+  `cat` int(11) NOT NULL,
+  `multicat` text NOT NULL,
+  `text` mediumtext NOT NULL,
+  `text_comments` mediumtext NOT NULL,
+  `lr_timestamp` int(11) NOT NULL,
+  `lr_profile_id` int(11) NOT NULL,
+  `lr_comment_id` int(11) NOT NULL,
+  `labels` text NOT NULL,
+  `views` int(11) NOT NULL default '0',
+  `rate` float NOT NULL default '0',
+  `votes` int(11) NOT NULL default '0',
+  `rrate` float NOT NULL default '0',
+  `rvotes` int(11) NOT NULL default '0',
+  `score` int(11) NOT NULL default '0',
+  `sc_up` int(11) NOT NULL default '0',
+  `sc_down` int(11) NOT NULL default '0',
+  `favorites` int(11) NOT NULL default '0',
+  `comments` int(11) NOT NULL default '0',
+  `reports` int(11) NOT NULL default '0',
+  `featured` int(11) NOT NULL default '0',
+  `stick` tinyint(4) NOT NULL DEFAULT '0',
+  `lock` tinyint(4) NOT NULL DEFAULT '0',
+  `allow_view_to` varchar(16) NOT NULL DEFAULT '3',
+  `status` enum('active','hidden') NOT NULL DEFAULT 'active',
+  `status_admin` enum('active','hidden') NOT NULL DEFAULT 'active',
+  PRIMARY KEY (`id`),
+  FULLTEXT KEY `title_text` (`title`,`text`,`text_comments`),
+  KEY `lr_timestamp` (`lr_timestamp`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_forum_categories` (
+  `category` int(11) NOT NULL default '0',
+  `visible_for_levels` int(11) NOT NULL default '2147483647',
+  PRIMARY KEY (`category`)
+);
+
+-- TABLE: storages & transcoders
+CREATE TABLE IF NOT EXISTS `bx_forum_covers` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `profile_id` int(10) unsigned NOT NULL,
+  `remote_id` varchar(128) NOT NULL,
+  `path` varchar(255) NOT NULL,
+  `file_name` varchar(255) NOT NULL,
+  `mime_type` varchar(128) NOT NULL,
+  `ext` varchar(32) NOT NULL,
+  `size` bigint(20) NOT NULL,
+  `added` int(11) NOT NULL,
+  `modified` int(11) NOT NULL,
+  `private` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `remote_id` (`remote_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_forum_files` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `profile_id` int(10) unsigned NOT NULL,
+  `remote_id` varchar(128) NOT NULL,
+  `path` varchar(255) NOT NULL,
+  `file_name` varchar(255) NOT NULL,
+  `mime_type` varchar(128) NOT NULL,
+  `ext` varchar(32) NOT NULL,
+  `size` bigint(20) NOT NULL,
+  `added` int(11) NOT NULL,
+  `modified` int(11) NOT NULL,
+  `private` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `remote_id` (`remote_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_forum_photos` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `profile_id` int(10) unsigned NOT NULL,
+  `remote_id` varchar(128) NOT NULL,
+  `path` varchar(255) NOT NULL,
+  `file_name` varchar(255) NOT NULL,
+  `mime_type` varchar(128) NOT NULL,
+  `ext` varchar(32) NOT NULL,
+  `size` bigint(20) NOT NULL,
+  `added` int(11) NOT NULL,
+  `modified` int(11) NOT NULL,
+  `private` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `remote_id` (`remote_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_forum_photos_resized` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `profile_id` int(10) unsigned NOT NULL,
+  `remote_id` varchar(128) NOT NULL,
+  `path` varchar(255) NOT NULL,
+  `file_name` varchar(255) NOT NULL,
+  `mime_type` varchar(128) NOT NULL,
+  `ext` varchar(32) NOT NULL,
+  `size` bigint(20) NOT NULL,
+  `added` int(11) NOT NULL,
+  `modified` int(11) NOT NULL,
+  `private` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `remote_id` (`remote_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_forum_videos` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `profile_id` int(10) unsigned NOT NULL,
+  `remote_id` varchar(128) NOT NULL,
+  `path` varchar(255) NOT NULL,
+  `file_name` varchar(255) NOT NULL,
+  `mime_type` varchar(128) NOT NULL,
+  `ext` varchar(32) NOT NULL,
+  `size` bigint(20) NOT NULL,
+  `added` int(11) NOT NULL,
+  `modified` int(11) NOT NULL,
+  `private` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `remote_id` (`remote_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_forum_videos_resized` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `profile_id` int(10) unsigned NOT NULL,
+  `remote_id` varchar(128) NOT NULL,
+  `path` varchar(255) NOT NULL,
+  `file_name` varchar(255) NOT NULL,
+  `mime_type` varchar(128) NOT NULL,
+  `ext` varchar(32) NOT NULL,
+  `size` bigint(20) NOT NULL,
+  `added` int(11) NOT NULL,
+  `modified` int(11) NOT NULL,
+  `private` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `remote_id` (`remote_id`)
+);
+
+-- TABLE: subscribers
+CREATE TABLE IF NOT EXISTS `bx_forum_subscribers` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `initiator` int(11) NOT NULL,
+  `content` int(11) NOT NULL,
+  `added` int(10) unsigned NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `initiator` (`initiator`,`content`),
+  KEY `content` (`content`)
+);
+
+-- TABLE: comments
+CREATE TABLE IF NOT EXISTS `bx_forum_cmts` (
+  `cmt_id` int(11) NOT NULL AUTO_INCREMENT,
+  `cmt_parent_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_vparent_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_object_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_author_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_level` int(11) NOT NULL DEFAULT '0',
+  `cmt_text` text NOT NULL,
+  `cmt_mood` tinyint(4) NOT NULL DEFAULT '0',
+  `cmt_rate` int(11) NOT NULL DEFAULT '0',
+  `cmt_rate_count` int(11) NOT NULL DEFAULT '0',
+  `cmt_time` int(11) unsigned NOT NULL DEFAULT '0',
+  `cmt_replies` int(11) NOT NULL DEFAULT '0',
+  `cmt_pinned` int(11) NOT NULL default '0',
+  PRIMARY KEY (`cmt_id`),
+  KEY `cmt_object_id` (`cmt_object_id`,`cmt_parent_id`),
+  FULLTEXT KEY `search_fields` (`cmt_text`)
+);
+
+-- TABLE: views
+CREATE TABLE `bx_forum_views_track` (
+  `object_id` int(11) NOT NULL default '0',
+  `viewer_id` int(11) NOT NULL default '0',
+  `viewer_nip` int(11) unsigned NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  KEY `id` (`object_id`,`viewer_id`,`viewer_nip`)
+);
+
+-- TABLE: votes
+CREATE TABLE IF NOT EXISTS `bx_forum_votes` (
+  `object_id` int(11) NOT NULL default '0',
+  `count` int(11) NOT NULL default '0',
+  `sum` int(11) NOT NULL default '0',
+  UNIQUE KEY `object_id` (`object_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_forum_votes_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `author_nip` int(11) unsigned NOT NULL default '0',
+  `value` tinyint(4) NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `vote` (`object_id`, `author_nip`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_forum_reactions` (
+  `object_id` int(11) NOT NULL default '0',
+  `reaction` varchar(32) NOT NULL default '',
+  `count` int(11) NOT NULL default '0',
+  `sum` int(11) NOT NULL default '0',
+  UNIQUE KEY `reaction` (`object_id`, `reaction`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_forum_reactions_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `author_nip` int(11) unsigned NOT NULL default '0',
+  `reaction` varchar(32) NOT NULL default '',
+  `value` tinyint(4) NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `vote` (`object_id`, `author_nip`)
+);
+
+-- TABLE: metas
+CREATE TABLE `bx_forum_meta_keywords` (
+  `object_id` int(10) unsigned NOT NULL,
+  `keyword` varchar(255) NOT NULL,
+  KEY `object_id` (`object_id`),
+  KEY `keyword` (`keyword`)
+);
+
+CREATE TABLE `bx_forum_meta_mentions` (
+  `object_id` int(10) unsigned NOT NULL,
+  `profile_id` int(10) unsigned NOT NULL,
+  KEY `object_id` (`object_id`),
+  KEY `profile_id` (`profile_id`)
+);
+
+-- TABLE: reports
+CREATE TABLE IF NOT EXISTS `bx_forum_reports` (
+  `object_id` int(11) NOT NULL default '0',
+  `count` int(11) NOT NULL default '0',
+  UNIQUE KEY `object_id` (`object_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_forum_reports_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `author_nip` int(11) unsigned NOT NULL default '0',
+  `type` varchar(32) NOT NULL default '',
+  `text` text NOT NULL default '',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `report` (`object_id`, `author_nip`)
+);
+
+-- TABLES: favorites
+CREATE TABLE `bx_forum_favorites_track` (
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `list_id` int(11) NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  KEY `id` (`object_id`,`author_id`)
+);
+
+CREATE TABLE `bx_forum_favorites_lists` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `title` varchar(255) NOT NULL,
+  `author_id` int(11) NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  `allow_view_favorite_list_to` varchar(16) NOT NULL DEFAULT '3',
+   PRIMARY KEY (`id`)
+);
+
+-- TABLE: scores
+CREATE TABLE IF NOT EXISTS `bx_forum_scores` (
+  `object_id` int(11) NOT NULL default '0',
+  `count_up` int(11) NOT NULL default '0',
+  `count_down` int(11) NOT NULL default '0',
+  UNIQUE KEY `object_id` (`object_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_forum_scores_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `author_nip` int(11) unsigned NOT NULL default '0',
+  `type` varchar(8) NOT NULL default '',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `vote` (`object_id`, `author_nip`)
+);
+
+-- TABLE: polls
+CREATE TABLE IF NOT EXISTS `bx_forum_polls` (
+  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+  `author_id` int(11) NOT NULL default '0',
+  `content_id` int(11) NOT NULL default '0',
+  `text` text NOT NULL,
+  PRIMARY KEY (`id`),
+  KEY `content_id` (`content_id`),
+  FULLTEXT KEY `search_fields` (`text`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_forum_polls_answers` (
+  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+  `poll_id` int(11) unsigned NOT NULL default '0',
+  `title` varchar(255) NOT NULL,
+  `rate` float NOT NULL default '0',
+  `votes` int(11) NOT NULL default '0',
+  `order` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `poll_id` (`poll_id`),
+  FULLTEXT KEY `title` (`title`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_forum_polls_answers_votes` (
+  `object_id` int(11) NOT NULL default '0',
+  `count` int(11) NOT NULL default '0',
+  `sum` int(11) NOT NULL default '0',
+  UNIQUE KEY `object_id` (`object_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_forum_polls_answers_votes_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `author_nip` int(11) unsigned NOT NULL default '0',
+  `value` tinyint(4) NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `vote` (`object_id`, `author_nip`)
+);
+
+
+-- STORAGES & TRANSCODERS
+INSERT INTO `sys_objects_storage` (`object`, `engine`, `params`, `token_life`, `cache_control`, `levels`, `table_files`, `ext_mode`, `ext_allow`, `ext_deny`, `quota_size`, `current_size`, `quota_number`, `current_number`, `max_file_size`, `ts`) VALUES
+('bx_forum_covers', @sStorageEngine, '', 360, 2592000, 3, 'bx_forum_covers', 'allow-deny', 'jpg,jpeg,jpe,gif,png', '', 0, 0, 0, 0, 0, 0),
+
+('bx_forum_photos', @sStorageEngine, '', 360, 2592000, 3, 'bx_forum_photos', 'allow-deny', 'jpg,jpeg,jpe,gif,png', '', 0, 0, 0, 0, 0, 0),
+('bx_forum_photos_resized', @sStorageEngine, '', 360, 2592000, 3, 'bx_forum_photos_resized', 'allow-deny', 'jpg,jpeg,jpe,gif,png', '', 0, 0, 0, 0, 0, 0),
+
+('bx_forum_videos', @sStorageEngine, '', 360, 2592000, 3, 'bx_forum_videos', 'allow-deny', 'avi,flv,mpg,mpeg,wmv,mp4,m4v,mov,qt,divx,xvid,3gp,3g2,webm,mkv,ogv,ogg,rm,rmvb,asf,drc', '', 0, 0, 0, 0, 0, 0),
+('bx_forum_videos_resized', @sStorageEngine, '', 360, 2592000, 3, 'bx_forum_videos_resized', 'allow-deny', 'jpg,jpeg,jpe,gif,png,avi,flv,mpg,mpeg,wmv,mp4,m4v,mov,qt,divx,xvid,3gp,3g2,webm,mkv,ogv,ogg,rm,rmvb,asf,drc', '', 0, 0, 0, 0, 0, 0),
+
+('bx_forum_files', @sStorageEngine, '', 360, 2592000, 3, 'bx_forum_files', 'deny-allow', '', 'action,apk,app,bat,bin,cmd,com,command,cpl,csh,exe,gadget,inf,ins,inx,ipa,isu,job,jse,ksh,lnk,msc,msi,msp,mst,osx,out,paf,pif,prg,ps1,reg,rgs,run,sct,shb,shs,u3p,vb,vbe,vbs,vbscript,workflow,ws,wsf', 0, 0, 0, 0, 0, 0),
+
+-- For Comments
+('bx_forum_files_cmts', @sStorageEngine, '', 360, 2592000, 3, 'bx_forum_files', 'deny-allow', '', 'action,apk,app,bat,bin,cmd,com,command,cpl,csh,exe,gadget,inf,ins,inx,ipa,isu,job,jse,ksh,lnk,msc,msi,msp,mst,osx,out,paf,pif,prg,ps1,reg,rgs,run,sct,shb,shs,u3p,vb,vbe,vbs,vbscript,workflow,ws,wsf', 0, 0, 0, 0, 0, 0);
+
+INSERT INTO `sys_objects_transcoder` (`object`, `storage_object`, `source_type`, `source_params`, `private`, `atime_tracking`, `atime_pruning`, `ts`, `override_class_name`, `override_class_file`) VALUES 
+('bx_forum_preview', 'bx_forum_photos_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_forum_covers";}', 'no', '1', '2592000', '0', '', ''),
+('bx_forum_gallery', 'bx_forum_photos_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_forum_covers";}', 'no', '1', '2592000', '0', '', ''),
+('bx_forum_cover', 'bx_forum_photos_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_forum_covers";}', 'no', '1', '2592000', '0', '', ''),
+
+('bx_forum_preview_photos', 'bx_forum_photos_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_forum_photos";}', 'no', '1', '2592000', '0', '', ''),
+('bx_forum_gallery_photos', 'bx_forum_photos_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_forum_photos";}', 'no', '1', '2592000', '0', '', ''),
+
+('bx_forum_videos_poster', 'bx_forum_videos_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_forum_videos";}', 'no', '0', '0', '0', 'BxDolTranscoderVideo', ''),
+('bx_forum_videos_poster_preview', 'bx_forum_videos_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_forum_videos";}', 'no', '0', '0', '0', 'BxDolTranscoderVideo', ''),
+('bx_forum_videos_mp4', 'bx_forum_videos_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_forum_videos";}', 'no', '0', '0', '0', 'BxDolTranscoderVideo', ''),
+('bx_forum_videos_mp4_hd', 'bx_forum_videos_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_forum_videos";}', 'no', '0', '0', '0', 'BxDolTranscoderVideo', ''),
+
+('bx_forum_preview_files', 'bx_forum_photos_resized', 'Storage', 'a:1:{s:6:"object";s:14:"bx_forum_files";}', 'no', '1', '2592000', '0', '', ''),
+('bx_forum_gallery_files', 'bx_forum_photos_resized', 'Storage', 'a:1:{s:6:"object";s:14:"bx_forum_files";}', 'no', '1', '2592000', '0', '', ''),
+
+-- For Comments
+('bx_forum_preview_cmts', 'bx_forum_photos_resized', 'Storage', 'a:1:{s:6:"object";s:19:"bx_forum_files_cmts";}', 'no', '1', '2592000', '0', '', '');
+
+INSERT INTO `sys_transcoder_filters` (`transcoder_object`, `filter`, `filter_params`, `order`) VALUES 
+('bx_forum_preview', 'Resize', 'a:3:{s:1:"w";s:3:"300";s:1:"h";s:3:"200";s:11:"crop_resize";s:1:"1";}', '0'),
+('bx_forum_gallery', 'Resize', 'a:1:{s:1:"w";s:3:"500";}', '0'),
+('bx_forum_cover', 'Resize', 'a:1:{s:1:"w";s:4:"2000";}', '0'),
+
+('bx_forum_preview_photos', 'Resize', 'a:3:{s:1:"w";s:3:"300";s:1:"h";s:3:"200";s:11:"crop_resize";s:1:"1";}', '0'),
+('bx_forum_gallery_photos', 'Resize', 'a:1:{s:1:"w";s:4:"2000";}', '0'),
+
+('bx_forum_videos_poster_preview', 'Resize', 'a:3:{s:1:"w";s:3:"300";s:1:"h";s:3:"200";s:13:"square_resize";s:1:"1";}', 10),
+('bx_forum_videos_poster_preview', 'Poster', 'a:2:{s:1:"h";s:3:"480";s:10:"force_type";s:3:"jpg";}', 0),
+('bx_forum_videos_poster', 'Poster', 'a:2:{s:1:"h";s:3:"318";s:10:"force_type";s:3:"jpg";}', 0),
+('bx_forum_videos_mp4', 'Mp4', 'a:2:{s:1:"h";s:3:"318";s:10:"force_type";s:3:"mp4";}', 0),
+('bx_forum_videos_mp4_hd', 'Mp4', 'a:3:{s:1:"h";s:3:"720";s:13:"video_bitrate";s:4:"1536";s:10:"force_type";s:3:"mp4";}', 0),
+
+('bx_forum_preview_files', 'Resize', 'a:3:{s:1:"w";s:3:"300";s:1:"h";s:3:"200";s:11:"crop_resize";s:1:"1";}', '0'),
+('bx_forum_gallery_files', 'Resize', 'a:1:{s:1:"w";s:3:"500";}', '0'),
+
+-- For Comments
+('bx_forum_preview_cmts', 'Resize', 'a:4:{s:1:"w";s:3:"100";s:1:"h";s:3:"100";s:13:"square_resize";s:1:"1";s:10:"force_type";s:3:"jpg";}', '0');
+
+
+-- FORMS
+INSERT INTO `sys_objects_form`(`object`, `module`, `title`, `action`, `form_attrs`, `table`, `key`, `uri`, `uri_title`, `submit_name`, `params`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+(@sName, @sName, '_bx_forum_form_entry', '', 'a:1:{s:7:\"enctype\";s:19:\"multipart/form-data\";}', 'bx_forum_discussions', 'id', '', '', 'do_submit', '', 0, 1, 'BxForumFormEntry', 'modules/boonex/forum/classes/BxForumFormEntry.php'),
+('bx_forum_search', @sName, '_bx_forum_form_search', '', 'a:1:{s:7:\"enctype\";s:19:\"multipart/form-data\";}', 'bx_forum_discussions', 'id', '', '', 'do_submit', '', 0, 1, 'BxForumFormSearch', 'modules/boonex/forum/classes/BxForumFormSearch.php');
+
+INSERT INTO `sys_form_displays`(`object`, `display_name`, `module`, `view_mode`, `title`) VALUES 
+(@sName, 'bx_forum_entry_add', @sName, 0, '_bx_forum_form_entry_display_add'),
+(@sName, 'bx_forum_entry_delete', @sName, 0, '_bx_forum_form_entry_display_delete'),
+(@sName, 'bx_forum_entry_edit', @sName, 0, '_bx_forum_form_entry_display_edit'),
+(@sName, 'bx_forum_entry_view', @sName, 1, '_bx_forum_form_entry_display_view'),
+
+('bx_forum_search', 'bx_forum_search_full', @sName, 0, '_bx_forum_form_search_display_full');
+
+INSERT INTO `sys_form_inputs`(`object`, `module`, `name`, `value`, `values`, `checked`, `type`, `caption_system`, `caption`, `info`, `required`, `collapsed`, `html`, `attrs`, `attrs_tr`, `attrs_wrapper`, `checker_func`, `checker_params`, `checker_error`, `db_pass`, `db_params`, `editable`, `deletable`) VALUES
+(@sName, @sName, 'allow_view_to', '', '', 0, 'custom', '_bx_forum_form_entry_input_sys_allow_view_to', '_bx_forum_form_entry_input_allow_view_to', '', 1, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+(@sName, @sName, 'delete_confirm', 1, '', 0, 'checkbox', '_bx_forum_form_entry_input_sys_delete_confirm', '_bx_forum_form_entry_input_delete_confirm', '_bx_forum_form_entry_input_delete_confirm_info', 1, 0, 0, '', '', '', 'Avail', '', '_bx_forum_form_entry_input_delete_confirm_error', '', '', 1, 0),
+(@sName, @sName, 'do_submit', '_bx_forum_form_entry_input_do_submit', '', 0, 'submit', '_bx_forum_form_entry_input_sys_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+(@sName, @sName, 'text', '', '', 0, 'textarea', '_bx_forum_form_entry_input_sys_text', '_bx_forum_form_entry_input_text', '', 1, 0, 2, '', '', '', 'Avail', '', '_bx_forum_form_entry_input_text_err', 'XssHtml', '', 1, 0),
+(@sName, @sName, 'title', '', '', 0, 'text', '_bx_forum_form_entry_input_sys_title', '_bx_forum_form_entry_input_title', '', 1, 0, 0, '', '', '', 'Avail', '', '_bx_forum_form_entry_input_title_err', 'Xss', '', 1, 0),
+(@sName, @sName, 'cat', '', '#!bx_forum_cats', 0, 'select', '_bx_forum_form_entry_input_sys_cat', '_bx_forum_form_entry_input_cat', '', 1, 0, 0, '', '', '', 'avail', '', '_bx_forum_form_entry_input_cat_err', 'Xss', '', 1, 0),
+(@sName, @sName, 'multicat', '', '', 0, 'custom', '_bx_forum_form_entry_input_sys_multicat', '_bx_forum_form_entry_input_multicat', '', 1, 0, 0, '', '', '', 'avail', '', '_bx_forum_form_entry_input_multicat_err', 'Xss', '', 1, 0),
+(@sName, @sName, 'attachments', '', '', 0, 'custom', '_bx_forum_form_entry_input_sys_attachments', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+(@sName, @sName, 'covers', 'a:1:{i:0;s:14:"bx_forum_html5";}', 'a:2:{s:15:"bx_forum_simple";s:26:"_sys_uploader_simple_title";s:14:"bx_forum_html5";s:25:"_sys_uploader_html5_title";}', 0, 'files', '_bx_forum_form_entry_input_sys_covers', '_bx_forum_form_entry_input_covers', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+(@sName, @sName, 'pictures', 'a:1:{i:0;s:21:"bx_forum_photos_html5";}', 'a:2:{s:22:"bx_forum_photos_simple";s:26:"_sys_uploader_simple_title";s:21:"bx_forum_photos_html5";s:25:"_sys_uploader_html5_title";}', 0, 'files', '_bx_forum_form_entry_input_sys_pictures', '_bx_forum_form_entry_input_pictures', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+(@sName, @sName, 'videos', 'a:2:{i:0;s:21:"bx_forum_videos_html5";i:1;s:28:"bx_forum_videos_record_video";}', 'a:3:{s:22:"bx_forum_videos_simple";s:26:"_sys_uploader_simple_title";s:21:"bx_forum_videos_html5";s:25:"_sys_uploader_html5_title";s:28:"bx_forum_videos_record_video";s:32:"_sys_uploader_record_video_title";}', 0, 'files', '_bx_forum_form_entry_input_sys_videos', '_bx_forum_form_entry_input_videos', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+(@sName, @sName, 'files', 'a:1:{i:0;s:20:"bx_forum_files_html5";}', 'a:2:{s:21:"bx_forum_files_simple";s:26:"_sys_uploader_simple_title";s:20:"bx_forum_files_html5";s:25:"_sys_uploader_html5_title";}', 0, 'files', '_bx_forum_form_entry_input_sys_files', '_bx_forum_form_entry_input_files', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+(@sName, @sName, 'polls', '', '', 0, 'custom', '_bx_forum_form_entry_input_sys_polls', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+(@sName, @sName, 'labels', '', '', 0, 'custom', '_sys_form_input_sys_labels', '_sys_form_input_labels', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+(@sName, @sName, 'anonymous', '', '', 0, 'switcher', '_sys_form_input_sys_anonymous', '_sys_form_input_anonymous', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+(@sName, @sName, 'added', '', '', 0, 'datetime', '_bx_forum_form_entry_input_sys_date_added', '_bx_forum_form_entry_input_date_added', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+(@sName, @sName, 'changed', '', '', 0, 'datetime', '_bx_forum_form_entry_input_sys_date_changed', '_bx_forum_form_entry_input_date_changed', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+
+('bx_forum_search', @sName, 'author', '', '', 0, 'custom', '_bx_forum_form_search_input_sys_author', '_bx_forum_form_search_input_author', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_forum_search', @sName, 'category', '', '#!bx_forum_cats', 0, 'select', '_bx_forum_form_search_input_sys_category', '_bx_forum_form_search_input_category', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_forum_search', @sName, 'keyword', '', '', 0, 'text', '_bx_forum_form_search_input_sys_keyword', '_bx_forum_form_search_input_keyword', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_forum_search', @sName, 'do_submit', '_bx_forum_form_search_input_do_submit', '', 0, 'submit', '_bx_forum_form_search_input_sys_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0);
+
+INSERT INTO `sys_form_display_inputs` (`display_name`, `input_name`, `visible_for_levels`, `active`, `order`) VALUES
+('bx_forum_entry_add', 'title', 2147483647, 1, 1),
+('bx_forum_entry_add', 'cat', 2147483647, 1, 2),
+('bx_forum_entry_add', 'text', 2147483647, 1, 3),
+('bx_forum_entry_add', 'attachments', 2147483647, 1, 4),
+('bx_forum_entry_add', 'pictures', 2147483647, 1, 5),
+('bx_forum_entry_add', 'videos', 2147483647, 1, 6),
+('bx_forum_entry_add', 'files', 2147483647, 1, 7),
+('bx_forum_entry_add', 'polls', 2147483647, 1, 8),
+('bx_forum_entry_add', 'covers', 2147483647, 1, 9),
+('bx_forum_entry_add', 'allow_view_to', 2147483647, 1, 10),
+('bx_forum_entry_add', 'do_submit', 2147483647, 1, 11),
+
+('bx_forum_entry_edit', 'title', 2147483647, 1, 1),
+('bx_forum_entry_edit', 'cat', 2147483647, 1, 2),
+('bx_forum_entry_edit', 'text', 2147483647, 1, 3),
+('bx_forum_entry_edit', 'attachments', 2147483647, 1, 4),
+('bx_forum_entry_edit', 'pictures', 2147483647, 1, 5),
+('bx_forum_entry_edit', 'videos', 2147483647, 1, 6),
+('bx_forum_entry_edit', 'files', 2147483647, 1, 7),
+('bx_forum_entry_edit', 'polls', 2147483647, 1, 8),
+('bx_forum_entry_edit', 'covers', 2147483647, 1, 9),
+('bx_forum_entry_edit', 'allow_view_to', 2147483647, 1, 10),
+('bx_forum_entry_edit', 'do_submit', 2147483647, 1, 11),
+
+('bx_forum_entry_view', 'title', 2147483647, 1, 1),
+('bx_forum_entry_view', 'cat', 2147483647, 1, 2),
+('bx_forum_entry_view', 'text', 2147483647, 1, 3),
+
+('bx_forum_entry_delete', 'delete_confirm', 2147483647, 1, 1),
+('bx_forum_entry_delete', 'do_submit', 2147483647, 1, 2),
+
+('bx_forum_search_full', 'author', 2147483647, 1, 1),
+('bx_forum_search_full', 'category', 2147483647, 1, 2),
+('bx_forum_search_full', 'keyword', 2147483647, 1, 3),
+('bx_forum_search_full', 'do_submit', 2147483647, 1, 4);
+
+-- FORMS: poll
+INSERT INTO `sys_objects_form` (`object`, `module`, `title`, `action`, `form_attrs`, `submit_name`, `table`, `key`, `uri`, `uri_title`, `params`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES
+('bx_forum_poll', 'bx_forum', '_bx_forum_form_poll', '', '', 'do_submit', 'bx_forum_polls', 'id', '', '', 'a:1:{s:14:"checker_helper";s:28:"BxForumFormPollCheckerHelper";}', 0, 1, 'BxForumFormPoll', 'modules/boonex/forum/classes/BxForumFormPoll.php');
+
+INSERT INTO `sys_form_displays` (`display_name`, `module`, `object`, `title`, `view_mode`) VALUES
+('bx_forum_poll_add', 'bx_forum', 'bx_forum_poll', '_bx_forum_form_poll_display_add', 0);
+
+INSERT INTO `sys_form_inputs` (`object`, `module`, `name`, `value`, `values`, `checked`, `type`, `caption_system`, `caption`, `info`, `required`, `collapsed`, `html`, `attrs`, `attrs_tr`, `attrs_wrapper`, `checker_func`, `checker_params`, `checker_error`, `db_pass`, `db_params`, `editable`, `deletable`) VALUES
+('bx_forum_poll', 'bx_forum', 'text', '', '', 0, 'text', '_bx_forum_form_poll_input_sys_text', '_bx_forum_form_poll_input_text', '', 1, 0, 0, '', '', '', 'Avail', '', '_bx_forum_form_poll_input_text_err', 'Xss', '', 1, 0),
+('bx_forum_poll', 'bx_forum', 'answers', '', '', 0, 'custom', '_bx_forum_form_poll_input_sys_answers', '_bx_forum_form_poll_input_answers', '', 1, 0, 0, '', '', '', 'AvailAnswers', '', '_bx_forum_form_poll_input_answers_err', '', '', 1, 0),
+('bx_forum_poll', 'bx_forum', 'controls', '', 'do_submit,do_cancel', 0, 'input_set', '', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
+('bx_forum_poll', 'bx_forum', 'do_submit', '_bx_forum_form_poll_input_do_submit', '', 0, 'submit', '_bx_forum_form_poll_input_sys_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
+('bx_forum_poll', 'bx_forum', 'do_cancel', '_bx_forum_form_poll_input_do_cancel', '', 0, 'button', '_bx_forum_form_poll_input_do_cancel', '', '', 0, 0, 0, 'a:2:{s:7:"onclick";s:45:"$(''.bx-popup-applied:visible'').dolPopupHide()";s:5:"class";s:22:"bx-def-margin-sec-left";}', '', '', '', '', '', '', '', 0, 0);
+
+INSERT INTO `sys_form_display_inputs` (`display_name`, `input_name`, `visible_for_levels`, `active`, `order`) VALUES
+('bx_forum_poll_add', 'text', 2147483647, 1, 1),
+('bx_forum_poll_add', 'answers', 2147483647, 1, 2),
+('bx_forum_poll_add', 'controls', 2147483647, 1, 3),
+('bx_forum_poll_add', 'do_submit', 2147483647, 1, 4),
+('bx_forum_poll_add', 'do_cancel', 2147483647, 1, 5);
+
+
+-- PRE-VALUES
+INSERT INTO `sys_form_pre_lists`(`key`, `title`, `module`, `use_for_sets`) VALUES
+('bx_forum_cats', '_bx_forum_pre_lists_cats', 'bx_forum', '0');
+
+INSERT INTO `sys_form_pre_values`(`Key`, `Value`, `Order`, `LKey`, `LKey2`) VALUES
+('bx_forum_cats', '', 0, '_sys_please_select', ''),
+('bx_forum_cats', '1', 1, '_bx_forum_cat_General', '');
+
+
+-- COMMENTS
+INSERT INTO `sys_objects_cmts` (`Name`, `Module`, `Table`, `CharsPostMin`, `CharsPostMax`, `CharsDisplayMax`, `Html`, `PerView`, `PerViewReplies`, `BrowseType`, `IsBrowseSwitch`, `PostFormPosition`, `NumberOfLevels`, `IsDisplaySwitch`, `IsRatable`, `ViewingThreshold`, `IsOn`, `RootStylePrefix`, `BaseUrl`, `ObjectVote`, `TriggerTable`, `TriggerFieldId`, `TriggerFieldAuthor`, `TriggerFieldTitle`, `TriggerFieldComments`, `ClassName`, `ClassFile`) VALUES
+(@sName, @sName, 'bx_forum_cmts', 1, 5000, 1000, 2, 50, 3, 'tail', 0, 'bottom', 1, 1, 1, -3, 1, 'cmt', 'page.php?i=view-discussion&id={object_id}', '', 'bx_forum_discussions', 'id', 'author', 'title', 'comments', 'BxForumCmts', 'modules/boonex/forum/classes/BxForumCmts.php');
+
+
+-- VIEWS
+INSERT INTO `sys_objects_view` (`name`, `table_track`, `period`, `is_on`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_count`, `class_name`, `class_file`) VALUES 
+(@sName, 'bx_forum_views_track', '86400', '1', 'bx_forum_discussions', 'id', 'author', 'views', '', '');
+
+
+-- VOTES
+INSERT INTO `sys_objects_vote` (`Name`, `TableMain`, `TableTrack`, `PostTimeout`, `MinValue`, `MaxValue`, `IsUndo`, `IsOn`, `TriggerTable`, `TriggerFieldId`, `TriggerFieldAuthor`, `TriggerFieldRate`, `TriggerFieldRateCount`, `ClassName`, `ClassFile`) VALUES 
+(@sName, 'bx_forum_votes', 'bx_forum_votes_track', '604800', '1', '1', '0', '1', 'bx_forum_discussions', 'id', 'author', 'rate', 'votes', '', ''),
+('bx_forum_reactions', 'bx_forum_reactions', 'bx_forum_reactions_track', '604800', '1', '1', '1', '1', 'bx_forum_discussions', 'id', 'author', 'rrate', 'rvotes', 'BxTemplVoteReactions', ''),
+('bx_forum_poll_answers', 'bx_forum_polls_answers_votes', 'bx_forum_polls_answers_votes_track', '604800', '1', '1', '0', '1', 'bx_forum_polls_answers', 'id', 'author_id', 'rate', 'votes', 'BxForumVotePollAnswers', 'modules/boonex/forum/classes/BxForumVotePollAnswers.php');
+
+
+-- SCORES
+INSERT INTO `sys_objects_score` (`name`, `module`, `table_main`, `table_track`, `post_timeout`, `is_on`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_score`, `trigger_field_cup`, `trigger_field_cdown`, `class_name`, `class_file`) VALUES 
+(@sName, @sName, 'bx_forum_scores', 'bx_forum_scores_track', '604800', '0', 'bx_forum_discussions', 'id', 'author', 'score', 'sc_up', 'sc_down', '', '');
+
+
+-- FAVORITES
+INSERT INTO `sys_objects_favorite` (`name`, `table_track`, `table_lists`, `is_on`, `is_undo`, `is_public`, `base_url`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_count`, `class_name`, `class_file`) VALUES 
+(@sName, 'bx_forum_favorites_track', 'bx_forum_favorites_lists', '1', '1', '1', 'page.php?i=view-discussion&id={object_id}', 'bx_forum_discussions', 'id', 'author', 'favorites', '', '');
+
+
+-- FEATURED
+INSERT INTO `sys_objects_feature` (`name`, `module`, `is_on`, `is_undo`, `base_url`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_flag`, `class_name`, `class_file`) VALUES 
+(@sName, @sName, '1', '1', 'page.php?i=view-discussion&id={object_id}', 'bx_forum_discussions', 'id', 'author', 'featured', '', '');
+
+
+-- CONTENT INFO
+INSERT INTO `sys_objects_content_info` (`name`, `title`, `alert_unit`, `alert_action_add`, `alert_action_update`, `alert_action_delete`, `class_name`, `class_file`) VALUES
+(@sName, '_bx_forum', @sName, 'added', 'edited', 'deleted', '', ''),
+('bx_forum_cmts', '_bx_forum_cmts', @sName, 'commentPost', 'commentUpdated', 'commentRemoved', 'BxDolContentInfoCmts', '');
+
+INSERT INTO `sys_content_info_grids` (`object`, `grid_object`, `grid_field_id`, `condition`, `selection`) VALUES
+(@sName, @sName, 'id', '', 'a:1:{s:4:"sort";a:2:{s:5:"stick";s:4:"desc";s:12:"lr_timestamp";s:4:"desc";}}'),
+(@sName, 'bx_forum_administration', 'id', '', ''),
+(@sName, 'bx_forum_common', 'id', '', '');
+
+
+-- SEARCH EXTENDED
+INSERT INTO `sys_objects_search_extended` (`object`, `object_content_info`, `module`, `title`, `active`, `class_name`, `class_file`) VALUES
+('bx_forum', 'bx_forum', 'bx_forum', '_bx_forum_search_extended', 1, '', ''),
+('bx_forum_cmts', 'bx_forum_cmts', 'bx_forum', '_bx_forum_search_extended_cmts', 1, 'BxTemplSearchExtendedCmts', '');
+
+
+-- REPORTS
+INSERT INTO `sys_objects_report` (`name`, `module`, `table_main`, `table_track`, `is_on`, `base_url`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_count`, `class_name`, `class_file`) VALUES 
+('bx_forum', 'bx_forum', 'bx_forum_reports', 'bx_forum_reports_track', '1', 'page.php?i=view-discussion&id={object_id}', 'bx_forum_discussions', 'id', 'author', 'reports', '', '');
+
+
+-- STUDIO: page & widget
+INSERT INTO `sys_std_pages`(`index`, `name`, `header`, `caption`, `icon`) VALUES
+(3, @sName, '_bx_forum', '_bx_forum', 'bx_forum@modules/boonex/forum/|std-icon.svg');
+SET @iPageId = LAST_INSERT_ID();
+
+SET @iParentPageId = (SELECT `id` FROM `sys_std_pages` WHERE `name` = 'home');
+SET @iParentPageOrder = (SELECT MAX(`order`) FROM `sys_std_pages_widgets` WHERE `page_id` = @iParentPageId);
+INSERT INTO `sys_std_widgets` (`page_id`, `module`, `type`, `url`, `click`, `icon`, `caption`, `cnt_notices`, `cnt_actions`) VALUES
+(@iPageId, @sName, 'content', '{url_studio}module.php?name=bx_forum', '', 'bx_forum@modules/boonex/forum/|std-icon.svg', '_bx_forum', '', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:11:"get_actions";s:6:"params";a:0:{}s:5:"class";s:18:"TemplStudioModules";}');
+INSERT INTO `sys_std_pages_widgets` (`page_id`, `widget_id`, `order`) VALUES
+(@iParentPageId, LAST_INSERT_ID(), IF(ISNULL(@iParentPageOrder), 1, @iParentPageOrder + 1));

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

@@ -0,0 +1,51 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'title' => 'Glossary',
+    'version_from' => '12.0.0',
+    'version_to' => '12.0.1',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '12.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/glossary/updates/update_12.0.0_12.0.1/',
+    'home_uri' => 'glossary_update_1200_1201',
+
+    'module_dir' => 'boonex/glossary/',
+    'module_uri' => 'glossary',
+
+    'db_prefix' => 'bx_glossary_',
+    'class_prefix' => 'BxGlsr',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 0,
+        'update_files' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 0,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Glossary',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

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

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

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

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

+ 136 - 0
modules/boonex/glossary/updates/12.0.0_12.0.1/source/install/config.php

@@ -0,0 +1,136 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Glossary Glossary
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+
+    /**
+      * Main Section.
+      */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_glossary',
+    'title' => 'Glossary',
+    'note' => 'Glossary module.',
+    'version' => '12.0.1',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '12.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/glossary/',
+    'home_uri' => 'glossary',
+
+    'db_prefix' => 'bx_glossary_',
+    'class_prefix' => 'BxGlsr',
+
+    /**
+      * Category for language keys.
+      */
+    'language_category' => 'Glossary',
+
+    /**
+      * 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_glossary_files'
+    ),
+
+    /**
+      * Transcoders.
+      */
+    'transcoders' => array(
+        'bx_glossary_preview',
+        'bx_glossary_gallery',
+        'bx_glossary_cover'
+    ),
+
+    /**
+      * Extended Search Forms.
+      */
+    'esearches' => array(
+        'bx_glossary',
+        'bx_glossary_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'
+    ),
+
+);
+
+/** @} */

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

@@ -0,0 +1,244 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources name="en" flag="gb" title="English">
+
+	<string name="_bx_glossary"><![CDATA[Glossary]]></string>
+	<string name="_bx_glossary_cmts"><![CDATA[Glossary's Comments]]></string>
+        <string name="_bx_glossary_reactions"><![CDATA[Glossary's Reactions]]></string>
+
+	<string name="_bx_glossary_option_summary_chars"><![CDATA[Number of characters in auto-cropped term summary]]></string>
+	<string name="_bx_glossary_option_plain_summary_chars"><![CDATA[Number of characters in plain term description when term hasn't thumb]]></string>
+	<string name="_bx_glossary_option_per_page_browse"><![CDATA[Number of items per page]]></string>
+	<string name="_bx_glossary_option_per_page_profile"><![CDATA[Number of items on profile/group page]]></string>
+	<string name="_bx_glossary_option_rss_num"><![CDATA[Number of items in RSS feed]]></string>
+	<string name="_bx_glossary_option_searchable_fields"><![CDATA[Searchable fields for keyword search]]></string>
+  <string name="_bx_glossary_option_activate_terms_after_creation"><![CDATA[Activate terms after creation]]></string>
+  <string name="_bx_glossary_option_per_page_for_favorites_lists"><![CDATA[Number of favorite lists per page]]></string>
+
+  <string name="_bx_glossary_form_entry"><![CDATA[Glossary]]></string>
+	<string name="_bx_glossary_form_entry_display_add"><![CDATA[Add Term]]></string>
+	<string name="_bx_glossary_form_entry_display_edit"><![CDATA[Edit Term]]></string>
+	<string name="_bx_glossary_form_entry_display_delete"><![CDATA[Delete Term]]></string>
+	<string name="_bx_glossary_form_entry_display_view"><![CDATA[View Term]]></string>
+	<string name="_bx_glossary_form_entry_input_author"><![CDATA[Author]]></string>
+	<string name="_bx_glossary_form_entry_input_sys_do_submit"><![CDATA[Submit]]></string>
+	<string name="_bx_glossary_form_entry_input_do_submit"><![CDATA[Submit]]></string>
+	<string name="_bx_glossary_form_entry_input_sys_do_publish"><![CDATA[Publish]]></string>
+	<string name="_bx_glossary_form_entry_input_do_publish"><![CDATA[Publish]]></string>
+	<string name="_bx_glossary_form_entry_input_sys_title"><![CDATA[Title]]></string>
+	<string name="_bx_glossary_form_entry_input_title"><![CDATA[Title]]></string>
+	<string name="_bx_glossary_form_entry_input_title_err"><![CDATA[Title is essential. Please, fill in this field]]></string>
+	<string name="_bx_glossary_form_entry_input_sys_cat"><![CDATA[Category]]></string>
+	<string name="_bx_glossary_form_entry_input_cat"><![CDATA[Category]]></string>
+  <string name="_bx_glossary_form_entry_input_cat_err"><![CDATA[Please select category]]></string>
+  <string name="_bx_glossary_form_entry_input_status_admin_error"><![CDATA[Please select status]]></string>
+	<string name="_bx_glossary_form_entry_input_sys_text"><![CDATA[Text]]></string>
+	<string name="_bx_glossary_form_entry_input_text"><![CDATA[Text]]></string>
+	<string name="_bx_glossary_form_entry_input_text_err"><![CDATA[Text field can't be empty]]></string>
+	<string name="_bx_glossary_form_entry_input_sys_delete_confirm"><![CDATA[Delete confirmation]]></string>
+	<string name="_bx_glossary_form_entry_input_delete_confirm"><![CDATA[I am sure I want to delete this term]]></string>
+	<string name="_bx_glossary_form_entry_input_delete_confirm_info"><![CDATA[This action can not be undone]]></string>
+	<string name="_bx_glossary_form_entry_input_delete_confirm_error"><![CDATA[Please check this checkbox if you really want to delete the term]]></string>
+	<string name="_bx_glossary_form_entry_input_sys_pictures"><![CDATA[Pictures]]></string>
+	<string name="_bx_glossary_form_entry_input_pictures"><![CDATA[Pictures]]></string>
+    <string name="_bx_glossary_form_entry_input_sys_allow_view_to"><![CDATA[Visibility]]></string>
+    <string name="_bx_glossary_form_entry_input_allow_view_to"><![CDATA[Visibility]]></string>
+    <string name="_bx_glossary_form_entry_input_allow_view_favorite_list"><![CDATA[Visibility]]></string>
+    <string name="_bx_glossary_form_entry_input_picture_use_as_thumb"><![CDATA[Cover Image]]></string>
+    <string name="_bx_glossary_form_entry_input_sys_date_added"><![CDATA[Created]]></string>
+    <string name="_bx_glossary_form_entry_input_date_added"><![CDATA[Created]]></string>
+    <string name="_bx_glossary_form_entry_input_sys_date_changed"><![CDATA[Updated]]></string>
+    <string name="_bx_glossary_form_entry_input_date_changed"><![CDATA[Updated]]></string>
+    <string name="_bx_glossary_form_entry_input_sys_status_admin"><![CDATA[Status]]></string>
+    <string name="_bx_glossary_form_entry_input_status_admin"><![CDATA[Status]]></string>
+
+	<string name="_bx_glossary_acl_action_create_entry"><![CDATA[Create Term]]></string>
+	<string name="_bx_glossary_acl_action_delete_entry"><![CDATA[Delete Term]]></string>
+	<string name="_bx_glossary_acl_action_view_entry"><![CDATA[View Term]]></string>
+	<string name="_bx_glossary_acl_action_set_thumb"><![CDATA[Set Term Thumbnail]]></string>
+	<string name="_bx_glossary_acl_action_edit_any_entry"><![CDATA[Edit Any Term]]></string>
+
+	<string name="_bx_glossary_page_title_sys_create_entry"><![CDATA[New Term]]></string>
+	<string name="_bx_glossary_page_title_create_entry"><![CDATA[New Term]]></string>
+	<string name="_bx_glossary_page_block_title_create_entry"><![CDATA[New Term]]></string>
+	<string name="_bx_glossary_page_title_sys_edit_entry"><![CDATA[Edit]]></string>
+	<string name="_bx_glossary_page_title_edit_entry"><![CDATA[Edit]]></string>
+	<string name="_bx_glossary_page_block_title_edit_entry"><![CDATA[Edit]]></string>
+    <string name="_bx_glossary_page_title_sys_delete_entry"><![CDATA[Delete]]></string>
+    <string name="_bx_glossary_page_title_delete_entry"><![CDATA[Delete]]></string>
+    <string name="_bx_glossary_page_block_title_delete_entry"><![CDATA[Delete]]></string>
+	<string name="_bx_glossary_page_title_sys_view_entry"><![CDATA[View Term]]></string>
+	<string name="_bx_glossary_page_title_view_entry"><![CDATA[{title}]]></string>
+	<string name="_bx_glossary_page_block_title_entry_text"><![CDATA[Term Text]]></string>
+	<string name="_bx_glossary_page_title_browse"><![CDATA[Glossary]]></string>
+	<string name="_bx_glossary_page_title_search_results"><![CDATA[Terms matching "{0}"]]></string>
+	<string name="_bx_glossary_page_title_browse_by_author"><![CDATA[Terms of {display_name}]]></string>
+  <string name="_bx_glossary_page_title_browse_by_context"><![CDATA[Terms in {display_name}]]></string>
+	<string name="_bx_glossary_page_title_browse_featured"><![CDATA[Featured Terms]]></string>
+    <string name="_bx_glossary_page_title_browse_recent"><![CDATA[Latest Terms]]></string>
+    <string name="_bx_glossary_page_title_browse_popular"><![CDATA[Popular Terms]]></string>
+    <string name="_bx_glossary_page_title_browse_top"><![CDATA[Top Terms]]></string>
+    <string name="_bx_glossary_page_title_browse_alphabetical"><![CDATA[Alphabetical Index]]></string>
+    <string name="_bx_glossary_page_title_browse_updated"><![CDATA[Updated Terms]]></string>
+    <string name="_bx_glossary_page_title_sys_home"><![CDATA[Glossary Home]]></string>
+    <string name="_bx_glossary_page_title_home"><![CDATA[Glossary]]></string>
+    <string name="_bx_glossary_page_block_title_featured_entries_view_extended"><![CDATA[Featured Terms]]></string>
+    <string name="_bx_glossary_page_block_title_featured_entries_view_alphabetical"><![CDATA[Alphabetical Terms]]></string>
+    <string name="_bx_glossary_page_block_title_recent_entries"><![CDATA[Latest Terms (Gallery View)]]></string>
+    <string name="_bx_glossary_page_block_title_recent_entries_view_extended"><![CDATA[Latest Terms]]></string>
+    <string name="_bx_glossary_page_block_title_recent_entries_view_full"><![CDATA[Latest Terms (Full View)]]></string>
+    <string name="_bx_glossary_page_block_title_entry_social_sharing"><![CDATA[Share]]></string>
+    <string name="_bx_glossary_page_block_title_entry_author"><![CDATA[Author]]></string>
+    <string name="_bx_glossary_page_block_title_entry_actions"><![CDATA[Actions]]></string>
+    <string name="_bx_glossary_page_block_title_entry_comments"><![CDATA[Comments]]></string>
+    <string name="_bx_glossary_page_block_title_entry_comments_link"><![CDATA[Comments to <a href="{entry_link}">{title}</a>]]></string>
+    <string name="_bx_glossary_page_block_title_entry_attachments"><![CDATA[Attachments]]></string>
+    <string name="_bx_glossary_page_block_title_entry_all_actions"><![CDATA[All Actions]]></string>
+    <string name="_bx_glossary_page_title_sys_entries_popular"><![CDATA[Popular Terms]]></string>
+    <string name="_bx_glossary_page_title_entries_popular"><![CDATA[Popular Terms]]></string>
+    <string name="_bx_glossary_page_title_sys_entries_top"><![CDATA[Top Terms]]></string>
+    <string name="_bx_glossary_page_title_entries_top"><![CDATA[Top Terms]]></string>
+    <string name="_bx_glossary_page_title_sys_entries_updated"><![CDATA[Updated Terms]]></string>
+    <string name="_bx_glossary_page_title_entries_updated"><![CDATA[Updated Terms]]></string>
+    <string name="_bx_glossary_page_title_sys_entries_search"><![CDATA[Search]]></string>
+    <string name="_bx_glossary_page_title_entries_search"><![CDATA[Search]]></string>
+    <string name="_bx_glossary_page_title_sys_entries_favorites"><![CDATA[Favorives Terms]]></string>
+    <string name="_bx_glossary_page_title_entries_favorites"><![CDATA[Favorives Terms]]></string>
+    <string name="_bx_glossary_page_block_title_search_form"><![CDATA[Search Form]]></string>
+    <string name="_bx_glossary_page_block_title_search_results"><![CDATA[Search Results]]></string>
+    <string name="_bx_glossary_page_block_title_search_form_cmts"><![CDATA[Comments Search Form]]></string>
+    <string name="_bx_glossary_page_block_title_search_results_cmts"><![CDATA[Comments Search Results]]></string>
+    <string name="_bx_glossary_page_block_title_popular_entries"><![CDATA[Popular Terms]]></string>
+    <string name="_bx_glossary_page_block_title_popular_entries_view_extended"><![CDATA[Popular Terms (Extended View)]]></string>
+    <string name="_bx_glossary_page_block_title_popular_entries_view_full"><![CDATA[Popular Terms (Full View)]]></string>
+    <string name="_bx_glossary_page_block_title_top_entries"><![CDATA[Top Terms]]></string>
+    <string name="_bx_glossary_page_block_title_updated_entries"><![CDATA[Updated Terms]]></string>
+    <string name="_bx_glossary_page_block_title_favorites_entries"><![CDATA["{title}" List]]></string>
+    <string name="_bx_glossary_page_block_title_favorites_entries_info"><![CDATA[Info]]></string>
+    <string name="_bx_glossary_page_block_title_favorites_entries_actions"><![CDATA[Favorites List Actions]]></string>
+    <string name="_bx_glossary_page_title_sys_view_entry_comments"><![CDATA[Term Comments]]></string>
+    <string name="_bx_glossary_page_title_view_entry_comments"><![CDATA[Comments to {title}]]></string>
+    <string name="_bx_glossary_page_title_sys_entries_of_author"><![CDATA[Terms of author]]></string>
+    <string name="_bx_glossary_page_title_entries_of_author"><![CDATA[Terms by {display_name}]]></string>
+    <string name="_bx_glossary_page_block_title_favorites_of_author"><![CDATA[Favorites by <a href="{profile_link}">{display_name}</a>]]></string>
+    <string name="_bx_glossary_page_block_title_sys_favorites_of_author"><![CDATA[Favorites of author]]></string>
+    <string name="_bx_glossary_page_block_title_entries_of_author"><![CDATA[Terms by <a href="{profile_link}">{display_name}</a>]]></string>
+    <string name="_bx_glossary_page_title_sys_entries_in_context"><![CDATA[Terms in context]]></string>
+    <string name="_bx_glossary_page_title_entries_in_context"><![CDATA[Terms in {display_name}]]></string>
+    <string name="_bx_glossary_page_block_title_sys_entries_of_author"><![CDATA[Terms of author]]></string>
+    <string name="_bx_glossary_page_block_title_entries_in_context"><![CDATA[Terms in <a href="{profile_link}">{display_name}</a>]]></string>
+    <string name="_bx_glossary_page_block_title_sys_entries_in_context"><![CDATA[Terms in context]]></string>
+    <string name="_bx_glossary_page_block_title_entries_actions"><![CDATA[Terms actions]]></string>
+    <string name="_bx_glossary_page_block_title_browse_cmts"><![CDATA[Terms' Comments]]></string>
+	<string name="_bx_glossary_page_title_sys_manage"><![CDATA[Manage Own]]></string>
+	<string name="_bx_glossary_page_title_sys_manage_administration"><![CDATA[Manage All]]></string> 
+	<string name="_bx_glossary_page_title_manage"><![CDATA[Manage]]></string>
+	<string name="_bx_glossary_page_block_title_system_manage"><![CDATA[Manage Own]]></string>
+	<string name="_bx_glossary_page_block_title_system_manage_administration"><![CDATA[Manage All]]></string>
+	<string name="_bx_glossary_page_block_title_manage"><![CDATA[Manage]]></string>    
+	<string name="_bx_glossary_page_block_title_popular_keywords"><![CDATA[Popular Hashtags]]></string>
+	<string name="_bx_glossary_page_block_title_cats"><![CDATA[Terms Categories]]></string>
+	<string name="_bx_glossary_page_block_title_entry_info"><![CDATA[Info]]></string>
+    <string name="_bx_glossary_page_block_title_sys_my_entries"><![CDATA[User Terms]]></string>
+    <string name="_bx_glossary_page_block_title_my_entries"><![CDATA[{display_name} Terms]]></string>
+    <string name="_bx_glossary_page_block_title_sys_recent_entries_view_showcase"><![CDATA[Latest Terms (Showcase View)]]></string>
+    <string name="_bx_glossary_page_block_title_recent_entries_view_showcase"><![CDATA[Latest Terms]]></string>
+    <string name="_bx_glossary_page_block_title_sys_popular_entries_view_showcase"><![CDATA[Popular Terms (Showcase View)]]></string>
+    <string name="_bx_glossary_page_block_title_popular_entries_view_showcase"><![CDATA[Popular Terms]]></string>
+    <string name="_bx_glossary_page_block_title_sys_featured_entries_view_showcase"><![CDATA[Featured Terms (Showcase View)]]></string>
+    <string name="_bx_glossary_page_block_title_featured_entries_view_showcase"><![CDATA[Featured Terms]]></string>
+	<string name="_bx_glossary_page_block_title_sys_entry_context"><![CDATA[Posted in]]></string>
+	<string name="_bx_glossary_page_block_title_entry_context"><![CDATA[Posted in]]></string>
+
+    <string name="_bx_glossary_menu_set_title_view_entry"><![CDATA[Term Actions]]></string>
+    <string name="_bx_glossary_menu_title_view_entry"><![CDATA[Term Actions]]></string>
+    <string name="_bx_glossary_menu_title_submenu"><![CDATA[Glossary Submenu]]></string>
+    <string name="_bx_glossary_menu_set_title_submenu"><![CDATA[Glossary Submenu]]></string>
+    <string name="_bx_glossary_menu_item_title_system_create_entry"><![CDATA[Term]]></string>
+    <string name="_bx_glossary_menu_item_title_create_entry"><![CDATA[Term]]></string>
+    <string name="_bx_glossary_menu_item_title_system_edit_entry"><![CDATA[Edit]]></string>
+    <string name="_bx_glossary_menu_item_title_edit_entry"><![CDATA[Edit]]></string>
+    <string name="_bx_glossary_menu_item_title_system_delete_entry"><![CDATA[Delete]]></string>
+    <string name="_bx_glossary_menu_item_title_delete_entry"><![CDATA[Delete]]></string>
+    <string name="_bx_glossary_menu_item_title_system_view_entry"><![CDATA[View Term]]></string>
+    <string name="_bx_glossary_menu_item_title_system_entries_home"><![CDATA[Glossary]]></string>
+    <string name="_bx_glossary_menu_item_title_entries_home"><![CDATA[Glossary]]></string>
+    <string name="_bx_glossary_menu_item_title_system_entries_public"><![CDATA[Alphabetical]]></string>
+    <string name="_bx_glossary_menu_item_title_entries_public"><![CDATA[Alphabetical]]></string>
+    <string name="_bx_glossary_menu_item_title_system_entries_manage"><![CDATA[Manage]]></string>
+    <string name="_bx_glossary_menu_item_title_entries_manage"><![CDATA[Manage]]></string>
+    <string name="_bx_glossary_menu_item_title_system_entries_popular"><![CDATA[Popular]]></string>
+    <string name="_bx_glossary_menu_item_title_entries_popular"><![CDATA[Popular]]></string>
+    <string name="_bx_glossary_menu_item_title_system_entries_top"><![CDATA[Top]]></string>
+    <string name="_bx_glossary_menu_item_title_entries_top"><![CDATA[Top]]></string>
+    <string name="_bx_glossary_menu_item_title_system_entries_search"><![CDATA[Search]]></string>
+    <string name="_bx_glossary_menu_item_title_entries_search"><![CDATA[Search]]></string>
+    <string name="_bx_glossary_menu_title_view_entry_submenu"><![CDATA[View Glossary Submenu]]></string>
+    <string name="_bx_glossary_menu_set_title_view_entry_submenu"><![CDATA[View Glossary Submenu]]></string>
+    <string name="_bx_glossary_menu_item_title_view_entry_submenu_entry"><![CDATA[Term]]></string>
+    <string name="_bx_glossary_menu_item_title_view_entry_submenu_comments"><![CDATA[Comments]]></string>
+    <string name="_bx_glossary_menu_item_title_system_view_entry_comments"><![CDATA[Term Comments]]></string>
+    <string name="_bx_glossary_menu_item_title_system_view_entries_author"><![CDATA[Glossary]]></string>
+    <string name="_bx_glossary_menu_item_title_view_entries_author"><![CDATA[Glossary]]></string>
+    <string name="_bx_glossary_menu_item_title_system_view_entries_in_context"><![CDATA[Glossary]]></string>
+    <string name="_bx_glossary_menu_item_title_view_entries_in_context"><![CDATA[Glossary]]></string>
+    <string name="_bx_glossary_menu_title_entries_my"><![CDATA[My Glossary Action Menu]]></string>
+    <string name="_bx_glossary_menu_set_title_entries_my"><![CDATA[My Glossary Menu]]></string>
+	<string name="_bx_glossary_menu_item_title_system_manage_my_glossary"><![CDATA[My terms]]></string>
+    <string name="_bx_glossary_menu_item_title_manage_my_glossary"><![CDATA[Terms]]></string>
+    <string name="_bx_glossary_menu_set_title_manage_tools"><![CDATA[Manage Tools Submenu]]></string>
+    <string name="_bx_glossary_menu_title_manage_tools"><![CDATA[Manage Tools Submenu]]></string>
+    <string name="_bx_glossary_menu_item_title_system_manage_account"><![CDATA[Manage account]]></string>
+    <string name="_bx_glossary_menu_item_title_manage_account"><![CDATA[Manage account]]></string>
+	<string name="_bx_glossary_menu_item_title_system_admt_glossary"><![CDATA[Glossary]]></string>
+	<string name="_bx_glossary_menu_item_title_admt_glossary"><![CDATA[Glossary]]></string>
+	<string name="_bx_glossary_menu_item_title_manage_my"><![CDATA[My Terms]]></string>
+	<string name="_bx_glossary_menu_item_title_manage_all"><![CDATA[All Terms]]></string>
+
+	<string name="_bx_glossary_grid_filter_item_title_adm_select_one_filter1"><![CDATA[All Statuses]]></string>
+	<string name="_bx_glossary_grid_filter_item_title_adm_active"><![CDATA[Active]]></string>
+	<string name="_bx_glossary_grid_filter_item_title_adm_hidden"><![CDATA[Hidden]]></string>
+  <string name="_bx_glossary_grid_filter_item_title_adm_pending"><![CDATA[Pending]]></string>
+  <string name="_bx_glossary_grid_column_title_adm_active"><![CDATA[Active]]></string>
+    <string name="_bx_glossary_grid_column_title_adm_title"><![CDATA[Title]]></string>
+    <string name="_bx_glossary_grid_column_title_adm_added"><![CDATA[Added]]></string>
+    <string name="_bx_glossary_grid_column_title_adm_author"><![CDATA[Author]]></string>
+    <string name="_bx_glossary_grid_action_title_adm_edit"><![CDATA[Edit]]></string>
+    <string name="_bx_glossary_grid_action_title_adm_delete"><![CDATA[Delete]]></string>
+    <string name="_bx_glossary_grid_action_title_adm_clear_reports"><![CDATA[Clear reports]]></string>
+    <string name="_bx_glossary_grid_action_title_adm_more_actions"><![CDATA[More Actions]]></string>
+    <string name="_bx_glossary_grid_action_title_adm_audit_content"><![CDATA[Audit actions]]></string>  
+    <string name="_bx_glossary_grid_action_err_delete"><![CDATA[Cannot delete the selected term(s).]]></string>
+    <string name="_bx_glossary_grid_txt_account_manager"><![CDATA[Redirect to manage account.]]></string>
+
+    <string name="_bx_glossary_chart_growth"><![CDATA[Terms: Growth]]></string>
+    <string name="_bx_glossary_chart_growth_speed"><![CDATA[Terms: Growth Speed]]></string>
+
+    <string name="_bx_glossary_search_extended"><![CDATA[Terms Search]]></string>
+    <string name="_bx_glossary_search_extended_cmts"><![CDATA[Terms Comments Search]]></string>
+
+    <string name="_bx_glossary_pre_lists_cats"><![CDATA[Term categories]]></string>
+    <string name="_bx_glossary_cat_Nouns"><![CDATA[Nouns]]></string>
+    <string name="_bx_glossary_cat_Pronouns"><![CDATA[Pronouns]]></string>
+    <string name="_bx_glossary_cat_Verbs"><![CDATA[Verbs]]></string>
+    <string name="_bx_glossary_cat_Adverbs"><![CDATA[Adverbs]]></string>
+    <string name="_bx_glossary_cat_Adjectives"><![CDATA[Adjectives]]></string>
+    <string name="_bx_glossary_cat_Interjections"><![CDATA[Interjections]]></string>
+    <string name="_bx_glossary_cat_Prepositions"><![CDATA[Prepositions]]></string>
+    <string name="_bx_glossary_cat_Infinitives"><![CDATA[Infinitives]]></string>
+
+    <string name="_bx_glossary_pre_lists_statuses"><![CDATA[Term status]]></string>
+    <string name="_bx_glossary_item_admin_status_active"><![CDATA[Active]]></string>
+    <string name="_bx_glossary_item_admin_status_hidden"><![CDATA[Hidden]]></string>
+    <string name="_bx_glossary_item_admin_status_pending"><![CDATA[Pending]]></string>
+
+    <string name="_bx_glossary_txt_all_entries_by"><![CDATA[{0} terms]]></string>
+    <string name="_bx_glossary_txt_all_entries_in"><![CDATA[<a href="{0}">All Terms in {1} ({2})</a>]]></string>
+    <string name="_bx_glossary_txt_sample_single"><![CDATA[term]]></string>
+    <string name="_bx_glossary_txt_sample_single_with_article"><![CDATA[a term]]></string>
+    <string name="_bx_glossary_txt_sample_comment_single"><![CDATA[comment to term]]></string>
+    <string name="_bx_glossary_txt_sample_vote_single"><![CDATA[vote to term]]></string>
+    <string name="_bx_glossary_txt_sample_reaction_single"><![CDATA['{0}' reaction to term]]></string>
+    <string name="_bx_glossary_txt_sample_score_up_single"><![CDATA[score up vote to term]]></string>
+    <string name="_bx_glossary_txt_sample_score_down_single"><![CDATA[score down vote to term]]></string>
+    <string name="_bx_glossary_txt_term_in_pending_status"><![CDATA[This term is pending approval.]]></string>
+</resources>

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

@@ -0,0 +1,51 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'title' => 'Groups',
+    'version_from' => '12.0.0',
+    'version_to' => '12.0.1',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '12.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/groups/updates/update_12.0.0_12.0.1/',
+    'home_uri' => 'groups_update_1200_1201',
+
+    'module_dir' => 'boonex/groups/',
+    'module_uri' => 'groups',
+
+    'db_prefix' => 'bx_groups_',
+    'class_prefix' => 'BxGroups',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 0,
+        'update_files' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 0,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Groups',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

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

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

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

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

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

@@ -0,0 +1,152 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Groups Groups
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_groups',
+    'title' => 'Groups',
+    'note' => 'Basic group profiles functionality.',
+    'version' => '12.0.1',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '12.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/groups/',
+    'home_uri' => 'groups',
+
+    'db_prefix' => 'bx_groups_',
+    'class_prefix' => 'BxGroups',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Groups',
+
+    /**
+     * Connections.
+     */
+    'connections' => array(
+    	'sys_profiles_friends' => array ('type' => 'profiles'),
+		'sys_profiles_subscriptions' => array ('type' => 'profiles'),
+    ),
+
+    /**
+     * Menu triggers.
+     */
+    'menu_triggers' => array(
+    	'trigger_profile_view_submenu',
+        'trigger_group_view_submenu',
+        'trigger_group_snippet_meta',
+        'trigger_group_view_actions',
+    ),
+
+    /**
+     * Page triggers.
+     */
+    'page_triggers' => array (
+    	'trigger_page_group_view_entry', 
+    ),
+
+	/**
+     * Storage objects to automatically delete files from upon module uninstallation.
+     * Note. Don't add storage objects used in transcoder objects.
+     */
+    'storages' => array(
+    	'bx_groups_pics'
+    ),
+
+	/**
+     * Transcoders.
+     */
+    'transcoders' => array(
+    	'bx_groups_icon', 
+    	'bx_groups_thumb', 
+    	'bx_groups_avatar', 
+        'bx_groups_avatar_big', 
+    	'bx_groups_picture', 
+    	'bx_groups_cover', 
+    	'bx_groups_cover_thumb',
+        'bx_groups_gallery'
+    ),
+
+    /**
+     * Extended Search Forms.
+     */
+    'esearches' => array(
+        'bx_groups',
+    	'bx_groups_cmts',
+    ),
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'uninstall' => array (
+    	'process_esearches' => 1,
+        'execute_sql' => 1,
+        'update_languages' => 1,
+    	'process_connections' => 1,
+        'process_deleted_profiles' => 1,
+    	'update_relations' => 1,        
+        'clear_db_cache' => 1,
+    ),
+    'enable' => array(
+        'execute_sql' => 1,
+    	'update_relations' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'enable_success' => array(
+    	'process_menu_triggers' => 1,
+    	'process_page_triggers' => 1,
+    	'process_esearches' => 1,
+    	'register_transcoders' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable' => array (
+        'execute_sql' => 1,
+        'unregister_transcoders' => 1,
+        'update_relations' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable_failed' => array (
+    	'register_transcoders' => 1,
+    	'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Dependencies Section
+     */
+    'dependencies' => array(),
+
+    /**
+     * Connections Section
+     */
+    'relations' => array(
+        'bx_timeline',
+        'bx_notifications',
+    ),
+);
+
+/** @} */

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

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

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

@@ -0,0 +1,51 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'title' => 'Market',
+    'version_from' => '12.0.0',
+    'version_to' => '12.0.1',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '12.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_12.0.0_12.0.1/',
+    'home_uri' => 'market_update_1200_1201',
+
+    'module_dir' => 'boonex/market/',
+    'module_uri' => 'market',
+
+    'db_prefix' => 'bx_market_',
+    'class_prefix' => 'BxMarket',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 0,
+        'update_files' => 1,
+        'update_languages' => 0,
+        'clear_db_cache' => 0,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Market',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

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

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

+ 708 - 0
modules/boonex/market/updates/12.0.0_12.0.1/source/classes/BxMarketDb.php

@@ -0,0 +1,708 @@
+<?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 database queries
+ */
+class BxMarketDb extends BxBaseModTextDb
+{
+	protected $_aRecurringDurations;
+
+    function __construct(&$oConfig)
+    {
+        parent::__construct($oConfig);
+
+        $this->_aRecurringDurations = array(
+        	'day' => 'INTERVAL 1 DAY',
+        	'week' => 'INTERVAL 7 DAY',
+        	'month' => 'INTERVAL 1 MONTH',
+        	'year' => 'INTERVAL 1 YEAR',
+        );
+    }
+
+    public function getProductsNames ($iVendor = 0, $iLimit = 1000)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $sWhere = '';
+        $aBindings = array('limit' => $iLimit);
+        if ($iVendor) {
+            $aBindings['author'] = $iVendor;
+            $sWhere .= "AND `{$CNF['FIELD_AUTHOR']} = :author`";
+        }
+
+        return $this->getColumn("SELECT `{$CNF['FIELD_NAME']}` FROM `{$CNF['TABLE_ENTRIES']}` WHERE (`{$CNF['FIELD_PRICE_SINGLE']}` != '0' OR `{$CNF['FIELD_PRICE_RECURRING']}` != '0') $sWhere LIMIT :limit", $aBindings);
+    }
+    
+    public function getContentInfoBy ($aParams)
+    {
+    	$CNF = &$this->_oConfig->CNF;
+
+    	$aMethod = array('name' => 'getAll', 'params' => array(0 => 'query'));
+		$aOrderWay = array('up' => 'ASC', 'down' => 'DESC');
+
+    	$sFieldsClause = $sJoinClause = $sWhereClause = $sGroupClause = $sOrderClause = $sLimitClause = '';
+
+    	//--- Add file info.
+    	$sFieldsClause .= " `te`.`" . $CNF['FIELD_PACKAGE'] . "` AS `file_id`, `tf`.`file_name` AS `file_name`, `tfe`.`version` AS `file_version`, ";
+    	$sJoinClause .= " LEFT JOIN `" . $CNF['TABLE_FILES2ENTRIES'] . "` AS `tfe` ON `te`.`" . $CNF['FIELD_ID'] . "`=`tfe`.`content_id` AND `te`.`" . $CNF['FIELD_PACKAGE'] . "`=`tfe`.`file_id` LEFT JOIN `" . $CNF['TABLE_FILES'] . "` AS `tf` ON `te`.`" . $CNF['FIELD_PACKAGE'] . "`=`tf`.`id` ";
+
+    	//--- Add license checking for Public listings if Client is specified.
+    	if(in_array($aParams['type'], array('latest', 'popular', 'featured', 'category', 'tag', 'vendor', 'keyword')) && isset($aParams['client']) && (int)$aParams['client'] != 0) {
+    	    //--- Direct license purchase for a product
+    	    $sLicDir = $this->prepareAsString("SELECT `tl`.`added` FROM `" . $CNF['TABLE_LICENSES'] . "` AS `tl` WHERE `tl`.`product_id`=`te`.`" . $CNF['FIELD_ID'] . "` AND `tl`.`profile_id`=? AND (`tl`.`domain`=?" . (empty($aParams['key_assigned']) ? " OR `tl`.`domain`=''" : "") . ") LIMIT 1", (int)$aParams['client'], $aParams['key']);
+
+    	    //--- License got with package purchase
+    	    $oConnnection = BxDolConnection::getObjectInstance($CNF['OBJECT_CONNECTION_SUBENTRIES']);
+            $aConnectionSql = $oConnnection->getConnectedInitiatorsAsSQLPartsMultiple('tl', 'product_id', 'te', $CNF['FIELD_ID']);
+
+    	    $sLicPack = $this->prepareAsString("SELECT `tl`.`added` FROM `" . $CNF['TABLE_LICENSES'] . "` AS `tl` " . $aConnectionSql['join'] . " WHERE 1 " . $aConnectionSql['where'] . " AND `tl`.`profile_id`=? AND (`tl`.`domain`=?" . (empty($aParams['key_assigned']) ? " OR `tl`.`domain`=''" : "") . ") LIMIT 1", (int)$aParams['client'], $aParams['key']);
+
+    		$sFieldsClause .= " ((" . $sLicDir . ") OR (" . $sLicPack . ")) AS `purchased_on`, ";
+    	}
+
+    	//--- Exclude content by ids or names
+        if(!empty($aParams['exclude_by']) && in_array($aParams['exclude_by'], array('id', 'name')) && !empty($aParams['exclude_values']))
+            $sWhereClause .= " AND `te`.`" . $aParams['exclude_by'] . "` NOT IN (" . $this->implode_escape($aParams['exclude_values']) . ") ";
+
+        //--- Attach custom queries described with field - value pairs.
+        if(!empty($aParams['custom_and']) && is_array($aParams['custom_and']))
+            $sWhereClause .= " AND (" . $this->arrayToSQL($aParams['custom_and'], ' AND ') . ") ";
+
+        if(!empty($aParams['custom_or']) && is_array($aParams['custom_or']))
+            $sWhereClause .= " AND (" . $this->arrayToSQL($aParams['custom_or'], ' OR ') . ") ";
+
+    	if(isset($aParams['start']) && !empty($aParams['per_page']))
+            $sLimitClause = $aParams['start'] . ", " . $aParams['per_page'];
+
+        switch($aParams['type']) {
+            case 'id':
+                    $aMethod['name'] = 'getRow';
+                    $sFieldsClause .= "";
+                    $sJoinClause .= "";
+                    $sWhereClause .= $this->prepareAsString(" AND `te`.`" . $CNF['FIELD_ID'] . "`=? ", $aParams['value']);
+                    $sOrderClause .= "";
+                    break;
+
+            case 'name':
+                    $aMethod['name'] = 'getRow';
+                    $sFieldsClause .= "";
+                    $sJoinClause .= "";
+                    $sWhereClause .= $this->prepareAsString(" AND `te`.`" . $CNF['FIELD_NAME'] . "`=? ", $aParams['value']);
+                    $sOrderClause .= "";
+                    break;
+
+            case 'file_id':
+                    $aMethod['name'] = 'getRow';
+                    $sFieldsClause .= "";
+                    $sJoinClause .= "";
+                    $sWhereClause .= $this->prepareAsString(" AND `te`.`" . $CNF['FIELD_PACKAGE'] . "`=? ", $aParams['value']);
+                    $sOrderClause .= "";
+                    break;
+
+            case 'latest':
+                    $sFieldsClause .= "";
+                    $sJoinClause .= "";
+                    $sWhereClause .= "";
+                    $sOrderClause = "`te`.`added` " . (isset($aParams['order_way']) ? $aOrderWay[$aParams['order_way']] : "DESC");
+                    break;
+
+            case 'featured':
+                    $sFieldsClause .= "";
+                    $sJoinClause .= "";
+                    $sWhereClause .= " AND `te`.`" . $CNF['FIELD_FEATURED'] . "`<>0";
+                    $sOrderClause = "`te`.`" . $CNF['FIELD_FEATURED'] . "` " . (isset($aParams['order_way']) ? $aOrderWay[$aParams['order_way']] : "DESC");
+                    break;
+
+            case 'popular':
+                    $sFieldsClause .= "";
+                    $sJoinClause .= "";
+                    $sWhereClause .= "";
+                    $sOrderClause = "`te`.`views` " . (isset($aParams['order_way']) ? $aOrderWay[$aParams['order_way']] : "DESC");
+                    break;
+
+            case 'selected':
+                    $sFieldsClause .= "";
+                    $sJoinClause .= "";
+                    $sWhereClause .= " AND `te`.`id` IN (" . $this->implode_escape($aParams['selected']) . ") ";
+                    $sOrderClause = "`te`.`added` " . (isset($aParams['order_way']) ? $aOrderWay[$aParams['order_way']] : "DESC");
+                    break;
+
+            case 'category':
+                    if(!is_array($aParams['value']))
+                            $aParams['value'] = array($aParams['value']);
+
+                    $sFieldsClause .= "";
+                    $sJoinClause .= "";
+                    $sWhereClause .= " AND `te`.`" . $CNF['FIELD_CATEGORY'] . "` IN (" . $this->implode_escape($aParams['value']) . ")";
+                    $sOrderClause = "`te`.`added` " . (isset($aParams['order_way']) ? $aOrderWay[$aParams['order_way']] : "DESC");
+                    break;
+
+            case 'tag':
+                $sFieldsClause .= "";
+
+                $aSql = BxDolMetatags::getObjectInstance($CNF['OBJECT_METATAGS'])->keywordsGetAsSQLPart('te', $CNF['FIELD_ID'], $aParams['value']);
+                if(!empty($aSql['where'])) {
+                    $sWhereClause .= $aSql['where'];
+                
+                    if(!empty($aSql['join']))
+                        $sJoinClause .= $aSql['join'];
+                }
+
+                $sOrderClause = "`te`.`added` " . (isset($aParams['order_way']) ? $aOrderWay[$aParams['order_way']] : "DESC");
+                break;
+
+            case 'vendor':
+                    $sFieldsClause .= "";
+                    $sJoinClause .= "";
+
+                    $sWhereClause .= $this->prepareAsString(" AND `te`.`" . $CNF['FIELD_AUTHOR'] . "`=? ", (int)$aParams['value']); 
+                    if(isset($aParams['paid']) && (int)$aParams['paid'] == 1)
+                            $sWhereClause .= " AND `te`.`" . $CNF['FIELD_PRICE_SINGLE'] . "`<>'0' AND `te`.`" . $CNF['FIELD_PRICE_RECURRING'] . "`<>'0'";
+
+                    $sOrderClause = "`te`.`" . (isset($aParams['order_by']) ? $aParams['order_by'] : "added") . "` " . (isset($aParams['order_way']) ? $aOrderWay[$aParams['order_way']] : "DESC");
+                    break;
+
+            case 'keyword':
+                    $sFieldsClause .= $this->prepareAsString(" MATCH(`" . $CNF['FIELD_TITLE'] . "`, `" . $CNF['FIELD_TEXT'] . "`) AGAINST (?) AS `search_condition`, ", $aParams['value']);
+                    $sJoinClause .= "";
+                    $sWhereClause .= $this->prepareAsString(" AND MATCH(`" . $CNF['FIELD_TITLE'] . "`, `" . $CNF['FIELD_TEXT'] . "`) AGAINST (?) ", $aParams['value']);
+                    $sOrderClause = "`search_condition` " . (isset($aParams['order_way']) ? $aOrderWay[$aParams['order_way']] : "DESC");
+                    break;
+
+            case 'granted':
+                    $sFieldsClause .= " '" . $aParams['license']['license'] . "' AS `license`, '" . $aParams['license']['profile_id'] . "' AS `purchased_by`, '' AS `purchased_for`, '" . $aParams['license']['added'] . "' AS `purchased_on`, ";
+                    $sWhereClause .= $this->prepareAsString(" AND `te`.`" . $CNF['FIELD_AUTHOR'] . "`=? AND (`te`.`" . $CNF['FIELD_PRICE_SINGLE'] . "`<>'0' OR `te`.`" . $CNF['FIELD_PRICE_RECURRING'] . "`<>'0') ", (int)$aParams['value']);
+                    $sOrderClause = "`te`.`added` " . (isset($aParams['order_way']) ? $aOrderWay[$aParams['order_way']] : "DESC");
+                    break;
+
+            case 'purchased':
+                    $sFieldsClause .= " `tl`.`license` AS `license`, `tl`.`profile_id` AS `purchased_by`, `tl`.`domain` AS `purchased_for`, `tl`.`added` AS `purchased_on`, ";
+
+                    if(isset($aParams['package']) && (int)$aParams['package'] == 1) {
+                        $oConnnection = BxDolConnection::getObjectInstance($CNF['OBJECT_CONNECTION_SUBENTRIES']);
+                        $aConnectionSql = $oConnnection->getConnectedContentAsSQLPartsMultiple('te', $CNF['FIELD_ID'], 'tl', 'product_id');
+
+                        $sJoinClause .= " " . $aConnectionSql['join'] . " LEFT JOIN `" . $CNF['TABLE_LICENSES'] . "` AS `tl` ON " . trim($aConnectionSql['where'], " AND ") . " ";
+                    }
+                    else
+                        $sJoinClause .= " LEFT JOIN `" . $CNF['TABLE_LICENSES'] . "` AS `tl` ON `te`.`" . $CNF['FIELD_ID'] . "`=`tl`.`product_id` ";
+
+                    $sWhereClause .= $this->prepareAsString(" AND `tl`.`profile_id`=? AND (`tl`.`domain`=?" . (empty($aParams['key_assigned']) ? " OR `tl`.`domain`=''" : "") . ") ", (int)$aParams['client'], $aParams['key']);
+                    $sGroupClause .= "`te`.`" . $CNF['FIELD_ID'] . "`";
+                    $sOrderClause = "`tl`.`added` " . (isset($aParams['order_way']) ? $aOrderWay[$aParams['order_way']] : "DESC");
+                    break;
+        }
+
+        $sGroupClause = $sGroupClause ? "GROUP BY " . $sGroupClause : "";
+        $sOrderClause = $sOrderClause ? "ORDER BY " . $sOrderClause : "";
+        $sLimitClause = $sLimitClause ? "LIMIT " . $sLimitClause : "";
+
+        $aMethod['params'][0] = "SELECT " . $sFieldsClause . "`te`.*
+        FROM `" . $CNF['TABLE_ENTRIES'] . "` AS `te`" . $sJoinClause . "
+        WHERE 1" . $sWhereClause . " " . $sGroupClause . " " . $sOrderClause . " " . $sLimitClause;
+
+        return call_user_func_array(array($this, $aMethod['name']), $aMethod['params']);
+    }
+
+	public function getContentInfoByName ($sContentName)
+    {
+        $sQuery = $this->prepare ("SELECT * FROM `" . $this->_oConfig->CNF['TABLE_ENTRIES'] . "` WHERE `" . $this->_oConfig->CNF['FIELD_NAME'] . "` = ?", $sContentName);
+        return $this->getRow($sQuery);
+    }
+
+    public function updateContentInfoBy ($aSet, $aWhere)
+    {
+        $sQuery = "UPDATE `" . $this->_oConfig->CNF['TABLE_ENTRIES'] . "` SET " . $this->arrayToSQL($aSet) . " WHERE " . (!empty($aWhere) ? $this->arrayToSQL($aWhere, ' AND ') : "1");
+        return (int)$this->query($sQuery) > 0;
+    }
+
+	public function getPhoto($aParams = array())
+    {
+    	return $this->_getAttachment($this->_oConfig->CNF['TABLE_PHOTOS2ENTRIES'], $aParams);
+    }
+
+	public function updatePhoto($aSet, $aWhere)
+    {
+    	return $this->_updateAttachment($this->_oConfig->CNF['TABLE_PHOTOS2ENTRIES'], $aSet, $aWhere);
+    }
+
+    public function getFile($aParams = array())
+    {
+    	return $this->_getAttachment($this->_oConfig->CNF['TABLE_FILES2ENTRIES'], $aParams);
+    }
+
+    public function updateFile($aSet, $aWhere)
+    {
+    	return $this->_updateAttachment($this->_oConfig->CNF['TABLE_FILES2ENTRIES'], $aSet, $aWhere);
+    }
+
+    public function associatePhotoWithContent($iContentId, $iFileId, $sTitle)
+    {
+        $sQuery = $this->prepare ("SELECT MAX(`order`) FROM `" . $this->_oConfig->CNF['TABLE_PHOTOS2ENTRIES'] . "` WHERE `content_id` = ?", $iContentId);
+        $iOrder = 1 + (int)$this->getOne($sQuery);
+
+        $sQuery = $this->prepare ("INSERT INTO `" . $this->_oConfig->CNF['TABLE_PHOTOS2ENTRIES'] . "` SET `content_id` = ?, `file_id` = ?, `title` = ?, `order` = ? ON DUPLICATE KEY UPDATE `title` = ?", $iContentId, $iFileId, $sTitle, $iOrder, $sTitle);
+        return $this->res($sQuery);
+    }
+
+    public function deassociatePhotoWithContent($iContentId, $iFileId)
+    {
+    	return $this->_deassociateAttachmentWithContent($this->_oConfig->CNF['TABLE_PHOTOS2ENTRIES'], $iContentId, $iFileId);
+    }
+
+    public function associateFileWithContent($iContentId, $iFileId, $aParams)
+    {
+        $sQuery = $this->prepare ("SELECT MAX(`order`) FROM `" . $this->_oConfig->CNF['TABLE_FILES2ENTRIES'] . "` WHERE `content_id` = ?", $iContentId);
+        $iOrder = 1 + (int)$this->getOne($sQuery);
+
+        $aBindings = array_merge(array(
+        	'content_id' => $iContentId,
+        	'file_id' => $iFileId,
+        	'order' => $iOrder,
+        ), $aParams);
+
+        $sDiv = ", ";
+        $sParams = "";
+        foreach($aParams as $sKey => $mixedValue)
+            $sParams .= "`" . $sKey . "` = :" . $sKey . $sDiv;
+		$sParams = trim($sParams, $sDiv);
+
+        $sQuery = $this->prepare("INSERT INTO `" . $this->_oConfig->CNF['TABLE_FILES2ENTRIES'] . "` SET `content_id` = :content_id, `file_id` = :file_id, " . $sParams . ", `order` = :order ON DUPLICATE KEY UPDATE " . $sParams);
+        return $this->res($sQuery, $aBindings);
+    }
+
+    public function deassociateFileWithContent($iContentId, $iFileId)
+    {
+    	return $this->_deassociateAttachmentWithContent($this->_oConfig->CNF['TABLE_FILES2ENTRIES'], $iContentId, $iFileId);
+    }
+
+    public function insertDownload($iFileId, $iProfileId, $iProfileNip)
+    {
+    	$sQuery = $this->prepare("INSERT IGNORE INTO `" . $this->_oConfig->CNF['TABLE_DOWNLOADS'] . "` SET `file_id` = ?, `profile_id` = ?, `profile_nip` = ?, `date` = UNIX_TIMESTAMP()", $iFileId, $iProfileId, $iProfileNip);
+		return (int)$this->query($sQuery) > 0;
+    }
+
+    /**
+     * Integration with Payment based modules.  
+     */
+	public function getLicense($aParams = array())
+    {
+    	$CNF = &$this->_oConfig->CNF;
+    	$aMethod = array('name' => 'getAll', 'params' => array(0 => 'query'));
+
+    	$sSelectClause = "`tl`.*";
+    	$sJoinClause = $sWhereClause = $sLimitClause = "";
+        switch($aParams['type']) {
+            case 'id':
+            	$aMethod['name'] = 'getRow';
+            	$aMethod['params'][1] = array(
+                	'id' => $aParams['id']
+                );
+
+                $sWhereClause = " AND `tl`.`id`=:id";
+                break;
+
+            case 'new':
+				$aMethod['params'][1] = array(
+                	'profile_id' => $aParams['profile_id']
+                );
+
+                $sWhereClause = " AND `tl`.`profile_id`=:profile_id AND `tl`.`new`='1'";
+                break;
+
+			case 'unused':
+				$aMethod['params'][1] = array(
+                	'profile_id' => $aParams['profile_id']
+                );
+
+                $sWhereClause = " AND `tl`.`profile_id`=:profile_id AND `tl`.`domain`=''";
+                break;
+
+			case 'expired':
+				$aMethod['params'][1] = array(
+                	'type' => BX_MARKET_LICENSE_TYPE_RECURRING
+                );
+
+				$sWhereClause = " AND `type` = :type AND `added` < UNIX_TIMESTAMP() AND `expired` <> 0 AND `expired` < UNIX_TIMESTAMP()";
+				break;
+
+            case 'product_id':
+				$aMethod['params'][1] = array(
+                	'product_id' => $aParams['product_id']
+                );
+
+				$sWhereClause = " AND `tl`.`product_id`=:product_id";
+
+				if(!empty($aParams['profile_id'])) {
+					$aMethod['params'][1]['profile_id'] = $aParams['profile_id'];
+					$sWhereClause .= " AND `tl`.`profile_id`=:profile_id";
+				}
+				break;
+
+			case 'profile_id':
+				$aMethod['params'][1] = array(
+                	'profile_id' => $aParams['profile_id']
+                );
+
+				$sWhereClause = " AND `tl`.`profile_id`=:profile_id";
+
+				if(!empty($aParams['product_id'])) {
+					$aMethod['params'][1]['product_id'] = $aParams['product_id'];
+					$sWhereClause .= " AND `tl`.`product_id`=:product_id";
+				}
+				break;
+
+			case 'profile_id_file_id_key':
+				$aMethod['name'] = "getRow";
+				$aMethod['params'][1] = array(
+                	'profile_id' => $aParams['profile_id'],
+					'key' => $aParams['key']
+                );
+
+				$iProductId = $this->getOne("SELECT `" . $CNF['FIELD_ID'] . "` FROM `" . $this->_oConfig->CNF['TABLE_ENTRIES'] . "` WHERE `" . $CNF['FIELD_PACKAGE'] . "`=:file_id LIMIT 1", array(
+				    'file_id' => $aParams['file_id']
+				));
+
+				if(isset($aParams['package']) && (int)$aParams['package'] == 1) {
+				    $oConnnection = BxDolConnection::getObjectInstance($CNF['OBJECT_CONNECTION_SUBENTRIES']);
+                    $aConnectionSql = $oConnnection->getConnectedInitiatorsAsSQLParts('tl', 'product_id', $iProductId);
+
+                    $sJoinClause .= $aConnectionSql['join'];
+				}
+				else {
+                    $aMethod['params'][1]['product_id'] = $iProductId;
+
+                    $sWhereClause .= " AND `tl`.`product_id`=:product_id";
+				}
+
+				$sWhereClause .= " AND `tl`.`profile_id`=:profile_id AND (`tl`.`domain`='' OR `tl`.`domain`=:key)";
+				$sLimitClause = "1";
+				break;
+
+			case 'has_by':
+				$aMethod['name'] = "getOne";
+				$aMethod['params'][1] = array(
+                	'profile_id' => $aParams['profile_id']
+                );
+
+                $sSelectClause = "`tl`.`id`";
+                $sWhereClause = " AND `tl`.`profile_id`=:profile_id";
+
+                if(isset($aParams['package']) && (int)$aParams['package'] == 1) {
+                    $oConnnection = BxDolConnection::getObjectInstance($CNF['OBJECT_CONNECTION_SUBENTRIES']);
+                    $aConnectionSql = $oConnnection->getConnectedInitiatorsAsSQLParts('tl', 'product_id', $aParams['product_id']);
+
+                    $sJoinClause .= $aConnectionSql['join'];
+                }
+                else {
+                    $aMethod['params'][1]['product_id'] = $aParams['product_id'];
+
+                    $sWhereClause .= " AND `tl`.`product_id`=:product_id";
+                }
+
+                if(!empty($aParams['domain'])) {
+                	$aMethod['params'][1]['domain'] = $aParams['domain'];
+                	$sWhereClause .= " AND `tl`.`domain`=:domain";
+                }
+
+		        if(!empty($aParams['order'])) {
+                	$aMethod['params'][1]['order'] = $aParams['order'];
+                	$sWhereClause .= " AND `tl`.`order`=:order";
+                }
+
+                $sLimitClause = "1";
+                break;
+        }
+
+        $sLimitClause = !empty($sLimitClause) ? "LIMIT " . $sLimitClause : $sLimitClause;
+
+        $aMethod['params'][0] = "SELECT
+        		" . $sSelectClause . "
+            FROM `" . $this->_oConfig->CNF['TABLE_LICENSES'] . "` AS `tl`" . $sJoinClause . "
+            WHERE 1" . $sWhereClause . " " . $sLimitClause;
+
+        return call_user_func_array(array($this, $aMethod['name']), $aMethod['params']);
+    }
+
+	public function updateLicense($aSet, $aWhere)
+    {
+        $sQuery = "UPDATE `" . $this->_oConfig->CNF['TABLE_LICENSES'] . "` SET " . $this->arrayToSQL($aSet) . " WHERE " . (!empty($aWhere) ? $this->arrayToSQL($aWhere, ' AND ') : "1");
+        return (int)$this->query($sQuery) > 0;
+    }
+
+	public function deleteLicense($aWhere)
+    {
+    	if(empty($aWhere))
+    		return false;
+
+        $sQuery = "DELETE FROM `" . $this->_oConfig->CNF['TABLE_LICENSES'] . "` WHERE " . $this->arrayToSQL($aWhere, ' AND ');
+        return (int)$this->query($sQuery) > 0;
+    }
+
+    public function hasLicense ($iProfileId, $iProductId, $sDomain = '')
+    {
+        $aParams = array(
+    		'type' => 'has_by', 
+    		'profile_id' => $iProfileId, 
+    		'product_id' => $iProductId, 
+    		'domain' => !empty($sDomain) ? $sDomain : ''
+    	);
+ 
+        $iLicenseId = (int)$this->getLicense($aParams);
+    	if($iLicenseId > 0)
+    	    return true;
+
+        $aParams['package'] = 1;
+        $iLicenseId = (int)$this->getLicense($aParams);
+    	if($iLicenseId > 0)
+    	    return true;
+
+    	return false;
+    }
+
+	public function hasLicenseByOrder ($iProfileId, $iProductId, $sOrder = '')
+    {
+        $aParams = array(
+    		'type' => 'has_by', 
+    		'profile_id' => $iProfileId, 
+    		'product_id' => $iProductId, 
+    		'order' => !empty($sOrder) ? $sOrder : ''
+    	);
+
+        $iLicenseId = (int)$this->getLicense($aParams);
+        if($iLicenseId > 0)
+    	    return true;
+
+        $aParams['package'] = 1;
+        $iLicenseId = (int)$this->getLicense($aParams);
+    	if($iLicenseId > 0)
+    	    return true;
+
+    	return false;
+    }
+
+    public function registerLicense($iProfileId, $iProductId, $iCount, $sOrder, $sLicense, $sType, $sDuration = '', $iTrial = 0)
+    {
+    	$CNF = &$this->_oConfig->CNF;
+
+        $oPayments = BxDolPayments::getInstance();
+
+        $iProcessed = 0;
+        for($i = 0; $i < $iCount; $i++) {
+            $aQueryParams = array(
+                'profile_id' => $iProfileId,
+                'product_id' => $iProductId,
+                'count' => 1,
+                'order' => $sOrder,
+                'license' => $sLicense,
+                'type' => $sType
+            );
+
+            $sExpireParam = '';
+            if(!empty($iTrial))
+                $sExpireParam = ', `expired`=UNIX_TIMESTAMP(DATE_ADD(DATE_ADD(NOW(), INTERVAL ' . (int)$iTrial . ' DAY), INTERVAL ' . (int)$this->getParam($CNF['OPTION_RECURRING_RESERVE']) . ' DAY))';
+            else if(!empty($sDuration) && isset($this->_aRecurringDurations[$sDuration]))
+                $sExpireParam = ', `expired`=UNIX_TIMESTAMP(DATE_ADD(DATE_ADD(NOW(), ' . $this->_aRecurringDurations[$sDuration] . '), INTERVAL ' . (int)$this->getParam($CNF['OPTION_RECURRING_RESERVE']) . ' DAY))';
+
+            if((int)$this->query("INSERT INTO `" . $CNF['TABLE_LICENSES'] . "` SET " . $this->arrayToSQL($aQueryParams) . ", `added`=UNIX_TIMESTAMP()" . $sExpireParam) == 0)
+                continue;
+
+            $sLicense = $oPayments->generateLicense();
+            $iProcessed += 1;
+        }
+
+        return $iCount == $iProcessed;
+    }
+
+    public function prolongLicense($iProfileId, $iProductId, $iCount, $sOrder, $sLicense, $sType, $sDuration = '', $iTrial = 0)
+    {
+    	$CNF = &$this->_oConfig->CNF;
+
+    	if($sType == BX_MARKET_LICENSE_TYPE_SINGLE)
+    		return true;
+
+    	if(empty($sDuration) || empty($this->_aRecurringDurations[$sDuration]))
+    		return false;
+
+    	$sQuery = $this->prepare("UPDATE 
+    			`" . $CNF['TABLE_LICENSES'] . "` 
+    		SET 
+    			`expired`=UNIX_TIMESTAMP(DATE_ADD(FROM_UNIXTIME(`expired`), " . $this->_aRecurringDurations[$sDuration] . ")) 
+    		WHERE 
+    			`profile_id` = ? AND 
+    			`product_id` = ? AND 
+    			`order` = ? 
+    		LIMIT ?", $iProfileId, $iProductId, $sOrder, (int)$iCount);
+
+        return (int)$this->query($sQuery) > 0;
+    }
+
+    public function unregisterLicense($iProfileId, $iProductId, $sOrder, $sLicense, $sType)
+    {
+    	$sWhereClause = "`profile_id` = :profile_id AND `product_id` = :product_id AND `order` = :order AND `license` = :license";
+    	$aWhereBindings = array(
+    		'profile_id' => $iProfileId,
+    		'product_id' => $iProductId,
+    		'order' => $sOrder,
+    		'license' => $sLicense
+    	);
+    	
+		//--- Move to deleted licenses table with 'refund' as reason.   
+    	$sQuery = "INSERT IGNORE INTO `" . $this->_oConfig->CNF['TABLE_LICENSES_DELETED'] . "` SELECT *, 'refund' AS `reason`, UNIX_TIMESTAMP() AS `deleted` FROM `" . $this->_oConfig->CNF['TABLE_LICENSES'] . "` WHERE " . $sWhereClause;
+		$this->query($sQuery, $aWhereBindings);
+
+    	$sQuery = "DELETE FROM `" . $this->_oConfig->CNF['TABLE_LICENSES'] . "` WHERE " . $sWhereClause;
+        return $this->query($sQuery, $aWhereBindings) !== false;
+    }
+
+    function processExpiredLicense($aLicense)
+    {
+        //--- Move to deleted licenses table with 'expire' as reason.  
+        $this->query("INSERT IGNORE INTO `" . $this->_oConfig->CNF['TABLE_LICENSES_DELETED'] . "` SET " . $this->arrayToSQL($aLicense));
+
+        return $this->query("DELETE FROM `" . $this->_oConfig->CNF['TABLE_LICENSES'] . "` WHERE `id`=:id LIMIT 1", array('id' => $aLicense['id'])) !== false;
+    }
+
+    function processExpiredLicenses()
+    {
+        $sWhereClause = "`type` = :type AND `added` < UNIX_TIMESTAMP() AND `expired` <> 0 AND `expired` < UNIX_TIMESTAMP()";
+        $aWhereBindings = array(
+            'type' => BX_MARKET_LICENSE_TYPE_RECURRING
+        );
+
+        //--- Move to deleted licenses table with 'expire' as reason.  
+        $sQuery = "INSERT IGNORE INTO `" . $this->_oConfig->CNF['TABLE_LICENSES_DELETED'] . "` SELECT *, 'expire' AS `reason`, UNIX_TIMESTAMP() AS `deleted` FROM `" . $this->_oConfig->CNF['TABLE_LICENSES'] . "` WHERE " . $sWhereClause;
+        $this->query($sQuery, $aWhereBindings);
+
+        $sQuery = "DELETE FROM `" . $this->_oConfig->CNF['TABLE_LICENSES'] . "` WHERE " . $sWhereClause;
+        return $this->query($sQuery, $aWhereBindings) !== false;
+    }
+
+    protected function _deassociateAttachmentWithContent($sTable, $iContentId, $iFileId)
+    {
+        $sWhere = '';
+        $aBindings = array();
+        if ($iContentId) {
+            $sWhere .= " AND `content_id` = :content_id ";
+            $aBindings['content_id'] = $iContentId;
+        }
+
+        if ($iFileId) {
+            $sWhere .= " AND `file_id` = :file_id ";
+            $aBindings['file_id'] = $iFileId;
+        }
+
+        $sQuery = "DELETE FROM `" . $sTable . "` WHERE 1 " . $sWhere;
+        return $this->query($sQuery, $aBindings) !== false;
+    }
+
+    protected function _getAttachment($sTable, $aParams = array())
+    {
+    	$aMethod = array('name' => 'getRow', 'params' => array(0 => 'query'));
+    	
+    	$sFieldsClause = "`tfe`.*";
+    	$sJoinClause = $sWhereClause = $sOrderClause = $sLimitClause = "";
+        switch($aParams['type']) {
+            case 'id':
+            	$aMethod['params'][1] = array(
+                    'id' => $aParams['id']
+                );
+
+                $sWhereClause = " AND `tfe`.`id`=:id";
+                break;
+
+            case 'file_id':
+                $aMethod['params'][1] = array(
+                    'file_id' => $aParams['file_id']
+                );
+
+                $sWhereClause = " AND `tfe`.`file_id`=:file_id";
+                break;
+
+            case 'file_id_ext':
+                $aMethod['params'][1] = array(
+                    'file_id' => $aParams['file_id']
+                );
+
+                $sFieldsClause .= ", `tf`.`file_name`, `tf`.`size` AS `file_size`";
+                $sJoinClause = " LEFT JOIN `" . $this->_oConfig->CNF['TABLE_FILES'] . "` AS `tf` ON `tfe`.`file_id`=`tf`.`id` ";
+                $sWhereClause = " AND `tfe`.`file_id`=:file_id";
+                break;
+                
+
+            case 'content_id':
+            	$aMethod['name'] = 'getAll';
+            	$aMethod['params'][1] = array(
+                    'content_id' => $aParams['content_id']
+                );
+
+            	$sWhereClause = " AND `tfe`.`content_id`=:content_id";
+            	if(!empty($aParams['except']))
+                    $sWhereClause .= " AND `tfe`.`file_id` NOT IN (" . $this->implode_escape($aParams['except']) . ")";
+
+            	break;
+
+            case 'content_id_key_file_id':
+                $aMethod['name'] = 'getAllWithKey';
+                $aMethod['params'][1] = 'file_id';
+                $aMethod['params'][2] = array(
+                    'content_id' => $aParams['content_id']
+                );
+
+                $sWhereClause = " AND `tfe`.`content_id`=:content_id";
+                $sOrderClause = "`tfe`.`type` ASC, `tfe`.`order` DESC";
+                break;
+
+            case 'content_id_and_type':
+                $aMethod['name'] = 'getAll';
+            	$aMethod['params'][1] = array(
+                    'content_id' => $aParams['content_id'],
+                    'type' => $aParams['file_type']
+                );
+
+                $sFieldsClause .= ", `tf`.`file_name`, `tf`.`size` AS `file_size`";
+                $sJoinClause = " LEFT JOIN `" . $this->_oConfig->CNF['TABLE_FILES'] . "` AS `tf` ON `tfe`.`file_id`=`tf`.`id` ";
+                $sWhereClause = " AND `tfe`.`content_id`=:content_id AND `tfe`.`type`=:type";
+
+                if(!empty($aParams['version'])) {
+                    $aMethod['name'] = 'getRow';
+                    $aMethod['params'][1]['version'] = $aParams['version'];
+                    $sWhereClause .= " AND `tfe`.`version`=:version";
+                }
+
+                if(isset($aParams['ordered']) && $aParams['ordered'] === true)
+                    $sOrderClause = "`tfe`.`version` ASC";
+
+            	break;
+        }
+
+        if(!empty($sOrderClause))
+            $sOrderClause = " ORDER BY " . $sOrderClause;
+
+        if(!empty($sLimitClause))
+            $sLimitClause = " LIMIT " . $sLimitClause;
+
+        $aMethod['params'][0] = "SELECT
+                " . $sFieldsClause . "
+            FROM `" . $sTable . "` AS `tfe`" . $sJoinClause . "
+            WHERE 1" . $sWhereClause . $sOrderClause . $sLimitClause;
+        return call_user_func_array(array($this, $aMethod['name']), $aMethod['params']);
+    }
+
+	protected function _updateAttachment($sTable, $aSet, $aWhere)
+    {
+        $sQuery = "UPDATE `" . $sTable . "` SET " . $this->arrayToSQL($aSet) . " WHERE " . (!empty($aWhere) ? $this->arrayToSQL($aWhere, ' AND ') : "1");
+        return (int)$this->query($sQuery) > 0;
+    }
+}
+
+/** @} */

+ 1346 - 0
modules/boonex/market/updates/12.0.0_12.0.1/source/classes/BxMarketModule.php

@@ -0,0 +1,1346 @@
+<?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 array();
+
+    	$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 array();
+
+		$oStorage = BxDolStorage::getObjectInstance($CNF['OBJECT_STORAGE']);
+    	$oImagesTranscoder = BxDolTranscoderImage::getObjectInstance($CNF['OBJECT_IMAGES_TRANSCODER_SCREENSHOT']);
+
+    	$aResult = array();
+    	foreach($aPhotos as $aPhoto) 
+    		$aResult[] = array(
+    			'id' => $aPhoto['file_id'],
+    			'url_sm' => $oImagesTranscoder ? $oImagesTranscoder->getFileUrl($aPhoto['file_id']) : '',
+    			'url_bg' => $oStorage ? $oStorage->getFileUrlById($aPhoto['file_id']) : ''
+    		);
+
+		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));
+    }
+}
+
+/** @} */

+ 140 - 0
modules/boonex/market/updates/12.0.0_12.0.1/source/install/config.php

@@ -0,0 +1,140 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Market Market
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_market',
+    'title' => 'Market',
+    'note' => 'Market module.',
+    'version' => '12.0.1',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '12.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'
+    ),
+
+);
+
+/** @} */

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

@@ -0,0 +1,51 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'title' => 'Notifications',
+    'version_from' => '12.0.0',
+    'version_to' => '12.0.1',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '12.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/notifications/updates/update_12.0.0_12.0.1/',
+    'home_uri' => 'notifications_update_1200_1201',
+
+    'module_dir' => 'boonex/notifications/',
+    'module_uri' => 'notifications',
+
+    'db_prefix' => 'bx_notifications_',
+    'class_prefix' => 'BxNtfs',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 0,
+        'update_files' => 1,
+        'update_languages' => 0,
+        'clear_db_cache' => 0,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Notifications',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

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

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

+ 236 - 0
modules/boonex/notifications/updates/12.0.0_12.0.1/source/classes/BxNtfsConfig.php

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

+ 186 - 0
modules/boonex/notifications/updates/12.0.0_12.0.1/source/classes/BxNtfsCronNotify.php

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

+ 48 - 0
modules/boonex/notifications/updates/12.0.0_12.0.1/source/classes/BxNtfsCronQueue.php

@@ -0,0 +1,48 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Notifications Notifications
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxNtfsCronQueue extends BxDolCron
+{
+    protected $_sModule;
+    protected $_oModule;
+
+    public function __construct()
+    {
+    	$this->_sModule = 'bx_notifications';
+    	$this->_oModule = BxDolModule::getInstance($this->_sModule);
+
+        parent::__construct();
+    }
+
+    public function processing()
+    {
+        $iDeliveryTimeout = $this->_oModule->_oConfig->getDeliveryTimeout();
+        if($iDeliveryTimeout == 0)
+            return;
+
+        $aItems = $this->_oModule->_oDb->queueGet(array('type' => 'all_to_send', 'timeout' => $iDeliveryTimeout));
+        if(empty($aItems) || !is_array($aItems))
+            return;
+
+        $this->_oModule->_oDb->queueDeleteByIds(array_keys($aItems));
+
+        $aSent = array();
+        foreach($aItems as $aItem) {
+            $sMethod = 'sendNotification' . bx_gen_method_name($aItem['delivery']);
+            $oProfile = BxDolProfile::getInstance($aItem['profile_id']);
+
+            if($this->_oModule->$sMethod($oProfile, unserialize($aItem['content'])) !== false)
+                $aSent[] = $aItem['id'];
+        }
+    }
+}
+
+/** @} */

+ 341 - 0
modules/boonex/notifications/updates/12.0.0_12.0.1/source/classes/BxNtfsDb.php

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

+ 250 - 0
modules/boonex/notifications/updates/12.0.0_12.0.1/source/classes/BxNtfsGridSettingsAdministration.php

@@ -0,0 +1,250 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Notifications Notifications
+ * @ingroup     UnaModules
+ * 
+ * @{
+ */
+
+require_once(BX_DOL_DIR_STUDIO_INC . 'utils.inc.php');
+
+class BxNtfsGridSettingsAdministration extends BxTemplGrid
+{
+    protected $_sModule;
+    protected $_oModule;
+
+    protected $_bAdministration;
+
+    protected $_bGrouped;
+    protected $_sDeliveryType;
+    protected $_sTitleMask;
+
+    protected $_sSource;
+
+    public function __construct ($aOptions, $oTemplate = false)
+    {
+        parent::__construct ($aOptions, $oTemplate);
+
+        $this->_sModule = 'bx_notifications';
+        $this->_oModule = BxDolModule::getInstance($this->_sModule);
+
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        $this->_bAdministration = true;      
+
+        $this->_bGrouped = $this->_oModule->_oConfig->isSettingsGrouped();
+        if($this->_bGrouped)
+            $this->_aOptions['show_total_count'] = 0;
+
+        $this->_sDeliveryType = BX_BASE_MOD_NTFS_DTYPE_SITE;
+        $this->_sTitleMask = _t('_bx_ntfs_setting_title_mask', '%s', '%s');
+
+        $this->_sSource = '';
+
+        $sDeliveryType = bx_get('delivery_type');
+        if(!empty($sDeliveryType))
+            $this->setDeliveryType($sDeliveryType);
+
+        $this->init();
+    }
+
+    public function init()
+    {
+        if(!$this->_bGrouped && !isset($this->_aOptions['fields']['unit'], $this->_aOptions['fields']['type']))
+            $this->_aOptions['fields'] = bx_array_insert_after(array(
+                'unit' => array('title' => _t('_bx_ntfs_grid_column_title_unit'), 'width' => '10%', 'translatable' => 0 ,'chars_limit' => 0),
+                'type' => array('title' => _t('_bx_ntfs_grid_column_title_type'), 'width' => '20%', 'translatable' => 0 ,'chars_limit' => 0),
+            ), $this->_aOptions['fields'], 'switcher');
+    }
+
+    public function setGrouped($bGrouped)
+    {
+        $bReinit = $this->_bGrouped !== (boolean)$bGrouped;
+
+        $this->_bGrouped = $bGrouped;
+
+        if($bReinit)
+            $this->init();
+    }
+
+    public function setDeliveryType($sType)
+    {
+        $this->_sDeliveryType = bx_process_input($sType);
+        $this->_aQueryAppend['delivery_type'] = $this->_sDeliveryType;
+    }
+
+    public function performActionActivate()
+    {
+        parent::performActionEnable(1);
+    }
+
+    public function performActionDeactivate()
+    {
+        parent::performActionEnable(0);
+    }
+    
+    public function performActionChangeValue()
+    {
+        $aIds = bx_get('ids');
+        if(empty($aIds) || !is_array($aIds))
+            return echoJson(array());
+
+        $iId = array_shift($aIds);
+        $iValue = $this->_switcherChecked2State((int)bx_get('checked'));
+
+        if(!$this->_bGrouped)
+            $mixedResult = $this->_oModule->_oDb->updateSetting(array('value' => $iValue), array('id' => $iId));
+        else 
+            $mixedResult = $this->_oModule->_changeSettingsValueLike($iId, 'value', $iValue, $this->_bAdministration);
+
+        $aResult = array();
+        if($mixedResult === false)
+            $aResult = array('msg' => _t('_bx_ntfs_txt_err_cannot_perform'));
+        else if((int)$mixedResult == 0)
+            $aResult = array('msg' => _t('_bx_ntfs_txt_err_nothing_changed'));
+
+        return echoJson($aResult);
+    }
+
+    protected function _enable ($mixedId, $isChecked)
+    {
+        if(!$this->_bGrouped)
+            return parent::_enable($mixedId, $isChecked);
+
+        return $this->_oModule->enableSettingsLike($mixedId, $isChecked, $this->_bAdministration);
+    }
+
+    protected function _isCheckboxDisabled($aRow)
+    {
+        return false;
+    }
+
+    protected function _getFilterControls()
+    {
+        if($this->_bGrouped)
+            return '';
+
+        return parent::_getFilterControls();
+    }
+
+    protected function _getCellValue($mixedValue, $sKey, $aField, $aRow)
+    {
+        $sAttr = $this->_convertAttrs(
+            $aField, 'attr_cell',
+            'bx-def-padding-sec-bottom bx-def-padding-sec-top',
+            isset($aField['width']) ? 'width:' . $aField['width'] : false
+        );
+
+        $oForm = new BxTemplFormView(array(), $this->_oTemplate);
+        $oForm->addCssJs();
+        $aInput = array(
+            'type' => 'switcher',
+            'name' => $this->_sObject . '_change_value_' . $aRow[$this->_aOptions['field_id']],
+            'caption' => '',
+            'attrs' => array (
+                'bx_grid_action_single' => 'change_value',
+                'bx_grid_action_confirm' => '',
+                'bx_grid_action_data' => $aRow[$this->_aOptions['field_id']],
+            ),
+            'value' => $aRow[$this->_aOptions['field_id']],
+            'checked' => $this->_isSwitcherOn($mixedValue, $sKey, $aField, $aRow),
+        );
+        $sSwitcher = $oForm->genInput($aInput);
+        return '<td ' . $sAttr . '>' . $sSwitcher . '</td>';
+    }
+
+    protected function _getCellUnit($mixedValue, $sKey, $aField, $aRow)
+    {
+        return parent::_getCellDefault(_t($this->_oModule->_oConfig->getHandlersUnitTitle($mixedValue)), $sKey, $aField, $aRow);
+    }
+
+    protected function _getCellType($mixedValue, $sKey, $aField, $aRow)
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        return parent::_getCellDefault(_t($CNF['T']['setting_' . $mixedValue]), $sKey, $aField, $aRow);
+    }
+
+    protected function _getCellTitle($mixedValue, $sKey, $aField, $aRow)
+    {
+        if(empty($mixedValue)) {
+            $mixedValueKey = $this->_oModule->_oConfig->getHandlersActionTitle($aRow['unit'], $aRow['action'], $aRow['type']);
+            $mixedValue = _t($mixedValueKey);
+
+            if(strcmp($mixedValueKey, $mixedValue) !== 0)
+                $this->_updateSettingTitle($mixedValueKey, $aRow);
+        }
+
+        if($this->_bGrouped && $aRow['type'] == BX_NTFS_STYPE_OTHER)
+            $mixedValue = sprintf($this->_sTitleMask, _t($this->_oModule->_oConfig->getHandlersUnitTitle($aRow['unit'])), $mixedValue);
+
+        if($this->_bGrouped && !$this->_isSettingsGroupValid($aRow))
+            $mixedValue = $this->_oTemplate->parseIcon('exclamation-triangle', array('class' => 'bx-def-margin-sec-right', 'title' => _t('_bx_ntfs_grid_column_title_title_warning'))) . $mixedValue;
+
+        return parent::_getCellDefault($mixedValue, $sKey, $aField, $aRow);
+    }
+
+    protected function _getActionActivate($sType, $sKey, $a, $isSmall = false, $isDisabled = false, $aRow = array())
+    {
+    	return $this->_getActionDefault ($sType, $sKey, $a, $isSmall, $isDisabled, $aRow);
+    }
+
+    protected function _getActionDeactivate($sType, $sKey, $a, $isSmall = false, $isDisabled = false, $aRow = array())
+    {
+    	return $this->_getActionDefault ($sType, $sKey, $a, $isSmall, $isDisabled, $aRow);
+    }
+
+    protected function _getDataSql($sFilter, $sOrderField, $sOrderDir, $iStart, $iPerPage)
+    {
+        $this->_aOptions['source'] .= $this->_oModule->_oDb->prepareAsString(" AND `ts`.`delivery`=?", $this->_sDeliveryType);
+        if(!$this->_bGrouped)
+            return parent::_getDataSql($sFilter, $sOrderField, $sOrderDir, $iStart, $iPerPage);
+
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        $aResult = array();
+        $this->_sSource = $this->_aOptions['source'];
+
+        $aTypes = $this->_oModule->_oConfig->getSettingsTypes();
+        foreach($aTypes as $sType) {
+            $this->_aOptions['source'] = $this->_sSource . $this->_oModule->_oDb->prepareAsString(" AND `ts`.`type`=?", $sType) . " GROUP BY `ts`.`group`";
+
+            $aRows = parent::_getDataSql($sFilter, $sOrderField, $sOrderDir, $iStart, $iPerPage);
+            if(empty($aRows) || !is_array($aRows)) 
+                continue;
+
+            $aResult[] = _t($CNF['T']['setting_' . $sType]);
+            $aResult = array_merge($aResult, $aRows);
+        }
+
+        return $aResult;
+    }
+
+    protected function _updateSettingTitle($sTitle, &$aRow)
+    {
+        return $this->_oModule->_oDb->updateSetting(array('title' => $sTitle), array('id' => $aRow['id']));
+    }
+    
+    protected function _isSettingsGroupValid(&$aRow)
+    {
+        if(!$this->_bGrouped)
+            return true;
+
+        $iEnabled = $iDisabled = 0;
+
+        $sSql = $this->_sSource . $this->_oModule->_oDb->prepareAsString(" AND `ts`.`group`=? AND `ts`.`type`=?", $aRow['group'], $aRow['type']);
+        $aItems = $this->_oModule->_oDb->getAll($sSql);
+        foreach($aItems as $aItem) 
+            if((int)$aItem['active'] != 0)
+                $iEnabled += 1;
+            else 
+                $iDisabled += 1;
+
+        return $iEnabled == 0 || $iDisabled == 0;
+    }
+}
+
+/** @} */

+ 543 - 0
modules/boonex/notifications/updates/12.0.0_12.0.1/source/classes/BxNtfsModule.php

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

+ 82 - 0
modules/boonex/notifications/updates/12.0.0_12.0.1/source/install/config.php

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

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

@@ -0,0 +1,51 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'title' => 'Organizations',
+    'version_from' => '12.0.0',
+    'version_to' => '12.0.1',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '12.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_12.0.0_12.0.1/',
+    'home_uri' => 'orgs_update_1200_1201',
+
+    'module_dir' => 'boonex/organizations/',
+    'module_uri' => 'orgs',
+
+    'db_prefix' => 'bx_organizations_',
+    'class_prefix' => 'BxOrgs',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 0,
+        'update_files' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 0,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Organizations',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

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

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

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

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

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

@@ -0,0 +1,152 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Organizations Organizations
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_organizations',
+    'title' => 'Organizations',
+    'note' => 'Basic organization profiles functionality.',
+    'version' => '12.0.1',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '12.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/',
+    'home_uri' => 'orgs',
+
+    'db_prefix' => 'bx_organizations_',
+    'class_prefix' => 'BxOrgs',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Organizations',
+
+    /**
+     * Connections.
+     */
+    'connections' => array(
+    	'sys_profiles_friends' => array ('type' => 'profiles'),
+        'sys_profiles_subscriptions' => array ('type' => 'profiles'),
+        'sys_profiles_relations' => array ('type' => 'profiles'),
+    ),
+
+    /**
+     * Menu triggers.
+     */
+    'menu_triggers' => array(
+        'trigger_profile_view_submenu',
+        'trigger_profile_snippet_meta',
+        'trigger_profile_view_actions',
+    ),
+
+    /**
+     * Page triggers.
+     */
+    'page_triggers' => array (
+    	'trigger_page_profile_view_entry', 
+    ),
+
+	/**
+     * Storage objects to automatically delete files from upon module uninstallation.
+     * Note. Don't add storage objects used in transcoder objects.
+     */
+    'storages' => array(
+    	'bx_organizations_pics'
+    ),
+
+	/**
+     * Transcoders.
+     */
+    'transcoders' => array(
+    	'bx_organizations_icon', 
+    	'bx_organizations_thumb', 
+    	'bx_organizations_avatar', 
+        'bx_organizations_avatar_big', 
+    	'bx_organizations_picture', 
+    	'bx_organizations_cover', 
+    	'bx_organizations_cover_thumb',
+    	'bx_organizations_gallery'
+    ),
+
+	/**
+     * Extended Search Forms.
+     */
+    'esearches' => array(
+        'bx_organizations',
+    	'bx_organizations_cmts',
+    ),
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'uninstall' => array (
+    	'process_esearches' => 1,
+        'execute_sql' => 1,
+        'update_languages' => 1,
+    	'process_connections' => 1,
+    	'process_deleted_profiles' => 1,
+    	'update_relations' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'enable' => array(
+        'execute_sql' => 1,
+    	'update_relations' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'enable_success' => array(
+    	'process_menu_triggers' => 1,
+    	'process_page_triggers' => 1,
+    	'process_esearches' => 1,
+    	'register_transcoders' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable' => array (
+        'execute_sql' => 1,
+    	'unregister_transcoders' => 1,
+    	'update_relations' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable_failed' => array (
+    	'register_transcoders' => 1,
+    	'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Dependencies Section
+     */
+    'dependencies' => array(),
+
+    /**
+     * Connections Section
+     */
+    'relations' => array(
+        'bx_timeline',
+        'bx_notifications',
+    ),
+);
+
+/** @} */

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

@@ -0,0 +1,488 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources name="en" flag="gb" title="English">
+    <string name="_bx_orgs"><![CDATA[Organizations]]></string>
+    <string name="_bx_organizations"><![CDATA[Organizations]]></string>
+    <string name="_bx_orgs_cmts"><![CDATA[Organizations' Comments]]></string>
+
+    <string name="_bx_orgs_option_autoapproval"><![CDATA[Organization moderation]]></string>
+    <string name="_bx_orgs_option_default_acl_level"><![CDATA[Default level to assign after organizations's profile creation]]></string>
+    <string name="_bx_orgs_option_enable_profile_activation_letter"><![CDATA[Enable profile activation letter]]></string>
+    <string name="_bx_orgs_option_redirect_aadd"><![CDATA[Redirect after organizations's profile creation to]]></string>
+    <string name="_bx_orgs_option_redirect_aadd_profile"><![CDATA[Profile Page]]></string>
+    <string name="_bx_orgs_option_redirect_aadd_last"><![CDATA[Last Page]]></string>
+    <string name="_bx_orgs_option_redirect_aadd_custom"><![CDATA[Custom Page]]></string>
+    <string name="_bx_orgs_option_redirect_aadd_custom_url"><![CDATA[URL for 'Custom Page' redirect]]></string>
+    <string name="_bx_orgs_option_activation_on"><![CDATA[Auto-activate after creation & editing]]></string>
+    <string name="_bx_orgs_option_activation_add"><![CDATA[Manually activate after editing, auto-activate after creation]]></string>
+    <string name="_bx_orgs_option_activation_edit"><![CDATA[Manually activate after creating, auto-activate after editing]]></string>
+    <string name="_bx_orgs_option_activation_off"><![CDATA[Activate manually after creation & editing]]></string>
+    <string name="_bx_orgs_option_num_connections_quick"><![CDATA[Number of items in friends block]]></string>
+    <string name="_bx_orgs_option_per_page_browse"><![CDATA[Number of items per page]]></string>
+    <string name="_bx_orgs_option_num_rss"><![CDATA[Number of items in RSS feed]]></string>
+    <string name="_bx_orgs_option_searchable_fields"><![CDATA[Searchable fields for keyword search]]></string>
+    <string name="_bx_orgs_option_members_mode"><![CDATA[Special mode for organization members]]></string>
+    <string name="_bx_orgs_option_members_mode_multi_roles"><![CDATA[Multi Roles]]></string>
+    <string name="_bx_orgs_option_public_subscriptions"><![CDATA[Public following list]]></string>
+    <string name="_bx_orgs_option_public_subscribed_me"><![CDATA[Public followers list]]></string>
+    <string name="_bx_orgs_option_auto_activation_for_categories"><![CDATA[Auto-Activation For Categories]]></string>
+    <string name="_bx_orgs_option_per_page_for_favorites_lists"><![CDATA[Number of favorite lists per page]]></string>
+    <string name="_bx_orgs_option_internal_notifications"><![CDATA[Use internal notifications]]></string>
+
+    <string name="_bx_orgs_form_profile"><![CDATA[Organizations]]></string>
+    <string name="_bx_orgs_form_profile_display_add"><![CDATA[Add Organization]]></string>
+    <string name="_bx_orgs_form_profile_display_edit"><![CDATA[Edit Organization]]></string>
+    <string name="_bx_orgs_form_profile_display_edit_cover"><![CDATA[Edit Cover]]></string>
+    <string name="_bx_orgs_form_profile_display_delete"><![CDATA[Delete Organization]]></string>
+    <string name="_bx_orgs_form_profile_display_view"><![CDATA[View Organization]]></string>
+    <string name="_bx_orgs_form_profile_display_view_full"><![CDATA[Full View Organization]]></string>
+    <string name="_bx_orgs_form_profile_display_invite"><![CDATA[Invite to Organization]]></string>
+    <string name="_bx_orgs_form_profile_input_sys_do_submit"><![CDATA[Submit]]></string>
+    <string name="_bx_orgs_form_profile_input_sys_join_confirm"><![CDATA[Join confirmation]]></string>
+    <string name="_bx_orgs_form_profile_input_join_confirm"><![CDATA[Join confirmation]]></string>
+    <string name="_bx_orgs_form_profile_input_sys_allow_view_to"><![CDATA[Visible to]]></string>
+    <string name="_bx_orgs_form_profile_input_allow_view_to"><![CDATA[Visible to]]></string>
+    <string name="_bx_orgs_form_entry_input_allow_view_favorite_list"><![CDATA[Visibility]]></string>
+    <string name="_bx_orgs_form_profile_input_allow_view_to_info"><![CDATA[Closed - anyone can find the organization and see who's in it, only members can see posts. Secret - only members can find the organization and see posts.]]></string>
+    <string name="_bx_orgs_form_profile_input_allow_view_notification_to"><![CDATA[Show notifications to]]></string>
+    <string name="_bx_orgs_form_profile_input_sys_allow_post_to"><![CDATA[Who can post to my profile]]></string>
+    <string name="_bx_orgs_form_profile_input_allow_post_to"><![CDATA[Who can post to my profile]]></string>
+    <string name="_bx_orgs_form_profile_input_sys_allow_contact_to"><![CDATA[Who can contact me]]></string>
+    <string name="_bx_orgs_form_profile_input_allow_contact_to"><![CDATA[Who can contact me]]></string>
+    <string name="_bx_orgs_form_profile_input_sys_initial_members"><![CDATA[Invite Members]]></string>
+    <string name="_bx_orgs_form_profile_input_initial_members"><![CDATA[Invite Members]]></string>
+    <string name="_bx_orgs_form_profile_input_sys_org_name"><![CDATA[Organization Name]]></string>
+    <string name="_bx_orgs_form_profile_input_org_name"><![CDATA[Organization Name]]></string>
+    <string name="_bx_orgs_form_profile_input_org_name_err"><![CDATA[Profile name is mandatory and and cannot start with @]]></string>
+    <string name="_bx_orgs_form_profile_input_sys_org_desc"><![CDATA[Description]]></string>
+    <string name="_bx_orgs_form_profile_input_org_desc"><![CDATA[Description]]></string>
+    <string name="_bx_orgs_form_profile_input_sys_org_cat"><![CDATA[Category]]></string>
+    <string name="_bx_orgs_form_profile_input_org_cat"><![CDATA[Category]]></string>
+    <string name="_bx_orgs_form_profile_input_org_cat_err"><![CDATA[Category field is mandatory]]></string>
+    <string name="_bx_orgs_form_entry_input_sys_multicat"><![CDATA[Categories]]></string>
+    <string name="_bx_orgs_form_entry_input_multicat"><![CDATA[Categories]]></string>
+    <string name="_bx_orgs_form_entry_input_multicat_err"><![CDATA[Please select category]]></string>
+    <string name="_bx_orgs_form_profile_input_sys_picture"><![CDATA[Profile Picture]]></string>
+    <string name="_bx_orgs_form_profile_input_picture"><![CDATA[Upload a profile picture]]></string>
+    <string name="_bx_orgs_form_profile_input_picture_err"><![CDATA[Profile picture is mandatory.]]></string>
+    <string name="_bx_orgs_form_profile_input_picture_search"><![CDATA[With photo]]></string>
+    <string name="_bx_orgs_form_profile_input_online_search"><![CDATA[Online only]]></string>
+    <string name="_bx_orgs_form_profile_input_sys_cover"><![CDATA[Cover Picture]]></string>
+    <string name="_bx_orgs_form_profile_input_cover"><![CDATA[Upload New Cover Picture]]></string>
+    <string name="_bx_orgs_form_profile_input_sys_delete_confirm"><![CDATA[Delete confirmation]]></string>
+    <string name="_bx_orgs_form_profile_input_delete_confirm"><![CDATA[I am sure I want to delete this profile]]></string>
+    <string name="_bx_orgs_form_profile_input_delete_confirm_info"><![CDATA[This action can not be undone.]]></string>
+    <string name="_bx_orgs_form_profile_input_delete_confirm_error"><![CDATA[Please check this checkbox if you really want to delete your profile.]]></string>
+    <string name="_bx_orgs_form_profile_input_sys_profile_email"><![CDATA[Email]]></string>
+    <string name="_bx_orgs_form_profile_input_profile_email"><![CDATA[Email]]></string>
+    <string name="_bx_orgs_form_profile_input_sys_profile_status"><![CDATA[Status]]></string>
+    <string name="_bx_orgs_form_profile_input_profile_status"><![CDATA[Status]]></string>
+    <string name="_bx_orgs_form_profile_input_sys_profile_ip"><![CDATA[IP]]></string>
+    <string name="_bx_orgs_form_profile_input_profile_ip"><![CDATA[IP]]></string>
+    <string name="_bx_orgs_form_profile_input_sys_date_added"><![CDATA[Added]]></string>
+    <string name="_bx_orgs_form_profile_input_date_added"><![CDATA[Added]]></string>
+    <string name="_bx_orgs_form_profile_input_sys_date_changed"><![CDATA[Updated]]></string>
+    <string name="_bx_orgs_form_profile_input_date_changed"><![CDATA[Updated]]></string>
+    <string name="_bx_orgs_form_profile_input_sys_friends_count"><![CDATA[Friends count]]></string>
+    <string name="_bx_orgs_form_profile_input_friends_count"><![CDATA[Friends count]]></string>
+    <string name="_bx_orgs_form_profile_input_sys_followers_count"><![CDATA[Followers count]]></string>
+    <string name="_bx_orgs_form_profile_input_followers_count"><![CDATA[Followers count]]></string>
+
+	<string name="_bx_orgs_acl_action_create_profile"><![CDATA[Create Organization's Profile]]></string>
+	<string name="_bx_orgs_acl_action_delete_profile"><![CDATA[Delete Organization's Profile]]></string>
+	<string name="_bx_orgs_acl_action_view_profile"><![CDATA[View Organization's Profile]]></string>
+	<string name="_bx_orgs_acl_action_edit_any_profile"><![CDATA[Edit Any Organization's Profile]]></string>
+
+	<string name="_bx_orgs_page_title_sys_create_profile"><![CDATA[Create a Profile - Organization]]></string>
+	<string name="_bx_orgs_page_title_create_profile"><![CDATA[Create a Profile - Organization]]></string>
+	<string name="_bx_orgs_page_title_sys_edit_profile"><![CDATA[Edit Profile]]></string>
+	<string name="_bx_orgs_page_title_edit_profile"><![CDATA[Edit Profile]]></string>
+	<string name="_bx_orgs_page_title_sys_edit_profile_cover"><![CDATA[Edit Profile Cover]]></string>
+	<string name="_bx_orgs_page_title_edit_profile_cover"><![CDATA[Edit Cover]]></string>
+	<string name="_bx_orgs_page_title_sys_delete_profile"><![CDATA[Delete Profile]]></string>
+	<string name="_bx_orgs_page_title_delete_profile"><![CDATA[Delete Profile]]></string>
+	<string name="_bx_orgs_page_title_sys_view_profile"><![CDATA[View Profile]]></string>
+	<string name="_bx_orgs_page_title_sys_view_profile_closed"><![CDATA[View Profile with Limited Visibility]]></string>
+	<string name="_bx_orgs_page_title_view_profile"><![CDATA[{display_name}]]></string>
+	<string name="_bx_orgs_page_title_browse"><![CDATA[Organizations]]></string>
+	<string name="_bx_orgs_page_title_browse_by_author"><![CDATA[Organizations of {display_name}]]></string>
+	<string name="_bx_orgs_page_title_browse_featured"><![CDATA[Featured Organizations]]></string>
+	<string name="_bx_orgs_page_title_browse_active"><![CDATA[Active Organizations]]></string>
+	<string name="_bx_orgs_page_title_browse_online"><![CDATA[Online Organizations]]></string>
+	<string name="_bx_orgs_page_title_browse_recent"><![CDATA[New Organizations]]></string>
+	<string name="_bx_orgs_page_title_browse_connections"><![CDATA[{0} connections]]></string>
+	<string name="_bx_orgs_page_title_browse_connections_mutual"><![CDATA[{0} and {1} mutual connections]]></string>
+	<string name="_bx_orgs_page_title_browse_favorites"><![CDATA[{0} favorites]]></string>
+	<string name="_bx_orgs_page_title_browse_by_acl"><![CDATA[{0} Organizations]]></string>
+	<string name="_bx_orgs_page_title_browse_by_cmts"><![CDATA[Organizations' Comments]]></string>
+	<string name="_bx_orgs_page_title_sys_profile_favorites"><![CDATA[Favorite Organizations]]></string>
+	<string name="_bx_orgs_page_title_profile_favorites"><![CDATA[Favorite Organizations]]></string>
+	<string name="_bx_orgs_page_title_sys_profile_friends"><![CDATA[Friends]]></string>
+	<string name="_bx_orgs_page_title_profile_friends"><![CDATA[Friends]]></string>
+	<string name="_bx_orgs_page_title_sys_friend_requests"><![CDATA[Friend Requests]]></string>
+    <string name="_bx_orgs_page_title_friend_requests"><![CDATA[Friend Requests]]></string>
+	<string name="_bx_orgs_page_title_sys_profile_subscriptions"><![CDATA[Following]]></string>
+    <string name="_bx_orgs_page_title_profile_subscriptions"><![CDATA[Following & Followers]]></string>
+    <string name="_bx_orgs_page_title_sys_profile_relations"><![CDATA[Relationships]]></string>
+    <string name="_bx_orgs_page_title_profile_relations"><![CDATA[Relationships]]></string>
+    <string name="_bx_orgs_page_title_sys_fans"><![CDATA[Members]]></string>
+    <string name="_bx_orgs_page_title_fans"><![CDATA[Members]]></string>
+    <string name="_bx_orgs_page_title_sys_profile_comments"><![CDATA[Comments]]></string>
+    <string name="_bx_orgs_page_title_profile_comments"><![CDATA[Comments]]></string>
+	<string name="_bx_orgs_page_title_sys_profile_info"><![CDATA[Profile Info]]></string>
+	<string name="_bx_orgs_page_title_profile_info"><![CDATA[Info about {display_name}]]></string>
+	<string name="_bx_orgs_page_title_sys_recent"><![CDATA[New Organizations]]></string>
+	<string name="_bx_orgs_page_title_recent"><![CDATA[New Organizations]]></string>
+	<string name="_bx_orgs_page_title_sys_manage"><![CDATA[Manage Own Organizations]]></string>
+	<string name="_bx_orgs_page_title_sys_manage_administration"><![CDATA[Manage All Organizations]]></string>
+	<string name="_bx_orgs_page_title_manage"><![CDATA[Manage Organizations]]></string>
+	<string name="_bx_orgs_page_title_sys_active"><![CDATA[Active Organizations]]></string>
+	<string name="_bx_orgs_page_title_active"><![CDATA[Active Organizations]]></string>
+	<string name="_bx_orgs_page_title_sys_online"><![CDATA[Online Organizations]]></string>
+	<string name="_bx_orgs_page_title_online"><![CDATA[Online Organizations]]></string>
+	<string name="_bx_orgs_page_title_sys_invite_to_organization"><![CDATA[Invite Members to the Organization]]></string>
+    <string name="_bx_orgs_page_title_invite_to_organization"><![CDATA[Invite Members to the Organization]]></string>
+	<string name="_bx_orgs_page_title_sys_entries_search"><![CDATA[Search]]></string>
+    <string name="_bx_orgs_page_title_entries_search"><![CDATA[Search]]></string>
+    <string name="_bx_orgs_page_title_sys_entries_favorites"><![CDATA[Favorives Organizations]]></string>
+    <string name="_bx_orgs_page_title_entries_favorites"><![CDATA[Favorives Organizations]]></string>
+    <string name="_bx_orgs_page_title_sys_joined_entries"><![CDATA[Joined Organizations]]></string>
+    <string name="_bx_orgs_page_title_joined_entries"><![CDATA[Joined Organizations]]></string>
+
+    <string name="_bx_orgs_page_block_title_profile_private"><![CDATA[Private Profile]]></string>
+    <string name="_bx_orgs_page_block_title_choose_type"><![CDATA[Choose Profile Type]]></string>
+	<string name="_bx_orgs_page_block_title_create_profile"><![CDATA[Create a Profile - Organization]]></string>
+	<string name="_bx_orgs_page_block_title_edit_profile"><![CDATA[Edit Profile]]></string>
+	<string name="_bx_orgs_page_block_title_edit_profile_cover"><![CDATA[Edit Cover]]></string>
+	<string name="_bx_orgs_page_block_title_delete_profile"><![CDATA[Delete Profile]]></string>
+	<string name="_bx_orgs_page_block_title_profile_all_actions"><![CDATA[All Actions]]></string>
+	<string name="_bx_orgs_page_block_title_profile_info_link"><![CDATA[About <a href="{profile_link}">{display_name}</a>]]></string>
+	<string name="_bx_orgs_page_block_title_profile_info"><![CDATA[Info]]></string>
+	<string name="_bx_orgs_page_block_title_system_profile_info"><![CDATA[Info]]></string>
+	<string name="_bx_orgs_page_block_title_profile_membership"><![CDATA[Membership]]></string>
+	<string name="_bx_orgs_page_block_title_system_profile_membership"><![CDATA[Membership]]></string>
+	<string name="_bx_orgs_page_block_title_profile_description"><![CDATA[Description]]></string>
+	<string name="_bx_orgs_page_block_title_profile_favorites"><![CDATA[Favorite Organizations]]></string>
+	<string name="_bx_orgs_page_block_title_system_profile_favorites"><![CDATA[Favorite Organizations]]></string>
+	<string name="_bx_orgs_page_block_title_profile_friends_link"><![CDATA[Friends of <a href="{profile_link}">{display_name}</a>]]></string>
+	<string name="_bx_orgs_page_block_title_profile_friends"><![CDATA[Friends]]></string>
+	<string name="_bx_orgs_page_block_title_system_profile_friends"><![CDATA[Friends]]></string>
+	<string name="_bx_orgs_page_block_title_friend_requests_link"><![CDATA[Friend Requests for <a href="{profile_link}">{display_name}</a>]]></string>
+    <string name="_bx_orgs_page_block_title_system_friend_requests"><![CDATA[Friend Requests]]></string>
+    <string name="_bx_orgs_page_block_title_admins"><![CDATA[Administrators]]></string>
+    <string name="_bx_orgs_page_block_title_fans_link"><![CDATA[Members of <a href="{profile_link}">{display_name}</a>]]></string>
+    <string name="_bx_orgs_page_block_title_fans"><![CDATA[Members]]></string>
+    <string name="_bx_orgs_page_block_title_system_fans"><![CDATA[Members]]></string>
+	<string name="_bx_orgs_page_block_title_profile_location"><![CDATA[Location]]></string>
+	<string name="_bx_orgs_page_block_title_system_profile_subscriptions"><![CDATA[Following]]></string>
+    <string name="_bx_orgs_page_block_title_profile_subscriptions"><![CDATA[Following]]></string>
+    <string name="_bx_orgs_page_block_title_system_profile_subscribed_me"><![CDATA[Followers]]></string>
+    <string name="_bx_orgs_page_block_title_profile_subscribed_me"><![CDATA[Followers]]></string>
+    <string name="_bx_orgs_page_block_title_system_profile_relations"><![CDATA[Relationships]]></string>
+    <string name="_bx_orgs_page_block_title_profile_relations"><![CDATA[Relationships]]></string>
+    <string name="_bx_orgs_page_block_title_system_profile_related_me"><![CDATA[Relationships with Me]]></string>
+    <string name="_bx_orgs_page_block_title_profile_related_me"><![CDATA[Relationships with Me]]></string>
+    <string name="_bx_orgs_page_block_title_profile_comments"><![CDATA[Comments]]></string>
+    <string name="_bx_orgs_page_block_title_profile_comments_link"><![CDATA[Comments to <a href="{entry_link}">{title}</a>]]></string>
+    <string name="_bx_orgs_page_block_title_profile_actions"><![CDATA[Actions]]></string>
+    <string name="_bx_orgs_page_block_title_featured_profiles"><![CDATA[Featured Organizations]]></string>
+    <string name="_bx_orgs_page_block_title_latest_profiles"><![CDATA[New Organizations]]></string>
+    <string name="_bx_orgs_page_block_title_system_manage"><![CDATA[Manage Own Organizations]]></string>
+    <string name="_bx_orgs_page_block_title_system_manage_administration"><![CDATA[Manage All Organizations]]></string>
+    <string name="_bx_orgs_page_block_title_manage"><![CDATA[Manage Organizations]]></string>
+    <string name="_bx_orgs_page_block_title_sys_active_profiles"><![CDATA[Active Organizations]]></string>
+    <string name="_bx_orgs_page_block_title_sys_multicats"><![CDATA[Organizations Categories(Multi)]]></string>
+    <string name="_bx_orgs_page_block_title_multicats"><![CDATA[Organizations Categories]]></string>
+    <string name="_bx_orgs_page_block_title_active_profiles"><![CDATA[Active Organizations]]></string>
+    <string name="_bx_orgs_page_block_title_online_profiles"><![CDATA[Online Organizations]]></string>
+    <string name="_bx_orgs_page_block_title_categories"><![CDATA[Organization categories]]></string>
+    <string name="_bx_orgs_page_block_title_invite_to_organization"><![CDATA[Invite Members to the Organization]]></string>
+    <string name="_bx_orgs_page_block_title_search_form"><![CDATA[Search Form]]></string>
+    <string name="_bx_orgs_page_block_title_search_results"><![CDATA[Search Results]]></string>
+    <string name="_bx_orgs_page_block_title_search_form_cmts"><![CDATA[Comments Search Form]]></string>
+    <string name="_bx_orgs_page_block_title_search_results_cmts"><![CDATA[Comments Search Results]]></string>
+    <string name="_bx_orgs_page_block_title_favorites_of_author"><![CDATA[Favorite Organizations]]></string>
+    <string name="_bx_orgs_page_block_title_sys_favorites_of_author"><![CDATA[Favorite Organizations]]></string>
+    <string name="_bx_orgs_page_block_title_favorites_entries"><![CDATA["{title}" List]]></string>
+    <string name="_bx_orgs_page_block_title_favorites_entries_info"><![CDATA[Info]]></string>
+    <string name="_bx_orgs_page_block_title_favorites_entries_actions"><![CDATA[Favorites List Actions]]></string>
+    <string name="_bx_orgs_page_block_title_sys_joined_entries"><![CDATA[Joined Organizations]]></string>
+    <string name="_bx_orgs_page_block_title_joined_entries"><![CDATA[Joined Organizations]]></string>
+    <string name="_bx_orgs_page_block_title_sys_entries_actions"><![CDATA[Organizations actions]]></string>
+    <string name="_bx_orgs_page_block_title_entries_actions"><![CDATA[Organizations actions]]></string>
+    <string name="_bx_orgs_page_block_title_sys_featured_entries_view_showcase"><![CDATA[Featured Organizations (Showcase View)]]></string>
+    <string name="_bx_orgs_page_block_title_featured_entries_view_showcase"><![CDATA[Featured Organizations]]></string>
+    <string name="_bx_orgs_page_block_title_sys_recommended_entries_view_showcase"><![CDATA[Recommended Organizations (Showcase View)]]></string>
+    <string name="_bx_orgs_page_block_title_recommended_entries_view_showcase"><![CDATA[Recommended Organizations]]></string>
+    <string name="_bx_orgs_page_block_title_sys_active_entries_view_showcase"><![CDATA[Active Organizations (Showcase View)]]></string>
+    <string name="_bx_orgs_page_block_title_active_entries_view_showcase"><![CDATA[Active Organizations]]></string>
+
+    <string name="_bx_orgs_menu_title_submenu"><![CDATA[Organizations Submenu]]></string>
+    <string name="_bx_orgs_menu_set_title_submenu"><![CDATA[Organizations Submenu]]></string>
+    <string name="_bx_orgs_menu_set_title_view_profile_actions"><![CDATA[Organization Actions]]></string>
+    <string name="_bx_orgs_menu_title_view_profile_actions"><![CDATA[Organization Actions]]></string>
+    <string name="_bx_orgs_menu_set_title_view_profile_actions_more"><![CDATA[Organization More Actions]]></string>
+    <string name="_bx_orgs_menu_title_view_profile_actions_more"><![CDATA[Organization More Actions]]></string>
+    <string name="_bx_orgs_menu_set_title_view_profile_submenu"><![CDATA[View Organization Submenu]]></string>
+    <string name="_bx_orgs_menu_title_view_profile_submenu"><![CDATA[View Organization Submenu]]></string>
+    <string name="_bx_orgs_menu_title_view_profile_submenu_cover"><![CDATA[Organization Cover Submenu]]></string>
+    <string name="_bx_orgs_menu_title_entries_my"><![CDATA[Profile Organizations Action Menu]]></string>
+    <string name="_bx_orgs_menu_set_title_entries_my"><![CDATA[Profile Organizations Menu]]></string>
+	<string name="_bx_orgs_menu_set_title_manage_tools"><![CDATA[Manage Tools Submenu]]></string>
+    <string name="_bx_orgs_menu_title_manage_tools"><![CDATA[Manage Tools Submenu]]></string>
+    <string name="_bx_orgs_menu_item_title_system_delete"><![CDATA[Delete]]></string>
+    <string name="_bx_orgs_menu_item_title_delete"><![CDATA[Delete]]></string>
+    <string name="_bx_orgs_menu_item_title_system_delete_with_content"><![CDATA[Delete With Content]]></string>
+    <string name="_bx_orgs_menu_item_title_delete_with_content"><![CDATA[Delete With Content]]></string>
+    <string name="_bx_orgs_menu_item_title_system_clear_reports"><![CDATA[Clear reports]]></string>
+    <string name="_bx_orgs_menu_item_title_clear_reports"><![CDATA[Clear reports]]></string>
+    <string name="_bx_orgs_menu_item_title_system_edit_cover"><![CDATA[Edit Cover]]></string>
+    <string name="_bx_orgs_menu_item_title_edit_cover"><![CDATA[Edit Cover]]></string>
+    <string name="_bx_orgs_menu_item_title_system_edit_profile"><![CDATA[Edit Organization]]></string>
+    <string name="_bx_orgs_menu_item_title_edit_profile"><![CDATA[Edit Profile]]></string>
+    <string name="_bx_orgs_menu_item_title_system_delete_profile"><![CDATA[Delete Organization]]></string>
+    <string name="_bx_orgs_menu_item_title_delete_profile"><![CDATA[Delete Profile]]></string>
+    <string name="_bx_orgs_menu_item_title_system_delete_account"><![CDATA[Delete Account]]></string>
+    <string name="_bx_orgs_menu_item_title_delete_account"><![CDATA[Delete Account]]></string>
+    <string name="_bx_orgs_menu_item_title_system_delete_account_content"><![CDATA[Delete Account with Content]]></string>
+    <string name="_bx_orgs_menu_item_title_delete_account_content"><![CDATA[Delete Account with Content]]></string>
+    <string name="_bx_orgs_menu_item_title_system_profile_type"><![CDATA[Organization]]></string>
+    <string name="_bx_orgs_menu_item_title_profile_type"><![CDATA[Organization]]></string>
+    <string name="_bx_orgs_menu_item_title_system_create_profile"><![CDATA[Organization]]></string>
+    <string name="_bx_orgs_menu_item_title_create_profile"><![CDATA[Organization]]></string>
+    <string name="_bx_orgs_menu_item_title_system_new_profile"><![CDATA[New Organization]]></string>
+    <string name="_bx_orgs_menu_item_title_new_profile"><![CDATA[New Organization]]></string>
+    <string name="_bx_orgs_menu_item_title_system_view_profile_fans"><![CDATA[Members]]></string>
+    <string name="_bx_orgs_menu_item_title_view_profile_fans"><![CDATA[Members]]></string>
+    <string name="_bx_orgs_menu_item_title_system_view_profile_friends"><![CDATA[Friends]]></string>
+    <string name="_bx_orgs_menu_item_title_view_profile_friends"><![CDATA[Friends]]></string>
+    <string name="_bx_orgs_menu_item_title_system_view_profile_relations"><![CDATA[Relationships]]></string>
+    <string name="_bx_orgs_menu_item_title_view_profile_relations"><![CDATA[Relationships]]></string>
+    <string name="_bx_orgs_menu_item_title_system_view_profile_subscriptions"><![CDATA[Following]]></string>
+    <string name="_bx_orgs_menu_item_title_view_profile_subscriptions"><![CDATA[Following]]></string>
+    <string name="_bx_orgs_menu_item_title_system_view_profile_comments"><![CDATA[Comments]]></string>
+    <string name="_bx_orgs_menu_item_title_view_profile_comments"><![CDATA[Comments]]></string>
+    <string name="_bx_orgs_menu_item_title_system_view_profile_info"><![CDATA[Info]]></string>
+    <string name="_bx_orgs_menu_item_title_view_profile_info"><![CDATA[Info]]></string>
+    <string name="_bx_orgs_menu_item_title_system_view_profile_view"><![CDATA[Organization]]></string>
+    <string name="_bx_orgs_menu_item_title_view_profile_view"><![CDATA[Organization]]></string>
+    <string name="_bx_orgs_menu_item_title_system_view_profile_more_auto"><![CDATA[More]]></string>
+    <string name="_bx_orgs_menu_item_title_view_profile_more_auto"><![CDATA[More]]></string>
+    <string name="_bx_orgs_menu_item_title_system_view_joined_groups"><![CDATA[Organizations]]></string>
+    <string name="_bx_orgs_menu_item_title_view_joined_groups"><![CDATA[Organizations]]></string>
+    <string name="_bx_orgs_menu_item_title_system_invite"><![CDATA[Invite]]></string>
+    <string name="_bx_orgs_menu_item_title_invite"><![CDATA[Invite]]></string>
+    <string name="_bx_orgs_menu_item_title_system_befriend"><![CDATA[Add friend]]></string>
+    <string name="_bx_orgs_menu_item_title_befriend"><![CDATA[Add friend]]></string>
+    <string name="_bx_orgs_menu_item_title_befriend_sent"><![CDATA[Add friend (requested)]]></string>
+    <string name="_bx_orgs_menu_item_title_befriend_confirm"><![CDATA[Accept friend request]]></string>
+    <string name="_bx_orgs_menu_item_title_system_unfriend"><![CDATA[Unfriend]]></string>
+    <string name="_bx_orgs_menu_item_title_unfriend"><![CDATA[Unfriend]]></string>
+    <string name="_bx_orgs_menu_item_title_unfriend_cancel_request"><![CDATA[Cancel friend request]]></string>
+    <string name="_bx_orgs_menu_item_title_unfriend_reject_request"><![CDATA[Reject friend request]]></string>
+    <string name="_bx_orgs_menu_item_title_system_become_fan"><![CDATA[Join Organization]]></string>
+    <string name="_bx_orgs_menu_item_title_become_fan"><![CDATA[Join Organization]]></string>
+    <string name="_bx_orgs_menu_item_title_become_fan_sent"><![CDATA[Join Organization (requested)]]></string>
+    <string name="_bx_orgs_menu_item_title_become_fan_confirm"><![CDATA[Accept Request]]></string>
+    <string name="_bx_orgs_menu_item_title_system_leave_organization"><![CDATA[Leave Organization]]></string>
+    <string name="_bx_orgs_menu_item_title_leave_organization"><![CDATA[Leave Organization]]></string>
+    <string name="_bx_orgs_menu_item_title_leave_organization_cancel_request"><![CDATA[Cancel Request]]></string>
+    <string name="_bx_orgs_menu_item_title_leave_organization_reject_request"><![CDATA[Reject Request]]></string>
+    <string name="_bx_orgs_menu_item_title_system_subscribe"><![CDATA[Follow]]></string>
+    <string name="_bx_orgs_menu_item_title_subscribe"><![CDATA[Follow]]></string>
+    <string name="_bx_orgs_menu_item_title_system_unsubscribe"><![CDATA[Unfollow]]></string>
+    <string name="_bx_orgs_menu_item_title_unsubscribe"><![CDATA[Unfollow]]></string>
+    <string name="_bx_orgs_menu_item_title_system_relation_add"><![CDATA[Add Relationship]]></string>
+    <string name="_bx_orgs_menu_item_title_relation_add"><![CDATA[Add Relationship]]></string>
+    <string name="_bx_orgs_menu_item_title_system_relation_delete"><![CDATA[Remove Relationship]]></string>
+    <string name="_bx_orgs_menu_item_title_relation_delete"><![CDATA[Remove Relationship]]></string>
+    <string name="_bx_orgs_menu_item_title_system_more_actions"><![CDATA[More Actions]]></string>
+    <string name="_bx_orgs_menu_item_title_more_actions"><![CDATA[]]></string>
+    <string name="_bx_orgs_menu_item_title_system_friends"><![CDATA[Friends]]></string>
+    <string name="_bx_orgs_menu_item_title_friends"><![CDATA[Friends]]></string>
+    <string name="_bx_orgs_menu_item_title_system_friend_requests"><![CDATA[Friend requests number]]></string>
+    <string name="_bx_orgs_menu_item_title_friend_requests"><![CDATA[Friend requests]]></string>
+    <string name="_bx_orgs_menu_item_title_system_relations"><![CDATA[Relationships]]></string>
+    <string name="_bx_orgs_menu_item_title_relations"><![CDATA[Relationships]]></string>
+    <string name="_bx_orgs_menu_item_title_system_manage_my_organizations"><![CDATA[My organizations]]></string>
+    <string name="_bx_orgs_menu_item_title_manage_my_organizations"><![CDATA[Organizations]]></string>
+    <string name="_bx_orgs_menu_item_title_system_favorites"><![CDATA[Favorite Organizations]]></string>
+    <string name="_bx_orgs_menu_item_title_favorites"><![CDATA[Favorite organizations]]></string>
+    <string name="_bx_orgs_menu_item_title_system_subscriptions"><![CDATA[Following]]></string>
+    <string name="_bx_orgs_menu_item_title_subscriptions"><![CDATA[Following]]></string>
+    <string name="_bx_orgs_menu_item_title_system_subscribed_me"><![CDATA[Followers]]></string>
+    <string name="_bx_orgs_menu_item_title_subscribed_me"><![CDATA[Followers]]></string>
+    <string name="_bx_orgs_menu_item_title_system_relations"><![CDATA[Relationships]]></string>
+    <string name="_bx_orgs_menu_item_title_relations"><![CDATA[Relationships]]></string>
+    <string name="_bx_orgs_menu_item_title_system_related_me"><![CDATA[Relationships with Me]]></string>
+    <string name="_bx_orgs_menu_item_title_related_me"><![CDATA[Relationships with Me]]></string>
+    <string name="_bx_orgs_menu_item_title_system_entries_recent"><![CDATA[New]]></string>
+    <string name="_bx_orgs_menu_item_title_entries_recent"><![CDATA[New]]></string>
+    <string name="_bx_orgs_menu_item_title_system_entries_search"><![CDATA[Search]]></string>
+    <string name="_bx_orgs_menu_item_title_entries_search"><![CDATA[Search]]></string>
+    <string name="_bx_orgs_menu_item_title_system_entries_manage"><![CDATA[Manage]]></string>
+    <string name="_bx_orgs_menu_item_title_entries_manage"><![CDATA[Manage]]></string>
+    <string name="_bx_orgs_menu_item_title_system_entries_home"><![CDATA[Orgs]]></string>
+    <string name="_bx_orgs_menu_item_title_entries_home"><![CDATA[Orgs]]></string>
+    <string name="_bx_orgs_menu_item_title_system_admt_organizations"><![CDATA[Organizations]]></string>
+	<string name="_bx_orgs_menu_item_title_admt_organizations"><![CDATA[Organizations]]></string>
+	<string name="_bx_orgs_menu_item_title_manage_my"><![CDATA[My Organizations]]></string>
+	<string name="_bx_orgs_menu_item_title_manage_all"><![CDATA[All Organizations]]></string>
+	<string name="_bx_orgs_menu_item_title_system_entries_active"><![CDATA[Active]]></string>
+	<string name="_bx_orgs_menu_item_title_entries_active"><![CDATA[Active]]></string>
+	<string name="_bx_orgs_menu_item_title_system_entries_online"><![CDATA[Online]]></string>
+	<string name="_bx_orgs_menu_item_title_entries_online"><![CDATA[Online]]></string>
+
+	<string name="_bx_orgs_grid_filter_item_title_adm_select_one_filter1"><![CDATA[All Statuses]]></string>
+	<string name="_bx_orgs_grid_filter_item_title_adm_select_one_filter2"><![CDATA[All]]></string>
+	<string name="_bx_orgs_grid_filter_item_title_adm_active"><![CDATA[Active]]></string>
+	<string name="_bx_orgs_grid_filter_item_title_adm_pending"><![CDATA[Pending]]></string>
+  <string name="_bx_orgs_grid_filter_item_title_adm_unconfirmed"><![CDATA[Unconfirmed]]></string>
+	<string name="_bx_orgs_grid_filter_item_title_adm_suspended"><![CDATA[Suspended]]></string>
+	<string name="_bx_orgs_grid_column_title_adm_active"><![CDATA[Active]]></string>
+    <string name="_bx_orgs_grid_column_title_adm_fullname"><![CDATA[Name]]></string>
+    <string name="_bx_orgs_grid_column_title_adm_last_online"><![CDATA[Last Logged]]></string>
+    <string name="_bx_orgs_grid_column_title_adm_account"><![CDATA[Account]]></string>
+    <string name="_bx_orgs_grid_action_title_adm_delete"><![CDATA[Delete]]></string>
+    <string name="_bx_orgs_grid_action_title_adm_delete_with_content"><![CDATA[Delete With Content]]></string>
+    <string name="_bx_orgs_grid_action_title_adm_clear_reports"><![CDATA[Clear reports]]></string>
+    <string name="_bx_orgs_grid_action_title_adm_set_acl_level"><![CDATA[Set Membership]]></string>
+    <string name="_bx_orgs_grid_action_title_adm_more_actions"><![CDATA[More Actions]]></string>
+    <string name="_bx_orgs_grid_action_title_adm_audit_content"><![CDATA[Audit actions with profile]]></string>
+    <string name="_bx_orgs_grid_action_title_adm_audit_profile"><![CDATA[Audit profile's actions]]></string>
+    <string name="_bx_orgs_grid_action_err_delete"><![CDATA[Cannot delete the selected organization(s).]]></string>
+    <string name="_bx_orgs_grid_txt_account_manager"><![CDATA[Redirect to manage account.]]></string>
+
+    <string name="_bx_orgs_chart_growth"><![CDATA[Organizations: Growth]]></string>
+    <string name="_bx_orgs_chart_growth_speed"><![CDATA[Organizations: Growth Speed]]></string>
+
+    <string name="_bx_orgs_search_extended"><![CDATA[Organizations Search]]></string>
+    <string name="_bx_orgs_search_extended_cmts"><![CDATA[Organizations Comments Search]]></string>
+
+    <string name="_bx_orgs_txt_account_pending"><![CDATA[This profile is pending approval, please wait until it is activated.]]></string>
+    <string name="_bx_orgs_txt_account_pending_moderation"><![CDATA[This <a href="{0}">profile</a> is pending approval.]]></string>
+    <string name="_bx_orgs_txt_account_suspended"><![CDATA[This profile is suspended.]]></string>
+    <string name="_bx_orgs_txt_account_suspended_moderation"><![CDATA[This <a href="{0}">profile</a> is suspended.]]></string>
+
+    <string name="_bx_orgs_pre_lists_cats"><![CDATA[Organization categories]]></string>
+    <string name="_bx_orgs_cat_Agriculture"><![CDATA[Agriculture]]></string>
+    <string name="_bx_orgs_cat_Financial"><![CDATA[Financial]]></string>
+    <string name="_bx_orgs_cat_Biotech"><![CDATA[Biotech]]></string>
+    <string name="_bx_orgs_cat_Cause"><![CDATA[Cause]]></string>
+    <string name="_bx_orgs_cat_Chemical"><![CDATA[Chemical]]></string>
+    <string name="_bx_orgs_cat_Religious"><![CDATA[Religious]]></string>
+    <string name="_bx_orgs_cat_Community"><![CDATA[Community]]></string>
+    <string name="_bx_orgs_cat_Company"><![CDATA[Company]]></string>
+    <string name="_bx_orgs_cat_Entertainment"><![CDATA[Entertainment]]></string>
+    <string name="_bx_orgs_cat_Technology"><![CDATA[Technology]]></string>
+    <string name="_bx_orgs_cat_Consulting"><![CDATA[Consulting]]></string>
+    <string name="_bx_orgs_cat_Education"><![CDATA[Education]]></string>
+    <string name="_bx_orgs_cat_Energy"><![CDATA[Energy]]></string>
+    <string name="_bx_orgs_cat_Engineering"><![CDATA[Engineering]]></string>
+    <string name="_bx_orgs_cat_Food"><![CDATA[Food]]></string>
+    <string name="_bx_orgs_cat_Government"><![CDATA[Government]]></string>
+    <string name="_bx_orgs_cat_Health"><![CDATA[Health]]></string>
+    <string name="_bx_orgs_cat_Medical"><![CDATA[Medical]]></string>
+    <string name="_bx_orgs_cat_Industrial"><![CDATA[Industrial]]></string>
+    <string name="_bx_orgs_cat_Insurance"><![CDATA[Insurance]]></string>
+    <string name="_bx_orgs_cat_Internet"><![CDATA[Internet]]></string>
+    <string name="_bx_orgs_cat_Software"><![CDATA[Software]]></string>
+    <string name="_bx_orgs_cat_Legal"><![CDATA[Legal]]></string>
+    <string name="_bx_orgs_cat_Media"><![CDATA[Media]]></string>
+    <string name="_bx_orgs_cat_School"><![CDATA[School]]></string>
+    <string name="_bx_orgs_cat_NGO"><![CDATA[NGO]]></string>
+    <string name="_bx_orgs_cat_NPO"><![CDATA[NPO]]></string>
+    <string name="_bx_orgs_cat_Political"><![CDATA[Political]]></string>
+    <string name="_bx_orgs_cat_Retail"><![CDATA[Retail]]></string>
+    <string name="_bx_orgs_cat_Small_Business"><![CDATA[Small Business]]></string>
+    <string name="_bx_orgs_cat_Telecommunication"><![CDATA[Telecommunication]]></string>
+    <string name="_bx_orgs_cat_Transport"><![CDATA[Transport]]></string>
+    <string name="_bx_orgs_cat_Travel"><![CDATA[Travel]]></string>
+    <string name="_bx_orgs_cat_University"><![CDATA[University]]></string>
+    <string name="_bx_orgs_cat_Other"><![CDATA[Other]]></string>
+
+    <string name="_bx_orgs_pre_lists_roles"><![CDATA[Organization roles]]></string>
+    <string name="_bx_orgs_role_regular"><![CDATA[Regular]]></string>
+    <string name="_bx_orgs_role_administrator"><![CDATA[Administrator]]></string>
+    <string name="_bx_orgs_role_moderator"><![CDATA[Moderator]]></string>
+
+    <string name="_bx_organizations_alert_action_fan_added"><![CDATA[member joined]]></string>
+    <string name="_bx_organizations_alert_action_join_invitation_notif"><![CDATA[join invitation]]></string>
+    <string name="_bx_organizations_alert_action_join_request"><![CDATA[join request]]></string>
+    <string name="_bx_organizations_alert_action_profile_cover_changed"><![CDATA[cover changed]]></string>
+    <string name="_bx_organizations_alert_action_profile_picture_changed"><![CDATA[picture changed]]></string>
+    <string name="_bx_orgs_txt_ntfs_fan_added"><![CDATA[Organization <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_orgs_txt_ntfs_join_invitation"><![CDATA[<b class="bx-ntfs-content-profile">{owner_name}</b> organization's representative invites <b class="bx-ntfs-content-entry">{subentry_sample}</b> to join organization]]></string>
+    <string name="_bx_orgs_txt_ntfs_join_request"><![CDATA[Organization <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_orgs_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> organization timeline]]></string>
+
+    <string name="_bx_orgs_txt_sample_single"><![CDATA[organization]]></string>
+    <string name="_bx_orgs_txt_sample_comment_single"><![CDATA[comment to organization]]></string>
+    <string name="_bx_orgs_txt_sample_vote_single"><![CDATA[vote to organization]]></string>
+    <string name="_bx_orgs_txt_sample_score_up_single"><![CDATA[score up vote to organization]]></string>
+    <string name="_bx_orgs_txt_sample_score_down_single"><![CDATA[score down vote to organization]]></string>
+    <string name="_bx_orgs_txt_sample_pp_single"><![CDATA[profile picture]]></string>
+    <string name="_bx_orgs_txt_sample_pp_single_with_article"><![CDATA[a profile picture]]></string>
+    <string name="_bx_orgs_txt_sample_pc_single"><![CDATA[profile cover]]></string>
+    <string name="_bx_orgs_txt_sample_pc_single_with_article"><![CDATA[a profile cover]]></string>
+    <string name="_bx_orgs_txt_sample_pi_action"><![CDATA[changed {0}]]></string>
+    <string name="_bx_orgs_txt_sample_pi_action_user"><![CDATA[{0} changed {1}]]></string>
+    <string name="_bx_orgs_txt_N_friends"><![CDATA[{0} friends]]></string>
+    <string name="_bx_orgs_txt_role"><![CDATA[Role]]></string>
+    <string name="_bx_orgs_txt_set_role"><![CDATA[Set Role]]></string>
+    <string name="_bx_orgs_txt_private_organization"><![CDATA[Private organization]]></string>
+    <string name="_bx_orgs_ps_group_title_participants"><![CDATA[Employees]]></string>
+
+    <string name="_bx_orgs_email_friend_request"><![CDATA[Friend request]]></string>
+    <string name="_bx_orgs_email_friend_request_subject"><![CDATA[Friendship Request]]></string>
+    <string name="_bx_orgs_email_friend_request_body"><![CDATA[{email_header}
+<p><a href="{SenderUrl}">{SenderDisplayName}</a> wants to be friends with you. <a href="{FriendsLink}">Respond</a>.</p>
+{email_footer}]]></string>
+
+    <string name="_bx_orgs_email_join_request"><![CDATA[Organization join request]]></string>
+    <string name="_bx_orgs_email_join_request_subject"><![CDATA[Request to join your organization]]></string>
+    <string name="_bx_orgs_email_join_request_body"><![CDATA[{email_header}
+<p>New request to join <a href="{EntryUrl}">{EntryTitle}</a> organization from <a href="{NewMemberUrl}">{NewMemberDisplayName}</a></p>
+{email_footer}]]></string>
+
+    <string name="_bx_orgs_email_join_reject"><![CDATA[Organization join request was rejected]]></string>
+    <string name="_bx_orgs_email_join_reject_subject"><![CDATA[Request to join an organization was rejected]]></string>
+    <string name="_bx_orgs_email_join_reject_body"><![CDATA[{email_header}
+<p>Your request to join <a href="{EntryUrl}">{EntryTitle}</a> organization was rejected by the organization admin.</p>
+{email_footer}]]></string>
+
+    <string name="_bx_orgs_email_join_confirm"><![CDATA[Organization join request was confirmed]]></string>
+    <string name="_bx_orgs_email_join_confirm_subject"><![CDATA[Your request to join an organization was confirmed]]></string>
+    <string name="_bx_orgs_email_join_confirm_body"><![CDATA[{email_header}
+<p>Your request to join <a href="{EntryUrl}">{EntryTitle}</a> organization was confirmed by the organization admin.</p>
+{email_footer}]]></string>
+
+    <string name="_bx_orgs_email_fan_remove"><![CDATA[Profile was removed from organization members]]></string>
+    <string name="_bx_orgs_email_fan_remove_subject"><![CDATA[Your profile was removed from the organization]]></string>
+    <string name="_bx_orgs_email_fan_remove_body"><![CDATA[{email_header}
+<p>Your profile was removed from <a href="{EntryUrl}">{EntryTitle}</a> organization by the organization admin.</p>
+{email_footer}]]></string>
+
+    <string name="_bx_orgs_email_fan_become_admin"><![CDATA[Organization admin status was granted]]></string>
+    <string name="_bx_orgs_email_fan_become_admin_subject"><![CDATA[You are an organization admin now]]></string>
+    <string name="_bx_orgs_email_fan_become_admin_body"><![CDATA[{email_header}
+<p>You are an admin of <a href="{EntryUrl}">{EntryTitle}</a> organization now.</p>
+{email_footer}]]></string>
+
+    <string name="_bx_orgs_email_admin_become_fan"><![CDATA[Organization admin status was revoked]]></string>
+    <string name="_bx_orgs_email_admin_become_fan_subject"><![CDATA[Your organization admin status was revoked]]></string>
+    <string name="_bx_orgs_email_admin_become_fan_body"><![CDATA[{email_header}
+<p>Your admin status was revoked from <a href="{EntryUrl}">{EntryTitle}</a> organization.</p>
+{email_footer}]]></string>
+
+    <string name="_bx_orgs_email_set_role"><![CDATA[Organization member status was changed]]></string>
+    <string name="_bx_orgs_email_set_role_subject"><![CDATA[Your organization status was changed]]></string>
+    <string name="_bx_orgs_email_set_role_body"><![CDATA[{email_header}
+<p>Your status in <a href="{EntryUrl}">{EntryTitle}</a> organization was changed to <b>{Role}</b>.</p>
+{email_footer}]]></string>
+
+    <string name="_bx_orgs_email_invitation"><![CDATA[Invitation to organization]]></string>
+    <string name="_bx_orgs_email_invitation_subject"><![CDATA[Invitation to "{EntryTitle}" organization]]></string>
+    <string name="_bx_orgs_email_invitation_body"><![CDATA[{email_header}
+<p><a href="{InviterUrl}">{InviterDisplayName}</a> invited you to <a href="{EntryUrl}">{EntryTitle}</a> organization.</p>
+{email_footer}]]></string>
+</resources>

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

@@ -0,0 +1,51 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'title' => 'Payment',
+    'version_from' => '12.0.0',
+    'version_to' => '12.0.1',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '12.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/payment/updates/update_12.0.0_12.0.1/',
+    'home_uri' => 'payment_update_1200_1201',
+
+    'module_dir' => 'boonex/payment/',
+    'module_uri' => 'payment',
+
+    'db_prefix' => 'bx_payment_',
+    'class_prefix' => 'BxPayment',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_files' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Payment',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

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

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

+ 85 - 0
modules/boonex/payment/updates/12.0.0_12.0.1/install/langs/en.xml

@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources name="en" flag="gb" title="English">
+	<string_add name="_bx_payment_page_title_sys_invoices"><![CDATA[Invoices]]></string_add>
+    <string_add name="_bx_payment_page_title_invoices"><![CDATA[Invoices]]></string_add>
+    <string_add name="_bx_payment_page_block_title_invoices"><![CDATA[Invoices]]></string_add>
+	<string_add name="_bx_payment_lmi_cpt_commissions"><![CDATA[Commissions]]></string_add>
+	<string_add name="_bx_payment_menu_item_title_system_admt_invoices"><![CDATA[Invoices]]></string_add>
+    <string_add name="_bx_payment_menu_item_title_admt_invoices"><![CDATA[Invoices]]></string_add>
+    <string_add name="_bx_payment_menu_item_title_admt_addon_counter1_caption"><![CDATA[paid]]></string_add>
+    <string_add name="_bx_payment_menu_item_title_admt_addon_counter2_caption"><![CDATA[overdue]]></string_add>
+	<string_add name="_bx_payment_grid_column_title_cms_caption"><![CDATA[Caption]]></string_add>
+    <string_add name="_bx_payment_grid_column_title_cms_description"><![CDATA[Description]]></string_add>
+    <string_add name="_bx_payment_grid_column_title_cms_acl_id"><![CDATA[Membership]]></string_add>
+    <string_add name="_bx_payment_grid_column_title_cms_percentage"><![CDATA[Percentage]]></string_add>
+    <string_add name="_bx_payment_grid_column_title_cms_installment"><![CDATA[Installment]]></string_add>
+    <string_add name="_bx_payment_grid_column_title_inv_commissionaire_id"><![CDATA[Commissionaire]]></string_add>
+    <string_add name="_bx_payment_grid_column_title_inv_committent_id"><![CDATA[Committent]]></string_add>
+    <string_add name="_bx_payment_grid_column_title_inv_name"><![CDATA[Name]]></string_add>
+    <string_add name="_bx_payment_grid_column_title_inv_period_start"><![CDATA[Period start]]></string_add>
+    <string_add name="_bx_payment_grid_column_title_inv_period_end"><![CDATA[Period end]]></string_add>
+    <string_add name="_bx_payment_grid_column_title_inv_amount"><![CDATA[Amount]]></string_add>
+    <string_add name="_bx_payment_grid_column_title_inv_date_issue"><![CDATA[Issue date]]></string_add>
+    <string_add name="_bx_payment_grid_column_title_inv_date_due"><![CDATA[Due date]]></string_add>
+    <string_add name="_bx_payment_grid_column_title_inv_status"><![CDATA[Status]]></string_add>
+	<string_add name="_bx_payment_grid_action_title_cms_add"><![CDATA[Add]]></string_add>
+    <string_add name="_bx_payment_grid_action_title_cms_edit"><![CDATA[Edit]]></string_add>
+    <string_add name="_bx_payment_grid_action_title_cms_delete"><![CDATA[Delete]]></string_add>
+    <string_add name="_bx_payment_grid_action_title_inv_edit"><![CDATA[Edit]]></string_add>
+    <string_add name="_bx_payment_grid_action_title_inv_delete"><![CDATA[Delete]]></string_add>
+    <string_add name="_bx_payment_grid_action_title_inv_pay"><![CDATA[Pay]]></string_add>
+	<string_add name="_bx_payment_popup_title_cms_add"><![CDATA[Add Commission]]></string_add>
+    <string_add name="_bx_payment_popup_title_cms_edit"><![CDATA[Edit Commission]]></string_add>
+    <string_add name="_bx_payment_popup_title_inv_edit"><![CDATA[Edit Invoice]]></string_add>
+	<string_add name="_bx_payment_form_commissions_form"><![CDATA[Commissions Form]]></string_add>
+    <string_add name="_bx_payment_form_commissions_display_add"><![CDATA[Add Commission Display]]></string_add>
+    <string_add name="_bx_payment_form_commissions_display_edit"><![CDATA[Edit Commission Display]]></string_add>
+    <string_add name="_bx_payment_form_commissions_input_caption_sys"><![CDATA[Caption]]></string_add>
+    <string_add name="_bx_payment_form_commissions_input_caption"><![CDATA[Caption]]></string_add>
+    <string_add name="_bx_payment_form_commissions_input_caption_err"><![CDATA[This field is essential. Please, fill it in.]]></string_add>
+    <string_add name="_bx_payment_form_commissions_input_description_sys"><![CDATA[Description]]></string_add>
+    <string_add name="_bx_payment_form_commissions_input_description"><![CDATA[Description]]></string_add>
+    <string_add name="_bx_payment_form_commissions_input_acl_id_sys"><![CDATA[Membership Level]]></string_add>
+    <string_add name="_bx_payment_form_commissions_input_acl_id"><![CDATA[Membership Level]]></string_add>
+    <string_add name="_bx_payment_form_commissions_input_percentage_sys"><![CDATA[Percentage]]></string_add>
+    <string_add name="_bx_payment_form_commissions_input_percentage"><![CDATA[Percentage]]></string_add>
+    <string_add name="_bx_payment_form_commissions_input_installment_sys"><![CDATA[Installment]]></string_add>
+    <string_add name="_bx_payment_form_commissions_input_installment"><![CDATA[Installment]]></string_add>
+    <string_add name="_bx_payment_form_commissions_input_submit_sys"><![CDATA[Submit]]></string_add>
+    <string_add name="_bx_payment_form_commissions_input_submit"><![CDATA[Submit]]></string_add>
+    <string_add name="_bx_payment_form_commissions_input_cancel_sys"><![CDATA[Cancel]]></string_add>
+    <string_add name="_bx_payment_form_commissions_input_cancel"><![CDATA[Cancel]]></string_add>
+    <string_add name="_bx_payment_form_invoices_form"><![CDATA[Invoices Form]]></string_add>
+    <string_add name="_bx_payment_form_invoices_display_edit"><![CDATA[Edit Invoice Display]]></string_add>
+    <string_add name="_bx_payment_form_invoices_input_amount_sys"><![CDATA[Amount]]></string_add>
+    <string_add name="_bx_payment_form_invoices_input_amount"><![CDATA[Amount]]></string_add>
+    <string_add name="_bx_payment_form_invoices_input_amount_err"><![CDATA[This field is essential. Please, fill it in.]]></string_add>
+    <string_add name="_bx_payment_form_invoices_input_date_due_sys"><![CDATA[Due date]]></string_add>
+    <string_add name="_bx_payment_form_invoices_input_date_due"><![CDATA[Due date]]></string_add>
+    <string_add name="_bx_payment_form_invoices_input_date_due_err"><![CDATA[This field is essential. Please, fill it in.]]></string_add>
+    <string_add name="_bx_payment_form_invoices_input_status_sys"><![CDATA[Status]]></string_add>
+    <string_add name="_bx_payment_form_invoices_input_status"><![CDATA[Status]]></string_add>
+    <string_add name="_bx_payment_form_invoices_input_submit_sys"><![CDATA[Submit]]></string_add>
+    <string_add name="_bx_payment_form_invoices_input_submit"><![CDATA[Submit]]></string_add>
+    <string_add name="_bx_payment_form_invoices_input_cancel_sys"><![CDATA[Cancel]]></string_add>
+    <string_add name="_bx_payment_form_invoices_input_cancel"><![CDATA[Cancel]]></string_add>
+	<string_add name="_bx_payment_et_txt_name_expiring_notification_committent"><![CDATA[Invoice expiring notification.]]></string_add>
+    <string_add name="_bx_payment_et_txt_subject_expiring_notification_committent"><![CDATA[Invoice expiring notification.]]></string_add>
+    <string_add name="_bx_payment_et_txt_body_expiring_notification_committent"><![CDATA[{email_header}
+<p>Hello,</p>
+<p>Your invoice '{invoice}' is expiring in '{days}' day(s).</p>
+<p>Invoice info:<br />Period start: {period_start}<br />Period end: {period_end}<br />Issue date: {date_issue}<br />Due date: {date_due}</p>
+{email_footer}]]></string_add>
+
+    <string_add name="_bx_payment_et_txt_name_overdue_notification_committent"><![CDATA[Overdue invoice notification.]]></string_add>
+    <string_add name="_bx_payment_et_txt_subject_overdue_notification_committent"><![CDATA[Overdue invoice notification.]]></string_add>
+    <string_add name="_bx_payment_et_txt_body_overdue_notification_committent"><![CDATA[{email_header}
+<p>Hello,</p>
+<p>Your invoice '{invoice}' is overdue '{date_due}'.</p>
+<p>Invoice info:<br />Period start: {period_start}<br />Period end: {period_end}<br />Issue date: {date_issue}<br />Due date: {date_due}</p>
+{email_footer}]]></string_add>
+	<string_add name="_bx_payment_txt_status_paid"><![CDATA[Paid]]></string_add>
+	<string_add name="_bx_payment_txt_status_overdue"><![CDATA[Overdue]]></string_add>
+	<string_add name="_bx_payment_txt_invoice_title"><![CDATA[Invoice {0} from {1}]]></string_add>
+    <string_add name="_bx_payment_txt_invoice_description"><![CDATA[For a period between {0} and {1}]]></string_add>
+</resources>

+ 31 - 0
modules/boonex/payment/updates/12.0.0_12.0.1/install/sql/enable.sql

@@ -0,0 +1,31 @@
+SET @sName = 'bx_payment';
+
+
+-- PAGES & BLOCKS
+DELETE FROM `sys_objects_page` WHERE `object`='bx_payment_invoices';
+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_payment_invoices', '_bx_payment_page_title_sys_invoices', '_bx_payment_page_title_invoices', @sName, 5, 2147483647, 1, 'payment-invoices', 'page.php?i=payment-invoices', '', '', '', 0, 1, 0, 'BxPaymentPageInvoices', 'modules/boonex/payment/classes/BxPaymentPageInvoices.php');
+
+DELETE FROM `sys_pages_blocks` WHERE `object`='bx_payment_invoices';
+INSERT INTO `sys_pages_blocks` (`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES
+('bx_payment_invoices', 1, @sName, '', '_bx_payment_page_block_title_invoices', 11, 2147483647, 'service', 'a:4:{s:6:"module";s:10:"bx_payment";s:6:"method";s:18:"get_block_invoices";s:6:"params";a:0:{}s:5:"class";s:11:"Commissions";}', 0, 0, 1);
+
+
+-- MENUS
+DELETE FROM `sys_menu_items` WHERE `set_name`='sys_account_dashboard_manage_tools' AND `name`='payment-invoices';
+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`, `markers`, `submenu_object`, `visible_for_levels`, `visibility_custom`, `active`, `copyable`, `order`) VALUES 
+('sys_account_dashboard_manage_tools', 'bx_payment', 'payment-invoices', '_bx_payment_menu_item_title_system_admt_invoices', '_bx_payment_menu_item_title_admt_invoices', 'page.php?i=payment-invoices', '', '_self', 'credit-card col-gray-dark', 'a:2:{s:6:"module";s:10:"bx_payment";s:6:"method";s:27:"get_menu_addon_manage_tools";}', '', '', 192, '', 1, 0, @iManageMenuOrder + 1);
+
+
+-- EMAIL TEMPLATES
+DELETE FROM `sys_email_templates` WHERE `Name` IN ('bx_payment_expiring_notification_committent', 'bx_payment_overdue_notification_committent');
+INSERT INTO `sys_email_templates` (`Module`, `NameSystem`, `Name`, `Subject`, `Body`) VALUES 
+(@sName, '_bx_payment_et_txt_name_expiring_notification_committent', 'bx_payment_expiring_notification_committent', '_bx_payment_et_txt_subject_expiring_notification_committent', '_bx_payment_et_txt_body_expiring_notification_committent'),
+(@sName, '_bx_payment_et_txt_name_overdue_notification_committent', 'bx_payment_overdue_notification_committent', '_bx_payment_et_txt_subject_overdue_notification_committent', '_bx_payment_et_txt_body_overdue_notification_committent');
+
+
+-- CRON
+DELETE FROM `sys_cron_jobs` WHERE `name`='bx_payment_commissions';
+INSERT INTO `sys_cron_jobs` (`name`, `time`, `class`, `file`, `service_call`) VALUES
+('bx_payment_commissions', '0 * * * *', 'BxPaymentCronCommissions', 'modules/boonex/payment/classes/BxPaymentCronCommissions.php', '');

+ 137 - 0
modules/boonex/payment/updates/12.0.0_12.0.1/install/sql/install.sql

@@ -0,0 +1,137 @@
+SET @sName = 'bx_payment';
+
+DELETE FROM `bx_payment_modules` WHERE `name`=@sName;
+INSERT INTO `bx_payment_modules`(`name`) VALUES
+(@sName);
+
+CREATE TABLE IF NOT EXISTS `bx_payment_commissions` (
+  `id` int(11) NOT NULL auto_increment,
+  `name` varchar(64) NOT NULL default '',
+  `caption` varchar(128) NOT NULL default '',
+  `description` varchar(128) NOT NULL default '',
+  `acl_id` int(11) NOT NULL default '0',
+  `percentage` float NOT NULL default '0',
+  `installment` float NOT NULL default '0',
+  `active` tinyint(4) NOT NULL default '0',
+  `order` tinyint(4) NOT NULL default '0',
+  PRIMARY KEY(`id`),
+  UNIQUE KEY `name`(`name`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_payment_invoices` (
+  `id` int(11) NOT NULL auto_increment,
+  `name` varchar(64) NOT NULL default '',
+  `commissionaire_id` varchar(32) NOT NULL default '',
+  `committent_id` varchar(32) NOT NULL default '',
+  `amount` float NOT NULL default '0',
+  `period_start` int(11) NOT NULL default '0',
+  `period_end` int(11) NOT NULL default '0',
+  `date_issue` int(11) NOT NULL default '0',
+  `date_due` int(11) NOT NULL default '0',
+  `status` varchar(32) NOT NULL default 'unpaid',
+  `ntf_exp` tinyint(4) NOT NULL default '0',
+  `ntf_due` tinyint(4) NOT NULL default '0',
+  PRIMARY KEY(`id`),
+  UNIQUE KEY `name`(`name`)
+);
+
+
+-- GRIDS
+DELETE FROM `sys_objects_grid` WHERE `object` IN ('bx_payment_grid_commissions', 'bx_payment_grid_invoices');
+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_payment_grid_commissions', 'Sql', 'SELECT * FROM `bx_payment_commissions` WHERE 1 ', 'bx_payment_commissions', 'id', 'order', 'active', '', 100, NULL, 'start', '', 'name', 'caption,description', 'auto', '', '', 192, 'BxPaymentGridCommissions', 'modules/boonex/payment/classes/BxPaymentGridCommissions.php'),
+('bx_payment_grid_invoices', 'Sql', 'SELECT * FROM `bx_payment_invoices` WHERE 1 ', 'bx_payment_invoices', 'id', '', '', '', 100, NULL, 'start', '', '', '', 'auto', '', '', 2147483647, 'BxPaymentGridInvoices', 'modules/boonex/payment/classes/BxPaymentGridInvoices.php');
+
+DELETE FROM `sys_grid_fields` WHERE `object` IN ('bx_payment_grid_commissions', 'bx_payment_grid_invoices');
+INSERT INTO `sys_grid_fields` (`object`, `name`, `title`, `width`, `translatable`, `chars_limit`, `params`, `order`) VALUES
+('bx_payment_grid_commissions', 'order', '', '2%', 0, '0', '', 1),
+('bx_payment_grid_commissions', 'switcher', '', '8%', 0, '0', '', 2),
+('bx_payment_grid_commissions', 'caption', '_bx_payment_grid_column_title_cms_caption', '15%', 1, '16', '', 3),
+('bx_payment_grid_commissions', 'description', '_bx_payment_grid_column_title_cms_description', '20%', 1, '16', '', 4),
+('bx_payment_grid_commissions', 'acl_id', '_bx_payment_grid_column_title_cms_acl_id', '15%', 0, '16', '', 5),
+('bx_payment_grid_commissions', 'percentage', '_bx_payment_grid_column_title_cms_percentage', '10%', 0, '0', '', 6),
+('bx_payment_grid_commissions', 'installment', '_bx_payment_grid_column_title_cms_installment', '10%', 0, '0', '', 7),
+('bx_payment_grid_commissions', 'actions', '', '20%', 0, '0', '', 8),
+
+('bx_payment_grid_invoices', 'checkbox', '', '2%', 0, '0', '', 1),
+('bx_payment_grid_invoices', 'commissionaire_id', '_bx_payment_grid_column_title_inv_commissionaire_id', '10%', 1, '0', '', 2),
+('bx_payment_grid_invoices', 'committent_id', '_bx_payment_grid_column_title_inv_committent_id', '10%', 1, '0', '', 3),
+('bx_payment_grid_invoices', 'name', '_bx_payment_grid_column_title_inv_name', '8%', 1, '0', '', 4),
+('bx_payment_grid_invoices', 'period_start', '_bx_payment_grid_column_title_inv_period_start', '10%', 0, '0', '', 5),
+('bx_payment_grid_invoices', 'period_end', '_bx_payment_grid_column_title_inv_period_end', '10%', 0, '0', '', 6),
+('bx_payment_grid_invoices', 'amount', '_bx_payment_grid_column_title_inv_amount', '6%', 0, '0', '', 7),
+('bx_payment_grid_invoices', 'date_issue', '_bx_payment_grid_column_title_inv_date_issue', '10%', 0, '0', '', 8),
+('bx_payment_grid_invoices', 'date_due', '_bx_payment_grid_column_title_inv_date_due', '10%', 0, '0', '', 9),
+('bx_payment_grid_invoices', 'status', '_bx_payment_grid_column_title_inv_status', '6%', 0, '8', '', 10),
+('bx_payment_grid_invoices', 'actions', '', '18%', 0, '0', '', 11);
+
+DELETE FROM `sys_grid_actions` WHERE `object` IN ('bx_payment_grid_commissions', 'bx_payment_grid_invoices');
+INSERT INTO `sys_grid_actions` (`object`, `type`, `name`, `title`, `icon`, `icon_only`, `confirm`, `order`) VALUES
+('bx_payment_grid_commissions', 'independent', 'add', '_bx_payment_grid_action_title_cms_add', '', 0, 0, 1),
+('bx_payment_grid_commissions', 'bulk', 'delete', '_bx_payment_grid_action_title_cms_delete', '', 0, 1, 1),
+('bx_payment_grid_commissions', 'single', 'edit', '_bx_payment_grid_action_title_cms_edit', 'pencil', 1, 0, 1),
+('bx_payment_grid_commissions', 'single', 'delete', '_bx_payment_grid_action_title_cms_delete', 'remove', 1, 1, 2),
+
+('bx_payment_grid_invoices', 'bulk', 'delete', '_bx_payment_grid_action_title_inv_delete', '', 0, 1, 1),
+('bx_payment_grid_invoices', 'single', 'pay', '_bx_payment_grid_action_title_inv_pay', 'credit-card', 1, 0, 1),
+('bx_payment_grid_invoices', 'single', 'edit', '_bx_payment_grid_action_title_inv_edit', 'pencil', 1, 0, 2),
+('bx_payment_grid_invoices', 'single', 'delete', '_bx_payment_grid_action_title_inv_delete', 'remove', 1, 1, 3);
+
+
+-- FORMS
+DELETE FROM `sys_objects_form` WHERE `object` IN ('bx_payment_form_commissions', 'bx_payment_form_invoices');
+INSERT INTO `sys_objects_form` (`object`, `module`, `title`, `action`, `form_attrs`, `submit_name`, `table`, `key`, `uri`, `uri_title`, `params`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES
+('bx_payment_form_commissions', @sName, '_bx_payment_form_commissions_form', '', '', 'do_submit', 'bx_payment_commissions', 'id', '', '', '', 0, 1, 'BxPaymentFormCommissions', 'modules/boonex/payment/classes/BxPaymentFormCommissions.php'),
+('bx_payment_form_invoices', @sName, '_bx_payment_form_invoices_form', '', '', 'do_submit', 'bx_payment_invoices', 'id', '', '', '', 0, 1, 'BxPaymentFormInvoices', 'modules/boonex/payment/classes/BxPaymentFormInvoices.php');
+
+
+DELETE FROM `sys_form_displays` WHERE `object` IN ('bx_payment_form_commissions', 'bx_payment_form_invoices');
+INSERT INTO `sys_form_displays` (`display_name`, `module`, `object`, `title`, `view_mode`) VALUES
+('bx_payment_form_commissions_add', @sName, 'bx_payment_form_commissions', '_bx_payment_form_commissions_display_add', 0),
+('bx_payment_form_commissions_edit', @sName, 'bx_payment_form_commissions', '_bx_payment_form_commissions_display_edit', 0),
+('bx_payment_form_invoices_edit', @sName, 'bx_payment_form_invoices', '_bx_payment_form_invoices_display_edit', 0);
+
+DELETE FROM `sys_form_inputs` WHERE `object` IN ('bx_payment_form_commissions', 'bx_payment_form_invoices');
+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_payment_form_commissions', @sName, 'caption', '0', '', 0, 'text_translatable', '_bx_payment_form_commissions_input_caption_sys', '_bx_payment_form_commissions_input_caption', '', 1, 0, 0, '', '', '', 'AvailTranslatable', 'a:1:{i:0;s:7:"caption";}', '_bx_payment_form_commissions_input_caption_err', 'Xss', '', 0, 0),
+('bx_payment_form_commissions', @sName, 'description', '0', '', 0, 'textarea_translatable', '_bx_payment_form_commissions_input_description_sys', '_bx_payment_form_commissions_input_description', '', 0, 0, 0, '', '', '', '', '', '', 'Xss', '', 0, 0),
+('bx_payment_form_commissions', @sName, 'acl_id', '0', '', 0, 'select', '_bx_payment_form_commissions_input_acl_id_sys', '_bx_payment_form_commissions_input_acl_id', '', 0, 0, 0, '', '', '', '', '', '', 'Int', '', 0, 0),
+('bx_payment_form_commissions', @sName, 'percentage', '0', '', 0, 'text', '_bx_payment_form_commissions_input_percentage_sys', '_bx_payment_form_commissions_input_percentage', '', 0, 0, 0, '', '', '', '', '', '', 'Float', '', 0, 0),
+('bx_payment_form_commissions', @sName, 'installment', '0', '', 0, 'text', '_bx_payment_form_commissions_input_installment_sys', '_bx_payment_form_commissions_input_installment', '', 0, 0, 0, '', '', '', '', '', '', 'Float', '', 0, 0),
+('bx_payment_form_commissions', @sName, 'controls', '', 'do_submit,do_cancel', 0, 'input_set', '', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
+('bx_payment_form_commissions', @sName, 'do_submit', '_bx_payment_form_commissions_input_submit', '', 0, 'submit', '_bx_payment_form_commissions_input_submit_sys', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
+('bx_payment_form_commissions', @sName, 'do_cancel', '_bx_payment_form_commissions_input_cancel', '', 0, 'button', '_bx_payment_form_commissions_input_cancel_sys', '', '', 0, 0, 0, 'a:2:{s:7:"onclick";s:45:"$(''.bx-popup-applied:visible'').dolPopupHide()";s:5:"class";s:22:"bx-def-margin-sec-left";}', '', '', '', '', '', '', '', 0, 0),
+
+('bx_payment_form_invoices', @sName, 'amount', '0', '', 0, 'text', '_bx_payment_form_invoices_input_amount_sys', '_bx_payment_form_invoices_input_amount', '', 1, 0, 0, '', '', '', 'Avail', '', '_bx_payment_form_invoices_input_amount_err', 'Float', '', 0, 0),
+('bx_payment_form_invoices', @sName, 'date_due', '', '', 0, 'datepicker', '_bx_payment_form_invoices_input_date_due_sys', '_bx_payment_form_invoices_input_date_due', '', 1, 0, 0, '', '', '', 'Avail', '', '_bx_payment_form_invoices_input_date_due_err', 'DateUtc', '', 0, 0),
+('bx_payment_form_invoices', @sName, 'status', '', '', 0, 'select', '_bx_payment_form_invoices_input_status_sys', '_bx_payment_form_invoices_input_status', '', 0, 0, 0, '', '', '', '', '', '', 'Xss', '', 0, 0),
+('bx_payment_form_invoices', @sName, 'controls', '', 'do_submit,do_cancel', 0, 'input_set', '', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
+('bx_payment_form_invoices', @sName, 'do_submit', '_bx_payment_form_invoices_input_submit', '', 0, 'submit', '_bx_payment_form_invoices_input_submit_sys', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
+('bx_payment_form_invoices', @sName, 'do_cancel', '_bx_payment_form_invoices_input_cancel', '', 0, 'button', '_bx_payment_form_invoices_input_cancel_sys', '', '', 0, 0, 0, 'a:2:{s:7:"onclick";s:45:"$(''.bx-popup-applied:visible'').dolPopupHide()";s:5:"class";s:22:"bx-def-margin-sec-left";}', '', '', '', '', '', '', '', 0, 0);
+
+DELETE FROM `sys_form_display_inputs` WHERE `display_name` IN ('bx_payment_form_commissions_add', 'bx_payment_form_commissions_edit', 'bx_payment_form_invoices_edit');
+INSERT INTO `sys_form_display_inputs` (`display_name`, `input_name`, `visible_for_levels`, `active`, `order`) VALUES
+('bx_payment_form_commissions_add', 'caption', 2147483647, 1, 1),
+('bx_payment_form_commissions_add', 'description', 2147483647, 1, 2),
+('bx_payment_form_commissions_add', 'acl_id', 2147483647, 1, 3),
+('bx_payment_form_commissions_add', 'percentage', 2147483647, 1, 4),
+('bx_payment_form_commissions_add', 'installment', 2147483647, 1, 5),
+('bx_payment_form_commissions_add', 'controls', 2147483647, 1, 6),
+('bx_payment_form_commissions_add', 'do_submit', 2147483647, 1, 7),
+('bx_payment_form_commissions_add', 'do_cancel', 2147483647, 1, 8),
+
+('bx_payment_form_commissions_edit', 'caption', 2147483647, 1, 1),
+('bx_payment_form_commissions_edit', 'description', 2147483647, 1, 2),
+('bx_payment_form_commissions_edit', 'acl_id', 2147483647, 1, 3),
+('bx_payment_form_commissions_edit', 'percentage', 2147483647, 1, 4),
+('bx_payment_form_commissions_edit', 'installment', 2147483647, 1, 5),
+('bx_payment_form_commissions_edit', 'controls', 2147483647, 1, 6),
+('bx_payment_form_commissions_edit', 'do_submit', 2147483647, 1, 7),
+('bx_payment_form_commissions_edit', 'do_cancel', 2147483647, 1, 8),
+
+('bx_payment_form_invoices_edit', 'amount', 2147483647, 1, 1),
+('bx_payment_form_invoices_edit', 'date_due', 2147483647, 1, 2),
+('bx_payment_form_invoices_edit', 'status', 2147483647, 1, 3),
+('bx_payment_form_invoices_edit', 'controls', 2147483647, 1, 4),
+('bx_payment_form_invoices_edit', 'do_submit', 2147483647, 1, 5),
+('bx_payment_form_invoices_edit', 'do_cancel', 2147483647, 1, 6);

+ 49 - 0
modules/boonex/payment/updates/12.0.0_12.0.1/source/classes/BxPaymentCommissions.php

@@ -0,0 +1,49 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Payment Payment
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxPaymentCommissions extends BxBaseModPaymentCommissions
+{
+    public function __construct()
+    {   
+        $this->_sModule = 'bx_payment';
+
+        parent::__construct();
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_payment Payment
+     * @subsection bx_payment-page_blocks Page Blocks
+     * @subsubsection bx_payment-get_block_invoices get_block_invoices
+     * 
+     * @code bx_srv('bx_payment', 'get_block_invoices', [...], 'Details'); @endcode
+     * 
+     * Get page block with a list of invoices.
+     *
+     * @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 BxPaymentDetails::serviceGetBlockDetails
+     */
+    /** 
+     * @ref bx_payment-get_block_invoices "get_block_invoices"
+     */
+    public function serviceGetBlockInvoices($iUserId = BX_PAYMENT_EMPTY_ID)
+    {
+        if(!$this->_oModule->isLogged())
+            return MsgBox(_t($this->_sLangsPrefix . 'err_required_login'));
+
+        $this->_oModule->setSiteSubmenu('menu_dashboard', 'system', 'dashboard-invoices');
+
+        return $this->_oModule->_oTemplate->displayBlockInvoices();
+    }
+}
+
+/** @} */

+ 325 - 0
modules/boonex/payment/updates/12.0.0_12.0.1/source/classes/BxPaymentConfig.php

@@ -0,0 +1,325 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Payment Payment
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxPaymentConfig extends BxBaseModPaymentConfig
+{
+    protected $_bCreditsOnly;
+
+    protected $_iPayAttemptsMax;
+    protected $_iPayAttemptsInterval;
+
+    function __construct($aModule)
+    {
+        parent::__construct($aModule);
+
+        $sBaseUrl = BX_DOL_URL_ROOT . $this->getBaseUri();
+
+        $this->CNF = array_merge($this->CNF, array(
+            // module icon
+            'ICON' => 'credit-card col-gray-dark',
+
+            // database tables
+            'TABLE_COMMISSIONS' => $aModule['db_prefix'] . 'commissions',
+            'TABLE_INVOICES' => $aModule['db_prefix'] . 'invoices',
+
+            // page URIs
+            'URL_JOIN' => 'page.php?i=payment-join',
+            'URL_CARTS' => 'page.php?i=payment-carts',
+            'URL_CART' => 'page.php?i=payment-cart',
+            'URL_CART_CHECKOUT' => $sBaseUrl . 'initialize_checkout/' . BX_PAYMENT_TYPE_SINGLE . '/',
+            'URL_SUBSCRIBE' => $sBaseUrl . 'subscribe/',
+            'URL_SUBSCRIBE_JSON' => $sBaseUrl . 'subscribe_json/',
+            'URL_SUBSCRIPTIONS' => 'page.php?i=payment-sbs-list-my',
+            'URL_HISTORY' => 'page.php?i=payment-history',
+            'URL_ORDERS' => 'page.php?i=payment-orders',
+            'URL_INVOICES' => 'page.php?i=payment-invoices',
+            'URL_DETAILS' => 'page.php?i=payment-details',
+            'URL_RETURN' => 'page.php?i=payment-cart-thank-you',
+            'URL_RETURN_DATA' => $sBaseUrl . 'finalize_checkout/',
+            'URL_NOTIFY' => $sBaseUrl . 'notify/',
+            
+            'KEY_ARRAY_PRICE_SINGLE' => 'price_single',
+            'KEY_ARRAY_PRICE_RECURRING' => 'price_recurring',
+            'KEY_ARRAY_TRIAL_RECURRING' => 'trial_recurring',
+
+            // objects
+            'OBJECT_FORM_PRELISTS_CURRENCIES' => 'bx_payment_currencies',
+            'OBJECT_PP_CREDITS' => 'credits', //Credits payment provider
+
+            'MODULE_CREDITS' => 'bx_credits',
+
+            // some language keys
+            'T' => array(
+                'MSG_ITEM_ADDED' => '_bx_payment_msg_item_added',
+                'MSG_ITEM_DELETED' => '_bx_payment_msg_item_deleted',
+                'MSG_SINGLE_SELLER_MODE' => '_bx_payment_msg_single_seller',
+                'ERR_WRONG_DATA' => '_bx_payment_err_wrong_data',
+                'ERR_REQUIRED_LOGIN' => '_bx_payment_err_required_login',
+                'ERR_NOT_ACCEPT_PAYMENTS' => '_bx_payment_err_not_accept_payments',
+                'ERR_SELF_PURCHASE' => '_bx_payment_err_self_purchase',
+                'ERR_INACTIVE_VENDOR' => '_bx_payment_err_inactive_vendor',
+                'ERR_UNKNOWN_VENDOR' => '_bx_payment_err_unknown_vendor',
+
+                'BLOCK_TITLE_CART' => '_bx_payment_page_block_title_cart',
+
+                'POPUP_PROVIDERS_SELECT' => '_bx_payment_popup_title_crd_providers_select', 
+
+                'TXT_CART_PROVIDER' => '_bx_payment_txt_cart_'
+            )
+        ));
+
+        $this->_aHtmlIds = array(
+            'cart' => array(
+                'providers_select' => $this->_sName . '-cart-providers-select-',
+            ),
+            'history' => array(
+                'order_history_view' => $this->_sName . '-order-view-history',
+            ),
+            'subscription' => array(
+                'order_subscription_view' => $this->_sName . '-order-view-subscription',
+                'order_subscription_get_details' => $this->_sName . '-order-get-details-subscription',
+                'order_subscription_change_details' => $this->_sName . '-order-change-details-subscription',
+                'order_subscription_get_billing' => $this->_sName . '-order-get-billing-subscription',
+                'order_subscription_change_billing' => $this->_sName . '-order-change-billing-subscription',
+                'form_subscription_change_billing' => $this->_sName . '-form-change-billing-subscription',
+                'form_subscription_change_details' => $this->_sName . '-form-change-details-subscription',
+            ),
+            'pending' => array(
+                'order_pending_view' => $this->_sName . '-order-view-pending',
+                'order_pending_process' => $this->_sName . '-order-process',
+            ),
+            'processed' => array(
+                'order_processed_view' => $this->_sName . '-order-view-processed',
+                'order_processed_add' => $this->_sName . '-order-add',
+                'order_processed_client_id' => $this->_sName . '-oa-client-id',
+                'order_processed_client' => $this->_sName . '-oa-client',
+                'order_processed_items' => $this->_sName . '-oa-items',	
+            ),
+            'commission' => array(
+                'popup_add' => $this->_sName . '-commission-popup-add',
+                'popup_edit' => $this->_sName . '-commission-popup-edit',
+            ),
+            'invoice' => array(
+                'popup_edit' => $this->_sName . '-invoice-popup-edit',
+            )
+        );
+
+        $this->_aPerPage = array(
+            'orders' => 10,
+            'history' => 10
+        );
+        $this->_aHandlers = array();
+
+        $this->_aJsClasses = array(
+            'cart' => 'BxPaymentCart',
+            'history' => 'BxPaymentOrders',
+            'subscription' => 'BxPaymentSubscriptions',
+            'pending' => 'BxPaymentOrders',
+            'processed' => 'BxPaymentOrders',
+            'chargebee_v3' => 'BxPaymentProviderChargebeeV3',
+            'stripe' => 'BxPaymentProviderStripe',
+            'stripe_v3' => 'BxPaymentProviderStripeV3'
+        );
+
+        $this->_aJsObjects = array(
+            'cart' => 'oPaymentCart',
+            'history' => 'oPaymentOrders',
+            'subscription' => 'oBxPaymentSubscriptions',
+            'pending' => 'oPaymentOrders',
+            'processed' => 'oPaymentOrders',
+            'chargebee_v3' => 'oPaymentProviderChargebeeV3',
+            'stripe' => 'oPaymentProviderStripe',
+            'stripe_v3' => 'oPaymentProviderStripeV3'
+        );
+
+        $this->_bCreditsOnly = false;
+
+        $this->_iPayAttemptsMax = 3;
+        $this->_iPayAttemptsInterval = 86400; //--- in sec
+    }
+
+    public function init(&$oDb)
+    {
+        parent::init($oDb);
+
+        $sPrefix = $this->getPrefix('options');
+
+        $this->_bCreditsOnly = $this->_oDb->getParam($sPrefix . 'credits_only') == 'on';
+    }
+
+    public function isCreditsOnly()
+    {
+        return $this->_bCreditsOnly;
+    }
+
+    public function getPayAttemptsMax()
+    {
+        return $this->_iPayAttemptsMax;
+    }
+
+    public function getPayAttemptsInterval()
+    {
+        return $this->_iPayAttemptsInterval;
+    }
+
+    public function getPrice($sType, $aItem)
+    {
+    	$fPrice = 0;
+
+        switch($sType) {
+            case BX_PAYMENT_TYPE_SINGLE:
+                $fPrice = $aItem[$this->getKey('KEY_ARRAY_PRICE_SINGLE')];
+                break;
+
+            case BX_PAYMENT_TYPE_RECURRING:
+                $fPrice = $aItem[$this->getKey('KEY_ARRAY_PRICE_RECURRING')];
+                break;
+        }
+
+        return (float)$fPrice;
+    }
+
+    public function getTrial($sType, $aItem)
+    {
+        $iTrial = 0;
+
+        switch($sType) {
+            case BX_PAYMENT_TYPE_RECURRING:
+                $iTrial = $aItem[$this->getKey('KEY_ARRAY_TRIAL_RECURRING')];
+                break;
+        }
+
+        return (int)$iTrial;
+    }
+
+    public function getModuleId($mixedId)
+    {
+        if(is_numeric($mixedId))
+            return (int)$mixedId;
+
+        if(is_string($mixedId)) {
+            $aInfo = $this->_oDb->getModuleByName($mixedId);
+            if(!is_array($aInfo) || empty($aInfo['id']))
+                $aInfo = $this->_oDb->getModuleByUri($mixedId);
+
+            if(is_array($aInfo) && !empty($aInfo['id']))
+                return (int)$aInfo['id'];
+        } 
+
+        return 0;
+    }
+
+    public function a2s($a)
+    {
+        return base64_encode(serialize($a));
+    }
+
+    public function s2a($s)
+    {
+        return unserialize(base64_decode($s));
+    }
+            
+    public function descriptorA2S($a) 
+    {
+    	return implode($this->getDivider('DIVIDER_DESCRIPTOR'), $a);
+    }
+
+    public function descriptorS2A($s) 
+    {
+    	return explode($this->getDivider('DIVIDER_DESCRIPTOR'), $s);
+    }
+
+    /**
+     * Conver items to array with necessary structure.
+     *
+     * @param  string/array $mixed - string with cart items divided with (:) or an array of cart items.
+     * @return array        with items.
+     */
+    public function descriptorsM2A($mixed)
+    {
+        $aResults = array();
+
+        if(is_string($mixed))
+           $aItems = explode($this->getDivider('DIVIDER_DESCRIPTORS'), $mixed);
+        else if(is_array($mixed))
+           $aItems = $mixed;
+        else
+            $aItems = array();
+
+        foreach($aItems as $mixedItem) {
+            $aItem = is_array($mixedItem) ? $mixedItem : $this->descriptorS2A($mixedItem);
+
+            $aResult = array('vendor_id' => $aItem[0], 'module_id' => $aItem[1], 'item_id' => $aItem[2], 'item_count' => $aItem[3]);
+            if(isset($aItem[4]))
+                $aResult['item_addons'] = $aItem[4];
+
+            $aResults[] = $aResult;
+        }
+
+        return $aResults;
+    }
+
+    public function putCustom($mDsc, $aCustom, &$aCustoms)
+    {
+        if(empty($aCustom) || !is_array($aCustom))
+            return;
+
+        if(is_array($mDsc))
+            $mDsc = $this->descriptorA2S(array_slice($mDsc, 0, 3));
+
+        $aCustoms[$mDsc] = !empty($aCustoms[$mDsc]) && is_array($aCustoms[$mDsc]) ? array_merge($aCustoms[$mDsc], $aCustom) : $aCustom;
+    }
+
+    public function getCustom($mDsc, &$aCustoms)
+    {
+        if(is_array($mDsc))
+            $mDsc = $this->descriptorA2S(array_slice($mDsc, 0, 3));
+
+        if(empty($aCustoms) || !is_array($aCustoms) || empty($aCustoms[$mDsc]))
+            return array();
+
+        return $aCustoms[$mDsc];
+    }
+
+    public function pullCustom($mDsc, &$aCustoms)
+    {
+        if(is_array($mDsc))
+            $mDsc = $this->descriptorA2S(array_slice($mDsc, 0, 3));
+
+        if(empty($aCustoms) || !is_array($aCustoms) || empty($aCustoms[$mDsc]))
+            return array();
+
+        $aResult = $aCustoms[$mDsc];
+        unset($aCustoms[$mDsc]);           
+
+        return $aResult;
+    }
+
+    public function http2https($s)
+    {
+    	if(strncmp($s, 'https://', 8) === 0)
+    		return $s;
+
+        return 'https://' . bx_ltrim_str($s, 'http://');
+    }
+
+    public function sortByColumn($sColumn, &$aValues)
+    {
+        return usort($aValues, function($aV1, $aV2) use ($sColumn) {
+            if($aV1[$sColumn] == $aV2[$sColumn])
+                return 0;
+
+            return $aV1[$sColumn] < $aV2[$sColumn] ? -1 : 1;
+        });
+    }
+}
+
+/** @} */

+ 31 - 0
modules/boonex/payment/updates/12.0.0_12.0.1/source/classes/BxPaymentCronCommissions.php

@@ -0,0 +1,31 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Payment Payment
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxPaymentCronCommissions extends BxDolCron
+{
+    protected $_sModule;
+    protected $_oModule;
+
+    public function __construct()
+    {
+        parent::__construct();
+
+    	$this->_sModule = 'bx_payment';
+    	$this->_oModule = BxDolModule::getInstance($this->_sModule);
+    }
+
+    function processing()
+    {
+        $this->_oModule->processCommissions();
+    }
+}
+
+/** @} */

+ 776 - 0
modules/boonex/payment/updates/12.0.0_12.0.1/source/classes/BxPaymentDb.php

@@ -0,0 +1,776 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Payment Payment
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxPaymentDb extends BxBaseModPaymentDb
+{
+    function __construct(&$oConfig)
+    {
+        parent::__construct($oConfig);
+    }
+
+    public function getModulesWithPayments()
+    {
+    	$sQuery = $this->prepare("SELECT `name` FROM `" . $this->_sPrefix . "modules`");
+        return $this->getColumn($sQuery);
+    }
+
+    /**
+     * Payment details methods
+     */
+    public function getForm()
+    {
+        $sQuery = "SELECT
+                `tp`.`id` AS `provider_id`,
+                `tp`.`name` AS `provider_name`,
+                `tp`.`caption` AS `provider_caption`,
+                `tp`.`description` AS `provider_description`,
+                `tp`.`option_prefix` AS `provider_option_prefix`,
+                `tp`.`for_owner_only` AS `provider_for_owner_only`,
+                `tp`.`single_seller` AS `provider_single_seller`,
+                `tpo`.`id` AS `id`,
+                `tpo`.`name` AS `name`,
+                `tpo`.`type` AS `type`,
+                `tpo`.`caption` AS `caption`,
+                `tpo`.`description` AS `description`,
+                `tpo`.`extra` AS `extra`,
+                `tpo`.`check_type` AS `check_type`,
+                `tpo`.`check_params` AS `check_params`,
+                `tpo`.`check_error` AS `check_error`
+            FROM `" . $this->_sPrefix . "providers` AS `tp`
+            LEFT JOIN `" . $this->_sPrefix . "providers_options` AS `tpo` ON `tp`.`id`=`tpo`.`provider_id`
+            WHERE `tp`.`active`='1' 
+            ORDER BY `tp`.`order` ASC, `tpo`.`order` ASC";
+
+        return $this->getAll($sQuery);
+    }
+
+    public function getProviders($aParams = array())
+    {
+    	$aMethod = array('name' => 'getAll', 'params' => array(0 => 'query'));
+
+        $sWhereClause = "";
+        if(!empty($aParams['type']))
+	        switch($aParams['type']) {
+                    case 'by_name':
+                        $aMethod['name'] = 'getRow';
+                        $aMethod['params'][1] = array(
+                            'name' => $aParams['name']
+                        );
+
+                        $sWhereClause = " AND `tp`.`name`=:name";
+                        break;
+
+                    case 'for_single':
+                        $aMethod['name'] = 'getAllWithKey';
+                        $aMethod['params'][1] = 'name';
+
+                        $sWhereClause = " AND `tp`.`for_single`='1'";
+                        break;
+
+                    case 'for_recurring':
+                        $aMethod['name'] = 'getAllWithKey';
+                        $aMethod['params'][1] = 'name';
+
+                        $sWhereClause = " AND `tp`.`for_recurring`='1'";
+                        break;
+
+                    case 'all':
+                        $aMethod['name'] = 'getAllWithKey';
+                        $aMethod['params'][1] = 'name';
+
+                        if(!empty($aParams['active'])) 
+                            $sWhereClause = " AND `tp`.`active`='1'";
+                        break;
+	        }          
+
+        $aMethod['params'][0] = "SELECT
+                `tp`.`id` AS `id`,
+                `tp`.`name` AS `name`,
+                `tp`.`caption` AS `caption`,
+                `tp`.`description` AS `description`,
+                `tp`.`option_prefix` AS `option_prefix`,
+                `tp`.`for_visitor` AS `for_visitor`,
+                `tp`.`for_single` AS `for_single`,
+                `tp`.`for_recurring` AS `for_recurring`,
+                `tp`.`class_name` AS `class_name`,
+                `tp`.`class_file` AS `class_file`
+            FROM `" . $this->_sPrefix . "providers` AS `tp`
+            WHERE 1" . $sWhereClause;
+
+        return call_user_func_array(array($this, $aMethod['name']), $aMethod['params']);
+    }
+
+    public function getOption($aParams)
+    {
+        $aMethod = array('name' => 'getAll', 'params' => array(0 => 'query'));
+
+        $sSelectClause = "`tpo`.*";
+        $sJoinClause = $sWhereClause = "";
+        if(!empty($aParams['type']))
+	        switch($aParams['type']) {
+                    case 'by_pid_and_name':
+                        $aMethod['name'] = 'getRow';
+                        $aMethod['params'][1] = array(
+                            'provider_id' => $aParams['provider_id'],
+                            'name' => $aParams['name'],
+                        );
+
+                        $sWhereClause = " AND `tpo`.`provider_id`=:provider_id AND `tpo`.`name`=:name";
+                        break;
+                }
+
+        $aMethod['params'][0] = "SELECT " . $sSelectClause . " FROM `" . $this->_sPrefix . "providers_options` AS `tpo` " . $sJoinClause . " WHERE 1" . $sWhereClause;
+
+        return call_user_func_array(array($this, $aMethod['name']), $aMethod['params']);
+    }
+
+    public function getOptions($iUserId = BX_PAYMENT_EMPTY_ID, $iProviderId = 0)
+    {
+    	$aBinding = array(
+    		'user_id' => $iUserId
+    	);
+
+        if($iUserId == BX_PAYMENT_EMPTY_ID && empty($iProviderId))
+           return $this->getAll("SELECT `id`, `name`, `type` FROM `" . $this->_sPrefix . "providers_options`");
+
+        $sWhereAddon = "";
+        if(!empty($iProviderId)) {
+        	$aBinding['provider_id'] = $iProviderId;
+
+            $sWhereAddon = " AND `tpo`.`provider_id`=:provider_id";
+        }
+
+        $sQuery = "SELECT
+               `tpo`.`name` AS `name`,
+               `tuv`.`value` AS `value`
+            FROM `" . $this->_sPrefix . "providers_options` AS `tpo`
+            LEFT JOIN `" . $this->_sPrefix . "user_values` AS `tuv` ON `tpo`.`id`=`tuv`.`option_id`
+            WHERE 1" . $sWhereAddon . " AND `tuv`.`user_id`=:user_id";
+
+        return $this->getAllWithKey($sQuery, 'name', $aBinding);
+    }
+
+    public function updateOption($iUserId, $iOptionId, $sValue)
+    {
+        $sQuery = $this->prepare("REPLACE INTO `" . $this->_sPrefix . "user_values` SET `user_id`=?, `option_id`=?, `value`=?", $iUserId, $iOptionId, $sValue);
+        return $this->query($sQuery);
+    }
+
+
+    /**
+     * Shopping cart methods.
+     */
+    public function getCartItems($iId)
+    {
+    	$sQuery = $this->prepare("SELECT `items` FROM `" . $this->_sPrefix . "cart` WHERE `client_id`=? LIMIT 1", $iId);
+        return $this->getOne($sQuery);
+    }
+
+    public function getCartContent($iId)
+    {
+        $aCart = $this->getRow("SELECT * FROM `" . $this->_sPrefix . "cart` WHERE `client_id`=:client_id LIMIT 1", array(
+            'client_id' => $iId
+        ));
+
+        if(empty($aCart) || !is_array($aCart))
+            $aCart = array('items' => '', 'customs' => '');
+
+        return $aCart;
+    }
+
+    public function setCartItems($iId, $sItems, $aCustoms = array())
+    {
+        $sItems = trim($sItems, ":");
+        if(empty($sItems))
+            return $this->query("DELETE FROM `" . $this->_sPrefix . "cart` WHERE `client_id`=:client_id LIMIT 1", array(
+                'client_id' => $iId
+            ));
+
+        return $this->query("REPLACE INTO `" . $this->_sPrefix . "cart` SET `client_id`=:client_id, `items`=:items, `customs`=:customs", array(
+            'client_id' => $iId,
+            'items' => $sItems,
+            'customs' => !empty($aCustoms) && is_array($aCustoms) ? serialize($aCustoms) : ''
+        ));
+    }
+
+	public function getVendorInfoProvidersSingle($iVendorId)
+    {
+    	return $this->getVendorInfoProviders($iVendorId, array('type' => 'for_single'));
+    }
+
+	public function getVendorInfoProvidersRecurring($iVendorId)
+    {
+    	return $this->getVendorInfoProviders($iVendorId, array('type' => 'for_recurring'));
+    }
+
+    public function getVendorInfoProviders($iVendorId, $aParams = array())
+    {
+    	if(empty($aParams))
+    		$aParams = array('type' => 'all');
+
+		$aProviders = $this->getProviders($aParams);
+		$aOptions = $this->getOptions($iVendorId);
+
+		$aResult = array();
+		foreach($aProviders as $sProvider => $aProvider) {
+			if(!isset($aOptions[$aProvider['option_prefix'] . 'active']) || $aOptions[$aProvider['option_prefix'] . 'active']['value'] != 'on') 
+                            continue;
+
+                        if(isset($aOptions[$aProvider['option_prefix'] . 'hidden']) && $aOptions[$aProvider['option_prefix'] . 'hidden']['value'] == 'on') 
+                            continue;
+
+                        foreach($aOptions as $sName => $aOption)
+                                if(strpos($sName, $aProvider['option_prefix']) !== false)
+                                        $aProvider['options'][$sName] = $aOption;
+                        $aResult[$sProvider] = $aProvider;
+                }
+
+		return $aResult;
+	}
+
+    public function getAdminsIds()
+    {
+        $sQuery = "SELECT 
+        		`tp`.`id` AS `id`,
+        		`tp`.`type` AS `type`  
+        	FROM `sys_profiles` AS `tp` 
+        	INNER JOIN `sys_accounts` AS `ta` ON `tp`.`account_id`=`ta`.`id` AND `ta`.`role`&" . BX_DOL_ROLE_ADMIN . " 
+        	WHERE 
+        		`tp`.`type`<>'system' AND `tp`.`status`='active' 
+        	ORDER BY `tp`.`id` ASC";
+
+        $aAdmins = $this->getAllWithKey($sQuery, 'id');
+        foreach($aAdmins as $iId => $aAdmin)
+            if(!BxDolService::call($aAdmin['type'], 'act_as_profile'))
+                unset($aAdmins[$iId]);
+
+        return array_keys($aAdmins);
+    }
+
+
+	/*
+     * Pending Orders methods
+     */
+    public function getOrderPending($aParams)
+    {
+    	$aMethod = array('name' => 'getRow', 'params' => array(0 => 'query'));
+
+    	$sWhereClause = $sLimitClause = '';
+        switch($aParams['type']) {
+            case 'id':
+            	$aMethod['params'][1] = array(
+                	'id' => $aParams['id']
+                );
+
+                $sWhereClause = " AND `id`=:id";
+                $sLimitClause = " LIMIT 1";
+                break;
+
+            case 'order':
+            	$aMethod['params'][1] = array(
+                	'order' => $aParams['order']
+                );
+
+            	$sWhereClause = " AND `order`=:order";
+                $sLimitClause = " LIMIT 1";
+                break;
+
+            case 'mixed':
+                $aMethod['name'] = 'getAll';
+
+                $sWhereClause = ' AND ' . $this->arrayToSQL($aParams['conditions'], ' AND ');
+                break;
+        }
+
+        $aMethod['params'][0] = "SELECT * FROM `" . $this->_sPrefix . "transactions_pending` WHERE 1 " . $sWhereClause . $sLimitClause;
+        return call_user_func_array(array($this, $aMethod['name']), $aMethod['params']);
+    }
+
+    public function insertOrderPending($iClientId, $sType, $sProvider, $aCartInfo, $aCustom = array())
+    {
+        $sItems = "";
+        foreach($aCartInfo['items'] as $aItem) {
+            $sItems .= $this->_oConfig->descriptorA2S(array($aItem['author_id'], $aItem['module_id'], $aItem['id'], $aItem['quantity'])) . ':';
+
+            if(empty($aItem['addons']) || !is_array($aItem['addons']))
+                continue;
+
+            foreach($aItem['addons'] as $sAddon => $aAddon)
+                $sItems .= $this->_oConfig->descriptorA2S(array($aAddon['author_id'], $aAddon['module_id'], $aAddon['id'], $aAddon['quantity'])) . ':';
+        }
+
+        return (int)$this->query("INSERT INTO `" . $this->_sPrefix . "transactions_pending` SET `client_id`=:client_id, `seller_id`=:seller_id, `type`=:type, `provider`=:provider, `items`=:items, `customs`=:customs, `amount`=:amount, `date`=UNIX_TIMESTAMP()", array(
+            'client_id' => $iClientId,
+            'seller_id' => $aCartInfo['vendor_id'],
+            'type' => $sType, 
+            'provider' => $sProvider,
+            'items' => trim($sItems, ':'),
+            'customs' => !empty($aCustom) && is_array($aCustom) ? serialize($aCustom) : '',
+            'amount' => $aCartInfo['items_price']
+        )) > 0 ? $this->lastId() : 0;
+    }
+
+    public function updateOrderPending($iId, $aValues)
+    {
+        $sQuery = $this->prepare("UPDATE `" . $this->_sPrefix . "transactions_pending` SET " . $this->arrayToSQL($aValues) . " WHERE `id`=?", $iId);
+        return (int)$this->query($sQuery) > 0;
+    }
+
+    public function deleteOrderPending($mixedId)
+    {
+    	if(!is_array($mixedId))
+    		$mixedId = array($mixedId);
+
+        return (int)$this->query("DELETE FROM `" . $this->_sPrefix . "transactions_pending` WHERE `id` IN (" . $this->implode_escape($mixedId) . ")") > 0;
+    }
+
+    /*
+     * Processed Orders
+     */
+    public function getOrderProcessed($aParams)
+    {
+    	$aMethod = array('name' => 'getRow', 'params' => array(0 => 'query'));
+
+        $sSelectClause = "`tt`.`id`, `tt`.`license`, `ttp`.`type`, `tt`.`client_id`, `tt`.`seller_id`, `tt`.`author_id`, `tt`.`module_id`, `tt`.`item_id`, `tt`.`item_count`, `tt`.`amount`, `tt`.`date`, `ttp`.`order`, `ttp`.`error_msg`, `ttp`.`provider`";
+        $sWhereClause = $sGroupClause = "";
+
+        switch($aParams['type']) {
+            case 'id':
+            	$aMethod['params'][1] = array(
+                    'id' => $aParams['id']
+                );
+
+                $sWhereClause = " AND `tt`.`id`=:id";
+                break;
+
+            case 'new':
+                $aMethod['name'] = 'getAll';
+                $aMethod['params'][1] = array(
+                    'seller_id' => $aParams['seller_id']
+                );
+
+                $sWhereClause = " AND `tt`.`seller_id`=:seller_id AND `tt`.`new`='1'";
+                break;
+
+            case 'pending_id':
+                if(empty($aParams['with_key'])) {
+                    $aMethod['name'] = 'getAll';
+                    $aMethod['params'][1] = array(
+                        'pending_id' => $aParams['pending_id']
+                    );
+                }
+                else {
+                    $aMethod['name'] = 'getAllWithKey';
+                    $aMethod['params'][1] = $aParams['with_key'];
+                    $aMethod['params'][2] = array(
+                        'pending_id' => $aParams['pending_id']
+                    );
+                }
+
+                $sWhereClause = " AND `tt`.`pending_id`=:pending_id";
+                break;
+
+            case 'clients':
+                $aMethod['name'] = 'getColumn';
+                $aMethod['params'][1] = array(
+                    'seller_id' => $aParams['seller_id']
+                );
+
+                $sSelectClause = "DISTINCT `tt`.`client_id`";
+                $sWhereClause = " AND `tt`.`seller_id`=:seller_id";
+                break;
+
+            case 'authors':
+                $aMethod['name'] = 'getColumn';
+                $aMethod['params'][1] = array(
+                    'seller_id' => $aParams['seller_id']
+                );
+
+                $sSelectClause = "DISTINCT `tt`.`author_id`";
+                $sWhereClause = " AND `tt`.`seller_id`=:seller_id";
+                break;
+
+            case 'license':
+                $aMethod['name'] = 'getAll';
+                $aMethod['params'][1] = array(
+                    'license' => $aParams['license']
+                );
+
+                $sWhereClause = " AND `tt`.`license`=:license";
+                break;
+            
+            case 'income':
+                $aMethod['name'] = 'getAll';
+                $aMethod['params'][1] = array(
+                    'period_start' => $aParams['period_start'],
+                    'period_end' => $aParams['period_end']
+                );
+
+                $sSelectClause = '`tt`.`author_id` AS `id`, SUM(`tt`.`amount`) AS `amount`';
+                $sWhereClause = ' AND `tt`.`date`>=:period_start AND `tt`.`date`<=:period_end';
+                $sGroupClause = '`tt`.`author_id`';
+                break;
+
+            case 'mixed':
+                $aMethod['name'] = 'getAll';
+
+                $sWhereClause = ' AND ' . $this->arrayToSQL($aParams['conditions'], ' AND ');
+                break;
+
+        }
+
+        if(!empty($sGroupClause))
+            $sGroupClause = ' GROUP BY ' . $sGroupClause;
+
+        $aMethod['params'][0] = "SELECT
+                " . $sSelectClause . "
+            FROM `" . $this->_sPrefix . "transactions` AS `tt`
+            LEFT JOIN `" . $this->_sPrefix . "transactions_pending` AS `ttp` ON `tt`.`pending_id`=`ttp`.`id`
+            WHERE 1" . $sWhereClause . $sGroupClause;
+
+        return call_user_func_array(array($this, $aMethod['name']), $aMethod['params']);
+    }
+
+    public function insertOrderProcessed($aValues)
+    {
+        return $this->query("INSERT INTO `" . $this->_sPrefix . "transactions` SET " . $this->arrayToSQL($aValues) . ", `date`=UNIX_TIMESTAMP()");
+    }
+
+    public function updateOrderProcessed($iId, $aValues)
+    {        
+        return $this->updateOrdersProcessed($aValues, array('id' => $iId));
+    }
+
+    public function updateOrdersProcessed($aValues, $aWhere)
+    {
+        if(empty($aValues) || !is_array($aValues) || empty($aWhere) || !is_array($aWhere))
+            return false;
+
+        return (int)$this->query("UPDATE `" . $this->_sPrefix . "transactions` SET " . $this->arrayToSQL($aValues) . " WHERE " . $this->arrayToSQL($aWhere, ' AND ')) > 0;
+    }
+
+    public function deleteOrderProcessed($mixedId)
+    {
+    	if(!is_array($mixedId))
+            $mixedId = array($mixedId);
+
+        return (int)$this->query("DELETE FROM `" . $this->_sPrefix . "transactions` WHERE `id` IN (" . $this->implode_escape($mixedId) . ")") > 0;
+    }
+
+    public function getOrderHistory($aParams)
+    {
+        return $this->getOrderProcessed($aParams);
+    }
+
+    /*
+     * Subscriptions methods
+     */
+    public function getOrderSubscription($aParams)
+    {
+        return $this->getOrderPending($aParams);
+    }
+
+    public function getSubscription($aParams)
+    {
+    	$aMethod = array('name' => 'getAll', 'params' => array(0 => 'query'));
+
+        $sSelectClause = "`ts`.*";
+    	$sJoinClause = $sWhereClause = $sLimitClause = '';
+        switch($aParams['type']) {
+            case 'pending_id':
+                $aMethod['name'] = 'getRow';
+            	$aMethod['params'][1] = array(
+                    'pending_id' => $aParams['pending_id']
+                );
+
+                $sWhereClause = " AND `ts`.`pending_id`=:pending_id";
+                $sLimitClause = " LIMIT 1";
+                break;
+
+            case 'mixed':
+                $sWhereClause = " AND " . $this->arrayToSQL($aParams['conditions'], ' AND ');
+                break;
+
+            case 'mixed_ext':
+                $sSelectClause .= ", `ttp`.`client_id`, `ttp`.`seller_id`, `ttp`.`type`, `ttp`.`provider`, `ttp`.`order`";
+                $sJoinClause = "LEFT JOIN `" . $this->_sPrefix . "transactions_pending` AS `ttp` ON `ts`.`pending_id`=`ttp`.`id`";
+                $sWhereClause = " AND " . $this->arrayToSQL($aParams['conditions'], ' AND ');
+                break;
+
+            case 'time_tracker':
+                $aMethod['params'][1] = array(
+                    'status_active' => $aParams['status_active'],
+                    'status_trial' => $aParams['status_trial'],
+                    'status_unpaid' => $aParams['status_unpaid'],
+                    'pay_attempts_max' => $aParams['pay_attempts_max'],
+                    'pay_attempts_interval' => $aParams['pay_attempts_interval']
+                );
+
+                $sSelectClause .= ", `ttp`.`client_id`, `ttp`.`seller_id`, `ttp`.`type`, `ttp`.`provider`, `ttp`.`amount`, `ttp`.`order`";
+                $sJoinClause = "LEFT JOIN `" . $this->_sPrefix . "transactions_pending` AS `ttp` ON `ts`.`pending_id`=`ttp`.`id` INNER JOIN `" . $this->_sPrefix . "providers` AS `tp` ON `ttp`.`provider`=`tp`.`name` AND `tp`.`time_tracker`='1'";
+                $sWhereClause = " AND `ts`.`date_next`<=UNIX_TIMESTAMP() AND (`ts`.`status`=:status_active OR `ts`.`status`=:status_trial OR (`ts`.`status`=:status_unpaid AND `ts`.`pay_attempts`<:pay_attempts_max AND DATE_ADD(FROM_UNIXTIME(`ts`.`date_next`), INTERVAL `ts`.`pay_attempts`*:pay_attempts_interval SECOND)<=NOW()))";
+                break;
+        }
+
+        $aMethod['params'][0] = "SELECT " . $sSelectClause . " FROM `" . $this->_sPrefix . "subscriptions` AS `ts` " . $sJoinClause . " WHERE 1 " . $sWhereClause . $sLimitClause;
+        return call_user_func_array(array($this, $aMethod['name']), $aMethod['params']);
+    }
+
+    public function isSubscriptionByPending($iPending)
+    {
+    	$aSubscription = $this->getSubscription(array(
+            'type' => 'pending_id', 
+            'pending_id' => $iPending
+    	));
+
+    	return !empty($aSubscription) && is_array($aSubscription);
+    }
+
+    public function insertSubscription($aValues)
+    {
+        if(empty($aValues) || !is_array($aValues))
+            return false;
+
+        $sSetClause = $this->arrayToSQL($aValues);
+        if(empty($aValues['date_add']))
+            $sSetClause .= ", `date_add`=UNIX_TIMESTAMP()";
+
+        return (int)$this->query("INSERT INTO `" . $this->_sPrefix . "subscriptions` SET " . $sSetClause) > 0;
+    }
+
+    public function updateSubscription($aValues, $aWhere)
+    {
+        if(empty($aValues) || !is_array($aValues) || empty($aWhere) || !is_array($aWhere))
+            return false;
+
+        return (int)$this->query("UPDATE `" . $this->_sPrefix . "subscriptions` SET " . $this->arrayToSQL($aValues) . " WHERE " . $this->arrayToSQL($aWhere, ' AND ')) > 0;
+    }
+
+    public function deleteSubscription($mixedId, $sReason)
+    {
+    	if(!is_array($mixedId))
+            $mixedId = array($mixedId);
+
+        //--- Move to deleted subscriptions table.   
+    	$sQuery = "INSERT IGNORE INTO `" . $this->_sPrefix . "subscriptions_deleted` SELECT *, :reason AS `reason`, UNIX_TIMESTAMP() AS `deleted` FROM `" . $this->_sPrefix . "subscriptions` WHERE `id` IN (" . $this->implode_escape($mixedId) . ")";
+        $this->query($sQuery, array(
+            'reason' => $sReason
+        ));
+
+        return (int)$this->query("DELETE FROM `" . $this->_sPrefix . "subscriptions` WHERE `id` IN (" . $this->implode_escape($mixedId) . ")") > 0;
+    }
+
+    //--- Order Administration ---//
+    public function onProfileDelete($iId)
+    {
+    	$sQuery = $this->prepare("DELETE FROM `" . $this->_sPrefix . "cart` WHERE `client_id`=?", $iId);
+    	$this->query($sQuery);
+
+    	$sQuery = $this->prepare("DELETE FROM `" . $this->_sPrefix . "user_values` WHERE `user_id`=?", $iId);
+    	$this->query($sQuery);
+    }
+
+
+    /*
+     * Commissions methods
+     */
+    public function getCommissions($aParams = array())
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+    	$aMethod = array('name' => 'getAll', 'params' => array(0 => 'query'));
+
+        $sSelectClause = "`tc`.*";
+        $sWhereClause = $sOrderClause = "";
+        if(!empty($aParams['type']))
+            switch($aParams['type']) {
+                case 'max_order':
+                    $aMethod['name'] = 'getOne';
+                    $aMethod['params'][1] = array();
+
+                    $sSelectClause = "IFNULL(MAX(`tc`.`order`), 0)";
+                    break;
+
+                case 'id':
+                    $aMethod['name'] = 'getRow';
+                    $aMethod['params'][1] = array(
+                        'id' => $aParams['id']
+                    );
+
+                    $sWhereClause = " AND `tc`.`id`=:id";
+                    break;
+
+                case 'acl_id':
+                    $aMethod['name'] = 'getAll';
+                    $aMethod['params'][1] = array(
+                        'acl_id' => $aParams['acl_id']
+                    );
+
+                    $sWhereClause = " AND (`tc`.`acl_id`=:acl_id OR `tc`.`acl_id`=0)";
+                    $sOrderClause = "`tc`.`order` ASC";
+                    break;
+
+                case 'all':
+                    if(!empty($aParams['active'])) 
+                        $sWhereClause = " AND `tc`.`active`='1'";
+                    break;
+            }
+
+        if(!empty($sOrderClause))
+            $sOrderClause = " ORDER BY " . $sOrderClause;
+
+        $aMethod['params'][0] = "SELECT " . $sSelectClause . "
+            FROM `" . $CNF['TABLE_COMMISSIONS'] . "` AS `tc`
+            WHERE 1" . $sWhereClause . $sOrderClause;
+
+        return call_user_func_array(array($this, $aMethod['name']), $aMethod['params']);
+    }
+
+    public function getInvoices($aParams = array())
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+    	$aMethod = array('name' => 'getAll', 'params' => array(0 => 'query'));
+
+        $sSelectClause = "`ti`.*";
+        $sWhereClause = "";
+        if(!empty($aParams['type']))
+            switch($aParams['type']) {
+                case 'index':
+                    $aMethod['name'] = 'getOne';
+                    $aMethod['params'][1] = array(
+                        'commissionaire_id' => $aParams['commissionaire_id'],
+                        'committent_id' => $aParams['committent_id'],
+                    );
+
+                    $sSelectClause = "COUNT(`ti`.`id`) + 1";
+                    $sWhereClause = " AND `ti`.`commissionaire_id`=:commissionaire_id AND `ti`.`committent_id`=:committent_id";
+                    break;
+
+                case 'id':
+                    $aMethod['name'] = 'getRow';
+                    $aMethod['params'][1] = array(
+                        'id' => $aParams['id']
+                    );
+
+                    $sWhereClause = " AND `ti`.`id`=:id";
+                    break;
+
+                case 'commissionaire_id':
+                    $aMethod['params'][1] = array(
+                        'commissionaire_id' => $aParams['commissionaire_id']
+                    );
+
+                    $sWhereClause = " AND `ti`.`commissionaire_id`=:commissionaire_id";
+                    break;
+
+                case 'committent_id':
+                    $aMethod['params'][1] = array(
+                        'committent_id' => $aParams['committent_id']
+                    );
+
+                    $sWhereClause = " AND `ti`.`committent_id`=:committent_id";
+
+                    if(!empty($aParams['period_start'])) {
+                        $aMethod['params'][1]['period_start'] = (int)$aParams['period_start'];
+
+                        $sWhereClause .= " AND `ti`.`period_start`=:period_start";
+                    }
+
+                    if(!empty($aParams['period_end'])) {
+                        $aMethod['params'][1]['period_end'] = (int)$aParams['period_end'];
+
+                        $sWhereClause .= " AND `ti`.`period_end`=:period_end";
+                    }
+                    break;
+
+                case 'expiring':
+                    $aMethod['params'][1] = array(
+                        'notify_days' => $CNF['PARAM_CMSN_INVOICE_EXPIRATION_NOTIFY'],
+                        'status' => BX_PAYMENT_INV_STATUS_UNPAID
+                    );
+
+                    $sWhereClause = " AND DATE_SUB(FROM_UNIXTIME(`ti`.`date_due`), INTERVAL :notify_days DAY) < NOW() AND DATE_SUB(FROM_UNIXTIME(`ti`.`date_due`), INTERVAL (:notify_days - 1) DAY) > NOW() AND `ti`.`status`=:status";
+                    break;
+
+                case 'overdue':
+                    $aMethod['params'][1] = array(
+                        'status_unpaid' => BX_PAYMENT_INV_STATUS_UNPAID,
+                        'status_overdue' => BX_PAYMENT_INV_STATUS_OVERDUE
+                    );
+
+                    $sWhereClause = " AND `ti`.`date_due` < UNIX_TIMESTAMP() AND (`ti`.`status`=:status_unpaid OR (`ti`.`status`=:status_overdue AND `ti`.`ntf_due`='0'))";
+                    break;
+
+                case 'status':
+                    $aMethod['params'][1] = array(
+                        'status' => $aParams['status']
+                    );
+
+                    $sWhereClause = " AND `ti`.`status`=:status";
+                    
+                    if(isset($aParams['count']) && $aParams['count'] === true) {
+                        $sSelectClause = "COUNT(`ti`.`id`)";
+                        $aMethod['name'] = 'getOne';
+                    }
+
+                    if(isset($aParams['committent_id'])) {
+                        $aMethod['params'][1]['committent_id'] = $aParams['committent_id'];
+
+                        $sWhereClause .= " AND `ti`.`committent_id`=:committent_id";
+                    }
+                    break;
+
+                case 'all_count':
+                    $sSelectClause = "COUNT(`ti`.`id`)";
+                    $aMethod['name'] = 'getOne';
+                    break;
+                
+                case 'all':
+                    break;
+            }
+
+        $aMethod['params'][0] = "SELECT " . $sSelectClause . "
+            FROM `" . $CNF['TABLE_INVOICES'] . "` AS `ti`
+            WHERE 1" . $sWhereClause;
+
+        return call_user_func_array(array($this, $aMethod['name']), $aMethod['params']);
+    }
+
+    public function insertInvoice($aValues)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        return $this->query("INSERT INTO `" . $CNF['TABLE_INVOICES'] . "` SET " . $this->arrayToSQL($aValues));
+    }
+
+    public function updateInvoice($mixedId, $aValues)
+    {
+        $CNF = &$this->_oConfig->CNF;
+        
+        if(!is_array($mixedId))
+            $mixedId = array($mixedId);
+
+        return (int)$this->query("UPDATE `" . $CNF['TABLE_INVOICES'] . "` SET " . $this->arrayToSQL($aValues) . " WHERE `id` IN (" . $this->implode_escape($mixedId) . ')') > 0;
+    }
+
+    public function deleteInvoice($mixedId)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+    	if(!is_array($mixedId))
+            $mixedId = array($mixedId);
+
+        return (int)$this->query("DELETE FROM `" . $CNF['TABLE_INVOICES'] . "` WHERE `id` IN (" . $this->implode_escape($mixedId) . ")") > 0;
+    }
+}
+
+/** @} */

+ 36 - 0
modules/boonex/payment/updates/12.0.0_12.0.1/source/classes/BxPaymentFormCommissions.php

@@ -0,0 +1,36 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Payment Payment
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxPaymentFormCommissions extends BxTemplStudioFormView
+{
+    protected $_sModule;
+    protected $_oModule;
+
+    function __construct($aInfo, $oTemplate = false)
+    {
+        parent::__construct($aInfo, $oTemplate);
+        
+        $this->_sModule = 'bx_payment';
+        $this->_oModule = BxDolModule::getInstance($this->_sModule);
+
+        if(isset($this->aInputs['acl_id'])) {
+            $this->aInputs['acl_id']['values'] = array(
+                array('key' => '0', 'value' => _t('_Select_one'))
+            );
+
+            $aLevels = BxDolAcl::getInstance()->getMemberships(false, true, false, true);
+            foreach($aLevels as $iLevelId => $sLevelTitle)
+               $this->aInputs['acl_id']['values'][] = array('key' => $iLevelId, 'value' => _t($sLevelTitle));
+        }
+    }
+}
+
+/** @} */

+ 34 - 0
modules/boonex/payment/updates/12.0.0_12.0.1/source/classes/BxPaymentFormInvoices.php

@@ -0,0 +1,34 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Payment Payment
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxPaymentFormInvoices extends BxTemplFormView
+{
+    protected $_sModule;
+    protected $_oModule;
+
+    function __construct($aInfo, $oTemplate = false)
+    {
+        parent::__construct($aInfo, $oTemplate);
+
+        $this->_sModule = 'bx_payment';
+        $this->_oModule = BxDolModule::getInstance($this->_sModule);
+
+        if(isset($this->aInputs['status'])) {
+            $aStatuses = array(BX_PAYMENT_INV_STATUS_UNPAID, BX_PAYMENT_INV_STATUS_PAID, BX_PAYMENT_INV_STATUS_OVERDUE);
+
+            $this->aInputs['status']['values'] = array();
+            foreach($aStatuses as $sStatus)
+                $this->aInputs['status']['values'][] = array('key' => $sStatus, 'value' => _t('_bx_payment_txt_status_' . $sStatus));
+        }
+    }
+}
+
+/** @} */

+ 140 - 0
modules/boonex/payment/updates/12.0.0_12.0.1/source/classes/BxPaymentGridCommissions.php

@@ -0,0 +1,140 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Payment Payment
+ * @ingroup     UnaModules
+ * 
+ * @{
+ */
+
+class BxPaymentGridCommissions extends BxBaseModPaymentGridCommissions
+{
+    public function __construct ($aOptions, $oTemplate = false)
+    {
+        $this->_sModule = 'bx_payment';
+
+        parent::__construct ($aOptions, $oTemplate);
+    }
+
+    public function performActionAdd()
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        $sAction = 'add';
+
+        $oForm = $this->_getFormObject($sAction);
+        $oForm->initChecker();
+        if($oForm->isSubmittedAndValid()) {
+            $sFormMethod = $oForm->aFormAttrs['method'];
+
+            $sLanguage = BxDolStudioLanguagesUtils::getInstance()->getCurrentLangName(false);
+
+            $sName = BxDolForm::getSubmittedValue('caption-' . $sLanguage, $sFormMethod);
+            $sName = uriGenerate(strtolower($sName), $CNF['TABLE_COMMISSIONS'], 'name', 'commission');
+
+            $aValsToAdd = array(
+                'name' => $sName,
+                'active' => 1,
+                'order' => $this->_oModule->_oDb->getCommissions(array('type' => 'max_order')) + 1
+            );
+
+            if(($iId = $oForm->insert($aValsToAdd)) !== false)
+                $aRes = array('grid' => $this->getCode(false), 'blink' => $iId);
+            else
+                $aRes = array('msg' => _t('_bx_payment_err_cannot_perform'));
+
+            return echoJson($aRes);
+        }
+
+        $sId = $this->_oModule->_oConfig->getHtmlIds('commission', 'popup_' . $sAction);
+        $sTitle = _t($this->_sLangsPrefix . 'popup_title_cms_' . $sAction);
+
+        $sContent = BxTemplStudioFunctions::getInstance()->popupBox($sId, $sTitle, $this->_oModule->_oTemplate->parseHtmlByName('commission_form.html', array(
+            'form_id' => $oForm->aFormAttrs['id'],
+            'form' => $oForm->getCode(true),
+            'object' => $this->_sObject,
+            'action' => $sAction
+        )));
+
+        echoJson(array('popup' => array('html' => $sContent, 'options' => array('closeOnOuterClick' => false))));
+    }
+
+    public function performActionEdit()
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        $aIds = bx_get('ids');
+        if(!$aIds || !is_array($aIds)) {
+            $iId = (int)bx_get('id');
+            if(!$iId)
+                return echoJson(array());
+
+            $aIds = array($iId);
+        }
+
+        $iId = (int)array_shift($aIds);
+        $aCommission = $this->_oModule->_oDb->getCommissions(array('type' => 'id', 'id' => $iId));
+        if(empty($aCommission) || !is_array($aCommission))
+            return echoJson(array());
+
+        $sAction = 'edit';
+
+        $oForm = $this->_getFormObject($sAction, $iId);
+        $oForm->initChecker($aCommission);
+        if($oForm->isSubmittedAndValid()) {
+            if($oForm->update($iId) !== false)
+                $aRes = array('grid' => $this->getCode(false), 'blink' => $iId);
+            else
+                $aRes = array('msg' => _t('_bx_payment_err_cannot_perform'));
+
+            return echoJson($aRes);
+        }
+
+        $sId = $this->_oModule->_oConfig->getHtmlIds('commission', 'popup_' . $sAction);
+        $sTitle = _t($this->_sLangsPrefix . 'popup_title_cms_' . $sAction);
+
+        $sContent = BxTemplStudioFunctions::getInstance()->popupBox($sId, $sTitle, $this->_oModule->_oTemplate->parseHtmlByName('commission_form.html', array(
+            'form_id' => $oForm->aFormAttrs['id'],
+            'form' => $oForm->getCode(true),
+            'object' => $this->_sObject,
+            'action' => $sAction
+        )));
+
+        echoJson(array('popup' => array('html' => $sContent, 'options' => array('closeOnOuterClick' => false))));
+    }
+
+    protected function _delete($mixedId)
+    {
+        $aCommission = $this->_oModule->_oDb->getCommissions(array('type' => 'id', 'id' => $mixedId));
+        if(empty($aCommission) || !is_array($aCommission))
+            return false;
+
+        $mixedResult = parent::_delete($mixedId);
+        if($mixedResult !== false) {
+            $oLanguage = BxDolStudioLanguagesUtils::getInstance();
+            $oLanguage->deleteLanguageString($aCommission['caption']);
+            $oLanguage->deleteLanguageString($aCommission['description']);
+        }
+
+        return $mixedResult;
+    }
+
+    protected function _getFormObject($sAction, $iId = 0)
+    {
+        $sFormObject = $this->_oModule->_oConfig->getObject('form_commissions');
+        $sFormDisplay = $this->_oModule->_oConfig->getObject('form_display_commissions_' . $sAction);
+
+        $aParams = array('o' => $this->_sObject, 'a' => $sAction);
+        if(!empty($iId))
+            $aParams['id'] = $iId;
+
+        $oForm = BxDolForm::getObjectInstance($sFormObject, $sFormDisplay);
+        $oForm->aFormAttrs['action'] = BX_DOL_URL_ROOT . bx_append_url_params('grid.php', $aParams);
+
+        return $oForm;
+    }
+}
+
+/** @} */

+ 81 - 0
modules/boonex/payment/updates/12.0.0_12.0.1/source/classes/BxPaymentGridInvoices.php

@@ -0,0 +1,81 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Payment Payment
+ * @ingroup     UnaModules
+ * 
+ * @{
+ */
+
+class BxPaymentGridInvoices extends BxBaseModPaymentGridInvoices
+{
+    public function __construct ($aOptions, $oTemplate = false)
+    {
+        $this->_sModule = 'bx_payment';
+
+        parent::__construct ($aOptions, $oTemplate);
+    }
+
+    public function performActionEdit()
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        $aIds = bx_get('ids');
+        if(!$aIds || !is_array($aIds)) {
+            $iId = (int)bx_get('id');
+            if(!$iId)
+                return echoJson(array());
+
+            $aIds = array($iId);
+        }
+
+        $iId = (int)array_shift($aIds);
+        $aInvoice = $this->_oModule->_oDb->getInvoices(array('type' => 'id', 'id' => $iId));
+        if(empty($aInvoice) || !is_array($aInvoice))
+            return echoJson(array());
+
+        $sAction = 'edit';
+
+        $oForm = $this->_getFormObject($sAction, $iId);
+        $oForm->initChecker($aInvoice);
+        if($oForm->isSubmittedAndValid()) {
+            if($oForm->update($iId) !== false)
+                $aRes = array('grid' => $this->getCode(false), 'blink' => $iId);
+            else
+                $aRes = array('msg' => _t('_bx_payment_err_cannot_perform'));
+
+            return echoJson($aRes);
+        }
+
+        $sId = $this->_oModule->_oConfig->getHtmlIds('invoice', 'popup_' . $sAction);
+        $sTitle = _t($this->_sLangsPrefix . 'popup_title_cms_' . $sAction);
+
+        $sContent = BxTemplStudioFunctions::getInstance()->popupBox($sId, $sTitle, $this->_oModule->_oTemplate->parseHtmlByName('commission_form.html', array(
+            'form_id' => $oForm->aFormAttrs['id'],
+            'form' => $oForm->getCode(true),
+            'object' => $this->_sObject,
+            'action' => $sAction
+        )));
+
+        echoJson(array('popup' => array('html' => $sContent, 'options' => array('closeOnOuterClick' => false))));
+    }
+
+    protected function _getFormObject($sAction, $iId = 0)
+    {
+        $sFormObject = $this->_oModule->_oConfig->getObject('form_invoices');
+        $sFormDisplay = $this->_oModule->_oConfig->getObject('form_display_invoices_' . $sAction);
+
+        $aParams = array('o' => $this->_sObject, 'a' => $sAction);
+        if(!empty($iId))
+            $aParams['id'] = $iId;
+
+        $oForm = BxDolForm::getObjectInstance($sFormObject, $sFormDisplay);
+        $oForm->aFormAttrs['action'] = BX_DOL_URL_ROOT . bx_append_url_params('grid.php', $aParams);
+
+        return $oForm;
+    }
+}
+
+/** @} */

+ 90 - 0
modules/boonex/payment/updates/12.0.0_12.0.1/source/classes/BxPaymentGridPending.php

@@ -0,0 +1,90 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Payment Payment
+ * @ingroup     UnaModules
+ * 
+ * @{
+ */
+
+
+class BxPaymentGridPending extends BxBaseModPaymentGridOrders
+{
+    public function __construct ($aOptions, $oTemplate = false)
+    {
+    	$this->MODULE = 'bx_payment';
+
+        parent::__construct ($aOptions, $oTemplate);
+
+        $this->_sOrdersType = 'pending';
+    }
+
+	public function performActionProcess()
+    {
+    	$aIds = bx_get('ids');
+        if(!$aIds || !is_array($aIds)) {
+            $iId = (int)bx_get('id');
+            if(!$iId)
+                return echoJson(array());
+
+            $aIds = array($iId);
+        }
+
+        $iId = (int)$aIds[0];
+
+    	$sAction = 'process';
+        $sFormObject = $this->_oModule->_oConfig->getObject('form_pendings');
+        $sFormDisplay = $this->_oModule->_oConfig->getObject('form_display_pendings_process');
+
+        $oForm = BxDolForm::getObjectInstance($sFormObject, $sFormDisplay, $this->_oModule->_oTemplate);
+        $oForm->aFormAttrs['action'] = BX_DOL_URL_ROOT . 'grid.php?o=' . $this->_sObject . '&a=' . $sAction;
+
+        $oForm->aInputs['id']['value'] = $iId;
+        $oForm->aInputs['seller_id']['value'] = $this->_aQueryAppend['seller_id'];
+
+        $oForm->initChecker();
+        if($oForm->isSubmittedAndValid()) {
+        	$iId = $oForm->getCleanValue('id');
+
+			$this->_oModule->_oDb->updateOrderPending($iId, array(
+				'order' => $oForm->getCleanValue('order'),
+				'error_code' => 0,
+				'error_msg' => 'Manually processed'
+			));
+
+            if($this->_oModule->registerPayment($iId))
+                $aRes = array('grid' => $this->getCode(false), 'blink' => $iId);
+            else
+                $aRes = array('msg' => _t($this->_sLangsPrefix . 'err_cannot_perform'));
+
+            return echoJson($aRes);
+        }
+
+        $sKey = 'order_' . $this->_sOrdersType . '_process';
+        $sId = $this->_oModule->_oConfig->getHtmlIds('pending', $sKey);
+    	$sTitle = _t($this->_sLangsPrefix . 'popup_title_ods_' . $sKey);
+
+		$sContent = BxTemplStudioFunctions::getInstance()->popupBox($sId, $sTitle, $this->_oModule->_oTemplate->parseHtmlByName('order_pending_process.html', array(
+			'form_id' => $oForm->aFormAttrs['id'],
+			'form' => $oForm->getCode(true),
+			'object' => $this->_sObject,
+			'action' => $sAction
+		)));
+
+		echoJson(array('popup' => array('html' => $sContent, 'options' => array('closeOnOuterClick' => false))));
+    }
+
+	protected function _getDataSql($sFilter, $sOrderField, $sOrderDir, $iStart, $iPerPage)
+    {
+    	if(empty($this->_aQueryAppend['seller_id']))
+    		return array();
+
+		$this->_aOptions['source'] .= $this->_oModule->_oDb->prepareAsString(" AND `tt`.`seller_id`=?", $this->_aQueryAppend['seller_id']);
+
+        return parent::_getDataSql($sFilter, $sOrderField, $sOrderDir, $iStart, $iPerPage);
+    }
+}
+
+/** @} */

+ 257 - 0
modules/boonex/payment/updates/12.0.0_12.0.1/source/classes/BxPaymentGridProcessed.php

@@ -0,0 +1,257 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Payment Payment
+ * @ingroup     UnaModules
+ * 
+ * @{
+ */
+
+
+class BxPaymentGridProcessed extends BxBaseModPaymentGridOrders
+{
+    public function __construct ($aOptions, $oTemplate = false)
+    {
+    	$this->MODULE = 'bx_payment';
+
+        parent::__construct ($aOptions, $oTemplate);
+
+        $this->_sOrdersType = 'processed';
+
+        $this->_sJsObject = $this->_oModule->_oConfig->getJsObject('processed');
+    }
+
+    public function performActionAdd()
+    {
+        $sType = BX_PAYMENT_TYPE_SINGLE;
+        $sAction = 'add';
+        $sJsObject = $this->_oModule->_oConfig->getJsObject('processed');
+
+        $sFormObject = $this->_oModule->_oConfig->getObject('form_processed');
+        $sFormDisplay = $this->_oModule->_oConfig->getObject('form_display_processed_add');
+
+        $oForm = BxDolForm::getObjectInstance($sFormObject, $sFormDisplay, $this->_oModule->_oTemplate);
+        $oForm->aFormAttrs['action'] = BX_DOL_URL_ROOT . 'grid.php?o=' . $this->_sObject . '&a=' . $sAction;
+
+        $oForm->aInputs['seller_id']['value'] = $this->_aQueryAppend['seller_id'];
+
+        $oForm->aInputs['client_id']['attrs'] = array(
+            'id' => $this->_oModule->_oConfig->getHtmlIds('processed', 'order_processed_client_id'),
+        );
+
+        $oForm->aInputs['client']['attrs'] = array(
+            'id' => $this->_oModule->_oConfig->getHtmlIds('processed', 'order_processed_client')			
+        );
+
+        $oForm->aInputs['client']['ajax_get_suggestions'] = BX_DOL_URL_ROOT . 'modules/?r=' . $this->_oModule->_oConfig->getUri() . '/get_clients';
+
+        $oForm->aInputs['client']['custom'] = array(
+            'only_once' => true,
+            'on_select' => "function(oObject){{$sJsObject}.showPopup(oObject);}"
+        );
+
+        $oForm->aInputs['module_id']['attrs'] = array(
+            'onchange' => 'javascript:' . $sJsObject . '.selectModule(this);'
+        );
+        $oForm->aInputs['module_id']['values'] = array(
+            array('key' => '0', 'value' => _t('_Select_one'))
+        );
+
+        $aModules = $this->_oModule->_oDb->getModules();
+        foreach($aModules as $aModule)
+           $oForm->aInputs['module_id']['values'][] = array('key' => $aModule['id'], 'value' => $aModule['title']);
+
+        $oForm->aInputs['items']['content'] = $this->_oModule->_oTemplate->displayItems($sType);
+
+        $oForm->initChecker();
+        if($oForm->isSubmittedAndValid()) {
+            $sFormMethod = $oForm->aFormAttrs['method'];
+
+            $aItemIds = $oForm->getSubmittedValue('items', $sFormMethod);
+            if(empty($aItemIds) || !is_array($aItemIds))
+                return echoJson(array('msg' => $this->_sLangsPrefix . 'err_empty_items'));
+
+            $aItems = array();
+            $sPriceKey = $this->_oModule->_oConfig->getKey('KEY_ARRAY_PRICE_SINGLE');
+            foreach($aItemIds as $iItemId) {
+                $iItemId = (int)$iItemId;
+                $fItemPrice = (float)$oForm->getSubmittedValue('item-price-' . $iItemId, $sFormMethod);
+                $iItemQuantity = (int)$oForm->getSubmittedValue('item-quantity-' . $iItemId, $sFormMethod);
+
+                if($iItemQuantity <= 0)
+                    return echoJson(array('msg' => $this->_sLangsPrefix . 'err_wrong_quantity'));
+
+                $aItems[] = array(
+                    'id' => $iItemId, 
+                     $sPriceKey => $fItemPrice, 
+                    'quantity' => $iItemQuantity
+                );
+            }
+
+            $mixedResult = $this->_oModule->getObjectOrders()->addOrder(array(
+                'client_id' => $oForm->getCleanValue('client_id'),
+                'seller_id' => $oForm->getCleanValue('seller_id'),
+                'provider' => 'manual',
+                'type' => $sType,
+                'order' => $oForm->getCleanValue('order'),
+                'error_code' => 0,
+                'error_msg' => 'Manually processed',        		
+                'module_id' => $oForm->getCleanValue('module_id'),
+                'items' => $aItems
+            ));
+            if(is_array($mixedResult))
+                return echoJson($mixedResult);
+
+            $iPendingId = (int)$mixedResult;
+            if(!$this->_oModule->registerPayment($iPendingId))
+                return echoJson(array('msg' => _t($this->_sLangsPrefix . 'err_cannot_perform')));
+
+            $aOrders = $this->_oModule->_oDb->getOrderProcessed(array('type' => 'pending_id', 'pending_id' => $iPendingId, 'with_key' => 'id'));
+            return echoJson(array('grid' => $this->getCode(false), 'blink' => array_keys($aOrders)));
+        }
+
+        $sKey = 'order_' . $this->_sOrdersType . '_add';
+        $sId = $this->_oModule->_oConfig->getHtmlIds('processed', $sKey);
+        $sTitle = _t($this->_sLangsPrefix . 'popup_title_ods_' . $sKey);
+
+        $sContent = BxTemplStudioFunctions::getInstance()->popupBox($sId, $sTitle, $this->_oModule->_oTemplate->parseHtmlByName('order_processed_add.html', array(
+            'js_object' => $sJsObject,
+            'form_id' => $oForm->aFormAttrs['id'],
+            'form' => $oForm->getCode(true),
+            'object' => $this->_sObject,
+            'action' => $sAction
+        )));
+
+        echoJson(array('popup' => array('html' => $sContent, 'options' => array('closeOnOuterClick' => false))));
+    }
+
+    protected function _getActionCancel ($sType, $sKey, $a, $isSmall = false, $isDisabled = false, $aRow = array())
+    {
+        if(!empty($aRow['seller_id']) && $aRow['seller_id'] != bx_get_logged_profile_id())
+            return '';
+
+        return $this->_getActionDefault($sType, $sKey, $a, $isSmall, $isDisabled, $aRow);
+    }
+            
+            
+    protected function _getFilterClients()
+    {
+        $aIds = $this->_oModule->_oDb->getOrderProcessed(array('type' => 'clients', 'seller_id' => $this->_aQueryAppend['seller_id']));
+
+        $aValues = array();
+        foreach($aIds as $iId)
+            if(!empty($iId) && ($oClient = BxDolProfile::getInstanceMagic($iId)) !== false)
+                $aValues[] = array('key' => $iId, 'value' => $oClient->getDisplayName());
+
+        $this->_oModule->_oConfig->sortByColumn('value', $aValues);
+
+        return $this->_getFilterSelectAll('client', array(
+            'values' => array_merge(array(
+                array('key' => '', 'value' => _t('_bx_payment_txt_all_clients'))
+            ), $aValues)
+        ));
+    }
+
+    protected function _getFilterAuthors()
+    {
+        $aIds = $this->_oModule->_oDb->getOrderProcessed(array('type' => 'authors', 'seller_id' => $this->_aQueryAppend['seller_id']));
+
+        $aValues = array();
+        foreach($aIds as $iId)
+            if(!empty($iId) && ($oClient = BxDolProfile::getInstanceMagic($iId)) !== false)
+                $aValues[] = array('key' => $iId, 'value' => $oClient->getDisplayName());
+
+        $this->_oModule->_oConfig->sortByColumn('value', $aValues);
+
+        return $this->_getFilterSelectAll('author', array(
+            'values' => array_merge(array(
+                array('key' => '', 'value' => _t('_bx_payment_txt_all_authors'))
+            ), $aValues)
+        ));
+    }
+
+    protected function _getFilterModules()
+    {
+        $aModules = $this->_oModule->_oDb->getModules();
+        
+        $aValues = array();
+        foreach($aModules as $aModule) {
+            $sLangKey = '_' . $aModule['name'];
+            $sLangValue = _t($sLangKey);
+
+            $aValues[] = array('key' => $aModule['id'], 'value' => $sLangKey != $sLangValue ? $sLangValue : $aModule['title']);
+        }
+
+        $this->_oModule->_oConfig->sortByColumn('value', $aValues);
+
+        return $this->_getFilterSelectAll('module', array(
+            'js_onchange' => 'onChangeFilterModule(this, ' . $this->_aQueryAppend['seller_id'] . ')',
+            'values' => array_merge(array(
+                array('key' => '', 'value' => _t('_bx_payment_txt_all_modules'))
+            ), $aValues)
+        ));
+    }
+
+    protected function _getFilterItems()
+    {
+        return $this->_getFilterSelectAll('item', array(
+            'attrs' => array('disabled' => 'disabled'),
+            'values' => array(
+                array('key' => '', 'value' => _t('_bx_payment_txt_all_items'))
+            )
+        ));
+    }
+
+    protected function _getFilterControls ()
+    {
+        parent::_getFilterControls();
+
+        $sResult = $this->_getFilterClients();
+        if($this->_bSingleSeller && $this->_aQueryAppend['seller_id'] == $this->_iSingleSeller)
+            $sResult .= $this->_getFilterAuthors();
+        $sResult .= $this->_getFilterModules() . $this->_getFilterItems() . $this->_getSearchInput();
+
+        return $sResult;
+    }
+
+    protected function _getDataSql($sFilter, $sOrderField, $sOrderDir, $iStart, $iPerPage)
+    {
+    	if(empty($this->_aQueryAppend['seller_id']))
+            return array();
+
+        $sParamsDivider = $this->_oModule->_oConfig->getDivider('DIVIDER_GRID_FILTERS');
+
+        $iClient = $iAuthor = $iModule = $iItem = 0;
+        if(strpos($sFilter, $sParamsDivider) !== false) {
+            $aFilters = explode($sParamsDivider, $sFilter);
+            if($this->_bSingleSeller && $this->_aQueryAppend['seller_id'] = $this->_iSingleSeller)
+                list($iClient, $iAuthor, $iModule, $iItem, $sFilter) = $aFilters;
+            else
+                list($iClient, $iModule, $iItem, $sFilter) = $aFilters;
+        }
+
+        $this->_aOptions['source'] .= $this->_oModule->_oDb->prepareAsString(" AND (`tt`.`seller_id`=? OR `tt`.`author_id`=?)", $this->_aQueryAppend['seller_id'], $this->_aQueryAppend['seller_id']);
+
+        $iClient = (int)$iClient;
+        if($iClient != 0)
+            $this->_aOptions['source'] .= $this->_oModule->_oDb->prepareAsString(" AND `tt`.`client_id`=?", $iClient);
+
+        $iAuthor = (int)$iAuthor;
+        if($iAuthor != 0)
+            $this->_aOptions['source'] .= $this->_oModule->_oDb->prepareAsString(" AND `tt`.`author_id`=?", $iAuthor);
+
+        $iModule = (int)$iModule;
+        if($iModule != 0)
+            $this->_aOptions['source'] .= $this->_oModule->_oDb->prepareAsString(" AND `tt`.`module_id`=?", $iModule);
+
+        $iItem = (int)$iItem;
+        if($iItem != 0)
+            $this->_aOptions['source'] .= $this->_oModule->_oDb->prepareAsString(" AND `tt`.`item_id`=?", $iItem);
+
+        return parent::_getDataSql($sFilter, $sOrderField, $sOrderDir, $iStart, $iPerPage);
+    }
+}
+
+/** @} */

+ 1608 - 0
modules/boonex/payment/updates/12.0.0_12.0.1/source/classes/BxPaymentModule.php

@@ -0,0 +1,1608 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Payment Payment
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+define('BX_PAYMENT_ORDERS_TYPE_PENDING', 'pending');
+define('BX_PAYMENT_ORDERS_TYPE_PROCESSED', 'processed');
+define('BX_PAYMENT_ORDERS_TYPE_SUBSCRIPTION', 'subscription');
+define('BX_PAYMENT_ORDERS_TYPE_HISTORY', 'history');
+
+define('BX_PAYMENT_RESULT_SUCCESS', 0);
+
+/*
+ * Subscriptions: statuses.
+ */
+define('BX_PAYMENT_SBS_STATUS_SCHEDULED', 'scheduled');
+define('BX_PAYMENT_SBS_STATUS_TRIAL', 'trial');
+define('BX_PAYMENT_SBS_STATUS_ACTIVE', 'active');
+define('BX_PAYMENT_SBS_STATUS_UNPAID', 'unpaid');
+define('BX_PAYMENT_SBS_STATUS_PAUSED', 'paused');
+define('BX_PAYMENT_SBS_STATUS_CANCELED', 'canceled');
+define('BX_PAYMENT_SBS_STATUS_UNKNOWN', 'unknown');
+
+/*
+ * Subscriptions: period units.
+ */
+define('BX_PAYMENT_SBS_PU_YEAR', 'year');
+define('BX_PAYMENT_SBS_PU_MONTH', 'month');
+define('BX_PAYMENT_SBS_PU_WEEK', 'week');
+define('BX_PAYMENT_SBS_PU_DAY', 'day');
+define('BX_PAYMENT_SBS_PU_HOUR', 'hour');
+define('BX_PAYMENT_SBS_PU_MINUTE', 'minute');
+
+/*
+ * Invoice: statuses.
+ */
+define('BX_PAYMENT_INV_STATUS_UNPAID', 'unpaid');
+define('BX_PAYMENT_INV_STATUS_PAID', 'paid');
+define('BX_PAYMENT_INV_STATUS_OVERDUE', 'overdue');
+
+
+/**
+ * Payment module by BoonEx
+ *
+ * This module is needed to work with payment providers and organize the process
+ * of some item purchasing. Shopping Cart and Orders Manager are included.
+ *
+ * Integration notes:
+ * To integrate your module with this one, you need:
+ * 1. Get 'Add To Cart' button using serviceGetAddToCartLink service.
+ * 2. Add info about your module in the 'bx_pmt_modules' table.
+ * 3. Realize the following service methods in your Module class.
+ *   a. serviceGetItems($iSellerId) - Is used in Orders Administration to get all products of the requested seller(vendor).
+ *   b. serviceGetCartItem($iClientId, $iItemId) - Is used in Shopping Cart to get one product by specified id.
+ *   c. serviceRegisterCartItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrderId) - Register purchased product.
+ *   d. serviceUnregisterCartItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrderId) - Unregister the product purchased earlier.
+ * @see You may see an example of integration in Membership module.
+ *
+ *
+ * Profile's Wall:
+ * no spy events
+ *
+ *
+ *
+ * Spy:
+ * no spy events
+ *
+ *
+ *
+ * Memberships/ACL:
+ * Doesn't depend on user's membership.
+ *
+ *
+ *
+ * Service methods:
+ *
+ * Is used to get "Add to cart" link for some item(s) in your module.
+ * @see BxPmtModule::serviceGetAddToCartLink
+ * BxDolService::call('payment', 'get_add_to_cart_link', array($iSellerId, $mixedModuleId, $iItemId, $iItemCount));
+ *
+ * Check transaction(s) in database which satisty all conditions.
+ * @see BxPmtModule::serviceGetOrdersInfo
+ * BxDolService::call('payment', 'get_orders_info', array($aConditions), 'Orders');
+ *
+ * Get total count of items in Shopping Cart.
+ * @see BxPmtModule::serviceGetCartItemsCount
+ * BxDolService::call('payment', 'get_cart_items_count', array($iUserId, $iOldCount));
+ * @note is needed for internal usage(integration with member tool bar).
+ *
+ * Get Shopping cart content.
+ * @see BxPmtModule::serviceGetCartItems
+ * BxDolService::call('payment', 'get_cart_items');
+ * @note is needed for internal usage(integration with member tool bar).
+ *
+ *
+ * Alerts:
+ * no alerts available
+ *
+ */
+class BxPaymentModule extends BxBaseModPaymentModule
+{
+    protected $_iUserId;
+
+    protected $_aOrderTypes;
+
+    function __construct($aModule)
+    {
+        parent::__construct($aModule);
+
+        $this->_iUserId = $this->getProfileId();
+
+        $this->_aOrderTypes = array(
+            BX_PAYMENT_ORDERS_TYPE_PENDING, 
+            BX_PAYMENT_ORDERS_TYPE_PROCESSED, 
+            BX_PAYMENT_ORDERS_TYPE_SUBSCRIPTION, 
+            BX_PAYMENT_ORDERS_TYPE_HISTORY
+        );
+    }
+
+    /**
+     * Manage Orders Methods
+     */
+    public function actionGetClients()
+    {
+        $sTerm = bx_get('term');
+
+        $aResult = BxDolService::call('system', 'profiles_search', array($sTerm), 'TemplServiceProfiles');
+
+        echoJson($aResult);
+    }
+
+    public function actionGetItems($sType, $iModuleId)
+    {
+    	$iSellerId = $this->getProfileId();
+        $aItems = $this->callGetCartItems((int)$iModuleId, array($iSellerId));
+
+        echoJson(array(
+            'code' => 0, 
+            'eval' => $this->_oConfig->getJsObject('processed') . '.onSelectModule(oData);', 
+            'data' => $this->_oTemplate->displayItems($sType, $aItems)
+        ));
+    }
+
+    public function actionGetFilterValuesItem($iSellerId, $iModuleId)
+    {
+        $sItems = '<option value="">' . _t('_bx_payment_txt_all_items') . '</option>';
+
+        if(empty($iSellerId) || empty($iModuleId))
+            return echoJson(array('code' => 1, 'content' => $sItems));
+
+        $aItems = $this->callGetCartItems((int)$iModuleId, array($iSellerId));
+
+        $this->_oConfig->sortByColumn('title', $aItems);
+
+        foreach($aItems as $aItem)
+            $sItems .= '<option value="' . $aItem['id'] . '">' . $aItem['title'] . '</option>';
+
+        echoJson(array('code' => 0, 'content' => $sItems));
+    }
+
+    public function serviceGetSafeServices()
+    {
+        $a = parent::serviceGetSafeServices();
+        return array_merge($a, array (
+            'GetBlockJoin' => 'BxPaymentJoin',
+            'GetBlockCarts' => 'BxPaymentCart',
+            'GetBlockCart' => 'BxPaymentCart',
+            'GetBlockCartHistory' => 'BxPaymentCart',
+            'GetBlockListMy' => 'BxPaymentSubscriptions',
+            'GetBlockHistory' => 'BxPaymentSubscriptions',
+        ));
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_payment Payment
+     * @subsection bx_payment-purchase_processing Purchase Processing
+     * @subsubsection bx_payment-get_modules_with_payments get_modules_with_payments
+     * 
+     * @code bx_srv('bx_payment', 'get_modules_with_payments', []); @endcode
+     * 
+     * Get modules with payments functionality
+     *
+     * @return array with modules names
+     * 
+     * @see BxPaymentModule::serviceGetModulesWithPayments
+     */
+    /** 
+     * @ref bx_payment-get_modules_with_payments "get_modules_with_payments"
+     */
+    public function serviceGetModulesWithPayments()
+    {
+        return $this->_oDb->getModulesWithPayments();
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_payment Payment
+     * @subsection bx_payment-purchase_processing Purchase Processing
+     * @subsubsection bx_payment-is_credits_only is_credits_only
+     * 
+     * @code bx_srv('bx_payment', 'is_credits_only'); @endcode
+     * 
+     * Check whether the 'Credits Only' mode is enabled or not.
+     *
+     * @return boolean value determining the result of checking.
+     * 
+     * @see BxPaymentModule::serviceIsCreditsOnly
+     */
+    /** 
+     * @ref bx_payment-is_credits_only "is_credits_only"
+     */
+    public function serviceIsCreditsOnly()
+    {
+        return $this->_oConfig->isCreditsOnly();
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_payment Payment
+     * @subsection bx_payment-purchase_processing Purchase Processing
+     * @subsubsection bx_payment-is_accepting_payments is_accepting_payments
+     * 
+     * @code bx_srv('bx_payment', 'is_accepting_payments', [...]); @endcode
+     * 
+     * Check whether the specified vendor has a configured payment provider or not.
+     *
+     * @param $iVendorId integer value with vendor ID.
+     * @param $sPaymentType (optional) string value with payment type. If specified then the vendor will be checked for having the payment provider of the requested type.
+     * @return boolean value determining the result of checking.
+     * 
+     * @see BxPaymentModule::serviceIsAcceptingPayments
+     */
+    /** 
+     * @ref bx_payment-is_accepting_payments "is_accepting_payments"
+     */
+    public function serviceIsAcceptingPayments($iVendorId, $sPaymentType = '')
+    {
+    	$bResult = false;
+
+    	switch($sPaymentType) {
+            case BX_PAYMENT_TYPE_SINGLE:
+                $aProvidersCart = $this->_oDb->getVendorInfoProvidersSingle($iVendorId);
+                $bResult = !empty($aProvidersCart);
+                break;
+
+            case BX_PAYMENT_TYPE_RECURRING:
+                $aProvidersSubscription = $this->_oDb->getVendorInfoProvidersRecurring($iVendorId);
+                $bResult = !empty($aProvidersSubscription);
+                break;
+
+            default:
+                $aProviders = $this->_oDb->getVendorInfoProviders($iVendorId);
+                $bResult = !empty($aProviders);
+    	}
+
+        return $bResult;
+    }
+
+    /** 
+     * @deprecated since version 11.0.0
+     * 
+     * @see BxPaymentModule::serviceIsProviderOptions
+     */
+    public function serviceIsPaymentProvider($iVendorId, $sVendorProvider, $sPaymentType = '')
+    {
+    	return $this->serviceIsProviderOptions($iVendorId, $sVendorProvider, $sPaymentType);
+    }
+
+    /** 
+     * @deprecated since version 11.0.0
+     * 
+     * @see BxPaymentModule::serviceGetProviderOptions
+     */
+    public function serviceGetPaymentProvider($iVendorId, $sVendorProvider, $sPaymentType = '')
+    {
+    	return $this->serviceGetProviderOptions($iVendorId, $sVendorProvider, $sPaymentType);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_payment Payment
+     * @subsection bx_payment-purchase_processing Purchase Processing
+     * @subsubsection bx_payment-is_provider_options is_provider_options
+     * 
+     * @code bx_srv('bx_payment', 'is_provider_options', [...]); @endcode
+     * 
+     * Check whether the specified vendor has configured the specified payment provider or not.
+     *
+     * @param $iVendorId integer value with vendor ID.
+     * @param $sVendorProvider string value with payment provider name.
+     * @param $sPaymentType (optional) string value with payment type. If specified then the vendor will be checked for having the payment provider of the requested type.
+     * @return boolean value determining the result of checking.
+     * 
+     * @see BxPaymentModule::serviceIsProviderOptions
+     */
+    /** 
+     * @ref bx_payment-is_provider_options "is_provider_options"
+     */
+    public function serviceIsProviderOptions($iVendorId, $sVendorProvider, $sPaymentType = '')
+    {
+    	$aProvider = $this->serviceGetProviderOptions($iVendorId, $sVendorProvider, $sPaymentType);
+    	return $aProvider !== false;
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_payment Payment
+     * @subsection bx_payment-purchase_processing Purchase Processing
+     * @subsubsection bx_payment-get_provider_options get_provider_options
+     * 
+     * @code bx_srv('bx_payment', 'get_provider_options', [...]); @endcode
+     * 
+     * Get configuration settings for the payment provider entered by the specified vendor.
+     *
+     * @param $iVendorId integer value with vendor ID.
+     * @param $sVendorProvider string value with payment provider name.
+     * @param $sPaymentType (optional) string value with payment type. If specified then the vendor will be checked for having the payment provider of the requested type.
+     * @return an array with special format describing the payment provider or false value if something is wrong.
+     * 
+     * @see BxPaymentModule::serviceGetProviderOptions
+     */
+    /** 
+     * @ref bx_payment-get_provider_options "get_provider_options"
+     */
+    public function serviceGetProviderOptions($iVendorId, $sVendorProvider, $sPaymentType = '')
+    {
+    	$aProviders = array();
+    	switch($sPaymentType) {
+            case BX_PAYMENT_TYPE_SINGLE:
+                $aProviders = $this->_oDb->getVendorInfoProvidersSingle($iVendorId);
+                break;
+
+            case BX_PAYMENT_TYPE_RECURRING:
+                $aProviders = $this->_oDb->getVendorInfoProvidersRecurring($iVendorId);
+                break;
+
+            default:
+                $aProviders = $this->_oDb->getVendorInfoProviders($iVendorId);
+    	}
+
+    	return !empty($aProviders) && !empty($aProviders[$sVendorProvider]) && is_array(($aProviders[$sVendorProvider])) ? $aProviders[$sVendorProvider] : false;
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_payment Payment
+     * @subsection bx_payment-other Other
+     * @subsubsection bx_payment-get_options_default_currency_code get_options_default_currency_code
+     * 
+     * @code bx_srv('bx_payment', 'get_options_default_currency_code', [...]); @endcode
+     * 
+     * Get an array with available currencies. Is used in forms.
+     *
+     * @return an array with available currencies represented as key => value pairs.
+     * 
+     * @see BxPaymentModule::serviceGetOptionsDefaultCurrencyCode
+     */
+    /** 
+     * @ref bx_payment-get_options_default_currency_code "get_options_default_currency_code"
+     */
+    public function serviceGetOptionsDefaultCurrencyCode()
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $aCurrencies = BxDolForm::getDataItems($CNF['OBJECT_FORM_PRELISTS_CURRENCIES']);
+
+        $aResult = array();
+        foreach($aCurrencies as $sKey => $sValue)
+            $aResult[] = array(
+                'key' => $sKey,
+                'value' => $sValue
+            );
+
+        return $aResult;
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_payment Payment
+     * @subsection bx_payment-other Other
+     * @subsubsection bx_payment-get_options_site_admin get_options_site_admin
+     * 
+     * @code bx_srv('bx_payment', 'get_options_site_admin', [...]); @endcode
+     * 
+     * Get an array with profiles which can be used as 'Site Admin (Owner)'. 'Site Admin' is a person who will be displayed to buyers when something is selling on behalf of the site.
+     *
+     * @return an array with profiles represented as key => value pairs.
+     * 
+     * @see BxPaymentModule::serviceGetOptionsSiteAdmin
+     */
+    /** 
+     * @ref bx_payment-get_options_site_admin "get_options_site_admin"
+     */
+    public function serviceGetOptionsSiteAdmin()
+    {
+        $aResult = array(
+            array('key' => '', 'value' => _t('_Select_one'))
+        );
+
+        $aIds = $this->_oDb->getAdminsIds();
+        foreach($aIds as $iId) {
+            $aUser = $this->getProfileInfo($iId);
+
+            $aResult[] = array(
+                'key' => $iId,
+                'value' => $aUser['name']
+            );
+        }
+
+        return $aResult;
+    }
+
+    public function serviceGetMenuAddonManageTools()
+    {
+        return array(
+            'counter1_value' => (int)$this->_oDb->getInvoices(array('type' => 'status', 'status' => BX_PAYMENT_INV_STATUS_PAID, 'count' => true)), 
+            'counter1_caption' => _t('_bx_payment_menu_item_title_admt_addon_counter1_caption'), 
+            'counter2_value' => (int)$this->_oDb->getInvoices(array('type' => 'status', 'status' => BX_PAYMENT_INV_STATUS_OVERDUE, 'count' => true)), 
+            'counter2_caption' => _t('_bx_payment_menu_item_title_admt_addon_counter2_caption'), 
+            'counter3_value' => (int)$this->_oDb->getInvoices(array('type' => 'all_count'))
+        );
+    }
+
+    /**
+     * Cart Processing Methods
+     */
+    public function actionAddToCart($iSellerId, $iModuleId, $iItemId, $iItemCount, $sCustom = '')
+    {
+        if(empty($sCustom) && bx_get('custom') !== false)
+            $sCustom = bx_process_input(bx_get('custom'));
+
+        $aCustom = array();
+        if(!empty($sCustom)) {
+            $aCustom = unserialize(base64_decode($sCustom));
+            if(empty($aCustom) || !is_array($aCustom))
+                $aCustom = array();
+        }
+
+        $aResult = $this->getObjectCart()->serviceAddToCart($iSellerId, $iModuleId, $iItemId, $iItemCount, $aCustom);
+		echoJson($aResult);
+    }
+
+    /**
+     * Isn't used yet.
+     */
+    public function actionDeleteFromCart($iSellerId, $iModuleId, $iItemId)
+    {
+        echoJson($this->getObjectCart()->serviceDeleteFromCart($iSellerId, $iModuleId, $iItemId));
+    }
+
+    /**
+     * Isn't used yet.
+     */
+    public function actionEmptyCart($iSellerId)
+    {
+        echoJson($this->getObjectCart()->serviceDeleteFromCart($iSellerId));
+    }
+
+    public function actionSubscribe()
+    {
+    	$iSellerId = bx_process_input(bx_get('seller_id'), BX_DATA_INT);
+    	$sSellerProvider = bx_process_input(bx_get('seller_provider'));
+    	$iModuleId = bx_process_input(bx_get('module_id'), BX_DATA_INT);
+    	$iItemId = bx_process_input(bx_get('item_id'), BX_DATA_INT);
+    	$iItemCount = bx_process_input(bx_get('item_count'), BX_DATA_INT);
+    	if(empty($iItemCount))
+    		$iItemCount = 1;
+
+        $sRedirect = bx_process_input(bx_get('redirect'));
+        $sCustom = bx_process_input(bx_get('custom'));
+
+        $aCustom = array();
+        if(!empty($sCustom)) {
+            $aCustom = unserialize(base64_decode($sCustom));
+            if(empty($aCustom) || !is_array($aCustom))
+                $aCustom = array();
+        }
+
+        $aResult = $this->getObjectSubscriptions()->serviceSubscribe($iSellerId, $sSellerProvider, $iModuleId, $iItemId, $iItemCount, $sRedirect, $aCustom);
+        $bRedirect = !empty($aResult['redirect']);
+
+        if(!empty($aResult['popup'])) {
+            $sContent = '';
+            $sContent .= $this->_oTemplate->displayCartJs(BX_PAYMENT_TYPE_RECURRING, $iSellerId);
+            $sContent .= !empty($aResult['popup']['html']) ? $aResult['popup']['html'] : $aResult['popup'];
+
+			return $this->_oTemplate->displayPageCodeResponse($sContent, false, true);
+        }
+
+		if(!empty($aResult['code']))
+			return $this->_oTemplate->displayPageCodeError($aResult['message']);
+
+		if(!empty($aResult['message']) && !$bRedirect)
+			return $this->_oTemplate->displayPageCodeResponse($aResult['message']);
+
+        if($bRedirect) {
+    		header('Location: ' . $aResult['redirect']);
+            exit;
+        }
+    }
+
+    public function actionSubscribeJson()
+    {
+    	$iSellerId = bx_process_input(bx_get('seller_id'), BX_DATA_INT);
+    	$sSellerProvider = bx_process_input(bx_get('seller_provider'));
+    	$iModuleId = bx_process_input(bx_get('module_id'), BX_DATA_INT);
+    	$iItemId = bx_process_input(bx_get('item_id'), BX_DATA_INT);
+
+    	$iItemCount = bx_process_input(bx_get('item_count'), BX_DATA_INT);
+    	if(empty($iItemCount))
+            $iItemCount = 1;
+
+        $sItemAddons = '';
+        if(bx_get('item_addons') !== false) {
+            $sItemAddons = bx_process_input(bx_get('item_addons'));
+            if(is_array($sItemAddons))
+                $sItemAddons = $this->_oConfig->a2s($sItemAddons);
+        }
+
+        $sRedirect = bx_process_input(bx_get('redirect'));
+        $sCustom = bx_process_input(bx_get('custom'));
+
+        $aCustom = array();
+        if(!empty($sCustom)) {
+            $aCustom = unserialize(base64_decode($sCustom));
+            if(empty($aCustom) || !is_array($aCustom))
+                $aCustom = array();
+        }
+
+        echoJson($this->getObjectSubscriptions()->serviceSubscribeWithAddons($iSellerId, $sSellerProvider, $iModuleId, $iItemId, $iItemCount, $sItemAddons, $sRedirect, $aCustom));
+    }
+
+    public function actionSubscriptionGetDetails($iId)
+    {
+        echoJson($this->_oTemplate->displaySubscriptionGetDetails($iId));
+    }
+
+    public function actionSubscriptionChangeDetails($iId)
+    {
+        echoJson($this->_oTemplate->displaySubscriptionChangeDetails($iId));
+    }
+
+    public function actionSubscriptionGetBilling($iId)
+    {
+        echoJson($this->_oTemplate->displaySubscriptionGetBilling($iId));
+    }
+
+    public function actionSubscriptionChangeBilling($iId)
+    {
+        echoJson($this->_oTemplate->displaySubscriptionChangeBilling($iId));
+    }
+
+    public function actionSubscriptionCancelation($iId)
+    {
+        $aResult = array('code' => 1, 'message' => _t('_bx_payment_err_cannot_perform'));
+
+        $aPending = $this->_oDb->getOrderPending(array('type' => 'id', 'id' => $iId));
+        if(empty($aPending) || !is_array($aPending))
+            return echoJson($aResult);
+
+        $aSubscription = $this->_oDb->getSubscription(array('type' => 'pending_id', 'pending_id' => $iId));
+        if(empty($aSubscription) || !is_array($aSubscription))
+            return echoJson($aResult);
+
+        $oRecipient = BxDolProfile::getInstance((int)$aPending['seller_id']);
+        if(!$oRecipient)
+            return echoJson($aResult);
+
+        $mixedResult = $this->isAllowedManage($aPending);
+        if($mixedResult !== true)
+            return echoJson(array('code' => 2, 'message' => $mixedResult));
+
+        $aTemplate = BxDolEmailTemplates::getInstance()->parseTemplate($this->_oConfig->getPrefix('general') . 'cancelation_request', array(
+            'sibscription_id' => $aSubscription['subscription_id'],
+            'sibscription_customer' => $aSubscription['customer_id'],
+            'sibscription_date' => bx_time_js($aSubscription['date'], BX_FORMAT_DATE, true)
+        ), 0, (int)$aPending['client_id']);
+
+        $sEmail = '';
+        $oProvider = $this->getObjectProvider($aPending['provider'], $aPending['seller_id']);
+        if($oProvider !== false && $oProvider->isActive())
+            $sEmail = $oProvider->getOption('cancellation_email');
+
+        if(empty($sEmail))
+            $sEmail = $oRecipient->getAccountObject()->getEmail();
+
+        if(!sendMail($sEmail, $aTemplate['Subject'], $aTemplate['Body'], 0, array(), BX_EMAIL_SYSTEM))
+            return echoJson($aResult);
+
+        echoJson(array('code' => 0, 'message' => _t('_bx_payment_msg_cancelation_request_sent')));
+    }
+
+    public function actionSubscriptionCancel($iId, $mixedGridObject = false)
+    {
+        $aResult = array('code' => 1, 'message' => _t('_bx_payment_err_cannot_perform'));
+
+        $aPending = $this->_oDb->getOrderPending(array('type' => 'id', 'id' => $iId));
+        if(empty($aPending) || !is_array($aPending))
+            return echoJson($aResult);
+
+        $mixedResult = $this->isAllowedManage($aPending);
+        if($mixedResult !== true)
+            return echoJson(array('code' => 2, 'message' => $mixedResult));
+
+        if(!$this->getObjectSubscriptions()->cancel($iId))
+            return echoJson($aResult);
+
+        if(empty($mixedGridObject) && bx_get('grid') !== false)
+            $mixedGridObject = bx_process_input(bx_get('grid'));
+
+        if(!empty($mixedGridObject) && $aPending['client_id'] == $this->getProfileId()) {
+            $oGrid = BxDolGrid::getObjectInstance($mixedGridObject, $this->_oTemplate);
+            $oGrid->addQueryParam('client_id', $aPending['client_id']);
+
+            return echoJson(array('object' => $mixedGridObject, 'grid' => $oGrid->getCode(false), 'blink' => array($iId)));
+        }
+        else
+            return echoJson(array('code' => 0, 'message' => _t('_bx_payment_msg_successfully_performed')));
+    }
+
+    /**
+     * Payment Processing Methods
+     */
+    public function actionInitializeCheckout($sType)
+    {
+    	if(!$this->isLogged())
+            return $this->_oTemplate->displayPageCodeError($this->_sLangsPrefix . 'err_required_login');
+
+        if(bx_get('seller_id') !== false && bx_get('provider') !== false && bx_get('items') !== false) {
+            $iSellerId = bx_process_input(bx_get('seller_id'), BX_DATA_INT);
+            $sProvider = bx_process_input(bx_get('provider'));
+            $aItems = bx_process_input(bx_get('items'));
+
+            $mixedResult = $this->serviceInitializeCheckout(BX_PAYMENT_TYPE_SINGLE, $iSellerId, $sProvider, $aItems);
+            if($mixedResult !== true)
+                return $this->_oTemplate->displayPageCodeError($mixedResult);
+        }
+
+        header('Location: ' . $this->_oConfig->getUrl('URL_CART'));
+        exit;
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_payment Payment
+     * @subsection bx_payment-purchase_processing Purchase Processing
+     * @subsubsection bx_payment-initialize_checkout initialize_checkout
+     * 
+     * @code bx_srv('bx_payment', 'initialize_checkout', [...]); @endcode
+     * 
+     * Initialize the checkout process.
+     * 
+     * @param $sType string value with payment type (single or recurring). 
+     * @param $iSellerId integer value with seller ID. 
+     * @param $sProvider string value with payment provider name. 
+     * @param $aItems (optional) an array with items to be purchased. 
+     * @param $sRedirect (optional) string value with redirect URL if it's needed.
+     * @param $aCustom (optional) array with custom data to attach to a payment.
+     * @return the result depends on the payment provider which is used for processing or represented as string value with error message if something is wrong.
+     * 
+     * @see BxPaymentModule::serviceInitializeCheckout
+     */
+    /** 
+     * @ref bx_payment-initialize_checkout "initialize_checkout"
+     */
+    public function serviceInitializeCheckout($sType, $iSellerId, $sProvider, $aItems = array(), $sRedirect = '', $aCustoms = array())
+    {
+        $bTypeSingle = $sType == BX_PAYMENT_TYPE_SINGLE;
+        $bTypeRecurring = $sType == BX_PAYMENT_TYPE_RECURRING;
+
+        if(!is_array($aItems))
+            $aItems = array($aItems);
+
+        $iSellerId = (int)$iSellerId;
+        if($iSellerId == BX_PAYMENT_EMPTY_ID)
+            return $this->_sLangsPrefix . 'err_unknown_vendor';
+
+        $oProvider = $this->getObjectProvider($sProvider, $iSellerId);
+        if($oProvider === false || !$oProvider->isActive())
+            return $this->_sLangsPrefix . 'err_incorrect_provider';
+
+        $aInfo = $this->getObjectCart()->getInfo($sType, $this->_iUserId, $iSellerId, $aItems);
+        if(empty($aInfo) || $aInfo['vendor_id'] == BX_PAYMENT_EMPTY_ID || empty($aInfo['items']))
+            return $this->_sLangsPrefix . 'err_empty_order';
+
+        /*
+         * Process FREE (price = 0) items for LOGGED IN members
+         * WITHOUT processing via payment provider.
+         * Note. This section isn't used for now!
+         */
+        $bProcessedFree = false;
+        $sKeyPriceSingle = $this->_oConfig->getKey('KEY_ARRAY_PRICE_SINGLE');
+        $sKeyPriceRecurring = $this->_oConfig->getKey('KEY_ARRAY_PRICE_RECURRING');
+        foreach($aInfo['items'] as $iIndex => $aItem) {
+            if((int)$aInfo['client_id'] == 0)
+                continue;
+
+            //--- For Single time payments.
+            if($bTypeSingle && (float)$aItem[$sKeyPriceSingle] == 0) {
+                $aCart = $this->_oDb->getCartContent($aInfo['client_id']);
+                $aCartCustoms = !empty($aCart['customs']) ? unserialize($aCart['customs']) : array();
+
+                $aCartItem = array($aInfo['vendor_id'], $aItem['module_id'], $aItem['id'], $aItem['quantity']);
+                $aCartItemCustom = $this->_oConfig->pullCustom($aCartItem, $aCartCustoms);
+
+                $aItemInfo = $this->callRegisterCartItem((int)$aItem['module_id'], array($aInfo['client_id'], $aInfo['vendor_id'], $aItem['id'], $aItem['quantity'], $this->_oConfig->getLicense(), $aCartItemCustom));
+                if(!empty($aItemInfo) && is_array($aItemInfo)) {
+                    if(!empty($aItemInfo['addons']) && is_array($aItemInfo['addons']))
+                        foreach($aItemInfo['addons'] as $sAddon => $aAddon)
+                            $this->callRegisterCartItem((int)$aAddon['module_id'], array($aInfo['client_id'], $aInfo['vendor_id'], $aAddon['id'], $aAddon['quantity'], $this->_oConfig->getLicense(), $aCartItemCustom));
+
+                    $bProcessedFree = true;
+                }
+
+                $aInfo['items_count'] -= 1;
+                unset($aInfo['items'][$iIndex]);
+
+                $aCart['items'] = trim(preg_replace("'" . $this->_oConfig->descriptorA2S($aCartItem) . ":?'", "", $aCart['items']), ":");
+                $this->_oDb->setCartItems($aInfo['client_id'], $aCart['items'], $aCartCustoms);
+            }
+
+            //--- For Recurring payments.
+            if($bTypeRecurring && (float)$aItem[$sKeyPriceRecurring] == 0) {
+                //TODO: Process FREE subscription here, if such situation will be possible.
+            }
+        }
+
+        if(empty($aInfo['items']))
+            return $this->_sLangsPrefix . ($bProcessedFree ? 'msg_successfully_processed_free' : 'err_empty_order');
+
+        if($bTypeSingle && (empty($aCustoms) || !is_array($aCustoms))) {
+            $aCart = $this->_oDb->getCartContent($aInfo['client_id']);
+            $aCartCustoms = !empty($aCart['customs']) ? unserialize($aCart['customs']) : array();
+
+            $aCustoms = array();
+            foreach($aInfo['items'] as $aItem) {
+                $sCartItem = $this->_oConfig->descriptorA2S(array($aItem['author_id'], $aItem['module_id'], $aItem['id']));
+                $aCartItemCustom = $this->_oConfig->getCustom($sCartItem, $aCartCustoms);
+                $this->_oConfig->putCustom($sCartItem, $aCartItemCustom, $aCustoms);
+            }
+        }
+
+        bx_alert($this->getName(), 'before_pending', 0, bx_get_logged_profile_id(), array(
+            'client_id' => $this->_iUserId,
+            'type' => &$sType,
+            'provider' => &$sProvider,
+            'cart_info' => &$aInfo,
+            'custom' => &$aCustoms,
+        ));
+
+        $iPendingId = $this->_oDb->insertOrderPending($this->_iUserId, $sType, $sProvider, $aInfo, $aCustoms);
+        if(empty($iPendingId))
+            return $this->_sLangsPrefix . 'err_access_db';
+
+        /*
+         * Perform Join WITHOUT processing via payment provider
+         * if a client ISN'T logged in and has only ONE FREE item in the card.
+         * Note. This section isn't used for now because only a member can purchase!
+         */
+        if((int)$aInfo['client_id'] == 0 && (int)$aInfo['items_count'] == 1) {
+            reset($aInfo['items']);
+            $aItem = current($aInfo['items']);
+
+            if(!empty($aItem) && $this->_oConfig->getPrice($sType, $aItem)) {
+                $this->_oDb->updateOrderPending($iPendingId, array(
+                    'order' => $this->_oConfig->getLicense(),
+                    'error_code' => '1',
+                    'error_msg' => ''
+                ));
+
+                $this->getObjectJoin()->performJoin($iPendingId);
+            }
+        }
+
+        return $oProvider->initializeCheckout($iPendingId, $aInfo, $sRedirect);
+    }
+
+    public function actionFinalizeCheckout($sProvider, $mixedVendorId = "")
+    {
+        $aData = &$_REQUEST;
+
+        $oProvider = $this->getObjectProvider($sProvider, $mixedVendorId);
+        if($oProvider === false || !$oProvider->isActive())
+            return $this->_oTemplate->displayPageCodeError($this->_sLangsPrefix . 'err_incorrect_provider');
+
+        $aResult = $oProvider->finalizeCheckout($aData);
+        if((int)$aResult['code'] != BX_PAYMENT_RESULT_SUCCESS) 
+            return $this->_oTemplate->displayPageCodeError($aResult['message']);
+
+        $aPending = $this->_oDb->getOrderPending(array('type' => 'id', 'id' => (int)$aResult['pending_id']));
+        $bTypeRecurring = $aPending['type'] == BX_PAYMENT_TYPE_RECURRING;
+        if($bTypeRecurring) {
+            $sStatus = BX_PAYMENT_SBS_STATUS_UNPAID;
+            if(isset($aResult['paid']) && $aResult['paid'])
+                $sStatus = BX_PAYMENT_SBS_STATUS_ACTIVE;
+            else if(isset($aResult['trial']) && $aResult['trial'])
+                $sStatus = BX_PAYMENT_SBS_STATUS_TRIAL;
+
+            $aSubscription = array(
+                'customer_id' => $aResult['customer_id'], 
+                'subscription_id' => $aResult['subscription_id'],
+                'status' => $sStatus
+            );
+
+            if(!$this->getObjectSubscriptions()->register($aPending, $aSubscription))
+                return $this->_oTemplate->displayPageCodeError($this->_sLangsPrefix . 'err_already_registered');
+        }
+
+        $this->onPaymentRegisterBefore($aPending);
+
+        //--- Check "Pay Before Join" situation
+        if((int)$aPending['client_id'] == 0)
+            $this->getObjectJoin()->performJoin((int)$aPending['id'], isset($aResult['client_name']) ? $aResult['client_name'] : '', isset($aResult['client_email']) ? $aResult['client_email'] : '');
+
+        //--- Register payment for purchased items in associated modules 
+        if(!empty($aResult['paid']) || ($bTypeRecurring && !empty($aResult['trial'])))
+            $this->registerPayment($aPending);
+
+        bx_alert($this->getName(), 'finalize_checkout', 0, bx_get_logged_profile_id(), array(
+            'pending' => $aPending,
+            'transactions' => $this->_oDb->getOrderProcessed(array('type' => 'pending_id', 'pending_id' => (int)$aPending['id'])),
+            'provider' => $oProvider,
+            'message' => &$aResult['message'],
+            'result' => &$aResult,
+        ));
+
+        if($oProvider->needRedirect()) {
+            header('Location: ' . $oProvider->getReturnUrl());
+            exit;
+        }
+
+        if(!empty($aResult['redirect'])) {
+            header('Location: ' . base64_decode(urldecode($aResult['redirect'])));
+            exit;
+        }
+
+        $this->_oTemplate->displayPageCodeResponse($aResult['message']);
+    }
+
+    public function actionFinalizedCheckout($sProvider, $mixedVendorId = "")
+    {
+        $oProvider = $this->getObjectProvider($sProvider, $mixedVendorId);
+        if($oProvider === false || !$oProvider->isActive())
+            return $this->_oTemplate->displayPageCodeError($this->_sLangsPrefix . 'err_incorrect_provider');
+
+        $aResult = $oProvider->finalizedCheckout();
+        $this->_oTemplate->displayPageCodeResponse($aResult['message']);
+    }
+
+    public function actionNotify($sProvider, $mixedVendorId = "")
+    {
+    	$oProvider = $this->getObjectProvider($sProvider, $mixedVendorId);
+        if($oProvider === false || !$oProvider->isActive())
+            return $this->_oTemplate->displayPageCodeError($this->_sLangsPrefix . 'err_incorrect_provider');
+
+        $oProvider->notify();
+    }
+    
+    /**
+     * The method is needed to pass direct action calls to necessary Payment Provider.
+     */
+    public function actionCall($sProvider, $sAction, $mixedVendorId = BX_PAYMENT_EMPTY_ID)
+    {
+        $oProvider = $this->getObjectProvider($sProvider, $mixedVendorId);
+        if($oProvider === false)
+            BxDolRequest::methodNotFound($sAction, $this->getName());
+
+         $sMethod = 'action' . bx_gen_method_name($sAction);
+         if(!method_exists($oProvider, $sMethod))
+             BxDolRequest::methodNotFound($sAction, $this->getName());
+
+        return call_user_func_array(array($oProvider, $sMethod), array_slice(func_get_args(), 2));
+    }
+
+    public function onProfileJoin($iProfileId)
+    {
+    	$this->getObjectJoin()->onProfileJoin($iProfileId);
+    }
+
+    public function onProfileDelete($iProfileId)
+    {
+        $this->_oDb->onProfileDelete($iProfileId);
+    }
+
+    public function isAllowedPurchase($aItem, $bPerform = false)
+    {
+        $iUserId = (int)$this->getProfileId();
+
+        $aItemInfo = $this->callGetCartItem((int)$aItem['module_id'], array($aItem['item_id'], isset($aItem['custom']) ? $aItem['custom'] : array()));
+        if(empty($aItemInfo))
+            return false;
+
+        if(isAdmin())
+            return true;
+
+        $aCheckResult = checkActionModule($iUserId, 'purchase', $this->getName(), $bPerform);
+        if($aCheckResult[CHECK_ACTION_RESULT] == CHECK_ACTION_RESULT_ALLOWED)
+            return true;
+
+        return $aCheckResult[CHECK_ACTION_MESSAGE];
+    }
+
+    public function isAllowedSell($aItem, $bPerform = false)
+    {
+        $iUserId = (int)$this->getProfileId();
+        if(!$iUserId)
+            return false;
+
+        $aItemInfo = $this->callGetCartItem((int)$aItem['module_id'], array($aItem['item_id']));
+        if(empty($aItemInfo))
+            return false;
+
+        if(isAdmin())
+            return true;
+
+        $aCheckResult = checkActionModule($iUserId, 'sell', $this->getName(), $bPerform);
+        if((int)$aItemInfo['author_id'] == $iUserId && $aCheckResult[CHECK_ACTION_RESULT] == CHECK_ACTION_RESULT_ALLOWED)
+            return true;
+
+        return $aCheckResult[CHECK_ACTION_MESSAGE];
+    }
+
+    public function isAllowedManage($aPending, $bPerform = false)
+    {
+        $iUserId = (int)$this->getProfileId();
+
+        if($iUserId == $aPending['client_id'] || $iUserId == $aPending['seller_id'] || isAdmin())
+            return true;
+
+        $aCheckResult = checkActionModule($iUserId, 'manage any purchase', $this->getName(), $bPerform);
+        if($aCheckResult[CHECK_ACTION_RESULT] == CHECK_ACTION_RESULT_ALLOWED)
+            return true;
+
+        return $aCheckResult[CHECK_ACTION_MESSAGE];
+    }
+
+    public function isAllowedManageInvoices($bPerform = false)
+    {
+        if(BxDolAcl::getInstance()->isMemberLevelInSet(array(MEMBERSHIP_ID_MODERATOR, MEMBERSHIP_ID_ADMINISTRATOR)) || isAdmin())
+            return true;
+
+        return _t('_sys_txt_access_denied');
+    }
+
+    public function checkData($iClientId, $iSellerId, $iModuleId, $iItemId, $iItemCount, $aCustom = array())
+    {
+    	$CNF = &$this->_oConfig->CNF;
+
+		if($iSellerId == BX_PAYMENT_EMPTY_ID || empty($iModuleId) || empty($iItemId) || empty($iItemCount))
+            return array('code' => 1, 'message' => _t($CNF['T']['ERR_WRONG_DATA']));
+
+		$iClientId = $this->getProfileId();
+        if(empty($iClientId)) {
+        	$sLoginUrl = BxDolPermalinks::getInstance()->permalink('page.php?i=login');
+            return array('code' => 2, 'eval' => 'window.open("' . $sLoginUrl . '", "_self");');
+        }
+
+        $mixedResult = $this->isAllowedPurchase(array('module_id' => $iModuleId, 'item_id' => $iItemId, 'custom' => $aCustom));
+        if($mixedResult !== true) {
+            if(is_string($mixedResult) && !empty($mixedResult))
+                return array('code' => 2, 'message' => $mixedResult);
+            else 
+                return array('code' => 1, 'message' => _t($CNF['T']['ERR_WRONG_DATA']));
+        }
+
+        if($iClientId == $iSellerId)
+            return array('code' => 3, 'message' => _t($CNF['T']['ERR_SELF_PURCHASE']));
+
+        $aSeller = $this->getVendorInfo($iSellerId);
+        if(!$aSeller['active'])
+            return array('code' => 4, 'message' => _t($CNF['T']['ERR_INACTIVE_VENDOR']));
+
+		return true;
+    }
+
+    public function registerPayment($mixedPending)
+    {
+    	$aPending = is_array($mixedPending) ? $mixedPending : $this->_oDb->getOrderPending(array('type' => 'id', 'id' => (int)$mixedPending));
+    	if(empty($aPending) || !is_array($aPending))
+            return false;
+
+        $sType = $aPending['type'];
+        $bTypeSingle = $sType == BX_PAYMENT_TYPE_SINGLE;
+
+        if($bTypeSingle && (int)$aPending['processed'] == 1)
+            return true;
+
+        $iClientId = (int)$aPending['client_id'];
+        $sLicense = $this->_oConfig->getLicense();
+        $aCustoms = !empty($aPending['customs']) ? unserialize($aPending['customs']) : array();
+
+        $aCart = array();
+        if($bTypeSingle) {
+            $aCart = $this->_oDb->getCartContent($iClientId);
+            $aCart['customs'] = !empty($aCart['customs']) ? unserialize($aCart['customs']) : array();
+        }
+
+        $bResult = false;
+        $aItems = $this->_oConfig->descriptorsM2A($aPending['items']);
+        foreach($aItems as $aItem) {
+            $sItem = $this->_oConfig->descriptorA2S(array($aItem['vendor_id'], $aItem['module_id'], $aItem['item_id']));
+            $aItemCustom = $this->_oConfig->getCustom($sItem, $aCustoms);
+
+            $sMethod = $bTypeSingle ? 'callRegisterCartItem' : 'callRegisterSubscriptionItem';
+            $aItemInfo = $this->$sMethod((int)$aItem['module_id'], array($aPending['client_id'], $aPending['seller_id'], $aItem['item_id'], $aItem['item_count'], $aPending['order'], $sLicense, $aItemCustom));
+            if(empty($aItemInfo) || !is_array($aItemInfo))
+                continue;
+
+            $this->_oDb->insertOrderProcessed(array(
+                'pending_id' => $aPending['id'],
+                'client_id' => $aPending['client_id'],
+                'seller_id' => $aPending['seller_id'],
+                'author_id' => $aItem['vendor_id'],
+                'module_id' => (int)$aItem['module_id'],
+                'item_id' => (int)$aItem['item_id'],
+                'item_count' => (int)$aItem['item_count'],
+                'amount' => (int)$aItem['item_count'] * $this->_oConfig->getPrice($sType, $aItemInfo),
+            	'license' => $sLicense,
+            ));
+
+            if($bTypeSingle) {
+                $this->_oConfig->pullCustom($sItem, $aCart['customs']);
+
+            	$aCart['items'] = trim(preg_replace("'" . $this->_oConfig->descriptorA2S($aItem) . ":?'", "", $aCart['items']), ":");
+            }
+
+            $bResult = true;
+        }
+
+        if($bTypeSingle)
+            $this->_oDb->setCartItems($iClientId, $aCart['items'], $aCart['customs']);
+
+        if($bResult) {
+            $this->_oDb->updateOrderPending($aPending['id'], array('processed' => 1));
+
+            $this->onPaymentRegister($aPending);
+        }
+
+        return $bResult;
+    }
+
+    public function refundPayment($mixedPending)
+    {
+        $aPending = is_array($mixedPending) ? $mixedPending : $this->_oDb->getOrderPending(array('type' => 'id', 'id' => (int)$mixedPending));
+        if(empty($aPending) || !is_array($aPending))
+            return false;
+
+        $bTypeSingle = $aPending['type'] == BX_PAYMENT_TYPE_SINGLE;
+
+        $iCanceled = 0;
+        $aOrders = $this->_oDb->getOrderProcessed(array('type' => 'pending_id', 'pending_id' => (int)$aPending['id']));
+        foreach($aOrders as $aOrder) {
+            $sMethod = $bTypeSingle ? 'callUnregisterCartItem' : 'callUnregisterSubscriptionItem';
+            $bResult = $this->$sMethod((int)$aOrder['module_id'], array($aOrder['client_id'], $aOrder['seller_id'], $aOrder['item_id'], $aOrder['item_count'], $aPending['order'], $aOrder['license']));
+            if(!$bResult)
+                continue;
+
+            if($this->_oDb->deleteOrderProcessed($aOrder['id']))
+                $iCanceled++;
+        }
+
+        if($iCanceled != count($aOrders))
+                return false;
+
+        $bResult = $this->_oDb->deleteOrderPending($aPending['id']);
+        if($bResult)
+                $this->onPaymentRefund($aPending);
+
+        return $bResult;
+    }
+
+    /**
+     * @deprecated since version 12.0.0
+     * 
+     * @use BxPaymentSubscriptions::register instead.
+     */
+    public function registerSubscription($aPending, $aParams = array())
+    {
+        return $this->getObjectSubscriptions()->register($aPending, $aParams);
+    }
+
+    /**
+     * @deprecated since version 12.0.0
+     * 
+     * @use BxPaymentSubscriptions::cancelLocal instead.
+     */
+    public function cancelSubscription($mixedPending)
+    {
+        return $this->getObjectSubscriptions()->cancelLocal($mixedPending);
+    }
+
+    public function processCommissions()
+    {
+        if(!defined('BX_DOL_CRON_EXECUTE'))
+            return;
+
+        $CNF = &$this->_oConfig->CNF;
+
+        if((int)date('j') == $CNF['PARAM_CMSN_INVOICE_ISSUE_DAY'])
+            $this->_invoicesIssue();
+
+        $this->_invoicesCheck();
+    }
+
+    protected function _invoicesIssue()
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $sInvoiceNameMask = 'INV-%d-%d-%d';
+
+        $iMonth = date('m');
+        $iYear = date('Y');
+        $iPeriodStart = mktime(0, 0, 0, $iMonth-1, 1, $iYear);
+        $iPeriodEnd = mktime(23, 59, 59, $iMonth, 0, $iYear);
+        $iDateIssue = time();
+        $iDateDue = $iDateIssue + 86400 * $CNF['PARAM_CMSN_INVOICE_LIFETIME'];
+
+        $aCommissionsInfo = array();
+        $aAclLevels = BxDolAcl::getInstance()->getMemberships(false, true, false, true);
+        foreach($aAclLevels as $iAclLevelId => $sAclLevelTitle)
+            $aCommissionsInfo[$iAclLevelId] = $this->_oDb->getCommissions(array('type' => 'acl_id', 'acl_id' => $iAclLevelId));
+
+        $iMainSellerId = $this->_oConfig->getSiteAdmin();
+
+        $aVendors = $this->_oDb->getOrderProcessed(array('type' => 'income', 'period_start' => $iPeriodStart, 'period_end' => $iPeriodEnd));
+        foreach($aVendors as $aVendor) {
+            $iVendorId = (int)$aVendor['id'];
+            if($iVendorId == $iMainSellerId)
+                continue;
+
+            $aInvoice = $this->_oDb->getInvoices(array('type' => 'committent_id', 'committent_id' => $iVendorId, 'period_start' => $iPeriodStart, 'period_end' => $iPeriodEnd));
+            if(!empty($aInvoice) && is_array($aInvoice))
+                continue;
+
+            $aVendorAcl = BxDolAcl::getInstance()->getMemberMembershipInfo($iVendorId);
+            $aCommissions = $aCommissionsInfo[$aVendorAcl['id']];
+
+            $fCommission = 0;
+            foreach($aCommissions as $aCommission) {
+                if((float)$aCommission['percentage'] > 0)
+                    $fCommission += (float)$aVendor['amount'] * (float)$aCommission['percentage'] / 100;
+
+                if((float)$aCommission['installment'] > 0)
+                    $fCommission += (float)$aCommission['installment'];
+            }
+
+            $this->_oDb->insertInvoice(array(
+                'name' => sprintf($sInvoiceNameMask, $iMainSellerId, $iVendorId, $this->_oDb->getInvoices(array(
+                    'type' => 'index', 
+                    'commissionaire_id' => $iMainSellerId, 
+                    'committent_id' => $iVendorId
+                ))),
+                'commissionaire_id' => $iMainSellerId, 
+                'committent_id' => $iVendorId,
+                'amount' => $fCommission,
+                'period_start' => $iPeriodStart,
+                'period_end' => $iPeriodEnd,
+                'date_issue' => $iDateIssue,
+                'date_due' => $iDateDue,
+                'status' => BX_PAYMENT_INV_STATUS_UNPAID
+            ));
+        }
+    }
+
+    protected function _invoicesCheck()
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $sPrefix = $this->_oConfig->getPrefix('general');
+        $oEmailTemplates = BxDolEmailTemplates::getInstance();
+
+        //--- Process expiring invoices.
+        $aInvoices = $this->_oDb->getInvoices(array('type' => 'expiring'));
+        if(!empty($aInvoices) && is_array($aInvoices))
+            foreach($aInvoices as $aInvoice) {
+                if((int)$aInvoice['ntf_exp'] > 0)
+                    continue;
+
+                $oCommittent = BxDolProfile::getInstance($aInvoice['committent_id']);
+                if(!$oCommittent)
+                    continue;
+
+                $bResult = sendMailTemplate($sPrefix . 'expiring_notification_committent', 0, (int)$aInvoice['committent_id'], array(
+                    'invoice' => $aInvoice['name'],
+                    'days' => $CNF['PARAM_CMSN_INVOICE_EXPIRATION_NOTIFY'],
+                    'period_start' => $this->_oConfig->formatDate($aInvoice['period_start']),
+                    'period_end' => $this->_oConfig->formatDate($aInvoice['period_end']),
+                    'date_issue' => $this->_oConfig->formatDateTime($aInvoice['date_issue']),
+                    'date_due' => $this->_oConfig->formatDateTime($aInvoice['date_due']),
+                ), BX_EMAIL_NOTIFY, true);
+
+                if($bResult)
+                    $this->_oDb->updateInvoice($aInvoice['id'], array('ntf_exp' => 1));
+            }
+
+        //--- Process overdue invoices.
+        $aInvoices = $this->_oDb->getInvoices(array('type' => 'overdue'));
+        if(!empty($aInvoices) && is_array($aInvoices))
+            foreach($aInvoices as $aInvoice) {
+                if((int)$aInvoice['ntf_due'] > 0 && $aInvoice['status'] == BX_PAYMENT_INV_STATUS_OVERDUE)
+                    continue;
+
+                $oCommittent = BxDolProfile::getInstance($aInvoice['committent_id']);
+                if(!$oCommittent)
+                    continue;
+
+                $bResult = sendMailTemplate($sPrefix . 'overdue_notification_committent', 0, (int)$aInvoice['committent_id'], array(
+                    'invoice' => $aInvoice['name'],
+                    'period_start' => $this->_oConfig->formatDate($aInvoice['period_start']),
+                    'period_end' => $this->_oConfig->formatDate($aInvoice['period_end']),
+                    'date_issue' => $this->_oConfig->formatDateTime($aInvoice['date_issue']),
+                    'date_due' => $this->_oConfig->formatDateTime($aInvoice['date_due']),
+                ), BX_EMAIL_NOTIFY, true);
+
+                $this->_oDb->updateInvoice($aInvoice['id'], array(
+                    'status' => BX_PAYMENT_INV_STATUS_OVERDUE, 
+                    'ntf_due' => $bResult ? 1 : 0
+                ));
+            }
+    }
+
+    public function processTimeTracker()
+    {
+        if(!defined('BX_DOL_CRON_EXECUTE'))
+            return;
+
+        $aSubscriptions = $this->_oDb->getSubscription(array(
+            'type' => 'time_tracker',
+            'status_active' => BX_PAYMENT_SBS_STATUS_ACTIVE,
+            'status_trial' => BX_PAYMENT_SBS_STATUS_TRIAL,
+            'status_unpaid' => BX_PAYMENT_SBS_STATUS_UNPAID,
+            'pay_attempts_max' => $this->_oConfig->getPayAttemptsMax(),
+            'pay_attempts_interval' => $this->_oConfig->getPayAttemptsInterval()
+        ));
+
+        if(empty($aSubscriptions) || !is_array($aSubscriptions))
+            return;
+
+        foreach($aSubscriptions as $aSubscription) {
+            $aPending = $this->_oDb->getOrderPending(array('type' => 'id', 'id' => (int)$aSubscription['pending_id']));
+            if(empty($aPending) || !is_array($aPending) || $aPending['type'] != BX_PAYMENT_TYPE_RECURRING) {
+                $this->log($aSubscription, 'Time Tracker', 'Cannot process subscription.');
+                continue;
+            }
+
+            $oProvider = $this->getObjectProvider($aPending['provider'], $aPending['seller_id']);
+            if($oProvider === false || !$oProvider->isActive() || !method_exists($oProvider, 'makePayment')) {
+                $this->log($aSubscription, 'Time Tracker', 'Payment provider unavailable or incorrect.');
+                continue;
+            }
+
+            if(!$oProvider->makePayment($aPending)) {
+                $this->log($aSubscription, 'Time Tracker', 'Payment cannot be processed.');
+                continue;
+            }
+
+            if(!$this->getObjectSubscriptions()->prolong($aPending)) {
+                $this->log($aSubscription, 'Time Tracker', 'Cannot prolong subscription.');
+                continue;
+            }
+
+            if(!$this->registerPayment($aPending)) {
+                $this->log($aSubscription, 'Time Tracker', 'Cannot register payment.');
+                continue;
+            }
+        }
+    }
+
+    public function onPaymentRegisterBefore($aPending, $aResult = array())
+    {
+        bx_alert('system', 'before_register_payment', 0, $aPending['client_id'], array('pending' => $aPending));
+    }
+
+    public function onPaymentRegister($aPending, $aResult = array())
+    {
+        $bTypeSingle = $aPending['type'] == BX_PAYMENT_TYPE_SINGLE;
+
+        if($bTypeSingle) {
+            $aItems = $this->_oConfig->descriptorsM2A($aPending['items']);
+            foreach($aItems as $aItem)
+                $this->isAllowedPurchase(array('module_id' => $aItem['module_id'], 'item_id' => $aItem['item_id']), true);
+        }
+
+        bx_alert('system', 'register_payment', 0, $aPending['client_id'], array('pending' => $aPending));
+    }
+
+    public function onPaymentRefund($aPending, $aResult = array())
+    {
+        bx_alert('system', 'refund_payment', 0, $aPending['client_id'], array('pending' => $aPending));
+    }
+
+    public function onSubscriptionCreate($aPending, $aSubscription, $aResult = array())
+    {
+        $aItems = $this->_oConfig->descriptorsM2A($aPending['items']);
+        $this->isAllowedPurchase(array('module_id' => $aItems[0]['module_id'], 'item_id' => $aItems[0]['item_id']), true);
+
+        bx_alert('system', 'create_subscription', 0, $aPending['client_id'], array(
+            'pending' => $aPending,
+            'subscription' => $aSubscription
+        ));
+    }
+
+    public function onSubscriptionProlong($aPending, $aSubscription, $aResult = array())
+    {
+        bx_alert('system', 'prolong_subscription', 0, $aPending['client_id'], array(
+            'pending' => $aPending,
+            'subscription' => $aSubscription
+        ));
+    }
+
+    public function onSubscriptionOverdue($aPending, $aSubscription, $aResult = array())
+    {
+        bx_alert('system', 'overdue_subscription', 0, $aPending['client_id'], array(
+            'pending' => $aPending,
+            'subscription' => $aSubscription
+        ));
+    }
+
+    public function onSubscriptionCancel($aPending, $aSubscription, $aResult = array())
+    {
+        bx_alert('system', 'cancel_subscription', 0, $aPending['client_id'], array(
+            'pending' => $aPending,
+            'subscription' => $aSubscription
+        ));
+    }
+
+    public function setSiteSubmenu($sSubmenu, $sSelModule, $sSelName)
+    {
+        $oSiteSubmenu = BxDolMenu::getObjectInstance('sys_site_submenu');
+        if(!$oSiteSubmenu)
+            return;
+
+        $sModuleSubmenu = $this->_oConfig->getObject($sSubmenu);
+        $oModuleSubmenu = BxDolMenu::getObjectInstance($sModuleSubmenu);
+        if(!$oModuleSubmenu) 
+            return;
+
+        $oSiteSubmenu->setObjectSubmenu($sModuleSubmenu);
+        $oModuleSubmenu->setSelected($sSelModule, $sSelName);
+    }
+
+    public function getProviderButtonJs($aCartItem, $aProvider, $sRedirect = '', $aCustom = array())
+    {
+        $aButtonJs = array();
+        $iClientId = $this->getProfileId();
+
+        $sItemAddons = '';
+        if(count($aCartItem) == 5)
+            $sItemAddons = array_pop($aCartItem);
+
+        list($iSellerId, $iModuleId, $iItemId, $iItemCount) = $aCartItem;
+
+        $oProvider = $this->getObjectProvider($aProvider['name'], $iSellerId);
+        if($oProvider !== false && method_exists($oProvider, 'getButtonRecurring')) {
+            $aParams = array(
+                'sObjNameCart' => $this->_oConfig->getJsObject('cart'),
+                'iSellerId' => $iSellerId,
+                'iModuleId' => $iModuleId,
+                'iItemId' => $iItemId,
+                'iItemCount' => $iItemCount,
+                'sItemAddons' => $sItemAddons,
+                'sRedirect' => $sRedirect,
+                'sCustom' => base64_encode(serialize($aCustom))
+            );
+
+            $aCartInfo = $this->getObjectCart()->getInfo(BX_PAYMENT_TYPE_RECURRING, $iClientId, $iSellerId, $this->_oConfig->descriptorA2S($aCartItem));
+            if(!empty($aCartInfo['items_price']) && !empty($aCartInfo['items']) && is_array($aCartInfo['items'])) {
+                $aItem = array_shift($aCartInfo['items']);
+
+                $aParams = array_merge($aParams, array(
+                    'iAmount' => (int)round(100 * (float)$aCartInfo['items_price']),
+                    'sItemName' => $aItem['name'],
+                    'sItemTitle' => $aItem['title']
+                ));
+            }
+
+            $aButtonJs = $oProvider->getButtonRecurringJs($iClientId, $iSellerId, $aParams);
+        }
+
+        if(empty($aButtonJs) || !is_array($aButtonJs))
+            $aButtonJs = $this->getObjectSubscriptions()->serviceGetSubscribeJs($iSellerId, $aProvider['name'], $iModuleId, $iItemId, $iItemCount, $sRedirect, $aCustom);
+
+        return $aButtonJs;
+    }
+
+    /**
+     * Integration with itslef which is needed to pay an invoice.
+     */
+
+    /**
+     * @page service Service Calls
+     * @section bx_payment Payment
+     * @subsection bx_payment-payments Payments
+     * @subsubsection bx_payment-get_payment_data get_payment_data
+     * 
+     * @code bx_srv('bx_payment', '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 BxPaymentModule::serviceGetPaymentData
+     */
+    /** 
+     * @ref bx_payment-get_payment_data "get_payment_data"
+     */
+    public function serviceGetPaymentData()
+    {
+        return $this->_aModule;
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_payment Payment
+     * @subsection bx_payment-payments Payments
+     * @subsubsection bx_payment-get_cart_item get_cart_item
+     * 
+     * @code bx_srv('bx_payment', '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 BxPaymentModule::serviceGetCartItem
+     */
+    /** 
+     * @ref bx_payment-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->getInvoices(array('type' => 'id', 'id' => (int)$mixedItemId));
+        else 
+            $aItem = $this->_oDb->getInvoices(array('type' => 'name', 'name' => $mixedItemId));
+
+        if(empty($aItem) || !is_array($aItem))
+            return array();
+
+        $oCommissionaire = BxDolProfile::getInstanceMagic($aItem['commissionaire_id']);
+
+        return array (
+            'id' => $aItem['id'],
+            'author_id' => $aItem['commissionaire_id'],
+            'name' => $aItem['name'],
+            'title' => _t('_bx_payment_txt_invoice_title', $aItem['name'], $oCommissionaire->getDisplayName()),
+            'description' => _t('_bx_payment_txt_invoice_description', bx_process_output($aItem['period_start'], BX_DATA_DATE_TS_UTC), bx_process_output($aItem['period_end'], BX_DATA_DATE_TS_UTC)),
+            'url' => '',
+            'price_single' => $aItem['amount'],
+            'price_recurring' => '',
+            'period_recurring' => 0,
+            'period_unit_recurring' => '',
+            'trial_recurring' => ''
+        );
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_payment Payment
+     * @subsection bx_payment-payments Payments
+     * @subsubsection bx_payment-get_cart_items get_cart_items
+     * 
+     * @code bx_srv('bx_payment', 'get_cart_items', [...]); @endcode
+     * 
+     * Get an array with prodicts' descriptions by seller. Is used in Manual Order Processing in payments processing module.
+     * 
+     * @param $iCommissionaireId commissionaire ID.
+     * @return an array with prodicts' descriptions. Empty array is returned if something is wrong or seller doesn't have any products.
+     * 
+     * @see BxPaymentModule::serviceGetCartItems
+     */
+    /** 
+     * @ref bx_payment-get_cart_items "get_cart_items"
+     */
+    public function serviceGetCartItems($iCommissionaireId)
+    {
+    	$CNF = &$this->_oConfig->CNF;
+
+        $iCommissionaireId = (int)$iCommissionaireId;
+        if(empty($iCommissionaireId))
+            return array();
+
+        $sCommissionaireName = BxDolProfile::getInstanceMagic($iCommissionaireId)->getDisplayName();
+
+        $aItems = $this->_oDb->getInvoices(array('type' => 'commissionaire_id', 'commissionaire_id' => $iCommissionaireId));      
+
+        $aResult = array();
+        foreach($aItems as $aItem)
+            $aResult[] = array(
+                'id' => $aItem['id'],
+                'author_id' => $aItem['commissionaire_id'],
+                'name' => $aItem['name'],
+                'title' => _t('_bx_payment_txt_invoice_title', $aItem['name'], $sCommissionaireName),
+                'description' => _t('_bx_payment_txt_invoice_description', bx_process_output($aItem['period_start'], BX_DATA_DATE_TS_UTC), bx_process_output($aItem['period_end'], BX_DATA_DATE_TS_UTC)),
+                'url' => '',
+                'price_single' => $aItem['amount'],
+                'price_recurring' => '',
+                'period_recurring' => 0,
+                'period_unit_recurring' => '',
+                'trial_recurring' => ''
+            );
+
+        return $aResult;
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_payment Payment
+     * @subsection bx_payment-payments Payments
+     * @subsubsection bx_payment-register_cart_item register_cart_item
+     * 
+     * @code bx_srv('bx_payment', 'register_cart_item', [...]); @endcode
+     * 
+     * Register a processed single time payment inside the Payment 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 BxPaymentModule::serviceRegisterCartItem
+     */
+    /** 
+     * @ref bx_payment-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();
+
+        if(!$this->_oDb->updateInvoice($iItemId, array('status' => BX_PAYMENT_INV_STATUS_PAID)))
+            return array();
+
+        bx_alert($this->getName(), 'invoice_marked_as_paid', 0, false, array(
+            'product_id' => $iItemId,
+            'profile_id' => $iClientId,
+            'order' => $sOrder,
+            'license' => $sLicense,
+            'type' => BX_PAYMENT_TYPE_SINGLE,
+            'count' => $iItemCount,
+            'duration' => '',
+            'trial' => ''
+        ));
+
+        return $aItem;
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_payment Payment
+     * @subsection bx_payment-payments Payments
+     * @subsubsection bx_payment-unregister_cart_item unregister_cart_item
+     * 
+     * @code bx_srv('bx_payment', 'unregister_cart_item', [...]); @endcode
+     * 
+     * Unregister an earlier processed single time payment inside the Payment 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 BxPaymentModule::serviceUnregisterCartItem
+     */
+    /** 
+     * @ref bx_payment-unregister_cart_item "unregister_cart_item"
+     */
+    public function serviceUnregisterCartItem($iClientId, $iSellerId, $iItemId, $iItemCount, $sOrder, $sLicense)
+    {
+        if(!$this->_oDb->updateInvoice($iItemId, array('status' => BX_PAYMENT_INV_STATUS_UNPAID)))
+            return false;
+
+        bx_alert($this->getName(), 'invoice_marked_as_unpaid', 0, false, array(
+            'product_id' => $iItemId,
+            'profile_id' => $iClientId,
+            'order' => $sOrder,
+            'license' => $sLicense,
+            'type' => BX_PAYMENT_TYPE_SINGLE,
+            'count' => $iItemCount
+        ));
+
+    	return true;
+    }
+    
+}
+
+/** @} */

+ 200 - 0
modules/boonex/payment/updates/12.0.0_12.0.1/source/classes/BxPaymentOrders.php

@@ -0,0 +1,200 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Payment Payment
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxPaymentOrders extends BxBaseModPaymentOrders
+{
+    protected $_sLangsPrefix;
+
+    function __construct()
+    {
+    	$this->MODULE = 'bx_payment';
+
+    	parent::__construct();
+
+        $this->_sLangsPrefix = $this->_oModule->_oConfig->getPrefix('langs');
+    }
+
+	/*
+     * Service methods
+     */
+    
+    /**
+     * @page service Service Calls
+     * @section bx_payment Payment
+     * @subsection bx_payment-page_blocks Page Blocks
+     * @subsubsection bx_payment-get_block_orders get_block_orders
+     * 
+     * @code bx_srv('bx_payment', 'get_block_orders', [...], 'Orders'); @endcode
+     * 
+     * Get page block with a list of orders represented as table.
+     *
+     * @param $sType string value with order type (processed or pending).
+     * @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 BxPaymentOrders::serviceGetBlockOrders
+     */
+    /** 
+     * @ref bx_payment-get_block_orders "get_block_orders"
+     */
+	public function serviceGetBlockOrders($sType = '', $iUserId = BX_PAYMENT_EMPTY_ID)
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+    	if(empty($sType))
+    		$sType = bx_get('type') !== false ? bx_process_input(bx_get('type')) : BX_PAYMENT_ORDERS_TYPE_PROCESSED;
+
+    	if(!$this->_oModule->isLogged())
+            return array(
+            	'content' => MsgBox(_t($this->_sLangsPrefix . 'err_required_login'))
+            );
+
+        $iUserId = $iUserId != BX_PAYMENT_EMPTY_ID ? $iUserId : $this->_oModule->getProfileId();
+        if($sType == BX_PAYMENT_ORDERS_TYPE_PROCESSED)
+            $this->_oModule->_oDb->updateOrdersProcessed(array('new' => 0), array('seller_id' => $iUserId, 'new' => 1));
+
+        $this->_oModule->setSiteSubmenu('menu_dashboard', 'system', 'dashboard-orders');
+
+        $sBlockSubmenu = $this->_oModule->_oConfig->getObject('menu_orders_submenu');
+        $oBlockSubmenu = BxDolMenu::getObjectInstance($sBlockSubmenu);
+        if($oBlockSubmenu)
+            $oBlockSubmenu->setSelected($this->MODULE, 'orders-' . $sType);
+
+        return array(
+        	'title' => _t($this->_sLangsPrefix . 'page_block_title_orders_' . $sType),
+        	'content' => $this->_oModule->_oTemplate->displayBlockOrders($sType, $iUserId),
+            'menu' => $oBlockSubmenu
+        );
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_payment Payment
+     * @subsection bx_payment-other Other
+     * @subsubsection bx_payment-get_orders_info get_orders_info
+     * 
+     * @code bx_srv('bx_payment', 'get_orders_info', [...], 'Orders'); @endcode
+     * 
+     * Get transaction(s) which meets all requirements.
+     *
+     * @param $aConditions an array of pears('key' => 'value'). Available keys are the following:
+     * a. license - internal license (string)
+     * b. client_id - client's ID (integer)
+     * c. seller_id - seller's ID (integer)
+     * d. module_id - modules's where the purchased product is located. (integer)
+     * e. item_id - item id in the database. (integer)
+     * f. date - the date when the payment was processed(UNIXTIME STAMP)
+     * @return an array of transactions. Each transaction has full info(client ID, seller ID, external transaction ID, date and so on)
+     * 
+     * @see BxPaymentOrders::serviceGetOrdersInfo
+     */
+    /** 
+     * @ref bx_payment-get_orders_info "get_orders_info"
+     */
+    public function serviceGetOrdersInfo($aConditions)
+    {
+        if(empty($aConditions) || !is_array($aConditions))
+            return array();
+
+        return $this->_oModule->_oDb->getOrderProcessed(array('type' => 'mixed', 'conditions' => $aConditions));
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_payment Payment
+     * @subsection bx_payment-other Other
+     * @subsubsection bx_payment-get_pending_orders_info get_pending_orders_info
+     * 
+     * @code bx_srv('bx_payment', 'get_pending_orders_info', [...], 'Orders'); @endcode
+     * 
+     * Get pending transaction(s) which meets all requirements.
+     *
+     * @param $aConditions an array of pears('key' => 'value'). The most useful keys are the following:
+     * a. client_id - client's ID (integer)
+     * b. seller_id - seller's ID (integer)
+     * c. type - transaction type: single or recurring (string)
+     * d. amount - transaction amount (float)
+     * e. order - order ID received from payment provider (string)
+     * f. provider - payment provider name (string)
+     * g. date - the date when the payment was established(UNIXTIME STAMP)
+     * h. processed - whether the payment was processed or not (integer, 0 or 1)
+     * @return an array of pending transactions. Each transaction has full info(client ID, seller ID, type, date and so on)
+     * 
+     * @see BxPaymentOrders::serviceGetPendingOrdersInfo
+     */
+    /** 
+     * @ref bx_payment-get_pending_orders_info "get_pending_orders_info"
+     */
+    public function serviceGetPendingOrdersInfo($aConditions)
+    {
+        if(empty($aConditions) || !is_array($aConditions))
+            return array();
+
+        return $this->_oModule->_oDb->getOrderPending(array('type' => 'mixed', 'conditions' => $aConditions));
+    }
+
+    public function addOrder($aData)
+    {
+        $iSellerId = isset($aData['seller_id']) ? (int)$aData['seller_id'] : $this->_oModule->getProfileId();
+        if($iSellerId == $aData['client_id'])
+            return array('msg' => $this->_sLangsPrefix . 'err_self_purchase');
+
+        $sOrder = trim($aData['order']);
+        if(empty($sOrder))
+            return array('msg' => $this->_sLangsPrefix . 'form_processed_input_order_err');
+
+        $aCartInfo = array('vendor_id' => $iSellerId, 'items_price' => 0, 'items' => array());
+        foreach($aData['items'] as $aItem) {
+        	if(!$this->_oModule->isAllowedSell(array('module_id' => $aData['module_id'], 'item_id' => $aItem['id']), true))
+        		continue;
+
+            $aCartInfo['items_price'] += $this->_oModule->_oConfig->getPrice($aData['type'], $aItem) * $aItem['quantity'];
+            $aCartInfo['items'][] = array(
+                'author_id' => $iSellerId,
+                'module_id' => $aData['module_id'],
+                'id' => $aItem['id'],
+                'quantity' => $aItem['quantity']
+            );
+        }
+
+        $iPendingId = $this->_oModule->_oDb->insertOrderPending($aData['client_id'], $aData['type'], $aData['provider'], $aCartInfo);
+        $this->_oModule->_oDb->updateOrderPending($iPendingId, array(
+            'order' => $sOrder,
+            'error_code' => $aData['error_code'],
+            'error_msg' => $aData['error_msg']
+        ));
+
+        return (int)$iPendingId;
+    }
+
+    public function getOrder($sType, $iId)
+    {
+        return $this->_oModule->_oTemplate->displayOrder($sType, $iId);
+    }
+
+    public function cancel($sType, $iOrderId)
+    {
+    	$sMethodName = 'getOrder' . bx_gen_method_name($sType);
+    	$aOrder = $this->_oModule->_oDb->$sMethodName(array('type' => 'id', 'id' => $iOrderId));
+		if(empty($aOrder) || !is_array($aOrder))
+	    	return true;
+
+		if($sType == BX_PAYMENT_ORDERS_TYPE_PROCESSED && !$this->_oModule->callUnregisterCartItem((int)$aOrder['module_id'], array($aOrder['client_id'], $aOrder['seller_id'], $aOrder['item_id'], $aOrder['item_count'], $aOrder['order'], $aOrder['license'])))
+			return false;
+
+		$sMethodName = 'deleteOrder' . bx_gen_method_name($sType);
+		if(!$this->_oModule->_oDb->$sMethodName($iOrderId))
+			return false;
+
+        return true;
+    }
+}
+
+/** @} */

+ 26 - 0
modules/boonex/payment/updates/12.0.0_12.0.1/source/classes/BxPaymentPageInvoices.php

@@ -0,0 +1,26 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Payment Payment
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxPaymentPageInvoices extends BxTemplPage
+{
+    protected $_sModule;
+    protected $_oModule;
+
+    public function __construct($aObject, $oTemplate = false)
+    {
+        parent::__construct($aObject, $oTemplate);
+
+        $this->_sModule = 'bx_payment';
+        $this->_oModule = BxDolModule::getInstance($this->_sModule);
+    }
+}
+
+/** @} */

+ 49 - 0
modules/boonex/payment/updates/12.0.0_12.0.1/source/classes/BxPaymentStudioPage.php

@@ -0,0 +1,49 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Forum Forum
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxPaymentStudioPage extends BxTemplStudioModule
+{
+    protected $_sModule;
+    protected $_oModule;
+
+    function __construct($sModule, $mixedPageName, $sPage = "")
+    {
+    	$this->_sModule = 'bx_payment';
+    	$this->_oModule = BxDolModule::getInstance($this->_sModule);
+
+        parent::__construct($sModule, $mixedPageName, $sPage);
+
+        $this->aMenuItems = array_merge($this->aMenuItems, array(
+            'providers' => array('name' => 'providers', 'icon' => 'money-bill-alt', 'title' => '_bx_payment_lmi_cpt_providers'),
+            'commissions' => array('name' => 'commissions', 'icon' => 'percent', 'title' => '_bx_payment_lmi_cpt_commissions')
+        ));
+    }
+
+    protected function getProviders()
+    {
+        $oGrid = BxDolGrid::getObjectInstance($this->_oModule->_oConfig->getObject('grid_providers'), BxDolStudioTemplate::getInstance());
+        if(!$oGrid)
+            return '';
+
+        return $oGrid->getCode();
+    }
+
+    protected function getCommissions()
+    {
+        $oGrid = BxDolGrid::getObjectInstance($this->_oModule->_oConfig->getObject('grid_commissions'), BxDolStudioTemplate::getInstance());
+        if(!$oGrid)
+            return '';
+
+        return $oGrid->getCode();
+    }
+}
+
+/** @} */

+ 476 - 0
modules/boonex/payment/updates/12.0.0_12.0.1/source/classes/BxPaymentTemplate.php

@@ -0,0 +1,476 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Payment Payment
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxPaymentTemplate extends BxBaseModPaymentTemplate
+{
+	protected $_sLangsPrefix;
+
+    function __construct(&$oConfig, &$oDb)
+    {
+    	$this->MODULE = 'bx_payment';
+
+        parent::__construct($oConfig, $oDb);
+
+        $this->_sLangsPrefix = $this->_oConfig->getPrefix('langs');
+    }
+
+    public function addJsCssOrders()
+    {
+    	$this->addJs(array(
+            'jquery-ui/jquery.ui.widget.min.js',
+            'jquery-ui/jquery.ui.menu.min.js', 
+            'jquery-ui/jquery.ui.autocomplete.min.js', 
+            'jquery.form.min.js', 
+            'jquery.anim.js', 
+            'jquery.webForms.js',
+            'orders.js'
+    	));
+    	$this->addCss(array('orders.css'));
+    }
+
+    public function addJsCssSubscriptions()
+    {
+        $this->addJs(array('jquery.form.min.js', 'jquery.anim.js', 'jquery.webForms.js', 'main.js', 'subscriptions.js'));
+        $this->addCss(array('orders.css', 'subscriptions.css'));
+    }
+
+    public function addJsCssCart($sType = '', $iVendorId = 0)
+    {
+    	$this->addJsTranslation(array('_bx_payment_err_nothing_selected'));
+    	$this->addJs(array('jquery.anim.js', 'main.js', 'cart.js'));
+    	$this->addCss(array('orders.css', 'cart.css'));
+
+    	$oModule = $this->getModule();
+    	if(!empty($iVendorId)) {
+            $sMethod = 'getVendorInfoProviders' . bx_gen_method_name($sType);
+            $aProviders = $this->_oDb->$sMethod($iVendorId);
+            foreach($aProviders as $sProvider => $aProvider)
+                $oModule->getObjectProvider($sProvider, $iVendorId)->addJsCss();
+    	}
+    }
+
+    public function addJsCssInvoices()
+    {
+    	$this->addCss(array('invoices.css'));
+    }
+
+    public function displayCartJs($sType = '', $iVendorId = 0)
+    {
+        $this->addJsCssCart($sType, $iVendorId);
+        return $this->displayJsCode('cart');
+    }
+
+    public function displayAddToCartJs($iVendorId, $iModuleId, $iItemId, $iItemCount, $bNeedRedirect = false, $aCustom = array())
+    {
+        $sJsCode = $this->displayCartJs(BX_PAYMENT_TYPE_SINGLE, $iVendorId);
+        $sJsMethod = $this->parseHtmlByName('add_to_cart_js.html', array(
+            'js_object' => $this->_oConfig->getJsObject('cart'),
+            'vendor_id' => $iVendorId,
+            'module_id' => $iModuleId,
+            'item_id' => $iItemId,
+            'item_count' => $iItemCount,
+            'need_redirect' => (int)$bNeedRedirect,
+            'custom' => !empty($aCustom) && is_array($aCustom) ? base64_encode(serialize($aCustom)) : ''
+        ));
+
+        return array($sJsCode, $sJsMethod);
+    }
+
+    public function displayAddToCartLink($iVendorId, $iModuleId, $iItemId, $iItemCount, $bNeedRedirect = false, $aCustom = array())
+    {
+        $this->addJsCssCart(BX_PAYMENT_TYPE_SINGLE, $iVendorId);
+        return $this->parseHtmlByName('add_to_cart.html', array(
+            'js_object' => $this->_oConfig->getJsObject('cart'),
+            'js_content' => $this->displayJsCode('cart'),
+            'txt_add_to_cart' => _t($this->_sLangsPrefix . 'txt_add_to_cart'),
+            'vendor_id' => $iVendorId,
+            'module_id' => $iModuleId,
+            'item_id' => $iItemId,
+            'item_count' => $iItemCount,
+            'need_redirect' => (int)$bNeedRedirect,
+            'custom' => !empty($aCustom) && is_array($aCustom) ? base64_encode(serialize($aCustom)) : ''
+        ));
+    }
+
+    public function displaySubscribeJs($iVendorId, $sVendorProvider, $iModuleId, $iItemId, $iItemCount = 1, $sRedirect = '', $aCustom = array())
+    {
+        return $this->displaySubscribeJsWithAddons($iVendorId, $sVendorProvider, $iModuleId, $iItemId, $iItemCount, '', $sRedirect, $aCustom);
+    }
+
+    public function displaySubscribeJsWithAddons($iVendorId, $sVendorProvider, $iModuleId, $iItemId, $iItemCount = 1, $sItemAddons = '', $sRedirect = '', $aCustom = array())
+    {
+        $aSellerProviders = $this->_oDb->getVendorInfoProvidersRecurring($iVendorId);
+        if(empty($sVendorProvider) && count($aSellerProviders) == 1) {
+            $aCartItem = array($iVendorId, $iModuleId, $iItemId, $iItemCount, $sItemAddons);
+
+            $this->addJsCssCart(BX_PAYMENT_TYPE_RECURRING, $iVendorId);
+            return $this->getModule()->getProviderButtonJs($aCartItem, array_shift($aSellerProviders), $sRedirect, $aCustom);
+        }
+
+        return array(
+            $this->displayCartJs(BX_PAYMENT_TYPE_RECURRING, $iVendorId),
+            $this->parseHtmlByName('subscribe_js.html', array(
+                'js_object' => $this->_oConfig->getJsObject('cart'),
+                'vendor_id' => $iVendorId,
+                'vendor_provider' => $sVendorProvider,
+                'module_id' => $iModuleId,
+                'item_id' => $iItemId,
+                'item_count' => $iItemCount,
+                'redirect' => !empty($sRedirect) ? $sRedirect : '',
+                'custom' => !empty($aCustom) && is_array($aCustom) ? base64_encode(serialize($aCustom)) : ''
+            ))
+        );
+    }
+
+    public function displaySubscribeLink($iVendorId, $sVendorProvider, $iModuleId, $iItemId, $iItemCount = 1, $sRedirect = '', $aCustom = array())
+    {
+        $this->addJsCssCart(BX_PAYMENT_TYPE_RECURRING, $iVendorId);
+        return $this->parseHtmlByName('subscribe.html', array(
+            'js_object' => $this->_oConfig->getJsObject('cart'),
+            'js_content' => $this->displayJsCode('cart'),
+            'txt_add_to_cart' => _t($this->_sLangsPrefix . 'txt_subscribe'),
+            'vendor_id' => $iVendorId,
+            'vendor_provider' => $sVendorProvider,
+            'module_id' => $iModuleId,
+            'item_id' => $iItemId,
+            'item_count' => $iItemCount,
+            'redirect' => !empty($sRedirect) ? $sRedirect : '',
+            'custom' => !empty($aCustom) && is_array($aCustom) ? base64_encode(serialize($aCustom)) : ''
+        ));
+    }
+
+    public function displaySubscriptionGetDetails($iId)
+    {
+    	return $this->_displaySubscriptionData('get_details', $iId);
+    }
+
+    public function displaySubscriptionChangeDetails($iId)
+    {
+    	return $this->_displaySubscriptionData('change_details', $iId);
+    }
+
+    public function displaySubscriptionGetBilling($iId)
+    {
+    	return $this->_displaySubscriptionData('get_billing', $iId);
+    }
+
+    public function displaySubscriptionChangeBilling($iId)
+    {
+    	return $this->_displaySubscriptionData('change_billing', $iId);
+    }
+
+	public function displayBlockCarts($iClientId)
+    {
+    	$oGrid = BxDolGrid::getObjectInstance($this->_oConfig->getObject('grid_carts'));
+        if(!$oGrid)
+            return MsgBox(_t($this->_sLangsPrefix . 'msg_no_results'));
+
+		$oGrid->addQueryParam('client_id', $iClientId);
+
+		$this->addJsCssCart(BX_PAYMENT_TYPE_SINGLE);
+        return $this->displayJsCode('cart') . $oGrid->getCode();
+    }
+
+    public function displayBlockCart($iClientId, $iSellerId = 0)
+    {
+    	$oGrid = BxDolGrid::getObjectInstance($this->_oConfig->getObject('grid_cart'));
+        if(!$oGrid || empty($iSellerId))
+            return MsgBox(_t($this->_sLangsPrefix . 'msg_no_results'));
+
+        $oGrid->addQueryParam('client_id', $iClientId);
+        $oGrid->addQueryParam('seller_id', $iSellerId);
+
+        $this->addJsCssCart(BX_PAYMENT_TYPE_SINGLE, $iSellerId);
+        return $this->displayJsCode('cart') . $oGrid->getCode();
+    }
+
+    public function displayBlockHistory($iClientId, $iSellerId)
+    {
+        return $this->_displayBlockHistory('grid_history', $iClientId, $iSellerId);
+    }
+
+    public function displayBlockSbsListMy($iClientId)
+    {
+        $oGrid = BxDolGrid::getObjectInstance($this->_oConfig->getObject('grid_sbs_list_my'), $this->getModule()->_oTemplate);
+        if(!$oGrid || empty($iClientId))
+            return MsgBox(_t($this->_sLangsPrefix . 'msg_no_results'));
+
+		$oGrid->addQueryParam('client_id', $iClientId);
+
+		$this->addJsCssSubscriptions();
+        return $this->displayJsCode(BX_PAYMENT_ORDERS_TYPE_SUBSCRIPTION) . $oGrid->getCode();
+    }
+
+    public function displayBlockSbsListAll()
+    {
+        $oGrid = BxDolGrid::getObjectInstance($this->_oConfig->getObject('grid_sbs_list_all'), $this->getModule()->_oTemplate);
+        if(!$oGrid)
+            return MsgBox(_t($this->_sLangsPrefix . 'msg_no_results'));
+
+		$this->addJsCssSubscriptions();
+        return $this->displayJsCode(BX_PAYMENT_ORDERS_TYPE_SUBSCRIPTION) . $oGrid->getCode();
+    }
+
+    public function displayBlockSbsHistory($iClientId)
+    {
+        return $this->_displayBlockHistory('grid_sbs_history', $iClientId);
+    }
+
+    public function displayBlockSbsDetails($iClientId)
+    {
+        return 'Details would be here';
+    }
+
+    public function displayBlockOrders($sType, $iSellerId)
+    {
+        $sGrid = $this->_oConfig->getObject('grid_' . $sType);
+        $oGrid = BxDolGrid::getObjectInstance($sGrid);
+        if(!$oGrid || empty($iSellerId))
+            return MsgBox(_t($this->_sLangsPrefix . 'msg_no_results'));
+
+        $oGrid->addQueryParam('seller_id', $iSellerId);
+
+        $this->addJsCssOrders();
+        return $this->displayJsCode($sType, array(
+            'sObjNameGrid' => $sGrid,
+            'sParamsDivider' => $this->_oConfig->getDivider('DIVIDER_GRID_FILTERS'),
+            'sTextSearchInput' => _t('_sys_grid_search')
+        )) . $oGrid->getCode();
+    }
+
+    public function displayOrder($sType, $iId)
+    {
+        $sMethodName = 'getOrder' . bx_gen_method_name($sType);
+        $aOrder = $this->_oDb->$sMethodName(array('type' => 'id', 'id' => $iId));
+
+        $oModule = $this->getModule();
+        $aSeller = $oModule->getVendorInfo((int)$aOrder['seller_id']);
+        $aClient = $oModule->getProfileInfo((int)$aOrder['client_id']);
+
+        $aTmplVarsLicense = array();
+        if(in_array($sType, array(BX_PAYMENT_ORDERS_TYPE_PROCESSED, BX_PAYMENT_ORDERS_TYPE_HISTORY)))
+            $aTmplVarsLicense = array(
+                'txt_license' => _t($this->_sLangsPrefix . 'txt_license'),
+                'license' => $aOrder['license']
+            );
+
+        $bTmplVarsShowSlrAtr = !empty($aOrder['author_id']) && $aOrder['seller_id'] != $aOrder['author_id'];
+
+        $aTmplVarsAuthor = array();
+        if($bTmplVarsShowSlrAtr) {
+            $aAuthor = $oModule->getProfileInfo((int)$aOrder['author_id']);
+
+            $aTmplVarsAuthor = array(
+                'txt_author' => _t($this->_sLangsPrefix . 'txt_author'),
+                'author_name' => $aAuthor['name'],
+                'author_url' => $aAuthor['link'],
+            );
+        }
+
+        $aTmplVarsSeller = array(
+            'txt_seller' => _t($this->_sLangsPrefix . 'txt_seller'),
+            'bx_if:show_link' => array(
+                'condition' => !empty($aSeller['link']),
+                'content' => array(
+                    'seller_name' => $aSeller['name'],
+                    'seller_url' => $aSeller['link'],
+                )
+            ),
+            'bx_if:show_text' => array(
+                'condition' => empty($aSeller['link']),
+                'content' => array(
+                    'seller_name' => $aSeller['name']
+                )
+            ),
+        );
+        
+        $aResult = array_merge(array(
+            'txt_client' => _t($this->_sLangsPrefix . 'txt_client'),
+            'txt_order' => _t($this->_sLangsPrefix . 'txt_order'),
+            'txt_processed_with' => _t($this->_sLangsPrefix . 'txt_processed_with'),
+            'txt_message' => _t($this->_sLangsPrefix . 'txt_message'),
+            'txt_date' => _t($this->_sLangsPrefix . 'txt_date'),
+            'txt_products' => _t($this->_sLangsPrefix . 'txt_products'),
+            'client_name' => $aClient['name'],
+            'client_url' => $aClient['link'],
+            'bx_if:show_seller' => array(
+                'condition' => $bTmplVarsShowSlrAtr,
+                'content' => $aTmplVarsSeller
+            ),
+            'bx_if:show_license' => array(
+                'condition' => !empty($aTmplVarsLicense),
+                'content' => $aTmplVarsLicense
+            ),
+            'order' => $aOrder['order'],
+            'provider' => _t('_bx_payment_txt_name_' . $aOrder['provider']),
+            'error' => $aOrder['error_msg'],
+            'date' => bx_time_js($aOrder['date'], BX_FORMAT_DATE_TIME, true),
+            'bx_if:show_author' => array(
+                'condition' => $bTmplVarsShowSlrAtr,
+                'content' => $aTmplVarsAuthor
+            ),
+            'bx_repeat:items' => array()
+        ), $aTmplVarsSeller);
+
+        if(in_array($sType, array(BX_PAYMENT_ORDERS_TYPE_PENDING, BX_PAYMENT_ORDERS_TYPE_SUBSCRIPTION)))
+            $aItems = $this->_oConfig->descriptorsM2A($aOrder['items']);
+        else
+            $aItems = $this->_oConfig->descriptorsM2A($this->_oConfig->descriptorA2S(array($aOrder['seller_id'], $aOrder['module_id'], $aOrder['item_id'], $aOrder['item_count'])));
+
+        foreach($aItems as $aItem) {
+            $aInfo = $oModule->callGetCartItem((int)$aItem['module_id'], array($aItem['item_id']));
+            if(!empty($aInfo) && is_array($aInfo))
+	            $aResult['bx_repeat:items'][] = array(
+	                'bx_if:link' => array(
+	                    'condition' => !empty($aInfo['url']),
+	                    'content' => array(
+	                        'title' => $aInfo['title'],
+	                        'url' => $aInfo['url']
+	                    )
+	                ),
+	                'bx_if:text' => array(
+	                    'condition' => empty($aInfo['url']),
+	                    'content' => array(
+	                        'title' => $aInfo['title'],
+	                    )
+	                ),
+	                'quantity' => $aItem['item_count'],
+	                'price' => $this->_oConfig->getPrice($aOrder['type'], $aInfo),
+	                'currency_code' => $aSeller['currency_code']
+	            );
+        }
+
+        return $this->parseHtmlByName('order_' . $sType . '.html', $aResult);
+    }
+
+    public function displayBlockInvoices()
+    {
+        $sGrid = $this->_oConfig->getObject('grid_invoices');
+        $oGrid = BxDolGrid::getObjectInstance($sGrid);
+        if(!$oGrid)
+            return MsgBox(_t($this->_sLangsPrefix . 'msg_no_results'));
+
+        $this->addJsCssInvoices();
+        return $oGrid->getCode();
+    }
+
+    public function displayItems($sType, $aItems = array())
+    {
+        $aTmplVarsItems = array();
+
+        if(!empty($aItems) && is_array($aItems))
+            foreach($aItems as $aItem) {
+                $aTmplVarsItems[$aItem['title']] = array(
+                    'id' => $aItem['id'],
+                    'price' => $this->_oConfig->getPrice($sType, $aItem),
+                    'bx_if:link' => array(
+                        'condition' => !empty($aItem['url']),
+                        'content' => array(
+                            'url' => $aItem['url'],
+                            'title' => $aItem['title']
+                        )
+                    ),
+                    'bx_if:text' => array(
+                        'condition' => empty($aItem['url']),
+                        'content' => array(
+                            'title' => $aItem['title']
+                        )
+                    ),
+                );
+            }
+
+        if(!empty($aTmplVarsItems) && is_array($aTmplVarsItems)) {
+            ksort($aTmplVarsItems);
+            $aTmplVarsItems = array_values($aTmplVarsItems);
+        }
+        else 
+        	$aTmplVarsItems = MsgBox(_t($this->_sLangsPrefix . 'msg_no_results'));
+
+        return $this->parseHtmlByName('items.html', array(
+        	'html_id' => $this->_oConfig->getHtmlIds('processed', 'order_processed_items'),
+        	'bx_repeat:items' => $aTmplVarsItems
+        ));
+    }
+
+    public function displayProvidersSelector($aCartItem, $aProviders, $sRedirect = '', $aCustom = array())
+    {
+    	$oModule = $this->getModule();
+
+        $aTmplVarsProviders = array();
+        foreach($aProviders as $sProvider => $aProvider) {
+            list($sJsCode, $sJsOnclick) = $oModule->getProviderButtonJs($aCartItem, $aProvider, $sRedirect, $aCustom);
+
+            $aTmplVarsProviders[] = array(
+                'button' => $this->parseHtmlByName('providers_select_button.html', array(
+                    'onclick' => $sJsOnclick,
+                    'title' => _t('_bx_payment_txt_checkout_with', _t($aProvider['caption'])),
+                    'js_code' => $sJsCode
+                ))
+            );
+        }
+
+        return $this->parseHtmlByName('providers_select.html', array(
+            'bx_repeat:providers' => $aTmplVarsProviders
+        ));
+    }
+
+    protected function _displayBlockHistory($sObject, $iClientId, $iSellerId = 0)
+    {
+    	$oGrid = BxDolGrid::getObjectInstance($this->_oConfig->getObject($sObject), $this->getModule()->_oTemplate);
+        if(!$oGrid || empty($iClientId))
+            return MsgBox(_t($this->_sLangsPrefix . 'msg_no_results'));
+
+		$oGrid->addQueryParam('client_id', $iClientId);
+		if(!empty($iSellerId))
+			$oGrid->addQueryParam('seller_id', $iSellerId);
+
+		$this->addJsCssOrders();
+        return $this->displayJsCode(BX_PAYMENT_ORDERS_TYPE_HISTORY) . $oGrid->getCode();
+    }
+
+    protected function _displaySubscriptionData($sType, $iId)
+    {
+        $aResult = array('code' => 1, 'message' => _t('_bx_payment_err_cannot_perform'));
+
+        $aPending = $this->_oDb->getOrderPending(array('type' => 'id', 'id' => $iId));
+        if(empty($aPending) || !is_array($aPending))
+            return $aResult;
+
+        $aSubscription = $this->_oDb->getSubscription(array('type' => 'pending_id', 'pending_id' => $iId));
+        if(empty($aSubscription) || !is_array($aSubscription))
+            return $aResult;
+
+        $mixedResult = $this->getModule()->isAllowedManage($aPending);
+        if($mixedResult !== true)
+            return array('code' => 2, 'message' => $mixedResult);
+            
+        $sMethod = bx_gen_method_name($sType) . 'Recurring';
+        $oProvider = $this->getModule()->getObjectProvider($aPending['provider'], $aPending['seller_id']);
+        if($oProvider === false || !$oProvider->isActive() || !method_exists($oProvider, $sMethod))
+        	return $aResult;
+
+        $mixedContent = $oProvider->$sMethod($iId, $aSubscription['customer_id'], $aSubscription['subscription_id']);
+        if(empty($mixedContent))
+            return $aResult;
+        else if(is_array($mixedContent))
+            return $mixedContent;
+
+        $sKey = 'order_' . BX_PAYMENT_ORDERS_TYPE_SUBSCRIPTION . '_' . $sType;
+    	$sId = $this->_oConfig->getHtmlIds(BX_PAYMENT_ORDERS_TYPE_SUBSCRIPTION, $sKey);
+    	$sTitle = _t($this->_sLangsPrefix . 'popup_title_ods_' . $sKey);
+    	return array('popup' => array(
+    		'html' => BxTemplFunctions::getInstance()->popupBox($sId, $sTitle, $mixedContent), 
+    		'options' => array('closeOnOuterClick' => 1)
+    	));
+    }
+}
+
+/** @} */

+ 70 - 0
modules/boonex/payment/updates/12.0.0_12.0.1/source/install/config.php

@@ -0,0 +1,70 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Payment Payment
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_payment',
+    'title' => 'Payment',
+    'note' => 'Payment module.',
+    'version' => '12.0.1',
+    'vendor' => 'Boonex',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '12.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/payment/',
+    'home_uri' => 'payment',
+
+    'db_prefix' => 'bx_payment_',
+    'class_prefix' => 'BxPayment',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Payment',
+
+    /**
+     * 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(),
+);
+
+/** @} */

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

@@ -0,0 +1,690 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources name="en" flag="gb" title="English">
+    <string name="_bx_payment"><![CDATA[Payments]]></string>
+
+    <!-- OPTIONS -->
+    <string name="_bx_payment_option_default_currency_code"><![CDATA[Currency]]></string>
+    <string name="_bx_payment_option_err_default_currency_code"><![CDATA[Currency code cannot be empty.]]></string>
+    <string name="_bx_payment_option_site_admin"><![CDATA[Main seller (To sell on behalf of the site)]]></string>
+    <string name="_bx_payment_option_credits_only"><![CDATA[Pay with Credits only mode ('Credits' app should be installed).]]></string>
+    <string name="_bx_payment_option_single_seller"><![CDATA[Single seller mode (To sell everything on behalf of the 'Main seller').]]></string>
+
+    <!-- PAGES and BLOCKS -->
+    <string name="_bx_payment_page_title_sys_carts"><![CDATA[Shopping Carts]]></string>
+    <string name="_bx_payment_page_title_carts"><![CDATA[Shopping Carts]]></string>
+    <string name="_bx_payment_page_title_sys_cart"><![CDATA[Shopping Cart]]></string>
+    <string name="_bx_payment_page_title_cart"><![CDATA[Shopping Cart]]></string>
+    <string name="_bx_payment_page_title_sys_cart_thank_you"><![CDATA[Thank you!]]></string>
+    <string name="_bx_payment_page_title_cart_thank_you"><![CDATA[Thank you!]]></string>
+    <string name="_bx_payment_page_block_title_carts"><![CDATA[Shopping Carts]]></string>
+    <string name="_bx_payment_page_block_title_cart"><![CDATA[{0}'s Shopping Cart]]></string>
+    <string name="_bx_payment_page_block_title_cart_thank_you"><![CDATA[Thank you!]]></string>
+    <string name="_bx_payment_page_block_content_cart_thank_you"><![CDATA[Thank you! Payment was successfully performed. The data will be processed shortly. Please wait.]]></string>
+
+    <string name="_bx_payment_page_title_sys_sbs_list_my"><![CDATA[My Subscriptions]]></string>
+    <string name="_bx_payment_page_title_sbs_list_my"><![CDATA[My Subscriptions]]></string>
+    <string name="_bx_payment_page_block_title_sbs_list_my"><![CDATA[My Subscriptions]]></string>
+
+    <string name="_bx_payment_page_title_sys_sbs_list_all"><![CDATA[All Subscriptions]]></string>
+    <string name="_bx_payment_page_title_sbs_list_all"><![CDATA[All Subscriptions]]></string>
+    <string name="_bx_payment_page_block_title_sbs_list_all"><![CDATA[All Subscriptions]]></string>
+
+    <string name="_bx_payment_page_title_sys_sbs_history"><![CDATA[My Payments]]></string>
+    <string name="_bx_payment_page_title_sbs_history"><![CDATA[My Payments]]></string>
+    <string name="_bx_payment_page_block_title_sbs_history"><![CDATA[My Payments]]></string>
+
+    <string name="_bx_payment_page_title_sys_history"><![CDATA[Shopping History]]></string>
+    <string name="_bx_payment_page_title_history"><![CDATA[Shopping History]]></string>
+    <string name="_bx_payment_page_block_title_history"><![CDATA[Shopping History]]></string>
+
+    <string name="_bx_payment_page_title_sys_orders"><![CDATA[Orders]]></string>
+    <string name="_bx_payment_page_title_orders"><![CDATA[Orders]]></string>
+    <string name="_bx_payment_page_block_title_orders"><![CDATA[Orders]]></string>
+
+    <string name="_bx_payment_page_title_sys_details"><![CDATA[Payments Details]]></string>
+    <string name="_bx_payment_page_title_details"><![CDATA[Payments Details]]></string>
+    <string name="_bx_payment_page_block_title_details"><![CDATA[Payments Details]]></string>
+
+    <string name="_bx_payment_page_block_title_orders_processed"><![CDATA[Processed Orders]]></string>
+    <string name="_bx_payment_page_block_title_orders_pending"><![CDATA[Pending Orders]]></string>
+
+    <string name="_bx_payment_page_title_response"><![CDATA[Payment Response]]></string>
+    <string name="_bx_payment_page_title_error"><![CDATA[Payment Error]]></string>
+
+    <string name="_bx_payment_page_title_sys_join"><![CDATA[Join]]></string>
+    <string name="_bx_payment_page_title_join"><![CDATA[Join]]></string>
+    <string name="_bx_payment_page_block_title_join"><![CDATA[Join]]></string>
+
+    <string name="_bx_payment_page_title_sys_invoices"><![CDATA[Invoices]]></string>
+    <string name="_bx_payment_page_title_invoices"><![CDATA[Invoices]]></string>
+    <string name="_bx_payment_page_block_title_invoices"><![CDATA[Invoices]]></string>
+    
+    <!-- MENUS -->
+    <string name="_bx_payment_lmi_cpt_providers"><![CDATA[Providers]]></string>
+    <string name="_bx_payment_lmi_cpt_commissions"><![CDATA[Commissions]]></string>
+
+    <string name="_bx_payment_menu_title_orders_submenu"><![CDATA[Orders Submenu]]></string>
+    <string name="_bx_payment_menu_set_title_orders_submenu"><![CDATA[Orders Submenu]]></string>
+    <string name="_bx_payment_menu_item_title_system_orders_processed"><![CDATA[Processed Orders]]></string>
+    <string name="_bx_payment_menu_item_title_orders_processed"><![CDATA[Processed]]></string>
+    <string name="_bx_payment_menu_item_title_system_orders_pending"><![CDATA[Pending Orders]]></string>
+    <string name="_bx_payment_menu_item_title_orders_pending"><![CDATA[Pending]]></string>
+    <string name="_bx_payment_menu_item_title_system_details"><![CDATA[Payments Details]]></string>
+    <string name="_bx_payment_menu_item_title_details"><![CDATA[Payments]]></string>
+    <string name="_bx_payment_menu_item_title_system_admt_invoices"><![CDATA[Invoices]]></string>
+    <string name="_bx_payment_menu_item_title_admt_invoices"><![CDATA[Invoices]]></string>
+    <string name="_bx_payment_menu_item_title_admt_addon_counter1_caption"><![CDATA[paid]]></string>
+    <string name="_bx_payment_menu_item_title_admt_addon_counter2_caption"><![CDATA[overdue]]></string>
+
+    <string name="_bx_payment_menu_title_cart_submenu"><![CDATA[Cart Submenu]]></string>
+    <string name="_bx_payment_menu_set_title_cart_submenu"><![CDATA[Cart Submenu]]></string>
+    <string name="_bx_payment_menu_item_title_system_cart"><![CDATA[Cart]]></string>
+    <string name="_bx_payment_menu_item_title_cart"><![CDATA[Cart]]></string>
+    <string name="_bx_payment_menu_item_title_system_cart_history"><![CDATA[Cart History]]></string>
+    <string name="_bx_payment_menu_item_title_cart_history"><![CDATA[Cart History]]></string>
+
+    <string name="_bx_payment_menu_title_sbs_submenu"><![CDATA[Subscriptions Submenu]]></string>
+    <string name="_bx_payment_menu_set_title_sbs_submenu"><![CDATA[Subscriptions Submenu]]></string>
+    <string name="_bx_payment_menu_item_title_system_sbs_list_my"><![CDATA[My Subscriptions List]]></string>
+    <string name="_bx_payment_menu_item_title_sbs_list_my"><![CDATA[My Subscriptions]]></string>
+    <string name="_bx_payment_menu_item_title_system_sbs_list_all"><![CDATA[All Subscriptions List]]></string>
+    <string name="_bx_payment_menu_item_title_sbs_list_all"><![CDATA[All Subscriptions]]></string>
+    <string name="_bx_payment_menu_item_title_system_sbs_history"><![CDATA[My Payments History]]></string>
+    <string name="_bx_payment_menu_item_title_sbs_history"><![CDATA[My Payments]]></string>
+
+    <string name="_bx_payment_menu_title_sbs_actions"><![CDATA[Subscription Actions]]></string>
+    <string name="_bx_payment_menu_set_title_sbs_actions"><![CDATA[Subscription Actions]]></string>
+    <string name="_bx_payment_menu_item_title_system_sbs_request_cancelation"><![CDATA[Request Cancellation]]></string>
+    <string name="_bx_payment_menu_item_title_sbs_request_cancelation"><![CDATA[Request Cancellation]]></string>
+    <string name="_bx_payment_menu_item_title_system_sbs_cancel"><![CDATA[Cancel Subscription]]></string>
+    <string name="_bx_payment_menu_item_title_sbs_cancel"><![CDATA[Cancel Subscription]]></string>
+
+    <!-- GRIDS -->
+    <string name="_bx_payment_grid_column_title_pdrs_caption"><![CDATA[Caption]]></string>
+    <string name="_bx_payment_grid_column_title_pdrs_description"><![CDATA[Description]]></string>
+    <string name="_bx_payment_grid_column_title_pdrs_for_visitor"><![CDATA[For visitors]]></string>
+    <string name="_bx_payment_grid_column_title_pdrs_for_single"><![CDATA[One Time]]></string>
+    <string name="_bx_payment_grid_column_title_pdrs_for_recurring"><![CDATA[Recurring]]></string>
+    <string name="_bx_payment_grid_column_title_pdrs_single_seller"><![CDATA[Single Seller]]></string>
+    <string name="_bx_payment_grid_column_title_pdrs_time_tracker"><![CDATA[Time Tracker]]></string>
+    <string name="_bx_payment_grid_column_title_ods_client_id"><![CDATA[Client]]></string>
+    <string name="_bx_payment_grid_column_title_ods_seller_id"><![CDATA[Seller]]></string>
+    <string name="_bx_payment_grid_column_title_ods_author_id"><![CDATA[Author]]></string>
+    <string name="_bx_payment_grid_column_title_ods_transaction"><![CDATA[Transaction]]></string>
+    <string name="_bx_payment_grid_column_title_ods_license"><![CDATA[License]]></string>
+    <string name="_bx_payment_grid_column_title_ods_item"><![CDATA[Product]]></string>
+    <string name="_bx_payment_grid_column_title_ods_amount"><![CDATA[Amount]]></string>
+    <string name="_bx_payment_grid_column_title_ods_date"><![CDATA[Date]]></string>
+    <string name="_bx_payment_grid_column_title_sbs_seller_id"><![CDATA[Seller]]></string>
+    <string name="_bx_payment_grid_column_title_sbs_client_id"><![CDATA[Client]]></string>
+    <string name="_bx_payment_grid_column_title_sbs_client_email"><![CDATA[Email]]></string>
+    <string name="_bx_payment_grid_column_title_sbs_customer_id"><![CDATA[Customer ID]]></string>
+    <string name="_bx_payment_grid_column_title_sbs_subscription_id"><![CDATA[Subscription]]></string>
+    <string name="_bx_payment_grid_column_title_sbs_transaction"><![CDATA[Transaction]]></string>
+    <string name="_bx_payment_grid_column_title_sbs_license"><![CDATA[License]]></string>
+    <string name="_bx_payment_grid_column_title_sbs_amount"><![CDATA[Amount]]></string>
+    <string name="_bx_payment_grid_column_title_sbs_provider"><![CDATA[Provider]]></string>
+    <string name="_bx_payment_grid_column_title_sbs_status"><![CDATA[Status]]></string>
+    <string name="_bx_payment_grid_column_title_sbs_date"><![CDATA[Date]]></string>
+    <string name="_bx_payment_grid_column_title_sbs_date_add"><![CDATA[Created]]></string>
+    <string name="_bx_payment_grid_column_title_sbs_date_next"><![CDATA[Next Payment]]></string>
+    <string name="_bx_payment_grid_column_title_crts_vendor_id"><![CDATA[Vendor]]></string>
+    <string name="_bx_payment_grid_column_title_crts_items_count"><![CDATA[Count]]></string>
+    <string name="_bx_payment_grid_column_title_crts_items_price"><![CDATA[Price]]></string>
+    <string name="_bx_payment_grid_column_title_crt_title"><![CDATA[Product]]></string>
+    <string name="_bx_payment_grid_column_title_crt_description"><![CDATA[Description]]></string>
+    <string name="_bx_payment_grid_column_title_crt_quantity"><![CDATA[Quantity]]></string>
+    <string name="_bx_payment_grid_column_title_crt_price"><![CDATA[Price]]></string>
+    <string name="_bx_payment_grid_column_title_cms_caption"><![CDATA[Caption]]></string>
+    <string name="_bx_payment_grid_column_title_cms_description"><![CDATA[Description]]></string>
+    <string name="_bx_payment_grid_column_title_cms_acl_id"><![CDATA[Membership]]></string>
+    <string name="_bx_payment_grid_column_title_cms_percentage"><![CDATA[Percentage]]></string>
+    <string name="_bx_payment_grid_column_title_cms_installment"><![CDATA[Installment]]></string>
+    <string name="_bx_payment_grid_column_title_inv_commissionaire_id"><![CDATA[Commissionaire]]></string>
+    <string name="_bx_payment_grid_column_title_inv_committent_id"><![CDATA[Committent]]></string>
+    <string name="_bx_payment_grid_column_title_inv_name"><![CDATA[Name]]></string>
+    <string name="_bx_payment_grid_column_title_inv_period_start"><![CDATA[Period start]]></string>
+    <string name="_bx_payment_grid_column_title_inv_period_end"><![CDATA[Period end]]></string>
+    <string name="_bx_payment_grid_column_title_inv_amount"><![CDATA[Amount]]></string>
+    <string name="_bx_payment_grid_column_title_inv_date_issue"><![CDATA[Issue date]]></string>
+    <string name="_bx_payment_grid_column_title_inv_date_due"><![CDATA[Due date]]></string>
+    <string name="_bx_payment_grid_column_title_inv_status"><![CDATA[Status]]></string>
+
+    <string name="_bx_payment_grid_action_title_ods_add"><![CDATA[Manual Order]]></string>
+    <string name="_bx_payment_grid_action_title_ods_cancel"><![CDATA[Cancel]]></string>
+    <string name="_bx_payment_grid_action_title_ods_process"><![CDATA[Process]]></string>
+    <string name="_bx_payment_grid_action_title_ods_view_order"><![CDATA[View]]></string>
+    <string name="_bx_payment_grid_action_title_sbs_actions"><![CDATA[Actions]]></string>
+    <string name="_bx_payment_grid_action_title_sbs_view_order"><![CDATA[View]]></string>
+    <string name="_bx_payment_grid_action_title_sbs_cancel"><![CDATA[Cancel]]></string>
+    <string name="_bx_payment_grid_action_title_sbs_delete"><![CDATA[Remove]]></string>
+    <string name="_bx_payment_grid_action_title_crts_delete"><![CDATA[Delete]]></string>
+    <string name="_bx_payment_grid_action_title_crts_continue"><![CDATA[Continue to checkout]]></string>
+    <string name="_bx_payment_grid_action_title_crt_checkout"><![CDATA[Checkout with {0}]]></string>
+    <string name="_bx_payment_grid_action_title_crt_delete"><![CDATA[Delete]]></string>
+    <string name="_bx_payment_grid_action_title_cms_add"><![CDATA[Add]]></string>
+    <string name="_bx_payment_grid_action_title_cms_edit"><![CDATA[Edit]]></string>
+    <string name="_bx_payment_grid_action_title_cms_delete"><![CDATA[Delete]]></string>
+    <string name="_bx_payment_grid_action_title_inv_edit"><![CDATA[Edit]]></string>
+    <string name="_bx_payment_grid_action_title_inv_delete"><![CDATA[Delete]]></string>
+    <string name="_bx_payment_grid_action_title_inv_pay"><![CDATA[Pay]]></string>
+
+    <string name="_bx_payment_popup_title_ods_order_subscription_view"><![CDATA[Subscription]]></string>
+    <string name="_bx_payment_popup_title_ods_order_subscription_get_details"><![CDATA[Subscription Details]]></string>
+    <string name="_bx_payment_popup_title_ods_order_subscription_change_details"><![CDATA[Change Subscription Details]]></string>
+    <string name="_bx_payment_popup_title_ods_order_subscription_get_billing"><![CDATA[Billing Information]]></string>
+    <string name="_bx_payment_popup_title_ods_order_subscription_change_billing"><![CDATA[Change Billing Information]]></string>
+    <string name="_bx_payment_popup_title_ods_order_history_view"><![CDATA[Order]]></string>
+    <string name="_bx_payment_popup_title_ods_order_pending_view"><![CDATA[Pending Order]]></string>
+    <string name="_bx_payment_popup_title_ods_order_pending_process"><![CDATA[Process Pending Order]]></string>
+    <string name="_bx_payment_popup_title_ods_order_processed_view"><![CDATA[Processed Order]]></string>
+    <string name="_bx_payment_popup_title_ods_order_processed_add"><![CDATA[Manual Order]]></string>
+    <string name="_bx_payment_popup_title_crd_providers_select"><![CDATA[Select Payment Method]]></string>
+    <string name="_bx_payment_popup_title_cms_add"><![CDATA[Add Commission]]></string>
+    <string name="_bx_payment_popup_title_cms_edit"><![CDATA[Edit Commission]]></string>
+    <string name="_bx_payment_popup_title_inv_edit"><![CDATA[Edit Invoice]]></string>
+
+    <!-- FORMS -->
+    <string name="_bx_payment_form_cart_input_do_delete"><![CDATA[Delete]]></string>
+    <string name="_bx_payment_form_cart_input_do_checkout"><![CDATA[Checkout]]></string>
+    <string name="_bx_payment_form_details_input_do_submit"><![CDATA[Save]]></string>
+
+    <string name="_bx_payment_form_pendings_form"><![CDATA[Pendings Form]]></string>
+    <string name="_bx_payment_form_processed_form"><![CDATA[Processed Form]]></string>
+    <string name="_bx_payment_form_pendings_display_process"><![CDATA[Process Pending Display]]></string>
+    <string name="_bx_payment_form_processed_display_add"><![CDATA[Add Processed Display]]></string>
+    <string name="_bx_payment_form_pendings_input_id_sys"><![CDATA[ID]]></string>
+    <string name="_bx_payment_form_pendings_input_seller_id_sys"><![CDATA[Seller ID]]></string>
+    <string name="_bx_payment_form_pendings_input_order_sys"><![CDATA[Order]]></string>
+    <string name="_bx_payment_form_pendings_input_order"><![CDATA[Order]]></string>
+    <string name="_bx_payment_form_pendings_input_order_err"><![CDATA[You need to fill in order number here.]]></string>
+    <string name="_bx_payment_form_pendings_input_process_sys"><![CDATA[Process]]></string>
+    <string name="_bx_payment_form_pendings_input_process"><![CDATA[Process]]></string>
+    <string name="_bx_payment_form_pendings_input_cancel_sys"><![CDATA[Cancel]]></string>
+    <string name="_bx_payment_form_pendings_input_cancel"><![CDATA[Cancel]]></string>
+    <string name="_bx_payment_form_processed_input_seller_id_sys"><![CDATA[Seller ID]]></string>
+    <string name="_bx_payment_form_processed_input_client_id_sys"><![CDATA[Client ID]]></string>
+    <string name="_bx_payment_form_processed_input_client_sys"><![CDATA[Client]]></string>
+    <string name="_bx_payment_form_processed_input_client"><![CDATA[Client]]></string>
+    <string name="_bx_payment_form_processed_input_client_err"><![CDATA[You need to enter a name of an existed member here.]]></string>
+    <string name="_bx_payment_form_processed_input_order_sys"><![CDATA[Order]]></string>
+    <string name="_bx_payment_form_processed_input_order"><![CDATA[Order]]></string>
+    <string name="_bx_payment_form_processed_input_order_err"><![CDATA[You need to fill in order number here.]]></string>
+    <string name="_bx_payment_form_processed_input_module_id_sys"><![CDATA[Module]]></string>
+    <string name="_bx_payment_form_processed_input_module_id"><![CDATA[Module]]></string>
+    <string name="_bx_payment_form_processed_input_module_id_err"><![CDATA[You need to select a module here.]]></string>
+    <string name="_bx_payment_form_processed_input_items_sys"><![CDATA[Items]]></string>
+    <string name="_bx_payment_form_processed_input_items"><![CDATA[Items]]></string>
+    <string name="_bx_payment_form_processed_input_items_err"><![CDATA[You need to select at least one item from the list here.]]></string>
+    <string name="_bx_payment_form_processed_input_add"><![CDATA[Add]]></string>
+    <string name="_bx_payment_form_processed_input_add_sys"><![CDATA[Add]]></string>
+    <string name="_bx_payment_form_processed_input_cancel"><![CDATA[Cancel]]></string>
+    <string name="_bx_payment_form_processed_input_cancel_sys"><![CDATA[Cancel]]></string>
+    
+    <string name="_bx_payment_form_commissions_form"><![CDATA[Commissions Form]]></string>
+    <string name="_bx_payment_form_commissions_display_add"><![CDATA[Add Commission Display]]></string>
+    <string name="_bx_payment_form_commissions_display_edit"><![CDATA[Edit Commission Display]]></string>
+    <string name="_bx_payment_form_commissions_input_caption_sys"><![CDATA[Caption]]></string>
+    <string name="_bx_payment_form_commissions_input_caption"><![CDATA[Caption]]></string>
+    <string name="_bx_payment_form_commissions_input_caption_err"><![CDATA[This field is essential. Please, fill it in.]]></string>
+    <string name="_bx_payment_form_commissions_input_description_sys"><![CDATA[Description]]></string>
+    <string name="_bx_payment_form_commissions_input_description"><![CDATA[Description]]></string>
+    <string name="_bx_payment_form_commissions_input_acl_id_sys"><![CDATA[Membership Level]]></string>
+    <string name="_bx_payment_form_commissions_input_acl_id"><![CDATA[Membership Level]]></string>
+    <string name="_bx_payment_form_commissions_input_percentage_sys"><![CDATA[Percentage]]></string>
+    <string name="_bx_payment_form_commissions_input_percentage"><![CDATA[Percentage]]></string>
+    <string name="_bx_payment_form_commissions_input_installment_sys"><![CDATA[Installment]]></string>
+    <string name="_bx_payment_form_commissions_input_installment"><![CDATA[Installment]]></string>
+    <string name="_bx_payment_form_commissions_input_submit_sys"><![CDATA[Submit]]></string>
+    <string name="_bx_payment_form_commissions_input_submit"><![CDATA[Submit]]></string>
+    <string name="_bx_payment_form_commissions_input_cancel_sys"><![CDATA[Cancel]]></string>
+    <string name="_bx_payment_form_commissions_input_cancel"><![CDATA[Cancel]]></string>
+    
+    <string name="_bx_payment_form_invoices_form"><![CDATA[Invoices Form]]></string>
+    <string name="_bx_payment_form_invoices_display_edit"><![CDATA[Edit Invoice Display]]></string>
+    <string name="_bx_payment_form_invoices_input_amount_sys"><![CDATA[Amount]]></string>
+    <string name="_bx_payment_form_invoices_input_amount"><![CDATA[Amount]]></string>
+    <string name="_bx_payment_form_invoices_input_amount_err"><![CDATA[This field is essential. Please, fill it in.]]></string>
+    <string name="_bx_payment_form_invoices_input_date_due_sys"><![CDATA[Due date]]></string>
+    <string name="_bx_payment_form_invoices_input_date_due"><![CDATA[Due date]]></string>
+    <string name="_bx_payment_form_invoices_input_date_due_err"><![CDATA[This field is essential. Please, fill it in.]]></string>
+    <string name="_bx_payment_form_invoices_input_status_sys"><![CDATA[Status]]></string>
+    <string name="_bx_payment_form_invoices_input_status"><![CDATA[Status]]></string>
+    <string name="_bx_payment_form_invoices_input_submit_sys"><![CDATA[Submit]]></string>
+    <string name="_bx_payment_form_invoices_input_submit"><![CDATA[Submit]]></string>
+    <string name="_bx_payment_form_invoices_input_cancel_sys"><![CDATA[Cancel]]></string>
+    <string name="_bx_payment_form_invoices_input_cancel"><![CDATA[Cancel]]></string>
+
+    <!-- Predefined Values -->
+    <string name="_bx_payment_pre_lists_currencies"><![CDATA[Currencies]]></string>
+
+    <!-- ACL -->
+    <string name="_bx_payment_acl_action_purchase"><![CDATA[Purchase]]></string>
+    <string name="_bx_payment_acl_action_sell"><![CDATA[Sell]]></string>
+    <string name="_bx_payment_acl_action_manage_any_purchase"><![CDATA[Manage Any Purchase]]></string>
+
+    <!-- EMAIL TEMPLATES -->
+    <string name="_bx_payment_et_txt_name_paid_need_join"><![CDATA[Paid and need to join.]]></string>
+    <string name="_bx_payment_et_txt_subject_paid_need_join"><![CDATA[Payment was processed.]]></string>
+    <string name="_bx_payment_et_txt_body_paid_need_join"><![CDATA[{email_header}
+<p>Hello, {RealName}.</p>
+<p>Your payment was processed. If you did not fill in the join form yet, then you may do it using the following link.</p>
+<p><a href="{JoinLink}">Join Now</a></p>
+{email_footer}]]></string>
+
+    <string name="_bx_payment_et_txt_name_cancelation_request"><![CDATA[Subscription cancellation request.]]></string>
+    <string name="_bx_payment_et_txt_subject_cancelation_request"><![CDATA[Subscription cancellation request.]]></string>
+    <string name="_bx_payment_et_txt_body_cancelation_request"><![CDATA[{email_header}
+<p>Hello,</p>
+<p>A user with {profile_name} profile name requested cancellation for a subscription.</p>
+<p>Subscription info:<br />ID: {sibscription_id}<br />Customer: {sibscription_customer}<br />Date: {sibscription_date}</p>
+{email_footer}]]></string>
+
+    <string name="_bx_payment_et_txt_name_expiration_notification_seller"><![CDATA[Subscription expiration notification (for seller).]]></string>
+    <string name="_bx_payment_et_txt_subject_expiration_notification_seller"><![CDATA[Subscription expiration notification.]]></string>
+    <string name="_bx_payment_et_txt_body_expiration_notification_seller"><![CDATA[{email_header}
+<p>Hello,</p>
+<p>A subscription purchased by '{profile_name}' expired.</p>
+<p>Subscription info:<br />ID: {sibscription_id}<br />Customer: {sibscription_customer}<br />Date: {sibscription_date}</p>
+<p><b>Note</b>. An associated data will be removed shortly.</p>
+{email_footer}]]></string>
+
+    <string name="_bx_payment_et_txt_name_expiration_notification_client"><![CDATA[Subscription expiration notification (for client).]]></string>
+    <string name="_bx_payment_et_txt_subject_expiration_notification_client"><![CDATA[Subscription expiration notification.]]></string>
+    <string name="_bx_payment_et_txt_body_expiration_notification_client"><![CDATA[{email_header}
+<p>Hello,</p>
+<p>Your subscription purchased from '{profile_name}' expired.</p>
+<p>Subscription info:<br />ID: {sibscription_id}<br />Customer: {sibscription_customer}<br />Date: {sibscription_date}</p>
+<p><b>Note</b>. An associated data will be removed shortly.</p>
+{email_footer}]]></string>
+
+    <string name="_bx_payment_et_txt_name_expiring_notification_committent"><![CDATA[Invoice expiring notification.]]></string>
+    <string name="_bx_payment_et_txt_subject_expiring_notification_committent"><![CDATA[Invoice expiring notification.]]></string>
+    <string name="_bx_payment_et_txt_body_expiring_notification_committent"><![CDATA[{email_header}
+<p>Hello,</p>
+<p>Your invoice '{invoice}' is expiring in '{days}' day(s).</p>
+<p>Invoice info:<br />Period start: {period_start}<br />Period end: {period_end}<br />Issue date: {date_issue}<br />Due date: {date_due}</p>
+{email_footer}]]></string>
+
+    <string name="_bx_payment_et_txt_name_overdue_notification_committent"><![CDATA[Overdue invoice notification.]]></string>
+    <string name="_bx_payment_et_txt_subject_overdue_notification_committent"><![CDATA[Overdue invoice notification.]]></string>
+    <string name="_bx_payment_et_txt_body_overdue_notification_committent"><![CDATA[{email_header}
+<p>Hello,</p>
+<p>Your invoice '{invoice}' is overdue '{date_due}'.</p>
+<p>Invoice info:<br />Period start: {period_start}<br />Period end: {period_end}<br />Issue date: {date_issue}<br />Due date: {date_due}</p>
+{email_footer}]]></string>
+
+	<!-- MESSAGES, WARNINGS and ERRORS -->
+	<string name="_bx_payment_msg_no_results"><![CDATA[Empty]]></string>
+	<string name="_bx_payment_msg_redirecting"><![CDATA[Redirecting... Please wait.]]></string>
+	<string name="_bx_payment_msg_item_added"><![CDATA[The item was successfully added to your shopping cart.]]></string>
+	<string name="_bx_payment_msg_item_deleted"><![CDATA[The item was successfully deleted from your shopping cart.]]></string>
+	<string name="_bx_payment_msg_successfully_performed"><![CDATA[The action was successfully performed.]]></string>
+	<string name="_bx_payment_msg_successfully_processed_free"><![CDATA[Free item was successfully processed]]></string>
+	<string name="_bx_payment_msg_cancelation_request_sent"><![CDATA[Cancellation request was sent. Please wait.]]></string>
+        <string name="_bx_payment_msg_confirm_cancelation"><![CDATA[Are you sure you want to cancel your subscription?]]></string>
+        <string name="_bx_payment_msg_single_seller"><![CDATA[Single seller mode is enabled. <a href="{0}">Got to</a> single shopping cart.]]></string>
+	<string name="_bx_payment_err_access_db"><![CDATA[Database access error.]]></string>
+	<string name="_bx_payment_err_cannot_validate"><![CDATA[Can't connect to remote host for validation.]]></string>
+	<string name="_bx_payment_err_empty_items"><![CDATA[There are no items selected.]]></string>
+	<string name="_bx_payment_err_empty_order"><![CDATA[The order is empty.]]></string>
+	<string name="_bx_payment_err_inactive_vendor"><![CDATA[The vendor status is not active.]]></string>
+	<string name="_bx_payment_err_incorrect_provider"><![CDATA[Incorrect or unavailable payment provider.]]></string>
+	<string name="_bx_payment_err_not_accept_payments"><![CDATA[The vendor does not accept payments.]]></string>
+	<string name="_bx_payment_err_nothing_selected"><![CDATA[You need to select at least one item.]]></string>
+	<string name="_bx_payment_err_self_purchase"><![CDATA[Buying from your own store is not permitted.]]></string>
+	<string name="_bx_payment_err_required_login"><![CDATA[You need to login.]]></string>
+	<string name="_bx_payment_err_unknown_vendor"><![CDATA[Unknown vendor.]]></string>
+	<string name="_bx_payment_err_wrong_data"><![CDATA[Incorrect input data.]]></string>
+	<string name="_bx_payment_err_not_found_pending"><![CDATA[Pending order was not found.]]></string>
+	<string name="_bx_payment_err_cannot_perform"><![CDATA[Cannot perform the action. Please report.]]></string>
+	<string name="_bx_payment_err_wrong_quantity"><![CDATA[Incorrect quantity specified.]]></string>
+	<string name="_bx_payment_err_already_processed"><![CDATA[This payment has already processed.]]></string>
+	<string name="_bx_payment_err_already_registered"><![CDATA[Subscription with the same data was already registered.]]></string>
+        <string name="_bx_payment_err_not_supported"><![CDATA[Operation isn't supported.]]></string>
+
+	<!-- Other -->
+	<string name="_bx_payment_txt_add_to_cart"><![CDATA[Add to Cart]]></string>
+	<string name="_bx_payment_txt_subscribe"><![CDATA[Subscribe]]></string>
+	<string name="_bx_payment_txt_payment_to"><![CDATA[Payment to {0}]]></string>
+	<string name="_bx_payment_txt_payment_to_for"><![CDATA[Payment to {0} for:]]></string>
+	<string name="_bx_payment_txt_checkout_to"><![CDATA[Continue checkouting to {0}]]></string>
+	<string name="_bx_payment_txt_checkout_with"><![CDATA[Checkout with {0}]]></string>
+	<string name="_bx_payment_txt_client"><![CDATA[Client]]></string>
+        <string name="_bx_payment_txt_license"><![CDATA[License]]></string>
+	<string name="_bx_payment_txt_seller"><![CDATA[Seller]]></string>
+        <string name="_bx_payment_txt_author"><![CDATA[Author]]></string>
+	<string name="_bx_payment_txt_order"><![CDATA[Order ID]]></string>
+	<string name="_bx_payment_txt_processed_with"><![CDATA[Processed with]]></string>
+	<string name="_bx_payment_txt_message"><![CDATA[Result]]></string>
+	<string name="_bx_payment_txt_date"><![CDATA[Date]]></string>
+	<string name="_bx_payment_txt_products"><![CDATA[Products]]></string>
+	<string name="_bx_payment_txt_buyer_name_mask"><![CDATA[{0} {1}]]></string>
+	<string name="_bx_payment_txt_none"><![CDATA[none]]></string>
+	<string name="_bx_payment_txt_name_manual"><![CDATA[Manually]]></string>
+	<string name="_bx_payment_txt_yes"><![CDATA[Yes]]></string>
+	<string name="_bx_payment_txt_no"><![CDATA[No]]></string>
+        <string name="_bx_payment_txt_unsubscribe_yes"><![CDATA[Cancel automatically]]></string>
+        <string name="_bx_payment_txt_unsubscribe_no"><![CDATA[Do not cancel]]></string>
+        <string name="_bx_payment_txt_all_authors"><![CDATA[All Authors]]></string>
+        <string name="_bx_payment_txt_all_clients"><![CDATA[All Clients]]></string>
+        <string name="_bx_payment_txt_all_modules"><![CDATA[All Modules]]></string>
+        <string name="_bx_payment_txt_all_items"><![CDATA[All Items]]></string>
+        <string name="_bx_payment_txt_status_scheduled"><![CDATA[Scheduled]]></string>
+        <string name="_bx_payment_txt_status_trial"><![CDATA[Trial]]></string>
+        <string name="_bx_payment_txt_status_active"><![CDATA[Active]]></string>
+        <string name="_bx_payment_txt_status_paid"><![CDATA[Paid]]></string>
+        <string name="_bx_payment_txt_status_unpaid"><![CDATA[Unpaid]]></string>
+        <string name="_bx_payment_txt_status_overdue"><![CDATA[Overdue]]></string>
+        <string name="_bx_payment_txt_status_paused"><![CDATA[Paused]]></string>
+        <string name="_bx_payment_txt_status_canceled"><![CDATA[Canceled]]></string>
+        <string name="_bx_payment_txt_status_unknown"><![CDATA[Unknown]]></string>
+        <string name="_bx_payment_txt_invoice_title"><![CDATA[Invoice {0} from {1}]]></string>
+        <string name="_bx_payment_txt_invoice_description"><![CDATA[For a period between {0} and {1}]]></string>
+
+        <!-- Credits payment provider -->
+	<string name="_bx_payment_cdt_cpt"><![CDATA[Credits]]></string>
+	<string name="_bx_payment_cdt_dsc"><![CDATA[Credits payment provider]]></string>
+	<string name="_bx_payment_cdt_active_cpt"><![CDATA[Active]]></string>
+	<string name="_bx_payment_cdt_active_dsc"><![CDATA[Activate(Deactivate) provider]]></string>
+        <string name="_bx_payment_cdt_msg_charged"><![CDATA[Payment was successfully processed.]]></string>
+        <string name="_bx_payment_cdt_msg_subscribed"><![CDATA[Thank you! Subscription created. Please, check your email for further instructions.]]></string>
+        <string name="_bx_payment_cdt_err_not_available"><![CDATA[Checkout with Credits isn't available now.]]></string>
+        <string name="_bx_payment_cdt_err_wrong_transaction"><![CDATA[Transaction verification failed.]]></string>
+        <string name="_bx_payment_txt_name_credits"><![CDATA[Credits]]></string>
+	<string name="_bx_payment_txt_cart_credits"><![CDATA[Credits]]></string>
+
+	<!-- PayPal payment provider -->
+	<string name="_bx_payment_pp_cpt"><![CDATA[PayPal]]></string>
+	<string name="_bx_payment_pp_dsc"><![CDATA[PayPal payment provider]]></string>
+	<string name="_bx_payment_pp_active_cpt"><![CDATA[Active]]></string>
+	<string name="_bx_payment_pp_active_dsc"><![CDATA[Activate(Deactivate) provider]]></string>
+	<string name="_bx_payment_pp_mode_cpt"><![CDATA[Mode]]></string>
+	<string name="_bx_payment_pp_mode_dsc"><![CDATA[Mode to process payments]]></string>
+	<string name="_bx_payment_pp_mode_live"><![CDATA[live]]></string>
+	<string name="_bx_payment_pp_mode_test"><![CDATA[test]]></string>
+	<string name="_bx_payment_pp_business_cpt"><![CDATA[Business]]></string>
+	<string name="_bx_payment_pp_business_dsc"><![CDATA[Business email address]]></string>
+	<string name="_bx_payment_pp_prc_type_cpt"><![CDATA[Process type]]></string>
+	<string name="_bx_payment_pp_prc_type_dsc"><![CDATA[The type in which data is to be processed]]></string>
+	<string name="_bx_payment_pp_prc_type_direct"><![CDATA[direct]]></string>
+	<string name="_bx_payment_pp_prc_type_pdt"><![CDATA[PDT]]></string>
+	<string name="_bx_payment_pp_prc_type_ipn"><![CDATA[IPN]]></string>
+	<string name="_bx_payment_pp_token_cpt"><![CDATA[Identity token]]></string>
+	<string name="_bx_payment_pp_token_dsc"><![CDATA[Identity token]]></string>
+	<string name="_bx_payment_pp_sandbox_cpt"><![CDATA[Sandbox]]></string>
+	<string name="_bx_payment_pp_sandbox_dsc"><![CDATA[Sandbox email address]]></string>
+	<string name="_bx_payment_pp_return_data_url_cpt"><![CDATA[Data return URL]]></string>
+	<string name="_bx_payment_pp_err_no_data_given"><![CDATA[No data given.]]></string>
+	<string name="_bx_payment_pp_err_not_completed"><![CDATA[Payment is not completed.]]></string>
+	<string name="_bx_payment_pp_err_wrong_vendor"><![CDATA[Wrong vendor.]]></string>
+	<string name="_bx_payment_pp_err_wrong_business"><![CDATA[Wrong receiver email.]]></string>
+	<string name="_bx_payment_pp_err_wrong_transaction"><![CDATA[Transaction verification failed.]]></string>
+	<string name="_bx_payment_pp_err_wrong_verification_status"><![CDATA[No verification status received.]]></string>
+	<string name="_bx_payment_pp_err_wrong_amount"><![CDATA[Wrong amount.]]></string>
+	<string name="_bx_payment_pp_err_wrong_custom_data"><![CDATA[Incorrect custom data.]]></string>
+	<string name="_bx_payment_pp_msg_verified"><![CDATA[Payment was successfully processed.]]></string>
+	<string name="_bx_payment_txt_name_paypal"><![CDATA[PayPal]]></string>
+	<string name="_bx_payment_txt_cart_paypal"><![CDATA[PayPal]]></string>
+
+	<!-- 2Checkout payment provider -->
+	<string name="_bx_payment_2co_cpt"><![CDATA[2Checkout]]></string>
+	<string name="_bx_payment_2co_dsc"><![CDATA[2Checkout payment provider]]></string>
+	<string name="_bx_payment_2co_active_cpt"><![CDATA[Active]]></string>
+	<string name="_bx_payment_2co_active_dsc"><![CDATA[Activate(Deactivate) provider]]></string>
+	<string name="_bx_payment_2co_mode_cpt"><![CDATA[Mode]]></string>
+	<string name="_bx_payment_2co_mode_dsc"><![CDATA[Mode to process payments]]></string>
+	<string name="_bx_payment_2co_mode_live"><![CDATA[live]]></string>
+	<string name="_bx_payment_2co_mode_test"><![CDATA[test]]></string>
+	<string name="_bx_payment_2co_account_id_cpt"><![CDATA[Account number]]></string>
+	<string name="_bx_payment_2co_account_id_dsc"><![CDATA[Your 2Checkout vendor account number]]></string>
+	<string name="_bx_payment_2co_payment_method_cpt"><![CDATA[Payment Method]]></string>
+	<string name="_bx_payment_2co_payment_method_dsc"><![CDATA[This will set the default selection on the payment method step during the checkout process]]></string>
+	<string name="_bx_payment_2co_payment_method_cc"><![CDATA[Credit Card(CC)]]></string>
+	<string name="_bx_payment_2co_payment_method_ppi"><![CDATA[PayPal(PPI)]]></string>
+	<string name="_bx_payment_2co_secret_word_cpt"><![CDATA[Secret Word]]></string>
+	<string name="_bx_payment_2co_secret_word_dsc"><![CDATA[Secret word is used to calculate a check hash]]></string>
+	<string name="_bx_payment_2co_return_data_url_cpt"><![CDATA[Data return URL]]></string>
+	<string name="_bx_payment_2co_err_no_vendor_given"><![CDATA[Unknown vendor]]></string>
+	<string name="_bx_payment_2co_err_no_data_given"><![CDATA[No data given.]]></string>
+	<string name="_bx_payment_2co_err_wrong_key"><![CDATA[Check key is incorrect.]]></string>
+	<string name="_bx_payment_2co_err_wrong_payment"><![CDATA[Wrong payment.]]></string>
+	<string name="_bx_payment_2co_err_already_processed"><![CDATA[This payment has already processed]]></string>
+	<string name="_bx_payment_2co_msg_verified"><![CDATA[Successfully verified.]]></string>
+	<string name="_bx_payment_txt_name_2checkout"><![CDATA[2Checkout]]></string>
+	<string name="_bx_payment_txt_cart_2checkout"><![CDATA[2Checkout]]></string>
+
+	<!-- BitPay payment provider -->
+	<string name="_bx_payment_bp_cpt"><![CDATA[BitPay]]></string>
+	<string name="_bx_payment_bp_dsc"><![CDATA[BitPay payment provider]]></string>
+	<string name="_bx_payment_bp_active_cpt"><![CDATA[Active]]></string>
+	<string name="_bx_payment_bp_active_dsc"><![CDATA[Activate(Deactivate) provider]]></string>
+	<string name="_bx_payment_bp_active_err"><![CDATA[You should have SSL certificate (HTTPS connection) to activate and use BitPay on your site.]]></string>
+	<string name="_bx_payment_bp_api_key_cpt"><![CDATA[API Key]]></string>
+	<string name="_bx_payment_bp_api_key_dsc"><![CDATA[Your merchant BitPay API Access key]]></string>
+	<string name="_bx_payment_bp_transaction_speed_cpt"><![CDATA[Transaction speed]]></string>
+	<string name="_bx_payment_bp_transaction_speed_dsc"><![CDATA[Determines when an invoice is confirmed]]></string>
+	<string name="_bx_payment_bp_transaction_speed_high"><![CDATA[High]]></string>
+	<string name="_bx_payment_bp_transaction_speed_medium"><![CDATA[Medium]]></string>
+	<string name="_bx_payment_bp_transaction_speed_low"><![CDATA[Low]]></string>
+	<string name="_bx_payment_bp_full_notifications_cpt"><![CDATA[Enable full notifications]]></string>
+	<string name="_bx_payment_bp_full_notifications_dsc"><![CDATA[When enabled notifications will be sent on every status change, otherwise when an invoice is confirmed only.]]></string>
+	<string name="_bx_payment_bp_notification_email_cpt"><![CDATA[Notification Email]]></string>
+	<string name="_bx_payment_bp_notification_email_dsc"><![CDATA[Email where invoice update notifications will be sent. Leave empty to disable.]]></string>
+	<string name="_bx_payment_bp_err_posdata_exceed_limit"><![CDATA[The value of posData exceeds limit. Contact with administrator.]]></string>
+	<string name="_bx_payment_bp_err_no_data_given"><![CDATA[No data given.]]></string>
+	<string name="_bx_payment_bp_err_no_vendor_given"><![CDATA[Unknown vendor.]]></string>
+	<string name="_bx_payment_bp_err_incorrect_data"><![CDATA[Incorrect order data.]]></string>
+	<string name="_bx_payment_bp_err_wrong_amount"><![CDATA[Wrong payment amount.]]></string>
+	<string name="_bx_payment_bp_err_already_processed"><![CDATA[This payment has already processed.]]></string>
+	<string name="_bx_payment_bp_err_no_confirmation_given"><![CDATA[Payment is waiting for full confirmation from the Bitcoin network.]]></string>
+	<string name="_bx_payment_bp_msg_checkout_finished"><![CDATA[A payment has been confirmed. Once the transaction is fully confirmed on the Bitcoin network, the payment will be processed automatically here. Then the purchased product(s) will be displayed in shopping cart history.<br /><b>Note.</b> If it doesn't happen for some reason, you need to contact with product\'s vendor and provide him with your payment's details. He'll be able to process payment manually if the payment was received.]]></string>
+	<string name="_bx_payment_txt_name_bitpay"><![CDATA[BitPay]]></string>
+	<string name="_bx_payment_txt_cart_bitpay"><![CDATA[BitPay]]></string>
+
+	<!-- Chargebee payment provider -->
+	<string name="_bx_payment_cbee_cpt"><![CDATA[Chargebee]]></string>
+	<string name="_bx_payment_cbee_dsc"><![CDATA[If enabled, users can checkout using Chargebee's hosted pages.]]></string>
+	<string name="_bx_payment_cbee_v3_cpt"><![CDATA[Chargebee]]></string>
+    <string name="_bx_payment_cbee_v3_dsc"><![CDATA[If enabled, users can checkout using Chargebee's drop-in script.]]></string>
+	<string name="_bx_payment_cbee_active_cpt"><![CDATA[Active]]></string>
+	<string name="_bx_payment_cbee_active_dsc"><![CDATA[Activate(Deactivate) provider. Note. It's recommended to use SSL for better payment processing.]]></string>
+        <string name="_bx_payment_cbee_hidden_cpt"><![CDATA[Hidden]]></string>
+	<string name="_bx_payment_cbee_hidden_dsc"><![CDATA[Hide provider if you don't want to accept new payments but already have active subscriptions.]]></string>
+	<string name="_bx_payment_cbee_mode_cpt"><![CDATA[Mode]]></string>
+	<string name="_bx_payment_cbee_mode_dsc"><![CDATA[Mode to process payments]]></string>
+	<string name="_bx_payment_cbee_mode_live"><![CDATA[live]]></string>
+	<string name="_bx_payment_cbee_mode_test"><![CDATA[test]]></string>
+	<string name="_bx_payment_cbee_live_site_cpt"><![CDATA[Site (live)]]></string>
+	<string name="_bx_payment_cbee_live_site_dsc"><![CDATA[Your site name registered in Chargebee for 'live' mode]]></string>
+	<string name="_bx_payment_cbee_live_api_key_cpt"><![CDATA[API Key (live)]]></string>
+	<string name="_bx_payment_cbee_live_api_key_dsc"><![CDATA[Your Chargebee API Access key for 'live' mode]]></string>
+	<string name="_bx_payment_cbee_test_site_cpt"><![CDATA[Site (test)]]></string>
+	<string name="_bx_payment_cbee_test_site_dsc"><![CDATA[Your site name registered in Chargebee for 'test' mode]]></string>
+	<string name="_bx_payment_cbee_test_api_key_cpt"><![CDATA[API Key (test)]]></string>
+	<string name="_bx_payment_cbee_test_api_key_dsc"><![CDATA[Your Chargebee API Access key for 'test' mode]]></string>
+	<string name="_bx_payment_cbee_check_amount_cpt"><![CDATA[Enable amount checking]]></string>
+	<string name="_bx_payment_cbee_check_amount_dsc"><![CDATA[Enable amount checking for Chargebee Webhooks (recomended). However checking should be disabled when discounts and coupons are used.]]></string>
+	<string name="_bx_payment_cbee_ssl_cpt"><![CDATA[Enable SSL]]></string>
+	<string name="_bx_payment_cbee_ssl_dsc"><![CDATA[Enable SSL connection to communicate with Chargebee. Note. URLs below will be updated after saving.]]></string>
+        <string name="_bx_payment_cbee_cancellation_email_cpt"><![CDATA[Cancellation Email]]></string>
+        <string name="_bx_payment_cbee_expiration_email_cpt"><![CDATA[Expiration Email]]></string>
+	<string name="_bx_payment_cbee_return_data_url_cpt"><![CDATA[Data return URL]]></string>
+	<string name="_bx_payment_cbee_notify_url_cpt"><![CDATA[Webhooks URL]]></string>
+	<string name="_bx_payment_cbee_msg_subscribed"><![CDATA[Thank you! Subscription created. Please, check your email for further instructions.]]></string>
+	<string name="_bx_payment_cbee_txt_checkout_with_single"><![CDATA[Checkout with {0}]]></string>
+    <string name="_bx_payment_cbee_txt_checkout_with_recurring"><![CDATA[Checkout with {0}]]></string>
+    <string name="_bx_payment_cbee_menu_item_title_manager"><![CDATA[Self-serve Portal]]></string>
+	<string name="_bx_payment_txt_name_chargebee"><![CDATA[Chargebee]]></string>
+	<string name="_bx_payment_txt_name_chargebee_v3"><![CDATA[Chargebee]]></string>
+	<string name="_bx_payment_txt_cart_chargebee"><![CDATA[Chargebee]]></string>
+	<string name="_bx_payment_txt_cart_chargebee_v3"><![CDATA[Chargebee]]></string>
+
+	<!-- Recurly payment provider -->
+	<string name="_bx_payment_rcrl_cpt"><![CDATA[Recurly]]></string>
+	<string name="_bx_payment_rcrl_dsc"><![CDATA[Recurly payment provider]]></string>
+	<string name="_bx_payment_rcrl_active_cpt"><![CDATA[Active]]></string>
+	<string name="_bx_payment_rcrl_active_dsc"><![CDATA[Activate(Deactivate) provider.]]></string>
+	<string name="_bx_payment_rcrl_active_err"><![CDATA[You should have SSL certificate (HTTPS connection) to activate and use Recurly on your site.]]></string>
+        <string name="_bx_payment_rcrl_hidden_cpt"><![CDATA[Hidden]]></string>
+	<string name="_bx_payment_rcrl_hidden_dsc"><![CDATA[Hide provider if you don't want to accept new payments but already have active subscriptions.]]></string>
+	<string name="_bx_payment_rcrl_mode_cpt"><![CDATA[Mode]]></string>
+	<string name="_bx_payment_rcrl_mode_dsc"><![CDATA[Mode to process payments]]></string>
+	<string name="_bx_payment_rcrl_mode_live"><![CDATA[live]]></string>
+	<string name="_bx_payment_rcrl_mode_test"><![CDATA[test]]></string>
+	<string name="_bx_payment_rcrl_site_cpt"><![CDATA[Site]]></string>
+	<string name="_bx_payment_rcrl_site_dsc"><![CDATA[Your site name registered in Recurly]]></string>
+	<string name="_bx_payment_rcrl_api_key_private_cpt"><![CDATA[Private API Key]]></string>
+	<string name="_bx_payment_rcrl_api_key_private_dsc"><![CDATA[Your Recurly Private API Access key]]></string>
+	<string name="_bx_payment_rcrl_api_key_public_cpt"><![CDATA[Public API Key]]></string>
+	<string name="_bx_payment_rcrl_api_key_public_dsc"><![CDATA[Your Recurly Public API Access key]]></string>
+	<string name="_bx_payment_rcrl_return_data_url_cpt"><![CDATA[Data return URL]]></string>
+	<string name="_bx_payment_rcrl_notify_url_cpt"><![CDATA[Webhooks URL]]></string>
+	<string name="_bx_payment_rcrl_msg_subscribed"><![CDATA[Thank you! Subscription created. Please, check your email for further instructions.]]></string>
+	<string name="_bx_payment_txt_name_recurly"><![CDATA[Recurly]]></string>
+	<string name="_bx_payment_txt_cart_recurly"><![CDATA[Recurly]]></string>
+
+	<string name="_bx_payment_form_rcrl_card"><![CDATA[Recurly: Card Form]]></string>
+	<string name="_bx_payment_form_rcrl_card_display_add"><![CDATA[Recurly: Add Card Display]]></string>
+	<string name="_bx_payment_form_rcrl_card_input_pending_id_sys"><![CDATA[Pending ID]]></string>
+	<string name="_bx_payment_form_rcrl_card_input_item_sys"><![CDATA[Item]]></string>
+	<string name="_bx_payment_form_rcrl_card_input_token_sys"><![CDATA[Token]]></string>
+	<string name="_bx_payment_form_rcrl_card_input_first_name_sys"><![CDATA[First Name]]></string>
+	<string name="_bx_payment_form_rcrl_card_input_first_name"><![CDATA[First Name]]></string>
+	<string name="_bx_payment_form_rcrl_card_input_first_name_err"><![CDATA[You need to fill in your first name here.]]></string>
+	<string name="_bx_payment_form_rcrl_card_input_last_name_sys"><![CDATA[Last Name]]></string>
+	<string name="_bx_payment_form_rcrl_card_input_last_name"><![CDATA[Last Name]]></string>
+	<string name="_bx_payment_form_rcrl_card_input_last_name_err"><![CDATA[You need to fill in your last name here.]]></string>
+	<string name="_bx_payment_form_rcrl_card_input_email_sys"><![CDATA[Email]]></string>
+	<string name="_bx_payment_form_rcrl_card_input_email"><![CDATA[Email]]></string>
+	<string name="_bx_payment_form_rcrl_card_input_email_err"><![CDATA[You need to fill in your email here.]]></string>
+	<string name="_bx_payment_form_rcrl_card_input_card_number_sys"><![CDATA[Card Number]]></string>
+	<string name="_bx_payment_form_rcrl_card_input_card_number"><![CDATA[Card Number]]></string>
+	<string name="_bx_payment_form_rcrl_card_input_card_number_inf"><![CDATA[16 digits without spaces describing your card number]]></string>
+	<string name="_bx_payment_form_rcrl_card_input_card_expire_sys"><![CDATA[Expiry Date]]></string>
+	<string name="_bx_payment_form_rcrl_card_input_card_expire"><![CDATA[Expiry Date]]></string>
+	<string name="_bx_payment_form_rcrl_card_input_card_expire_month"><![CDATA[Month]]></string>
+	<string name="_bx_payment_form_rcrl_card_input_card_expire_year"><![CDATA[Year]]></string>
+	<string name="_bx_payment_form_rcrl_card_input_card_expire_inf"><![CDATA[Use 'mm yyyy' format]]></string>
+	<string name="_bx_payment_form_rcrl_card_input_card_cvv_sys"><![CDATA[CVV]]></string>
+	<string name="_bx_payment_form_rcrl_card_input_card_cvv"><![CDATA[CVV]]></string>
+	<string name="_bx_payment_form_rcrl_card_input_card_cvv_inf"><![CDATA[Three digits from the back side of your card.]]></string>
+	<string name="_bx_payment_form_rcrl_card_input_submit_sys"><![CDATA[Submit]]></string>
+	<string name="_bx_payment_form_rcrl_card_input_submit"><![CDATA[Submit]]></string>
+	<string name="_bx_payment_form_rcrl_card_input_cancel_sys"><![CDATA[Cancel]]></string>
+	<string name="_bx_payment_form_rcrl_card_input_cancel"><![CDATA[Cancel]]></string>
+	
+	<string name="_bx_payment_popup_title_rcrl_card_add"><![CDATA[Card details]]></string>
+
+	<!-- Stripe payment provider -->
+	<string name="_bx_payment_strp_cpt"><![CDATA[Stripe]]></string>
+	<string name="_bx_payment_strp_dsc"><![CDATA[Stripe payment provider]]></string>
+        <string name="_bx_payment_strp_v3_cpt"><![CDATA[Stripe]]></string>
+	<string name="_bx_payment_strp_v3_dsc"><![CDATA[Stripe payment provider with 3D Secure authentication for Strong Customer Authentication (SCA) support. Note, it doesn't allow to use recurring payments with trial period.]]></string>
+	<string name="_bx_payment_strp_active_cpt"><![CDATA[Active]]></string>
+	<string name="_bx_payment_strp_active_dsc"><![CDATA[Activate(Deactivate) provider. Note. It's recommended to use SSL for better payment processing.]]></string>
+        <string name="_bx_payment_strp_hidden_cpt"><![CDATA[Hidden]]></string>
+	<string name="_bx_payment_strp_hidden_dsc"><![CDATA[Hide provider if you don't want to accept new payments but already have active subscriptions.]]></string>
+	<string name="_bx_payment_strp_mode_cpt"><![CDATA[Mode]]></string>
+	<string name="_bx_payment_strp_mode_dsc"><![CDATA[Mode to process payments]]></string>
+	<string name="_bx_payment_strp_mode_live"><![CDATA[live]]></string>
+	<string name="_bx_payment_strp_mode_test"><![CDATA[test]]></string>
+	<string name="_bx_payment_strp_live_pub_key_cpt"><![CDATA[Public Key (live)]]></string>
+	<string name="_bx_payment_strp_live_pub_key_dsc"><![CDATA[Your Public Key generated in Stripe for 'live' mode]]></string>
+	<string name="_bx_payment_strp_live_sec_key_cpt"><![CDATA[Secret Key (live)]]></string>
+	<string name="_bx_payment_strp_live_sec_key_dsc"><![CDATA[Your Stripe Secret Key for 'live' mode]]></string>
+	<string name="_bx_payment_strp_test_pub_key_cpt"><![CDATA[Public Key (test)]]></string>
+	<string name="_bx_payment_strp_test_pub_key_dsc"><![CDATA[Your Public Key generated in Stripe for 'test' mode]]></string>
+	<string name="_bx_payment_strp_test_sec_key_cpt"><![CDATA[Secret Key (test)]]></string>
+	<string name="_bx_payment_strp_test_sec_key_dsc"><![CDATA[Your Stripe Secret Key for 'test' mode]]></string>
+	<string name="_bx_payment_strp_check_amount_cpt"><![CDATA[Enable amount checking]]></string>
+	<string name="_bx_payment_strp_check_amount_dsc"><![CDATA[Enable amount checking for Stripe Webhooks (recomended). However checking should be disabled when discounts and coupons are used.]]></string>
+	<string name="_bx_payment_strp_ssl_cpt"><![CDATA[Enable SSL]]></string>
+	<string name="_bx_payment_strp_ssl_dsc"><![CDATA[Enable SSL connection to communicate with Stripe. Note. URLs below will be updated after saving.]]></string>
+	<string name="_bx_payment_strp_notify_url_cpt"><![CDATA[Webhooks URL]]></string>
+	<string name="_bx_payment_strp_cancellation_email_cpt"><![CDATA[Cancellation Email]]></string>
+        <string name="_bx_payment_strp_expiration_email_cpt"><![CDATA[Expiration Email]]></string>
+	<string name="_bx_payment_strp_msg_charged"><![CDATA[Payment was successfully processed.]]></string>
+	<string name="_bx_payment_strp_msg_subscribed"><![CDATA[Thank you! Subscription created. Please, check your email for further instructions.]]></string>
+	<string name="_bx_payment_strp_msg_details_changed"><![CDATA[Subscription details were changed.]]></string>
+    <string name="_bx_payment_strp_err_details_changed"><![CDATA[Cannot change subscription details. Recheck provided data and try again.]]></string>
+	<string name="_bx_payment_strp_msg_billing_changed"><![CDATA[Billing information was changed.]]></string>
+	<string name="_bx_payment_strp_err_billing_changed"><![CDATA[Cannot change billing information. Recheck provided data and try again.]]></string>
+	<string name="_bx_payment_strp_txt_checkout_with_single"><![CDATA[Checkout with {0}]]></string>
+	<string name="_bx_payment_strp_txt_checkout_with_recurring"><![CDATA[Checkout with {0}]]></string>
+	<string name="_bx_payment_strp_menu_item_title_details"><![CDATA[Details]]></string>
+	<string name="_bx_payment_strp_menu_item_title_details_change"><![CDATA[Change Details]]></string>
+	<string name="_bx_payment_strp_menu_item_title_billing"><![CDATA[Billing Info]]></string>
+	<string name="_bx_payment_strp_menu_item_title_billing_change"><![CDATA[Change Billing Info]]></string>
+	<string name="_bx_payment_strp_txt_plan"><![CDATA[Plan]]></string>
+	<string name="_bx_payment_strp_txt_cost"><![CDATA[Cost]]></string>
+	<string name="_bx_payment_strp_txt_cost_mask"><![CDATA[{0} {1} / {2}]]></string>
+	<string name="_bx_payment_strp_txt_status"><![CDATA[Status]]></string>
+	<string name="_bx_payment_strp_txt_created"><![CDATA[Created]]></string>
+	<string name="_bx_payment_strp_txt_started"><![CDATA[Started]]></string>
+	<string name="_bx_payment_strp_txt_trial_start"><![CDATA[Trial start]]></string>
+	<string name="_bx_payment_strp_txt_trial_end"><![CDATA[Trial end]]></string>
+	<string name="_bx_payment_strp_txt_cperiod_start"><![CDATA[Current period start]]></string>
+	<string name="_bx_payment_strp_txt_cperiod_end"><![CDATA[Current period end]]></string>
+	<string name="_bx_payment_strp_txt_card_brand"><![CDATA[Brand]]></string>
+	<string name="_bx_payment_strp_txt_card_origin"><![CDATA[Origin]]></string>
+	<string name="_bx_payment_strp_txt_card_type"><![CDATA[Type]]></string>
+	<string name="_bx_payment_strp_txt_card_number"><![CDATA[Number]]></string>
+	<string name="_bx_payment_strp_txt_card_number_mask"><![CDATA[....{0}]]></string>
+	<string name="_bx_payment_strp_txt_card_expires"><![CDATA[Expires]]></string>
+	<string name="_bx_payment_strp_txt_card_expires_mask"><![CDATA[{0} / {1}]]></string>
+	<string name="_bx_payment_strp_txt_card_cvc"><![CDATA[CVC check]]></string>
+	<string name="_bx_payment_strp_txt_card_cvc_passed"><![CDATA[passed]]></string>
+
+    <string name="_bx_payment_form_strp_details"><![CDATA[Stripe: Details Form]]></string>
+    <string name="_bx_payment_form_strp_details_display_edit"><![CDATA[Stripe: Edit Details Display]]></string>
+    <string name="_bx_payment_form_strp_details_input_item_id_sys"><![CDATA[Plan]]></string>
+    <string name="_bx_payment_form_strp_details_input_item_id"><![CDATA[Plan]]></string>
+    <string name="_bx_payment_form_strp_details_input_item_id_err"><![CDATA[You need to select some plan here]]></string>
+    <string name="_bx_payment_form_strp_details_input_submit_sys"><![CDATA[Submit]]></string>
+    <string name="_bx_payment_form_strp_details_input_submit"><![CDATA[Submit]]></string>
+    <string name="_bx_payment_form_strp_details_input_cancel_sys"><![CDATA[Cancel]]></string>
+    <string name="_bx_payment_form_strp_details_input_cancel"><![CDATA[Cancel]]></string>
+
+    <string name="_bx_payment_form_strp_card"><![CDATA[Stripe: Card Form]]></string>
+    <string name="_bx_payment_form_strp_card_display_add"><![CDATA[Stripe: Add Card Display]]></string>
+    <string name="_bx_payment_form_strp_card_input_card_number_sys"><![CDATA[Card Number]]></string>
+    <string name="_bx_payment_form_strp_card_input_card_number"><![CDATA[Card Number]]></string>
+    <string name="_bx_payment_form_strp_card_input_card_number_inf"><![CDATA[16 digits without spaces describing your card number]]></string>
+    <string name="_bx_payment_form_strp_card_input_card_number_err"><![CDATA[You need to enter card number here]]></string>
+    <string name="_bx_payment_form_strp_card_input_card_expire_sys"><![CDATA[Expiry Date]]></string>
+    <string name="_bx_payment_form_strp_card_input_card_expire"><![CDATA[Expiry Date]]></string>
+    <string name="_bx_payment_form_strp_card_input_card_expire_month"><![CDATA[Month]]></string>
+    <string name="_bx_payment_form_strp_card_input_card_expire_year"><![CDATA[Year]]></string>
+    <string name="_bx_payment_form_strp_card_input_card_expire_inf"><![CDATA[Use 'mm yyyy' format]]></string>
+    <string name="_bx_payment_form_strp_card_input_card_expire_err"><![CDATA[You need to enter expiry date in specified format here]]></string>
+    <string name="_bx_payment_form_strp_card_input_card_cvv_sys"><![CDATA[CVV]]></string>
+    <string name="_bx_payment_form_strp_card_input_card_cvv"><![CDATA[CVV]]></string>
+    <string name="_bx_payment_form_strp_card_input_card_cvv_inf"><![CDATA[Three digits from the back side of your card.]]></string>
+    <string name="_bx_payment_form_strp_card_input_card_cvv_err"><![CDATA[You need to enter card CVV here]]></string>
+    <string name="_bx_payment_form_strp_card_input_submit_sys"><![CDATA[Submit]]></string>
+    <string name="_bx_payment_form_strp_card_input_submit"><![CDATA[Submit]]></string>
+    <string name="_bx_payment_form_strp_card_input_cancel_sys"><![CDATA[Cancel]]></string>
+    <string name="_bx_payment_form_strp_card_input_cancel"><![CDATA[Cancel]]></string>
+
+    <string name="_bx_payment_txt_name_stripe"><![CDATA[Stripe]]></string>
+    <string name="_bx_payment_txt_cart_stripe"><![CDATA[Stripe]]></string>
+    <string name="_bx_payment_txt_name_stripe_v3"><![CDATA[Stripe]]></string>
+    <string name="_bx_payment_txt_cart_stripe_v3"><![CDATA[Stripe]]></string>
+
+    <!-- _bx_payment_aina_mode_live payment provider -->
+    <string name="_bx_payment_aina_cpt"><![CDATA[Apple In-App]]></string>
+    <string name="_bx_payment_aina_dsc"><![CDATA[Apple In-App payment provider]]></string>
+    <string name="_bx_payment_aina_active_cpt"><![CDATA[Active]]></string>
+    <string name="_bx_payment_aina_active_dsc"><![CDATA[Activate(Deactivate) provider.]]></string>
+    <string name="_bx_payment_aina_hidden_cpt"><![CDATA[Hidden]]></string>
+    <string name="_bx_payment_aina_hidden_dsc"><![CDATA[Recommended. The provider should be hidden in WEB because it can be used in mobile app only.]]></string>
+    <string name="_bx_payment_aina_secret_cpt"><![CDATA[Shared Secret]]></string>
+    <string name="_bx_payment_aina_secret_dsc"><![CDATA[It's the app-specific unique code to receive receipts for auto-renewable subscriptions.]]></string>
+    <string name="_bx_payment_aina_notify_url_cpt"><![CDATA[URL for App Store Server Notifications]]></string>
+    <string name="_bx_payment_aina_menu_item_title_cancel"><![CDATA[Cancel]]></string>
+    <string name="_bx_payment_aina_msg_charged"><![CDATA[Payment was successfully processed.]]></string>
+    <string name="_bx_payment_aina_msg_subscribed"><![CDATA[Thank you! Subscription created. Please, check your email for further instructions.]]></string>
+    <string name="_bx_payment_txt_name_apple_in_app"><![CDATA[Apple In-App]]></string>
+    <string name="_bx_payment_txt_cart_apple_in_app"><![CDATA[Apple In-App]]></string>
+</resources>

+ 43 - 0
modules/boonex/payment/updates/12.0.0_12.0.1/source/install/sql/disable.sql

@@ -0,0 +1,43 @@
+SET @sName = 'bx_payment';
+
+
+-- OPTIONS
+SET @iTypeId = (SELECT `ID` FROM `sys_options_types` WHERE `name` = @sName LIMIT 1);
+SET @iCategId = (SELECT `ID` FROM `sys_options_categories` WHERE `type_id` = @iTypeId LIMIT 1);
+DELETE FROM `sys_options` WHERE `category_id` = @iCategId;
+DELETE FROM `sys_options_categories` WHERE `type_id` = @iTypeId;
+DELETE FROM `sys_options_types` WHERE `id` = @iTypeId;
+
+
+-- PAGES & BLOCKS
+DELETE FROM `sys_objects_page` WHERE `module` = @sName;
+DELETE FROM `sys_pages_blocks` WHERE `module` = @sName;
+
+
+-- MENU
+DELETE FROM `sys_objects_menu` WHERE `module` = @sName;
+DELETE FROM `sys_menu_sets` WHERE `module` = @sName;
+DELETE FROM `sys_menu_items` WHERE `module` = @sName OR `set_name` IN('bx_payment_menu_cart_submenu', 'bx_payment_menu_sbs_submenu', 'bx_payment_menu_sbs_actions', 'bx_payment_menu_orders_submenu');
+
+
+-- ALERTS
+SET @iHandlerId = (SELECT `id` FROM `sys_alerts_handlers` WHERE `name` = @sName LIMIT 1);
+DELETE FROM `sys_alerts` WHERE `handler_id` = @iHandlerId;
+DELETE FROM `sys_alerts_handlers` WHERE `id` = @iHandlerId LIMIT 1;
+
+
+-- ACL
+DELETE `sys_acl_actions`, `sys_acl_matrix` FROM `sys_acl_actions`, `sys_acl_matrix` WHERE `sys_acl_matrix`.`IDAction` = `sys_acl_actions`.`ID` AND `sys_acl_actions`.`Module` = @sName;
+DELETE FROM `sys_acl_actions` WHERE `Module` = @sName;
+
+
+-- EMAIL TEMPLATES
+DELETE FROM `sys_email_templates` WHERE `Module` = @sName;
+
+
+-- CRON
+DELETE FROM `sys_cron_jobs` WHERE `name` IN ('bx_payment_commissions', 'bx_payment_time_tracker');
+
+
+-- PAYMENTS
+DELETE FROM `sys_objects_payments` WHERE `object` = @sName;

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