AntonLV 4 роки тому
батько
коміт
26b75fe3ec
94 змінених файлів з 30262 додано та 0 видалено
  1. 51 0
      modules/boonex/notifications/updates/13.0.3_13.0.4/install/config.php
  2. 26 0
      modules/boonex/notifications/updates/13.0.3_13.0.4/install/installer.php
  3. 10 0
      modules/boonex/notifications/updates/13.0.3_13.0.4/install/langs/en.xml
  4. 25 0
      modules/boonex/notifications/updates/13.0.3_13.0.4/install/sql/enable.sql
  5. 5 0
      modules/boonex/notifications/updates/13.0.3_13.0.4/install/sql/install.sql
  6. 264 0
      modules/boonex/notifications/updates/13.0.3_13.0.4/source/classes/BxNtfsConfig.php
  7. 409 0
      modules/boonex/notifications/updates/13.0.3_13.0.4/source/classes/BxNtfsDb.php
  8. 625 0
      modules/boonex/notifications/updates/13.0.3_13.0.4/source/classes/BxNtfsModule.php
  9. 345 0
      modules/boonex/notifications/updates/13.0.3_13.0.4/source/classes/BxNtfsResponse.php
  10. 424 0
      modules/boonex/notifications/updates/13.0.3_13.0.4/source/classes/BxNtfsTemplate.php
  11. 82 0
      modules/boonex/notifications/updates/13.0.3_13.0.4/source/install/config.php
  12. 144 0
      modules/boonex/notifications/updates/13.0.3_13.0.4/source/install/langs/en.xml
  13. 173 0
      modules/boonex/notifications/updates/13.0.3_13.0.4/source/install/sql/enable.sql
  14. 216 0
      modules/boonex/notifications/updates/13.0.3_13.0.4/source/install/sql/install.sql
  15. 51 0
      modules/boonex/organizations/updates/13.0.3_13.0.4/install/config.php
  16. 13 0
      modules/boonex/organizations/updates/13.0.3_13.0.4/install/installer.php
  17. 16 0
      modules/boonex/organizations/updates/13.0.3_13.0.4/install/langs/en.xml
  18. 45 0
      modules/boonex/organizations/updates/13.0.3_13.0.4/install/sql/enable.sql
  19. 10 0
      modules/boonex/organizations/updates/13.0.3_13.0.4/install/sql/install.sql
  20. 322 0
      modules/boonex/organizations/updates/13.0.3_13.0.4/source/classes/BxOrgsConfig.php
  21. 21 0
      modules/boonex/organizations/updates/13.0.3_13.0.4/source/classes/BxOrgsGridInvites.php
  22. 152 0
      modules/boonex/organizations/updates/13.0.3_13.0.4/source/install/config.php
  23. 577 0
      modules/boonex/organizations/updates/13.0.3_13.0.4/source/install/langs/en.xml
  24. 770 0
      modules/boonex/organizations/updates/13.0.3_13.0.4/source/install/sql/enable.sql
  25. 565 0
      modules/boonex/organizations/updates/13.0.3_13.0.4/source/install/sql/install.sql
  26. 16 0
      modules/boonex/organizations/updates/13.0.3_13.0.4/source/js/invite_popup.js
  27. 1 0
      modules/boonex/organizations/updates/13.0.3_13.0.4/source/template/popup_invite.html
  28. 51 0
      modules/boonex/payment/updates/13.0.3_13.0.4/install/config.php
  29. 13 0
      modules/boonex/payment/updates/13.0.3_13.0.4/install/installer.php
  30. 4 0
      modules/boonex/payment/updates/13.0.3_13.0.4/install/langs/en.xml
  31. 338 0
      modules/boonex/payment/updates/13.0.3_13.0.4/source/classes/BxPaymentConfig.php
  32. 140 0
      modules/boonex/payment/updates/13.0.3_13.0.4/source/classes/BxPaymentGridCommissions.php
  33. 1955 0
      modules/boonex/payment/updates/13.0.3_13.0.4/source/classes/BxPaymentModule.php
  34. 225 0
      modules/boonex/payment/updates/13.0.3_13.0.4/source/classes/BxPaymentProviderCredits.php
  35. 947 0
      modules/boonex/payment/updates/13.0.3_13.0.4/source/classes/BxPaymentProviderPayPalApi.php
  36. 70 0
      modules/boonex/payment/updates/13.0.3_13.0.4/source/install/config.php
  37. 662 0
      modules/boonex/payment/updates/13.0.3_13.0.4/source/install/langs/en.xml
  38. 51 0
      modules/boonex/persons/updates/13.0.4_13.0.5/install/config.php
  39. 13 0
      modules/boonex/persons/updates/13.0.4_13.0.5/install/installer.php
  40. 6 0
      modules/boonex/persons/updates/13.0.4_13.0.5/install/langs/en.xml
  41. 7 0
      modules/boonex/persons/updates/13.0.4_13.0.5/install/sql/enable.sql
  42. 152 0
      modules/boonex/persons/updates/13.0.4_13.0.5/source/install/config.php
  43. 356 0
      modules/boonex/persons/updates/13.0.4_13.0.5/source/install/langs/en.xml
  44. 567 0
      modules/boonex/persons/updates/13.0.4_13.0.5/source/install/sql/enable.sql
  45. 51 0
      modules/boonex/profiler/updates/12.0.0_13.0.0/install/config.php
  46. 13 0
      modules/boonex/profiler/updates/12.0.0_13.0.0/install/installer.php
  47. 4 0
      modules/boonex/profiler/updates/12.0.0_13.0.0/install/sql/enable.sql
  48. 68 0
      modules/boonex/profiler/updates/12.0.0_13.0.0/source/install/config.php
  49. 49 0
      modules/boonex/profiler/updates/12.0.0_13.0.0/source/install/sql/enable.sql
  50. 51 0
      modules/boonex/smtpmailer/updates/13.0.0_13.0.1/install/config.php
  51. 13 0
      modules/boonex/smtpmailer/updates/13.0.0_13.0.1/install/installer.php
  52. 6 0
      modules/boonex/smtpmailer/updates/13.0.0_13.0.1/install/langs/en.xml
  53. 7 0
      modules/boonex/smtpmailer/updates/13.0.0_13.0.1/install/sql/enable.sql
  54. 210 0
      modules/boonex/smtpmailer/updates/13.0.0_13.0.1/source/classes/BxSMTPModule.php
  55. 68 0
      modules/boonex/smtpmailer/updates/13.0.0_13.0.1/source/install/config.php
  56. 59 0
      modules/boonex/smtpmailer/updates/13.0.0_13.0.1/source/install/langs/en.xml
  57. 41 0
      modules/boonex/smtpmailer/updates/13.0.0_13.0.1/source/install/sql/enable.sql
  58. 51 0
      modules/boonex/spaces/updates/13.0.2_13.0.3/install/config.php
  59. 13 0
      modules/boonex/spaces/updates/13.0.2_13.0.3/install/installer.php
  60. 7 0
      modules/boonex/spaces/updates/13.0.2_13.0.3/install/sql/enable.sql
  61. 152 0
      modules/boonex/spaces/updates/13.0.2_13.0.3/source/install/config.php
  62. 681 0
      modules/boonex/spaces/updates/13.0.2_13.0.3/source/install/sql/enable.sql
  63. 16 0
      modules/boonex/spaces/updates/13.0.2_13.0.3/source/js/invite_popup.js
  64. 51 0
      modules/boonex/timeline/updates/13.0.4_13.0.5/install/config.php
  65. 26 0
      modules/boonex/timeline/updates/13.0.4_13.0.5/install/installer.php
  66. 9 0
      modules/boonex/timeline/updates/13.0.4_13.0.5/install/langs/en.xml
  67. 37 0
      modules/boonex/timeline/updates/13.0.4_13.0.5/install/sql/enable.sql
  68. 11 0
      modules/boonex/timeline/updates/13.0.4_13.0.5/install/sql/install.sql
  69. 39 0
      modules/boonex/timeline/updates/13.0.4_13.0.5/source/classes/BxTimelineCmts.php
  70. 941 0
      modules/boonex/timeline/updates/13.0.4_13.0.5/source/classes/BxTimelineConfig.php
  71. 36 0
      modules/boonex/timeline/updates/13.0.4_13.0.5/source/classes/BxTimelineCronClean.php
  72. 1197 0
      modules/boonex/timeline/updates/13.0.4_13.0.5/source/classes/BxTimelineDb.php
  73. 397 0
      modules/boonex/timeline/updates/13.0.4_13.0.5/source/classes/BxTimelineFormPost.php
  74. 82 0
      modules/boonex/timeline/updates/13.0.4_13.0.5/source/classes/BxTimelineGridCommon.php
  75. 395 0
      modules/boonex/timeline/updates/13.0.4_13.0.5/source/classes/BxTimelineMenuItemActions.php
  76. 5467 0
      modules/boonex/timeline/updates/13.0.4_13.0.5/source/classes/BxTimelineModule.php
  77. 51 0
      modules/boonex/timeline/updates/13.0.4_13.0.5/source/classes/BxTimelinePageViewItem.php
  78. 349 0
      modules/boonex/timeline/updates/13.0.4_13.0.5/source/classes/BxTimelineResponse.php
  79. 3134 0
      modules/boonex/timeline/updates/13.0.4_13.0.5/source/classes/BxTimelineTemplate.php
  80. 143 0
      modules/boonex/timeline/updates/13.0.4_13.0.5/source/install/config.php
  81. 411 0
      modules/boonex/timeline/updates/13.0.4_13.0.5/source/install/langs/en.xml
  82. 570 0
      modules/boonex/timeline/updates/13.0.4_13.0.5/source/install/sql/enable.sql
  83. 667 0
      modules/boonex/timeline/updates/13.0.4_13.0.5/source/install/sql/install.sql
  84. 77 0
      modules/boonex/timeline/updates/13.0.4_13.0.5/source/install/sql/uninstall.sql
  85. 565 0
      modules/boonex/timeline/updates/13.0.4_13.0.5/source/js/main.js
  86. 372 0
      modules/boonex/timeline/updates/13.0.4_13.0.5/source/js/post.js
  87. 1430 0
      modules/boonex/timeline/updates/13.0.4_13.0.5/source/js/view.js
  88. 1023 0
      modules/boonex/timeline/updates/13.0.4_13.0.5/source/template/css/view.css
  89. 86 0
      modules/boonex/timeline/updates/13.0.4_13.0.5/source/template/item_outline.html
  90. 57 0
      modules/boonex/timeline/updates/13.0.4_13.0.5/source/template/item_search.html
  91. 84 0
      modules/boonex/timeline/updates/13.0.4_13.0.5/source/template/item_timeline.html
  92. 14 0
      modules/boonex/timeline/updates/13.0.4_13.0.5/source/template/jump_to.html
  93. 10 0
      modules/boonex/timeline/updates/13.0.4_13.0.5/source/template/load_more.html
  94. 56 0
      modules/boonex/timeline/updates/13.0.4_13.0.5/source/template/type_post.html

+ 51 - 0
modules/boonex/notifications/updates/13.0.3_13.0.4/install/config.php

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

+ 26 - 0
modules/boonex/notifications/updates/13.0.3_13.0.4/install/installer.php

@@ -0,0 +1,26 @@
+<?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);
+    }
+
+    public function actionExecuteSql($sOperation)
+    {
+        if($sOperation == 'install') {
+            if(!$this->oDb->isFieldExists('bx_notifications_events', 'source'))
+                $this->oDb->query("ALTER TABLE `bx_notifications_events` ADD `source` varchar(32) NOT NULL default '' AFTER `content`");
+
+            if(!$this->oDb->isFieldExists('bx_notifications_handlers', 'priority'))
+                $this->oDb->query("ALTER TABLE `bx_notifications_handlers` ADD `priority` int(11) NOT NULL default '0' AFTER `privacy`");
+        }
+
+        return parent::actionExecuteSql($sOperation);
+    }
+}

+ 10 - 0
modules/boonex/notifications/updates/13.0.3_13.0.4/install/langs/en.xml

@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources name="en" flag="gb" title="English">
+	<string_add name="_bx_ntfs_option_enable_group_events"><![CDATA[Group notifications by event]]></string_add>
+	<string_add name="_bx_ntfs_option_enable_comment_post_ext"><![CDATA[Notify a user about new comments for a content he's previously commented]]></string_add>
+	<string_add name="_bx_ntfs_alert_action_group_comment"><![CDATA[New comments]]></string_add>
+	<string_add name="_bx_ntfs_alert_action_comment_added_personal"><![CDATA[Someone adds a comment on a content you've already commented]]></string_add>
+	<string_add name="_bx_ntfs_alert_module_comment"><![CDATA[Comments]]></string_add>
+
+	<string_upd name="_bx_ntfs_option_enable_group_settings"><![CDATA[Group settings by category]]></string_upd>
+</resources>

+ 25 - 0
modules/boonex/notifications/updates/13.0.3_13.0.4/install/sql/enable.sql

@@ -0,0 +1,25 @@
+SET @sName = 'bx_notifications';
+
+
+-- SETTINGS
+SET @iCategId = (SELECT `id` FROM `sys_options_categories` WHERE `name`=@sName LIMIT 1);
+
+DELETE FROM `sys_options` WHERE `name` IN ('bx_notifications_enable_group_events', 'bx_notifications_enable_comment_post_ext');
+INSERT INTO `sys_options` (`name`, `value`, `category_id`, `caption`, `type`, `check`, `check_params`, `check_error`, `extra`, `order`) VALUES
+('bx_notifications_enable_group_events', 'on', @iCategId, '_bx_ntfs_option_enable_group_events', 'checkbox', '', '', '', '', 11), 
+('bx_notifications_enable_comment_post_ext', '', @iCategId, '_bx_ntfs_option_enable_comment_post_ext', 'checkbox', '', '', '', '', 40);
+
+
+-- MENUS
+UPDATE `sys_menu_items` SET `onclick`='bx_menu_slide(''bx_notifications_preview'', $(this).parents(''ul:first''), ''site'', {id:{value:''bx_notifications_preview'', force:1}, pointer:{align:''right''}, cssClass: ''''});', `hidden_on`='9' WHERE `set_name`='sys_toolbar_member' AND `name`='notifications-preview';
+
+UPDATE `sys_menu_items` SET `hidden_on`='6', `active`='1' WHERE `set_name`='sys_account_notifications' AND `name`='notifications-notifications';
+
+
+-- ALERTS
+SET @iHandler := (SELECT `id` FROM `sys_alerts_handlers` WHERE `name`=@sName LIMIT 1);
+
+DELETE FROM `sys_alerts` WHERE `unit`='comment' AND `action` IN ('added', 'deleted') AND `handler_id`=@iHandler;
+INSERT INTO `sys_alerts` (`unit`, `action`, `handler_id`) VALUES
+('comment', 'added', @iHandler),
+('comment', 'deleted', @iHandler);

+ 5 - 0
modules/boonex/notifications/updates/13.0.3_13.0.4/install/sql/install.sql

@@ -0,0 +1,5 @@
+SET @sName = 'bx_notifications';
+
+
+-- MENUS
+UPDATE `sys_menu_items` SET `onclick`='bx_menu_slide(''bx_notifications_preview'', this, ''site'', {id:{value:''bx_notifications_preview'', force:1}, cssClass: ''''});' WHERE `set_name`='sys_toolbar_member' AND `name`='notifications-preview';

+ 264 - 0
modules/boonex/notifications/updates/13.0.3_13.0.4/source/classes/BxNtfsConfig.php

@@ -0,0 +1,264 @@
+<?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;
+
+    protected $_bEventsGrouped;
+
+    /**
+     * 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,
+            'PARAM_COMMENT_POST_EXT' => 'bx_notifications_enable_comment_post_ext',
+
+            // 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');
+
+        $this->_bEventsGrouped = getParam($sOptionPrefix . 'enable_group_events') == 'on';
+    }
+
+    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 isEventsGrouped()
+    {
+        return $this->_bEventsGrouped;
+    }
+
+    public function getProcessedEvent()
+    {
+        return $this->_iProcessedEvent;
+    }
+    
+    public function setProcessedEvent($iEvent)
+    {
+        $this->_iProcessedEvent = $iEvent;
+
+        setParam($this->getPrefix('option') . 'processed_event', $iEvent);
+    }
+
+    /**
+     * Ancillary functions
+     */
+    public function getViewUrl()
+    {
+        return BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink('page.php?i=notifications-view');
+    }
+
+    public function getContentModule(&$aEvent)
+    {
+        $sModule = $aEvent['type'];
+        if($this->_oDb->isEnabledByName($sModule))
+            return $sModule;
+
+        $sModule = str_replace(array('_media', '_reactions'), array('', ''), $sModule);
+        if($this->_oDb->isEnabledByName($sModule))
+            return $sModule;
+
+        return '';
+    }
+
+    public function getContentObjectId(&$aEvent)
+    {
+        return !empty($aEvent['content']['object_id']) ? (int)$aEvent['content']['object_id'] : (int)$aEvent['object_id'];
+    }
+
+    public function getProfileBasedModules() 
+    {
+        if ($this->_aModulesProfiles !== false && $this->_aModulesContexts !== false)
+            return array($this->_aModulesProfiles, $this->_aModulesContexts);
+
+        if (getParam('sys_db_cache_enable')) {
+            $oDb = BxDolDb::getInstance();
+            $oCache = $oDb->getDbCacheObject();
+            $sCacheKey = $oDb->genDbCacheKey('bx_ntfs_profile_based_modules');
+            $aData = $oCache->getData($sCacheKey);
+            if (null === $aData) {
+                $aData = $this->_getProfileBasedModulesData();
+                $oCache->setData ($sCacheKey, $aData);
+            }
+        } 
+        else {
+            $aData = $this->_getProfileBasedModulesData();
+        }
+
+        return $aData;
+    }
+
+    protected function _getProfileBasedModulesData() 
+    {
+        $this->_aModulesProfiles = [];
+        $this->_aModulesContexts = [];
+
+        $aModules = BxDolModuleQuery::getInstance()->getModulesBy(['type' => 'modules']);
+        foreach($aModules as $aModule) {
+            if(!bx_is_srv($aModule['name'], 'act_as_profile'))
+                continue;
+
+            if(bx_srv($aModule['name'], 'act_as_profile'))
+                $this->_aModulesProfiles[] = $aModule['name'];
+            else
+                $this->_aModulesContexts[] = $aModule['name'];
+        }
+
+        return [$this->_aModulesProfiles, $this->_aModulesContexts];
+    }
+}
+
+/** @} */

+ 409 - 0
modules/boonex/notifications/updates/13.0.3_13.0.4/source/classes/BxNtfsDb.php

@@ -0,0 +1,409 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Notifications Notifications
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxNtfsDb extends BxBaseModNotificationsDb
+{
+    protected $_sTableEvt2Usr;
+    protected $_sTableQueue;
+
+    /*
+     * Constructor.
+     */
+    function __construct(&$oConfig)
+    {
+        parent::__construct($oConfig);
+
+        $this->_aDeliveryTypes = array(
+            BX_BASE_MOD_NTFS_DTYPE_SITE, 
+            BX_BASE_MOD_NTFS_DTYPE_EMAIL, 
+            BX_BASE_MOD_NTFS_DTYPE_PUSH
+        );
+
+        $this->_sTableEvt2Usr = $this->_sPrefix . 'events2users';
+        $this->_sTableQueue = $this->_sPrefix . 'queue';
+    }
+
+    public function markAsRead($iUserId, $iEventId)
+    {
+        $this->queueDeleteByProfile($iUserId, $iEventId);
+
+        return (int)$this->query("INSERT INTO `" . $this->_sTableEvt2Usr . "` (`user_id`, `event_id`) VALUES (:user_id, :event_id) ON DUPLICATE KEY UPDATE `event_id`=:event_id", array(
+            'user_id' => $iUserId,
+            'event_id' => $iEventId
+        )) > 0;
+    }
+
+    public function getLastRead($iUserId)
+    {
+        return (int)$this->getOne("SELECT `event_id` FROM `" . $this->_sTableEvt2Usr . "` WHERE `user_id`=:user_id LIMIT 1", array(
+            'user_id' => (int)$iUserId
+        ));
+    }
+
+    public function deleteEvent($aParams, $sWhereAddon = "")
+    {
+        $aEvents = $this->getAll("SELECT * FROM `{$this->_sTable}` WHERE " . $this->arrayToSQL($aParams, " AND ") . $sWhereAddon);
+        if(!empty($aEvents) && is_array($aEvents)) 
+            foreach($aEvents as $aEvent)
+                $this->queueDelete(array('event_id' => $aEvent['id']));
+
+        return parent::deleteEvent($aParams, $sWhereAddon);
+    }
+
+    public function getEvents($aParams, $bReturnCount = false)
+    {
+        bx_alert($this->_oConfig->getName(), 'get_events_before', 0, 0, [
+            'params' => &$aParams,
+        ]);
+
+        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, $sJoinClausePo, $sWhereClausePo, $sOrderClausePo) = $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` " . $sJoinClausePo . "
+            WHERE 1 " . $sWhereClausePo . (!$bCountOnly ? " " . $sOrderClausePo . " " . $sLimitClause : "");
+
+        //--- Get query for 'Connections based' notifications
+        $aParams['type'] = BX_BASE_MOD_NTFS_TYPE_CONNECTIONS;
+        list($sMethod, $sSelectClause, $sJoinClausePc, $sWhereClausePc, $sOrderClausePc) = $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` " . $sJoinClausePc . "
+            WHERE 1 " . $sWhereClausePc . (!$bCountOnly ? " " . $sOrderClausePc . " " . $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'] : "";
+        }
+
+        $aAlertParams = $aParams;
+        unset($aAlertParams['browse']);
+
+        /**
+         * Parts: 
+         * PO - notifications related to Owner's content
+         * PC - notifications related to Connections' content
+         */
+        bx_alert($this->_oConfig->getName(), 'get_events', 0, 0, [
+            'browse' => $aParams['browse'],
+            'params' => $aAlertParams,
+            'table' => $this->_sTable,
+            'method' => &$sUnionMethod,
+            'select_clause' => &$sSelectClause,
+            'join_clause_po' => &$sJoinClausePo,
+            'join_clause_pc' => &$sJoinClausePc,
+            'where_clause_po' => &$sWhereClausePo,
+            'where_clause_pc' => &$sWhereClausePc,
+            'order_clause_po' => &$sOrderClausePo,
+            'order_clause_pc' => &$sOrderClausePc,
+            'order_clause' => &$sUnionOrderClause,
+            'limit_clause' => &$sUnionLimitClause,
+            'query_po' => &$sQueryOwner,
+            'query_pc' => &$sQueryConnections,
+        ]);
+
+        $sQuery = "(" . $sQueryOwner . ") UNION (" . $sQueryConnections . ") {order} {limit}";
+        $sQuery = str_replace(['{select}', '{order}', '{limit}'], [$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 {
+                    $sSelectClause .= ", `{$this->_sTableHandlers}`.`priority` AS `priority`";
+
+                    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 = "";
+
+        //--- Apply status filter
+        $sWhereClauseStatus = '';
+        if(isset($aParams['active']))
+            $sWhereClauseStatus = $this->prepareAsString("AND `{$this->_sTable}`.`active`=? ", (int)$aParams['active']);
+
+        //--- Apply modules or handlers filter
+        $sWhereClauseModules = '';
+        if(!empty($aParams['modules']) && is_array($aParams['modules']))
+            $sWhereClauseModules = "AND `" . $this->_sTable . "`.`type` IN (" . $this->implode_escape($aParams['modules']) . ") ";
+
+        if($sWhereClauseModules == '') {
+            $aHidden = $this->_oConfig->getHandlersHidden();
+            $sWhereClauseModules = !empty($aHidden) && is_array($aHidden) ? "AND `" . $this->_sTableHandlers . "`.`id` NOT IN (" . $this->implode_escape($aHidden) . ") " : "";
+        }
+
+        //--- Check flag 'New'
+        $sWhereClauseNew = '';
+        if(!empty($aParams['new']) && !empty($aParams['owner_id']))
+            $sWhereClauseNew = $this->prepareAsString("AND `{$this->_sTable}`.`id`>? ", $this->getLastRead((int)$aParams['owner_id']));
+
+        //--- Check type
+        $sWhereClauseSettings = $sWhereClauseType = '';
+        if(!empty($aParams['owner_id']))
+            switch($aParams['type']) {
+                /*
+                 * Note. It isn't used for now and outdated.
+                 */
+                case BX_BASE_MOD_NTFS_TYPE_OWNER:
+                    $sWhereClauseType = $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;
+                    $sWhereClauseSettings = "AND ((ISNULL(`{$this->_sTableSettings2Users}`.`active`) AND `{$this->_sTableSettings}`.`value`='1') OR (NOT ISNULL(`{$this->_sTableSettings2Users}`.`active`) AND `{$this->_sTableSettings2Users}`.`active`='1')) ";
+
+                    $sWhereClauseType = $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'];
+
+                    $sWhereClauseType = '';
+                    if(!empty($aQueryParts['fields']['added']))
+                        $sWhereClauseType = "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;
+                    $sWhereClauseSettings = "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;
+                    $sWhereClauseSettings = "AND ((ISNULL(`{$this->_sTableSettings2Users}`.`active`) AND `{$this->_sTableSettings}`.`value`='1') OR (NOT ISNULL(`{$this->_sTableSettings2Users}`.`active`) AND `{$this->_sTableSettings2Users}`.`active`='1')) ";
+
+                    $sWhereClauseType = "AND ((" . $sWhereClauseObjectOwner . ") OR (" . $sWhereClauseConnections . ")) ";
+                    break;
+            }
+
+        $aAlertParams = $aParams;
+        unset($aAlertParams['type'], $aAlertParams['owner_id']);
+
+        bx_alert($this->_oConfig->getName(), 'get_list_by_type', 0, 0, [
+            'type' => $aParams['type'],
+            'owner_id' => $aParams['owner_id'],
+            'params' => $aAlertParams,
+            'table' => $this->_sTable,
+            'join_clause' => &$sJoinClause,
+            'where_clause' => &$sWhereClause,
+            'where_clause_status' => &$sWhereClauseStatus,
+            'where_clause_modules' => &$sWhereClauseModules,
+            'where_clause_new' => &$sWhereClauseNew,
+            'where_clause_settings' => &$sWhereClauseSettings,
+            'where_clause_type' => &$sWhereClauseType
+        ]);
+
+        $sWhereClause .= $sWhereClauseStatus;
+        $sWhereClause .= $sWhereClauseModules;
+        $sWhereClause .= $sWhereClauseNew;
+        $sWhereClause .= $sWhereClauseSettings;
+        $sWhereClause .= $sWhereClauseType;
+
+        return [$sJoinClause, $sWhereClause];
+    }
+
+    public function getEventsToProcess($iLimit = 0)
+    {
+        $aEvents = $this->getAll("SELECT * FROM `" . $this->_sTable . "` WHERE `id`>:id ORDER BY `id` ASC" . ($iLimit != 0 ? ' LIMIT ' . $iLimit : ''), 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));
+    }   
+
+    public function filterProfileIdsByModule($aIds, $mixedModule)
+    {
+        if(!is_array($mixedModule))
+            $mixedModule = array($mixedModule);
+
+        return $this->getColumn("SELECT `id` FROM `sys_profiles` WHERE `id` IN (" . $this->implode_escape($aIds) . ") AND `type` IN (" . $this->implode_escape($mixedModule) . ")");
+    }
+}
+
+/** @} */

+ 625 - 0
modules/boonex/notifications/updates/13.0.3_13.0.4/source/classes/BxNtfsModule.php

@@ -0,0 +1,625 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Notifications Notifications
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+bx_import('BxBaseModNotificationsModule');
+
+define('BX_NTFS_TYPE_OBJECT_OWNER_AND_CONNECTIONS', 'obj_own_and_con');
+define('BX_NTFS_TYPE_DEFAULT', BX_NTFS_TYPE_OBJECT_OWNER_AND_CONNECTIONS);
+
+/**
+ * STYPE - Setting Type:
+ * 1. personal - related to you;
+ * 2. follow_member - related to members you follow;
+ * 3. follow_context - related to contexts you follow;
+ * 4. other - others.
+ */
+define('BX_NTFS_STYPE_PERSONAL', 'personal');
+define('BX_NTFS_STYPE_FOLLOW_MEMBER', 'follow_member');
+define('BX_NTFS_STYPE_FOLLOW_CONTEXT', 'follow_context');
+define('BX_NTFS_STYPE_OTHER', 'other');
+
+/**
+ * SLTMODE - Silent mode:
+ * It is needed for alert sending module to tell that the alert should be ignored 
+ * with Notifications module completely or partially. Available values: 
+ * 1. disabled (global, value = 0) - all notifications are available;
+ * 2. absolute (global, value = 1) - alert isn't registered which means that there is no notifications at all;
+ * 3. absolute (for Notifications only, value = 11) - the same as global absolute.
+ * 3. on-site only (value = 12) - alert is registered. It means that on-site notification is available while the others are disabled.
+ * 4. on-site + email (value = 13) - alert is registered (on-site) and notification via 'email' is enabled.
+ * 5. on-site + push (value = 14) - alert is registered (on-site) and notification via 'push' is enabled.
+ * 
+ * @see BxNtfsResponse::response - 'silent_mode' parameter in Alerts Extras array.
+ */
+define('BX_NTFS_SLTMODE_ABSOLUTE', 11);
+define('BX_NTFS_SLTMODE_SITE', 12);
+define('BX_NTFS_SLTMODE_SITE_EMAIL', 13);
+define('BX_NTFS_SLTMODE_SITE_PUSH', 14);
+
+class BxNtfsModule extends BxBaseModNotificationsModule
+{
+    /**
+     * Constructor
+     */
+    function __construct($aModule)
+    {
+        parent::__construct($aModule);
+
+        $this->_iOwnerId = $this->getUserId();
+    }
+
+    /**
+     * ACTION METHODS
+     */
+    function actionGetPosts()
+    {
+        $aParams = $this->_prepareParamsGet();
+        if(empty($aParams['owner_id']) || (int)$aParams['owner_id'] != $this->_iOwnerId)
+            return echoJson([]);
+
+        echoJson([
+            'events' => $this->_oTemplate->getPosts($aParams)
+        ]);
+    }
+
+    /**
+     * SERVICE METHODS
+     */
+
+    public function serviceGetSafeServices()
+    {
+        return [
+            '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);
+
+        if($this->_oConfig->isEventsGrouped())
+            $this->groupEvents($aEvents);
+
+        // 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;
+
+        $sModule = $this->_oConfig->getName();
+        $aBrowseParams = $this->_prepareParams(BX_NTFS_TYPE_DEFAULT, $iOwnerId, 0, PHP_INT_MAX);
+
+        $sParamCheck = 'perform_privacy_check';
+        $sParamCheckFor = 'perform_privacy_check_for';
+
+        $iEvents = 0;
+        if($this->_oConfig->isEventsGrouped()) {
+            $aEvents = $this->_oDb->getEvents($aBrowseParams);
+
+            $this->groupEvents($aEvents);
+
+            $iCount = 0;
+            $iLastRead = $this->_oDb->getLastRead((int)$aBrowseParams['owner_id']);
+            foreach($aEvents as $aEvent)
+                if($aEvent['id'] > $iLastRead)
+                    $iCount++;
+
+            $aEvents = array_slice($aEvents, 0, $iCount);
+        }
+        else {
+            $aBrowseParams = array_merge($aBrowseParams, [
+                'new' => 1,
+            ]);
+
+            $aEvents = $this->_oDb->getEvents($aBrowseParams);
+        }
+
+        foreach($aEvents as $aEvent) {
+            if(isset($aBrowseParams[$sParamCheck]) && $aBrowseParams[$sParamCheck] !== true) 
+                continue;
+
+            $iViewerId = !empty($aBrowseParams[$sParamCheckFor]) ? (int)$aBrowseParams[$sParamCheckFor] : 0;
+
+            $oPrivacyInt = BxDolPrivacy::getObjectInstance($this->_oConfig->getObject('privacy_view'));
+            if(!$oPrivacyInt->check($aEvent['id'], $iViewerId))
+                continue;
+
+            $oPrivacyExt = $this->_oConfig->getPrivacyObject($aEvent['type'] . '_' . $aEvent['action']);
+            if($oPrivacyExt !== false && !$oPrivacyExt->check($aEvent['id'], $iViewerId))
+                continue;
+
+            $sSrvModule = $this->_oConfig->getContentModule($aEvent);
+            $sSrvMethod = 'check_allowed_with_content_for_profile';
+            if($sSrvModule && BxDolRequest::serviceExists($sSrvModule, $sSrvMethod) && BxDolService::call($sSrvModule, $sSrvMethod, array('view', $this->_oConfig->getContentObjectId($aEvent), $iViewerId)) !== CHECK_ACTION_RESULT_ALLOWED)
+                continue;
+
+            $bEventCanceled = false;
+            bx_alert($sModule, 'is_notification', 0, 0, [
+                'event' => &$aEvent, 
+                'event_canceled' => &$bEventCanceled,
+                'browse_params' => $aBrowseParams
+            ]);
+
+            if($bEventCanceled)
+                continue;
+
+            $iEvents++;
+        }
+
+        return $iEvents;
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_notifications Notifications
+     * @subsection bx_notifications-other Other
+     * @subsubsection bx_notifications-get_live_updates get_live_updates
+     * 
+     * @code bx_srv('bx_notifications', 'get_live_updates', [...]); @endcode
+     * 
+     * Get data for Live Updates system.
+     *
+     * @return an array with special format.
+     * 
+     * @see BxNtfsModule::serviceGetLiveUpdates
+     */
+    /** 
+     * @ref bx_notifications-get_live_updates "get_live_updates"
+     */
+    public function serviceGetLiveUpdates($aMenuItemParent, $aMenuItemChild, $iCount = 0)
+    {
+        $iOwnerId = $this->getUserId();
+        $iCountNew = $this->serviceGetUnreadNotificationsNum($iOwnerId);
+        if($iCountNew == $iCount)
+			return false;
+
+        return array(
+    		'count' => $iCountNew, // required
+    		'method' => 'bx_menu_show_live_update(oData)', // required
+    		'data' => array(
+    			'code' => BxDolTemplate::getInstance()->parseHtmlByTemplateName('menu_item_addon', array(
+    				'content' => '{count}'
+                )),
+                'mi_parent' => $aMenuItemParent,
+                'mi_child' => $aMenuItemChild
+    		),  // optional, may have some additional data to be passed in JS method provided using 'method' param above.
+    	);
+    }
+
+    /*
+     * COMMON METHODS
+     */
+    public function getBlockSettings($sDeliveryType, $aParams = array())
+    {
+        return $this->_oTemplate->getSettingsBlock($sDeliveryType, $aParams);
+    }
+
+    public function setSubmenu($sSelected)
+    {
+    	$oSubmenuSystem = BxDolMenu::getObjectInstance('sys_site_submenu');
+        if(!$oSubmenuSystem)
+            return;
+
+        $CNF = &$this->_oConfig->CNF;
+
+        $oSubmenuSystem->setObjectSubmenu($CNF['OBJECT_MENU_SUBMENU'], array (
+            'title' => _t('_bx_ntfs'),
+            'link' => BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink($CNF['URL_HOME']),
+            'icon' => '',
+        ));
+
+        $oSubmenuModule = BxDolMenu::getObjectInstance($CNF['OBJECT_MENU_SUBMENU']);
+        if($oSubmenuModule)
+            $oSubmenuModule->setSelected($this->_oConfig->getName(), $sSelected);
+    }
+
+    public function onPost($iId)
+    {
+    	//--- Event -> Post for Alerts Engine ---//
+        $oAlert = new BxDolAlerts($this->_oConfig->getObject('alert'), 'post', $iId);
+        $oAlert->alert();
+        //--- Event -> Post for Alerts Engine ---//
+    }
+
+    public function enableSettingsLike($iId, $bValue, $bAdministration = false)
+    {
+        $aSetting = $this->_oDb->getSetting(array(
+            'by' => $bAdministration ? 'id' : 'tsu_id', 
+            'id' => (int)$iId
+        ));
+        if(empty($aSetting) || !is_array($aSetting))
+            return false;
+
+        $aSettingsIds = $this->_oDb->getSetting(array(
+            'by' => 'group_type_delivery', 
+            'group' => $aSetting['group'], 
+            'delivery' => $aSetting['delivery'], 
+            'type' => $aSetting['type'], 
+            'active' => !$bAdministration
+        ));
+        if(empty($aSettingsIds) || !is_array($aSettingsIds))
+            return false;
+
+        $iUserId = bx_get_logged_profile_id();
+
+        $mixedResult = false;
+        if($bAdministration)
+            $mixedResult =  $this->_oDb->activateSettingById($bValue, $aSettingsIds);
+        else
+            $mixedResult = $this->_oDb->activateSettingByIdUser($bValue, $iUserId, $aSettingsIds);
+
+        return $mixedResult;
+    }
+
+    public function _changeSettingsValueLike($iId, $sField, $mixedValue, $bAdministration = false)
+    {
+        $aSetting = $this->_oDb->getSetting(array(
+            'by' => $bAdministration ? 'id' : 'tsu_id', 
+            'id' => (int)$iId
+        ));
+        if(empty($aSetting) || !is_array($aSetting))
+            return false;
+
+        $aSettingsIds = $this->_oDb->getSetting(array(
+            'by' => 'group_type_delivery', 
+            'group' => $aSetting['group'], 
+            'delivery' => $aSetting['delivery'], 
+            'type' => $aSetting['type'], 
+            'active' => !$bAdministration
+        ));
+        if(empty($aSettingsIds) || !is_array($aSettingsIds))
+            return false;
+
+        $iUserId = bx_get_logged_profile_id();
+
+        $mixedResult = false;
+        if($bAdministration)
+            $mixedResult =  $this->_oDb->changeSettingById($sField, $mixedValue, $aSettingsIds);
+        else
+            $mixedResult = $this->_oDb->changeSettingByIdUser($sField, $mixedValue, $iUserId, $aSettingsIds);
+
+        return $mixedResult;
+    }
+
+    public function sendNotificationEmail($iProfile, $aNotification)
+    {
+        if(!$iProfile)
+            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' => $iProfile, 'template' => $sTemplate, 'markers' => $aTemplateMarkers, 'notification' => $aNotification, 'override_result' => &$aTemplate));
+        if(is_null($aTemplate))
+            $aTemplate = BxDolEmailTemplates::getInstance()->parseTemplate($sTemplate, $aTemplateMarkers, 0, $iProfile);
+        if(!$aTemplate)
+            return false;
+
+        $sEmail = BxDolProfileQuery::getInstance()->getEmailById($iProfile);
+        $sSubject = !empty($aSettings['subject']) ? $aSettings['subject'] : $aTemplate['Subject'];
+        return sendMail($sEmail, $sSubject, $aTemplate['Body'], 0, array(), BX_EMAIL_NOTIFY, 'html', false, array(), true);
+    }
+
+    public function sendNotificationPush($iProfile, $aNotification)
+    {
+        if(!$iProfile)
+            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' => $iProfile, 'content' => &$aContent, 'setting' => &$aSettings, 'subject' => &$sSubject));
+   
+        return BxDolPush::getInstance()->send($iProfile, array(
+            'contents' => array(
+                'en' => $aContent['message']
+            ),
+            'headings' => array(
+                'en' => $sSubject
+            ),
+            'url' => $aContent['url'],
+            'icon' => $aContent['icon']
+        ), true);
+    }
+
+    public function groupEvents(&$aEvents)
+    {
+        //--- Check for Visual Grouping
+        $aGroups = [];
+        foreach($aEvents as $iIndex => $aEvent) {
+            if(empty($aEvent['source']))
+                continue;
+
+            $sSource = $aEvent['source'];
+            if(!isset($aGroups[$sSource]))
+               $aGroups[$sSource] = [];
+
+            $aGroups[$sSource][$iIndex] = $aEvent['priority'];
+        }
+
+        //--- Perform Visual Grouping
+        foreach($aGroups as $sSource => $aGroup) {
+            if(!is_array($aGroup) || count($aGroup) < 2)
+                continue;
+
+            arsort($aGroup);
+            $iPriorityMax = reset($aGroup);
+
+            foreach($aGroup as $iIndex => $iPriority)
+                if($iPriority != $iPriorityMax)
+                    unset($aEvents[$iIndex]);
+        }
+    }
+
+    /*
+     * 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;
+    }
+}
+
+/** @} */

+ 345 - 0
modules/boonex/notifications/updates/13.0.3_13.0.4/source/classes/BxNtfsResponse.php

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

+ 424 - 0
modules/boonex/notifications/updates/13.0.3_13.0.4/source/classes/BxNtfsTemplate.php

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

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

+ 144 - 0
modules/boonex/notifications/updates/13.0.3_13.0.4/source/install/langs/en.xml

@@ -0,0 +1,144 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources name="en" flag="gb" title="English">
+    <string name="_bx_ntfs"><![CDATA[Notifications]]></string>
+    <string name="_bx_notifications"><![CDATA[Notifications]]></string>
+
+    <string name="_bx_ntfs_page_title_system_view"><![CDATA[Notifications]]></string>
+    <string name="_bx_ntfs_page_title_view"><![CDATA[Notifications]]></string>
+    <string name="_bx_ntfs_page_block_title_view"><![CDATA[Notifications]]></string>
+    <string name="_bx_ntfs_page_title_system_settings"><![CDATA[Notifications Settings]]></string>
+    <string name="_bx_ntfs_page_title_settings"><![CDATA[Notifications Settings]]></string>
+    <string name="_bx_ntfs_page_block_title_delivery"><![CDATA[Receive via]]></string>
+    <string name="_bx_ntfs_page_block_title_settings"><![CDATA[Notifications]]></string>
+
+    <string name="_bx_ntfs_menu_title_submenu"><![CDATA[Notifications Submenu]]></string>
+    <string name="_bx_ntfs_menu_set_title_submenu"><![CDATA[Notifications Submenu]]></string>
+    <string name="_bx_ntfs_menu_item_title_system_notifications_all"><![CDATA[All Notifications]]></string>
+    <string name="_bx_ntfs_menu_item_title_notifications_all"><![CDATA[All Notifications]]></string>
+    <string name="_bx_ntfs_menu_title_settings"><![CDATA[Settings Submenu]]></string>
+    <string name="_bx_ntfs_menu_set_title_settings"><![CDATA[Settings Submenu]]></string>
+    <string name="_bx_ntfs_menu_item_title_system_notifications_site"><![CDATA[On Site]]></string>
+    <string name="_bx_ntfs_menu_item_title_notifications_site"><![CDATA[On Site]]></string>
+    <string name="_bx_ntfs_menu_item_title_system_notifications_email"><![CDATA[Email]]></string>
+    <string name="_bx_ntfs_menu_item_title_notifications_email"><![CDATA[Email]]></string>
+    <string name="_bx_ntfs_menu_item_title_system_notifications_push"><![CDATA[Push]]></string>
+    <string name="_bx_ntfs_menu_item_title_notifications_push"><![CDATA[Push]]></string>
+    <string name="_bx_ntfs_menu_item_title_system_notifications"><![CDATA[Notifications]]></string>
+    <string name="_bx_ntfs_menu_item_title_notifications"><![CDATA[Notifications]]></string>
+    <string name="_bx_ntfs_menu_item_title_system_preview"><![CDATA[Notifications]]></string>
+    <string name="_bx_ntfs_menu_item_title_preview"><![CDATA[]]></string>
+
+    <string name="_bx_ntfs_menu_title_preview"><![CDATA[Notifications Preview]]></string>
+    <string name="_bx_ntfs_menu_set_title_preview"><![CDATA[Notifications Preview]]></string>
+    <string name="_bx_ntfs_menu_item_title_system_more"><![CDATA[See all notifications]]></string>
+    <string name="_bx_ntfs_menu_item_title_more"><![CDATA[See all notifications]]></string>
+    <string name="_bx_ntfs_lmi_cpt_site"><![CDATA[On Site]]></string>
+    <string name="_bx_ntfs_lmi_cpt_email"><![CDATA[Email]]></string>
+    <string name="_bx_ntfs_lmi_cpt_push"><![CDATA[Push]]></string>
+
+    <string name="_bx_ntfs_options_category_system"><![CDATA[System]]></string>
+    <string name="_bx_ntfs_option_events_per_page"><![CDATA[Number of items per page]]></string>
+    <string name="_bx_ntfs_option_events_per_preview"><![CDATA[Number of items in preview]]></string>
+    <string name="_bx_ntfs_option_events_hide_site"><![CDATA[Onsite notifications]]></string>
+    <string name="_bx_ntfs_option_events_hide_email"><![CDATA[Email notifications]]></string>
+    <string name="_bx_ntfs_option_events_hide_push"><![CDATA[Push notifications]]></string>
+    <string name="_bx_ntfs_option_enable_group_settings"><![CDATA[Group settings by category]]></string>
+    <string name="_bx_ntfs_option_enable_group_events"><![CDATA[Group notifications by event]]></string>
+    <string name="_bx_ntfs_option_delivery_timeout"><![CDATA[Delay before sending Email and/or Push notifications (in seconds)]]></string>
+    <string name="_bx_ntfs_option_processed_event"><![CDATA[The last processed event upon notifications sending]]></string>
+    <string name="_bx_ntfs_option_clear_interval"><![CDATA[Notification lifetime, in days (0 - no limit)]]></string>
+    <string name="_bx_ntfs_option_enable_comment_post_ext"><![CDATA[Notify a user about new comments for a content he's previously commented]]></string>
+
+    <string name="_bx_ntfs_privacy_view"><![CDATA[View event]]></string>
+
+    <string name="_bx_ntfs_alert_action_group_comment"><![CDATA[New comments]]></string>
+    <string name="_bx_ntfs_alert_action_group_content_updated"><![CDATA[Content was updated]]></string>
+    <string name="_bx_ntfs_alert_action_group_action_required"><![CDATA[Your action required]]></string>    
+
+    <string name="_bx_ntfs_alert_action_added"><![CDATA[add]]></string>
+    <string name="_bx_ntfs_alert_action_commentPost"><![CDATA[add comment]]></string>
+    <string name="_bx_ntfs_alert_action_replyPost"><![CDATA[reply to own comment]]></string>
+    <string name="_bx_ntfs_alert_action_doVote"><![CDATA[add vote]]></string>
+    <string name="_bx_ntfs_alert_action_timeline_post_common"><![CDATA[post to timeline]]></string>
+    <string name="_bx_ntfs_alert_action_mention_added_personal"><![CDATA[Someone mentions you]]></string>
+    <string name="_bx_ntfs_alert_action_friendship_added_personal"><![CDATA[You get a new friend]]></string>
+    <string name="_bx_ntfs_alert_action_subscription_added_personal"><![CDATA[You get a new follower]]></string>
+    <string name="_bx_ntfs_alert_action_comment_added_personal"><![CDATA[Someone adds a comment on a content you've already commented]]></string>
+    <string name="_bx_ntfs_alert_action_added_follow_member"><![CDATA[New content]]></string>
+    <string name="_bx_ntfs_alert_action_added_follow_context"><![CDATA[New content]]></string>
+    <string name="_bx_ntfs_alert_action_commentPost_personal"><![CDATA[Someone adds a comment on your content]]></string>
+    <string name="_bx_ntfs_alert_action_commentPost_follow_member"><![CDATA[New comments]]></string>
+    <string name="_bx_ntfs_alert_action_commentPost_follow_context"><![CDATA[New comments]]></string>
+    <string name="_bx_ntfs_alert_action_replyPost_personal"><![CDATA[Someone adds a reply to your comment]]></string>
+    <string name="_bx_ntfs_alert_action_doVote_personal"><![CDATA[Someone adds a like to your content]]></string>
+    <string name="_bx_ntfs_alert_action_doVote_follow_member"><![CDATA[New likes]]></string>
+    <string name="_bx_ntfs_alert_action_doVote_follow_context"><![CDATA[New likes]]></string>
+    <string name="_bx_ntfs_alert_action_doVoteUp_personal"><![CDATA[Someone adds an 'Up' vote to your content]]></string>
+    <string name="_bx_ntfs_alert_action_doVoteUp_follow_member"><![CDATA[New 'Up' votes]]></string>
+    <string name="_bx_ntfs_alert_action_doVoteUp_follow_context"><![CDATA[New 'Up' votes]]></string>
+    <string name="_bx_ntfs_alert_action_doVoteDown_personal"><![CDATA[Someone adds a 'Down' vote to your content]]></string>
+    <string name="_bx_ntfs_alert_action_doVoteDown_follow_member"><![CDATA[New 'Down' votes]]></string>
+    <string name="_bx_ntfs_alert_action_doVoteDown_follow_context"><![CDATA[New 'Down' votes]]></string>
+    <string name="_bx_ntfs_alert_action_fan_added_personal"><![CDATA[New fans]]></string>
+    <string name="_bx_ntfs_alert_action_fan_added_follow_member"><![CDATA[New fans]]></string>
+    <string name="_bx_ntfs_alert_action_fan_added_follow_context"><![CDATA[New fans]]></string>
+    <string name="_bx_ntfs_alert_action_join_request_personal"><![CDATA[New join requests]]></string>
+    <string name="_bx_ntfs_alert_action_join_request_follow_member"><![CDATA[New join requests]]></string>
+    <string name="_bx_ntfs_alert_action_join_request_follow_context"><![CDATA[New join requests]]></string>
+    <string name="_bx_ntfs_alert_action_join_invitation_notif_personal"><![CDATA[New join invitation]]></string>
+    <string name="_bx_ntfs_alert_action_timeline_post_common_personal"><![CDATA[New posts on Timeline]]></string>
+    <string name="_bx_ntfs_alert_action_timeline_post_common_follow_member"><![CDATA[New posts on Timeline]]></string>
+    <string name="_bx_ntfs_alert_action_timeline_post_common_follow_context"><![CDATA[New posts on Timeline]]></string>
+    <string name="_bx_ntfs_alert_action_publish_failed_personal"><![CDATA[Delayed publishing failed]]></string>
+    <string name="_bx_ntfs_alert_action_publish_succeeded_personal"><![CDATA[Delayed publishing succeeded]]></string>
+    <string name="_bx_ntfs_alert_action_pending_approval_personal"><![CDATA[New pending approval content]]></string>
+    <string name="_bx_ntfs_alert_action_approved_personal"><![CDATA[Your content was approved]]></string>
+
+    <string name="_bx_ntfs_setting_title_mask"><![CDATA[{0}: {1}]]></string>
+    <string name="_bx_ntfs_setting_type_personal"><![CDATA[Activity related to you]]></string>
+    <string name="_bx_ntfs_setting_type_follow_member"><![CDATA[Activity by members you follow]]></string>
+    <string name="_bx_ntfs_setting_type_follow_context"><![CDATA[Activity in spaces (groups, events, etc.) you follow]]></string>
+    <string name="_bx_ntfs_setting_type_other"><![CDATA[Other Activity]]></string>
+
+    <string name="_bx_ntfs_alert_module_comment"><![CDATA[Comments]]></string>
+    <string name="_bx_ntfs_alert_module_sys_cmts"><![CDATA[Comments]]></string>
+    <string name="_bx_ntfs_alert_module_sys_cmts_reactions"><![CDATA[Comments' Reactions]]></string>
+    <string name="_bx_ntfs_alert_module_meta_mention"><![CDATA[Profiles Mentions]]></string>
+    <string name="_bx_ntfs_alert_module_sys_profiles_subscriptions"><![CDATA[Profiles Subscriptions]]></string>
+    <string name="_bx_ntfs_alert_module_sys_profiles_friends"><![CDATA[Profiles Friends]]></string>
+    <string name="_bx_ntfs_alert_action_connection_added"><![CDATA[add connection]]></string>
+
+    <string name="_bx_ntfs_txt_msg_no_results"><![CDATA[Empty]]></string>
+    <string name="_bx_ntfs_txt_err_nothing_changed"><![CDATA[Nothing was changed.]]></string>
+    <string name="_bx_ntfs_txt_err_cannot_perform"><![CDATA[Cannot perform the action.]]></string>
+    <string name="_bx_ntfs_txt_object_added"><![CDATA[<b class="bx-ntfs-content-profile">{owner_name}</b> added a {entry_sample} <b class="bx-ntfs-content-entry">{entry_caption}</b>]]></string>
+    <string name="_bx_ntfs_txt_object_added_in_context"><![CDATA[<b class="bx-ntfs-content-profile">{owner_name}</b> has got a {entry_sample} <b class="bx-ntfs-content-entry">{entry_caption}</b> added by <b class="bx-ntfs-content-profile">{object_owner_name}</b>]]></string>
+    <string name="_bx_ntfs_txt_object_post_common"><![CDATA[<b class="bx-ntfs-content-profile">{owner_name}</b> added a {entry_sample} <b class="bx-ntfs-content-entry">{entry_caption}</b>]]></string>
+    <string name="_bx_ntfs_txt_object_post_common_in_context"><![CDATA[<b class="bx-ntfs-content-profile">{owner_name}</b> has got a {entry_sample} <b class="bx-ntfs-content-entry">{entry_caption}</b> added by <b class="bx-ntfs-content-profile">{object_owner_name}</b>]]></string>
+    <string name="_bx_ntfs_txt_object_approved"><![CDATA[<b class="bx-ntfs-content-profile">{owner_name}</b> approved {entry_sample} <b class="bx-ntfs-content-entry">{entry_caption}</b>]]></string>
+    <string name="_bx_ntfs_txt_object_approved_in_context"><![CDATA[<b class="bx-ntfs-content-entry">{entry_caption}</b> {entry_sample} was approved in <b class="bx-ntfs-content-profile">{owner_name}</b>]]></string>
+    <string name="_bx_ntfs_txt_object_publish_failed"><![CDATA[Failed to publish your {entry_sample} <b class="bx-ntfs-content-entry">{entry_caption}</b>]]></string>
+    <string name="_bx_ntfs_txt_object_publish_succeeded"><![CDATA[Your {entry_sample} <b class="bx-ntfs-content-entry">{entry_caption}</b> was published successfully]]></string>
+    <string name="_bx_ntfs_txt_object_pending_approval"><![CDATA[<b class="bx-ntfs-content-profile">{owner_name}</b> added a pending approval {entry_sample} <b class="bx-ntfs-content-entry">{entry_caption}</b>]]></string>
+    <string name="_bx_ntfs_txt_subobject_added"><![CDATA[<b class="bx-ntfs-content-profile">{owner_name}</b> added a {subentry_sample} <b class="bx-ntfs-content-entry">{entry_caption}</b>]]></string>
+    <string name="_bx_ntfs_txt_subobject_added_in_context"><![CDATA[<b class="bx-ntfs-content-profile">{owner_name}</b> has got a {subentry_sample} <b class="bx-ntfs-content-entry">{entry_caption}</b>]]></string>
+
+    <string name="_bx_ntfs_push_new_event_subject"><![CDATA[New on "{0}"]]></string>
+
+    <string name="_bx_ntfs_email_new_event"><![CDATA[New notification]]></string>
+    <string name="_bx_ntfs_email_new_event_subject"><![CDATA[New notification on "{site_name}"]]></string>
+    <string name="_bx_ntfs_email_new_event_body"><![CDATA[{email_header}
+<p> </p>
+{content}
+<p> </p>
+{email_footer}]]></string>
+
+    <string name="_bx_ntfs_grid_column_title_active"><![CDATA[Active]]></string>
+    <string name="_bx_ntfs_grid_column_title_unit"><![CDATA[Module]]></string>
+    <string name="_bx_ntfs_grid_column_title_type"><![CDATA[Type]]></string>
+    <string name="_bx_ntfs_grid_column_title_title"><![CDATA[Notification]]></string>
+    <string name="_bx_ntfs_grid_column_title_title_warning"><![CDATA[The setting's value is corrupted. It is recommended to enable/disable it and reload the page.]]></string>
+    <string name="_bx_ntfs_grid_column_title_value"><![CDATA[Default value]]></string>
+    <string name="_bx_ntfs_grid_action_title_activate"><![CDATA[Activate]]></string>
+    <string name="_bx_ntfs_grid_action_title_deactivate"><![CDATA[Deactivate]]></string>
+</resources>

+ 173 - 0
modules/boonex/notifications/updates/13.0.3_13.0.4/source/install/sql/enable.sql

@@ -0,0 +1,173 @@
+SET @sName = 'bx_notifications';
+
+
+-- PAGES & BLOCKS
+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_notifications_view', '_bx_ntfs_page_title_system_view', '_bx_ntfs_page_title_view', @sName, 5, 2147483647, 1, 'notifications-view', 'page.php?i=notifications-view', '', '', '', 0, 1, 0, 'BxNtfsPageView', 'modules/boonex/notifications/classes/BxNtfsPageView.php');
+
+INSERT INTO `sys_pages_blocks` (`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES
+('bx_notifications_view', 1, @sName, '_bx_ntfs_page_block_title_view', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:16:"bx_notifications";s:6:"method";s:14:"get_block_view";}', 0, 1, 1);
+
+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_notifications_settings', '_bx_ntfs_page_title_system_settings', '_bx_ntfs_page_title_settings', @sName, 1, 2147483647, 1, 'notifications-settings', 'page.php?i=notifications-settings', '', '', '', 0, 1, 0, 'BxNtfsPageSettings', 'modules/boonex/notifications/classes/BxNtfsPageSettings.php');
+
+INSERT INTO `sys_pages_blocks` (`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES
+('bx_notifications_settings', 1, @sName, '_bx_ntfs_page_block_title_delivery', 13, 2147483644, 'menu', 'bx_notifications_settings', 0, 0, 1),
+('bx_notifications_settings', 2, @sName, '_bx_ntfs_page_block_title_settings', 13, 2147483644, 'service', 'a:2:{s:6:"module";s:16:"bx_notifications";s:6:"method";s:18:"get_block_settings";}', 0, 1, 1);
+
+-- PAGES: add page block on dashboard
+SET @iPBCellDashboard = 3;
+SET @iPBOrderDashboard = 4; --(SELECT IFNULL(MAX(`order`), 0) FROM `sys_pages_blocks` WHERE `object` = 'sys_dashboard' AND `cell_id` = @iPBCellDashboard LIMIT 1);
+INSERT INTO `sys_pages_blocks` (`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES
+('sys_dashboard', @iPBCellDashboard, @sName, '_bx_ntfs_page_block_title_view', 11, 2147483644, 'service', 'a:2:{s:6:"module";s:16:"bx_notifications";s:6:"method";s:14:"get_block_view";}', 0, 0, 0, @iPBOrderDashboard);
+
+
+-- MENU: module sub-menu
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_notifications_submenu', '_bx_ntfs_menu_title_submenu', 'bx_notifications_submenu', @sName, 8, 0, 1, '', '');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_notifications_submenu', @sName, '_bx_ntfs_menu_set_title_submenu', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('bx_notifications_submenu', @sName, 'notifications-all', '_bx_ntfs_menu_item_title_system_notifications_all', '_bx_ntfs_menu_item_title_notifications_all', 'page.php?i=notifications-view', '', '', '', '', 2147483647, 1, 0, 1);
+
+-- MENU: preview popup
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_notifications_preview', '_bx_ntfs_menu_title_preview', 'bx_notifications_preview', @sName, 20, 0, 1, 'BxNtfsMenuPreview', 'modules/boonex/notifications/classes/BxNtfsMenuPreview.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_notifications_preview', @sName, '_bx_ntfs_menu_set_title_preview', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('bx_notifications_preview', @sName, 'more', '_bx_ntfs_menu_item_title_system_more', '_bx_ntfs_menu_item_title_more', 'page.php?i=notifications-view', '', '', '', '', 2147483647, 1, 0, 1);
+
+-- MENU: settings sub-menu
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_notifications_settings', '_bx_ntfs_menu_title_settings', 'bx_notifications_settings', @sName, 6, 0, 1, '', '');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_notifications_settings', @sName, '_bx_ntfs_menu_set_title_settings', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('bx_notifications_settings', @sName, 'notifications-site', '_bx_ntfs_menu_item_title_system_notifications_site', '_bx_ntfs_menu_item_title_notifications_site', 'page.php?i=notifications-settings&delivery=site', '', '', '', '', 2147483647, 1, 0, 10),
+('bx_notifications_settings', @sName, 'notifications-email', '_bx_ntfs_menu_item_title_system_notifications_email', '_bx_ntfs_menu_item_title_notifications_email', 'page.php?i=notifications-settings&delivery=email', '', '', '', '', 2147483647, 1, 0, 20),
+('bx_notifications_settings', @sName, 'notifications-push', '_bx_ntfs_menu_item_title_system_notifications_push', '_bx_ntfs_menu_item_title_notifications_push', 'page.php?i=notifications-settings&delivery=push', '', '', '', '', 2147483647, 1, 0, 30);
+
+-- MENU: member toolbar
+SET @iMenuToolbarMenuOrder = (SELECT IFNULL(MAX(`order`), 0) FROM `sys_menu_items` WHERE `set_name`='sys_toolbar_member' LIMIT 1);
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `addon`, `markers`, `submenu_object`, `submenu_popup`, `visible_for_levels`, `hidden_on`, `active`, `copyable`, `order`) VALUES 
+('sys_toolbar_member', @sName, 'notifications-preview', '_bx_ntfs_menu_item_title_system_preview', '_bx_ntfs_menu_item_title_preview', 'javascript:void(0)', 'bx_menu_slide(''bx_notifications_preview'', $(this).parents(''ul:first''), ''site'', {id:{value:''bx_notifications_preview'', force:1}, pointer:{align:''right''}, cssClass: ''''});', '', 'bell col-green3', 'a:2:{s:6:"module";s:16:"bx_notifications";s:6:"method";s:28:"get_unread_notifications_num";}', '', 'bx_notifications_preview', 1, 2147483646, 9, 1, 1, 0);
+
+-- MENU: Notifications
+SET @iMIOrder = (SELECT IFNULL(MAX(`order`), 0) FROM `sys_menu_items` WHERE `set_name` = 'sys_account_notifications' AND `order` < 9999);
+INSERT INTO `sys_menu_items` (`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `addon`, `markers`, `submenu_object`, `submenu_popup`, `visible_for_levels`, `hidden_on`, `active`, `copyable`, `order`) VALUES
+('sys_account_notifications', @sName, 'notifications-notifications', '_bx_ntfs_menu_item_title_system_notifications', '_bx_ntfs_menu_item_title_notifications', 'javascript:void(0)', 'bx_menu_slide(''bx_notifications_preview'', this, ''site'', {id:{value:''bx_notifications_preview'', force:1}});', '', 'bell col-green3', 'a:2:{s:6:"module";s:16:"bx_notifications";s:6:"method";s:28:"get_unread_notifications_num";}', '', 'bx_notifications_preview', 1, 2147483646, 6, 1, 1, @iMIOrder + 1);
+
+-- 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', @sName, 'notifications-settings', '_bx_ntfs_menu_item_title_system_notifications', '_bx_ntfs_menu_item_title_notifications', 'page.php?i=notifications-settings', '', '', 'bell col-green3', '', '', 2147483646, 1, 0, 1, @iMoAccountSettings + 1);
+
+
+-- SETTINGS
+SET @iTypeOrder = (SELECT IFNULL(MAX(`order`), 0) FROM `sys_options_types` WHERE `group` = 'modules');
+INSERT INTO `sys_options_types`(`group`, `name`, `caption`, `icon`, `order`) VALUES 
+('modules', @sName, '_bx_ntfs', 'bx_notifications@modules/boonex/notifications/|std-icon.svg', @iTypeOrder + 1);
+SET @iTypeId = LAST_INSERT_ID();
+
+INSERT INTO `sys_options_categories` (`type_id`, `name`, `caption`, `hidden`, `order`) VALUES (@iTypeId, 'bx_notifications_system', '_bx_ntfs_options_category_system', 1, 1);
+SET @iCategId = LAST_INSERT_ID();
+
+INSERT INTO `sys_options` (`name`, `value`, `category_id`, `caption`, `type`, `check`, `check_params`, `check_error`, `extra`, `order`) VALUES
+('bx_notifications_events_hide_site', '', @iCategId, '_bx_ntfs_option_events_hide_site', 'rlist', '', '', '', 'a:2:{s:6:"module";s:16:"bx_notifications";s:6:"method";s:21:"get_actions_checklist";}', 1),
+('bx_notifications_events_hide_email', '', @iCategId, '_bx_ntfs_option_events_hide_email', 'rlist', '', '', '', 'a:2:{s:6:"module";s:16:"bx_notifications";s:6:"method";s:21:"get_actions_checklist";}', 2),
+('bx_notifications_events_hide_push', '', @iCategId, '_bx_ntfs_option_events_hide_push', 'rlist', '', '', '', 'a:2:{s:6:"module";s:16:"bx_notifications";s:6:"method";s:21:"get_actions_checklist";}', 3),
+('bx_notifications_processed_event', '', @iCategId, '_bx_ntfs_option_processed_event', 'digit', '', '', '', '', 10);
+
+INSERT INTO `sys_options_categories` (`type_id`, `name`, `caption`, `hidden`, `order`) VALUES (@iTypeId, @sName, '_bx_ntfs', 0, 1);
+SET @iCategId = LAST_INSERT_ID();
+
+INSERT INTO `sys_options` (`name`, `value`, `category_id`, `caption`, `type`, `check`, `check_params`, `check_error`, `extra`, `order`) VALUES
+('bx_notifications_events_per_page', '12', @iCategId, '_bx_ntfs_option_events_per_page', 'digit', '', '', '', '', 1),
+('bx_notifications_events_per_preview', '5', @iCategId, '_bx_ntfs_option_events_per_preview', 'digit', '', '', '', '', 5),
+('bx_notifications_enable_group_settings', 'on', @iCategId, '_bx_ntfs_option_enable_group_settings', 'checkbox', '', '', '', '', 10), 
+('bx_notifications_enable_group_events', 'on', @iCategId, '_bx_ntfs_option_enable_group_events', 'checkbox', '', '', '', '', 11), 
+('bx_notifications_delivery_timeout', '120', @iCategId, '_bx_ntfs_option_delivery_timeout', 'digit', '', '', '', '', 20),
+('bx_notifications_clear_interval', '0', @iCategId, '_bx_ntfs_option_clear_interval', 'digit', '', '', '', '', 30),
+('bx_notifications_enable_comment_post_ext', '', @iCategId, '_bx_ntfs_option_enable_comment_post_ext', 'checkbox', '', '', '', '', 40);
+
+
+-- PRIVACY 
+INSERT INTO `sys_objects_privacy` (`object`, `module`, `action`, `title`, `default_group`, `table`, `table_field_id`, `table_field_author`, `override_class_name`, `override_class_file`) VALUES
+('bx_notifications_privacy_view', @sName, 'view', '_bx_notifications_privacy_view', '3', 'bx_notifications_events', 'id', 'owner_id', 'BxNtfsPrivacy', 'modules/boonex/notifications/classes/BxNtfsPrivacy.php');
+
+
+-- LIVE UPDATES
+INSERT INTO `sys_objects_live_updates`(`name`, `frequency`, `service_call`, `active`) VALUES
+(@sName, 1, 'a:3:{s:6:"module";s:16:"bx_notifications";s:6:"method";s:16:"get_live_updates";s:6:"params";a:3:{i:0;a:2:{s:11:"menu_object";s:18:"sys_toolbar_member";s:9:"menu_item";s:7:"account";}i:1;a:2:{s:11:"menu_object";s:25:"sys_account_notifications";s:9:"menu_item";s:27:"notifications-notifications";}i:2;s:7:"{count}";}}', 1),
+('bx_notifications_toolbar', 1, 'a:3:{s:6:"module";s:16:"bx_notifications";s:6:"method";s:16:"get_live_updates";s:6:"params";a:3:{i:0;a:0:{}i:1;a:2:{s:11:"menu_object";s:18:"sys_toolbar_member";s:9:"menu_item";s:21:"notifications-preview";}i:2;s:7:"{count}";}}', 1);
+
+
+-- ALERTS
+INSERT INTO `sys_alerts_handlers`(`name`, `class`, `file`, `service_call`) VALUES 
+(@sName, 'BxNtfsResponse', 'modules/boonex/notifications/classes/BxNtfsResponse.php', '');
+SET @iHandler := LAST_INSERT_ID();
+
+INSERT INTO `sys_alerts` (`unit`, `action`, `handler_id`) VALUES
+('profile', 'delete', @iHandler),
+
+('comment', 'added', @iHandler),
+('comment', 'deleted', @iHandler),
+
+('meta_mention', 'added', @iHandler),
+
+('sys_profiles_friends', 'connection_added', @iHandler),
+('sys_profiles_friends', 'connection_removed', @iHandler),
+
+('sys_profiles_subscriptions', 'connection_added', @iHandler),
+('sys_profiles_subscriptions', 'connection_removed', @iHandler),
+
+('sys_cmts', 'doVote', @iHandler),
+('sys_cmts', 'undoVote', @iHandler),
+
+('sys_cmts_reactions', 'doVote', @iHandler),
+('sys_cmts_reactions', 'undoVote', @iHandler),
+
+('sys_cmts', 'doVoteUp', @iHandler),
+('sys_cmts', 'doVoteDown', @iHandler);
+
+
+-- EMAIL TEMPLATES
+INSERT INTO `sys_email_templates` (`Module`, `NameSystem`, `Name`, `Subject`, `Body`) VALUES
+(@sName, '_bx_ntfs_email_new_event', 'bx_notifications_new_event', '_bx_ntfs_email_new_event_subject', '_bx_ntfs_email_new_event_body');
+
+
+-- GRIDS
+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`, `visible_for_levels`, `override_class_name`, `override_class_file`) VALUES
+('bx_notifications_settings_administration', 'Sql', 'SELECT `ts`.*, `th`.`alert_unit` AS `unit`, `th`.`alert_action` AS `action` FROM `bx_notifications_settings` AS `ts` LEFT JOIN `bx_notifications_handlers` AS `th` ON `ts`.`handler_id`=`th`.`id` WHERE 1 ', 'bx_notifications_settings', 'id', 'order', 'active', '', 100, NULL, 'start', '', '', 'ts`.`title', 'auto', '', 192, 'BxNtfsGridSettingsAdministration', 'modules/boonex/notifications/classes/BxNtfsGridSettingsAdministration.php'),
+('bx_notifications_settings_common', 'Sql', 'SELECT `tsu`.`id` AS `id`, `ts`.`group` AS `group`, `ts`.`id` AS `setting_id`, `ts`.`type` AS `type`, `ts`.`delivery` AS `delivery`, `ts`.`title` AS `title`, `tsu`.`active` AS `active`, `ts`.`order` AS `order`, `th`.`alert_unit` AS `unit`, `th`.`alert_action` AS `action` FROM `bx_notifications_settings` AS `ts` LEFT JOIN `bx_notifications_handlers` AS `th` ON `ts`.`handler_id`=`th`.`id` LEFT JOIN `bx_notifications_settings2users` AS `tsu` ON `ts`.`id`=`tsu`.`setting_id` WHERE `ts`.`active`=''1'' ', 'bx_notifications_settings2users', 'id', 'order', 'active', '', 100, NULL, 'start', '', '', 'ts`.`title', 'auto', '', 2147483647, 'BxNtfsGridSettingsCommon', 'modules/boonex/notifications/classes/BxNtfsGridSettingsCommon.php');
+
+INSERT INTO `sys_grid_fields` (`object`, `name`, `title`, `width`, `translatable`, `chars_limit`, `params`, `order`) VALUES
+('bx_notifications_settings_administration', 'checkbox', '', '1%', 0, '', '', 1),
+('bx_notifications_settings_administration', 'switcher', '_bx_ntfs_grid_column_title_active', '10%', 0, '', '', 2),
+('bx_notifications_settings_administration', 'title', '_bx_ntfs_grid_column_title_title', '79%', 1, '', '', 10),
+('bx_notifications_settings_administration', 'value', '_bx_ntfs_grid_column_title_value', '10%', 0, '', '', 20),
+
+('bx_notifications_settings_common', 'checkbox', '', '1%', 0, '', '', 1),
+('bx_notifications_settings_common', 'switcher', '', '10%', 0, '', '', 2),
+('bx_notifications_settings_common', 'title', '_bx_ntfs_grid_column_title_title', '89%', 1, '', '', 10);
+
+INSERT INTO `sys_grid_actions` (`object`, `type`, `name`, `title`, `icon`, `confirm`, `order`) VALUES
+('bx_notifications_settings_administration', 'bulk', 'activate', '_bx_ntfs_grid_action_title_activate', '', 1, 1),
+('bx_notifications_settings_administration', 'bulk', 'deactivate', '_bx_ntfs_grid_action_title_deactivate', '', 1, 2),
+
+('bx_notifications_settings_common', 'bulk', 'activate', '_bx_ntfs_grid_action_title_activate', '', 1, 1),
+('bx_notifications_settings_common', 'bulk', 'deactivate', '_bx_ntfs_grid_action_title_deactivate', '', 1, 2);
+
+
+-- CRON
+INSERT INTO `sys_cron_jobs` (`name`, `time`, `class`, `file`, `service_call`) VALUES
+('bx_notifications_queue', '* * * * *', 'BxNtfsCronQueue', 'modules/boonex/notifications/classes/BxNtfsCronQueue.php', ''),
+('bx_notifications_notify', '* * * * *', 'BxNtfsCronNotify', 'modules/boonex/notifications/classes/BxNtfsCronNotify.php', ''),
+('bx_notifications_clean', '* * * * *', 'BxNtfsCronClean', 'modules/boonex/notifications/classes/BxNtfsCronClean.php', '');

+ 216 - 0
modules/boonex/notifications/updates/13.0.3_13.0.4/source/install/sql/install.sql

@@ -0,0 +1,216 @@
+SET @sName = 'bx_notifications';
+
+
+-- TABLES
+CREATE TABLE IF NOT EXISTS `bx_notifications_events` (
+  `id` int(11) NOT NULL auto_increment,
+  `owner_id` int(11) NOT NULL default '0',
+  `type` varchar(255) NOT NULL,
+  `action` varchar(255) NOT NULL,
+  `object_id` text NOT NULL,
+  `object_owner_id` int(11) NOT NULL default '0',
+  `object_privacy_view` varchar(32) NOT NULL default '3',
+  `subobject_id` int(11) NOT NULL default '0',
+  `content` text NOT NULL,
+  `source` varchar(32) NOT NULL default '',
+  `allow_view_event_to` varchar(32) NOT NULL default '3',
+  `date` int(11) NOT NULL default '0',
+  `processed` tinyint(4) NOT NULL default '0',
+  `active` tinyint(4) NOT NULL default '1',
+  PRIMARY KEY  (`id`),
+  KEY `owner_id` (`owner_id`),
+  KEY `object_owner_id` (`object_owner_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_notifications_events2users` (
+  `user_id` int(11) NOT NULL DEFAULT '0',
+  `event_id` int(11) NOT NULL DEFAULT '0',
+  PRIMARY KEY (`user_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_notifications_handlers` (
+  `id` int(11) NOT NULL auto_increment,
+  `group` varchar(64) NOT NULL default '',
+  `type` enum('insert','update','delete') NOT NULL DEFAULT 'insert',
+  `alert_unit` varchar(64) NOT NULL default '',
+  `alert_action` varchar(64) NOT NULL default '',
+  `content` text NOT NULL,
+  `privacy` varchar(64) NOT NULL default '',
+  `priority` int(11) NOT NULL default '0',
+  PRIMARY KEY  (`id`),
+  UNIQUE `handler` (`group`, `type`),
+  UNIQUE `alert` (`alert_unit`, `alert_action`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_notifications_settings` (
+  `id` int(11) NOT NULL auto_increment,
+  `group` varchar(64) NOT NULL default '',
+  `handler_id` int(11) NOT NULL DEFAULT '0',
+  `delivery` enum('site','email','push') NOT NULL DEFAULT 'site',
+  `type` enum('personal','follow_member','follow_context','other') NOT NULL DEFAULT 'personal',
+  `title` varchar(64) NOT NULL default '',
+  `value` tinyint(4) NOT NULL default '1',
+  `active` tinyint(4) NOT NULL default '1',
+  `order` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  UNIQUE `setting` (`handler_id`, `type`, `delivery`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_notifications_settings2users` (
+  `id` int(11) NOT NULL auto_increment,
+  `user_id` int(11) NOT NULL DEFAULT '0',
+  `setting_id` int(11) NOT NULL DEFAULT '0',
+  `active` tinyint(4) NOT NULL default '1',
+  PRIMARY KEY (`id`),
+  UNIQUE `setting` (`setting_id`, `user_id`)
+);
+
+INSERT INTO `bx_notifications_handlers`(`group`, `type`, `alert_unit`, `alert_action`, `content`) VALUES 
+('profile', 'delete', 'profile', 'delete', '');
+
+-- Mentions
+INSERT INTO `bx_notifications_handlers`(`group`, `type`, `alert_unit`, `alert_action`, `content`, `privacy`, `priority`) VALUES 
+('mention', 'insert', 'meta_mention', 'added', 'a:3:{s:11:"module_name";s:6:"system";s:13:"module_method";s:30:"get_notifications_post_mention";s:12:"module_class";s:20:"TemplServiceMetatags";}', '', 1);
+SET @iHandlerId = LAST_INSERT_ID();
+
+INSERT INTO `bx_notifications_settings`(`group`, `handler_id`, `delivery`, `type`, `title`, `order`) VALUES
+('mention', @iHandlerId, 'site', 'personal', '_bx_ntfs_alert_action_mention_added_personal', 1),
+('mention', @iHandlerId, 'email', 'personal', '_bx_ntfs_alert_action_mention_added_personal', 1),
+('mention', @iHandlerId, 'push', 'personal', '_bx_ntfs_alert_action_mention_added_personal', 1);
+
+-- Friendship
+INSERT INTO `bx_notifications_handlers`(`group`, `type`, `alert_unit`, `alert_action`, `content`) VALUES 
+('friendship', 'insert', 'sys_profiles_friends', 'connection_added', 'a:3:{s:11:"module_name";s:6:"system";s:13:"module_method";s:33:"get_notifications_post_friendship";s:12:"module_class";s:23:"TemplServiceConnections";}');
+SET @iHandlerId = LAST_INSERT_ID();
+
+INSERT INTO `bx_notifications_settings`(`group`, `handler_id`, `delivery`, `type`, `title`, `order`) VALUES
+('friendship', @iHandlerId, 'site', 'personal', '_bx_ntfs_alert_action_friendship_added_personal', 2),
+('friendship', @iHandlerId, 'email', 'personal', '_bx_ntfs_alert_action_friendship_added_personal', 2),
+('friendship', @iHandlerId, 'push', 'personal', '_bx_ntfs_alert_action_friendship_added_personal', 2);
+
+INSERT INTO `bx_notifications_handlers`(`group`, `type`, `alert_unit`, `alert_action`, `content`) VALUES 
+('friendship', 'delete', 'sys_profiles_friends', 'connection_removed', '');
+
+-- Subscription
+INSERT INTO `bx_notifications_handlers`(`group`, `type`, `alert_unit`, `alert_action`, `content`) VALUES 
+('subscription', 'insert', 'sys_profiles_subscriptions', 'connection_added', 'a:3:{s:11:"module_name";s:6:"system";s:13:"module_method";s:22:"get_notifications_post";s:12:"module_class";s:23:"TemplServiceConnections";}');
+SET @iHandlerId = LAST_INSERT_ID();
+
+INSERT INTO `bx_notifications_settings`(`group`, `handler_id`, `delivery`, `type`, `title`, `order`) VALUES
+('subscription', @iHandlerId, 'site', 'personal', '_bx_ntfs_alert_action_subscription_added_personal', 3),
+('subscription', @iHandlerId, 'email', 'personal', '_bx_ntfs_alert_action_subscription_added_personal', 3),
+('subscription', @iHandlerId, 'push', 'personal', '_bx_ntfs_alert_action_subscription_added_personal', 3);
+
+INSERT INTO `bx_notifications_handlers`(`group`, `type`, `alert_unit`, `alert_action`, `content`) VALUES 
+('subscription', 'delete', 'sys_profiles_subscriptions', 'connection_removed', '');
+
+-- Comments
+INSERT INTO `bx_notifications_handlers`(`group`, `type`, `alert_unit`, `alert_action`, `content`) VALUES 
+('comment', 'insert', 'comment', 'added', 'a:3:{s:11:"module_name";s:6:"system";s:13:"module_method";s:31:"get_notifications_comment_added";s:12:"module_class";s:17:"TemplCmtsServices";}');
+SET @iHandlerId = LAST_INSERT_ID();
+
+INSERT INTO `bx_notifications_settings`(`group`, `handler_id`, `delivery`, `type`, `title`, `order`) VALUES
+('comment', @iHandlerId, 'site', 'personal', '_bx_ntfs_alert_action_comment_added_personal', 1),
+('comment', @iHandlerId, 'email', 'personal', '_bx_ntfs_alert_action_comment_added_personal', 1),
+('comment', @iHandlerId, 'push', 'personal', '_bx_ntfs_alert_action_comment_added_personal', 1);
+
+INSERT INTO `bx_notifications_handlers`(`group`, `type`, `alert_unit`, `alert_action`, `content`) VALUES 
+('comment', 'delete', 'comment', 'deleted', '');
+
+-- Comments Actions (Like, Reaction, Score Up\Down)
+INSERT INTO `bx_notifications_handlers`(`group`, `type`, `alert_unit`, `alert_action`, `content`, `privacy`) VALUES 
+('sys_cmts_vote', 'insert', 'sys_cmts', 'doVote', 'a:3:{s:11:"module_name";s:6:"system";s:13:"module_method";s:22:"get_notifications_vote";s:12:"module_class";s:17:"TemplCmtsServices";}', '');
+SET @iHandlerId = LAST_INSERT_ID();
+
+INSERT INTO `bx_notifications_settings`(`group`, `handler_id`, `delivery`, `type`, `title`, `order`) VALUES
+('vote', @iHandlerId, 'site', 'personal', '_bx_ntfs_alert_action_doVote_personal', 4),
+('vote', @iHandlerId, 'email', 'personal', '_bx_ntfs_alert_action_doVote_personal', 4),
+('vote', @iHandlerId, 'push', 'personal', '_bx_ntfs_alert_action_doVote_personal', 4),
+
+('vote', @iHandlerId, 'site', 'follow_member', '_bx_ntfs_alert_action_doVote_follow_member', 1),
+('vote', @iHandlerId, 'email', 'follow_member', '_bx_ntfs_alert_action_doVote_follow_member', 1),
+('vote', @iHandlerId, 'push', 'follow_member', '_bx_ntfs_alert_action_doVote_follow_member', 1),
+
+('vote', @iHandlerId, 'site', 'follow_context', '_bx_ntfs_alert_action_doVote_follow_context', 1),
+('vote', @iHandlerId, 'email', 'follow_context', '_bx_ntfs_alert_action_doVote_follow_context', 1),
+('vote', @iHandlerId, 'push', 'follow_context', '_bx_ntfs_alert_action_doVote_follow_context', 1);
+
+INSERT INTO `bx_notifications_handlers`(`group`, `type`, `alert_unit`, `alert_action`, `content`) VALUES 
+('sys_cmts_vote', 'delete', 'sys_cmts', 'undoVote', '');
+
+INSERT INTO `bx_notifications_handlers`(`group`, `type`, `alert_unit`, `alert_action`, `content`, `privacy`) VALUES 
+('sys_cmts_reaction', 'insert', 'sys_cmts_reactions', 'doVote', 'a:3:{s:11:"module_name";s:6:"system";s:13:"module_method";s:26:"get_notifications_reaction";s:12:"module_class";s:17:"TemplCmtsServices";}', '');
+SET @iHandlerId = LAST_INSERT_ID();
+
+INSERT INTO `bx_notifications_settings`(`group`, `handler_id`, `delivery`, `type`, `title`, `order`) VALUES
+('vote', @iHandlerId, 'site', 'personal', '_bx_ntfs_alert_action_doVote_personal', 5),
+('vote', @iHandlerId, 'email', 'personal', '_bx_ntfs_alert_action_doVote_personal', 5),
+('vote', @iHandlerId, 'push', 'personal', '_bx_ntfs_alert_action_doVote_personal', 5),
+
+('vote', @iHandlerId, 'site', 'follow_member', '_bx_ntfs_alert_action_doVote_follow_member', 2),
+('vote', @iHandlerId, 'email', 'follow_member', '_bx_ntfs_alert_action_doVote_follow_member', 2),
+('vote', @iHandlerId, 'push', 'follow_member', '_bx_ntfs_alert_action_doVote_follow_member', 2),
+
+('vote', @iHandlerId, 'site', 'follow_context', '_bx_ntfs_alert_action_doVote_follow_context', 2),
+('vote', @iHandlerId, 'email', 'follow_context', '_bx_ntfs_alert_action_doVote_follow_context', 2),
+('vote', @iHandlerId, 'push', 'follow_context', '_bx_ntfs_alert_action_doVote_follow_context', 2);
+
+INSERT INTO `bx_notifications_handlers`(`group`, `type`, `alert_unit`, `alert_action`, `content`) VALUES 
+('sys_cmts_reaction', 'delete', 'sys_cmts_reactions', 'undoVote', '');
+
+INSERT INTO `bx_notifications_handlers`(`group`, `type`, `alert_unit`, `alert_action`, `content`, `privacy`) VALUES 
+('sys_cmts_score_up', 'insert', 'sys_cmts', 'doVoteUp', 'a:3:{s:11:"module_name";s:6:"system";s:13:"module_method";s:26:"get_notifications_score_up";s:12:"module_class";s:17:"TemplCmtsServices";}', '');
+SET @iHandlerId = LAST_INSERT_ID();
+
+INSERT INTO `bx_notifications_settings`(`group`, `handler_id`, `delivery`, `type`, `title`, `order`) VALUES
+('score_up', @iHandlerId, 'site', 'personal', '_bx_ntfs_alert_action_doVoteUp_personal', 6),
+('score_up', @iHandlerId, 'email', 'personal', '_bx_ntfs_alert_action_doVoteUp_personal', 6),
+('score_up', @iHandlerId, 'push', 'personal', '_bx_ntfs_alert_action_doVoteUp_personal', 6),
+
+('score_up', @iHandlerId, 'site', 'follow_member', '_bx_ntfs_alert_action_doVoteUp_follow_member', 3),
+('score_up', @iHandlerId, 'email', 'follow_member', '_bx_ntfs_alert_action_doVoteUp_follow_member', 3),
+('score_up', @iHandlerId, 'push', 'follow_member', '_bx_ntfs_alert_action_doVoteUp_follow_member', 3),
+
+('score_up', @iHandlerId, 'site', 'follow_context', '_bx_ntfs_alert_action_doVoteUp_follow_context', 3),
+('score_up', @iHandlerId, 'email', 'follow_context', '_bx_ntfs_alert_action_doVoteUp_follow_context', 3),
+('score_up', @iHandlerId, 'push', 'follow_context', '_bx_ntfs_alert_action_doVoteUp_follow_context', 3);
+
+INSERT INTO `bx_notifications_handlers`(`group`, `type`, `alert_unit`, `alert_action`, `content`, `privacy`) VALUES 
+('sys_cmts_score_down', 'insert', 'sys_cmts', 'doVoteDown', 'a:3:{s:11:"module_name";s:6:"system";s:13:"module_method";s:28:"get_notifications_score_down";s:12:"module_class";s:17:"TemplCmtsServices";}', '');
+SET @iHandlerId = LAST_INSERT_ID();
+
+INSERT INTO `bx_notifications_settings`(`group`, `handler_id`, `delivery`, `type`, `title`, `order`) VALUES
+('score_down', @iHandlerId, 'site', 'personal', '_bx_ntfs_alert_action_doVoteDown_personal', 7),
+('score_down', @iHandlerId, 'email', 'personal', '_bx_ntfs_alert_action_doVoteDown_personal', 7),
+('score_down', @iHandlerId, 'push', 'personal', '_bx_ntfs_alert_action_doVoteDown_personal', 7),
+
+('score_down', @iHandlerId, 'site', 'follow_member', '_bx_ntfs_alert_action_doVoteDown_follow_member', 4),
+('score_down', @iHandlerId, 'email', 'follow_member', '_bx_ntfs_alert_action_doVoteDown_follow_member', 4),
+('score_down', @iHandlerId, 'push', 'follow_member', '_bx_ntfs_alert_action_doVoteDown_follow_member', 4),
+
+('score_down', @iHandlerId, 'site', 'follow_context', '_bx_ntfs_alert_action_doVoteDown_follow_context', 4),
+('score_down', @iHandlerId, 'email', 'follow_context', '_bx_ntfs_alert_action_doVoteDown_follow_context', 4),
+('score_down', @iHandlerId, 'push', 'follow_context', '_bx_ntfs_alert_action_doVoteDown_follow_context', 4);
+
+CREATE TABLE IF NOT EXISTS `bx_notifications_queue` (
+  `id` int(11) NOT NULL auto_increment,
+  `profile_id` int(11) NOT NULL DEFAULT '0',
+  `event_id` int(11) NOT NULL DEFAULT '0',
+  `delivery` varchar(64) NOT NULL default '',
+  `content` text NOT NULL,
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY  (`id`)
+);
+
+
+-- STUDIO PAGE & WIDGET
+INSERT INTO `sys_std_pages`(`index`, `name`, `header`, `caption`, `icon`) VALUES
+(3, @sName, '_bx_ntfs', '_bx_ntfs', 'bx_notifications@modules/boonex/notifications/|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, 'extensions', '{url_studio}module.php?name=bx_notifications', '', 'bx_notifications@modules/boonex/notifications/|std-icon.svg', '_bx_ntfs', '', '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/organizations/updates/13.0.3_13.0.4/install/config.php

@@ -0,0 +1,51 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'title' => 'Organizations',
+    'version_from' => '13.0.3',
+    'version_to' => '13.0.4',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '13.0.0-B4'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/organizations/updates/update_13.0.3_13.0.4/',
+    'home_uri' => 'orgs_update_1303_1304',
+
+    'module_dir' => 'boonex/organizations/',
+    'module_uri' => 'orgs',
+
+    'db_prefix' => 'bx_organizations_',
+    'class_prefix' => 'BxOrgs',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_files' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Organizations',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

+ 13 - 0
modules/boonex/organizations/updates/13.0.3_13.0.4/install/installer.php

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

+ 16 - 0
modules/boonex/organizations/updates/13.0.3_13.0.4/install/langs/en.xml

@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources name="en" flag="gb" title="English">
+	<string_add name="_bx_orgs_acl_action_delete_invites"><![CDATA[Delete Invites]]></string_add>
+	<string_add name="_bx_orgs_page_block_title_fans_invites"><![CDATA[Invites]]></string_add>
+	<string_add name="_bx_orgs_page_block_title_system_invites"><![CDATA[Invites]]></string_add>
+	<string_add name="_bx_orgs_txt_invite_popup_text"><![CDATA[You have been invited to an organization. Click the button below to accept the invitation.]]></string_add>
+	<string_add name="_bx_orgs_txt_invite_popup_title"><![CDATA[Invitation to an organization]]></string_add>
+	<string_add name="_bx_orgs_txt_invite_popup_button_accept"><![CDATA[Accept]]></string_add>
+	<string_add name="_bx_orgs_txt_invite_popup_button_decline"><![CDATA[Decline]]></string_add>
+	<string_add name="_bx_orgs_txt_invite_popup_error_invitation_absent"><![CDATA[Sorry, an error has occurred. You can not join this organization. The invitation is expired or deleted.]]></string_add>
+	<string_add name="_bx_orgs_txt_invite_popup_error_invitation_wrong_user"><![CDATA[Sorry, an error has occurred. You can not join this organization. This invitation cannot be used by you.]]></string_add>
+
+	<string_del name="_bx_orgs_menu_item_title_system_delete"><![CDATA[Delete]]></string_del>
+	<string_del name="_bx_orgs_menu_item_title_delete"><![CDATA[Delete]]></string_del>
+	<string_del name="_bx_orgs_grid_action_title_adm_delete"><![CDATA[Delete]]></string_del>
+</resources>

+ 45 - 0
modules/boonex/organizations/updates/13.0.3_13.0.4/install/sql/enable.sql

@@ -0,0 +1,45 @@
+-- PAGES 
+DELETE FROM `sys_pages_blocks` WHERE `object`='bx_organizations_fans' AND `title`='_bx_orgs_page_block_title_fans_invites';
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_organizations_fans', 1, 'bx_organizations', '_bx_orgs_page_block_title_system_invites', '_bx_orgs_page_block_title_fans_invites', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:16:"bx_organizations";s:6:"method";s:13:"invites_table";}', 0, 0, 1, 2);
+
+
+-- MENUS
+DELETE FROM `sys_menu_items` WHERE `set_name`='bx_organizations_menu_manage_tools' AND `name`='delete';
+
+
+-- ACL
+SET @iIdActionProfileDeleteInvites = (SELECT `ID` FROM `sys_acl_actions` WHERE `Module`='bx_organizations' AND `Name`='delete invites' LIMIT 1);
+DELETE FROM `sys_acl_actions` WHERE `ID`=@iIdActionProfileDeleteInvites;
+DELETE FROM `sys_acl_matrix` WHERE `IDAction`=@iIdActionProfileDeleteInvites;
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_organizations', 'delete invites', NULL, '_bx_orgs_acl_action_delete_invites', '', 1, 3);
+SET @iIdActionProfileDeleteInvites = LAST_INSERT_ID();
+
+SET @iModerator = 7;
+SET @iAdministrator = 8;
+
+INSERT INTO `sys_acl_matrix` (`IDLevel`, `IDAction`) VALUES
+(@iModerator, @iIdActionProfileDeleteInvites),
+(@iAdministrator, @iIdActionProfileDeleteInvites);
+
+
+-- GRIDS
+DELETE FROM `sys_objects_grid` WHERE `object`='bx_organizations_invites';
+INSERT INTO `sys_objects_grid` (`object`, `source_type`, `source`, `table`, `field_id`, `field_order`, `field_active`, `paginate_url`, `paginate_per_page`, `paginate_simple`, `paginate_get_start`, `paginate_get_per_page`, `filter_fields`, `filter_fields_translatable`, `filter_mode`, `sorting_fields`, `sorting_fields_translatable`, `visible_for_levels`, `responsive`, `override_class_name`, `override_class_file`) VALUES
+('bx_organizations_invites', 'Sql', 'SELECT `i`.`id`, `i`.`invited_profile_id`, `i`.`added`, `i`.`author_profile_id` FROM `sys_profiles` AS `p` INNER JOIN `sys_accounts` AS `a` ON `a`.`id` = `p`.`account_id` INNER JOIN `bx_organizations_invites` AS `i` ON `i`.`invited_profile_id` = `p`.`id` ', 'bx_organizations_invites', 'id', 'i`.`added', '', '', 10, NULL, 'start', '', 'name,email', '', 'auto', '', '', 2147483647, 0, 'BxOrgsGridInvites', 'modules/boonex/organizations/classes/BxOrgsGridInvites.php');
+
+DELETE FROM `sys_grid_fields` WHERE `object`='bx_organizations_invites';
+INSERT INTO `sys_grid_fields` (`object`, `name`, `title`, `width`, `params`, `order`) VALUES
+('bx_organizations_invites', 'name', '_sys_name', '33%', '', 10),
+('bx_organizations_invites', 'added', '_sys_added', '33%', '', 20),
+('bx_organizations_invites', 'actions', '', '34%', '', 30);
+
+DELETE FROM `sys_grid_actions` WHERE `object`='bx_organizations_invites';
+INSERT INTO `sys_grid_actions` (`object`, `type`, `name`, `title`, `icon`, `confirm`, `order`) VALUES
+('bx_organizations_invites', 'single', 'delete', '', 'remove', 1, 10);
+
+
+DELETE FROM `sys_grid_actions` WHERE `object`='bx_organizations_administration' AND `type`='bulk' AND `name`='delete';
+DELETE FROM `sys_grid_actions` WHERE `object`='bx_organizations_common' AND `type`='bulk' AND `name`='delete';

+ 10 - 0
modules/boonex/organizations/updates/13.0.3_13.0.4/install/sql/install.sql

@@ -0,0 +1,10 @@
+-- TABLES
+CREATE TABLE IF NOT EXISTS `bx_organizations_invites` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `key` varchar(128) NOT NULL default '0',
+  `group_profile_id` int(11) NOT NULL default '0',
+  `author_profile_id` int(11) NOT NULL default '0',
+  `invited_profile_id` int(11) NOT NULL default '0',
+  `added` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`)
+);

+ 322 - 0
modules/boonex/organizations/updates/13.0.3_13.0.4/source/classes/BxOrgsConfig.php

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

+ 21 - 0
modules/boonex/organizations/updates/13.0.3_13.0.4/source/classes/BxOrgsGridInvites.php

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

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

+ 577 - 0
modules/boonex/organizations/updates/13.0.3_13.0.4/source/install/langs/en.xml

@@ -0,0 +1,577 @@
+<?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_homepage"><![CDATA[Homepage]]></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_enable_subscribe_wo_join"><![CDATA[Allow to follow without join]]></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[Approval required to join]]></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_form_price"><![CDATA[Price]]></string>
+    <string name="_bx_orgs_form_price_display_add"><![CDATA[Add]]></string>
+    <string name="_bx_orgs_form_price_display_edit"><![CDATA[Edit]]></string>
+    <string name="_bx_orgs_form_price_input_sys_id"><![CDATA[ID]]></string>
+    <string name="_bx_orgs_form_price_input_sys_role_id"><![CDATA[Role ID]]></string>
+    <string name="_bx_orgs_form_price_input_sys_name"><![CDATA[Name]]></string>
+    <string name="_bx_orgs_form_price_input_name"><![CDATA[Name]]></string>
+    <string name="_bx_orgs_form_price_input_inf_name"><![CDATA[Unique value which will be used in back end and API calls]]></string>
+    <string name="_bx_orgs_form_price_input_err_name"><![CDATA[You need to enter a unique value here]]></string>
+    <string name="_bx_orgs_form_price_input_sys_period"><![CDATA[Period]]></string>
+    <string name="_bx_orgs_form_price_input_period"><![CDATA[Period]]></string>
+    <string name="_bx_orgs_form_price_input_inf_period"><![CDATA[Use 0 for lifetime]]></string>
+    <string name="_bx_orgs_form_price_input_sys_period_unit"><![CDATA[Period unit]]></string>
+    <string name="_bx_orgs_form_price_input_period_unit"><![CDATA[Period unit]]></string>
+    <string name="_bx_orgs_form_price_input_inf_period_unit"><![CDATA[Leave empty for lifetime level.]]></string>
+    <string name="_bx_orgs_form_price_input_err_period_unit"><![CDATA[You need to select a period unit here.]]></string>
+    <string name="_bx_orgs_form_price_input_sys_price"><![CDATA[Price]]></string>
+    <string name="_bx_orgs_form_price_input_price"><![CDATA[Price]]></string>
+    <string name="_bx_orgs_form_price_input_inf_price"><![CDATA[Use 0 or leave empty to create free level.]]></string>
+    <string name="_bx_orgs_form_price_input_sys_do_submit"><![CDATA[Submit]]></string>
+    <string name="_bx_orgs_form_price_input_do_submit"><![CDATA[Submit]]></string>
+    <string name="_bx_orgs_form_price_input_sys_do_cancel"><![CDATA[Cancel]]></string>
+    <string name="_bx_orgs_form_price_input_do_cancel"><![CDATA[Cancel]]></string>
+
+    <string name="_bx_orgs_acl_action_create_profile"><![CDATA[Create Organization's Profile]]></string>
+    <string name="_bx_orgs_acl_action_use_paid_join"><![CDATA[Use paid join]]></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_acl_action_delete_any_profile"><![CDATA[Delete Any Organization's Profile]]></string>
+    <string name="_bx_orgs_acl_action_delete_invites"><![CDATA[Delete Invites]]></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_join_profile"><![CDATA[Join Organization]]></string>
+    <string name="_bx_orgs_page_title_join_profile"><![CDATA[Join Organization]]></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_familiar"><![CDATA[Organizations You May Know]]></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_profile_pricing"><![CDATA[Pricing]]></string>
+    <string name="_bx_orgs_page_title_profile_pricing"><![CDATA[Pricing]]></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[Favorites Organizations]]></string>
+    <string name="_bx_orgs_page_title_entries_favorites"><![CDATA[Favorites 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_join_profile"><![CDATA[Join Organization]]></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_system_profile_pricing"><![CDATA[Pricing]]></string>
+    <string name="_bx_orgs_page_block_title_profile_pricing"><![CDATA[Pricing]]></string>
+    <string name="_bx_orgs_page_block_title_profile_pricing_link"><![CDATA[Pricing of <a href="{profile_link}">{display_name}</a>]]></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_profile_friends_mutual"><![CDATA[Mutual 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_fans_invites"><![CDATA[Invites]]></string>
+    <string name="_bx_orgs_page_block_title_system_invites"><![CDATA[Invites]]></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_entry_reports"><![CDATA[Reports]]></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_sys_familiar_profiles"><![CDATA[Familiar Organizations]]></string>
+    <string name="_bx_orgs_page_block_title_familiar_profiles"><![CDATA[Organizations You May Know]]></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_sys_favorites_entries"><![CDATA[Favorite List]]></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_page_block_title_sys_cover_block"><![CDATA[Cover]]></string>
+    <string name="_bx_orgs_page_block_title_cover_block"><![CDATA[Cover]]></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_title_view_profile_meta"><![CDATA[Organization Meta]]></string>
+    <string name="_bx_orgs_menu_set_title_view_profile_meta"><![CDATA[Organization Meta]]></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_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_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_pricing"><![CDATA[Edit Pricing]]></string>
+    <string name="_bx_orgs_menu_item_title_edit_pricing"><![CDATA[Edit Pricing]]></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_pay_and_join"><![CDATA[Pay & Join]]></string>
+    <string name="_bx_orgs_menu_item_title_pay_and_join"><![CDATA[Pay & Join]]></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_followings"><![CDATA[Organizations]]></string>
+    <string name="_bx_orgs_menu_item_title_followings"><![CDATA[Organizations]]></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_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_grid_column_title_name"><![CDATA[Name]]></string>
+    <string name="_bx_orgs_grid_column_title_role_id"><![CDATA[Role]]></string>
+    <string name="_bx_orgs_grid_column_title_period"><![CDATA[Period]]></string>
+    <string name="_bx_orgs_grid_column_title_price"><![CDATA[Price]]></string>
+    <string name="_bx_orgs_grid_action_title_add"><![CDATA[Add]]></string>
+    <string name="_bx_orgs_grid_action_title_edit"><![CDATA[Edit]]></string>
+    <string name="_bx_orgs_grid_action_title_delete"><![CDATA[Delete]]></string>
+    <string name="_bx_orgs_grid_action_title_buy"><![CDATA[Buy]]></string>
+    <string name="_bx_orgs_grid_action_title_buy_title"><![CDATA[One-time payment]]></string>
+    <string name="_bx_orgs_grid_action_title_subscribe"><![CDATA[Subscribe]]></string>
+    <string name="_bx_orgs_grid_action_title_subscribe_title"><![CDATA[Create a subscription with recurring billing]]></string>
+    <string name="_bx_orgs_grid_action_title_choose"><![CDATA[Choose]]></string>
+    <string name="_bx_orgs_grid_action_title_choose_title"><![CDATA[Switch to the level for free]]></string>
+    <string name="_bx_orgs_popup_title_price_add"><![CDATA[Add Pricing Plan]]></string>
+    <string name="_bx_orgs_popup_title_price_edit"><![CDATA[Edit Pricing Plan]]></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_orgs_pre_lists_period_units"><![CDATA[Billing Interval]]></string>
+    <string name="_bx_orgs_period_unit_day"><![CDATA[day]]></string>
+    <string name="_bx_orgs_period_unit_week"><![CDATA[week]]></string>
+    <string name="_bx_orgs_period_unit_month"><![CDATA[month]]></string>
+    <string name="_bx_orgs_period_unit_year"><![CDATA[year]]></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_join_request_for_owner"><![CDATA[<b class="bx-ntfs-content-entry">{subentry_sample}</b> sent a join request to your organization]]></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_role_added"><![CDATA[Added]]></string>
+    <string name="_bx_orgs_txt_role_expired"><![CDATA[Expires]]></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_txt_invite_popup_text"><![CDATA[You have been invited to an organization. Click the button below to accept the invitation.]]></string>
+    <string name="_bx_orgs_txt_invite_popup_title"><![CDATA[Invitation to an organization]]></string>
+    <string name="_bx_orgs_txt_invite_popup_button_accept"><![CDATA[Accept]]></string>
+    <string name="_bx_orgs_txt_invite_popup_button_decline"><![CDATA[Decline]]></string>
+    <string name="_bx_orgs_txt_invite_popup_error_invitation_absent"><![CDATA[Sorry, an error has occurred. You can not join this organization. The invitation is expired or deleted.]]></string>
+    <string name="_bx_orgs_txt_invite_popup_error_invitation_wrong_user"><![CDATA[Sorry, an error has occurred. You can not join this organization. This invitation cannot be used by you.]]></string>
+    <string name="_bx_orgs_txt_n_unit"><![CDATA[{0} ({1})]]></string>
+    <string name="_bx_orgs_txt_cart_item_title"><![CDATA[{0}: {1} ({2} {3})]]></string>
+    <string name="_bx_orgs_txt_cart_item_title_lifetime"><![CDATA[{0}: {1} (lifetime)]]></string>    
+
+    <string name="_bx_orgs_msg_performed"><![CDATA[The action was successfully performed.]]></string>
+    <string name="_bx_orgs_err_price_duplicate"><![CDATA[Similar pricing plan is already exists.]]></string>
+    <string name="_bx_orgs_err_cannot_perform"><![CDATA[An error appeared. Please report.]]></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>

+ 770 - 0
modules/boonex/organizations/updates/13.0.3_13.0.4/source/install/sql/enable.sql

@@ -0,0 +1,770 @@
+
+-- SETTINGS
+
+SET @iTypeOrder = (SELECT MAX(`order`) FROM `sys_options_types` WHERE `group` = 'modules');
+INSERT INTO `sys_options_types`(`group`, `name`, `caption`, `icon`, `order`) VALUES 
+('modules', 'bx_organizations', '_bx_orgs', 'bx_organizations@modules/boonex/organizations/|std-icon.svg', IF(ISNULL(@iTypeOrder), 1, @iTypeOrder + 1));
+SET @iTypeId = LAST_INSERT_ID();
+
+INSERT INTO `sys_options_categories` (`type_id`, `name`, `caption`, `order`)
+VALUES (@iTypeId, 'bx_organizations', '_bx_orgs', 1);
+SET @iCategId = LAST_INSERT_ID();
+
+INSERT INTO `sys_options` (`name`, `value`, `category_id`, `caption`, `type`, `extra`, `check`, `check_error`, `order`) VALUES
+('bx_organizations_autoapproval', 'on', @iCategId, '_bx_orgs_option_autoapproval', 'select', 'a:2:{s:6:"module";s:16:"bx_organizations";s:6:"method";s:22:"get_options_activation";}', '', '', 1),
+('bx_organizations_default_acl_level', '3', @iCategId, '_bx_orgs_option_default_acl_level', 'select', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:15:"get_memberships";s:6:"params";a:4:{s:11:"purchasable";b:0;s:6:"active";b:1;s:9:"translate";b:1;s:22:"filter_out_auto_levels";b:1;}s:5:"class";s:16:"TemplAclServices";}', '', '', 2),
+('bx_organizations_redirect_aadd', 'profile', @iCategId, '_bx_orgs_option_redirect_aadd', 'select', 'a:2:{s:6:"module";s:16:"bx_organizations";s:6:"method";s:30:"get_options_redirect_after_add";}', '', '', 3),
+('bx_organizations_redirect_aadd_custom_url', '', @iCategId, '_bx_orgs_option_redirect_aadd_custom_url', 'digit', '', '', '', 4),
+('bx_organizations_num_connections_quick', '6', @iCategId, '_bx_orgs_option_num_connections_quick', 'digit', '', '', '', 10),
+('bx_organizations_per_page_browse', '24', @iCategId, '_bx_orgs_option_per_page_browse', 'digit', '', '', '', 11),
+('bx_organizations_num_rss', '10', @iCategId, '_bx_orgs_option_num_rss', 'digit', '', '', '', 12),
+('bx_organizations_per_page_browse_showcase', '32', @iCategId, '_sys_option_per_page_browse_showcase', 'digit', '', '', '', 15),
+('bx_organizations_per_page_browse_recommended', '10', @iCategId, '_sys_option_per_page_browse_recommended', 'digit', '', '', '', 16),
+('bx_organizations_per_page_for_favorites_lists', '5', @iCategId, '_bx_orgs_option_per_page_for_favorites_lists', 'digit', '', '', '', 17),
+('bx_organizations_searchable_fields', 'org_name,org_desc', @iCategId, '_bx_orgs_option_searchable_fields', 'list', 'a:2:{s:6:"module";s:16:"bx_organizations";s:6:"method";s:21:"get_searchable_fields";}', '', '', 20),
+('bx_organizations_members_mode', '', @iCategId, '_bx_orgs_option_members_mode', 'select', 'a:2:{s:6:"module";s:16:"bx_organizations";s:6:"method";s:24:"get_options_members_mode";}', '', '', 25),
+('bx_organizations_public_subscriptions', '', @iCategId, '_bx_orgs_option_public_subscriptions', 'checkbox', '', '', '', 30),
+('bx_organizations_public_subscribed_me', '', @iCategId, '_bx_orgs_option_public_subscribed_me', 'checkbox', '', '', '', 31),
+('bx_organizations_enable_subscribe_wo_join', '', @iCategId, '_bx_orgs_option_enable_subscribe_wo_join', 'checkbox', '', '', '', 32),
+('bx_organizations_enable_profile_activation_letter', 'on', @iCategId, '_bx_orgs_option_enable_profile_activation_letter', 'checkbox', '', '', '', 33),
+('bx_organizations_auto_activation_for_categories', 'on', @iCategId, '_bx_orgs_option_auto_activation_for_categories', 'checkbox', '', '', '', 35),
+('bx_organizations_internal_notifications', '', @iCategId, '_bx_orgs_option_internal_notifications', 'checkbox', '', '', '', 40);
+
+-- PAGES
+
+-- PAGE: create profile
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_organizations_create_profile', 'create-organization-profile', '_bx_orgs_page_title_sys_create_profile', '_bx_orgs_page_title_create_profile', 'bx_organizations', 5, 2147483647, 1, 'page.php?i=create-organization-profile', '', '', '', 0, 1, 0, '', '');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES
+('bx_organizations_create_profile', 1, 'bx_organizations', '_bx_orgs_page_block_title_choose_type', 11, 2147483647, 'menu', 'sys_add_profile_vertical', 0, 1, 0, 0),
+('bx_organizations_create_profile', 1, 'bx_organizations', '_bx_orgs_page_block_title_create_profile', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:16:\"bx_organizations\";s:6:\"method\";s:13:\"entity_create\";}', 0, 1, 1, 1);
+
+-- PAGE: view profile
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_organizations_view_profile', 'view-organization-profile', '_bx_orgs_page_title_sys_view_profile', '_bx_orgs_page_title_view_profile', 'bx_organizations', 7, 2147483647, 1, 'page.php?i=view-organization-profile', '', '', '', 0, 1, 0, 'BxOrgsPageEntry', 'modules/boonex/organizations/classes/BxOrgsPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES
+('bx_organizations_view_profile', 0, 'bx_organizations', '_bx_orgs_page_block_title_sys_cover_block', '_bx_orgs_page_block_title_cover_block', 3, 2147483647, 'service', 'a:2:{s:6:\"module\";s:16:\"bx_organizations\";s:6:\"method\";s:12:\"entity_cover\";}', 0, 0, 1, 0),
+('bx_organizations_view_profile', 0, 'bx_organizations', '', '_bx_orgs_page_block_title_profile_friends_mutual', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:16:\"bx_organizations\";s:6:\"method\";s:22:\"profile_friends_mutual\";}', 0, 0, 1, 0),
+('bx_organizations_view_profile', 2, 'bx_organizations', '', '_bx_orgs_page_block_title_profile_subscriptions', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:16:\"bx_organizations\";s:6:\"method\";s:21:\"profile_subscriptions\";}', 0, 1, 0, 0),
+('bx_organizations_view_profile', 2, 'bx_organizations', '', '_bx_orgs_page_block_title_profile_subscribed_me', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:16:\"bx_organizations\";s:6:\"method\";s:21:\"profile_subscribed_me\";}', 0, 1, 0, 0),
+('bx_organizations_view_profile', 2, 'bx_organizations', '', '_bx_orgs_page_block_title_profile_related_me', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:16:"bx_organizations";s:6:"method";s:18:"profile_related_me";}', 0, 1, 0, 0),
+('bx_organizations_view_profile', 2, 'bx_organizations', '', '_bx_orgs_page_block_title_profile_relations', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:16:"bx_organizations";s:6:"method";s:17:"profile_relations";}', 0, 1, 0, 0),
+('bx_organizations_view_profile', 2, 'bx_organizations', '', '_bx_orgs_page_block_title_profile_comments', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:16:\"bx_organizations\";s:6:\"method\";s:15:\"entity_comments\";}', 0, 0, 0, 0),
+('bx_organizations_view_profile', 2, 'bx_organizations', '', '_bx_orgs_page_block_title_profile_description', 13, 2147483647, 'service', 'a:2:{s:6:\"module\";s:16:\"bx_organizations\";s:6:\"method\";s:17:\"entity_text_block\";}', 0, 0, 1, 1),
+('bx_organizations_view_profile', 2, 'bx_organizations', '', '_bx_orgs_page_block_title_fans', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:16:\"bx_organizations\";s:6:\"method\";s:4:\"fans\";}', 0, 0, 1, 2),
+('bx_organizations_view_profile', 2, 'bx_organizations', '', '_bx_orgs_page_block_title_profile_friends', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:16:\"bx_organizations\";s:6:\"method\";s:15:\"profile_friends\";}', 0, 1, 1, 3),
+('bx_organizations_view_profile', 3, 'bx_organizations', '', '_bx_orgs_page_block_title_profile_location', 13, 2147483647, 'service', 'a:2:{s:6:\"module\";s:16:\"bx_organizations\";s:6:\"method\";s:15:\"entity_location\";}', 0, 0, 0, 0),
+('bx_organizations_view_profile', 3, 'bx_organizations', '', '_bx_orgs_page_block_title_profile_info', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:16:\"bx_organizations\";s:6:\"method\";s:11:\"entity_info\";}', 0, 0, 1, 1),
+('bx_organizations_view_profile', 3, 'bx_organizations', '', '_bx_orgs_page_block_title_profile_all_actions', 13, 2147483647, 'service', 'a:2:{s:6:"module";s:16:"bx_organizations";s:6:"method";s:18:"entity_all_actions";}', 0, 0, 0, 0),
+('bx_organizations_view_profile', 3, 'bx_organizations', '', '_bx_orgs_page_block_title_profile_membership', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:16:\"bx_organizations\";s:6:\"method\";s:18:\"profile_membership\";}', 0, 0, 1, 2),
+('bx_organizations_view_profile', 3, 'bx_organizations', '', '_bx_orgs_page_block_title_admins', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:16:\"bx_organizations\";s:6:\"method\";s:6:\"admins\";}', 0, 0, 1, 3),
+('bx_organizations_view_profile', 3, 'bx_organizations', '', '_bx_orgs_page_block_title_profile_location', 3, 2147483647, 'service', 'a:4:{s:6:\"module\";s:6:\"system\";s:6:\"method\";s:13:\"locations_map\";s:6:\"params\";a:2:{i:0;s:16:\"bx_organizations\";i:1;s:12:\"{content_id}\";}s:5:\"class\";s:20:\"TemplServiceMetatags\";}', 0, 0, 1, 4),
+('bx_organizations_view_profile', 2, 'bx_organizations', '', '_bx_orgs_page_block_title_entry_reports', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:16:\"bx_organizations\";s:6:\"method\";s:14:\"entity_reports\";}', 0, 0, 1, 6);
+
+
+-- PAGE: view closed profile 
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_organizations_view_profile_closed', 'view-organization-profile-closed', '_bx_orgs_page_title_sys_view_profile_closed', '_bx_orgs_page_title_view_profile', 'bx_organizations', 10, 2147483647, 1, 'page.php?i=view-organization-profile', '', '', '', 0, 1, 0, 'BxOrgsPageEntry', 'modules/boonex/organizations/classes/BxOrgsPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_organizations_view_profile_closed', 2, 'bx_organizations', '', '_bx_orgs_page_block_title_profile_info', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:16:\"bx_organizations\";s:6:\"method\";s:11:\"entity_info\";}', 0, 0, 1, 0),
+('bx_organizations_view_profile_closed', 3, 'bx_organizations', '', '_bx_orgs_page_block_title_fans', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:16:\"bx_organizations\";s:6:\"method\";s:4:\"fans\";}', 0, 0, 1, 0);
+
+-- PAGE: edit profile
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_organizations_edit_profile', 'edit-organization-profile', '_bx_orgs_page_title_sys_edit_profile', '_bx_orgs_page_title_edit_profile', 'bx_organizations', 5, 2147483647, 1, 'page.php?i=edit-organization-profile', '', '', '', 0, 1, 0, 'BxOrgsPageEntry', 'modules/boonex/organizations/classes/BxOrgsPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_organizations_edit_profile', 1, 'bx_organizations', '_bx_orgs_page_block_title_edit_profile', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:16:\"bx_organizations\";s:6:\"method\";s:11:\"entity_edit\";}', 0, 0, 0);
+
+-- PAGE: edit profile cover
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_organizations_edit_profile_cover', 'edit-organization-cover', '_bx_orgs_page_title_sys_edit_profile_cover', '_bx_orgs_page_title_edit_profile_cover', 'bx_organizations', 5, 2147483647, 1, 'page.php?i=edit-organization-cover', '', '', '', 0, 1, 0, 'BxOrgsPageEntry', 'modules/boonex/organizations/classes/BxOrgsPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_organizations_edit_profile_cover', 1, 'bx_organizations', '_bx_orgs_page_block_title_edit_profile_cover', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:16:\"bx_organizations\";s:6:\"method\";s:17:\"entity_edit_cover\";}', 0, 0, 0);
+
+-- PAGE: invite members
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_organizations_invite', 'invite-to-organization', '_bx_orgs_page_title_sys_invite_to_organization', '_bx_orgs_page_title_invite_to_organization', 'bx_organizations', 5, 2147483647, 1, 'page.php?i=invite-to-organization', '', '', '', 0, 1, 0, 'BxOrgsPageEntry', 'modules/boonex/organizations/classes/BxOrgsPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_organizations_invite', 1, 'bx_organizations', '_bx_orgs_page_block_title_invite_to_organization', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:16:\"bx_organizations\";s:6:\"method\";s:13:\"entity_invite\";}', 0, 0, 0);
+
+-- PAGE: delete profile
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_organizations_delete_profile', 'delete-organization-profile', '_bx_orgs_page_title_sys_delete_profile', '_bx_orgs_page_title_delete_profile', 'bx_organizations', 5, 2147483647, 1, 'page.php?i=delete-organization-profile', '', '', '', 0, 1, 0, 'BxOrgsPageEntry', 'modules/boonex/organizations/classes/BxOrgsPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_organizations_delete_profile', 1, 'bx_organizations', '_bx_orgs_page_block_title_delete_profile', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:16:\"bx_organizations\";s:6:\"method\";s:13:\"entity_delete\";}', 0, 0, 0);
+
+-- PAGE: join profile
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_organizations_join_profile', 'join-organization-profile', '_bx_orgs_page_title_sys_join_profile', '_bx_orgs_page_title_join_profile', 'bx_organizations', 5, 2147483647, 1, 'page.php?i=join-organization-profile', '', '', '', 0, 1, 0, 'BxOrgsPageEntry', 'modules/boonex/organizations/classes/BxOrgsPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_organizations_join_profile', 1, 'bx_organizations', '_bx_orgs_page_block_title_join_profile', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:16:"bx_organizations";s:6:"method";s:11:"entity_join";s:6:"params";a:1:{i:0;s:12:"{profile_id}";}}', 0, 0, 0);
+
+-- PAGE: profile info
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_organizations_profile_info', 'organization-profile-info', '_bx_orgs_page_title_sys_profile_info', '_bx_orgs_page_title_profile_info', 'bx_organizations', 5, 2147483647, 1, 'page.php?i=organization-profile-info', '', '', '', 0, 1, 0, 'BxOrgsPageEntry', 'modules/boonex/organizations/classes/BxOrgsPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_organizations_profile_info', 1, 'bx_organizations', '_bx_orgs_page_block_title_system_profile_info', '_bx_orgs_page_block_title_profile_info_link', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:16:\"bx_organizations\";s:6:\"method\";s:16:\"entity_info_full\";}', 0, 0, 1, 1),
+('bx_organizations_profile_info', 1, 'bx_organizations', '', '_bx_orgs_page_block_title_profile_description', 13, 2147483647, 'service', 'a:2:{s:6:\"module\";s:16:\"bx_organizations\";s:6:\"method\";s:17:\"entity_text_block\";}', 0, 0, 1, 2);
+
+-- PAGE: manage profile pricing
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_organizations_profile_pricing', 'edit-organization-pricing', '_bx_orgs_page_title_sys_profile_pricing', '_bx_orgs_page_title_profile_pricing', 'bx_organizations', 5, 2147483647, 1, 'page.php?i=edit-organization-pricing', '', '', '', 0, 1, 0, 'BxOrgsPageEntry', 'modules/boonex/organizations/classes/BxOrgsPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_organizations_profile_pricing', 1, 'bx_organizations', '_bx_orgs_page_block_title_system_profile_pricing', '_bx_orgs_page_block_title_profile_pricing_link', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:16:"bx_organizations";s:6:"method";s:14:"entity_pricing";s:6:"params";a:1:{i:0;s:12:"{profile_id}";}}', 0, 0, 1, 1);
+
+-- PAGE: group fans
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_organizations_fans', 'organization-profile-fans', '_bx_orgs_page_title_sys_fans', '_bx_orgs_page_title_fans', 'bx_organizations', 5, 2147483647, 1, 'page.php?i=organization-profile-fans', '', '', '', 0, 1, 0, 'BxOrgsPageEntry', 'modules/boonex/organizations/classes/BxOrgsPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_organizations_fans', 1, 'bx_organizations', '_bx_orgs_page_block_title_system_fans', '_bx_orgs_page_block_title_fans_link', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:16:"bx_organizations";s:6:"method";s:10:"fans_table";}', 0, 0, 1, 1),
+('bx_organizations_fans', 1, 'bx_organizations', '_bx_orgs_page_block_title_system_invites', '_bx_orgs_page_block_title_fans_invites', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:16:"bx_organizations";s:6:"method";s:13:"invites_table";}', 0, 0, 1, 2);
+
+-- PAGE: profile friends
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_organizations_profile_friends', 'organization-profile-friends', '_bx_orgs_page_title_sys_profile_friends', '_bx_orgs_page_title_profile_friends', 'bx_organizations', 5, 2147483647, 1, 'page.php?i=organization-profile-friends', '', '', '', 0, 1, 0, 'BxOrgsPageEntry', 'modules/boonex/organizations/classes/BxOrgsPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_organizations_profile_friends', 1, 'bx_organizations', '_bx_orgs_page_block_title_system_profile_friends', '_bx_orgs_page_block_title_profile_friends_link', 11, 2147483647, 'service', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:17:"connections_table";s:6:"params";a:1:{i:0;s:12:"{profile_id}";}s:5:"class";s:23:"TemplServiceConnections";}', 0, 0, 1, 1);
+
+-- PAGE: profile friend requests
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_organizations_friend_requests', 'organization-friend-requests', '_bx_orgs_page_title_sys_friend_requests', '_bx_orgs_page_title_friend_requests', 'bx_organizations', 5, 2147483647, 1, 'page.php?i=organization-friend-requests', '', '', '', 0, 1, 0, 'BxOrgsPageEntry', 'modules/boonex/organizations/classes/BxOrgsPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_organizations_friend_requests', 1, 'bx_organizations', '_bx_orgs_page_block_title_system_friend_requests', '_bx_orgs_page_block_title_friend_requests_link', 11, 2147483647, 'service', 'a:3:{s:6:\"module\";s:6:\"system\";s:6:\"method\";s:25:\"connections_request_table\";s:5:\"class\";s:23:\"TemplServiceConnections\";}', 0, 0, 1, 1);
+
+-- PAGE: profile favorites
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_organizations_profile_favorites', 'organization-profile-favorites', '_bx_orgs_page_title_sys_profile_favorites', '_bx_orgs_page_title_profile_favorites', 'bx_organizations', 5, 2147483647, 1, 'page.php?i=organization-profile-favorites', '', '', '', 0, 1, 0, 'BxOrgsPageBrowse', 'modules/boonex/organizations/classes/BxOrgsPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_organizations_profile_favorites', 1, 'bx_organizations', '_bx_orgs_page_block_title_system_profile_favorites', '_bx_orgs_page_block_title_profile_favorites', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:16:"bx_organizations";s:6:"method";s:21:"browse_favorite_lists";s:6:"params";a:2:{s:10:"profile_id";s:12:"{profile_id}";s:6:"params";a:3:{s:9:"unit_view";s:8:"showcase";s:13:"empty_message";b:0;s:13:"ajax_paginate";b:0;}}}', 0, 1, 1, 1);
+-- PAGE: profile subscriptions
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_organizations_profile_subscriptions', 'organization-profile-subscriptions', '_bx_orgs_page_title_sys_profile_subscriptions', '_bx_orgs_page_title_profile_subscriptions', 'bx_organizations', 5, 2147483647, 1, 'page.php?i=organization-profile-subscriptions', '', '', '', 0, 1, 0, 'BxOrgsPageEntry', 'modules/boonex/organizations/classes/BxOrgsPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_organizations_profile_subscriptions', 1, 'bx_organizations', '_bx_orgs_page_block_title_system_profile_subscriptions', '_bx_orgs_page_block_title_profile_subscriptions', 11, 2147483647, 'service', 'a:3:{s:6:\"module\";s:6:\"system\";s:6:\"method\";s:19:\"subscriptions_table\";s:5:\"class\";s:23:\"TemplServiceConnections\";}', 0, 0, 1, 1),
+('bx_organizations_profile_subscriptions', 1, 'bx_organizations', '_bx_orgs_page_block_title_system_profile_subscribed_me', '_bx_orgs_page_block_title_profile_subscribed_me', 11, 2147483647, 'service', 'a:3:{s:6:\"module\";s:6:\"system\";s:6:\"method\";s:19:\"subscribed_me_table\";s:5:\"class\";s:23:\"TemplServiceConnections\";}', 0, 0, 1, 2);
+
+-- PAGE: profile relations
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_organizations_profile_relations', 'organization-profile-relations', '_bx_orgs_page_title_sys_profile_relations', '_bx_orgs_page_title_profile_relations', 'bx_organizations', 5, 2147483647, 1, 'page.php?i=organization-profile-relations', '', '', '', 0, 1, 0, 'BxOrgsPageEntry', 'modules/boonex/organizations/classes/BxOrgsPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_organizations_profile_relations', 1, 'bx_organizations', '_bx_orgs_page_block_title_system_profile_relations', '_bx_orgs_page_block_title_profile_relations', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:6:"system";s:6:"method";s:15:"relations_table";s:5:"class";s:23:"TemplServiceConnections";}', 0, 0, 1, 1),
+('bx_organizations_profile_relations', 1, 'bx_organizations', '_bx_orgs_page_block_title_system_profile_related_me', '_bx_orgs_page_block_title_profile_related_me', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:6:"system";s:6:"method";s:16:"related_me_table";s:5:"class";s:23:"TemplServiceConnections";}', 0, 0, 1, 2);
+
+-- PAGE: view entry comments
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_organizations_profile_comments', '_bx_orgs_page_title_sys_profile_comments', '_bx_orgs_page_title_profile_comments', 'bx_organizations', 5, 2147483647, 1, 'organization-profile-comments', '', '', '', '', 0, 1, 0, 'BxOrgsPageEntry', 'modules/boonex/organizations/classes/BxOrgsPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_organizations_profile_comments', 1, 'bx_organizations', '_bx_orgs_page_block_title_profile_comments', '_bx_orgs_page_block_title_profile_comments_link', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:16:\"bx_organizations\";s:6:\"method\";s:15:\"entity_comments\";}', 0, 0, 0, 1);
+
+-- PAGE: module home
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_organizations_home', '_bx_orgs_page_title_sys_recent', '_bx_orgs_page_title_recent', 'bx_organizations', 5, 2147483647, 1, 'organizations-home', 'page.php?i=organizations-home', '', '', '', 0, 1, 0, 'BxOrgsPageBrowse', 'modules/boonex/organizations/classes/BxOrgsPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES
+('bx_organizations_home', 1, 'bx_organizations', '', '_bx_orgs_page_block_title_featured_profiles', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:16:"bx_organizations";s:6:"method";s:15:"browse_featured";s:6:"params";a:1:{i:0;s:7:"gallery";}}', 0, 1, 1, 0),
+('bx_organizations_home', 1, 'bx_organizations', '', '_bx_orgs_page_block_title_latest_profiles', 11, 2147483647, 'service', 'a:3:{s:6:\"module\";s:16:\"bx_organizations\";s:6:\"method\";s:22:\"browse_recent_profiles\";s:6:"params";a:1:{i:0;b:1;}}', 0, 1, 1, 1),
+('bx_organizations_home', 1, 'bx_organizations', '_bx_orgs_page_block_title_sys_multicats', '_bx_orgs_page_block_title_multicats', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:16:"bx_organizations";s:6:"method";s:21:"categories_multi_list";}', 0, 0, 0, 2);
+
+-- PAGE: active profiles
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_organizations_active', '_bx_orgs_page_title_sys_active', '_bx_orgs_page_title_active', 'bx_organizations', 5, 2147483647, 1, 'organizations-active', 'page.php?i=organizations-active', '', '', '', 0, 1, 0, 'BxOrgsPageBrowse', 'modules/boonex/organizations/classes/BxOrgsPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_organizations_active', 1, 'bx_organizations', '_bx_orgs_page_block_title_active_profiles', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:16:"bx_organizations";s:6:"method";s:22:"browse_active_profiles";s:6:"params";a:2:{s:9:"unit_view";s:7:"gallery";s:13:"empty_message";b:1;}}}', 0, 1, 0);
+
+-- PAGE: online profiles
+
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_organizations_online', '_bx_orgs_page_title_sys_online', '_bx_orgs_page_title_online', 'bx_organizations', 5, 2147483647, 1, 'organizations-online', 'page.php?i=organizations-online', '', '', '', 0, 1, 0, 'BxOrgsPageBrowse', 'modules/boonex/organizations/classes/BxOrgsPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_organizations_online', 1, 'bx_organizations', '_bx_orgs_page_block_title_online_profiles', 11, 2147483647, 'service', 'a:3:{s:6:\"module\";s:16:\"bx_organizations\";s:6:\"method\";s:22:\"browse_online_profiles\";s:6:"params";a:1:{i:0;b:1;}}', 0, 1, 0);
+
+-- PAGE: search for entries
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_organizations_search', '_bx_orgs_page_title_sys_entries_search', '_bx_orgs_page_title_entries_search', 'bx_organizations', 5, 2147483647, 1, 'organizations-search', 'page.php?i=organizations-search', '', '', '', 0, 1, 0, 'BxOrgsPageBrowse', 'modules/boonex/organizations/classes/BxOrgsPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_organizations_search', 1, 'bx_organizations', '_bx_orgs_page_block_title_search_form', 11, 2147483647, 'service', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:8:"get_form";s:6:"params";a:1:{i:0;a:1:{s:6:"object";s:16:"bx_organizations";}}s:5:"class";s:27:"TemplSearchExtendedServices";}', 0, 1, 1, 1),
+('bx_organizations_search', 1, 'bx_organizations', '_bx_orgs_page_block_title_search_results', 11, 2147483647, 'service', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:11:"get_results";s:6:"params";a:1:{i:0;a:2:{s:6:"object";s:16:"bx_organizations";s:10:"show_empty";b:1;}}s:5:"class";s:27:"TemplSearchExtendedServices";}', 0, 1, 1, 2),
+('bx_organizations_search', 1, 'bx_organizations', '_bx_orgs_page_block_title_search_form_cmts', 11, 2147483647, 'service', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:8:"get_form";s:6:"params";a:1:{i:0;a:1:{s:6:"object";s:21:"bx_organizations_cmts";}}s:5:"class";s:27:"TemplSearchExtendedServices";}', 0, 1, 0, 3),
+('bx_organizations_search', 1, 'bx_organizations', '_bx_orgs_page_block_title_search_results_cmts', 11, 2147483647, 'service', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:11:"get_results";s:6:"params";a:1:{i:0;a:2:{s:6:"object";s:21:"bx_organizations_cmts";s:10:"show_empty";b:1;}}s:5:"class";s:27:"TemplSearchExtendedServices";}', 0, 1, 0, 4);
+
+-- PAGE: module manage own
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_organizations_manage', '_bx_orgs_page_title_sys_manage', '_bx_orgs_page_title_manage', 'bx_organizations', 5, 2147483647, 1, 'organizations-manage', 'page.php?i=organizations-manage', '', '', '', 0, 1, 0, 'BxOrgsPageBrowse', 'modules/boonex/organizations/classes/BxOrgsPageBrowse.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_organizations_manage', 1, 'bx_organizations', '_bx_orgs_page_block_title_system_manage', '_bx_orgs_page_block_title_manage', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:16:\"bx_organizations\";s:6:\"method\";s:12:\"manage_tools\";}}', 0, 1, 0);
+
+-- PAGE: module manage all
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_organizations_administration', '_bx_orgs_page_title_sys_manage_administration', '_bx_orgs_page_title_manage', 'bx_organizations', 5, 192, 1, 'organizations-administration', 'page.php?i=organizations-administration', '', '', '', 0, 1, 0, 'BxOrgsPageBrowse', 'modules/boonex/organizations/classes/BxOrgsPageBrowse.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_organizations_administration', 1, 'bx_organizations', '_bx_orgs_page_block_title_system_manage_administration', '_bx_orgs_page_block_title_manage', 11, 192, 'service', 'a:3:{s:6:\"module\";s:16:\"bx_organizations\";s:6:\"method\";s:12:\"manage_tools\";s:6:\"params\";a:1:{i:0;s:14:\"administration\";}}', 0, 1, 0);
+
+-- PAGE: user's organizations
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_organizations_joined', 'joined-organizations', '_bx_orgs_page_title_sys_joined_entries', '_bx_orgs_page_title_joined_entries', 'bx_organizations', 5, 2147483647, 1, '', '', '', '', 0, 1, 0, 'BxOrgsPageJoinedEntries', 'modules/boonex/organizations/classes/BxOrgsPageJoinedEntries.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES
+('bx_organizations_joined', 1, 'bx_organizations', '_bx_orgs_page_block_title_sys_entries_actions', '_bx_orgs_page_block_title_entries_actions', 13, 2147483647, 'service', 'a:2:{s:6:"module";s:16:"bx_organizations";s:6:"method";s:18:"my_entries_actions";}', 0, 0, 1, 1),
+('bx_organizations_joined', 1, 'bx_organizations', '_bx_orgs_page_block_title_sys_favorites_of_author', '_bx_orgs_page_block_title_favorites_of_author', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:16:"bx_organizations";s:6:"method";s:21:"browse_favorite_lists";s:6:"params";a:2:{s:10:"profile_id";s:12:"{profile_id}";s:6:"params";a:3:{s:9:"unit_view";s:8:"showcase";s:13:"empty_message";b:0;s:13:"ajax_paginate";b:0;}}}', 0, 1, 1, 2),
+('bx_organizations_joined', 1, 'bx_organizations', '_bx_orgs_page_block_title_sys_joined_entries', '_bx_orgs_page_block_title_joined_entries', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:16:"bx_organizations";s:6:"method";s:21:"browse_joined_entries";s:6:"params";a:2:{i:0;i:0;i:1;b:1;}}', 0, 0, 1, 2);
+
+
+-- PAGE: favorites by list
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_organizations_favorites', '_bx_orgs_page_title_sys_entries_favorites', '_bx_orgs_page_title_entries_favorites', 'bx_organizations', 12, 2147483647, 1, 'organizations-favorites', 'page.php?i=organizations-favorites', '', '', '', 0, 1, 0, 'BxOrgsPageListEntry', 'modules/boonex/organizations/classes/BxOrgsPageListEntry.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_organizations_favorites', 2, 'bx_organizations', '_bx_orgs_page_block_title_sys_favorites_entries', '_bx_orgs_page_block_title_favorites_entries', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:16:"bx_organizations";s:6:"method";s:15:"browse_favorite";s:6:"params";a:2:{s:10:"profile_id";s:12:"{profile_id}";s:6:"params";a:3:{s:9:"unit_view";s:7:"gallery";s:13:"empty_message";b:0;s:13:"ajax_paginate";b:0;}}}', 0, 1, 1),
+('bx_organizations_favorites', 3, 'bx_organizations', '', '_bx_orgs_page_block_title_favorites_entries_info', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:16:"bx_organizations";s:6:"method";s:19:"favorites_list_info";}', 0, 0, 0),
+('bx_organizations_favorites', 3, 'bx_organizations', '', '_bx_orgs_page_block_title_favorites_entries_actions', 13, 2147483647, 'service', 'a:2:{s:6:"module";s:16:"bx_organizations";s:6:"method";s:22:"favorites_list_actions";}', 0, 0, 1);
+
+
+-- PAGE: add block to homepage
+SET @iBlockOrder = (SELECT `order` FROM `sys_pages_blocks` WHERE `object` = 'sys_home' AND `cell_id` = 1 ORDER BY `order` DESC LIMIT 1);
+INSERT INTO `sys_pages_blocks` (`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES
+('sys_home', 1, 'bx_organizations', '', '_bx_orgs_page_block_title_latest_profiles', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:16:"bx_organizations";s:6:"method";s:22:"browse_recent_profiles";}', 1, 0, 0, IFNULL(@iBlockOrder, 0) + 1),
+('sys_home', 1, 'bx_organizations', '_bx_orgs_page_block_title_sys_recommended_entries_view_showcase', '_bx_orgs_page_block_title_recommended_entries_view_showcase', 11, 2147483647, 'service', 'a:3:{s:6:\"module\";s:16:\"bx_organizations\";s:6:\"method\";s:18:\"browse_recommended\";s:6:\"params\";a:3:{s:9:\"unit_view\";s:8:\"showcase\";s:13:\"empty_message\";b:0;s:13:\"ajax_paginate\";b:0;}}', 1, 0, 0, IFNULL(@iBlockOrder, 0) + 2);
+
+-- PAGES: add page block to profiles modules (trigger* page objects are processed separately upon modules enable/disable)
+SET @iPBCellProfile = 2;
+INSERT INTO `sys_pages_blocks` (`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES
+('trigger_page_profile_view_entry', @iPBCellProfile, 'bx_organizations', '_bx_orgs_page_block_title_sys_joined_entries', '_bx_orgs_page_block_title_joined_entries', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:16:"bx_organizations";s:6:"method";s:21:"browse_joined_entries";s:6:"params";a:2:{i:0;s:12:"{profile_id}";i:1;b:0;}}', 0, 0, 1, 0);
+
+-- PAGE: service blocks
+SET @iBlockOrder = (SELECT `order` FROM `sys_pages_blocks` WHERE `object` = '' AND `cell_id` = 0 ORDER BY `order` DESC LIMIT 1);
+INSERT INTO `sys_pages_blocks` (`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES
+('', 0, 'bx_organizations', '', '_bx_orgs_page_block_title_categories', 11, 2147483647, 'service', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:15:"categories_list";s:6:"params";a:2:{i:0;s:21:"bx_organizations_cats";i:1;a:2:{s:10:\"show_empty\";b:1;s:21:\"show_empty_categories\";b:1;}}s:5:"class";s:20:"TemplServiceCategory";}', 1, 1, 1, IFNULL(@iBlockOrder, 0) + 1),
+('', 0, 'bx_organizations', '_bx_orgs_page_block_title_sys_featured_entries_view_showcase', '_bx_orgs_page_block_title_featured_entries_view_showcase', 11, 2147483647, 'service', 'a:3:{s:6:\"module\";s:16:\"bx_organizations\";s:6:\"method\";s:15:\"browse_featured\";s:6:\"params\";a:3:{s:9:\"unit_view\";s:8:\"showcase\";s:13:\"empty_message\";b:0;s:13:\"ajax_paginate\";b:0;}}', 0, 1, 1, IFNULL(@iBlockOrder, 0) + 2),
+('', 0, 'bx_organizations', '_bx_orgs_page_block_title_sys_recommended_entries_view_showcase', '_bx_orgs_page_block_title_recommended_entries_view_showcase', 11, 2147483647, 'service', 'a:3:{s:6:\"module\";s:16:\"bx_organizations\";s:6:\"method\";s:18:\"browse_recommended\";s:6:\"params\";a:3:{s:9:\"unit_view\";s:8:\"showcase\";s:13:\"empty_message\";b:0;s:13:\"ajax_paginate\";b:0;}}', 0, 1, 1, IFNULL(@iBlockOrder, 0) + 3),
+('', 0, 'bx_organizations', '_bx_orgs_page_block_title_sys_active_entries_view_showcase', '_bx_orgs_page_block_title_active_entries_view_showcase', 11, 2147483647, 'service', 'a:3:{s:6:\"module\";s:16:\"bx_organizations\";s:6:\"method\";s:22:\"browse_active_profiles\";s:6:\"params\";a:3:{s:9:\"unit_view\";s:16:\"showcase_wo_info\";s:13:\"empty_message\";b:0;s:13:\"ajax_paginate\";b:0;}}', 0, 1, 1, IFNULL(@iBlockOrder, 0) + 4),
+('', 0, 'bx_organizations', '_bx_orgs_page_block_title_sys_active_profiles', '_bx_orgs_page_block_title_active_profiles', 11, 2147483647, 'service', 'a:3:{s:6:\"module\";s:16:\"bx_organizations\";s:6:\"method\";s:22:\"browse_active_profiles\";s:6:\"params\";a:3:{s:9:\"unit_view\";s:12:\"unit_wo_info\";s:13:\"empty_message\";b:0;s:13:\"ajax_paginate\";b:0;}}', 0, 1, 1, IFNULL(@iBlockOrder, 0) + 5),
+('', 0, 'bx_organizations', '_bx_orgs_page_block_title_sys_familiar_profiles', '_bx_orgs_page_block_title_familiar_profiles', 11, 2147483647, 'service', 'a:3:{s:6:\"module\";s:16:\"bx_organizations\";s:6:\"method\";s:24:\"browse_familiar_profiles\";s:6:\"params\";a:4:{s:10:\"connection\";s:20:\"sys_profiles_friends\";s:9:\"unit_view\";s:4:\"unit\";s:13:\"empty_message\";b:0;s:13:\"ajax_paginate\";b:0;}}', 0, 1, 1, IFNULL(@iBlockOrder, 0) + 6);
+
+-- MENU
+
+-- MENU: add to site menu
+SET @iSiteMenuOrder = (SELECT `order` FROM `sys_menu_items` WHERE `set_name` = 'sys_site' AND `active` = 1 AND `order` < 9999 ORDER BY `order` DESC LIMIT 1);
+INSERT INTO `sys_menu_items` (`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('sys_site', 'bx_organizations', 'organizations-home', '_bx_orgs_menu_item_title_system_entries_home', '_bx_orgs_menu_item_title_entries_home', 'page.php?i=organizations-home', '', '', 'briefcase col-red2', 'bx_organizations_submenu', 2147483647, 1, 1, IFNULL(@iSiteMenuOrder, 0) + 1);
+
+-- MENU: add to homepage menu
+SET @iHomepageMenuOrder = (SELECT `order` FROM `sys_menu_items` WHERE `set_name` = 'sys_homepage' AND `active` = 1 ORDER BY `order` DESC LIMIT 1);
+INSERT INTO `sys_menu_items` (`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('sys_homepage', 'bx_organizations', 'organizations-home', '_bx_orgs_menu_item_title_system_entries_home', '_bx_orgs_menu_item_title_entries_home', 'page.php?i=organizations-home', '', '', 'briefcase col-red2', 'bx_organizations_submenu', 2147483647, 1, 1, IFNULL(@iHomepageMenuOrder, 0) + 1);
+
+--SET @iCreateProfileMenuOrder = (SELECT `order` FROM `sys_menu_items` WHERE `set_name` = 'sys_profiles_create' AND `active` = 1 ORDER BY `order` DESC LIMIT 1);
+--INSERT INTO `sys_menu_items` (`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES
+--('sys_profiles_create', 'bx_organizations', 'create-organization-profile', '_bx_orgs_menu_item_title_system_profile_type', '_bx_orgs_menu_item_title_profile_type', 'page.php?i=create-organization-profile', '', '', 'briefcase', '', 2147483647, 1, 1, IFNULL(@iCreateProfileMenuOrder, 0) + 1);
+
+-- MENU: add to create profile menu
+SET @iAddMenuOrder = (SELECT `order` FROM `sys_menu_items` WHERE `set_name` = 'sys_add_profile_links' AND `active` = 1 ORDER BY `order` DESC LIMIT 1);
+INSERT INTO `sys_menu_items` (`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('sys_add_profile_links', 'bx_organizations', 'create-organization-profile', '_bx_orgs_menu_item_title_system_create_profile', '_bx_orgs_menu_item_title_create_profile', 'page.php?i=create-organization-profile', '', '', 'briefcase col-red2', '', 2147483647, 1, 1, IFNULL(@iAddMenuOrder, 0) + 1);
+
+-- MENU: view actions
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_organizations_view_actions', '_bx_orgs_menu_title_view_profile_actions', 'bx_organizations_view_actions', 'bx_organizations', 9, 0, 1, 'BxOrgsMenuViewActions', 'modules/boonex/organizations/classes/BxOrgsMenuViewActions.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_organizations_view_actions', 'bx_organizations', '_bx_orgs_menu_set_title_view_profile_actions', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `submenu_popup`, `visible_for_levels`, `visibility_custom`, `active`, `copyable`, `editable`, `order`) VALUES 
+('bx_organizations_view_actions', 'bx_organizations', 'join-organization-profile', '_bx_orgs_menu_item_title_system_pay_and_join', '_bx_orgs_menu_item_title_pay_and_join', 'page.php?i=join-organization-profile&profile_id={profile_id}', '', '', 'sign-in-alt', '', 0, 2147483647, 'a:3:{s:6:"module";s:16:"bx_organizations";s:6:"method";s:22:"is_paid_join_avaliable";s:6:"params";a:1:{i:0;s:12:"{profile_id}";}}', 1, 0, 0, 4),
+('bx_organizations_view_actions', 'bx_organizations', 'profile-fan-add', '_bx_orgs_menu_item_title_system_become_fan', '{title_add_fan}', 'javascript:void(0)', 'bx_conn_action(this, \'bx_organizations_fans\', \'add\', \'{profile_id}\')', '', 'sign-in-alt', '', 0, 2147483647, 'a:3:{s:6:"module";s:16:"bx_organizations";s:6:"method";s:22:"is_free_join_avaliable";s:6:"params";a:1:{i:0;s:12:"{profile_id}";}}', 1, 0, 0, 5),
+('bx_organizations_view_actions', 'bx_organizations', 'profile-friend-add', '_bx_orgs_menu_item_title_system_befriend', '{title_add_friend}', 'javascript:void(0)', 'bx_conn_action(this, \'sys_profiles_friends\', \'add\', \'{profile_id}\')', '', 'user-plus', '', 0, 2147483647, '', 1, 0, 1, 10),
+('bx_organizations_view_actions', 'bx_organizations', 'profile-relation-add', '_bx_orgs_menu_item_title_system_relation_add', '_bx_orgs_menu_item_title_relation_add', 'javascript:void(0)', 'bx_menu_popup(''sys_add_relation'', window, {}, {profile_id: {profile_id}});', '', 'sync', '', 0, 2147483647, '', 1, 0, 1, 15),
+('bx_organizations_view_actions', 'bx_organizations', 'profile-subscribe-add', '_bx_orgs_menu_item_title_system_subscribe', '_bx_orgs_menu_item_title_subscribe', 'javascript:void(0)', 'bx_conn_action(this, \'sys_profiles_subscriptions\', \'add\', \'{profile_id}\')', '', 'check', '', 0, 2147483647, '', 1, 0, 1, 20),
+('bx_organizations_view_actions', 'bx_organizations', 'profile-set-acl-level', '_sys_menu_item_title_system_set_acl_level', '_sys_menu_item_title_set_acl_level', 'javascript:void(0)', 'bx_menu_popup(''sys_set_acl_level'', window, {id:{value:''sys_acl_set_{profile_id}'', force:true}, closeOnOuterClick: false, removeOnClose: true, displayMode: ''box'', cssClass: ''''}, {profile_id: {profile_id}});', '', 'certificate', '', 0, 2147483647, '', 1, 0, 1, 30),
+('bx_organizations_view_actions', 'bx_organizations', 'profile-set-badges', '_sys_menu_item_title_system_set_badges', '_sys_menu_item_title_set_badges', 'javascript:void(0)', 'bx_menu_popup(''sys_set_badges'', window, {}, {module: ''bx_organizations'', content_id: {content_id}});', '', 'check-circle', '', 0, 192, 'a:2:{s:6:"module";s:16:"bx_organizations";s:6:"method";s:19:"is_badges_avaliable";}', 1, 0, 1, 40),
+('bx_organizations_view_actions', 'bx_organizations', 'profile-actions-more', '_bx_orgs_menu_item_title_system_more_actions', '_bx_orgs_menu_item_title_more_actions', 'javascript:void(0)', 'bx_menu_popup(''bx_organizations_view_actions_more'', this, {}, {profile_id:{profile_id}});', '', 'cog', 'bx_organizations_view_actions_more', 1, 2147483647, '', 1, 0, 1, 9999);
+
+-- MENU: view actions more
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_organizations_view_actions_more', '_bx_orgs_menu_title_view_profile_actions_more', 'bx_organizations_view_actions_more', 'bx_organizations', 6, 0, 1, 'BxOrgsMenuViewActions', 'modules/boonex/organizations/classes/BxOrgsMenuViewActions.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_organizations_view_actions_more', 'bx_organizations', '_bx_orgs_menu_set_title_view_profile_actions_more', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `visibility_custom`, `active`, `copyable`, `order`) VALUES
+('bx_organizations_view_actions_more', 'bx_organizations', 'profile-fan-remove', '_bx_orgs_menu_item_title_system_leave_organization', '{title_remove_fan}', 'javascript:void(0)', 'bx_conn_action(this, \'bx_organizations_fans\', \'remove\', \'{profile_id}\')', '', 'sign-out-alt', '', 2147483647, '', 1, 0, 10),
+('bx_organizations_view_actions_more', 'bx_organizations', 'profile-friend-remove', '_bx_orgs_menu_item_title_system_unfriend', '{title_remove_friend}', 'javascript:void(0)', 'bx_conn_action(this, \'sys_profiles_friends\', \'remove\', \'{profile_id}\')', '', 'user-minus', '', 2147483647, '', 1, 0, 10),
+('bx_organizations_view_actions_more', 'bx_organizations', 'profile-relation-remove', '_bx_orgs_menu_item_title_system_relation_delete', '_bx_orgs_menu_item_title_relation_delete', 'javascript:void(0)', 'bx_conn_action(this, \'sys_profiles_relations\', \'remove\', \'{profile_id}\')', '', 'sync', '', 2147483647, '', 1, 0, 15),
+('bx_organizations_view_actions_more', 'bx_organizations', 'profile-subscribe-remove', '_bx_orgs_menu_item_title_system_unsubscribe', '_bx_orgs_menu_item_title_unsubscribe', 'javascript:void(0)', 'bx_conn_action(this, \'sys_profiles_subscriptions\', \'remove\', \'{profile_id}\')', '', 'check', '', 2147483647, '', 1, 0, 20),
+('bx_organizations_view_actions_more', 'bx_organizations', 'edit-organization-cover', '_bx_orgs_menu_item_title_system_edit_cover', '_bx_orgs_menu_item_title_edit_cover', 'page.php?i=edit-organization-cover&id={content_id}', '', '', 'edit', '', 2147483647, '', 1, 0, 25),
+('bx_organizations_view_actions_more', 'bx_organizations', 'edit-organization-profile', '_bx_orgs_menu_item_title_system_edit_profile', '_bx_orgs_menu_item_title_edit_profile', 'page.php?i=edit-organization-profile&id={content_id}', '', '', 'pencil-alt', '', 2147483647, '', 1, 0, 30),
+('bx_organizations_view_actions_more', 'bx_organizations', 'edit-organization-pricing', '_bx_orgs_menu_item_title_system_edit_pricing', '_bx_orgs_menu_item_title_edit_pricing', 'page.php?i=edit-organization-pricing&profile_id={profile_id}', '', '', 'money-check-alt', '', 2147483647, 'a:3:{s:6:"module";s:16:"bx_organizations";s:6:"method";s:20:"is_pricing_avaliable";s:6:"params";a:1:{i:0;s:12:"{profile_id}";}}', 1, 0, 41),
+('bx_organizations_view_actions_more', 'bx_organizations', 'invite-to-organization', '_bx_orgs_menu_item_title_system_invite', '_bx_orgs_menu_item_title_invite', 'page.php?i=invite-to-organization&id={content_id}', '', '', 'user-friends', '', 2147483647, '', 1, 0, 32),
+('bx_organizations_view_actions_more', 'bx_organizations', 'delete-organization-profile', '_bx_orgs_menu_item_title_system_delete_profile', '_bx_orgs_menu_item_title_delete_profile', 'page.php?i=delete-organization-profile&id={content_id}', '', '', 'remove', '', 2147483647, '', 1, 0, 40),
+('bx_organizations_view_actions_more', 'bx_organizations', 'delete-organization-account', '_bx_orgs_menu_item_title_system_delete_account', '_bx_orgs_menu_item_title_delete_account', 'page.php?i=account-settings-delete&id={account_id}', '', '', 'user-times', '', 128, '', 1, 0, 50),
+('bx_organizations_view_actions_more', 'bx_organizations', 'delete-organization-account-content', '_bx_orgs_menu_item_title_system_delete_account_content', '_bx_orgs_menu_item_title_delete_account_content', 'page.php?i=account-settings-delete&id={account_id}&content=1', '', '', 'trash', '', 128, '', 1, 0, 60);
+
+-- MENU: all actions menu for view entry 
+
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_organizations_view_actions_all', '_sys_menu_title_view_actions', 'bx_organizations_view_actions_all', 'bx_organizations', 15, 0, 1, 'BxOrgsMenuViewActionsAll', 'modules/boonex/organizations/classes/BxOrgsMenuViewActionsAll.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_organizations_view_actions_all', 'bx_organizations', '_sys_menu_set_title_view_actions', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `addon`, `submenu_object`, `submenu_popup`, `visible_for_levels`, `visibility_custom`, `active`, `copyable`, `order`) VALUES 
+('bx_organizations_view_actions_all', 'bx_organizations', 'join-organization-profile', '_bx_orgs_menu_item_title_system_pay_and_join', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 5),
+('bx_organizations_view_actions_all', 'bx_organizations', 'profile-fan-add', '_bx_orgs_menu_item_title_system_become_fan', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 10),
+('bx_organizations_view_actions_all', 'bx_organizations', 'profile-fan-remove', '_bx_orgs_menu_item_title_system_leave_organization', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 20),
+('bx_organizations_view_actions_all', 'bx_organizations', 'profile-friend-add', '_bx_orgs_menu_item_title_system_befriend', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 30),
+('bx_organizations_view_actions_all', 'bx_organizations', 'profile-friend-remove', '_bx_orgs_menu_item_title_system_unfriend', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 40),
+('bx_organizations_view_actions_all', 'bx_organizations', 'profile-relation-add', '_bx_orgs_menu_item_title_system_relation_add', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 43),
+('bx_organizations_view_actions_all', 'bx_organizations', 'profile-relation-remove', '_bx_orgs_menu_item_title_system_relation_delete', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 47),
+('bx_organizations_view_actions_all', 'bx_organizations', 'profile-subscribe-add', '_bx_orgs_menu_item_title_system_subscribe', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 50),
+('bx_organizations_view_actions_all', 'bx_organizations', 'profile-subscribe-remove', '_bx_orgs_menu_item_title_system_unsubscribe', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 60),
+('bx_organizations_view_actions_all', 'bx_organizations', 'profile-set-acl-level', '_sys_menu_item_title_system_set_acl_level', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 70),
+('bx_organizations_view_actions_all', 'bx_organizations', 'profile-set-badges', '_sys_menu_item_title_system_set_badges', '', '', '', '', '', '', '', 0, 192, 'a:2:{s:6:"module";s:16:"bx_organizations";s:6:"method";s:19:"is_badges_avaliable";}', 1, 0, 80),
+('bx_organizations_view_actions_all', 'bx_organizations', 'comment', '_sys_menu_item_title_system_va_comment', '', '', '', '', '', '', '', 0, 2147483647, '', 0, 0, 200),
+('bx_organizations_view_actions_all', 'bx_organizations', 'view', '_sys_menu_item_title_system_va_view', '', '', '', '', '', '', '', 0, 2147483647, '', 0, 0, 210),
+('bx_organizations_view_actions_all', 'bx_organizations', 'vote', '_sys_menu_item_title_system_va_vote', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 215),
+('bx_organizations_view_actions_all', 'bx_organizations', 'score', '_sys_menu_item_title_system_va_score', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 220),
+('bx_organizations_view_actions_all', 'bx_organizations', 'favorite', '_sys_menu_item_title_system_va_favorite', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 230),
+('bx_organizations_view_actions_all', 'bx_organizations', 'feature', '_sys_menu_item_title_system_va_feature', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 240),
+('bx_organizations_view_actions_all', 'bx_organizations', 'report', '_sys_menu_item_title_system_va_report', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 260),
+('bx_organizations_view_actions_all', 'bx_organizations', 'notes', '_sys_menu_item_title_system_va_notes', '_sys_menu_item_title_va_notes', 'javascript:void(0)', 'javascript:bx_get_notes(this,  ''{module_uri}'', {content_id});', '', 'exclamation-triangle', '', '', 0, 2147483647, '', 1, 0, 280),
+('bx_organizations_view_actions_all', 'bx_organizations', 'audit', '_sys_menu_item_title_system_va_audit', '_sys_menu_item_title_va_audit', 'page.php?i=dashboard-audit&module=bx_organizations&content_id={content_id}', '', '', 'history', '', '', 0, 192, '', 1, 0, 290),
+('bx_organizations_view_actions_all', 'bx_organizations', 'social-sharing', '_sys_menu_item_title_system_social_sharing', '_sys_menu_item_title_social_sharing', 'javascript:void(0)', 'oBxDolPage.share(this, \'{url_encoded}\')', '', 'share', '', '', 0, 2147483647, '', 1, 0, 300),
+('bx_organizations_view_actions_all', 'bx_organizations', 'edit-organization-cover', '_bx_orgs_menu_item_title_system_edit_cover', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 400),
+('bx_organizations_view_actions_all', 'bx_organizations', 'edit-organization-profile', '_bx_orgs_menu_item_title_system_edit_profile', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 410),
+('bx_organizations_view_actions_all', 'bx_organizations', 'edit-organization-pricing', '_bx_orgs_menu_item_title_system_edit_pricing', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 415),
+('bx_organizations_view_actions_all', 'bx_organizations', 'invite-to-organization', '_bx_orgs_menu_item_title_system_invite', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 420),
+('bx_organizations_view_actions_all', 'bx_organizations', 'delete-organization-profile', '_bx_orgs_menu_item_title_system_delete_profile', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 430),
+('bx_organizations_view_actions_all', 'bx_organizations', 'delete-organization-account', '_bx_orgs_menu_item_title_system_delete_account', '', '', '', '', '', '', '', 0, 128, '', 1, 0, 440),
+('bx_organizations_view_actions_all', 'bx_organizations', 'delete-organization-account-content', '_bx_orgs_menu_item_title_system_delete_account_content', '', '', '', '', '', '', '', 0, 128, '', 1, 0, 450),
+('bx_organizations_view_actions_all', 'bx_organizations', 'more-auto', '_sys_menu_item_title_system_va_more_auto', '_sys_menu_item_title_va_more_auto', 'javascript:void(0)', '', '', 'ellipsis-v', '', '', 0, 2147483647, '', 1, 0, 9999);
+
+-- MENU: meta (counters) menu for view entry
+
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_organizations_view_meta', '_bx_orgs_menu_title_view_profile_meta', 'bx_organizations_view_meta', 'bx_organizations', 15, 0, 1, 'BxOrgsMenuViewMeta', 'modules/boonex/organizations/classes/BxOrgsMenuViewMeta.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_organizations_view_meta', 'bx_organizations', '_bx_orgs_menu_set_title_view_profile_meta', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `submenu_popup`, `visible_for_levels`, `visibility_custom`, `active`, `copyable`, `order`) VALUES 
+('bx_organizations_view_meta', 'bx_organizations', 'membership', '_sys_menu_item_title_system_vm_membership', '_sys_menu_item_title_vm_membership', '', '', '', '', '', 0, 2147483647, '', 1, 0, 10),
+('bx_organizations_view_meta', 'bx_organizations', 'badges', '_sys_menu_item_title_system_vm_badges', '_sys_menu_item_title_vm_badges', '', '', '', '', '', 0, 2147483647, '', 1, 0, 20),
+('bx_organizations_view_meta', 'bx_organizations', 'members', '_sys_menu_item_title_system_sm_members', '_sys_menu_item_title_sm_members', '', '', '', '', '', 0, 2147483647, '', 1, 0, 30),
+('bx_organizations_view_meta', 'bx_organizations', 'subscribers', '_sys_menu_item_title_system_sm_subscribers', '_sys_menu_item_title_sm_subscribers', '', '', '', '', '', 0, 2147483647, '', 1, 0, 40),
+('bx_organizations_view_meta', 'bx_organizations', 'views', '_sys_menu_item_title_system_sm_views', '_sys_menu_item_title_sm_views', '', '', '', '', '', 0, 2147483647, '', 1, 0, 50),
+('bx_organizations_view_meta', 'bx_organizations', 'votes', '_sys_menu_item_title_system_sm_votes', '_sys_menu_item_title_sm_votes', '', '', '', '', '', 0, 2147483647, '', 1, 0, 60),
+('bx_organizations_view_meta', 'bx_organizations', 'comments', '_sys_menu_item_title_system_sm_comments', '_sys_menu_item_title_sm_comments', '', '', '', '', '', 0, 2147483647, '', 1, 0, 70);
+
+-- MENU: actions menu for my entries
+
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_organizations_my', '_bx_orgs_menu_title_entries_my', 'bx_organizations_my', 'bx_organizations', 9, 0, 1, 'BxOrgsMenu', 'modules/boonex/organizations/classes/BxOrgsMenu.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_organizations_my', 'bx_organizations', '_bx_orgs_menu_set_title_entries_my', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('bx_organizations_my', 'bx_organizations', 'create-organization-profile', '_bx_orgs_menu_item_title_system_new_profile', '_bx_orgs_menu_item_title_new_profile', 'page.php?i=create-organization-profile', '', '', 'plus', '', 2147483647, 1, 0, 0);
+
+-- MENU: module sub-menu
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_organizations_submenu', '_bx_orgs_menu_title_submenu', 'bx_organizations_submenu', 'bx_organizations', 8, 0, 1, '', '');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_organizations_submenu', 'bx_organizations', '_bx_orgs_menu_set_title_submenu', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('bx_organizations_submenu', 'bx_organizations', 'organizations-home', '_bx_orgs_menu_item_title_system_entries_recent', '_bx_orgs_menu_item_title_entries_recent', 'page.php?i=organizations-home', '', '', '', '', 2147483647, 1, 1, 1),
+('bx_organizations_submenu', 'bx_organizations', 'organizations-active', '_bx_orgs_menu_item_title_system_entries_active', '_bx_orgs_menu_item_title_entries_active', 'page.php?i=organizations-active', '', '', '', '', 2147483647, 1, 1, 2),
+('bx_organizations_submenu', 'bx_organizations', 'organizations-online', '_bx_orgs_menu_item_title_system_entries_online', '_bx_orgs_menu_item_title_entries_online', 'page.php?i=organizations-online', '', '', '', '', 2147483647, 1, 1, 3),
+('bx_organizations_submenu', 'bx_organizations', 'organizations-search', '_bx_orgs_menu_item_title_system_entries_search', '_bx_orgs_menu_item_title_entries_search', 'page.php?i=organizations-search', '', '', '', '', 2147483647, 1, 1, 4),
+('bx_organizations_submenu', 'bx_organizations', 'organizations-manage', '_bx_orgs_menu_item_title_system_entries_manage', '_bx_orgs_menu_item_title_entries_manage', 'page.php?i=organizations-manage', '', '', '', '', 2147483646, 1, 1, 5);
+
+-- MENU: view submenu
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_organizations_view_submenu', '_bx_orgs_menu_title_view_profile_submenu', 'bx_organizations_view_submenu', 'bx_organizations', 18, 0, 1, 'BxOrgsMenuView', 'modules/boonex/organizations/classes/BxOrgsMenuView.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_organizations_view_submenu', 'bx_organizations', '_bx_orgs_menu_set_title_view_profile_submenu', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `addon`, `submenu_object`, `submenu_popup`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('bx_organizations_view_submenu', 'bx_organizations', 'view-organization-profile', '_bx_orgs_menu_item_title_system_view_profile_view', '_bx_orgs_menu_item_title_view_profile_view', 'page.php?i=view-organization-profile&id={content_id}', '', '', 'briefcase col-red2', '', '', 0, 2147483647, 1, 0, 1),
+('bx_organizations_view_submenu', 'bx_organizations', 'organization-profile-info', '_bx_orgs_menu_item_title_system_view_profile_info', '_bx_orgs_menu_item_title_view_profile_info', 'page.php?i=organization-profile-info&id={content_id}', '', '', 'info-circle col-gray', '', '', 0, 2147483647, 1, 0, 2),
+('bx_organizations_view_submenu', 'bx_organizations', 'organization-profile-fans', '_bx_orgs_menu_item_title_system_view_profile_fans', '_bx_orgs_menu_item_title_view_profile_fans', 'page.php?i=organization-profile-fans&profile_id={profile_id}', '', '', 'users col-blue3', '', '', 0, 2147483647, 1, 0, 3),
+('bx_organizations_view_submenu', 'bx_organizations', 'organization-profile-friends', '_bx_orgs_menu_item_title_system_view_profile_friends', '_bx_orgs_menu_item_title_view_profile_friends', 'page.php?i=organization-profile-friends&profile_id={profile_id}', '', '', 'users col-blue3', '', '', 0, 2147483647, 1, 0, 4),
+('bx_organizations_view_submenu', 'bx_organizations', 'organization-profile-relations', '_bx_orgs_menu_item_title_system_view_profile_relations', '_bx_orgs_menu_item_title_view_profile_relations', 'page.php?i=organization-profile-relations&profile_id={profile_id}', '', '', 'sync col-blue3', '', '', 0, 2147483647, 1, 0, 5),
+('bx_organizations_view_submenu', 'bx_organizations', 'organization-profile-subscriptions', '_bx_orgs_menu_item_title_system_view_profile_subscriptions', '_bx_orgs_menu_item_title_view_profile_subscriptions', 'page.php?i=organization-profile-subscriptions&profile_id={profile_id}', '', '', 'check col-blue3', '', '', 0, 2147483647, 1, 0, 6),
+('bx_organizations_view_submenu', 'bx_organizations', 'organization-profile-comments', '_bx_orgs_menu_item_title_system_view_profile_comments', '_bx_orgs_menu_item_title_view_profile_comments', 'page.php?i=organization-profile-comments&id={content_id}', '', '', '', '', '', 0, 2147483647, 0, 0, 7),
+('bx_organizations_view_submenu', 'bx_organizations', 'more-auto', '_bx_orgs_menu_item_title_system_view_profile_more_auto', '_bx_orgs_menu_item_title_view_profile_more_auto', 'javascript:void(0)', '', '', 'ellipsis-v', '', '', 0, 2147483647, 1, 0, 9999);
+
+-- MENU: custom menu for snippet meta info
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_organizations_snippet_meta', '_sys_menu_title_snippet_meta', 'bx_organizations_snippet_meta', 'bx_organizations', 15, 0, 1, 'BxOrgsMenuSnippetMeta', 'modules/boonex/organizations/classes/BxOrgsMenuSnippetMeta.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_organizations_snippet_meta', 'bx_organizations', '_sys_menu_set_title_snippet_meta', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `visibility_custom`, `active`, `copyable`, `editable`, `order`) VALUES
+('bx_organizations_snippet_meta', 'bx_organizations', 'friends-mutual', '_sys_menu_item_title_system_sm_friends_mutual', '_sys_menu_item_title_sm_friends_mutual', '', '', '', '', '', 2147483647, '', 0, 0, 1, 0),
+('bx_organizations_snippet_meta', 'bx_organizations', 'date', '_sys_menu_item_title_system_sm_date', '_sys_menu_item_title_sm_date', '', '', '', '', '', 2147483647, '', 0, 0, 1, 1),
+('bx_organizations_snippet_meta', 'bx_organizations', 'category', '_sys_menu_item_title_system_sm_category', '_sys_menu_item_title_sm_category', '', '', '', '', '', 2147483647, '', 0, 0, 1, 5),
+('bx_organizations_snippet_meta', 'bx_organizations', 'tags', '_sys_menu_item_title_system_sm_tags', '_sys_menu_item_title_sm_tags', '', '', '', '', '', 2147483647, '', 0, 0, 1, 10),
+('bx_organizations_snippet_meta', 'bx_organizations', 'views', '_sys_menu_item_title_system_sm_views', '_sys_menu_item_title_sm_views', '', '', '', '', '', 2147483647, '', 0, 0, 1, 15),
+('bx_organizations_snippet_meta', 'bx_organizations', 'comments', '_sys_menu_item_title_system_sm_comments', '_sys_menu_item_title_sm_comments', '', '', '', '', '', 2147483647, '', 0, 0, 1, 20),
+('bx_organizations_snippet_meta', 'bx_organizations', 'members', '_sys_menu_item_title_system_sm_members', '_sys_menu_item_title_sm_members', '', '', '', '', '', 2147483647, '', 1, 0, 1, 25),
+('bx_organizations_snippet_meta', 'bx_organizations', 'friends', '_sys_menu_item_title_system_sm_friends', '_sys_menu_item_title_sm_friends', '', '', '', '', '', 2147483647, '', 1, 0, 1, 30),
+('bx_organizations_snippet_meta', 'bx_organizations', 'subscribers', '_sys_menu_item_title_system_sm_subscribers', '_sys_menu_item_title_sm_subscribers', '', '', '', '', '', 2147483647, '', 0, 0, 1, 35),
+('bx_organizations_snippet_meta', 'bx_organizations', 'membership', '_sys_menu_item_title_system_sm_membership', '_sys_menu_item_title_sm_membership', '', '', '', '', '', 2147483647, '', 0, 0, 1, 40),
+('bx_organizations_snippet_meta', 'bx_organizations', 'nl', '_sys_menu_item_title_system_sm_nl', '_sys_menu_item_title_sm_nl', '', '', '', '', '', 2147483647, '', 1, 0, 1, 45),
+('bx_organizations_snippet_meta', 'bx_organizations', 'join-paid', '_sys_menu_item_title_system_sm_join_paid', '_sys_menu_item_title_sm_join_paid', '', '', '', '', '', 2147483647, 'a:3:{s:6:"module";s:16:"bx_organizations";s:6:"method";s:33:"is_paid_join_avaliable_by_content";s:6:"params";a:1:{i:0;s:12:"{content_id}";}}', 1, 0, 1, 50),
+('bx_organizations_snippet_meta', 'bx_organizations', 'join', '_sys_menu_item_title_system_sm_join', '_sys_menu_item_title_sm_join', '', '', '', '', '', 2147483647, 'a:3:{s:6:"module";s:16:"bx_organizations";s:6:"method";s:33:"is_free_join_avaliable_by_content";s:6:"params";a:1:{i:0;s:12:"{content_id}";}}', 1, 0, 1, 55),
+('bx_organizations_snippet_meta', 'bx_organizations', 'leave', '_sys_menu_item_title_system_sm_leave', '_sys_menu_item_title_sm_leave', '', '', '', '', '', 2147483647, '', 0, 0, 1, 60),
+('bx_organizations_snippet_meta', 'bx_organizations', 'befriend', '_sys_menu_item_title_system_sm_befriend', '_sys_menu_item_title_sm_befriend', '', '', '', '', '', 2147483647, '', 1, 0, 1, 65),
+('bx_organizations_snippet_meta', 'bx_organizations', 'unfriend', '_sys_menu_item_title_system_sm_unfriend', '_sys_menu_item_title_sm_unfriend', '', '', '', '', '', 2147483647, '', 0, 0, 1, 70),
+('bx_organizations_snippet_meta', 'bx_organizations', 'subscribe', '_sys_menu_item_title_system_sm_subscribe', '_sys_menu_item_title_sm_subscribe', '', '', '', '', '', 2147483647, '', 0, 0, 1, 75),
+('bx_organizations_snippet_meta', 'bx_organizations', 'unsubscribe', '_sys_menu_item_title_system_sm_unsubscribe', '_sys_menu_item_title_sm_unsubscribe', '', '', '', '', '', 2147483647, '', 0, 0, 1, 80);
+
+-- MENU: notifications menu in account popup
+SET @iNotifMenuOrder = (SELECT IFNULL(MAX(`order`), 0) FROM `sys_menu_items` WHERE `set_name` = 'sys_account_notifications' AND `active` = 1 AND `order` < 9999 ORDER BY `order` DESC LIMIT 1);
+INSERT INTO `sys_menu_items` (`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `addon`, `submenu_object`, `visible_for_levels`, `visibility_custom`, `active`, `copyable`, `order`) VALUES
+('sys_account_notifications', 'bx_organizations', 'notifications-friend-requests', '_bx_orgs_menu_item_title_system_friends', '_bx_orgs_menu_item_title_friends', 'page.php?i=organization-profile-friends&profile_id={member_id}', '', '', 'group col-red2', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:31:"get_unconfirmed_connections_num";s:6:"params";a:1:{i:0;s:20:"sys_profiles_friends";}s:5:"class";s:23:"TemplServiceConnections";}', '', 2147483646, '', 1, 0, @iNotifMenuOrder + 1),
+('sys_account_notifications', 'bx_organizations', 'notifications-relation-requests', '_bx_orgs_menu_item_title_system_relations', '_bx_orgs_menu_item_title_relations', 'page.php?i=organization-profile-relations&profile_id={member_id}', '', '', 'sync col-blue3', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:31:"get_unconfirmed_connections_num";s:6:"params";a:1:{i:0;s:22:"sys_profiles_relations";}s:5:"class";s:23:"TemplServiceConnections";}', '', 2147483646, 'a:2:{s:6:"module";s:16:"bx_organizations";s:6:"method";s:19:"is_enable_relations";}', 1, 0, @iNotifMenuOrder + 2);
+
+-- MENU: profile stats
+SET @iNotifMenuOrder = (SELECT IFNULL(MAX(`order`), 0) FROM `sys_menu_items` WHERE `set_name` = 'sys_profile_stats' AND `active` = 1 LIMIT 1);
+INSERT INTO `sys_menu_items` (`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `addon`, `submenu_object`, `visible_for_levels`, `visibility_custom`, `active`, `copyable`, `order`) VALUES
+('sys_profile_stats', 'bx_organizations', 'profile-stats-friend-requests', '_bx_orgs_menu_item_title_system_friend_requests', '_bx_orgs_menu_item_title_friend_requests', 'page.php?i=organization-profile-friends&profile_id={member_id}', '', '', 'briefcase col-red2', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:31:"get_unconfirmed_connections_num";s:6:"params";a:1:{i:0;s:20:"sys_profiles_friends";}s:5:"class";s:23:"TemplServiceConnections";}', '', 2147483646, '', 1, 0, @iNotifMenuOrder + 1),
+('sys_profile_stats', 'bx_organizations', 'profile-stats-manage-organizations', '_bx_orgs_menu_item_title_system_manage_my_organizations', '_bx_orgs_menu_item_title_manage_my_organizations', 'page.php?i=organizations-manage', '', '_self', 'briefcase col-red2', 'a:2:{s:6:"module";s:16:"bx_organizations";s:6:"method";s:41:"get_menu_addon_manage_tools_profile_stats";}', '', 2147483646, '', 1, 0, @iNotifMenuOrder + 2),
+('sys_profile_stats', 'bx_organizations', 'profile-stats-favorite-organizations', '_bx_orgs_menu_item_title_system_favorites', '_bx_orgs_menu_item_title_favorites', 'page.php?i=organization-profile-favorites&profile_id={member_id}', '', '', 'star col-red2', 'a:2:{s:6:"module";s:16:"bx_organizations";s:6:"method";s:38:"get_menu_addon_favorites_profile_stats";}', '', 2147483646, '', 1, 0, @iNotifMenuOrder + 3);
+
+INSERT INTO `sys_menu_items` (`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `addon`, `addon_cache`, `submenu_object`, `visible_for_levels`, `visibility_custom`, `active`, `copyable`, `order`) VALUES
+('sys_profile_stats', 'bx_organizations', 'profile-stats-subscriptions', '_bx_orgs_menu_item_title_system_subscriptions', '_bx_orgs_menu_item_title_subscriptions', 'page.php?i=organization-profile-subscriptions&profile_id={member_id}#subscriptions', '', '_self', 'rss col-red2', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:25:"get_connected_content_num";s:6:"params";a:1:{i:0;s:26:"sys_profiles_subscriptions";}s:5:"class";s:23:"TemplServiceConnections";}', 0, '', 2147483646, '', 1, 0, @iNotifMenuOrder + 4),
+('sys_profile_stats', 'bx_organizations', 'profile-stats-subscribed-me', '_bx_orgs_menu_item_title_system_subscribed_me', '_bx_orgs_menu_item_title_subscribed_me', 'page.php?i=organization-profile-subscriptions&profile_id={member_id}#subscribers', '', '_self', 'rss col-red2', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:28:"get_connected_initiators_num";s:6:"params";a:1:{i:0;s:26:"sys_profiles_subscriptions";}s:5:"class";s:23:"TemplServiceConnections";}', 1, '', 2147483646, '', 1, 0, @iNotifMenuOrder + 5);
+
+INSERT INTO `sys_menu_items` (`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `addon`, `submenu_object`, `visible_for_levels`, `visibility_custom`, `active`, `copyable`, `order`) VALUES
+('sys_profile_stats', 'bx_organizations', 'profile-stats-relations', '_bx_orgs_menu_item_title_system_relations', '_bx_orgs_menu_item_title_relations', 'page.php?i=organization-profile-relations&profile_id={member_id}#relations', '', '_self', 'sync col-blue3', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:25:"get_connected_content_num";s:6:"params";a:3:{i:0;s:22:"sys_profiles_relations";i:1;i:0;i:2;i:1;}s:5:"class";s:23:"TemplServiceConnections";}', '', 2147483646, 'a:2:{s:6:"module";s:16:"bx_organizations";s:6:"method";s:19:"is_enable_relations";}', 1, 0, @iNotifMenuOrder + 6),
+('sys_profile_stats', 'bx_organizations', 'profile-stats-related-me', '_bx_orgs_menu_item_title_system_related_me', '_bx_orgs_menu_item_title_related_me', 'page.php?i=organization-profile-relations&profile_id={member_id}#related-me', '', '_self', 'sync col-blue3', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:28:"get_connected_initiators_num";s:6:"params";a:3:{i:0;s:22:"sys_profiles_relations";i:1;i:0;i:2;i:1;}s:5:"class";s:23:"TemplServiceConnections";}', '', 2147483646, 'a:2:{s:6:"module";s:16:"bx_organizations";s:6:"method";s:19:"is_enable_relations";}', 1, 0, @iNotifMenuOrder + 7);
+
+-- MENU: profile followings
+SET @iFollowingsMenuOrder = (SELECT IFNULL(MAX(`order`), 0) FROM `sys_menu_items` WHERE `set_name`='sys_profile_followings' LIMIT 1);
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `addon`, `submenu_object`, `visible_for_levels`, `collapsed`, `active`, `copyable`, `order`) VALUES 
+('sys_profile_followings', 'bx_organizations', 'organizations', '_bx_orgs_menu_item_title_system_followings', '_bx_orgs_menu_item_title_followings', 'javascript:void(0)', '', '_self', 'briefcase col-red2', '', '', 2147483647, 0, 1, 0, @iFollowingsMenuOrder + 1);
+
+-- MENU: manage tools submenu
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_organizations_menu_manage_tools', '_bx_orgs_menu_title_manage_tools', 'bx_organizations_menu_manage_tools', 'bx_organizations', 6, 0, 1, 'BxOrgsMenuManageTools', 'modules/boonex/organizations/classes/BxOrgsMenuManageTools.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_organizations_menu_manage_tools', 'bx_organizations', '_bx_orgs_menu_set_title_manage_tools', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('bx_organizations_menu_manage_tools', 'bx_organizations', 'clear-reports', '_bx_corgs_menu_item_title_system_clear_reports', '_bx_orgs_menu_item_title_clear_reports', 'javascript:void(0)', 'javascript:{js_object}.onClickClearReports({content_id});', '_self', 'eraser', '', 2147483647, 1, 0, 1),
+('bx_organizations_menu_manage_tools', 'bx_organizations', 'delete-with-content', '_bx_orgs_menu_item_title_system_delete_with_content', '_bx_orgs_menu_item_title_delete_with_content', 'javascript:void(0)', 'javascript:{js_object}.onClickDeleteWithContent({content_id});', '_self', 'far trash-alt', '', 2147483647, 1, 0, 99);
+
+-- MENU: dashboard manage tools
+SET @iManageMenuOrder = (SELECT IFNULL(MAX(`order`), 0) FROM `sys_menu_items` WHERE `set_name`='sys_account_dashboard_manage_tools' LIMIT 1);
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `addon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('sys_account_dashboard_manage_tools', 'bx_organizations', 'organizations-administration', '_bx_orgs_menu_item_title_system_admt_organizations', '_bx_orgs_menu_item_title_admt_organizations', 'page.php?i=organizations-administration', '', '_self', 'briefcase', 'a:2:{s:6:"module";s:16:"bx_organizations";s:6:"method";s:27:"get_menu_addon_manage_tools";}', '', 192, 1, 0, @iManageMenuOrder + 1);
+
+-- MENU: add menu item to profiles modules (trigger* menu sets are processed separately upon modules enable/disable)
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('trigger_profile_view_submenu', 'bx_organizations', 'joined-organizations', '_bx_orgs_menu_item_title_system_view_joined_groups', '_bx_orgs_menu_item_title_view_joined_groups', 'page.php?i=joined-organizations&profile_id={profile_id}', '', '', 'briefcase col-red2', '', 2147483647, 1, 0, 0);
+
+
+-- ACL
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_organizations', 'create entry', NULL, '_bx_orgs_acl_action_create_profile', '', 1, 1);
+SET @iIdActionProfileCreate = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_organizations', 'use paid join', NULL, '_bx_orgs_acl_action_use_paid_join', '', 1, 1);
+SET @iIdActionUsePaidJoin = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_organizations', 'delete entry', NULL, '_bx_orgs_acl_action_delete_profile', '', 1, 1);
+SET @iIdActionProfileDelete = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_organizations', 'view entry', NULL, '_bx_orgs_acl_action_view_profile', '', 1, 0);
+SET @iIdActionProfileView = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_organizations', 'edit any entry', NULL, '_bx_orgs_acl_action_edit_any_profile', '', 1, 3);
+SET @iIdActionProfileEditAny = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_organizations', 'delete any entry', NULL, '_bx_orgs_acl_action_delete_any_profile', '', 1, 3);
+SET @iIdActionProfileDeleteAny = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_organizations', 'delete invites', NULL, '_bx_orgs_acl_action_delete_invites', '', 1, 3);
+SET @iIdActionProfileDeleteInvites = LAST_INSERT_ID();
+
+SET @iUnauthenticated = 1;
+SET @iAccount = 2;
+SET @iStandard = 3;
+SET @iUnconfirmed = 4;
+SET @iPending = 5;
+SET @iSuspended = 6;
+SET @iModerator = 7;
+SET @iAdministrator = 8;
+SET @iPremium = 9;
+
+INSERT INTO `sys_acl_matrix` (`IDLevel`, `IDAction`) VALUES
+
+-- profile create
+(@iAccount, @iIdActionProfileCreate),
+(@iStandard, @iIdActionProfileCreate),
+(@iUnconfirmed, @iIdActionProfileCreate),
+(@iPending, @iIdActionProfileCreate),
+(@iModerator, @iIdActionProfileCreate),
+(@iAdministrator, @iIdActionProfileCreate),
+(@iPremium, @iIdActionProfileCreate),
+
+-- use paid join
+(@iStandard, @iIdActionUsePaidJoin),
+(@iModerator, @iIdActionUsePaidJoin),
+(@iAdministrator, @iIdActionUsePaidJoin),
+(@iPremium, @iIdActionUsePaidJoin),
+
+-- profile delete
+(@iAccount, @iIdActionProfileDelete),
+(@iStandard, @iIdActionProfileDelete),
+(@iUnconfirmed, @iIdActionProfileDelete),
+(@iPending, @iIdActionProfileDelete),
+(@iModerator, @iIdActionProfileDelete),
+(@iAdministrator, @iIdActionProfileDelete),
+(@iPremium, @iIdActionProfileDelete),
+
+-- profile view
+(@iUnauthenticated, @iIdActionProfileView),
+(@iAccount, @iIdActionProfileView),
+(@iStandard, @iIdActionProfileView),
+(@iUnconfirmed, @iIdActionProfileView),
+(@iPending, @iIdActionProfileView),
+(@iModerator, @iIdActionProfileView),
+(@iAdministrator, @iIdActionProfileView),
+(@iPremium, @iIdActionProfileView),
+
+-- any profile edit
+(@iModerator, @iIdActionProfileEditAny),
+(@iAdministrator, @iIdActionProfileEditAny),
+
+-- any profile delete
+(@iAdministrator, @iIdActionProfileDeleteAny),
+
+-- any invites delete
+(@iModerator, @iIdActionProfileDeleteInvites),
+(@iAdministrator, @iIdActionProfileDeleteInvites);
+
+
+-- METATAGS
+INSERT INTO `sys_objects_metatags` (`object`, `module`, `table_keywords`, `table_locations`, `table_mentions`, `override_class_name`, `override_class_file`) VALUES
+('bx_organizations', 'bx_organizations', 'bx_organizations_meta_keywords', 'bx_organizations_meta_locations', 'bx_organizations_meta_mentions', '', '');
+
+
+-- CATEGORY
+INSERT INTO `sys_objects_category` (`object`, `module`, `search_object`, `form_object`, `list_name`, `table`, `field`, `join`, `where`, `override_class_name`, `override_class_file`) VALUES
+('bx_organizations_cats', 'bx_organizations', 'bx_organizations', 'bx_organization', 'bx_organizations_cats', 'bx_organizations_data', 'org_cat', 'INNER JOIN `sys_profiles` ON (`sys_profiles`.`content_id` = `bx_organizations_data`.`id` AND `sys_profiles`.`type` = ''bx_organizations'')', 'AND `sys_profiles`.`status` = ''active''', '', '');
+
+
+-- SEARCH
+SET @iSearchOrder = (SELECT IFNULL(MAX(`Order`), 0) FROM `sys_objects_search`);
+INSERT INTO `sys_objects_search` (`ObjectName`, `Title`, `Order`, `ClassName`, `ClassPath`) VALUES
+('bx_organizations', '_bx_orgs', @iSearchOrder + 1, 'BxOrgsSearchResult', 'modules/boonex/organizations/classes/BxOrgsSearchResult.php'),
+('bx_organizations_cmts', '_bx_orgs_cmts', @iSearchOrder + 2, 'BxOrgsCmtsSearchResult', 'modules/boonex/organizations/classes/BxOrgsCmtsSearchResult.php');
+
+
+-- CONNECTIONS
+INSERT INTO `sys_objects_connection` (`object`, `table`, `profile_initiator`, `profile_content`, `type`, `override_class_name`, `override_class_file`) VALUES
+('bx_organizations_fans', 'bx_organizations_fans', 1, 1, 'mutual', '', '');
+
+
+-- STATS
+SET @iMaxOrderStats = (SELECT IFNULL(MAX(`order`), 0) FROM `sys_statistics`);
+INSERT INTO `sys_statistics` (`module`, `name`, `title`, `link`, `icon`, `query`, `order`) VALUES 
+('bx_organizations', 'bx_organizations', '_bx_orgs', 'page.php?i=organizations-home', 'briefcase col-red2', 'SELECT COUNT(*) FROM `bx_organizations_data` AS `td` LEFT JOIN `sys_profiles` AS `tp` ON `td`.`id` = `tp`.`content_id` AND `tp`.`type`=''bx_organizations'' WHERE 1 AND `tp`.`status`=''active''', @iMaxOrderStats + 1);
+
+
+-- CHARTS
+SET @iMaxOrderCharts = (SELECT IFNULL(MAX(`order`), 0) FROM `sys_objects_chart`);
+INSERT INTO `sys_objects_chart` (`object`, `title`, `table`, `field_date_ts`, `field_date_dt`, `field_status`, `query`, `active`, `order`, `class_name`, `class_file`) VALUES
+('bx_organizations_growth', '_bx_orgs_chart_growth', 'bx_organizations_data', 'added', '', '', 'SELECT {field_date_formatted} AS `period`, COUNT(*) AS {object} FROM {table} LEFT JOIN `sys_profiles` AS `tp` ON {table}.`id` = `tp`.`content_id` AND `tp`.`type`=''bx_organizations'' WHERE 1 AND `tp`.`status`=''active'' {where_inteval} GROUP BY `period` ORDER BY {table}.{field_date} ASC', 1, @iMaxOrderCharts + 1, 'BxDolChartGrowth', ''),
+('bx_organizations_growth_speed', '_bx_orgs_chart_growth_speed', 'bx_organizations_data', 'added', '', '', 'SELECT {field_date_formatted} AS `period`, COUNT(*) AS {object} FROM {table} LEFT JOIN `sys_profiles` AS `tp` ON {table}.`id` = `tp`.`content_id` AND `tp`.`type`=''bx_organizations'' WHERE 1 AND `tp`.`status`=''active'' {where_inteval} GROUP BY `period` ORDER BY {table}.{field_date} ASC', 1, @iMaxOrderCharts + 2, 'BxDolChartGrowthSpeed', '');
+
+
+-- GRID: connections
+INSERT INTO `sys_objects_grid` (`object`, `source_type`, `source`, `table`, `field_id`, `field_order`, `field_active`, `paginate_url`, `paginate_per_page`, `paginate_simple`, `paginate_get_start`, `paginate_get_per_page`, `filter_fields`, `filter_fields_translatable`, `filter_mode`, `sorting_fields`, `sorting_fields_translatable`, `visible_for_levels`, `responsive`, `override_class_name`, `override_class_file`) VALUES
+('bx_organizations_fans', 'Sql', 'SELECT `p`.`id`, `c`.`added`, `c`.`mutual` FROM `sys_profiles` AS `p` INNER JOIN `sys_accounts` AS `a` ON (`a`.`id` = `p`.`account_id`) {join_connections}', 'sys_profiles', 'id', 'c`.`added', '', '', 10, NULL, 'start', '', 'name,email', '', 'auto', '', '', 2147483647, 1, 'BxOrgsGridConnections', 'modules/boonex/organizations/classes/BxOrgsGridConnections.php');
+
+INSERT INTO `sys_grid_fields` (`object`, `name`, `title`, `width`, `params`, `order`) VALUES
+('bx_organizations_fans', 'name', '_sys_name', '50%', '', 10),
+('bx_organizations_fans', 'role', '_bx_orgs_txt_role', '10%', '', 15),
+('bx_organizations_fans', 'role_added', '_bx_orgs_txt_role_added', '10%', '', 16),
+('bx_organizations_fans', 'role_expired', '_bx_orgs_txt_role_expired', '10%', '', 17),
+('bx_organizations_fans', 'actions', '', '20%', '', 20);
+
+INSERT INTO `sys_grid_actions` (`object`, `type`, `name`, `title`, `icon`, `confirm`, `order`) VALUES
+('bx_organizations_fans', 'single', 'accept', '_sys_accept', '', 0, 10),
+('bx_organizations_fans', 'single', 'set_role', '_bx_orgs_txt_set_role', '', 0, 20),
+('bx_organizations_fans', 'single', 'set_role_submit', '', '', 0, 21),
+('bx_organizations_fans', 'single', 'delete', '', 'remove', 1, 40);
+
+-- GRID: invites
+INSERT INTO `sys_objects_grid` (`object`, `source_type`, `source`, `table`, `field_id`, `field_order`, `field_active`, `paginate_url`, `paginate_per_page`, `paginate_simple`, `paginate_get_start`, `paginate_get_per_page`, `filter_fields`, `filter_fields_translatable`, `filter_mode`, `sorting_fields`, `sorting_fields_translatable`, `visible_for_levels`, `responsive`, `override_class_name`, `override_class_file`) VALUES
+('bx_organizations_invites', 'Sql', 'SELECT `i`.`id`, `i`.`invited_profile_id`, `i`.`added`, `i`.`author_profile_id` FROM `sys_profiles` AS `p` INNER JOIN `sys_accounts` AS `a` ON `a`.`id` = `p`.`account_id` INNER JOIN `bx_organizations_invites` AS `i` ON `i`.`invited_profile_id` = `p`.`id` ', 'bx_organizations_invites', 'id', 'i`.`added', '', '', 10, NULL, 'start', '', 'name,email', '', 'auto', '', '', 2147483647, 0, 'BxOrgsGridInvites', 'modules/boonex/organizations/classes/BxOrgsGridInvites.php');
+
+INSERT INTO `sys_grid_fields` (`object`, `name`, `title`, `width`, `params`, `order`) VALUES
+('bx_organizations_invites', 'name', '_sys_name', '33%', '', 10),
+('bx_organizations_invites', 'added', '_sys_added', '33%', '', 20),
+('bx_organizations_invites', 'actions', '', '34%', '', 30);
+
+INSERT INTO `sys_grid_actions` (`object`, `type`, `name`, `title`, `icon`, `confirm`, `order`) VALUES
+('bx_organizations_invites', 'single', 'delete', '', 'remove', 1, 10);
+
+-- GRIDS: administration
+INSERT INTO `sys_objects_grid` (`object`, `source_type`, `source`, `table`, `field_id`, `field_order`, `field_active`, `paginate_url`, `paginate_per_page`, `paginate_simple`, `paginate_get_start`, `paginate_get_per_page`, `filter_fields`, `filter_fields_translatable`, `filter_mode`, `sorting_fields`, `sorting_fields_translatable`, `visible_for_levels`, `override_class_name`, `override_class_file`) VALUES
+('bx_organizations_administration', 'Sql', 'SELECT `td`.*, `td`.`org_name` AS `fullname`, `ta`.`email` AS `account`, `ta`.`logged` AS `last_online`, `tp`.`status` AS `status`, `tp`.`id` as `profile_id` FROM `bx_organizations_data` AS `td` LEFT JOIN `sys_profiles` AS `tp` ON `td`.`id`=`tp`.`content_id` AND `tp`.`type`=''bx_organizations'' LEFT JOIN `sys_accounts` AS `ta` ON `tp`.`account_id`=`ta`.`id` WHERE 1 ', 'bx_organizations_data', 'id', 'last_online', 'status', '', 20, NULL, 'start', '', 'org_name,email', '', 'like', 'reports', '', 192, 'BxOrgsGridAdministration', 'modules/boonex/organizations/classes/BxOrgsGridAdministration.php'),
+('bx_organizations_common', 'Sql', 'SELECT `td`.*, `td`.`org_name` AS `fullname`, `ta`.`email` AS `account`, `ta`.`logged` AS `last_online`, `tp`.`status` AS `status` FROM `bx_organizations_data` AS `td` LEFT JOIN `sys_profiles` AS `tp` ON `td`.`id`=`tp`.`content_id` AND `tp`.`type`=''bx_organizations'' LEFT JOIN `sys_accounts` AS `ta` ON `tp`.`account_id`=`ta`.`id` WHERE 1 ', 'bx_organizations_data', 'id', 'last_online', 'status', '', 20, NULL, 'start', '', 'org_name', '', 'like', '', '', 2147483647, 'BxOrgsGridCommon', 'modules/boonex/organizations/classes/BxOrgsGridCommon.php');
+
+INSERT INTO `sys_grid_fields` (`object`, `name`, `title`, `width`, `translatable`, `chars_limit`, `params`, `order`) VALUES
+('bx_organizations_administration', 'checkbox', '_sys_select', '2%', 0, '', '', 1),
+('bx_organizations_administration', 'switcher', '_bx_orgs_grid_column_title_adm_active', '8%', 0, '', '', 2),
+('bx_organizations_administration', 'reports', '_sys_txt_reports_title', '5%', 0, '', '', 3),
+('bx_organizations_administration', 'fullname', '_bx_orgs_grid_column_title_adm_fullname', '25%', 0, '', '', 4),
+('bx_organizations_administration', 'last_online', '_bx_orgs_grid_column_title_adm_last_online', '20%', 1, '25', '', 5),
+('bx_organizations_administration', 'account', '_bx_orgs_grid_column_title_adm_account', '20%', 0, '25', '', 6),
+('bx_organizations_administration', 'actions', '', '20%', 0, '', '', 7),
+
+('bx_organizations_common', 'checkbox', '_sys_select', '2%', 0, '', '', 1),
+('bx_organizations_common', 'fullname', '_bx_orgs_grid_column_title_adm_fullname', '48%', 0, '', '', 2),
+('bx_organizations_common', 'last_online', '_bx_orgs_grid_column_title_adm_last_online', '30%', 1, '25', '', 3),
+('bx_organizations_common', 'actions', '', '20%', 0, '', '', 4);
+
+INSERT INTO `sys_grid_actions` (`object`, `type`, `name`, `title`, `icon`, `icon_only`, `confirm`, `order`) VALUES
+('bx_organizations_administration', 'bulk', 'set_acl_level', '_bx_orgs_grid_action_title_adm_set_acl_level', '', 0, 0, 1),
+('bx_organizations_administration', 'bulk', 'clear_reports', '_bx_orgs_grid_action_title_adm_clear_reports', '', 0, 1, 2),
+('bx_organizations_administration', 'bulk', 'delete_with_content', '_bx_orgs_grid_action_title_adm_delete_with_content', '', 0, 1, 3),
+('bx_organizations_administration', 'single', 'set_acl_level', '_bx_orgs_grid_action_title_adm_set_acl_level', 'certificate', 1, 0, 1),
+('bx_organizations_administration', 'single', 'settings', '_bx_orgs_grid_action_title_adm_more_actions', 'cog', 1, 0, 2),
+('bx_organizations_administration', 'single', 'audit_content', '_bx_orgs_grid_action_title_adm_audit_content', 'search', 1, 0, 3),
+('bx_organizations_administration', 'single', 'audit_profile', '_bx_orgs_grid_action_title_adm_audit_profile', 'search-location', 1, 0, 4),
+
+('bx_organizations_common', 'bulk', 'delete_with_content', '_bx_orgs_grid_action_title_adm_delete_with_content', '', 0, 1, 1),
+('bx_organizations_common', 'single', 'settings', '_bx_orgs_grid_action_title_adm_more_actions', 'cog', 1, 0, 1);
+
+-- GRIDS: Pricing
+INSERT INTO `sys_objects_grid` (`object`, `source_type`, `source`, `table`, `field_id`, `field_order`, `field_active`, `paginate_url`, `paginate_per_page`, `paginate_simple`, `paginate_get_start`, `paginate_get_per_page`, `filter_fields`, `filter_fields_translatable`, `filter_mode`, `sorting_fields`, `sorting_fields_translatable`, `visible_for_levels`, `override_class_name`, `override_class_file`) VALUES
+('bx_organizations_prices_manage', 'Sql', 'SELECT * FROM `bx_organizations_prices` WHERE 1 ', 'bx_organizations_prices', 'id', 'order', '', '', 100, NULL, 'start', '', 'period,period_unit,price', '', 'like', '', '', 2147483647, 'BxOrgsGridPricesManage', 'modules/boonex/organizations/classes/BxOrgsGridPricesManage.php'),
+('bx_organizations_prices_view', 'Sql', 'SELECT * FROM `bx_organizations_prices` WHERE 1 ', 'bx_organizations_prices', 'id', 'order', '', '', 100, NULL, 'start', '', 'period,period_unit,price', '', 'like', '', '', 2147483647, 'BxOrgsGridPricesView', 'modules/boonex/organizations/classes/BxOrgsGridPricesView.php');
+
+INSERT INTO `sys_grid_fields` (`object`, `name`, `title`, `width`, `translatable`, `chars_limit`, `params`, `order`) VALUES
+('bx_organizations_prices_manage', 'checkbox', '_sys_select', '1%', 0, '', '', 1),
+('bx_organizations_prices_manage', 'order', '', '1%', 0, '', '', 2),
+('bx_organizations_prices_manage', 'name', '_bx_orgs_grid_column_title_name', '38%', 0, 32, '', 3),
+('bx_organizations_prices_manage', 'price', '_bx_orgs_grid_column_title_price', '20%', 0, 16, '', 4),
+('bx_organizations_prices_manage', 'period', '_bx_orgs_grid_column_title_period', '20%', 0, 16, '', 5),
+('bx_organizations_prices_manage', 'actions', '', '20%', 0, '', '', 6),
+
+('bx_organizations_prices_view', 'role_id', '_bx_orgs_grid_column_title_role_id', '40%', 0, 32, '', 1),
+('bx_organizations_prices_view', 'price', '_bx_orgs_grid_column_title_price', '20%', 0, 16, '', 2),
+('bx_organizations_prices_view', 'period', '_bx_orgs_grid_column_title_period', '20%', 0, 16, '', 3),
+('bx_organizations_prices_view', 'actions', '', '20%', 0, '', '', 4);
+
+INSERT INTO `sys_grid_actions` (`object`, `type`, `name`, `title`, `icon`, `icon_only`, `confirm`, `order`) VALUES
+('bx_organizations_prices_manage', 'independent', 'add', '_bx_orgs_grid_action_title_add', '', 0, 0, 1),
+('bx_organizations_prices_manage', 'single', 'edit', '_bx_orgs_grid_action_title_edit', 'pencil-alt', 1, 0, 1),
+('bx_organizations_prices_manage', 'single', 'delete', '_bx_orgs_grid_action_title_delete', 'remove', 1, 1, 2),
+('bx_organizations_prices_manage', 'bulk', 'delete', '_bx_orgs_grid_action_title_delete', '', 0, 1, 1),
+
+('bx_organizations_prices_view', 'single', 'buy', '_bx_orgs_grid_action_title_buy', 'cart-plus', 0, 0, 1),
+('bx_organizations_prices_view', 'single', 'subscribe', '_bx_orgs_grid_action_title_subscribe', 'credit-card', 0, 0, 2),
+('bx_organizations_prices_view', 'single', 'choose', '_bx_orgs_grid_action_title_choose', 'far check-square', 0, 0, 3);
+
+
+-- LIVE UPDATES
+INSERT INTO `sys_objects_live_updates`(`name`, `frequency`, `service_call`, `active`) VALUES
+('bx_organizations_friend_requests', 1, 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:40:"get_live_updates_unconfirmed_connections";s:6:"params";a:5:{i:0;s:16:"bx_organizations";i:1;s:20:"sys_profiles_friends";i:2;a:2:{s:11:"menu_object";s:18:"sys_toolbar_member";s:9:"menu_item";s:7:"account";}i:3;a:2:{s:11:"menu_object";s:25:"sys_account_notifications";s:9:"menu_item";s:29:"notifications-friend-requests";}i:4;s:7:"{count}";}s:5:"class";s:23:"TemplServiceConnections";}', 1);
+
+
+-- ALERTS
+INSERT INTO `sys_alerts_handlers` (`name`, `class`, `file`, `service_call`) VALUES 
+('bx_organizations', 'BxOrgsAlertsResponse', 'modules/boonex/organizations/classes/BxOrgsAlertsResponse.php', '');
+SET @iHandler := LAST_INSERT_ID();
+
+INSERT INTO `sys_alerts` (`unit`, `action`, `handler_id`) VALUES
+('system', 'save_setting', @iHandler),
+('account', 'check_switch_context', @iHandler),
+('sys_profiles_friends', 'connection_added', @iHandler),
+('bx_timeline', 'post_common', @iHandler),
+('bx_organizations_pics', 'file_deleted', @iHandler),
+('bx_organizations_fans', 'connection_added', @iHandler),
+('bx_organizations_fans', 'connection_removed', @iHandler),
+('bx_organizations', 'fan_added', @iHandler),
+('bx_organizations', 'join_invitation', @iHandler),
+('bx_organizations', 'join_request', @iHandler),
+('bx_organizations', 'join_request_accepted', @iHandler),
+('bx_organizations', 'timeline_view', @iHandler),
+('bx_organizations', 'timeline_post', @iHandler),
+('bx_organizations', 'timeline_delete', @iHandler),
+('bx_organizations', 'timeline_comment', @iHandler),
+('bx_organizations', 'timeline_vote', @iHandler),
+('bx_organizations', 'timeline_score', @iHandler),
+('bx_organizations', 'timeline_report', @iHandler),
+('bx_organizations', 'timeline_repost', @iHandler),
+('bx_organizations', 'timeline_pin', @iHandler),
+('bx_organizations', 'timeline_promote', @iHandler);
+
+
+-- PRIVACY 
+INSERT INTO `sys_objects_privacy` (`object`, `module`, `action`, `title`, `default_group`, `spaces`, `table`, `table_field_id`, `table_field_author`, `override_class_name`, `override_class_file`) VALUES
+('bx_organizations_allow_view_to', 'bx_organizations', 'view', '_bx_orgs_form_profile_input_allow_view_to', '3', '', 'bx_organizations_data', 'id', 'author', 'BxOrgsPrivacy', 'modules/boonex/organizations/classes/BxOrgsPrivacy.php'),
+('bx_organizations_allow_view_notification_to', 'bx_organizations', 'view_event', '_bx_orgs_form_profile_input_allow_view_notification_to', '3', '', 'bx_notifications_events', 'id', 'object_owner_id', 'BxOrgsPrivacyNotifications', 'modules/boonex/organizations/classes/BxOrgsPrivacyNotifications.php'),
+('bx_organizations_allow_post_to', 'bx_organizations', 'post', '_bx_orgs_form_profile_input_allow_post_to', '5', '', 'bx_organizations_data', 'id', 'author', 'BxOrgsPrivacyPost', 'modules/boonex/organizations/classes/BxOrgsPrivacyPost.php'),
+('bx_organizations_allow_contact_to', 'bx_organizations', 'contact', '_bx_orgs_form_profile_input_allow_contact_to', '3', '', 'bx_organizations_data', 'id', 'author', 'BxOrgsPrivacyContact', 'modules/boonex/organizations/classes/BxOrgsPrivacyContact.php'),
+('bx_organizations_allow_view_favorite_list', 'bx_organizations', 'view_favorite_list', '_bx_orgs_form_entry_input_allow_view_favorite_list', '3', '', 'bx_organizations_favorites_lists', 'id', 'author_id', 'BxOrgsPrivacy', 'modules/boonex/organizations/classes/BxOrgsPrivacy.php');
+
+
+-- EMAIL TEMPLATES
+INSERT INTO `sys_email_templates` (`Module`, `NameSystem`, `Name`, `Subject`, `Body`) VALUES
+('bx_organizations', '_bx_orgs_email_friend_request', 'bx_organizations_friend_request', '_bx_orgs_email_friend_request_subject', '_bx_orgs_email_friend_request_body'),
+('bx_organizations', '_bx_orgs_email_join_request', 'bx_organizations_join_request', '_bx_orgs_email_join_request_subject', '_bx_orgs_email_join_request_body'),
+('bx_organizations', '_bx_orgs_email_join_reject', 'bx_organizations_join_reject', '_bx_orgs_email_join_reject_subject', '_bx_orgs_email_join_reject_body'),
+('bx_organizations', '_bx_orgs_email_join_confirm', 'bx_organizations_join_confirm', '_bx_orgs_email_join_confirm_subject', '_bx_orgs_email_join_confirm_body'),
+('bx_organizations', '_bx_orgs_email_fan_remove', 'bx_organizations_fan_remove', '_bx_orgs_email_fan_remove_subject', '_bx_orgs_email_fan_remove_body'),
+('bx_organizations', '_bx_orgs_email_fan_become_admin', 'bx_organizations_fan_become_admin', '_bx_orgs_email_fan_become_admin_subject', '_bx_orgs_email_fan_become_admin_body'),
+('bx_organizations', '_bx_orgs_email_admin_become_fan', 'bx_organizations_admin_become_fan', '_bx_orgs_email_admin_become_fan_subject', '_bx_orgs_email_admin_become_fan_body'),
+('bx_organizations', '_bx_orgs_email_set_role', 'bx_organizations_set_role', '_bx_orgs_email_set_role_subject', '_bx_orgs_email_set_role_body'),
+('bx_organizations', '_bx_orgs_email_invitation', 'bx_organizations_invitation', '_bx_orgs_email_invitation_subject', '_bx_orgs_email_invitation_body');
+
+
+-- UPLOADERS
+INSERT INTO `sys_objects_uploader` (`object`, `active`, `override_class_name`, `override_class_file`) VALUES
+('bx_organizations_cover_crop', 1, 'BxOrgsUploaderCoverCrop', 'modules/boonex/organizations/classes/BxOrgsUploaderCoverCrop.php'),
+('bx_organizations_picture_crop', 1, 'BxOrgsUploaderPictureCrop', 'modules/boonex/organizations/classes/BxOrgsUploaderPictureCrop.php');
+
+
+-- CRON
+INSERT INTO `sys_cron_jobs` (`name`, `time`, `class`, `file`, `service_call`) VALUES
+('bx_organizations_pruning', '0 0 * * *', 'BxOrgsCronPruning', 'modules/boonex/organizations/classes/BxOrgsCronPruning.php', '');

+ 565 - 0
modules/boonex/organizations/updates/13.0.3_13.0.4/source/install/sql/install.sql

@@ -0,0 +1,565 @@
+
+SET @sStorageEngine = (SELECT `value` FROM `sys_options` WHERE `name` = 'sys_storage_default');
+
+-- TABLE: PROFILES
+CREATE TABLE IF NOT EXISTS `bx_organizations_data` (
+  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+  `author` int(10) unsigned NOT NULL,
+  `added` int(11) NOT NULL,
+  `changed` int(11) NOT NULL,
+  `picture` int(11) NOT NULL,
+  `cover` int(11) NOT NULL,
+  `org_name` varchar(255) NOT NULL,
+  `org_cat` int(11) NOT NULL,
+  `multicat` text NOT NULL,
+  `org_desc` text NOT NULL,
+  `labels` text NOT NULL,
+  `location` text NOT NULL,
+  `views` int(11) NOT NULL default '0',
+  `rate` float NOT NULL default '0',
+  `votes` int(11) NOT NULL default '0',
+  `score` int(11) NOT NULL default '0',
+  `sc_up` int(11) NOT NULL default '0',
+  `sc_down` int(11) NOT NULL default '0',
+  `favorites` int(11) NOT NULL default '0',
+  `comments` int(11) NOT NULL default '0',
+  `reports` int(11) NOT NULL default '0',
+  `featured` int(11) NOT NULL default '0',
+  `join_confirmation` tinyint(4) NOT NULL DEFAULT '1',
+  `allow_view_to` varchar(16) NOT NULL DEFAULT '3',
+  `allow_post_to` varchar(16) NOT NULL DEFAULT '5',
+  `allow_contact_to` varchar(16) NOT NULL DEFAULT '3',
+  `status` enum('active','awaiting','hidden') NOT NULL DEFAULT 'active',
+  PRIMARY KEY (`id`),
+  FULLTEXT KEY `search_fields` (`org_name`,`org_desc`)
+);
+
+-- TABLE: STORAGES & TRANSCODERS
+CREATE TABLE IF NOT EXISTS `bx_organizations_pics` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `profile_id` int(10) unsigned NOT NULL,
+  `remote_id` varchar(128) NOT NULL,
+  `path` varchar(255) NOT NULL,
+  `file_name` varchar(255) NOT NULL,
+  `mime_type` varchar(128) NOT NULL,
+  `ext` varchar(32) NOT NULL,
+  `size` bigint(20) NOT NULL,
+  `added` int(11) NOT NULL,
+  `modified` int(11) NOT NULL,
+  `private` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `remote_id` (`remote_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_organizations_pics_resized` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `profile_id` int(10) unsigned NOT NULL,
+  `remote_id` varchar(128) NOT NULL,
+  `path` varchar(255) NOT NULL,
+  `file_name` varchar(255) NOT NULL,
+  `mime_type` varchar(128) NOT NULL,
+  `ext` varchar(32) NOT NULL,
+  `size` bigint(20) NOT NULL,
+  `added` int(11) NOT NULL,
+  `modified` int(11) NOT NULL,
+  `private` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `remote_id` (`remote_id`)
+);
+
+-- TABLE: comments
+CREATE TABLE IF NOT EXISTS `bx_organizations_cmts` (
+  `cmt_id` int(11) NOT NULL AUTO_INCREMENT,
+  `cmt_parent_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_vparent_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_object_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_author_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_level` int(11) NOT NULL DEFAULT '0',
+  `cmt_text` text NOT NULL,
+  `cmt_mood` tinyint(4) NOT NULL DEFAULT '0',
+  `cmt_rate` int(11) NOT NULL DEFAULT '0',
+  `cmt_rate_count` int(11) NOT NULL DEFAULT '0',
+  `cmt_time` int(11) unsigned NOT NULL DEFAULT '0',
+  `cmt_replies` int(11) NOT NULL DEFAULT '0',
+  `cmt_pinned` int(11) NOT NULL default '0',
+  `cmt_cf` int(11) NOT NULL default '1',
+  PRIMARY KEY (`cmt_id`),
+  KEY `cmt_object_id` (`cmt_object_id`,`cmt_parent_id`),
+  FULLTEXT KEY `search_fields` (`cmt_text`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_organizations_cmts_notes` (
+  `cmt_id` int(11) NOT NULL AUTO_INCREMENT,
+  `cmt_parent_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_vparent_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_object_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_author_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_level` int(11) NOT NULL DEFAULT '0',
+  `cmt_text` text NOT NULL,
+  `cmt_mood` tinyint(4) NOT NULL DEFAULT '0',
+  `cmt_rate` int(11) NOT NULL DEFAULT '0',
+  `cmt_rate_count` int(11) NOT NULL DEFAULT '0',
+  `cmt_time` int(11) unsigned NOT NULL DEFAULT '0',
+  `cmt_replies` int(11) NOT NULL DEFAULT '0',
+  `cmt_pinned` int(11) NOT NULL default '0',
+  PRIMARY KEY (`cmt_id`),
+  KEY `cmt_object_id` (`cmt_object_id`,`cmt_parent_id`),
+  FULLTEXT KEY `search_fields` (`cmt_text`)
+);
+
+-- TABLE: VIEWS
+CREATE TABLE IF NOT EXISTS `bx_organizations_views_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `viewer_id` int(11) NOT NULL default '0',
+  `viewer_nip` int(11) unsigned NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `id` (`object_id`,`viewer_id`,`viewer_nip`)
+);
+
+-- TABLE: VOTES
+CREATE TABLE IF NOT EXISTS `bx_organizations_votes` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `count` int(11) NOT NULL default '0',
+  `sum` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `object_id` (`object_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_organizations_votes_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `author_nip` int(11) unsigned NOT NULL default '0',
+  `value` tinyint(4) NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `vote` (`object_id`, `author_nip`)
+);
+
+-- TABLE: favorites
+CREATE TABLE IF NOT EXISTS `bx_organizations_favorites_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `list_id` int(11) NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `id` (`object_id`,`author_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_organizations_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: reports
+CREATE TABLE IF NOT EXISTS `bx_organizations_reports` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `count` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `object_id` (`object_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_organizations_reports_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `author_nip` int(11) unsigned NOT NULL default '0',
+  `type` varchar(32) NOT NULL default '',
+  `text` text NOT NULL default '',
+  `date` int(11) NOT NULL default '0',
+  `checked_by` int(11) NOT NULL default '0',
+  `status` tinyint(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `report` (`object_id`, `author_nip`)
+);
+
+-- TABLE: metas
+CREATE TABLE IF NOT EXISTS `bx_organizations_meta_keywords` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(10) unsigned NOT NULL,
+  `keyword` varchar(255) NOT NULL,
+  PRIMARY KEY (`id`),
+  KEY `object_id` (`object_id`),
+  KEY `keyword` (`keyword`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_organizations_meta_locations` (
+  `object_id` int(10) unsigned NOT NULL,
+  `lat` double NOT NULL,
+  `lng` double NOT NULL,
+  `country` varchar(2) NOT NULL,
+  `state` varchar(255) NOT NULL,
+  `city` varchar(255) NOT NULL,
+  `zip` varchar(255) NOT NULL,
+  `street` varchar(255) NOT NULL,
+  `street_number` varchar(255) NOT NULL,
+  PRIMARY KEY (`object_id`),
+  KEY `country_state_city` (`country`,`state`(8),`city`(8))
+);
+
+CREATE TABLE `bx_organizations_meta_mentions` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(10) unsigned NOT NULL,
+  `profile_id` int(10) unsigned NOT NULL,
+  PRIMARY KEY (`id`),
+  KEY `object_id` (`object_id`),
+  KEY `profile_id` (`profile_id`)
+);
+
+-- TABLE: Invites
+CREATE TABLE IF NOT EXISTS `bx_organizations_invites` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `key` varchar(128) NOT NULL default '0',
+  `group_profile_id` int(11) NOT NULL default '0',
+  `author_profile_id` int(11) NOT NULL default '0',
+  `invited_profile_id` int(11) NOT NULL default '0',
+  `added` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`)
+);
+
+-- TABLE: fans
+CREATE TABLE IF NOT EXISTS `bx_organizations_fans` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `initiator` int(11) NOT NULL,
+  `content` int(11) NOT NULL,
+  `mutual` tinyint(4) NOT NULL,
+  `added` int(10) unsigned NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `initiator` (`initiator`,`content`),
+  KEY `content` (`content`)
+);
+
+-- TABLE: admins
+CREATE TABLE IF NOT EXISTS `bx_organizations_admins` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `group_profile_id` int(10) unsigned NOT NULL,
+  `fan_id` int(10) unsigned NOT NULL,
+  `role` int(10) unsigned NOT NULL default '0',
+  `order` varchar(32) NOT NULL default '',
+  `added` int(11) unsigned NOT NULL default '0',
+  `expired` int(11) unsigned NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `admin` (`group_profile_id`,`fan_id`)
+);
+
+-- TABLE: scores
+CREATE TABLE IF NOT EXISTS `bx_organizations_scores` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `count_up` int(11) NOT NULL default '0',
+  `count_down` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `object_id` (`object_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_organizations_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: Pricing
+CREATE TABLE IF NOT EXISTS `bx_organizations_prices` (
+  `id` int(11) NOT NULL auto_increment,
+  `profile_id` int(11) NOT NULL default '0',
+  `role_id` int(11) unsigned NOT NULL default '0',
+  `name` varchar(128) NOT NULL default '',
+  `period` int(11) unsigned NOT NULL default '1',
+  `period_unit` varchar(32) NOT NULL default '',
+  `price` float unsigned NOT NULL default '1',
+  `order` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `name` (`name`),
+  UNIQUE KEY `type` (`profile_id`, `role_id`,`period`, `period_unit`)
+);
+
+
+-- 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_organizations_pics', @sStorageEngine, '', 360, 2592000, 3, 'bx_organizations_pics', 'allow-deny', 'jpg,jpeg,jpe,gif,png', '', 0, 0, 0, 0, 0, 0),
+('bx_organizations_pics_resized', @sStorageEngine, '', 360, 2592000, 3, 'bx_organizations_pics_resized', 'allow-deny', 'jpg,jpeg,jpe,gif,png', '', 0, 0, 0, 0, 0, 0);
+
+INSERT INTO `sys_objects_transcoder` (`object`, `storage_object`, `source_type`, `source_params`, `private`, `atime_tracking`, `atime_pruning`, `ts`) VALUES 
+('bx_organizations_icon', 'bx_organizations_pics_resized', 'Storage', 'a:1:{s:6:"object";s:21:"bx_organizations_pics";}', 'no', '1', '2592000', '0'),
+('bx_organizations_thumb', 'bx_organizations_pics_resized', 'Storage', 'a:1:{s:6:"object";s:21:"bx_organizations_pics";}', 'no', '1', '2592000', '0'),
+('bx_organizations_avatar', 'bx_organizations_pics_resized', 'Storage', 'a:1:{s:6:"object";s:21:"bx_organizations_pics";}', 'no', '1', '2592000', '0'),
+('bx_organizations_avatar_big', 'bx_organizations_pics_resized', 'Storage', 'a:1:{s:6:"object";s:21:"bx_organizations_pics";}', 'no', '1', '2592000', '0'),
+('bx_organizations_picture', 'bx_organizations_pics_resized', 'Storage', 'a:1:{s:6:"object";s:21:"bx_organizations_pics";}', 'no', '1', '2592000', '0'),
+('bx_organizations_cover', 'bx_organizations_pics_resized', 'Storage', 'a:1:{s:6:"object";s:21:"bx_organizations_pics";}', 'no', '1', '2592000', '0'),
+('bx_organizations_cover_thumb', 'bx_organizations_pics_resized', 'Storage', 'a:1:{s:6:"object";s:21:"bx_organizations_pics";}', 'no', '1', '2592000', '0'),
+('bx_organizations_gallery', 'bx_organizations_pics_resized', 'Storage', 'a:1:{s:6:"object";s:21:"bx_organizations_pics";}', 'no', '1', '2592000', '0');
+
+INSERT INTO `sys_transcoder_filters` (`transcoder_object`, `filter`, `filter_params`, `order`) VALUES 
+('bx_organizations_icon', 'Resize', 'a:3:{s:1:"w";s:2:"30";s:1:"h";s:2:"30";s:13:"square_resize";s:1:"1";}', '0'),
+('bx_organizations_thumb', 'Resize', 'a:3:{s:1:"w";s:2:"50";s:1:"h";s:2:"50";s:13:"square_resize";s:1:"1";}', '0'),
+('bx_organizations_avatar', 'Resize', 'a:3:{s:1:"w";s:3:"100";s:1:"h";s:3:"100";s:13:"square_resize";s:1:"1";}', '0'),
+('bx_organizations_avatar_big', 'Resize', 'a:3:{s:1:"w";s:3:"200";s:1:"h";s:3:"200";s:13:"square_resize";s:1:"1";}', '0'),
+('bx_organizations_picture', 'Resize', 'a:3:{s:1:"w";s:4:"1024";s:1:"h";s:4:"1024";s:13:"square_resize";s:1:"0";}', '0'),
+('bx_organizations_cover', 'Resize', 'a:2:{s:1:"w";s:3:"960";s:1:"h";s:3:"480";}', '0'),
+('bx_organizations_cover_thumb', 'Resize', 'a:3:{s:1:"w";s:2:"48";s:1:"h";s:2:"48";s:13:"square_resize";s:1:"1";}', '0'),
+('bx_organizations_gallery', 'Resize', 'a:1:{s:1:"w";s:3:"500";}', '0');
+
+
+-- FORMS
+INSERT INTO `sys_objects_form`(`object`, `module`, `title`, `action`, `form_attrs`, `table`, `key`, `uri`, `uri_title`, `submit_name`, `params`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_organization', 'bx_organizations', '_bx_orgs_form_profile', '', 'a:1:{s:7:\"enctype\";s:19:\"multipart/form-data\";}', 'bx_organizations_data', 'id', '', '', 'do_submit', '', 0, 1, 'BxOrgsFormEntry', 'modules/boonex/organizations/classes/BxOrgsFormEntry.php');
+
+INSERT INTO `sys_form_displays`(`object`, `display_name`, `module`, `view_mode`, `title`) VALUES 
+('bx_organization', 'bx_organization_add', 'bx_organizations', 0, '_bx_orgs_form_profile_display_add'),
+('bx_organization', 'bx_organization_delete', 'bx_organizations', 0, '_bx_orgs_form_profile_display_delete'),
+('bx_organization', 'bx_organization_edit', 'bx_organizations', 0, '_bx_orgs_form_profile_display_edit'),
+('bx_organization', 'bx_organization_edit_cover', 'bx_organizations', 0, '_bx_orgs_form_profile_display_edit_cover'),
+('bx_organization', 'bx_organization_view', 'bx_organizations', 1, '_bx_orgs_form_profile_display_view'),
+('bx_organization', 'bx_organization_view_full', 'bx_organizations', 1, '_bx_orgs_form_profile_display_view_full'),
+('bx_organization', 'bx_organization_invite', 'bx_organizations', 0, '_bx_orgs_form_profile_display_invite');
+
+INSERT INTO `sys_form_inputs`(`object`, `module`, `name`, `value`, `values`, `checked`, `type`, `caption_system`, `caption`, `info`, `required`, `collapsed`, `html`, `attrs`, `attrs_tr`, `attrs_wrapper`, `checker_func`, `checker_params`, `checker_error`, `db_pass`, `db_params`, `editable`, `deletable`) VALUES 
+('bx_organization', 'bx_organizations', 'allow_view_to', 3, '', 0, 'custom', '_bx_orgs_form_profile_input_sys_allow_view_to', '_bx_orgs_form_profile_input_allow_view_to', '_bx_orgs_form_profile_input_allow_view_to_info', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_organization', 'bx_organizations', 'allow_post_to', 5, '', 0, 'custom', '_bx_orgs_form_profile_input_sys_allow_post_to', '_bx_orgs_form_profile_input_allow_post_to', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_organization', 'bx_organizations', 'allow_contact_to', 3, '', 0, 'custom', '_bx_orgs_form_profile_input_sys_allow_contact_to', '_bx_orgs_form_profile_input_allow_contact_to', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_organization', 'bx_organizations', 'delete_confirm', 1, '', 0, 'checkbox', '_bx_orgs_form_profile_input_sys_delete_confirm', '_bx_orgs_form_profile_input_delete_confirm', '_bx_orgs_form_profile_input_delete_confirm_info', 1, 0, 0, '', '', '', 'avail', '', '_bx_orgs_form_profile_input_delete_confirm_error', '', '', 1, 0),
+('bx_organization', 'bx_organizations', 'do_submit', '_sys_form_account_input_submit', '', 0, 'submit', '_bx_orgs_form_profile_input_sys_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_organization', 'bx_organizations', 'org_desc', '', '', 0, 'textarea', '_bx_orgs_form_profile_input_sys_org_desc', '_bx_orgs_form_profile_input_org_desc', '', 0, 0, 1, '', '', '', '', '', '', 'XssHtml', '', 1, 1),
+('bx_organization', 'bx_organizations', 'org_cat', '', '#!bx_organizations_cats', 0, 'select', '_bx_orgs_form_profile_input_sys_org_cat', '_bx_orgs_form_profile_input_org_cat', '', 1, 0, 0, '', '', '', 'avail', '', '_bx_orgs_form_profile_input_org_cat_err', 'Xss', '', 1, 1),
+('bx_organization', 'bx_organizations', 'multicat', '', '', 0, 'custom', '_bx_orgs_form_entry_input_sys_multicat', '_bx_orgs_form_entry_input_multicat', '', 1, 0, 0, '', '', '', 'avail', '', '_bx_orgs_form_entry_input_multicat_err', 'Xss', '', 1, 0),
+('bx_organization', 'bx_organizations', 'org_name', '', '', 0, 'text', '_bx_orgs_form_profile_input_sys_org_name', '_bx_orgs_form_profile_input_org_name', '', 1, 0, 0, '', '', '', 'ProfileName', '', '_bx_orgs_form_profile_input_org_name_err', 'Xss', '', 1, 0),
+('bx_organization', 'bx_organizations', 'initial_members', '', '', 0, 'custom', '_bx_orgs_form_profile_input_sys_initial_members', '_bx_orgs_form_profile_input_initial_members', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 1),
+('bx_organization', 'bx_organizations', 'join_confirmation', 1, '', 1, 'switcher', '_bx_orgs_form_profile_input_sys_join_confirm', '_bx_orgs_form_profile_input_join_confirm', '', 0, 0, 0, '', '', '', '', '', '', 'Xss', '', 1, 0),
+('bx_organization', 'bx_organizations', 'cover', 'a:1:{i:0;s:27:"bx_organizations_cover_crop";}', 'a:1:{s:27:"bx_organizations_cover_crop";s:24:"_sys_uploader_crop_title";}', 0, 'files', '_bx_orgs_form_profile_input_sys_cover', '_bx_orgs_form_profile_input_cover', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_organization', 'bx_organizations', 'picture', 'a:1:{i:0;s:29:"bx_organizations_picture_crop";}', 'a:1:{s:29:"bx_organizations_picture_crop";s:24:"_sys_uploader_crop_title";}', 0, 'files', '_bx_orgs_form_profile_input_sys_picture', '_bx_orgs_form_profile_input_picture', '', 0, 0, 0, '', '', '', '', '', '_bx_orgs_form_profile_input_picture_err', '', '', 1, 0),
+('bx_organization', 'bx_organizations', 'location', '', '', 0, 'location', '_sys_form_input_sys_location', '_sys_form_input_location', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_organization', 'bx_organizations', 'profile_email', '', '', 0, 'text', '_bx_orgs_form_profile_input_sys_profile_email', '_bx_orgs_form_profile_input_profile_email', '', 0, 0, 0, '', '', '', '', '', '', 'Xss', '', 0, 0),
+('bx_organization', 'bx_organizations', 'profile_status', '', '', 0, 'custom', '_bx_orgs_form_profile_input_sys_profile_status', '_bx_orgs_form_profile_input_profile_status', '', 0, 0, 0, '', '', '', '', '', '', 'Xss', '', 0, 0),
+('bx_organization', 'bx_organizations', 'profile_ip', '', '', 0, 'text', '_bx_orgs_form_profile_input_sys_profile_ip', '_bx_orgs_form_profile_input_profile_ip', '', 0, 0, 0, '', '', '', '', '', '', 'Xss', '', 0, 0),
+('bx_organization', 'bx_organizations', 'labels', '', '', 0, 'custom', '_sys_form_input_sys_labels', '_sys_form_input_labels', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_organization', 'bx_organizations', 'added', '', '', 0, 'datetime', '_bx_orgs_form_profile_input_sys_date_added', '_bx_orgs_form_profile_input_date_added', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_organization', 'bx_organizations', 'changed', '', '', 0, 'datetime', '_bx_orgs_form_profile_input_sys_date_changed', '_bx_orgs_form_profile_input_date_changed', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_organization', 'bx_organizations', 'friends_count', '', '', 0, 'text', '_bx_orgs_form_profile_input_sys_friends_count', '_bx_orgs_form_profile_input_friends_count', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_organization', 'bx_organizations', 'followers_count', '', '', 0, 'text', '_bx_orgs_form_profile_input_sys_followers_count', '_bx_orgs_form_profile_input_followers_count', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0);
+
+INSERT INTO `sys_form_display_inputs`(`display_name`, `input_name`, `visible_for_levels`, `active`, `order`) VALUES
+('bx_organization_add', 'initial_members', 2147483647, 1, 1),
+('bx_organization_add', 'picture', 2147483647, 1, 2),
+('bx_organization_add', 'org_name', 2147483647, 1, 3),
+('bx_organization_add', 'org_cat', 2147483647, 1, 4),
+('bx_organization_add', 'org_desc', 2147483647, 1, 5),
+('bx_organization_add', 'location', 2147483647, 1, 6),
+('bx_organization_add', 'join_confirmation', 2147483647, 1, 7),
+('bx_organization_add', 'allow_view_to', 2147483647, 1, 8),
+('bx_organization_add', 'allow_post_to', 2147483647, 1, 9),
+('bx_organization_add', 'allow_contact_to', 2147483647, 1, 10),
+('bx_organization_add', 'do_submit', 2147483647, 1, 11),
+
+('bx_organization_invite', 'initial_members', 2147483647, 1, 1),
+('bx_organization_invite', 'do_submit', 2147483647, 1, 2),
+
+('bx_organization_delete', 'delete_confirm', 2147483647, 1, 1),
+('bx_organization_delete', 'do_submit', 2147483647, 1, 2),
+
+('bx_organization_edit', 'picture', 2147483647, 1, 1),
+('bx_organization_edit', 'org_name', 2147483647, 1, 2),
+('bx_organization_edit', 'org_cat', 2147483647, 1, 3),
+('bx_organization_edit', 'org_desc', 2147483647, 1, 4),
+('bx_organization_edit', 'location', 2147483647, 1, 5),
+('bx_organization_edit', 'join_confirmation', 2147483647, 1, 6),
+('bx_organization_edit', 'allow_view_to', 2147483647, 1, 7),
+('bx_organization_edit', 'allow_post_to', 2147483647, 1, 8),
+('bx_organization_edit', 'allow_contact_to', 2147483647, 1, 9),
+('bx_organization_edit', 'do_submit', 2147483647, 1, 10),
+
+('bx_organization_edit_cover', 'cover', 2147483647, 1, 1),
+('bx_organization_edit_cover', 'do_submit', 2147483647, 1, 2),
+
+('bx_organization_view', 'org_name', 2147483647, 1, 1),
+('bx_organization_view', 'org_cat', 2147483647, 1, 2),
+('bx_organization_view', 'profile_email', 192, 1, 3),
+('bx_organization_view', 'profile_status', 192, 1, 4),
+('bx_organization_view', 'profile_ip', 192, 1, 5),
+('bx_organization_view', 'added', 192, 1, 6),
+('bx_organization_view', 'changed', 192, 1, 7),
+('bx_organization_view', 'friends_count', 2147483647, 1, 8),
+('bx_organization_view', 'followers_count', 2147483647, 1, 9),
+
+('bx_organization_view_full', 'org_name', 2147483647, 1, 1),
+('bx_organization_view_full', 'org_cat', 2147483647, 1, 2),
+('bx_organization_view_full', 'org_desc', 2147483647, 0, 3),
+('bx_organization_view_full', 'profile_email', 192, 1, 4),
+('bx_organization_view_full', 'profile_status', 192, 1, 5);
+
+-- FORMS: Price
+INSERT INTO `sys_objects_form` (`object`, `module`, `title`, `action`, `form_attrs`, `submit_name`, `table`, `key`, `uri`, `uri_title`, `params`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES
+('bx_organizations_price', 'bx_organizations', '_bx_orgs_form_price', '', '', 'do_submit', 'bx_organizations_prices', 'id', '', '', '', 0, 1, 'BxOrgsFormPrice', 'modules/boonex/organizations/classes/BxOrgsFormPrice.php');
+
+INSERT INTO `sys_form_displays` (`display_name`, `module`, `object`, `title`, `view_mode`) VALUES
+('bx_organizations_price_add', 'bx_organizations', 'bx_organizations_price', '_bx_orgs_form_price_display_add', 0),
+('bx_organizations_price_edit', 'bx_organizations', 'bx_organizations_price', '_bx_orgs_form_price_display_edit', 0);
+
+INSERT INTO `sys_form_inputs` (`object`, `module`, `name`, `value`, `values`, `checked`, `type`, `caption_system`, `caption`, `info`, `required`, `collapsed`, `html`, `attrs`, `attrs_tr`, `attrs_wrapper`, `checker_func`, `checker_params`, `checker_error`, `db_pass`, `db_params`, `editable`, `deletable`) VALUES
+('bx_organizations_price', 'bx_organizations', 'id', '', '', 0, 'hidden', '_bx_orgs_form_price_input_sys_id', '', '', 1, 0, 0, '', '', '', '', '', '', 'Int', '', 1, 0),
+('bx_organizations_price', 'bx_organizations', 'role_id', '', '', 0, 'hidden', '_bx_orgs_form_price_input_sys_role_id', '', '', 1, 0, 0, '', '', '', '', '', '', 'Int', '', 1, 0),
+('bx_organizations_price', 'bx_organizations', 'name', '', '', 0, 'text', '_bx_orgs_form_price_input_sys_name', '_bx_orgs_form_price_input_name', '_bx_orgs_form_price_input_inf_name', 1, 0, 0, '', '', '', 'Avail', '', '_bx_orgs_form_price_input_err_name', 'Xss', '', 1, 0),
+('bx_organizations_price', 'bx_organizations', 'period', '', '', 0, 'text', '_bx_orgs_form_price_input_sys_period', '_bx_orgs_form_price_input_period', '_bx_orgs_form_price_input_inf_period', 1, 0, 0, '', '', '', '', '', '', 'Int', '', 1, 0),
+('bx_organizations_price', 'bx_organizations', 'period_unit', '', '#!bx_organizations_period_units', 0, 'select', '_bx_orgs_form_price_input_sys_period_unit', '_bx_orgs_form_price_input_period_unit', '_bx_orgs_form_price_input_inf_period_unit', 1, 0, 0, '', '', '', '', '', '', 'Xss', '', 1, 0),
+('bx_organizations_price', 'bx_organizations', 'price', '', '', 0, 'price', '_bx_orgs_form_price_input_sys_price', '_bx_orgs_form_price_input_price', '_bx_orgs_form_price_input_inf_price', 1, 0, 0, '', '', '', '', '', '', 'Float', '', 1, 0),
+('bx_organizations_price', 'bx_organizations', 'controls', '', 'do_submit,do_cancel', 0, 'input_set', '', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_organizations_price', 'bx_organizations', 'do_submit', '_bx_orgs_form_price_input_do_submit', '', 0, 'submit', '_bx_orgs_form_price_input_sys_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_organizations_price', 'bx_organizations', 'do_cancel', '_bx_orgs_form_price_input_do_cancel', '', 0, 'button', '_bx_orgs_form_price_input_sys_do_cancel', '', '', 0, 0, 0, 'a:2:{s:7:"onclick";s:45:"$(''.bx-popup-applied:visible'').dolPopupHide()";s:5:"class";s:22:"bx-def-margin-sec-left";}', '', '', '', '', '', '', '', 1, 0);
+
+INSERT INTO `sys_form_display_inputs` (`display_name`, `input_name`, `visible_for_levels`, `active`, `order`) VALUES
+('bx_organizations_price_add', 'id', 2147483647, 0, 1),
+('bx_organizations_price_add', 'role_id', 2147483647, 1, 2),
+('bx_organizations_price_add', 'name', 2147483647, 1, 3),
+('bx_organizations_price_add', 'price', 2147483647, 1, 4),
+('bx_organizations_price_add', 'period', 2147483647, 1, 5),
+('bx_organizations_price_add', 'period_unit', 2147483647, 1, 6),
+('bx_organizations_price_add', 'controls', 2147483647, 1, 7),
+('bx_organizations_price_add', 'do_submit', 2147483647, 1, 8),
+('bx_organizations_price_add', 'do_cancel', 2147483647, 1, 9),
+
+('bx_organizations_price_edit', 'id', 2147483647, 1, 1),
+('bx_organizations_price_edit', 'role_id', 2147483647, 1, 2),
+('bx_organizations_price_edit', 'name', 2147483647, 1, 3),
+('bx_organizations_price_edit', 'price', 2147483647, 1, 4),
+('bx_organizations_price_edit', 'period', 2147483647, 1, 5),
+('bx_organizations_price_edit', 'period_unit', 2147483647, 1, 6),
+('bx_organizations_price_edit', 'controls', 2147483647, 1, 7),
+('bx_organizations_price_edit', 'do_submit', 2147483647, 1, 8),
+('bx_organizations_price_edit', 'do_cancel', 2147483647, 1, 9);
+
+-- PRE-VALUES
+INSERT INTO `sys_form_pre_lists`(`key`, `title`, `module`, `use_for_sets`) VALUES
+('bx_organizations_cats', '_bx_orgs_pre_lists_cats', 'bx_organizations', '0');
+
+INSERT INTO `sys_form_pre_values`(`Key`, `Value`, `Order`, `LKey`, `LKey2`) VALUES
+('bx_organizations_cats', '', 0, '_sys_please_select', ''),
+('bx_organizations_cats', '1', 1, '_bx_orgs_cat_Agriculture', ''),
+('bx_organizations_cats', '2', 2, '_bx_orgs_cat_Financial', ''),
+('bx_organizations_cats', '3', 3, '_bx_orgs_cat_Biotech', ''),
+('bx_organizations_cats', '4', 4, '_bx_orgs_cat_Cause', ''),
+('bx_organizations_cats', '5', 5, '_bx_orgs_cat_Chemical', ''),
+('bx_organizations_cats', '6', 6, '_bx_orgs_cat_Religious', ''),
+('bx_organizations_cats', '7', 7, '_bx_orgs_cat_Community', ''),
+('bx_organizations_cats', '8', 8, '_bx_orgs_cat_Company', ''),
+('bx_organizations_cats', '9', 9, '_bx_orgs_cat_Entertainment', ''),
+('bx_organizations_cats', '10', 10, '_bx_orgs_cat_Technology', ''),
+('bx_organizations_cats', '11', 11, '_bx_orgs_cat_Consulting', ''),
+('bx_organizations_cats', '12', 12, '_bx_orgs_cat_Education', ''),
+('bx_organizations_cats', '13', 13, '_bx_orgs_cat_Energy', ''),
+('bx_organizations_cats', '14', 14, '_bx_orgs_cat_Engineering', ''),
+('bx_organizations_cats', '15', 15, '_bx_orgs_cat_Food', ''),
+('bx_organizations_cats', '16', 16, '_bx_orgs_cat_Government', ''),
+('bx_organizations_cats', '17', 17, '_bx_orgs_cat_Health', ''),
+('bx_organizations_cats', '18', 18, '_bx_orgs_cat_Medical', ''),
+('bx_organizations_cats', '19', 19, '_bx_orgs_cat_Industrial', ''),
+('bx_organizations_cats', '20', 20, '_bx_orgs_cat_Insurance', ''),
+('bx_organizations_cats', '21', 21, '_bx_orgs_cat_Internet', ''),
+('bx_organizations_cats', '22', 22, '_bx_orgs_cat_Software', ''),
+('bx_organizations_cats', '23', 23, '_bx_orgs_cat_Legal', ''),
+('bx_organizations_cats', '24', 24, '_bx_orgs_cat_Media', ''),
+('bx_organizations_cats', '25', 25, '_bx_orgs_cat_School', ''),
+('bx_organizations_cats', '26', 26, '_bx_orgs_cat_NGO', ''),
+('bx_organizations_cats', '27', 27, '_bx_orgs_cat_NPO', ''),
+('bx_organizations_cats', '28', 28, '_bx_orgs_cat_Political', ''),
+('bx_organizations_cats', '29', 29, '_bx_orgs_cat_Retail', ''),
+('bx_organizations_cats', '30', 30, '_bx_orgs_cat_Small_Business', ''),
+('bx_organizations_cats', '31', 31, '_bx_orgs_cat_Telecommunication', ''),
+('bx_organizations_cats', '32', 32, '_bx_orgs_cat_Transport', ''),
+('bx_organizations_cats', '33', 33, '_bx_orgs_cat_Travel', ''),
+('bx_organizations_cats', '34', 34, '_bx_orgs_cat_University', ''),
+('bx_organizations_cats', '35', 35, '_bx_orgs_cat_Other', '');
+
+INSERT INTO `sys_form_pre_lists`(`key`, `title`, `module`, `use_for_sets`) VALUES
+('bx_organizations_roles', '_bx_orgs_pre_lists_roles', 'bx_organizations', '1');
+
+INSERT INTO `sys_form_pre_values`(`Key`, `Value`, `Order`, `LKey`, `LKey2`) VALUES
+('bx_organizations_roles', '0', 1, '_bx_orgs_role_regular', ''),
+('bx_organizations_roles', '1', 2, '_bx_orgs_role_administrator', ''),
+('bx_organizations_roles', '2', 3, '_bx_orgs_role_moderator', '');
+
+INSERT INTO `sys_form_pre_lists`(`key`, `title`, `module`, `use_for_sets`) VALUES
+('bx_organizations_period_units', '_bx_orgs_pre_lists_period_units', 'bx_organizations', '0');
+
+INSERT INTO `sys_form_pre_values`(`Key`, `Value`, `Order`, `LKey`, `LKey2`) VALUES
+('bx_organizations_period_units', '', 0, '_sys_please_select', ''),
+('bx_organizations_period_units', 'day', 1, '_bx_orgs_period_unit_day', ''),
+('bx_organizations_period_units', 'week', 2, '_bx_orgs_period_unit_week', ''),
+('bx_organizations_period_units', 'month', 3, '_bx_orgs_period_unit_month', ''),
+('bx_organizations_period_units', 'year', 4, '_bx_orgs_period_unit_year', '');
+
+-- COMMENTS
+INSERT INTO `sys_objects_cmts` (`Name`, `Module`, `Table`, `CharsPostMin`, `CharsPostMax`, `CharsDisplayMax`, `Html`, `PerView`, `PerViewReplies`, `BrowseType`, `IsBrowseSwitch`, `PostFormPosition`, `NumberOfLevels`, `IsDisplaySwitch`, `IsRatable`, `ViewingThreshold`, `IsOn`, `RootStylePrefix`, `BaseUrl`, `ObjectVote`, `TriggerTable`, `TriggerFieldId`, `TriggerFieldAuthor`, `TriggerFieldTitle`, `TriggerFieldComments`, `ClassName`, `ClassFile`) VALUES
+('bx_organizations', 'bx_organizations', 'bx_organizations_cmts', 1, 5000, 1000, 3, 5, 3, 'tail', 1, 'bottom', 1, 1, 1, -3, 1, 'cmt', 'page.php?i=view-organization-profile&id={object_id}', '', 'bx_organizations_data', 'id', 'author', 'org_name', 'comments', 'BxOrgsCmts', 'modules/boonex/organizations/classes/BxOrgsCmts.php'),
+('bx_organizations_notes', 'bx_organizations', 'bx_organizations_cmts_notes', 1, 5000, 1000, 0, 5, 3, 'tail', 1, 'bottom', 1, 1, 1, -3, 1, 'cmt', 'page.php?i=view-post&id={object_id}', '', 'bx_organizations_data', 'id', 'author', 'org_name', '', 'BxTemplCmtsNotes', '');
+
+
+-- VIEWS
+INSERT INTO `sys_objects_view` (`name`, `module`, `table_track`, `period`, `is_on`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_count`, `class_name`, `class_file`) VALUES 
+('bx_organizations', 'bx_organizations', 'bx_organizations_views_track', '86400', '1', 'bx_organizations_data', 'id', 'author', 'views', '', '');
+
+
+-- VOTES
+INSERT INTO `sys_objects_vote` (`Name`, `TableMain`, `TableTrack`, `PostTimeout`, `MinValue`, `MaxValue`, `IsUndo`, `IsOn`, `TriggerTable`, `TriggerFieldId`, `TriggerFieldAuthor`, `TriggerFieldRate`, `TriggerFieldRateCount`, `ClassName`, `ClassFile`) VALUES 
+('bx_organizations', 'bx_organizations_votes', 'bx_organizations_votes_track', '604800', '1', '1', '0', '1', 'bx_organizations_data', 'id', '', 'rate', 'votes', 'BxOrgsVote', 'modules/boonex/organizations/classes/BxOrgsVote.php');
+
+
+-- SCORES
+INSERT INTO `sys_objects_score` (`name`, `module`, `table_main`, `table_track`, `post_timeout`, `is_on`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_score`, `trigger_field_cup`, `trigger_field_cdown`, `class_name`, `class_file`) VALUES 
+('bx_organizations', 'bx_organizations', 'bx_organizations_scores', 'bx_organizations_scores_track', '604800', '0', 'bx_organizations_data', 'id', 'author', 'score', 'sc_up', 'sc_down', '', '');
+
+
+-- FAFORITES
+INSERT INTO `sys_objects_favorite` (`name`, `table_track`, `table_lists`, `is_on`, `is_undo`, `is_public`, `base_url`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_count`, `class_name`, `class_file`) VALUES 
+('bx_organizations', 'bx_organizations_favorites_track', 'bx_organizations_favorites_lists', '1', '1', '0', 'page.php?i=view-organization-profile&id={object_id}', 'bx_organizations_data', 'id', 'author', 'favorites', 'BxOrgsFavorite', 'modules/boonex/organizations/classes/BxOrgsFavorite.php');
+
+
+-- FEATURED
+INSERT INTO `sys_objects_feature` (`name`, `module`, `is_on`, `is_undo`, `base_url`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_flag`, `class_name`, `class_file`) VALUES 
+('bx_organizations', 'bx_organizations', '1', '1', 'page.php?i=view-organization-profile&id={object_id}', 'bx_organizations_data', 'id', 'author', 'featured', '', '');
+
+
+-- REPORTS
+INSERT INTO `sys_objects_report` (`name`, `module`, `table_main`, `table_track`, `is_on`, `base_url`, `object_comment`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_count`, `class_name`, `class_file`) VALUES 
+('bx_organizations', 'bx_organizations', 'bx_organizations_reports', 'bx_organizations_reports_track', '1', 'page.php?i=view-organization-profile&id={object_id}', 'bx_organizations_notes', 'bx_organizations_data', 'id', 'author', 'reports', 'BxOrgsReport', 'modules/boonex/organizations/classes/BxOrgsReport.php');
+
+
+-- CONTENT INFO
+INSERT INTO `sys_objects_content_info` (`name`, `title`, `alert_unit`, `alert_action_add`, `alert_action_update`, `alert_action_delete`, `class_name`, `class_file`) VALUES
+('bx_organizations', '_bx_orgs', 'bx_organizations', 'added', 'edited', 'deleted', '', ''),
+('bx_organizations_cmts', '_bx_orgs_cmts', 'bx_organizations', 'commentPost', 'commentUpdated', 'commentRemoved', 'BxDolContentInfoCmts', '');
+
+INSERT INTO `sys_content_info_grids` (`object`, `grid_object`, `grid_field_id`, `condition`, `selection`) VALUES
+('bx_organizations', 'bx_organizations_administration', 'td`.`id', '', ''),
+('bx_organizations', 'bx_organizations_common', 'td`.`id', '', '');
+
+
+-- SEARCH EXTENDED
+INSERT INTO `sys_objects_search_extended` (`object`, `object_content_info`, `module`, `title`, `active`, `class_name`, `class_file`) VALUES
+('bx_organizations', 'bx_organizations', 'bx_organizations', '_bx_orgs_search_extended', 1, '', ''),
+('bx_organizations_cmts', 'bx_organizations_cmts', 'bx_organizations', '_bx_orgs_search_extended_cmts', 1, 'BxTemplSearchExtendedCmts', '');
+
+
+-- STUDIO PAGE & WIDGET
+INSERT INTO `sys_std_pages`(`index`, `name`, `header`, `caption`, `icon`) VALUES
+(3, 'bx_organizations', '_bx_orgs', '_bx_orgs', 'bx_organizations@modules/boonex/organizations/|std-icon.svg');
+SET @iPageId = LAST_INSERT_ID();
+
+SET @iParentPageId = (SELECT `id` FROM `sys_std_pages` WHERE `name` = 'home');
+SET @iParentPageOrder = (SELECT MAX(`order`) FROM `sys_std_pages_widgets` WHERE `page_id` = @iParentPageId);
+INSERT INTO `sys_std_widgets` (`page_id`, `module`, `type`, `url`, `click`, `icon`, `caption`, `cnt_notices`, `cnt_actions`) VALUES
+(@iPageId, 'bx_organizations', 'users', '{url_studio}module.php?name=bx_organizations', '', 'bx_organizations@modules/boonex/organizations/|std-icon.svg', '_bx_orgs', '', '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));

+ 16 - 0
modules/boonex/organizations/updates/13.0.3_13.0.4/source/js/invite_popup.js

@@ -0,0 +1,16 @@
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Organizations Organizations
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+function BxOrgsInvitePopup(oOptions) {
+    BxBaseModGroupsInvitePopup.call(this, oOptions);
+}
+
+BxOrgsInvitePopup.prototype = Object.create(BxBaseModGroupsInvitePopup.prototype);
+BxOrgsInvitePopup.prototype.constructor = BxOrgsInvitePopup;

+ 1 - 0
modules/boonex/organizations/updates/13.0.3_13.0.4/source/template/popup_invite.html

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

+ 51 - 0
modules/boonex/payment/updates/13.0.3_13.0.4/install/config.php

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

+ 13 - 0
modules/boonex/payment/updates/13.0.3_13.0.4/install/installer.php

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

+ 4 - 0
modules/boonex/payment/updates/13.0.3_13.0.4/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_payment_cdt_err_wrong_balance"><![CDATA[Insufficient funds to write off.]]></string_add>
+</resources>

+ 338 - 0
modules/boonex/payment/updates/13.0.3_13.0.4/source/classes/BxPaymentConfig.php

@@ -0,0 +1,338 @@
+<?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_AUTHORIZE' => $sBaseUrl . 'authorize_checkout/',
+            '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/',
+            'URL_CHECKOUT_OFFLINE' => 'page.php?i=payment-checkout-offline',
+
+            'KEY_ARRAY_PRICE_SINGLE' => 'price_single',
+            'KEY_ARRAY_PRICE_RECURRING' => 'price_recurring',
+            'KEY_ARRAY_TRIAL_RECURRING' => 'trial_recurring',
+
+            // some params
+            'PARAM_CMSN_INVOICE_ISSUE_DAY' => 'bx_payment_inv_issue_day', //some day of month
+            'PARAM_CMSN_INVOICE_LIFETIME' => 'bx_payment_inv_lifetime', //in days
+            'PARAM_CMSN_INVOICE_EXPIRATION_NOTIFY' => 'bx_payment_inv_expiraction_notify', //in days, before expiration date
+
+            // objects
+            'OBJECT_FORM_PRELISTS_CURRENCIES' => 'bx_payment_currencies',
+            'OBJECT_PP_OFFLINE' => 'offline', //Offline payment provider
+            '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 round((float)$fPrice, 2);
+    }
+
+    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);
+    }
+
+    public function descriptorsA2S($a) 
+    {
+    	return implode($this->getDivider('DIVIDER_DESCRIPTORS'), $a);
+    }
+
+    /**
+     * 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;
+        });
+    }
+}
+
+/** @} */

+ 140 - 0
modules/boonex/payment/updates/13.0.3_13.0.4/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', ['empty' => '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 = BxTemplFunctions::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 = BxTemplFunctions::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;
+    }
+}
+
+/** @} */

+ 1955 - 0
modules/boonex/payment/updates/13.0.3_13.0.4/source/classes/BxPaymentModule.php

@@ -0,0 +1,1955 @@
+<?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'))
+        );
+    }
+
+    public function serviceGetBlockCheckoutOffline()
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $oBuyer = BxDolProfile::getInstance();
+        if(!$oBuyer)
+            return MsgBox(_t('_bx_payment_err_required_login'));
+        
+        $iSeller = (int)bx_get('seller');
+        $oSeller = BxDolProfile::getInstance($iSeller);
+        if(!$oSeller)
+            return MsgBox(_t('_bx_payment_err_unknown_vendor'));
+
+        $aData = array(
+            'seller' => $iSeller,
+            'currency' => array(
+                'code' => bx_process_input(bx_get('currency_code')),
+                'sign' => bx_process_input(bx_get('currency_sign')),
+            ),
+            'amount' => (float)bx_get('amount'),
+            'return_url' => bx_process_input(bx_get('return_url')),
+        );
+
+        if(empty($aData['currency']['code']))
+            $aData['currency']['code'] = $this->_oConfig->getDefaultCurrencyCode();
+
+        if(empty($aData['currency']['sign']))
+            $aData['currency']['sign'] = $this->_oConfig->getDefaultCurrencySign();
+
+        $sItems = '';
+        $iItemsCount = (int)bx_get('items_count');
+        for($i = 0; $i < $iItemsCount; $i++) {
+            $aItem = array(
+                'title' => bx_process_input(bx_get('item_title_' . $i)),
+                'quantity' => (int)bx_get('item_quantity_' . $i)
+            );
+
+            $sItems .= _t('_bx_payment_txt_checkout_item', $aItem['title'], $aItem['quantity']);
+            $aData['items'][] = $aItem;
+        }
+
+        $aTemplate = BxDolEmailTemplates::getInstance()->parseTemplate($this->_oConfig->getPrefix('general') . 'checkout_offline', array(
+            'profile_name' => $oBuyer->getDisplayName(),
+            'profile_link' => $oBuyer->getUrl(),
+            'items' => $sItems,
+            'amount' => $aData['currency']['sign'] . sprintf("%.2f", (float)($aData['amount'])),
+            'date' => bx_time_js(time(), BX_FORMAT_DATE, true),
+            'pending_orders_link' => $this->getObjectOrders()->serviceGetPendingOrdersUrl()
+        ), 0, $iSeller);
+
+        $sEmail = '';
+        $oProvider = $this->getObjectProvider($CNF['OBJECT_PP_OFFLINE'], $iSeller);
+        if($oProvider !== false && $oProvider->isActive())
+            $sEmail = $oProvider->getOption('checkout_email');
+
+        if(empty($sEmail))
+            $sEmail = $oBuyer->getAccountObject()->getEmail();
+
+        if(!sendMail($sEmail, $aTemplate['Subject'], $aTemplate['Body'], 0, array(), BX_EMAIL_SYSTEM))
+            return MsgBox(_t('_bx_payment_err_cannot_perform'));
+
+        return $this->_oTemplate->displayBlockCheckoutOffline($oBuyer, $oSeller, $aData);
+    }
+
+    /**
+     * 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_add'], 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 actionAuthorizeCheckout($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)
+            return $this->_oTemplate->displayPageCodeError($this->_sLangsPrefix . 'err_wrong_data');
+
+        $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->serviceAuthorizeCheckout($sType, $iSellerId, $sProvider, $aItems);
+        if(is_string($mixedResult))
+            return $this->_oTemplate->displayPageCodeError($mixedResult);
+
+        if(is_array($mixedResult) && !empty($mixedResult['redirect'])) {
+            header('Location: ' . $mixedResult['redirect']);
+            exit;
+        }
+
+        return $this->_oTemplate->displayPageCodeResponse($this->_sLangsPrefix . 'msg_successfully_performed');
+    }
+
+    public function actionCaptureAuthorizedCheckout($sType)
+    {
+        $iProfileId = bx_get_logged_profile_id();
+    	if(!$iProfileId)
+            return $this->_oTemplate->displayPageCodeError($this->_sLangsPrefix . 'err_required_login');
+
+        $sOrderAuth = '';
+        if(($sOrderAuth = bx_get('order')) !== false) 
+            $sOrderAuth = bx_process_input($sOrderAuth);
+
+        if(empty($sOrderAuth))
+            return $this->_oTemplate->displayPageCodeError($this->_sLangsPrefix . 'err_empty_order');
+
+        $aPending = $this->_oDb->getOrderPending(['type' => 'order', 'order' => $sOrderAuth]);
+        if(empty($aPending) || !is_array($aPending))
+            return $this->_oTemplate->displayPageCodeError($this->_sLangsPrefix . 'err_empty_order');
+
+        if((int)$aPending['seller_id'] != $iProfileId)
+            return $this->_oTemplate->displayPageCodeError($this->_sLangsPrefix . 'err_wrong_vendor');
+
+        $mixedResult = $this->serviceCaptureAuthorizedCheckout($sType, $sOrderAuth);
+        if(is_string($mixedResult))
+            return $this->_oTemplate->displayPageCodeError($mixedResult);
+
+        if(!empty($mixedResult['redirect'])) {
+            header('Location: ' . base64_decode(urldecode($mixedResult['redirect'])));
+            exit;
+        }
+
+        return $this->_oTemplate->displayPageCodeResponse($mixedResult['message']);
+    }
+
+    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;
+    }
+
+    public function actionInitializeCheckoutJson($sType)
+    {
+    	if(!$this->isLogged())
+            return echoJson(['code' => 1, 'message' => _t($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 === false)
+                return echoJson(['code' => 2, 'message' => _t($this->_sLangsPrefix . 'err_cannot_perform')]);
+            if(is_string($mixedResult))
+                return echoJson(['code' => 3, 'message' => $mixedResult]);
+            else if(is_array($mixedResult))
+                return echoJson($mixedResult);
+        }
+
+        return echoJson(['code' => 0, 'redirect' => $this->_oConfig->getUrl('URL_CART')]);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_payment Payment
+     * @subsection bx_payment-purchase_processing Purchase Processing
+     * @subsubsection bx_payment-authorize_checkout authorize_checkout
+     * 
+     * @code bx_srv('bx_payment', 'authorize_checkout', [...]); @endcode
+     * 
+     * Authorize order for future checkout.
+     * 
+     * @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.
+     * @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::serviceAuthorizeCheckout
+     */
+    /** 
+     * @ref bx_payment-authorize_checkout "authorize_checkout"
+     */
+    public function serviceAuthorizeCheckout($sType, $iSellerId, $sProvider, $aItems = [], $sRedirect = '')
+    {
+        $bTypeSingle = $sType == BX_PAYMENT_TYPE_SINGLE;
+        $bTypeRecurring = $sType == BX_PAYMENT_TYPE_RECURRING;
+
+        if(!is_array($aItems))
+            $aItems = [$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';
+
+        $this->alert('before_authorize', 0, $this->_iUserId, array(
+            'client_id' => $this->_iUserId,
+            'seller_id' => $iSellerId, 
+            'type' => &$sType,
+            'provider' => &$sProvider,
+            'cart_info' => &$aInfo,
+        ));
+
+        $iPendingId = $this->_oDb->insertOrderPending($this->_iUserId, $sType, $sProvider, $aInfo);
+        if(empty($iPendingId))
+            return $this->_sLangsPrefix . 'err_access_db';
+
+        return $oProvider->authorizeCheckout($iPendingId, $aInfo, $sRedirect);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_payment Payment
+     * @subsection bx_payment-purchase_processing Purchase Processing
+     * @subsubsection bx_payment-capture_authorized_checkout capture_authorized_checkout
+     * 
+     * @code bx_srv('bx_payment', 'capture_authorized_checkout', [...]); @endcode
+     * 
+     * Capture funds for previously authorized order.
+     * 
+     * @param $sType string value with payment type (single or recurring). 
+     * @param $sOrderAuth string value with order's authorization ID. 
+     * @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::serviceCaptureAuthorizedCheckout
+     */
+    /** 
+     * @ref bx_payment-capture_authorized_checkout "capture_authorized_checkout"
+     */
+    public function serviceCaptureAuthorizedCheckout($sType, $sOrderAuth, $sRedirect = '')
+    {
+        $aPending = $this->_oDb->getOrderPending(['type' => 'order', 'order' => $sOrderAuth]);
+        if(empty($aPending) || !is_array($aPending))
+            return $this->_sLangsPrefix . 'err_empty_order';
+
+        if((int)$aPending['processed'] != 0)
+            return $this->_sLangsPrefix . 'err_already_processed';
+
+        $iClientId = (int)$aPending['client_id'];
+        $iSellerId = (int)$aPending['seller_id'];
+        $sProvider = $aPending['provider'];
+
+        $oProvider = $this->getObjectProvider($sProvider, $iSellerId);
+        if($oProvider === false || !$oProvider->isActive())
+            return $this->_sLangsPrefix . 'err_incorrect_provider';
+
+        $aInfo = $this->getObjectCart()->getInfo($sType, $iClientId, $iSellerId, $aPending['items']);
+        if(empty($aInfo) || $aInfo['vendor_id'] == BX_PAYMENT_EMPTY_ID || empty($aInfo['items']))
+            return $this->_sLangsPrefix . 'err_empty_order';
+
+        $this->alert('before_capture_authorized', 0, $iClientId, array(
+            'order_auth' => $sOrderAuth,
+            'client_id' => $iClientId,
+            'seller_id' => $iSellerId, 
+            'type' => &$sType,
+            'provider' => &$sProvider,
+            'cart_info' => &$aInfo,
+        ));
+
+        $aResult = $oProvider->captureAuthorizedCheckout($sOrderAuth, $aPending, $aInfo, $sRedirect);
+        if((int)$aResult['code'] != BX_PAYMENT_RESULT_SUCCESS) 
+            return $aResult['message'];
+
+        //--- Get updated pending order
+        $aPending = $this->_oDb->getOrderPending(['type' => 'id', 'id' => $aResult['pending_id']]);
+
+        //--- Register payment for purchased items in associated modules 
+        if(isset($aResult['paid']) && $aResult['paid'])
+            $this->registerPayment($aPending);
+
+        $this->alert('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(empty($aResult['redirect']) && $oProvider->needRedirect())
+            $aResult['redirect'] = $oProvider->getReturnUrl();
+
+        return $aResult;
+    }
+
+    /**
+     * @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);
+            }
+        }
+
+        $this->alert('before_pending', 0, bx_get_logged_profile_id(), array(
+            'client_id' => $this->_iUserId,
+            'seller_id' => $iSellerId, 
+            '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(['type' => 'id', 'id' => (int)$aResult['pending_id']]);
+        $bTypeRecurring = $aPending['type'] == BX_PAYMENT_TYPE_RECURRING;
+        $bAuthorized = isset($aResult['authorized']) && $aResult['authorized'];
+        $bPaid = isset($aResult['paid']) && $aResult['paid'];
+        $bTrial = isset($aResult['trial']) && $aResult['trial'];
+
+        //--- Register subscription
+        if($bTypeRecurring) {
+            $sStatus = BX_PAYMENT_SBS_STATUS_UNPAID;
+            if($bPaid)
+                $sStatus = BX_PAYMENT_SBS_STATUS_ACTIVE;
+            else if($bTrial)
+                $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'] : '');
+
+        //--- Authorize order for selected items in associated modules 
+        if($bAuthorized)
+            $this->authorizePayment($aPending);
+
+        //--- Register payment for purchased items in associated modules 
+        if($bPaid || ($bTypeRecurring && $bTrial))
+            $this->registerPayment($aPending);
+
+        //--- Get updated pending order
+        $aPending = $this->_oDb->getOrderPending(['type' => 'id', 'id' => $aPending['id']]);
+
+        $this->alert('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)
+    {
+        //--- Cancel subscriptions
+        $aSubscriptions = $this->_oDb->getSubscription(['type' => 'mixed_ext', 'conditions' => ['client_id' => $iProfileId]]);
+        if(!empty($aSubscriptions) && is_array($aSubscriptions)) 
+            foreach($aSubscriptions as $aSubscription)
+                $this->getObjectSubscriptions()->cancel($aSubscription['pending_id']);
+
+        //--- Clean DB
+        $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 authorizePayment($mixedPending)
+    {
+        $aPending = is_array($mixedPending) ? $mixedPending : $this->_oDb->getOrderPending(['type' => 'id', 'id' => (int)$mixedPending]);
+    	if(empty($aPending) || !is_array($aPending))
+            return false;
+
+        $sType = $aPending['type'];
+        $bTypeSingle = $sType == BX_PAYMENT_TYPE_SINGLE;
+
+        if((int)$aPending['authorized'] == 1)
+            return true;
+
+        $iClientId = (int)$aPending['client_id'];
+
+        $aCart = array();
+        if($bTypeSingle)
+            $aCart = $this->_oDb->getCartContent($iClientId);
+        
+        $bResult = false;
+        $aItems = $this->_oConfig->descriptorsM2A($aPending['items']);
+        foreach($aItems as $aItem) {
+            $sItem = $this->_oConfig->descriptorA2S([$aItem['vendor_id'], $aItem['module_id'], $aItem['item_id']]);
+            
+            $sMethod = $bTypeSingle ? 'callAuthorizeCartItem' : 'callAuthorizeSubscriptionItem';
+            $aItemInfo = $this->$sMethod((int)$aItem['module_id'], [$aPending['client_id'], $aPending['seller_id'], $aItem['item_id'], $aItem['item_count'], $aPending['order']]);
+            if(empty($aItemInfo) || !is_array($aItemInfo))
+                continue;
+
+            if($bTypeSingle)
+            	$aCart['items'] = trim(preg_replace("'" . $this->_oConfig->descriptorA2S($aItem) . ":?'", "", $aCart['items']), ":");
+
+            $bResult = true;
+        }
+
+        if($bResult) {
+            $this->_oDb->updateOrderPending($aPending['id'], ['authorized' => 1]);
+
+            $this->onPaymentAuthorize($aPending);
+        }
+
+        return $bResult;
+    }
+    
+    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') == $this->_oConfig->getInvoiceIssueDay())
+            $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 * $this->_oConfig->getInvoiceLifetime();
+
+        $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->alert('calculate_commission', 0, 0, array(
+                'vendor' => $aVendor,
+                'commissions' => $aCommissions,
+                'override_result' => &$fCommission,
+            ));
+
+            $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' => $this->_oConfig->getInvoiceExpirationNotify(),
+                    '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(($mixedResult = $oProvider->makePayment($aPending)) !== true) {
+                $this->log($aSubscription, 'Time Tracker', 'Payment cannot be processed.' . (!empty($mixedResult['message']) ? ' ' . $mixedResult['message'] : ''));
+                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 = [])
+    {
+        $this->alert('before_register_payment', 0, $aPending['client_id'], array('pending' => $aPending));
+    }
+
+    public function onPaymentAuthorize($aPending, $aResult = [])
+    {
+        $this->alert('authorize_payment', 0, $aPending['client_id'], ['pending' => $aPending]);
+    }
+
+    public function onPaymentRegister($aPending, $aResult = [])
+    {
+        $bTypeSingle = $aPending['type'] == BX_PAYMENT_TYPE_SINGLE;
+
+        if($bTypeSingle) {
+            $aItems = $this->_oConfig->descriptorsM2A($aPending['items']);
+            foreach($aItems as $aItem)
+                $this->isAllowedPurchase(['module_id' => $aItem['module_id'], 'item_id' => $aItem['item_id']], true);
+        }
+
+        $this->alert('register_payment', 0, $aPending['client_id'], ['pending' => $aPending]);
+    }
+
+    public function onPaymentRefund($aPending, $aResult = [])
+    {
+        $this->alert('refund_payment', 0, $aPending['client_id'], ['pending' => $aPending]);
+    }
+
+    public function onSubscriptionCreate($aPending, $aSubscription, $aResult = [])
+    {
+        $aItems = $this->_oConfig->descriptorsM2A($aPending['items']);
+        $this->isAllowedPurchase(['module_id' => $aItems[0]['module_id'], 'item_id' => $aItems[0]['item_id']], true);
+
+        $this->alert('create_subscription', 0, $aPending['client_id'], [
+            'pending' => $aPending,
+            'subscription' => $aSubscription
+        ]);
+    }
+
+    public function onSubscriptionProlong($aPending, $aSubscription, $aResult = [])
+    {
+        $this->alert('prolong_subscription', 0, $aPending['client_id'], [
+            'pending' => $aPending,
+            'subscription' => $aSubscription
+        ]);
+    }
+
+    public function onSubscriptionOverdue($aPending, $aSubscription, $aResult = [])
+    {
+        $this->alert('overdue_subscription', 0, $aPending['client_id'], [
+            'pending' => $aPending,
+            'subscription' => $aSubscription
+        ]);
+    }
+
+    public function onSubscriptionCancel($aPending, $aSubscription, $aResult = [])
+    {
+        $this->alert('cancel_subscription', 0, $aPending['client_id'], [
+            '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();
+
+        $this->alert('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;
+
+        $this->alert('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;
+    }
+    
+}
+
+/** @} */

+ 225 - 0
modules/boonex/payment/updates/13.0.3_13.0.4/source/classes/BxPaymentProviderCredits.php

@@ -0,0 +1,225 @@
+<?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
+ *
+ * @{
+ */
+
+/**
+ * Credits payment provider can be used when 
+ * Credits module is installed and active.
+ */
+
+class BxPaymentProviderCredits extends BxBaseModPaymentProvider implements iBxBaseModPaymentProvider
+{
+    protected $_sModuleCredits;
+
+    function __construct($aConfig)
+    {
+    	$this->MODULE = 'bx_payment';
+
+        parent::__construct($aConfig);
+
+        $this->_sModuleCredits = $this->_oModule->_oConfig->CNF['MODULE_CREDITS'];
+    }
+
+    public function initializeCheckout($iPendingId, $aCartInfo, $sRedirect = '')
+    {
+        if(!BxDolModuleQuery::getInstance()->isEnabledByName($this->_sModuleCredits))
+            return $this->_sLangsPrefix . 'cdt_err_not_available';
+
+        $aPending = $this->_oModule->_oDb->getOrderPending(array('type' => 'id', 'id' => $iPendingId));
+        if(!empty($aPending['order']) || !empty($aPending['error_code']) || !empty($aPending['error_msg']) || (int)$aPending['processed'] != 0)
+            return $this->_sLangsPrefix . 'err_already_processed';
+
+        $iSellerId = (int)$aCartInfo['vendor_id'];
+        $sCustomData = $this->_constructCustomData($aCartInfo['vendor_id'], $iPendingId);
+        $sReturnDataUrl = $this->getReturnDataUrl($iSellerId);
+
+        switch($aPending['type']) {
+            case BX_PAYMENT_TYPE_SINGLE:
+                $aFormData = array(
+                    'currency_code' => $aCartInfo['vendor_currency_code'],
+                    'currency_sign' => $aCartInfo['vendor_currency_sign'],
+                    'seller' => $iSellerId,
+                    'amount' => (float)$aCartInfo['items_price'],
+                    'items_count' => count($aCartInfo['items']),
+                    'custom' => $sCustomData,
+                    'return_data_url' => $sReturnDataUrl,
+                );
+
+                $iIndex = 0;
+                foreach($aCartInfo['items'] as $aItem) {
+                    $aFormData['item_title_' . $iIndex] = bx_process_output($aItem['title']);
+                    $aFormData['item_quantity_' . $iIndex] = $aItem['quantity'];
+
+                    $iIndex += 1;
+                }
+
+                $sCheckoutUrl = bx_srv($this->_sModuleCredits, 'get_checkout_url');
+                $this->_oModule->_oTemplate->displayPageCodeRedirect($sCheckoutUrl, $aFormData);
+                exit;
+
+            case BX_PAYMENT_TYPE_RECURRING:
+                $aItem = array_shift($aCartInfo['items']);
+
+                return array(
+                    'code' => 0,
+                    'popup' => array(
+                        'html' => bx_srv($this->_sModuleCredits, 'get_popup_subscribe', array(array(
+                            'currency_code' => $aCartInfo['vendor_currency_code'],
+                            'currency_sign' => $aCartInfo['vendor_currency_sign'],
+                            'seller' => $iSellerId,
+                            'title' => bx_process_output($aItem['title']),
+                            'amount' => $aItem['price_recurring'],
+                            'period' => $aItem['period_recurring'],
+                            'period_unit' => $aItem['period_unit_recurring'],
+                            'trial' => isset($aItem['trial_recurring']) ? $aItem['trial_recurring'] : 0,
+                            'custom' => $sCustomData,
+                            'return_data_url' => $sReturnDataUrl,
+                        ))),
+                        'options' => array(
+                            'closeOnOuterClick' => true,
+                            'removeOnClose' => true
+                        )
+                    )
+                );
+        }
+    }
+
+    public function finalizeCheckout(&$aData)
+    {
+        $aResult = $this->_finalizeCheckout($aData);
+        if((int)$aResult['code'] != BX_PAYMENT_RESULT_SUCCESS) {
+            $this->log('Finalize Checkout: Failed');
+            $this->log($aData);
+            $this->log($aResult);
+        }
+
+        if(!empty($aResult['pending_id']))
+            $this->_oModule->_oDb->updateOrderPending($aResult['pending_id'], array(
+                'order' => $aResult['order'],
+                'error_code' => $aResult['code'],
+                'error_msg' => _t($aResult['message'])
+            ));
+
+        return $aResult;
+    }
+
+    public function makePayment($mixedPending)
+    {
+        if(!BxDolModuleQuery::getInstance()->isEnabledByName($this->_sModuleCredits))
+            return ['code' => 1, 'message' => $this->_sLangsPrefix . 'cdt_err_not_available'];
+
+        if(!is_array($mixedPending))
+            $mixedPending = $this->_oModule->_oDb->getOrderPending(['type' => 'id', 'id' => (int)$mixedPending]);
+
+        if(empty($mixedPending) || !is_array($mixedPending))
+            return ['code' => 2, 'message' => $this->_sLangsPrefix . 'err_not_found_pending'];
+
+        $iClient = (int)$mixedPending['client_id'];
+        $oClient = BxDolProfile::getInstance($iClient);
+
+        $iSeller = (int)$mixedPending['seller_id'];
+        $oSeller = BxDolProfile::getInstance($iSeller);
+
+        if(!$oClient || !$oSeller)
+            return ['code' => 3, 'message' => $this->_sLangsPrefix . 'err_wrong_data'];
+
+        $fAmount = (float)$mixedPending['amount'];
+        $fClientBalance = bx_srv($this->_sModuleCredits, 'get_profile_balance', [$iClient]);
+        if($fAmount > $fClientBalance)
+            return ['code' => 4, 'message' => $this->_sLangsPrefix . 'cdt_err_wrong_balance'];
+
+        if(!bx_srv($this->_sModuleCredits, 'make_payment', [$iClient, $fAmount, $iSeller, $mixedPending['order']]))
+            return ['code' => 5, 'message' => $this->_sLangsPrefix . 'err_cannot_perform'];
+
+        return true;        
+    }
+
+    public function cancelRecurring($iPendingId, $sCustomerId, $sSubscriptionId)
+    {
+        bx_alert($this->MODULE, $this->_sName . '_cancel_subscription', 0, false, array(
+            'pending_id' => $iPendingId,
+            'subscription_id' => $sSubscriptionId,
+        ));
+
+        return true;
+    }
+
+    public function getMenuItemsActionsRecurring($iClientId, $iVendorId, $aParams = array())
+    {
+        return array();
+    }
+
+    protected function _finalizeCheckout(&$aData)
+    {
+        list($iSellerId, $iPendingId) = $this->_deconstructCustomData($aData['c']);
+
+        if(empty($this->_aOptions) && !empty($iPendingId))
+            $this->_aOptions = $this->getOptionsByPending((int)$iPendingId);
+
+        $aPending = $this->_oModule->_oDb->getOrderPending(array('type' => 'id', 'id' => $iPendingId));
+        if(empty($aPending) || !is_array($aPending))
+            return array('code' => 1, 'message' => $this->_sLangsPrefix . 'err_not_found_pending');
+
+        if(empty($this->_aOptions) || !BxDolModuleQuery::getInstance()->isEnabledByName($this->_sModuleCredits))
+            return array('code' => 2, 'message' => $this->_sLangsPrefix . 'err_incorrect_provider', 'pending_id' => $iPendingId);
+
+        switch($aPending['type']) {
+            case BX_PAYMENT_TYPE_SINGLE:
+                if(!empty($aPending['order']) || !empty($aPending['error_code']) || !empty($aPending['error_msg']) || (int)$aPending['processed'] != 0)
+                    return array('code' => 3, 'message' => $this->_sLangsPrefix . 'err_already_processed');
+
+                $sOrder = $aData['o'];
+                if(!bx_srv($this->_sModuleCredits, 'validate_checkout', array((int)$aPending['seller_id'], (int)$aPending['client_id'], (float)$aPending['amount'], $sOrder)))
+                    return array('code' => 4, 'message' => $this->_sLangsPrefix . 'cdt_err_wrong_transaction', 'pending_id' => $iPendingId);
+
+                $aResult = array(
+                    'message' => $this->_sLangsPrefix . 'cdt_msg_charged',
+                    'order' => !empty($aData['o']) ? $aData['o'] : '',
+                    'paid' => true
+                );
+                break;
+
+            case BX_PAYMENT_TYPE_RECURRING:
+                $sSubscriptionId = bx_process_input($aData['sb']);
+
+                $aResult = array(
+                    'message' => $this->_sLangsPrefix . 'cdt_msg_subscribed',
+                    'customer_id' => bx_process_input($aData['cs']),
+                    'subscription_id' => $sSubscriptionId,
+                    'trial' => (bool)$aData['tr'],
+                    'order' => $sSubscriptionId,
+                );
+                break;
+        }
+
+        $oClient = BxDolProfile::getInstance($aPending['client_id']);
+        return array_merge(array(
+            'code' => BX_PAYMENT_RESULT_SUCCESS, 
+            'message' => '',
+            'pending_id' => $iPendingId,
+            'client_name' => $oClient->getDisplayName(),
+            'client_email' => $oClient->getAccountObject()->getEmail(),
+            'order' => ''
+        ), $aResult);
+    }
+
+    protected function _constructCustomData()
+    {
+        $aParams = func_get_args();
+        return urlencode(base64_encode(implode('|', $aParams)));
+    }
+
+    protected function _deconstructCustomData($data)
+    {
+        return explode('|', base64_decode(urldecode($data)));
+    }
+}
+
+/** @} */

+ 947 - 0
modules/boonex/payment/updates/13.0.3_13.0.4/source/classes/BxPaymentProviderPayPalApi.php

@@ -0,0 +1,947 @@
+<?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
+ *
+ * @{
+ */
+
+/*
+ * 1. Set up server-side SDK:
+ * https://developer.paypal.com/docs/business/checkout/server-side-api-calls/set-up-sdk/
+ * 
+ * 2. Orders API
+ * https://developer.paypal.com/docs/api/orders/v2
+ * 
+ * 2.1. Checkout SDK in GitHUB
+ * https://github.com/paypal/Checkout-PHP-SDK/
+ * 
+ * 3. Subscriptions:
+ * https://developer.paypal.com/docs/subscriptions/
+ * https://developer.paypal.com/docs/business/subscriptions/
+ * 
+ * 3.1. API
+ * https://developer.paypal.com/docs/api/subscriptions/v1
+ * https://developer.paypal.com/docs/api/catalog-products/v1
+ * 
+ * 3.2. Integration
+ * https://developer.paypal.com/docs/subscriptions/integrate/
+ * 
+ * 3.3 WebHooks
+ * https://developer.paypal.com/docs/api-basics/notifications/webhooks/rest/
+ * 
+ * 4. Authorize Intent and Capture Authorized: 
+ * https://github.com/paypal/Checkout-PHP-SDK/tree/develop/samples
+ * 
+ */
+
+use PayPalHttp\HttpException;
+use PayPalCheckoutSdk\Core\PayPalHttpClient;
+use PayPalCheckoutSdk\Core\SandboxEnvironment;
+use PayPalCheckoutSdk\Core\ProductionEnvironment;
+use PayPalCheckoutSdk\Orders\OrdersCreateRequest;
+use PayPalCheckoutSdk\Orders\OrdersGetRequest;
+use PayPalCheckoutSdk\Orders\OrdersCaptureRequest;
+use PayPalCheckoutSdk\Orders\OrdersAuthorizeRequest;
+use PayPalCheckoutSdk\Payments\AuthorizationsCaptureRequest;
+
+define('PP_API_MODE_LIVE', 1);
+define('PP_API_MODE_TEST', 2);
+define('PP_API_MODE_DEFAULT', PP_API_MODE_LIVE);
+
+define('PP_API_SBS_STATUS_APPROVAL_PENDING', 'APPROVAL_PENDING');
+define('PP_API_SBS_STATUS_APPROVED', 'APPROVED');
+define('PP_API_SBS_STATUS_ACTIVE', 'ACTIVE');
+
+class BxPaymentProviderPayPalApi extends BxBaseModPaymentProvider implements iBxBaseModPaymentProvider
+{
+    protected $_oSession;
+    protected $_sSessionKeyOrder;
+    protected $_sSessionKeySubscription;
+
+    protected $_bCheckAmount;
+    protected $_iMode;
+    protected $_sEndpoint;
+    protected $_sToken;
+
+    function __construct($aConfig)
+    {
+    	$this->MODULE = 'bx_payment';
+
+        parent::__construct($aConfig);
+
+        $this->_oSession = BxDolSession::getInstance();
+        $this->_sSessionKeyOrder = $this->MODULE . '_' . $this->_sPrefix . 'order';
+        $this->_sSessionKeySubscription = $this->MODULE . '_' . $this->_sPrefix . 'subscription';
+
+        $this->_bCheckAmount = true;
+        $this->_iMode = (int)$this->getOption('mode');
+        $this->_sEndpoint = 'https://api-m' . ($this->_iMode == PP_API_MODE_TEST ? '.sandbox' : '') . '.paypal.com/';
+    }
+
+    public function authorizeCheckout($iPendingId, $aCartInfo)
+    {
+        if(empty($aCartInfo['items']) || !is_array($aCartInfo['items']))
+            return $this->_sLangsPrefix . 'err_empty_items';
+
+        $aPending = $this->_oModule->_oDb->getOrderPending(array('type' => 'id', 'id' => $iPendingId));
+        if(!empty($aPending['order']) || !empty($aPending['error_code']) || !empty($aPending['error_msg']) || (int)$aPending['processed'] != 0)
+            return $this->_sLangsPrefix . 'err_already_processed';
+
+        switch($aPending['type']) {
+            case BX_PAYMENT_TYPE_SINGLE:
+                $mixedResult = $this->_createOrder($iPendingId, $aCartInfo, ['intent' => 'authorize']);
+                if($mixedResult === false)
+                    return $this->_sLangsPrefix . 'err_cannot_perform';
+
+                $this->_setSessionOrder($mixedResult['order']);
+                return [
+                    'code' => BX_PAYMENT_RESULT_SUCCESS,
+                    'redirect' => $mixedResult['redirect']
+                ];
+
+            case BX_PAYMENT_TYPE_RECURRING:
+                return $this->_sLangsPrefix . 'err_not_supported';
+        }
+    }
+
+    public function captureAuthorizedCheckout($sOrderAuth, $mixedPending, $aInfo)
+    {
+        $aPending = is_array($mixedPending) ? $mixedPending : $this->_oModule->_oDb->getOrderPending(['type' => 'id', 'id' => (int)$mixedPending]);
+        if(empty($aPending) || !is_array($aPending))
+            return ['code' => 2, 'message' => $this->_sLangsPrefix . 'err_empty_order'];
+
+        $mixedResult = false;
+        switch($aPending['type']) {
+            case BX_PAYMENT_TYPE_SINGLE:
+                $mixedResult = $this->_captureAuthorization($sOrderAuth);
+                if($mixedResult === false)
+                    return ['code' => 3, 'message' => $this->_sLangsPrefix . 'err_cannot_perform'];
+                break;
+
+            case BX_PAYMENT_TYPE_RECURRING:
+                return ['code' => 1, 'message' => $this->_sLangsPrefix . 'err_not_supported'];
+        }
+
+        $aResult = [
+            'code' => BX_PAYMENT_RESULT_SUCCESS,
+            'message' => $this->_sLangsPrefix . 'pp_api_msg_captured',
+            'pending_id' => $aPending['id'],
+            'paid' => true
+        ];
+
+        //--- Update pending transaction
+        $this->_oModule->_oDb->updateOrderPending($aResult['pending_id'], [
+            'order' => $mixedResult['order'],
+            'error_code' => $aResult['code'],
+            'error_msg' => _t($aResult['message']),
+        ]);
+
+        return $aResult;
+    }
+
+    public function initializeCheckout($iPendingId, $aCartInfo)
+    {
+        if(empty($aCartInfo['items']) || !is_array($aCartInfo['items']))
+            return $this->_sLangsPrefix . 'err_empty_items';
+
+        $aPending = $this->_oModule->_oDb->getOrderPending(array('type' => 'id', 'id' => $iPendingId));
+        if(!empty($aPending['order']) || !empty($aPending['error_code']) || !empty($aPending['error_msg']) || (int)$aPending['processed'] != 0)
+            return $this->_sLangsPrefix . 'err_already_processed';
+
+        switch($aPending['type']) {
+            case BX_PAYMENT_TYPE_SINGLE:
+                $mixedResult = $this->_createOrder($iPendingId, $aCartInfo);
+                if($mixedResult === false)
+                    return $this->_sLangsPrefix . 'err_cannot_perform';
+
+                $this->_setSessionOrder($mixedResult['order']);
+                header("Location: " . $mixedResult['redirect']);
+                exit;
+
+            case BX_PAYMENT_TYPE_RECURRING:
+                $mixedResult = $this->_createSubscription($iPendingId, $aCartInfo);
+                if(is_string($mixedResult))
+                    return $mixedResult;
+
+                $this->_setSessionSubscription($mixedResult['subscription']);
+                return array(
+                    'code' => 0,
+                    'redirect' => $mixedResult['redirect'],
+                );
+        }
+    }
+
+    public function finalizeCheckout(&$aData)
+    {
+        $sMethod = '_finalizeCheckout' . bx_gen_method_name(!empty($aData['subscription_id']) && !empty('ba_token') ? BX_PAYMENT_TYPE_RECURRING : BX_PAYMENT_TYPE_SINGLE);
+
+        $aResult = $this->$sMethod($aData);
+        if(!isset($aResult['code']) || (int)$aResult['code'] != BX_PAYMENT_RESULT_SUCCESS) {
+            $this->log($aResult, 'Finalize Checkout Failed:');
+            $this->log($aData, 'Finalize Checkout Input:');
+        }
+
+        return $aResult;
+    }
+
+    public function notify()
+    {
+        $iResult = $this->_processEvent();
+        http_response_code($iResult);
+    }
+
+    public function getClientId()
+    {
+        return $this->getOption($this->_getMode() . '_client_id');
+    }
+
+    public function getSecret()
+    {
+        return $this->getOption($this->_getMode() . '_secret');
+    }
+
+    public function getMenuItemsActionsRecurring($iClientId, $iVendorId, $aParams = array())
+    {
+        return array();
+    }
+
+    protected function _finalizeCheckoutSingle(&$aData)
+    {
+        $sOrder = '';
+        if(!empty($aData['token']))
+            $sOrder = bx_process_input($aData['token']);
+        if(empty($sOrder))
+            $sOrder = $this->_getSessionOrder();
+        if(empty($sOrder))
+            return['code' => 1, 'message' => $this->_sLangsPrefix . 'err_empty_order'];
+
+        $aOrder = $this->_getOrder($sOrder);
+        if(empty($aOrder) || !is_array($aOrder))
+            return ['code' => 1, 'message' => $this->_sLangsPrefix . 'err_empty_order'];
+
+        $sMessage = '';
+        $bAuthorized = $bPaid = false;
+        switch($aOrder['intent']) {
+            case 'authorize':
+                $mixedResult = $this->_authorizeOrder($sOrder);
+                if($mixedResult === false)
+                    return ['code' => 2, 'message' => $this->_sLangsPrefix . 'pp_api_err_cannot_authorize'];
+
+                $sMessage = $this->_sLangsPrefix . 'pp_api_msg_authorized';
+                $bAuthorized = true;
+                break;
+
+            case 'capture':
+                $mixedResult = $this->_captureOrder($sOrder);
+                if($mixedResult === false)
+                    return ['code' => 2, 'message' => $this->_sLangsPrefix . 'pp_api_err_cannot_capture'];
+
+                $sMessage = $this->_sLangsPrefix . 'pp_api_msg_captured';
+                $bPaid = true;
+                break;
+        }
+
+        $aResult = [
+            'code' => BX_PAYMENT_RESULT_SUCCESS, 
+            'message' => $sMessage,
+            'pending_id' => $mixedResult['pending_id'],
+            'client_name' => _t($this->_sLangsPrefix . 'txt_buyer_name_mask', $mixedResult['client_first_name'], $mixedResult['client_last_name']),
+            'client_email' => $mixedResult['client_email'],
+            'authorized' => $bAuthorized,
+            'paid' => $bPaid
+        ];
+
+        //--- Update pending transaction
+        $this->_oModule->_oDb->updateOrderPending($aResult['pending_id'], [
+            'order' => $mixedResult['order'],
+            'error_code' => $aResult['code'],
+            'error_msg' => _t($aResult['message']),
+        ]);
+
+        return $aResult;
+    }
+
+    protected function _finalizeCheckoutRecurring(&$aData)
+    {
+        $sSubscription = '';
+        if(!empty($aData['subscription_id']))
+            $sSubscription = bx_process_input($aData['subscription_id']);
+        if(empty($sSubscription))
+            $sSubscription = $this->_getSessionSubscription();
+        if(empty($sSubscription))
+            return array('code' => 1, 'message' => $this->_sLangsPrefix . 'pp_api_err_no_subscription');
+
+        $aSubscription = $this->_getSubscription($sSubscription);
+        if(empty($aSubscription) || !in_array($aSubscription['status'], array(PP_API_SBS_STATUS_APPROVAL_PENDING, PP_API_SBS_STATUS_APPROVED, PP_API_SBS_STATUS_ACTIVE)))
+            return array('code' => 2, 'message' => $this->_sLangsPrefix . 'pp_api_err_no_subscription');
+
+        $aSubscriber = $this->_getClientInfo($aSubscription['subscriber']);
+        list($bPaid, $bTrial) = $this->_getBillingStatus($aSubscription['billing_info']);
+
+        $aResult = array(
+            'code' => BX_PAYMENT_RESULT_SUCCESS, 
+            'message' => $this->_sLangsPrefix . 'pp_api_msg_subscribed',
+            'pending_id' => $aSubscription['custom_id'],
+            'customer_id' => $aSubscription['subscriber']['payer_id'], 
+            'subscription_id' => $sSubscription,
+            'client_name' => _t($this->_sLangsPrefix . 'txt_buyer_name_mask', $aSubscriber['client_first_name'], $aSubscriber['client_last_name']),
+            'client_email' => $aSubscriber['client_email'],
+            'paid' => $bPaid,
+            'trial' => $bTrial,
+        );
+
+        if($aSubscription['status'] == PP_API_SBS_STATUS_APPROVAL_PENDING)       
+            $aResult = array_merge($aResult, array(
+                'code' => 3,
+                'message' => $this->_sLangsPrefix . 'pp_api_err_subscription_not_confirmed'
+            ));
+
+        //--- Update pending transaction
+        $this->_oModule->_oDb->updateOrderPending($aResult['pending_id'], array(
+            'order' => $sSubscription,
+            'error_code' => $aResult['code'],
+            'error_msg' => _t($aResult['message'])
+        ));
+
+        return $aResult;
+    }
+
+    /**
+     * Methods which use common HTTPS calls to process Recurring time payments.
+     */
+    protected function _createSubscription($iPendingId, $aCartInfo, $sReturnType = 'approve')
+    {
+        $aItem = array_shift($aCartInfo['items']);
+        if(empty($aItem) || !is_array($aItem))
+            return $this->_sLangsPrefix . 'pp_api_err_no_item';
+
+        $aItem['price_currency'] = $aCartInfo['vendor_currency_code'];
+
+        $aProduct = $this->_getProduct($aItem['name']);
+        if(empty($aProduct)) {
+            $aProduct = $this->_createProduct($aItem);
+            if($aProduct === false)
+                return $this->_sLangsPrefix . 'err_cannot_perform';
+        }
+
+        $aProductPlan = array();
+
+        $aPlans = $this->_getPlans($aProduct['id']);
+        if(!empty($aPlans)) 
+            foreach($aPlans as $aPlan)
+                if(strcmp($aPlan['name'], $aItem['name']) == 0) {
+                    $aProductPlan = $aPlan;
+                    break;
+                }
+        
+        if(empty($aProductPlan) || !is_array($aProductPlan)) {
+            $aProductPlan = $this->_createPlan($aProduct['id'], $aItem);
+            if($aProductPlan === false)
+                return $this->_sLangsPrefix . 'err_cannot_perform';
+        }
+
+        $mixedResult = $this->_apiCallAuthorized($this->_sEndpoint . 'v1/billing/subscriptions', array(
+            'plan_id' => $aProductPlan['id'],
+            'custom_id' => $iPendingId,
+            'application_context' => array(
+                'cancel_url' => $aItem['url'],
+                'return_url' => $this->getReturnDataUrl($aCartInfo['vendor_id'])
+            )
+        ));
+
+        if($mixedResult === false || empty($mixedResult['id']) || empty($mixedResult['links'])) {
+            $this->log($mixedResult, 'Create Subscription:');
+
+            return $this->_sLangsPrefix . 'err_cannot_perform';
+        }
+
+        $mixedLink = false;
+        foreach($mixedResult['links'] as $aLink)
+            if($aLink['rel'] == $sReturnType) {
+                $mixedLink = $aLink['href'];
+                break;
+            }
+
+        return array(
+            'subscription' => $mixedResult['id'],
+            'redirect' => $mixedLink
+        );
+    }
+
+    protected function _getSubscription($sSubscriptionId)
+    {
+        $mixedResult = $this->_apiCallAuthorized($this->_sEndpoint . 'v1/billing/subscriptions/' . $sSubscriptionId, array(), array(), 'get');
+        if($mixedResult === false || !isset($mixedResult['id'])) {
+            $this->log($mixedResult, 'Get Subscription:');
+
+            return array();
+        }
+
+        return $mixedResult;
+    }
+
+    protected function _createProduct($aItem)
+    {
+        if(empty($aItem['description']))
+            $aItem['description'] = _t('_bx_payment_txt_payment_description', getParam('site_title'));
+        $aItem['description'] = strmaxtextlen($aItem['description'], 60, '...');
+
+        $mixedResult = $this->_apiCallAuthorized($this->_sEndpoint . 'v1/catalogs/products', array(
+            'id' => $aItem['name'],
+            'name' => $aItem['title'],
+            'description' => $aItem['description'],
+            'type' => 'DIGITAL',
+            'home_url' => $aItem['url'],
+        ), array(
+            'PayPal-Request-Id: bx_prod_' . $aItem['name']
+        ));
+
+        if($mixedResult === false || !isset($mixedResult['id'])) {
+            $this->log($mixedResult, 'Create Product:');
+
+            return false;
+        }
+
+        return $mixedResult;
+    }
+    
+    protected function _getProduct($sProductId)
+    {
+        $mixedResult = $this->_apiCallAuthorized($this->_sEndpoint . 'v1/catalogs/products/' . $sProductId, array(), array(), 'get');
+        if($mixedResult === false || !isset($mixedResult['id'])) {
+            $this->log($mixedResult, 'Get Product:');
+
+            return array();
+        }
+
+        return $mixedResult;
+    }
+
+    protected function _createPlan($sProductId, $aItem)
+    {
+        $aCycles = array();
+
+        $sIntervalUnit = $this->_getIntervalUnit($aItem['period_unit_recurring']);
+        if($sIntervalUnit === false)
+            return false;
+
+        $iSequence = 1;
+
+        $iTrial = $this->_oModule->_oConfig->getTrial(BX_PAYMENT_TYPE_RECURRING, $aItem);
+        if(!empty($iTrial)) 
+            $aCycles[] = array(
+                'frequency' => array(
+                    'interval_unit' => $this->_getIntervalUnit(BX_PAYMENT_SBS_PU_DAY),
+                    'interval_count' => $iTrial
+                ),
+                'tenure_type' => 'TRIAL',
+                'sequence' => $iSequence++,
+                'total_cycles' => 1,
+            );
+
+        $aCycles[] = array(
+            'frequency' => array(
+                'interval_unit' => $sIntervalUnit,
+                'interval_count' => (int)$aItem['period_recurring']
+            ),
+            'tenure_type' => 'REGULAR',
+            'sequence' => $iSequence,
+            'total_cycles' => 0,
+            'pricing_scheme' => array(
+                'fixed_price' => array(
+                    'value' => $this->_oModule->_oConfig->getPrice(BX_PAYMENT_TYPE_RECURRING, $aItem),
+                    'currency_code' => $aItem['price_currency']
+                )
+            )
+        );
+
+        $mixedResult = $this->_apiCallAuthorized($this->_sEndpoint . 'v1/billing/plans', array(
+            'product_id' => $sProductId,
+            'name' => $aItem['name'],
+            'description' => $aItem['title'],
+            'billing_cycles' => $aCycles,
+            'payment_preferences' => array(
+                'auto_bill_outstanding' => true,
+                'setup_fee' => array(
+                    'value' => 0,
+                    'currency_code' => $aItem['price_currency']
+                ),
+                'setup_fee_failure_action' => 'CONTINUE',
+                'payment_failure_threshold' => 3
+            ),
+        ), array(
+            'PayPal-Request-Id: bx_plan_' . $aItem['name']
+        ));
+
+        if($mixedResult === false || !isset($mixedResult['id'])) {
+            $this->log($mixedResult, 'Create Plan:');
+
+            return false;
+        }
+
+        return $mixedResult;
+    }
+
+    protected function _getPlan($sPlanId)
+    {
+        $mixedResult = $this->_apiCallAuthorized($this->_sEndpoint . 'v1/billing/plans/' . $sPlanId, array(), array(), 'get');
+        if($mixedResult === false || !isset($mixedResult['id'])) {
+            $this->log($mixedResult, 'Get Plan:');
+
+            return array();
+        }
+
+        return $mixedResult;
+    }
+
+    protected function _getPlans($sProductId, $iStart = false, $iPerPage = false)
+    {
+        $aParams = array(
+            'product_id' => $sProductId,
+        );
+        
+        if($iStart !== false)
+            $aParams['page'] = (int)$iStart >= 1 && (int)$iStart <= 100000 ? $iStart : 1;
+        if($iPerPage !== false)
+            $aParams['page_size'] = (int)$iPerPage >= 1 && (int)$iPerPage <= 20 ? $iPerPage : 20;
+
+        $mixedResult = $this->_apiCallAuthorized($this->_sEndpoint . 'v1/billing/plans', $aParams, array(), 'get');
+        if(empty($mixedResult) || !is_array($mixedResult) || !isset($mixedResult['plans'])) {
+            $this->log($mixedResult, 'Get Plans:');
+
+            return array();
+        }
+
+        return $mixedResult['plans'];
+    }
+
+    protected function _getToken()
+    {
+        $mixedResult = $this->_apiCall($this->_sEndpoint . 'v1/oauth2/token', array(
+            'grant_type' => 'client_credentials'
+        ), array(), 'post', array(
+            'user' => $this->getClientId(),
+            'password' => $this->getSecret()
+        ));
+
+        if($mixedResult === false || empty($mixedResult['access_token'])) {
+            $this->log($mixedResult, 'Get Token:');
+
+            return false;
+        }
+
+        return $mixedResult['access_token'];
+    }
+
+    protected function _apiCallAuthorized($sEndpoint, $aParams = array(), $aHeaders = array(), $sMethod = 'post-json')
+    {
+        if(!$this->_sToken)
+            $this->_sToken = $this->_getToken();
+
+        $aHeaders = array_merge(array(
+            'Authorization: Bearer ' . $this->_sToken,
+            'Prefer: return=representation'
+        ), $aHeaders);
+
+        return $this->_apiCall($sEndpoint, $aParams, $aHeaders, $sMethod);
+    }
+
+    protected function _apiCall($sEndpoint, $aParams = array(), $aHeaders = array(), $sMethod = 'post-json', $aBasicAuth = array())
+    {
+        $sHttpCode = null;
+        $aHeaders = array_merge(array(
+            'Accept: application/json',
+            'Content-Type: application/json'
+        ), $aHeaders);
+
+        $sResult = bx_file_get_contents($sEndpoint, $aParams, $sMethod, $aHeaders, $sHttpCode, $aBasicAuth);
+        if(empty($sResult))
+            return false;
+
+        return json_decode($sResult, true);
+    }
+
+    protected function _getIntervalUnit($sPeriodUnit)
+    {
+        $aIntervalUnits = array(
+            BX_PAYMENT_SBS_PU_DAY => 'DAY',
+            BX_PAYMENT_SBS_PU_WEEK => 'WEEK',
+            BX_PAYMENT_SBS_PU_MONTH => 'MONTH',
+            BX_PAYMENT_SBS_PU_YEAR => 'YEAR'
+        );
+
+        return isset($aIntervalUnits[$sPeriodUnit]) ? $aIntervalUnits[$sPeriodUnit] : false;
+    }
+
+
+    /**
+     * Methods which use 'Checkout SDK' to process Single time payments.
+     */
+    protected function _getClient()
+    {
+        $sClientId = $this->getClientId();
+        $sSecret = $this->getSecret();
+
+        if($this->_iMode == PP_API_MODE_LIVE)
+            $oEnvironment = new ProductionEnvironment($sClientId, $sSecret);
+        else 
+            $oEnvironment = new SandboxEnvironment($sClientId, $sSecret);
+
+        return new PayPalHttpClient($oEnvironment);
+    }
+
+    protected function _createOrder($iPendingId, $aCartInfo, $aParams = [])
+    {
+        $sReturnType = isset($aParams['return_type']) ? $aParams['return_type'] : 'approve';
+                
+        $aItems = array();
+        foreach($aCartInfo['items'] as $aItem)
+            $aItems[] = array(
+                'name' => $aItem['title'],
+                'unit_amount' => array(
+                    'value' => sprintf("%.2f", $this->_oModule->_oConfig->getPrice(BX_PAYMENT_TYPE_SINGLE, $aItem)),
+                    'currency_code' => $aCartInfo['vendor_currency_code']
+                ),
+                'quantity' => $aItem['quantity']
+            );
+
+        $sItemsPrice = sprintf("%.2f", round($aCartInfo['items_price'], 2));
+
+        $oRequest = new OrdersCreateRequest();
+        $oRequest->prefer('return=representation');
+        $oRequest->body = array(
+            'intent' => isset($aParams['intent']) ? strtoupper($aParams['intent']) : 'CAPTURE',
+            'purchase_units' => array(
+                array(
+                    'reference_id' => $iPendingId,
+                    'amount' => array(
+                        'currency_code' => $aCartInfo['vendor_currency_code'],
+                        'value' => $sItemsPrice,
+                        'breakdown' => array(
+                            'item_total' => array(
+                                'currency_code' => $aCartInfo['vendor_currency_code'],
+                                'value' => $sItemsPrice,
+                            )
+                        )
+                    ),
+                    'items' => $aItems
+                )
+            ),
+            'application_context' => array(
+                'cancel_url' => $this->_oModule->getObjectCart()->serviceGetCartUrl($aCartInfo['vendor_id']),
+                'return_url' => $this->getReturnDataUrl($aCartInfo['vendor_id'])
+            )
+        );
+
+        try {
+            $oResponse = $this->_getClient()->execute($oRequest);
+            if($oResponse->statusCode != 201)
+                return false;
+
+            $mixedLink = false;
+            foreach($oResponse->result->links as $oLink)
+                if($oLink->rel == $sReturnType) {
+                    $mixedLink = $oLink->href;
+                    break;
+                }
+
+            return array(
+                'order' => $oResponse->result->id,
+                'redirect' => $mixedLink,
+            );
+        }
+        catch (HttpException $oException) {
+            return $this->_processException('Create Order Error: ', $oException);
+        }
+    }
+
+    protected function _getOrder($sOrderId)
+    {
+        $oRequest = new OrdersGetRequest($sOrderId);
+
+        try {
+            $oResponse = $this->_getClient()->execute($oRequest);
+            if($oResponse->statusCode != 200 || strcmp(strtolower($oResponse->result->status), 'approved') != 0)
+                return false;
+
+            $oPurchase = current($oResponse->result->purchase_units);
+            return array_merge(array(
+                'id' => $oResponse->result->id,
+                'intent' => strtolower($oResponse->result->intent),
+                'pending_id' => (int)$oPurchase->reference_id,
+            ), $this->_getClientInfo($oResponse->result->payer));
+        }
+        catch (HttpException $oException) {
+            return $this->_processException('Get Order Error: ', $oException);
+        }
+        
+    }
+
+    protected function _authorizeOrder($sOrderId)
+    {
+        $oRequest = new OrdersAuthorizeRequest($sOrderId);
+
+        try {
+            $oResponse = $this->_getClient()->execute($oRequest);
+            if($oResponse->statusCode != 201 || strcmp(strtolower($oResponse->result->status), 'completed') != 0)
+                return false;
+
+            $oPurchase = current($oResponse->result->purchase_units);
+            $oAuthorization = current($oPurchase->payments->authorizations);
+            return array_merge(array(
+                'pending_id' => (int)$oPurchase->reference_id,
+                'order' => $oAuthorization->id,
+            ), $this->_getClientInfo($oResponse->result->payer));
+        }
+        catch (HttpException $oException) {
+            return $this->_processException('Authorize Order Error: ', $oException);
+        }
+    }
+
+    protected function _captureOrder($sOrderId)
+    {
+        $oRequest = new OrdersCaptureRequest($sOrderId);
+
+        try {
+            $oResponse = $this->_getClient()->execute($oRequest);
+            if($oResponse->statusCode != 201 || strcmp(strtolower($oResponse->result->status), 'completed') != 0)
+                return false;
+
+            $oPurchase = current($oResponse->result->purchase_units);
+            $oCapture = current($oPurchase->payments->captures);
+            return array_merge(array(
+                'pending_id' => (int)$oPurchase->reference_id,
+                'order' => $oCapture->id,
+            ), $this->_getClientInfo($oResponse->result->payer));
+        }
+        catch (HttpException $oException) {
+            return $this->_processException('Capture Order Error: ', $oException);
+        }
+    }
+    
+    protected function _captureAuthorization($sAuthorizationId)
+    {
+        $oRequest = new AuthorizationsCaptureRequest($sAuthorizationId);
+
+        try {
+            $oResponse = $this->_getClient()->execute($oRequest);
+            if($oResponse->statusCode != 201 || strcmp(strtolower($oResponse->result->status), 'completed') != 0)
+                return false;
+
+            return [
+                'order' => $oResponse->result->id
+            ];
+        }
+        catch (HttpException $oException) {
+            return $this->_processException('Capture Authorization Error: ', $oException);
+        }
+    }
+
+    protected function _processException($sMessage, &$oException)
+    {
+        $sDescription = '';
+        $aError = [];
+
+        $sMethod = 'getJsonBody';
+        if(method_exists($oException, $sMethod)) {
+            $aError = $oException->getJsonBody();
+            if(isset($aError['error']['message']))
+                $sDescription = $aError['error']['message'];
+        }
+
+        if(empty($sDescription))
+            $sDescription = $oException->getMessage();
+
+        $this->log($sMessage . $sDescription);
+        if(!empty($aError))
+            $this->log($aError);
+
+        return false;
+    }
+
+    /**
+     * Methods to process WebHooks
+     */
+    protected function _processEvent()
+    {
+        $sInput = @file_get_contents("php://input");
+        $aEvent = json_decode($sInput, true);
+        if(empty($aEvent) || !is_array($aEvent)) 
+            return 404;
+
+        $sType = $aEvent['event_type'];
+        if(!in_array($sType, array('PAYMENT.SALE.COMPLETED', 'PAYMENT.CAPTURE.REFUNDED', 'BILLING.SUBSCRIPTION.CANCELLED')))
+            return 200;
+
+        $this->log($aEvent, 'Webhooks: ' . (!empty($sType) ? $sType : ''));
+
+        $sMethod = '_processEvent' . bx_gen_method_name(strtolower($sType), array('.', '_', '-'));
+    	if(!method_exists($this, $sMethod))
+            return 200;
+
+    	return $this->$sMethod($aEvent) ? 200 : 403;
+    }
+
+    protected function _processEventPaymentSaleCompleted($aEvent)
+    {
+        $mixedResult = $this->_getEventData($aEvent);
+        if($mixedResult === false)
+            return false;
+
+        list($aPending, $aEventData) = $mixedResult;
+
+        $fChargeAmount = (float)$aEventData['amount']['total'];
+        $sChargeCurrency = strtoupper($aEventData['amount']['currency']);
+        if($this->_bCheckAmount && ((float)$aPending['amount'] != $fChargeAmount || strcasecmp($this->_oModule->_oConfig->getDefaultCurrencyCode(), $sChargeCurrency) !== 0))
+            return false;
+
+        if($aPending['type'] == BX_PAYMENT_TYPE_RECURRING)
+            $this->_oModule->getObjectSubscriptions()->prolong($aPending);
+
+        return $this->_oModule->registerPayment($aPending);
+    }
+
+    protected function _processEventPaymentCaptureRefunded($aEvent)
+    {
+        $mixedResult = $this->_getEventData($aEvent);
+        if($mixedResult === false)
+            return false;
+
+        list($aPending, $aEventData) = $mixedResult;
+        return $this->_oModule->refundPayment($aPending);
+    }
+
+    protected function _processEventBillingSubscriptionCancelled($aEvent)
+    {
+        $mixedResult = $this->_getEventData($aEvent);
+        if($mixedResult === false)
+            return false;
+
+        list($aPending, $aEventData) = $mixedResult;
+        return $this->_oModule->getObjectSubscriptions()->cancelLocal($aPending);
+    }
+
+    protected function _getEventData($aEvent)
+    {
+        if(empty($aEvent['resource']) || !is_array($aEvent['resource']))
+            return false;
+
+        $aData = $aEvent['resource'];
+        if(empty($aData['billing_agreement_id']))
+            return false;       
+
+        $aPending = $this->_oModule->_oDb->getOrderPending(array('type' => 'order', 'order' => $aData['billing_agreement_id']));
+        if(empty($aPending) || !is_array($aPending))
+            return false;
+
+        return array($aPending, $aData);
+    }
+
+    /**
+     * Common methods for internal usage.
+     */
+    protected function _getMode()
+    {
+        if(empty($this->_iMode))
+            $this->_iMode = (int)$this->getOption('mode');
+
+        $aModeI2S = array(
+            PP_API_MODE_LIVE => 'live',
+            PP_API_MODE_TEST => 'test'
+        );
+
+        return isset($aModeI2S[$this->_iMode]) ? $aModeI2S[$this->_iMode] : $aModeI2S[PP_API_MODE_DEFAULT];
+    }
+
+    protected function _getSessionOrder()
+    {
+        return $this->_oSession->getUnsetValue($this->_sSessionKeyOrder);
+    }
+
+    protected function _setSessionOrder($sValue)
+    {
+        $this->_oSession->setValue($this->_sSessionKeyOrder, $sValue);
+    }
+
+    protected function _getSessionSubscription()
+    {
+        return $this->_oSession->getUnsetValue($this->_sSessionKeySubscription);
+    }
+
+    protected function _setSessionSubscription($sValue)
+    {
+        $this->_oSession->setValue($this->_sSessionKeySubscription, $sValue);
+    }
+
+    /**
+     * Retrieve 'Client Info' from a 'getSubscription' call's response.
+     */
+    protected function _getClientInfo($mixedClient)
+    {
+        $_sName = 'name';
+        $_sFirst = 'given_name';
+        $_sLast = 'surname';
+        $_sEmail = 'email_address';
+
+        $aResult = [];
+        if(is_object($mixedClient))
+            $aResult = [
+                'client_first_name' => $mixedClient->$_sName->$_sFirst,
+                'client_last_name' => $mixedClient->$_sName->$_sLast,
+                'client_email' => $mixedClient->$_sEmail,
+            ];
+        else
+            $aResult = [
+                'client_first_name' => $mixedClient[$_sName][$_sFirst],
+                'client_last_name' => $mixedClient[$_sName][$_sLast],
+                'client_email' => $mixedClient[$_sEmail],
+            ];
+
+        return $aResult;
+    }
+
+    /**
+     * Retrieve 'Billing Status' from a 'getSubscription' call's response.
+     */
+    protected function _getBillingStatus($mixedBillingInfo)
+    {
+        $bTrial = $bPaid = false;
+
+        $_sCycles = 'cycle_executions';
+        $_sCycleType = 'tenure_type';
+        $_sCyclesCompleted = 'cycles_completed';
+        $_sCyclesTotal = 'total_cycles';
+
+        $bByObject = is_object($mixedBillingInfo);
+        $aCycles = $bByObject ? $mixedBillingInfo->$_sCycles : $mixedBillingInfo[$_sCycles];
+        if(empty($aCycles) || !is_array($aCycles))
+            return [$bPaid, $bTrial];
+
+        foreach($aCycles as $mixedCycle) {
+            $sCycleType = $bByObject ? $mixedCycle->$_sCycleType : $mixedCycle[$_sCycleType];
+            $iCyclesCompleted = $bByObject ? $mixedCycle->$_sCyclesCompleted : (int)$mixedCycle[$_sCyclesCompleted];
+            $iCyclesTotal = $bByObject ? $mixedCycle->$_sCyclesTotal : (int)$mixedCycle[$_sCyclesTotal];
+
+            switch($sCycleType) {
+                case 'TRIAL':
+                    if($iCyclesCompleted < $iCyclesTotal) {
+                        $bTrial = true;
+                        break 2;
+                    }
+                    break;
+                
+                case 'REGULAR':
+                    $bPaid = true;
+                    break 2;
+            }
+        }
+
+        return [$bPaid, $bTrial];
+    }
+}
+
+/** @} */

+ 70 - 0
modules/boonex/payment/updates/13.0.3_13.0.4/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' => '13.0.4',
+    'vendor' => 'Boonex',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '13.0.0-B4'
+    ),
+
+    /**
+     * '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(),
+);
+
+/** @} */

+ 662 - 0
modules/boonex/payment/updates/13.0.3_13.0.4/source/install/langs/en.xml

@@ -0,0 +1,662 @@
+<?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_options_category_general"><![CDATA[General]]></string>
+    <string name="_bx_payment_options_category_commissions"><![CDATA[Commissions]]></string>
+    <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>
+    <string name="_bx_payment_option_inv_issue_day"><![CDATA[Day of month when invoices are automatically generated (1, 2, 3, etc)]]></string>
+    <string name="_bx_payment_option_inv_lifetime"><![CDATA[Due date - days after invoice date]]></string>
+    <string name="_bx_payment_option_inv_expiraction_notify"><![CDATA[Number of days before invoice expiration to notify payer]]></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>
+    
+    <string name="_bx_payment_page_title_sys_checkout_offline"><![CDATA[Offline Checkout]]></string>
+    <string name="_bx_payment_page_title_checkout_offline"><![CDATA[Offline Checkout]]></string>
+    <string name="_bx_payment_page_block_title_sys_checkout_offline"><![CDATA[Offline Checkout]]></string>
+    <string name="_bx_payment_page_block_title_checkout_offline"><![CDATA[]]></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[Fixed fee]]></string>
+    <string name="_bx_payment_grid_column_title_inv_commissionaire_id"><![CDATA[Payee]]></string>
+    <string name="_bx_payment_grid_column_title_inv_committent_id"><![CDATA[Payer]]></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 Monthly Commission]]></string>
+    <string name="_bx_payment_popup_title_cms_edit"><![CDATA[Edit Monthly 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_details_form"><![CDATA[Details Form]]></string>
+    <string name="_bx_payment_form_details_display_edit"><![CDATA[Edit Details Display]]></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[Fixed fee]]></string>
+    <string name="_bx_payment_form_commissions_input_installment"><![CDATA[Fixed fee]]></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>
+
+    <string name="_bx_payment_form_input_email_err_cor_or_emp"><![CDATA[Use correct email address or leave empty.]]></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>
+
+    <string name="_bx_payment_et_txt_name_checkout_offline"><![CDATA[Offline checkout attempt.]]></string>
+    <string name="_bx_payment_et_txt_subject_checkout_offline"><![CDATA[An attempt to pay with cash.]]></string>
+    <string name="_bx_payment_et_txt_body_checkout_offline"><![CDATA[{email_header}
+<p>Hello,</p>
+<p>A site member <a href="{profile_link}">{profile_name}</a> wanted to pay you with cash for:</p>
+<p>{items}</p>
+<p>Amount: {amount}<br />Date: {date}</p>
+<p>Go to the <a href="{pending_orders_link}">pending orders page</a> to process the order once the payment is received.</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_vendor"><![CDATA[Incorrect 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_checkout_with_cash"><![CDATA[Checkout with cash]]></string>
+    <string name="_bx_payment_txt_checkout_for"><![CDATA[A message was sent to the seller ({0}), that you want to pay with cash for the following items. He should contact you shortly.]]></string>
+    <string name="_bx_payment_txt_checkout_qt"><![CDATA[qt.]]></string>
+    <string name="_bx_payment_txt_checkout_item"><![CDATA[{0} ({1}qt.)<br />]]></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_price"><![CDATA[Price]]></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>
+    <string name="_bx_payment_txt_payment_description"><![CDATA[Payment on {0} site.]]></string>
+
+    <!-- Offline payment provider -->
+    <string name="_bx_payment_off_cpt"><![CDATA[Offline]]></string>
+    <string name="_bx_payment_off_dsc"><![CDATA[For offline payments like cash, etransfer, etc.]]></string>
+    <string name="_bx_payment_off_active_cpt"><![CDATA[Active]]></string>
+    <string name="_bx_payment_off_active_dsc"><![CDATA[Activate(Deactivate) provider]]></string>
+    <string name="_bx_payment_off_checkout_email_cpt"><![CDATA[Email]]></string>
+    <string name="_bx_payment_off_checkout_email_dsc"><![CDATA[Email to send notifications about checkout attempts to. Leave empty to receive notifications on your profile email.]]></string>
+    <string name="_bx_payment_off_err_not_available"><![CDATA[Offline payment provider isn't available for online payments.]]></string>
+    <string name="_bx_payment_txt_name_offline"><![CDATA[Cash]]></string>
+    <string name="_bx_payment_txt_cart_offline"><![CDATA[Cash]]></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_balance"><![CDATA[Insufficient funds to write off.]]></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>
+
+    <!-- PayPal API payment provider -->
+    <string name="_bx_payment_pp_api_cpt"><![CDATA[PayPal API]]></string>
+    <string name="_bx_payment_pp_api_dsc"><![CDATA[PayPal payment provider (API based integration)]]></string>
+    <string name="_bx_payment_pp_api_active_cpt"><![CDATA[Active]]></string>
+    <string name="_bx_payment_pp_api_active_dsc"><![CDATA[Activate(Deactivate) provider]]></string>
+    <string name="_bx_payment_pp_api_hidden_cpt"><![CDATA[Hidden]]></string>
+    <string name="_bx_payment_pp_api_hidden_dsc"><![CDATA[Hide provider if you don't want to accept new payments but already have active subscriptions.]]></string>
+    <string name="_bx_payment_pp_api_mode_cpt"><![CDATA[Mode]]></string>
+    <string name="_bx_payment_pp_api_mode_dsc"><![CDATA[Mode to process payments]]></string>
+    <string name="_bx_payment_pp_api_mode_live"><![CDATA[live]]></string>
+    <string name="_bx_payment_pp_api_mode_test"><![CDATA[test]]></string>
+    <string name="_bx_payment_pp_api_live_account_cpt"><![CDATA[Account (live)]]></string>
+    <string name="_bx_payment_pp_api_live_account_dsc"><![CDATA[Email address which is used to access your PayPal account.]]></string>
+    <string name="_bx_payment_pp_api_live_client_id_cpt"><![CDATA[Client ID (live)]]></string>
+    <string name="_bx_payment_pp_api_live_client_id_dsc"><![CDATA[A part of application's credentials.]]></string>
+    <string name="_bx_payment_pp_api_live_secret_cpt"><![CDATA[Secret (live)]]></string>
+    <string name="_bx_payment_pp_api_live_secret_dsc"><![CDATA[A part of application's credentials.]]></string>
+    <string name="_bx_payment_pp_api_test_account_cpt"><![CDATA[Account (test)]]></string>
+    <string name="_bx_payment_pp_api_test_account_dsc"><![CDATA[Email address which is used to access your PayPal account.]]></string>
+    <string name="_bx_payment_pp_api_test_client_id_cpt"><![CDATA[Client ID (test)]]></string>
+    <string name="_bx_payment_pp_api_test_client_id_dsc"><![CDATA[A part of application's credentials.]]></string>
+    <string name="_bx_payment_pp_api_test_secret_cpt"><![CDATA[Secret (test)]]></string>
+    <string name="_bx_payment_pp_api_test_secret_dsc"><![CDATA[A part of application's credentials.]]></string>
+    <string name="_bx_payment_pp_api_return_data_url_cpt"><![CDATA[Data return URL]]></string>
+    <string name="_bx_payment_pp_api_notify_url_cpt"><![CDATA[Webhooks URL]]></string>
+    <string name="_bx_payment_pp_api_err_cannot_authorize"><![CDATA[Can't authorize the approved order.]]></string>
+    <string name="_bx_payment_pp_api_err_cannot_capture"><![CDATA[Can't finalize checkout.]]></string>
+    <string name="_bx_payment_pp_api_err_no_item"><![CDATA[There is nothing to subscribe.]]></string>
+    <string name="_bx_payment_pp_api_err_no_subscription"><![CDATA[The subscription data isn't available or incorrect.]]></string>
+    <string name="_bx_payment_pp_api_err_subscription_not_confirmed"><![CDATA[Subscription wasn't confirmed.]]></string>
+    <string name="_bx_payment_pp_api_msg_authorized"><![CDATA[The order was successfully authorized.]]></string>
+    <string name="_bx_payment_pp_api_msg_captured"><![CDATA[Payment was successfully processed.]]></string>
+    <string name="_bx_payment_pp_api_msg_subscribed"><![CDATA[Thank you! Subscription created. Please, check your email for further instructions.]]></string>
+    <string name="_bx_payment_txt_name_paypal_api"><![CDATA[PayPal]]></string>
+    <string name="_bx_payment_txt_cart_paypal_api"><![CDATA[PayPal]]></string>
+    <string name="_bx_payment_txt_subscribe_paypal_api"><![CDATA[PayPal]]></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_charged"><![CDATA[Payment was successfully processed.]]></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>
+
+    <!-- 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_authorized"><![CDATA[The order was successfully authorized.]]></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>

+ 51 - 0
modules/boonex/persons/updates/13.0.4_13.0.5/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' => 'Persons',
+    'version_from' => '13.0.4',
+    'version_to' => '13.0.5',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '13.0.0-B4'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/persons/updates/update_13.0.4_13.0.5/',
+    'home_uri' => 'persons_update_1304_1305',
+
+    'module_dir' => 'boonex/persons/',
+    'module_uri' => 'persons',
+
+    'db_prefix' => 'bx_persons_',
+    'class_prefix' => 'BxPersons',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_files' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Persons',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

+ 13 - 0
modules/boonex/persons/updates/13.0.4_13.0.5/install/installer.php

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

+ 6 - 0
modules/boonex/persons/updates/13.0.4_13.0.5/install/langs/en.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources name="en" flag="gb" title="English">
+	<string_del name="_bx_persons_menu_item_title_system_delete"><![CDATA[Delete]]></string_del>
+    <string_del name="_bx_persons_menu_item_title_delete"><![CDATA[Delete]]></string_del>
+	<string_del name="_bx_persons_grid_action_title_adm_delete"><![CDATA[Delete]]></string_del>
+</resources>

+ 7 - 0
modules/boonex/persons/updates/13.0.4_13.0.5/install/sql/enable.sql

@@ -0,0 +1,7 @@
+-- MENUS
+DELETE FROM `sys_menu_items` WHERE `set_name`='bx_persons_menu_manage_tools' AND `name`='delete';
+
+
+-- GRIDS
+DELETE FROM `sys_grid_actions` WHERE `object`='bx_persons_administration' AND `type`='bulk' AND `name`='delete';
+DELETE FROM `sys_grid_actions` WHERE `object`='bx_persons_common' AND `type`='bulk' AND `name`='delete';

+ 152 - 0
modules/boonex/persons/updates/13.0.4_13.0.5/source/install/config.php

@@ -0,0 +1,152 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Persons Persons
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_persons',
+    'title' => 'Persons',
+    'note' => 'Basic person profiles functionality.',
+    'version' => '13.0.5',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '13.0.0-B4'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/persons/',
+    'home_uri' => 'persons',
+
+    'db_prefix' => 'bx_persons_',
+    'class_prefix' => 'BxPersons',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Persons',
+
+    /**
+     * 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_persons_pictures'
+    ),
+
+	/**
+     * Transcoders.
+     */
+    'transcoders' => array(
+    	'bx_persons_icon',
+    	'bx_persons_thumb',
+    	'bx_persons_avatar',
+        'bx_persons_avatar_big',
+    	'bx_persons_picture',
+    	'bx_persons_cover',
+    	'bx_persons_cover_thumb',
+        'bx_persons_gallery'
+    ),
+
+    /**
+     * Extended Search Forms.
+     */
+    'esearches' => array(
+        'bx_persons',
+    	'bx_persons_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',
+    ),
+);
+
+/** @} */

+ 356 - 0
modules/boonex/persons/updates/13.0.4_13.0.5/source/install/langs/en.xml

@@ -0,0 +1,356 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources name="en" flag="gb" title="English">
+
+	<string name="_bx_persons"><![CDATA[Persons]]></string>
+	<string name="_bx_persons_cmts"><![CDATA[Persons' Comments]]></string>
+
+	<string name="_bx_persons_option_autoapproval"><![CDATA[Activate all persons automatically]]></string>
+	<string name="_bx_persons_option_default_acl_level"><![CDATA[Default member's level to assign after person's profile creation]]></string>
+  <string name="_bx_persons_option_enable_profile_activation_letter"><![CDATA[Enable profile activation letter]]></string>
+  <string name="_bx_persons_option_redirect_aadd"><![CDATA[Redirect after person's profile creation to]]></string>
+	<string name="_bx_persons_option_redirect_aadd_profile"><![CDATA[Profile Page]]></string>
+	<string name="_bx_persons_option_redirect_aadd_last"><![CDATA[Last Page]]></string>
+	<string name="_bx_persons_option_redirect_aadd_custom"><![CDATA[Custom Page]]></string>
+  <string name="_bx_persons_option_redirect_aadd_homepage"><![CDATA[Homepage]]></string>
+	<string name="_bx_persons_option_redirect_aadd_custom_url"><![CDATA[URL for 'Custom Page' redirect]]></string>
+  <string name="_bx_persons_option_activation_on"><![CDATA[After creation & after editing]]></string>
+  <string name="_bx_persons_option_activation_add"><![CDATA[After creation only]]></string>
+  <string name="_bx_persons_option_activation_edit"><![CDATA[After editing only]]></string>
+  <string name="_bx_persons_option_activation_off"><![CDATA[Manual activation]]></string>
+	<string name="_bx_persons_option_num_connections_quick"><![CDATA[Number of items in friends block]]></string>
+	<string name="_bx_persons_option_per_page_browse"><![CDATA[Number of items per page]]></string>
+	<string name="_bx_persons_option_num_rss"><![CDATA[Number of items in RSS feed]]></string>
+	<string name="_bx_persons_option_searchable_fields"><![CDATA[Searchable fields for keyword search]]></string>
+    <string name="_bx_persons_option_public_subscriptions"><![CDATA[Public following list]]></string>
+    <string name="_bx_persons_option_public_subscribed_me"><![CDATA[Public followers list]]></string>
+
+	<string name="_bx_persons_form_profile"><![CDATA[Persons]]></string>
+	<string name="_bx_persons_form_profile_display_add"><![CDATA[Add Person]]></string>
+	<string name="_bx_persons_form_profile_display_edit"><![CDATA[Edit Person]]></string>
+	<string name="_bx_persons_form_profile_display_edit_cover"><![CDATA[Edit Cover]]></string>
+	<string name="_bx_persons_form_profile_display_delete"><![CDATA[Delete Person]]></string>
+	<string name="_bx_persons_form_profile_display_view"><![CDATA[View Person]]></string>
+	<string name="_bx_persons_form_profile_display_view_full"><![CDATA[Full View Person]]></string>
+    <string name="_bx_persons_form_profile_input_sys_do_submit"><![CDATA[Submit]]></string>
+    <string name="_bx_persons_form_profile_input_submit"><![CDATA[Submit]]></string>
+    <string name="_bx_persons_form_profile_input_sys_allow_view_to"><![CDATA[Visible to]]></string>
+    <string name="_bx_persons_form_profile_input_allow_view_to"><![CDATA[Visible to]]></string>
+    <string name="_bx_persons_form_profile_input_sys_allow_post_to"><![CDATA[Who can post to my profile]]></string>
+    <string name="_bx_persons_form_profile_input_allow_post_to"><![CDATA[Who can post to my profile]]></string>
+    <string name="_bx_persons_form_profile_input_sys_allow_contact_to"><![CDATA[Who can contact me]]></string>
+    <string name="_bx_persons_form_profile_input_allow_contact_to"><![CDATA[Who can contact me]]></string>
+	<string name="_bx_persons_form_profile_input_sys_fullname"><![CDATA[Name]]></string>
+	<string name="_bx_persons_form_profile_input_fullname"><![CDATA[Name]]></string>
+    <string name="_bx_persons_form_profile_input_sys_last_name"><![CDATA[Last Name]]></string>
+	<string name="_bx_persons_form_profile_input_last_name"><![CDATA[Last Name]]></string>
+	<string name="_bx_persons_form_profile_input_fullname_err"><![CDATA[Profile name is mandatory and and cannot start with @]]></string>
+	<string name="_bx_persons_form_profile_input_sys_desc"><![CDATA[Description]]></string>
+	<string name="_bx_persons_form_profile_input_desc"><![CDATA[Description]]></string>
+	<string name="_bx_persons_form_profile_input_sys_picture"><![CDATA[Profile Picture]]></string>
+	<string name="_bx_persons_form_profile_input_picture"><![CDATA[Upload a profile picture]]></string>
+	<string name="_bx_persons_form_profile_input_picture_err"><![CDATA[Profile picture is mandatory.]]></string>
+	<string name="_bx_persons_form_profile_input_picture_search"><![CDATA[With photo]]></string>
+	<string name="_bx_persons_form_profile_input_online_search"><![CDATA[Online only]]></string>
+	<string name="_bx_persons_form_profile_input_sys_cover"><![CDATA[Cover Picture]]></string>
+	<string name="_bx_persons_form_profile_input_cover"><![CDATA[Upload New Cover Picture]]></string>
+	<string name="_bx_persons_form_profile_input_sys_delete_confirm"><![CDATA[Delete confirmation]]></string>
+	<string name="_bx_persons_form_profile_input_delete_confirm"><![CDATA[I am sure I want to delete this profile]]></string>
+	<string name="_bx_persons_form_profile_input_delete_confirm_info"><![CDATA[This action can not be undone.]]></string>
+	<string name="_bx_persons_form_profile_input_delete_confirm_error"><![CDATA[Please check this checkbox if you really want to delete your profile.]]></string>
+    <string name="_bx_persons_form_profile_input_sys_birthday"><![CDATA[Birthday]]></string>
+    <string name="_bx_persons_form_profile_input_birthday_err"><![CDATA[Age between 18 and 99]]></string>
+    <string name="_bx_persons_form_profile_input_birthday"><![CDATA[Birthday]]></string>
+    <string name="_bx_persons_form_profile_input_sys_gender"><![CDATA[Gender]]></string>
+    <string name="_bx_persons_form_profile_input_gender"><![CDATA[Gender]]></string>
+    <string name="_bx_persons_form_profile_input_sys_profile_email"><![CDATA[Email]]></string>
+    <string name="_bx_persons_form_profile_input_profile_email"><![CDATA[Email]]></string>
+    <string name="_bx_persons_form_profile_input_sys_profile_status"><![CDATA[Status]]></string>
+    <string name="_bx_persons_form_profile_input_profile_status"><![CDATA[Status]]></string>
+    <string name="_bx_persons_form_profile_input_sys_profile_ip"><![CDATA[IP]]></string>
+    <string name="_bx_persons_form_profile_input_profile_ip"><![CDATA[IP]]></string>
+    <string name="_bx_persons_form_profile_input_sys_skills"><![CDATA[Skills]]></string>
+    <string name="_bx_persons_form_profile_input_skills"><![CDATA[Skills]]></string>
+    <string name="_bx_persons_form_profile_input_sys_date_added"><![CDATA[Added]]></string>
+    <string name="_bx_persons_form_profile_input_date_added"><![CDATA[Added]]></string>
+    <string name="_bx_persons_form_profile_input_sys_date_changed"><![CDATA[Updated]]></string>
+    <string name="_bx_persons_form_profile_input_date_changed"><![CDATA[Updated]]></string>
+    <string name="_bx_persons_form_profile_input_sys_friends_count"><![CDATA[Friends count]]></string>
+    <string name="_bx_persons_form_profile_input_friends_count"><![CDATA[Friends count]]></string>
+    <string name="_bx_persons_form_profile_input_sys_followers_count"><![CDATA[Followers count]]></string>
+    <string name="_bx_persons_form_profile_input_followers_count"><![CDATA[Followers count]]></string>
+
+  <string name="_bx_persons_skills_form_profile"><![CDATA[Skills]]></string>
+  <string name="_bx_persons_skills_form_profile_display_add"><![CDATA[Add Skill]]></string>
+  <string name="_bx_persons_skills_form_profile_display_view"><![CDATA[View Skill]]></string>
+  <string name="_bx_persons_skills_form_profile_input_sys_skill_name"><![CDATA[Name]]></string>
+  <string name="_bx_persons_skills_form_profile_input_skill_name"><![CDATA[Name]]></string>
+  <string name="_bx_persons_skills_form_profile_input_skill_name_err"><![CDATA[This information is essential. Please, fill in this field.]]></string>
+
+	<string name="_bx_persons_acl_action_create_profile"><![CDATA[Create Person's Profile]]></string>
+	<string name="_bx_persons_acl_action_delete_profile"><![CDATA[Delete Person's Profile]]></string>
+	<string name="_bx_persons_acl_action_view_profile"><![CDATA[View Person's Profile]]></string>
+	<string name="_bx_persons_acl_action_edit_any_profile"><![CDATA[Edit Any Person's Profile]]></string>
+	<string name="_bx_persons_acl_action_delete_any_profile"><![CDATA[Delete Any Person's Profile]]></string>
+
+	<string name="_bx_persons_page_title_sys_create_profile"><![CDATA[Create a Profile - Person]]></string>
+	<string name="_bx_persons_page_title_create_profile"><![CDATA[Create a Profile - Person]]></string>
+	<string name="_bx_persons_page_title_sys_edit_profile"><![CDATA[Edit Profile]]></string>
+	<string name="_bx_persons_page_title_edit_profile"><![CDATA[Edit Profile]]></string>
+	<string name="_bx_persons_page_title_sys_edit_profile_cover"><![CDATA[Edit Cover]]></string>
+	<string name="_bx_persons_page_title_edit_profile_cover"><![CDATA[Edit Cover]]></string>
+	<string name="_bx_persons_page_title_sys_delete_profile"><![CDATA[Delete Profile]]></string>
+	<string name="_bx_persons_page_title_delete_profile"><![CDATA[Delete Profile]]></string>
+    <string name="_bx_persons_page_title_sys_view_profile"><![CDATA[View Profile]]></string>
+    <string name="_bx_persons_page_title_sys_view_profile_closed"><![CDATA[View Profile with Limited Visibility]]></string>
+	<string name="_bx_persons_page_title_view_profile"><![CDATA[{display_name}]]></string>
+	<string name="_bx_persons_page_title_browse"><![CDATA[People]]></string>
+	<string name="_bx_persons_page_title_browse_featured"><![CDATA[Featured People]]></string>
+	<string name="_bx_persons_page_title_browse_active"><![CDATA[Active People]]></string>
+	<string name="_bx_persons_page_title_browse_online"><![CDATA[Online People]]></string>
+	<string name="_bx_persons_page_title_browse_recent"><![CDATA[New People]]></string>
+	<string name="_bx_persons_page_title_browse_connections"><![CDATA[{0} connections]]></string>
+	<string name="_bx_persons_page_title_browse_connections_mutual"><![CDATA[{0} and {1} mutual connections]]></string>
+        <string name="_bx_persons_page_title_browse_familiar"><![CDATA[People You May Know]]></string>
+	<string name="_bx_persons_page_title_browse_favorites"><![CDATA[{0} favorites]]></string>
+	<string name="_bx_persons_page_title_browse_by_acl"><![CDATA[{0} People]]></string>
+	<string name="_bx_persons_page_title_browse_by_cmts"><![CDATA[People's Comments]]></string>
+	<string name="_bx_persons_page_title_sys_profile_favorites"><![CDATA[Favorite persons]]></string>
+	<string name="_bx_persons_page_title_profile_favorites"><![CDATA[Favorite persons]]></string>
+	<string name="_bx_persons_page_title_sys_profile_friends"><![CDATA[Friends]]></string>
+	<string name="_bx_persons_page_title_profile_friends"><![CDATA[Friends]]></string>
+	<string name="_bx_persons_page_title_sys_friend_requests"><![CDATA[Friend Requests]]></string>
+	<string name="_bx_persons_page_title_friend_requests"><![CDATA[Friend Requests]]></string>
+	<string name="_bx_persons_page_title_sys_profile_subscriptions"><![CDATA[Following]]></string>
+    <string name="_bx_persons_page_title_profile_subscriptions"><![CDATA[Following & Followers]]></string>
+    <string name="_bx_persons_page_title_sys_profile_relations"><![CDATA[Relationships]]></string>
+    <string name="_bx_persons_page_title_profile_relations"><![CDATA[Relationships]]></string>
+    <string name="_bx_persons_page_title_sys_profile_comments"><![CDATA[Comments]]></string>
+    <string name="_bx_persons_page_title_profile_comments"><![CDATA[Comments]]></string>
+	<string name="_bx_persons_page_title_sys_profile_info"><![CDATA[Profile Info]]></string>
+	<string name="_bx_persons_page_title_profile_info"><![CDATA[Info about {display_name}]]></string>
+	<string name="_bx_persons_page_title_sys_recent"><![CDATA[New People]]></string>
+	<string name="_bx_persons_page_title_recent"><![CDATA[New People]]></string>
+	<string name="_bx_persons_page_title_sys_manage"><![CDATA[Manage Own People]]></string>
+	<string name="_bx_persons_page_title_sys_manage_administration"><![CDATA[Manage All People]]></string>
+	<string name="_bx_persons_page_title_manage"><![CDATA[Manage People]]></string>
+	<string name="_bx_persons_page_title_sys_active"><![CDATA[Active People]]></string>
+	<string name="_bx_persons_page_title_active"><![CDATA[Active People]]></string>
+	<string name="_bx_persons_page_title_sys_online"><![CDATA[Online People]]></string>
+	<string name="_bx_persons_page_title_online"><![CDATA[Online People]]></string>
+	<string name="_bx_persons_page_title_sys_entries_search"><![CDATA[Search]]></string>
+    <string name="_bx_persons_page_title_entries_search"><![CDATA[Search]]></string>
+
+    <string name="_bx_persons_page_block_title_profile_private"><![CDATA[Private Profile]]></string>
+    <string name="_bx_persons_page_block_title_choose_type"><![CDATA[Choose Profile Type]]></string>
+    <string name="_bx_persons_page_block_title_create_profile"><![CDATA[Create a Profile - Person]]></string>
+    <string name="_bx_persons_page_block_title_edit_profile"><![CDATA[Edit Profile]]></string>
+    <string name="_bx_persons_page_block_title_edit_profile_cover"><![CDATA[Edit Cover]]></string>
+    <string name="_bx_persons_page_block_title_delete_profile"><![CDATA[Delete Profile]]></string>
+    <string name="_bx_persons_page_block_title_profile_all_actions"><![CDATA[All Actions]]></string>
+    <string name="_bx_persons_page_block_title_profile_info_link"><![CDATA[About <a href="{profile_link}">{display_name}</a>]]></string>
+    <string name="_bx_persons_page_block_title_profile_info"><![CDATA[Info]]></string>
+    <string name="_bx_persons_page_block_title_system_profile_info"><![CDATA[Info]]></string>
+    <string name="_bx_persons_page_block_title_profile_membership"><![CDATA[Membership]]></string>
+    <string name="_bx_persons_page_block_title_system_profile_membership"><![CDATA[Membership]]></string>
+    <string name="_bx_persons_page_block_title_profile_description"><![CDATA[Description]]></string>
+    <string name="_bx_persons_page_block_title_profile_favorites"><![CDATA[Favorite persons]]></string>
+    <string name="_bx_persons_page_block_title_system_profile_favorites"><![CDATA[Favorite persons]]></string>
+    <string name="_bx_persons_page_block_title_profile_friends_link"><![CDATA[Friends of <a href="{profile_link}">{display_name}</a>]]></string>
+    <string name="_bx_persons_page_block_title_profile_friends"><![CDATA[Friends]]></string>
+    <string name="_bx_persons_page_block_title_profile_friends_mutual"><![CDATA[Mutual Friends]]></string>
+    <string name="_bx_persons_page_block_title_system_profile_friends"><![CDATA[Friends]]></string>
+    <string name="_bx_persons_page_block_title_friend_requests_link"><![CDATA[Friend Requests for <a href="{profile_link}">{display_name}</a>]]></string>
+    <string name="_bx_persons_page_block_title_system_friend_requests"><![CDATA[Friend Requests]]></string>
+    <string name="_bx_persons_page_block_title_profile_location"><![CDATA[Location]]></string>
+    <string name="_bx_persons_page_block_title_system_profile_subscriptions"><![CDATA[Following]]></string>
+    <string name="_bx_persons_page_block_title_profile_subscriptions"><![CDATA[Following]]></string>
+    <string name="_bx_persons_page_block_title_system_profile_subscribed_me"><![CDATA[Followers]]></string>
+    <string name="_bx_persons_page_block_title_profile_subscribed_me"><![CDATA[Followers]]></string>
+    <string name="_bx_persons_page_block_title_system_profile_relations"><![CDATA[Relationships]]></string>
+    <string name="_bx_persons_page_block_title_profile_relations"><![CDATA[Relationships]]></string>
+    <string name="_bx_persons_page_block_title_system_profile_related_me"><![CDATA[Relationships with Me]]></string>
+    <string name="_bx_persons_page_block_title_profile_related_me"><![CDATA[Relationships with Me]]></string>
+    <string name="_bx_persons_page_block_title_profile_comments"><![CDATA[Comments]]></string>
+    <string name="_bx_persons_page_block_title_entry_reports"><![CDATA[Reports]]></string>
+    <string name="_bx_persons_page_block_title_profile_comments_link"><![CDATA[Comments to <a href="{entry_link}">{title}</a>]]></string>
+    <string name="_bx_persons_page_block_title_featured_profiles"><![CDATA[Featured People]]></string>
+    <string name="_bx_persons_page_block_title_profile_actions"><![CDATA[Actions]]></string>
+    <string name="_bx_persons_page_block_title_profile_calendar"><![CDATA[Calendar]]></string>
+    <string name="_bx_persons_page_block_title_latest_profiles"><![CDATA[New People]]></string>
+    <string name="_bx_persons_page_block_title_system_manage"><![CDATA[Manage Own People]]></string>
+    <string name="_bx_persons_page_block_title_system_manage_administration"><![CDATA[Manage All People]]></string>
+    <string name="_bx_persons_page_block_title_manage"><![CDATA[Manage People]]></string>
+    <string name="_bx_persons_page_block_title_sys_active_profiles"><![CDATA[Active People]]></string>
+    <string name="_bx_persons_page_block_title_active_profiles"><![CDATA[Active People]]></string>
+    <string name="_bx_persons_page_block_title_online_profiles"><![CDATA[Online People]]></string>
+    <string name="_bx_persons_page_block_title_sys_familiar_profiles"><![CDATA[Familiar People]]></string>
+    <string name="_bx_persons_page_block_title_familiar_profiles"><![CDATA[People You May Know]]></string>
+    <string name="_bx_persons_page_block_title_search_form"><![CDATA[Search Form]]></string>
+    <string name="_bx_persons_page_block_title_search_results"><![CDATA[Search Results]]></string>
+    <string name="_bx_persons_page_block_title_search_form_cmts"><![CDATA[Comments Search Form]]></string>
+    <string name="_bx_persons_page_block_title_search_results_cmts"><![CDATA[Comments Search Results]]></string>
+    <string name="_bx_persons_page_block_title_sys_featured_entries_view_showcase"><![CDATA[Featured People (Showcase View)]]></string>
+    <string name="_bx_persons_page_block_title_featured_entries_view_showcase"><![CDATA[Featured People]]></string>
+    <string name="_bx_persons_page_block_title_sys_recommended_entries_view_showcase"><![CDATA[Recommended People (Showcase View)]]></string>
+    <string name="_bx_persons_page_block_title_recommended_entries_view_showcase"><![CDATA[Recommended People]]></string>
+    <string name="_bx_persons_page_block_title_sys_active_entries_view_showcase"><![CDATA[Active People (Showcase View)]]></string>
+    <string name="_bx_persons_page_block_title_active_entries_view_showcase"><![CDATA[Active People]]></string>
+	
+	<string name="_bx_persons_page_block_title_sys_cover_block"><![CDATA[Cover]]></string>
+    <string name="_bx_persons_page_block_title_cover_block"><![CDATA[Cover]]></string>
+
+    <string name="_bx_persons_menu_title_submenu"><![CDATA[Persons Submenu]]></string>
+    <string name="_bx_persons_menu_set_title_submenu"><![CDATA[Persons Submenu]]></string>
+    <string name="_bx_persons_menu_set_title_view_profile_actions"><![CDATA[Person Actions]]></string>
+    <string name="_bx_persons_menu_title_view_profile_actions"><![CDATA[Person Actions]]></string>
+    <string name="_bx_persons_menu_set_title_view_profile_actions_more"><![CDATA[Person More Actions]]></string>
+    <string name="_bx_persons_menu_title_view_profile_actions_more"><![CDATA[Person More Actions]]></string>
+    <string name="_bx_persons_menu_title_view_profile_meta"><![CDATA[Person Meta]]></string>
+    <string name="_bx_persons_menu_set_title_view_profile_meta"><![CDATA[Person Meta]]></string>
+    <string name="_bx_persons_menu_set_title_view_profile_submenu"><![CDATA[View Person Submenu]]></string>
+    <string name="_bx_persons_menu_title_view_profile_submenu"><![CDATA[View Person Submenu]]></string>
+    <string name="_bx_persons_menu_set_title_manage_tools"><![CDATA[Manage Tools Submenu]]></string>
+    <string name="_bx_persons_menu_title_manage_tools"><![CDATA[Manage Tools Submenu]]></string>
+    <string name="_bx_persons_menu_item_title_system_delete_with_content"><![CDATA[Delete With Content]]></string>
+    <string name="_bx_persons_menu_item_title_delete_with_content"><![CDATA[Delete With Content]]></string>
+    <string name="_bx_persons_menu_item_title_system_clear_reports"><![CDATA[Clear reports]]></string>
+    <string name="_bx_persons_menu_item_title_clear_reports"><![CDATA[Clear reports]]></string>
+    <string name="_bx_persons_menu_item_title_system_manage_cf"><![CDATA[Manage audience]]></string>
+    <string name="_bx_persons_menu_item_title_manage_cf"><![CDATA[Manage audience]]></string>
+    <string name="_bx_persons_menu_item_title_system_edit_cover"><![CDATA[Edit Cover]]></string>
+    <string name="_bx_persons_menu_item_title_edit_cover"><![CDATA[Edit Cover]]></string>
+    <string name="_bx_persons_menu_item_title_system_edit_profile"><![CDATA[Edit Person]]></string>
+    <string name="_bx_persons_menu_item_title_edit_profile"><![CDATA[Edit Profile]]></string>
+    <string name="_bx_persons_menu_item_title_system_delete_profile"><![CDATA[Delete Person]]></string>
+    <string name="_bx_persons_menu_item_title_delete_profile"><![CDATA[Delete Profile]]></string>
+    <string name="_bx_persons_menu_item_title_system_delete_account"><![CDATA[Delete Account]]></string>
+    <string name="_bx_persons_menu_item_title_delete_account"><![CDATA[Delete Account]]></string>
+    <string name="_bx_persons_menu_item_title_system_delete_account_content"><![CDATA[Delete Account with Content]]></string>
+    <string name="_bx_persons_menu_item_title_delete_account_content"><![CDATA[Delete Account with Content]]></string>
+    <string name="_bx_persons_menu_item_title_system_profile_type"><![CDATA[Person]]></string>
+    <string name="_bx_persons_menu_item_title_profile_type"><![CDATA[Person]]></string>
+    <string name="_bx_persons_menu_item_title_system_create_profile"><![CDATA[Person]]></string>
+    <string name="_bx_persons_menu_item_title_create_profile"><![CDATA[Person]]></string>
+    <string name="_bx_persons_menu_item_title_system_view_profile_friends"><![CDATA[Friends]]></string>
+    <string name="_bx_persons_menu_item_title_view_profile_friends"><![CDATA[Friends]]></string>
+    <string name="_bx_persons_menu_item_title_system_view_profile_relations"><![CDATA[Relationships]]></string>
+    <string name="_bx_persons_menu_item_title_view_profile_relations"><![CDATA[Relationships]]></string>
+    <string name="_bx_persons_menu_item_title_system_view_profile_subscriptions"><![CDATA[Following]]></string>
+    <string name="_bx_persons_menu_item_title_view_profile_subscriptions"><![CDATA[Following]]></string>
+    <string name="_bx_persons_menu_item_title_system_view_profile_comments"><![CDATA[Comments]]></string>
+    <string name="_bx_persons_menu_item_title_view_profile_comments"><![CDATA[Comments]]></string>
+    <string name="_bx_persons_menu_item_title_system_view_profile_info"><![CDATA[Info]]></string>
+    <string name="_bx_persons_menu_item_title_view_profile_info"><![CDATA[Info]]></string>
+    <string name="_bx_persons_menu_item_title_system_view_profile_view"><![CDATA[Profile]]></string>
+    <string name="_bx_persons_menu_item_title_view_profile_view"><![CDATA[Profile]]></string>
+    <string name="_bx_persons_menu_item_title_system_view_profile_more_auto"><![CDATA[More]]></string>
+    <string name="_bx_persons_menu_item_title_view_profile_more_auto"><![CDATA[More]]></string>
+    <string name="_bx_persons_menu_item_title_system_befriend"><![CDATA[Add friend]]></string>
+    <string name="_bx_persons_menu_item_title_befriend"><![CDATA[Add friend]]></string>
+    <string name="_bx_persons_menu_item_title_befriend_sent"><![CDATA[Add friend (requested)]]></string>
+    <string name="_bx_persons_menu_item_title_befriend_confirm"><![CDATA[Accept friend request]]></string>
+    <string name="_bx_persons_menu_item_title_system_unfriend"><![CDATA[Unfriend]]></string>
+    <string name="_bx_persons_menu_item_title_unfriend"><![CDATA[Unfriend]]></string>
+    <string name="_bx_persons_menu_item_title_unfriend_cancel_request"><![CDATA[Cancel friend request]]></string>
+    <string name="_bx_persons_menu_item_title_unfriend_reject_request"><![CDATA[Reject friend request]]></string>
+    <string name="_bx_persons_menu_item_title_system_subscribe"><![CDATA[Follow]]></string>
+    <string name="_bx_persons_menu_item_title_subscribe"><![CDATA[Follow]]></string>
+    <string name="_bx_persons_menu_item_title_system_unsubscribe"><![CDATA[Unfollow]]></string>
+    <string name="_bx_persons_menu_item_title_unsubscribe"><![CDATA[Unfollow]]></string>
+    <string name="_bx_persons_menu_item_title_system_relation_add"><![CDATA[Add Relationship]]></string>
+    <string name="_bx_persons_menu_item_title_relation_add"><![CDATA[Add Relationship]]></string>
+    <string name="_bx_persons_menu_item_title_system_relation_delete"><![CDATA[Remove Relationship]]></string>
+    <string name="_bx_persons_menu_item_title_relation_delete"><![CDATA[Remove Relationship]]></string>
+    <string name="_bx_persons_menu_item_title_system_more_actions"><![CDATA[More Actions]]></string>
+    <string name="_bx_persons_menu_item_title_more_actions"><![CDATA[]]></string>
+    <string name="_bx_persons_menu_item_title_system_friends"><![CDATA[Friends]]></string>
+    <string name="_bx_persons_menu_item_title_friends"><![CDATA[Friends]]></string>
+    <string name="_bx_persons_menu_item_title_system_relations"><![CDATA[Relationships]]></string>
+    <string name="_bx_persons_menu_item_title_relations"><![CDATA[Relationships]]></string>
+    <string name="_bx_persons_menu_item_title_system_friend_requests"><![CDATA[Friend requests number]]></string>
+    <string name="_bx_persons_menu_item_title_friend_requests"><![CDATA[Friend requests]]></string>
+    <string name="_bx_persons_menu_item_title_system_manage_my_profiles"><![CDATA[My profiles]]></string>
+    <string name="_bx_persons_menu_item_title_manage_my_profiles"><![CDATA[Profiles]]></string>
+    <string name="_bx_persons_menu_item_title_system_favorites"><![CDATA[Favorite Persons]]></string>
+    <string name="_bx_persons_menu_item_title_favorites"><![CDATA[Favorite persons]]></string>    
+    <string name="_bx_persons_menu_item_title_system_subscriptions"><![CDATA[Following]]></string>
+    <string name="_bx_persons_menu_item_title_subscriptions"><![CDATA[Following]]></string>
+    <string name="_bx_persons_menu_item_title_system_subscribed_me"><![CDATA[Followers]]></string>
+    <string name="_bx_persons_menu_item_title_subscribed_me"><![CDATA[Followers]]></string>
+    <string name="_bx_persons_menu_item_title_system_relations"><![CDATA[Relationships]]></string>
+    <string name="_bx_persons_menu_item_title_relations"><![CDATA[Relationships]]></string>
+    <string name="_bx_persons_menu_item_title_system_related_me"><![CDATA[Relationships with Me]]></string>
+    <string name="_bx_persons_menu_item_title_related_me"><![CDATA[Relationships with Me]]></string>
+    <string name="_bx_persons_menu_item_title_system_followings"><![CDATA[Persons]]></string>
+    <string name="_bx_persons_menu_item_title_followings"><![CDATA[Persons]]></string>
+    <string name="_bx_persons_menu_item_title_system_entries_recent"><![CDATA[New]]></string>
+    <string name="_bx_persons_menu_item_title_entries_recent"><![CDATA[New]]></string>
+    <string name="_bx_persons_menu_item_title_system_entries_search"><![CDATA[Search]]></string>
+    <string name="_bx_persons_menu_item_title_entries_search"><![CDATA[Search]]></string>
+    <string name="_bx_persons_menu_item_title_system_entries_manage"><![CDATA[Manage]]></string>
+    <string name="_bx_persons_menu_item_title_entries_manage"><![CDATA[Manage]]></string>
+    <string name="_bx_persons_menu_item_title_system_entries_home"><![CDATA[Persons]]></string>
+    <string name="_bx_persons_menu_item_title_entries_home"><![CDATA[People]]></string>
+	<string name="_bx_persons_menu_item_title_system_admt_persons"><![CDATA[Profiles]]></string>
+	<string name="_bx_persons_menu_item_title_admt_persons"><![CDATA[Profiles]]></string>
+	<string name="_bx_persons_menu_item_title_manage_my"><![CDATA[My Profiles]]></string>
+	<string name="_bx_persons_menu_item_title_manage_all"><![CDATA[All Profiles]]></string>   
+	<string name="_bx_persons_menu_item_title_system_entries_active"><![CDATA[Active]]></string>
+	<string name="_bx_persons_menu_item_title_entries_active"><![CDATA[Active]]></string>
+	<string name="_bx_persons_menu_item_title_system_entries_online"><![CDATA[Online]]></string>
+	<string name="_bx_persons_menu_item_title_entries_online"><![CDATA[Online]]></string>
+
+    <string name="_bx_persons_grid_filter_item_title_adm_select_one_filter1"><![CDATA[All Statuses]]></string>
+    <string name="_bx_persons_grid_filter_item_title_adm_select_one_filter2"><![CDATA[All]]></string>
+    <string name="_bx_persons_grid_filter_item_title_adm_active"><![CDATA[Active]]></string>
+    <string name="_bx_persons_grid_filter_item_title_adm_pending"><![CDATA[Pending]]></string>
+    <string name="_bx_persons_grid_filter_item_title_adm_suspended"><![CDATA[Suspended]]></string>
+    <string name="_bx_persons_grid_filter_item_title_adm_unconfirmed"><![CDATA[Unconfirmed]]></string>
+    <string name="_bx_persons_grid_column_title_adm_active"><![CDATA[Active]]></string>
+    <string name="_bx_persons_grid_column_title_adm_fullname"><![CDATA[Name]]></string>
+    <string name="_bx_persons_grid_column_title_adm_last_online"><![CDATA[Last Logged]]></string>
+    <string name="_bx_persons_grid_column_title_adm_account"><![CDATA[Account]]></string>
+    <string name="_bx_persons_grid_action_title_adm_delete_with_content"><![CDATA[Delete With Content]]></string>
+    <string name="_bx_persons_grid_action_title_adm_clear_reports"><![CDATA[Clear reports]]></string>
+    <string name="_bx_persons_grid_action_title_adm_set_acl_level"><![CDATA[Set Membership]]></string>
+    <string name="_bx_persons_grid_action_title_adm_more_actions"><![CDATA[More Actions]]></string>
+    <string name="_bx_persons_grid_action_title_adm_audit_content"><![CDATA[Audit actions with profile]]></string>
+    <string name="_bx_persons_grid_action_title_adm_audit_profile"><![CDATA[Audit profile actions]]></string>
+    <string name="_bx_persons_grid_action_title_adm_manage_cf"><![CDATA[Manage audience]]></string>
+    
+    <string name="_bx_persons_grid_action_err_delete"><![CDATA[Cannot delete the selected person(s).]]></string>
+    <string name="_bx_persons_grid_txt_account_manager"><![CDATA[Redirect to manage account.]]></string>
+
+    <string name="_bx_persons_chart_growth"><![CDATA[Persons: Growth]]></string>
+    <string name="_bx_persons_chart_growth_speed"><![CDATA[Persons: Growth Speed]]></string>
+
+    <string name="_bx_persons_search_extended"><![CDATA[Persons Search]]></string>
+    <string name="_bx_persons_search_extended_cmts"><![CDATA[Persons Comments Search]]></string>
+
+    <string name="_bx_persons_alert_action_profile_cover_changed"><![CDATA[cover changed]]></string>
+    <string name="_bx_persons_alert_action_profile_picture_changed"><![CDATA[picture changed]]></string>
+
+    <string name="_bx_persons_txt_account_pending"><![CDATA[This profile is pending approval, please wait until it is activated.]]></string>
+    <string name="_bx_persons_txt_account_pending_moderation"><![CDATA[This <a href="{0}">profile</a> is pending approval.]]></string>
+    <string name="_bx_persons_txt_account_suspended"><![CDATA[This profile is suspended.]]></string>
+    <string name="_bx_persons_txt_account_suspended_moderation"><![CDATA[This <a href="{0}">profile</a> is suspended.]]></string>
+    <string name="_bx_persons_txt_N_friends"><![CDATA[{0} friends]]></string>
+    <string name="_bx_persons_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> profile timeline]]></string>
+    <string name="_bx_persons_txt_sample_single"><![CDATA[person]]></string>
+    <string name="_bx_persons_txt_sample_comment_single"><![CDATA[comment to person]]></string>
+    <string name="_bx_persons_txt_sample_vote_single"><![CDATA[vote to person]]></string>
+    <string name="_bx_persons_txt_sample_score_up_single"><![CDATA[score up vote to person]]></string>
+    <string name="_bx_persons_txt_sample_score_down_single"><![CDATA[score down vote to person]]></string>
+    <string name="_bx_persons_txt_sample_pp_single"><![CDATA[profile picture]]></string>
+    <string name="_bx_persons_txt_sample_pp_single_with_article"><![CDATA[a profile picture]]></string>
+    <string name="_bx_persons_txt_sample_pc_single"><![CDATA[profile cover]]></string>
+    <string name="_bx_persons_txt_sample_pc_single_with_article"><![CDATA[a profile cover]]></string>
+    <string name="_bx_persons_txt_sample_pi_action"><![CDATA[changed {0}]]></string>
+    <string name="_bx_persons_txt_sample_pi_action_user"><![CDATA[{0} changed {1}]]></string>
+
+    <string name="_bx_persons_email_friend_request"><![CDATA[Friend request]]></string>
+    <string name="_bx_persons_email_friend_request_subject"><![CDATA[Friendship Request]]></string>
+    <string name="_bx_persons_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>
+</resources>

+ 567 - 0
modules/boonex/persons/updates/13.0.4_13.0.5/source/install/sql/enable.sql

@@ -0,0 +1,567 @@
+
+-- SETTINGS
+
+SET @iTypeOrder = (SELECT MAX(`order`) FROM `sys_options_types` WHERE `group` = 'modules');
+INSERT INTO `sys_options_types`(`group`, `name`, `caption`, `icon`, `order`) VALUES 
+('modules', 'bx_persons', '_bx_persons', 'bx_persons@modules/boonex/persons/|std-icon.svg', IF(ISNULL(@iTypeOrder), 1, @iTypeOrder + 1));
+SET @iTypeId = LAST_INSERT_ID();
+
+INSERT INTO `sys_options_categories` (`type_id`, `name`, `caption`, `order`)
+VALUES (@iTypeId, 'bx_persons', '_bx_persons', 1);
+SET @iCategId = LAST_INSERT_ID();
+
+INSERT INTO `sys_options` (`name`, `value`, `category_id`, `caption`, `type`, `extra`, `check`, `check_error`, `order`) VALUES
+('bx_persons_autoapproval', 'on', @iCategId, '_bx_persons_option_autoapproval', 'select', 'a:2:{s:6:"module";s:10:"bx_persons";s:6:"method";s:22:"get_options_activation";}', '', '', 1),
+('bx_persons_default_acl_level', '3', @iCategId, '_bx_persons_option_default_acl_level', 'select', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:15:"get_memberships";s:6:"params";a:4:{s:11:"purchasable";b:0;s:6:"active";b:1;s:9:"translate";b:1;s:22:"filter_out_auto_levels";b:1;}s:5:"class";s:16:"TemplAclServices";}', '', '', 2),
+('bx_persons_redirect_aadd', 'profile', @iCategId, '_bx_persons_option_redirect_aadd', 'select', 'a:2:{s:6:"module";s:10:"bx_persons";s:6:"method";s:30:"get_options_redirect_after_add";}', '', '', 3),
+('bx_persons_redirect_aadd_custom_url', '', @iCategId, '_bx_persons_option_redirect_aadd_custom_url', 'digit', '', '', '', 4),
+('bx_persons_num_connections_quick', '6', @iCategId, '_bx_persons_option_num_connections_quick', 'digit', '', '', '', 10),
+('bx_persons_per_page_browse', '24', @iCategId, '_bx_persons_option_per_page_browse', 'digit', '', '', '', 11),
+('bx_persons_num_rss', '10', @iCategId, '_bx_persons_option_num_rss', 'digit', '', '', '', 12),
+('bx_persons_per_page_browse_showcase', '32', @iCategId, '_sys_option_per_page_browse_showcase', 'digit', '', '', '', 15),
+('bx_persons_per_page_browse_recommended', '10', @iCategId, '_sys_option_per_page_browse_recommended', 'digit', '', '', '', 16),
+('bx_persons_searchable_fields', 'fullname,description', @iCategId, '_bx_persons_option_searchable_fields', 'list', 'a:2:{s:6:"module";s:10:"bx_persons";s:6:"method";s:21:"get_searchable_fields";}', '', '', 20),
+('bx_persons_public_subscriptions', '', @iCategId, '_bx_persons_option_public_subscriptions', 'checkbox', '', '', '', 30),
+('bx_persons_public_subscribed_me', '', @iCategId, '_bx_persons_option_public_subscribed_me', 'checkbox', '', '', '', 31),
+('bx_persons_enable_profile_activation_letter', 'on', @iCategId, '_bx_persons_option_enable_profile_activation_letter', 'checkbox', '', '', '', 32);
+
+-- PAGES
+
+-- PAGE: create profile
+
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_persons_create_profile', 'create-persons-profile', '_bx_persons_page_title_sys_create_profile', '_bx_persons_page_title_create_profile', 'bx_persons', 5, 2147483647, 1, 'page.php?i=create-persons-profile', '', '', '', 0, 1, 0, '', '');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_persons_create_profile', 1, 'bx_persons', '_bx_persons_page_block_title_choose_type', 11, 2147483647, 'menu', 'sys_add_profile_vertical', 0, 1, 0, 0),
+('bx_persons_create_profile', 1, 'bx_persons', '_bx_persons_page_block_title_create_profile', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:13:\"entity_create\";}', 0, 1, 1, 1);
+
+-- PAGE: view profile
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_persons_view_profile', 'view-persons-profile', '_bx_persons_page_title_sys_view_profile', '_bx_persons_page_title_view_profile', 'bx_persons', 7, 2147483647, 1, 'page.php?i=view-persons-profile', '', '', '', 0, 1, 0, 'BxPersonsPageEntry', 'modules/boonex/persons/classes/BxPersonsPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES
+('bx_persons_view_profile', 0, 'bx_persons', '_bx_persons_page_block_title_sys_cover_block', '_bx_persons_page_block_title_cover_block', 3, 2147483647, 'service', 'a:2:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:12:\"entity_cover\";}', 0, 0, 1, 0),
+('bx_persons_view_profile', 0, 'bx_persons', '', '_bx_persons_page_block_title_profile_friends_mutual', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:22:\"profile_friends_mutual\";}', 0, 0, 1, 0),
+('bx_persons_view_profile', 2, 'bx_persons', '', '_bx_persons_page_block_title_profile_subscriptions', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:21:\"profile_subscriptions\";}', 0, 1, 0, 0),
+('bx_persons_view_profile', 2, 'bx_persons', '', '_bx_persons_page_block_title_profile_subscribed_me', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:21:\"profile_subscribed_me\";}', 0, 1, 0, 0),
+('bx_persons_view_profile', 2, 'bx_persons', '', '_bx_persons_page_block_title_profile_related_me', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:10:"bx_persons";s:6:"method";s:18:"profile_related_me";}', 0, 1, 0, 0),
+('bx_persons_view_profile', 2, 'bx_persons', '', '_bx_persons_page_block_title_profile_comments', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:15:\"entity_comments\";}', 0, 0, 0, 0),
+('bx_persons_view_profile', 2, 'bx_persons', '', '_bx_persons_page_block_title_profile_description', 13, 2147483647, 'service', 'a:2:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:17:\"entity_text_block\";}', 0, 0, 1, 1),
+('bx_persons_view_profile', 2, 'bx_persons', '', '_bx_persons_page_block_title_profile_friends', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:15:\"profile_friends\";}', 0, 1, 1, 2),
+('bx_persons_view_profile', 2, 'bx_persons', '', '_bx_persons_page_block_title_profile_relations', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:10:"bx_persons";s:6:"method";s:17:"profile_relations";}', 0, 1, 1, 3),
+('bx_persons_view_profile', 2, 'bx_persons', '', '_bx_persons_page_block_title_profile_calendar', 13, 2147483647, 'service', 'a:2:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:15:\"entity_calendar\";}', 0, 0, 0, 4),
+('bx_persons_view_profile', 3, 'bx_persons', '', '_bx_persons_page_block_title_profile_location', 13, 2147483647, 'service', 'a:2:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:15:\"entity_location\";}', 0, 0, 0, 0),
+('bx_persons_view_profile', 3, 'bx_persons', '', '_bx_persons_page_block_title_profile_info', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:11:\"entity_info\";}', 0, 0, 1, 1),
+('bx_persons_view_profile', 3, 'bx_persons', '', '_bx_persons_page_block_title_profile_all_actions', 13, 2147483647, 'service', 'a:2:{s:6:"module";s:10:"bx_persons";s:6:"method";s:18:"entity_all_actions";}', 0, 0, 0, 0),
+('bx_persons_view_profile', 3, 'bx_persons', '', '_bx_persons_page_block_title_profile_membership', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:18:\"profile_membership\";}', 0, 0, 1, 2),
+('bx_persons_view_profile', 3, 'bx_persons', '', '_bx_persons_page_block_title_profile_location', 3, 2147483647, 'service', 'a:4:{s:6:\"module\";s:6:\"system\";s:6:\"method\";s:13:\"locations_map\";s:6:\"params\";a:2:{i:0;s:10:\"bx_persons\";i:1;s:12:\"{content_id}\";}s:5:\"class\";s:20:\"TemplServiceMetatags\";}', 0, 0, 1, 3),
+('bx_persons_view_profile', 2, 'bx_persons', '', '_bx_persons_page_block_title_entry_reports', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:14:\"entity_reports\";}', 0, 0, 1, 6);
+
+-- PAGE: view closed profile 
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_persons_view_profile_closed', 'view-person-profile-closed', '_bx_persons_page_title_sys_view_profile_closed', '_bx_persons_page_title_view_profile', 'bx_persons', 10, 2147483647, 1, 'page.php?i=view-person-profile', '', '', '', 0, 1, 0, 'BxPersonsPageEntry', 'modules/boonex/persons/classes/BxPersonsPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_persons_view_profile_closed', 1, 'bx_persons', '', '_bx_persons_page_block_title_profile_private', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:19:\"private_profile_msg\";}', 0, 1, 1, 0);
+
+-- PAGE: edit profile
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_persons_edit_profile', 'edit-persons-profile', '_bx_persons_page_title_sys_edit_profile', '_bx_persons_page_title_edit_profile', 'bx_persons', 5, 2147483647, 1, 'page.php?i=edit-persons-profile', '', '', '', 0, 1, 0, 'BxPersonsPageEntry', 'modules/boonex/persons/classes/BxPersonsPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_persons_edit_profile', 1, 'bx_persons', '_bx_persons_page_block_title_edit_profile', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:11:\"entity_edit\";}', 0, 0, 0);
+
+-- PAGE: edit profile cover
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_persons_edit_profile_cover', 'edit-persons-cover', '_bx_persons_page_title_sys_edit_profile_cover', '_bx_persons_page_title_edit_profile_cover', 'bx_persons', 5, 2147483647, 1, 'page.php?i=edit-persons-cover', '', '', '', 0, 1, 0, 'BxPersonsPageEntry', 'modules/boonex/persons/classes/BxPersonsPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_persons_edit_profile_cover', 1, 'bx_persons', '_bx_persons_page_block_title_edit_profile_cover', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:17:\"entity_edit_cover\";}', 0, 0, 0);
+
+-- PAGE: delete profile
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_persons_delete_profile', 'delete-persons-profile', '_bx_persons_page_title_sys_delete_profile', '_bx_persons_page_title_delete_profile', 'bx_persons', 5, 2147483647, 1, 'page.php?i=delete-persons-profile', '', '', '', 0, 1, 0, 'BxPersonsPageEntry', 'modules/boonex/persons/classes/BxPersonsPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_persons_delete_profile', 1, 'bx_persons', '_bx_persons_page_block_title_delete_profile', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:13:\"entity_delete\";}', 0, 0, 0);
+
+-- PAGE: profile info
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_persons_profile_info', 'persons-profile-info', '_bx_persons_page_title_sys_profile_info', '_bx_persons_page_title_profile_info', 'bx_persons', 5, 2147483647, 1, 'page.php?i=persons-profile-info', '', '', '', 0, 1, 0, 'BxPersonsPageEntry', 'modules/boonex/persons/classes/BxPersonsPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_persons_profile_info', 1, 'bx_persons', '_bx_persons_page_block_title_system_profile_info', '_bx_persons_page_block_title_profile_info_link', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:16:\"entity_info_full\";}', 0, 0, 1, 1),
+('bx_persons_profile_info', 1, 'bx_persons', '', '_bx_persons_page_block_title_profile_description', 13, 2147483647, 'service', 'a:2:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:17:\"entity_text_block\";}', 0, 0, 1, 2);
+
+-- PAGE: profile friends
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_persons_profile_friends', 'persons-profile-friends', '_bx_persons_page_title_sys_profile_friends', '_bx_persons_page_title_profile_friends', 'bx_persons', 5, 2147483647, 1, 'page.php?i=persons-profile-friends', '', '', '', 0, 1, 0, 'BxPersonsPageEntry', 'modules/boonex/persons/classes/BxPersonsPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_persons_profile_friends', 1, 'bx_persons', '_bx_persons_page_block_title_system_profile_friends', '_bx_persons_page_block_title_profile_friends_link', 11, 2147483647, 'service', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:17:"connections_table";s:6:"params";a:1:{i:0;s:12:"{profile_id}";}s:5:"class";s:23:"TemplServiceConnections";}', 0, 0, 1, 1);
+
+-- PAGE: profile friend requests
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_persons_friend_requests', 'persons-friend-requests', '_bx_persons_page_title_sys_friend_requests', '_bx_persons_page_title_friend_requests', 'bx_persons', 5, 2147483647, 1, 'page.php?i=persons-friend-requests', '', '', '', 0, 1, 0, 'BxPersonsPageEntry', 'modules/boonex/persons/classes/BxPersonsPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_persons_friend_requests', 1, 'bx_persons', '_bx_persons_page_block_title_system_friend_requests', '_bx_persons_page_block_title_friend_requests_link', 11, 2147483647, 'service', 'a:3:{s:6:\"module\";s:6:\"system\";s:6:\"method\";s:25:\"connections_request_table\";s:5:\"class\";s:23:\"TemplServiceConnections\";}', 0, 0, 1, 1);
+
+-- PAGE: profile favorites
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_persons_profile_favorites', 'persons-profile-favorites', '_bx_persons_page_title_sys_profile_favorites', '_bx_persons_page_title_profile_favorites', 'bx_persons', 5, 2147483647, 1, 'page.php?i=persons-profile-favorites', '', '', '', 0, 1, 0, 'BxPersonsPageBrowse', 'modules/boonex/persons/classes/BxPersonsPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_persons_profile_favorites', 1, 'bx_persons', '_bx_persons_page_block_title_system_profile_favorites', '_bx_persons_page_block_title_profile_favorites', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:10:"bx_persons";s:6:"method";s:15:"browse_favorite";}', 0, 1, 1, 1);
+
+-- PAGE: profile subscriptions
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_persons_profile_subscriptions', 'persons-profile-subscriptions', '_bx_persons_page_title_sys_profile_subscriptions', '_bx_persons_page_title_profile_subscriptions', 'bx_persons', 5, 2147483647, 1, 'page.php?i=persons-profile-subscriptions', '', '', '', 0, 1, 0, 'BxPersonsPageEntry', 'modules/boonex/persons/classes/BxPersonsPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_persons_profile_subscriptions', 1, 'bx_persons', '_bx_persons_page_block_title_system_profile_subscriptions', '_bx_persons_page_block_title_profile_subscriptions', 11, 2147483647, 'service', 'a:3:{s:6:\"module\";s:6:\"system\";s:6:\"method\";s:19:\"subscriptions_table\";s:5:\"class\";s:23:\"TemplServiceConnections\";}', 0, 0, 1, 1),
+('bx_persons_profile_subscriptions', 1, 'bx_persons', '_bx_persons_page_block_title_system_profile_subscribed_me', '_bx_persons_page_block_title_profile_subscribed_me', 11, 2147483647, 'service', 'a:3:{s:6:\"module\";s:6:\"system\";s:6:\"method\";s:19:\"subscribed_me_table\";s:5:\"class\";s:23:\"TemplServiceConnections\";}', 0, 0, 1, 2);
+
+-- PAGE: profile relations
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_persons_profile_relations', 'persons-profile-relations', '_bx_persons_page_title_sys_profile_relations', '_bx_persons_page_title_profile_relations', 'bx_persons', 5, 2147483647, 1, 'page.php?i=persons-profile-relations', '', '', '', 0, 1, 0, 'BxPersonsPageEntry', 'modules/boonex/persons/classes/BxPersonsPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_persons_profile_relations', 1, 'bx_persons', '_bx_persons_page_block_title_system_profile_relations', '_bx_persons_page_block_title_profile_relations', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:6:"system";s:6:"method";s:15:"relations_table";s:5:"class";s:23:"TemplServiceConnections";}', 0, 0, 1, 1),
+('bx_persons_profile_relations', 1, 'bx_persons', '_bx_persons_page_block_title_system_profile_related_me', '_bx_persons_page_block_title_profile_related_me', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:6:"system";s:6:"method";s:16:"related_me_table";s:5:"class";s:23:"TemplServiceConnections";}', 0, 0, 1, 2);
+
+-- PAGE: view entry comments
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_persons_profile_comments', '_bx_persons_page_title_sys_profile_comments', '_bx_persons_page_title_profile_comments', 'bx_persons', 5, 2147483647, 1, 'persons-profile-comments', '', '', '', '', 0, 1, 0, 'BxPersonsPageEntry', 'modules/boonex/persons/classes/BxPersonsPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_persons_profile_comments', 1, 'bx_persons', '_bx_persons_page_block_title_profile_comments', '_bx_persons_page_block_title_profile_comments_link', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:15:\"entity_comments\";}', 0, 0, 0, 1);
+
+
+-- PAGE: module home
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_persons_home', '_bx_persons_page_title_sys_recent', '_bx_persons_page_title_recent', 'bx_persons', 5, 2147483647, 1, 'persons-home', 'page.php?i=persons-home', '', '', '', 0, 1, 0, 'BxPersonsPageBrowse', 'modules/boonex/persons/classes/BxPersonsPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES
+('bx_persons_home', 1, 'bx_persons', '_bx_persons_page_block_title_featured_profiles', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:10:"bx_persons";s:6:"method";s:15:"browse_featured";s:6:"params";a:1:{i:0;s:7:"gallery";}}', 0, 1, 0),
+('bx_persons_home', 1, 'bx_persons', '_bx_persons_page_block_title_latest_profiles', 11, 2147483647, 'service', 'a:3:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:22:\"browse_recent_profiles\";s:6:"params";a:1:{i:0;b:1;}}', 0, 1, 1);
+
+-- PAGE: active profiles
+
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_persons_active', '_bx_persons_page_title_sys_active', '_bx_persons_page_title_active', 'bx_persons', 5, 2147483647, 1, 'persons-active', 'page.php?i=persons-active', '', '', '', 0, 1, 0, 'BxPersonsPageBrowse', 'modules/boonex/persons/classes/BxPersonsPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_persons_active', 1, 'bx_persons', '_bx_persons_page_block_title_active_profiles', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:10:"bx_persons";s:6:"method";s:22:"browse_active_profiles";s:6:"params";a:2:{s:9:"unit_view";s:7:"gallery";s:13:"empty_message";b:1;}}', 0, 1, 0);
+
+-- PAGE: online profiles
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_persons_online', '_bx_persons_page_title_sys_online', '_bx_persons_page_title_online', 'bx_persons', 5, 2147483647, 1, 'persons-online', 'page.php?i=persons-online', '', '', '', 0, 1, 0, 'BxPersonsPageBrowse', 'modules/boonex/persons/classes/BxPersonsPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_persons_online', 1, 'bx_persons', '_bx_persons_page_block_title_online_profiles', 11, 2147483647, 'service', 'a:3:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:22:\"browse_online_profiles\";s:6:"params";a:1:{i:0;b:1;}}', 0, 1, 0);
+
+-- PAGE: search for entries
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_persons_search', '_bx_persons_page_title_sys_entries_search', '_bx_persons_page_title_entries_search', 'bx_persons', 5, 2147483647, 1, 'persons-search', 'page.php?i=persons-search', '', '', '', 0, 1, 0, 'BxPersonsPageBrowse', 'modules/boonex/persons/classes/BxPersonsPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_persons_search', 1, 'bx_persons', '_bx_persons_page_block_title_search_form', 11, 2147483647, 'service', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:8:"get_form";s:6:"params";a:1:{i:0;a:1:{s:6:"object";s:10:"bx_persons";}}s:5:"class";s:27:"TemplSearchExtendedServices";}', 0, 1, 1, 1),
+('bx_persons_search', 1, 'bx_persons', '_bx_persons_page_block_title_search_results', 11, 2147483647, 'service', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:11:"get_results";s:6:"params";a:1:{i:0;a:2:{s:6:"object";s:10:"bx_persons";s:10:"show_empty";b:1;}}s:5:"class";s:27:"TemplSearchExtendedServices";}', 0, 1, 1, 2),
+('bx_persons_search', 1, 'bx_persons', '_bx_persons_page_block_title_search_form_cmts', 11, 2147483647, 'service', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:8:"get_form";s:6:"params";a:1:{i:0;a:1:{s:6:"object";s:15:"bx_persons_cmts";}}s:5:"class";s:27:"TemplSearchExtendedServices";}', 0, 1, 0, 3),
+('bx_persons_search', 1, 'bx_persons', '_bx_persons_page_block_title_search_results_cmts', 11, 2147483647, 'service', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:11:"get_results";s:6:"params";a:1:{i:0;a:2:{s:6:"object";s:15:"bx_persons_cmts";s:10:"show_empty";b:1;}}s:5:"class";s:27:"TemplSearchExtendedServices";}', 0, 1, 0, 4);
+
+-- PAGE: module manage own
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_persons_manage', '_bx_persons_page_title_sys_manage', '_bx_persons_page_title_manage', 'bx_persons', 5, 2147483647, 1, 'persons-manage', 'page.php?i=persons-manage', '', '', '', 0, 1, 0, 'BxPersonsPageBrowse', 'modules/boonex/persons/classes/BxPersonsPageBrowse.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_persons_manage', 1, 'bx_persons', '_bx_persons_page_block_title_system_manage', '_bx_persons_page_block_title_manage', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:12:\"manage_tools\";}}', 0, 1, 0);
+
+-- PAGE: module manage all
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_persons_administration', '_bx_persons_page_title_sys_manage_administration', '_bx_persons_page_title_manage', 'bx_persons', 5, 192, 1, 'persons-administration', 'page.php?i=persons-administration', '', '', '', 0, 1, 0, 'BxPersonsPageBrowse', 'modules/boonex/persons/classes/BxPersonsPageBrowse.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_persons_administration', 1, 'bx_persons', '_bx_persons_page_block_title_system_manage_administration', '_bx_persons_page_block_title_manage', 11, 192, 'service', 'a:3:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:12:\"manage_tools\";s:6:\"params\";a:1:{i:0;s:14:\"administration\";}}', 0, 1, 0);
+
+-- PAGE: add block to homepage
+
+SET @iBlockOrder = (SELECT `order` FROM `sys_pages_blocks` WHERE `object` = 'sys_home' AND `cell_id` = 1 ORDER BY `order` DESC LIMIT 1);
+INSERT INTO `sys_pages_blocks` (`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES
+('sys_home', 1, 'bx_persons', '' , '_bx_persons_page_block_title_latest_profiles', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:10:"bx_persons";s:6:"method";s:22:"browse_recent_profiles";}', 1, 0, 0, IFNULL(@iBlockOrder, 0) + 1),
+('sys_home', 1, 'bx_persons', '_bx_persons_page_block_title_sys_recommended_entries_view_showcase', '_bx_persons_page_block_title_recommended_entries_view_showcase', 11, 2147483647, 'service', 'a:3:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:18:\"browse_recommended\";s:6:\"params\";a:3:{s:9:\"unit_view\";s:8:\"showcase\";s:13:\"empty_message\";b:0;s:13:\"ajax_paginate\";b:0;}}', 1, 0, 0, IFNULL(@iBlockOrder, 0) + 2);
+
+-- PAGE: service blocks
+
+SET @iBlockOrder = (SELECT `order` FROM `sys_pages_blocks` WHERE `object` = '' AND `cell_id` = 0 ORDER BY `order` DESC LIMIT 1);
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('', 0, 'bx_persons', '_bx_persons_page_block_title_sys_featured_entries_view_showcase', '_bx_persons_page_block_title_featured_entries_view_showcase', 11, 2147483647, 'service', 'a:3:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:15:\"browse_featured\";s:6:\"params\";a:3:{s:9:\"unit_view\";s:8:\"showcase\";s:13:\"empty_message\";b:0;s:13:\"ajax_paginate\";b:0;}}', 0, 1, 1, IFNULL(@iBlockOrder, 0) + 1),
+('', 0, 'bx_persons', '_bx_persons_page_block_title_sys_recommended_entries_view_showcase', '_bx_persons_page_block_title_recommended_entries_view_showcase', 11, 2147483647, 'service', 'a:3:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:18:\"browse_recommended\";s:6:\"params\";a:3:{s:9:\"unit_view\";s:8:\"showcase\";s:13:\"empty_message\";b:0;s:13:\"ajax_paginate\";b:0;}}', 0, 1, 1, IFNULL(@iBlockOrder, 0) + 2),
+('', 0, 'bx_persons', '_bx_persons_page_block_title_sys_active_entries_view_showcase', '_bx_persons_page_block_title_active_entries_view_showcase', 11, 2147483647, 'service', 'a:3:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:22:\"browse_active_profiles\";s:6:\"params\";a:3:{s:9:\"unit_view\";s:16:\"showcase_wo_info\";s:13:\"empty_message\";b:0;s:13:\"ajax_paginate\";b:0;}}', 0, 1, 1, IFNULL(@iBlockOrder, 0) + 3),
+('', 0, 'bx_persons', '_bx_persons_page_block_title_sys_active_profiles', '_bx_persons_page_block_title_active_profiles', 11, 2147483647, 'service', 'a:3:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:22:\"browse_active_profiles\";s:6:\"params\";a:3:{s:9:\"unit_view\";s:12:\"unit_wo_info\";s:13:\"empty_message\";b:0;s:13:\"ajax_paginate\";b:0;}}', 0, 1, 1, IFNULL(@iBlockOrder, 0) + 4),
+('', 0, 'bx_persons', '_bx_persons_page_block_title_sys_familiar_profiles', '_bx_persons_page_block_title_familiar_profiles', 11, 2147483647, 'service', 'a:3:{s:6:\"module\";s:10:\"bx_persons\";s:6:\"method\";s:24:\"browse_familiar_profiles\";s:6:\"params\";a:4:{s:10:\"connection\";s:20:\"sys_profiles_friends\";s:9:\"unit_view\";s:4:\"unit\";s:13:\"empty_message\";b:0;s:13:\"ajax_paginate\";b:0;}}', 0, 1, 1, IFNULL(@iBlockOrder, 0) + 5);
+
+-- MENU
+
+-- MENU: add to site menu
+
+SET @iSiteMenuOrder = (SELECT `order` FROM `sys_menu_items` WHERE `set_name` = 'sys_site' AND `active` = 1 AND `order` < 9999 ORDER BY `order` DESC LIMIT 1);
+INSERT INTO `sys_menu_items` (`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('sys_site', 'bx_persons', 'persons-home', '_bx_persons_menu_item_title_system_entries_home', '_bx_persons_menu_item_title_entries_home', 'page.php?i=persons-home', '', '', 'user col-blue3', 'bx_persons_submenu', 2147483647, 1, 1, IFNULL(@iSiteMenuOrder, 0) + 1);
+
+-- MENU: add to homepage menu
+
+SET @iHomepageMenuOrder = (SELECT `order` FROM `sys_menu_items` WHERE `set_name` = 'sys_homepage' AND `active` = 1 ORDER BY `order` DESC LIMIT 1);
+INSERT INTO `sys_menu_items` (`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('sys_homepage', 'bx_persons', 'persons-home', '_bx_persons_menu_item_title_system_entries_home', '_bx_persons_menu_item_title_entries_home', 'page.php?i=persons-home', '', '', 'user col-blue3', 'bx_persons_submenu', 2147483647, 1, 1, IFNULL(@iHomepageMenuOrder, 0) + 1);
+
+-- SET @iCreateProfileMenuOrder = (SELECT `order` FROM `sys_menu_items` WHERE `set_name` = 'sys_profiles_create' AND `active` = 1 ORDER BY `order` DESC LIMIT 1);
+-- INSERT INTO `sys_menu_items` (`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES
+-- ('sys_profiles_create', 'bx_persons', 'create-person-profile', '_bx_persons_menu_item_title_system_profile_type', '_bx_persons_menu_item_title_profile_type', 'page.php?i=create-persons-profile', '', '', 'user', '', 2147483647, 1, 1, IFNULL(@iCreateProfileMenuOrder, 0) + 1);
+
+SET @iAddMenuOrder = (SELECT `order` FROM `sys_menu_items` WHERE `set_name` = 'sys_add_profile_links' AND `active` = 1 ORDER BY `order` DESC LIMIT 1);
+INSERT INTO `sys_menu_items` (`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('sys_add_profile_links', 'bx_persons', 'create-persons-profile', '_bx_persons_menu_item_title_system_create_profile', '_bx_persons_menu_item_title_create_profile', 'page.php?i=create-persons-profile', '', '', 'user col-blue3', '', 2147483647, 1, 1, IFNULL(@iAddMenuOrder, 0) + 1);
+
+-- MENU: view actions
+
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_persons_view_actions', '_bx_persons_menu_title_view_profile_actions', 'bx_persons_view_actions', 'bx_persons', 9, 0, 1, 'BxPersonsMenuViewActions', 'modules/boonex/persons/classes/BxPersonsMenuViewActions.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_persons_view_actions', 'bx_persons', '_bx_persons_menu_set_title_view_profile_actions', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `submenu_popup`, `visible_for_levels`, `visibility_custom`, `active`, `copyable`, `order`) VALUES 
+('bx_persons_view_actions', 'bx_persons', 'profile-friend-add', '_bx_persons_menu_item_title_system_befriend', '{title_add_friend}', 'javascript:void(0)', 'bx_conn_action(this, \'sys_profiles_friends\', \'add\', \'{profile_id}\')', '', 'user-plus', '', 0, 2147483647, '', 1, 0, 10),
+('bx_persons_view_actions', 'bx_persons', 'profile-relation-add', '_bx_persons_menu_item_title_system_relation_add', '_bx_persons_menu_item_title_relation_add', 'javascript:void(0)', 'bx_menu_popup(''sys_add_relation'', window, {}, {profile_id: {profile_id}});', '', 'sync', '', 0, 2147483647, '', 1, 0, 15),
+('bx_persons_view_actions', 'bx_persons', 'profile-subscribe-add', '_bx_persons_menu_item_title_system_subscribe', '_bx_persons_menu_item_title_subscribe', 'javascript:void(0)', 'bx_conn_action(this, \'sys_profiles_subscriptions\', \'add\', \'{profile_id}\')', '', 'check', '', 0, 2147483647, '', 1, 0, 20),
+('bx_persons_view_actions', 'bx_persons', 'profile-set-acl-level', '_sys_menu_item_title_system_set_acl_level', '_sys_menu_item_title_set_acl_level', 'javascript:void(0)', 'bx_menu_popup(''sys_set_acl_level'', window, {id:{value:''sys_acl_set_{profile_id}'', force:true}, closeOnOuterClick: false, removeOnClose: true, displayMode: ''box'', cssClass: ''''}, {profile_id: {profile_id}});', '', 'certificate', '', 0, 2147483647, '', 1, 0, 30),
+('bx_persons_view_actions', 'bx_persons', 'profile-set-badges', '_sys_menu_item_title_system_set_badges', '_sys_menu_item_title_set_badges', 'javascript:void(0)', 'bx_menu_popup(''sys_set_badges'', window, {}, {module: ''bx_persons'', content_id: {content_id}});', '', 'check-circle', '', 0, 192, 'a:2:{s:6:"module";s:10:"bx_persons";s:6:"method";s:19:"is_badges_avaliable";}', 1, 0, 30),
+('bx_persons_view_actions', 'bx_persons', 'profile-actions-more', '_bx_persons_menu_item_title_system_more_actions', '_bx_persons_menu_item_title_more_actions', 'javascript:void(0)', 'bx_menu_popup(''bx_persons_view_actions_more'', this, {}, {profile_id:{profile_id}});', '', 'cog', 'bx_persons_view_actions_more', 1, 2147483647, '', 1, 0, 9999);
+
+-- MENU: view actions more
+
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_persons_view_actions_more', '_bx_persons_menu_title_view_profile_actions_more', 'bx_persons_view_actions_more', 'bx_persons', 6, 0, 1, 'BxPersonsMenuViewActions', 'modules/boonex/persons/classes/BxPersonsMenuViewActions.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_persons_view_actions_more', 'bx_persons', '_bx_persons_menu_set_title_view_profile_actions_more', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('bx_persons_view_actions_more', 'bx_persons', 'profile-friend-remove', '_bx_persons_menu_item_title_system_unfriend', '{title_remove_friend}', 'javascript:void(0)', 'bx_conn_action(this, \'sys_profiles_friends\', \'remove\', \'{profile_id}\')', '', 'user-times', '', 2147483647, 1, 0, 10),
+('bx_persons_view_actions_more', 'bx_persons', 'profile-relation-remove', '_bx_persons_menu_item_title_system_relation_delete', '_bx_persons_menu_item_title_relation_delete', 'javascript:void(0)', 'bx_conn_action(this, \'sys_profiles_relations\', \'remove\', \'{profile_id}\')', '', 'sync', '', 2147483647, 1, 0, 15),
+('bx_persons_view_actions_more', 'bx_persons', 'profile-subscribe-remove', '_bx_persons_menu_item_title_system_unsubscribe', '_bx_persons_menu_item_title_unsubscribe', 'javascript:void(0)', 'bx_conn_action(this, \'sys_profiles_subscriptions\', \'remove\', \'{profile_id}\')', '', 'check', '', 2147483647, 1, 0, 20),
+('bx_persons_view_actions_more', 'bx_persons', 'edit-persons-cover', '_bx_persons_menu_item_title_system_edit_cover', '_bx_persons_menu_item_title_edit_cover', 'page.php?i=edit-persons-cover&id={content_id}', '', '', 'edit', '', 2147483647, 1, 0, 25),
+('bx_persons_view_actions_more', 'bx_persons', 'edit-persons-profile', '_bx_persons_menu_item_title_system_edit_profile', '_bx_persons_menu_item_title_edit_profile', 'page.php?i=edit-persons-profile&id={content_id}', '', '', 'pencil-alt', '', 2147483647, 1, 0, 30),
+('bx_persons_view_actions_more', 'bx_persons', 'delete-persons-profile', '_bx_persons_menu_item_title_system_delete_profile', '_bx_persons_menu_item_title_delete_profile', 'page.php?i=delete-persons-profile&id={content_id}', '', '', 'remove', '', 2147483647, 1, 0, 40),
+('bx_persons_view_actions_more', 'bx_persons', 'delete-persons-account', '_bx_persons_menu_item_title_system_delete_account', '_bx_persons_menu_item_title_delete_account', 'page.php?i=account-settings-delete&id={account_id}', '', '', 'user-times', '', 128, 1, 0, 50),
+('bx_persons_view_actions_more', 'bx_persons', 'delete-persons-account-content', '_bx_persons_menu_item_title_system_delete_account_content', '_bx_persons_menu_item_title_delete_account_content', 'page.php?i=account-settings-delete&id={account_id}&content=1', '', '', 'trash', '', 128, 1, 0, 60);
+
+-- MENU: all actions menu for view entry 
+
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_persons_view_actions_all', '_sys_menu_title_view_actions', 'bx_persons_view_actions_all', 'bx_persons', 15, 0, 1, 'BxPersonsMenuViewActionsAll', 'modules/boonex/persons/classes/BxPersonsMenuViewActionsAll.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_persons_view_actions_all', 'bx_persons', '_sys_menu_set_title_view_actions', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `addon`, `submenu_object`, `submenu_popup`, `visible_for_levels`, `visibility_custom`, `active`, `copyable`, `order`) VALUES 
+('bx_persons_view_actions_all', 'bx_persons', 'profile-friend-add', '_bx_persons_menu_item_title_system_befriend', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 10),
+('bx_persons_view_actions_all', 'bx_persons', 'profile-friend-remove', '_bx_persons_menu_item_title_system_unfriend', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 20),
+('bx_persons_view_actions_all', 'bx_persons', 'profile-relation-add', '_bx_persons_menu_item_title_system_relation_add', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 23),
+('bx_persons_view_actions_all', 'bx_persons', 'profile-relation-remove', '_bx_persons_menu_item_title_system_relation_delete', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 27),
+('bx_persons_view_actions_all', 'bx_persons', 'profile-subscribe-add', '_bx_persons_menu_item_title_system_subscribe', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 30),
+('bx_persons_view_actions_all', 'bx_persons', 'profile-subscribe-remove', '_bx_persons_menu_item_title_system_unsubscribe', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 40),
+('bx_persons_view_actions_all', 'bx_persons', 'profile-set-acl-level', '_sys_menu_item_title_system_set_acl_level', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 50),
+('bx_persons_view_actions_all', 'bx_persons', 'profile-set-badges', '_sys_menu_item_title_system_set_badges', '', '', '', '', '', '', '', 0, 192, 'a:2:{s:6:"module";s:10:"bx_persons";s:6:"method";s:19:"is_badges_avaliable";}', 1, 0, 60),
+('bx_persons_view_actions_all', 'bx_persons', 'comment', '_sys_menu_item_title_system_va_comment', '', '', '', '', '', '', '', 0, 2147483647, '', 0, 0, 200),
+('bx_persons_view_actions_all', 'bx_persons', 'view', '_sys_menu_item_title_system_va_view', '', '', '', '', '', '', '', 0, 2147483647, '', 0, 0, 210),
+('bx_persons_view_actions_all', 'bx_persons', 'vote', '_sys_menu_item_title_system_va_vote', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 215),
+('bx_persons_view_actions_all', 'bx_persons', 'score', '_sys_menu_item_title_system_va_score', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 220),
+('bx_persons_view_actions_all', 'bx_persons', 'favorite', '_sys_menu_item_title_system_va_favorite', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 230),
+('bx_persons_view_actions_all', 'bx_persons', 'feature', '_sys_menu_item_title_system_va_feature', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 240),
+('bx_persons_view_actions_all', 'bx_persons', 'report', '_sys_menu_item_title_system_va_report', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 250),
+('bx_persons_view_actions_all', 'bx_persons', 'notes', '_sys_menu_item_title_system_va_notes', '_sys_menu_item_title_va_notes', 'javascript:void(0)', 'javascript:bx_get_notes(this,  ''{module_uri}'', {content_id});', '', 'exclamation-triangle', '', '', 0, 2147483647, '', 1, 0, 280),
+('bx_persons_view_actions_all', 'bx_persons', 'audit', '_sys_menu_item_title_system_va_audit', '_sys_menu_item_title_va_audit', 'page.php?i=dashboard-audit&module=bx_persons&content_id={content_id}', '', '', 'history', '', '', 0, 192, '', 1, 0, 290),
+('bx_persons_view_actions_all', 'bx_persons', 'edit-persons-cover', '_bx_persons_menu_item_title_system_edit_cover', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 400),
+('bx_persons_view_actions_all', 'bx_persons', 'edit-persons-profile', '_bx_persons_menu_item_title_system_edit_profile', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 410),
+('bx_persons_view_actions_all', 'bx_persons', 'delete-persons-profile', '_bx_persons_menu_item_title_system_delete_profile', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 420),
+('bx_persons_view_actions_all', 'bx_persons', 'delete-persons-account', '_bx_persons_menu_item_title_system_delete_account', '', '', '', '', '', '', '', 0, 128, '', 1, 0, 430),
+('bx_persons_view_actions_all', 'bx_persons', 'delete-persons-account-content', '_bx_persons_menu_item_title_system_delete_account_content', '', '', '', '', '', '', '', 0, 128, '', 1, 0, 440),
+('bx_persons_view_actions_all', 'bx_persons', 'more-auto', '_sys_menu_item_title_system_va_more_auto', '_sys_menu_item_title_va_more_auto', 'javascript:void(0)', '', '', 'ellipsis-v', '', '', 0, 2147483647, '', 1, 0, 9999);
+
+-- MENU: meta (counters) menu for view entry
+
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_persons_view_meta', '_bx_persons_menu_title_view_profile_meta', 'bx_persons_view_meta', 'bx_persons', 15, 0, 1, 'BxPersonsMenuViewMeta', 'modules/boonex/persons/classes/BxPersonsMenuViewMeta.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_persons_view_meta', 'bx_persons', '_bx_persons_menu_set_title_view_profile_meta', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `submenu_popup`, `visible_for_levels`, `visibility_custom`, `active`, `copyable`, `order`) VALUES 
+('bx_persons_view_meta', 'bx_persons', 'membership', '_sys_menu_item_title_system_vm_membership', '_sys_menu_item_title_vm_membership', '', '', '', '', '', 0, 2147483647, '', 1, 0, 10),
+('bx_persons_view_meta', 'bx_persons', 'badges', '_sys_menu_item_title_system_vm_badges', '_sys_menu_item_title_vm_badges', '', '', '', '', '', 0, 2147483647, '', 1, 0, 20),
+('bx_persons_view_meta', 'bx_persons', 'views', '_sys_menu_item_title_system_sm_views', '_sys_menu_item_title_sm_views', '', '', '', '', '', 0, 2147483647, '', 1, 0, 30),
+('bx_persons_view_meta', 'bx_persons', 'votes', '_sys_menu_item_title_system_sm_votes', '_sys_menu_item_title_sm_votes', '', '', '', '', '', 0, 2147483647, '', 1, 0, 40),
+('bx_persons_view_meta', 'bx_persons', 'comments', '_sys_menu_item_title_system_sm_comments', '_sys_menu_item_title_sm_comments', '', '', '', '', '', 0, 2147483647, '', 1, 0, 50);
+
+-- MENU: module sub-menu
+
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_persons_submenu', '_bx_persons_menu_title_submenu', 'bx_persons_submenu', 'bx_persons', 8, 0, 1, '', '');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_persons_submenu', 'bx_persons', '_bx_persons_menu_set_title_submenu', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('bx_persons_submenu', 'bx_persons', 'persons-home', '_bx_persons_menu_item_title_system_entries_recent', '_bx_persons_menu_item_title_entries_recent', 'page.php?i=persons-home', '', '', '', '', 2147483647, 1, 1, 1),
+('bx_persons_submenu', 'bx_persons', 'persons-active', '_bx_persons_menu_item_title_system_entries_active', '_bx_persons_menu_item_title_entries_active', 'page.php?i=persons-active', '', '', '', '', 2147483647, 1, 1, 2),
+('bx_persons_submenu', 'bx_persons', 'persons-online', '_bx_persons_menu_item_title_system_entries_online', '_bx_persons_menu_item_title_entries_online', 'page.php?i=persons-online', '', '', '', '', 2147483647, 1, 1, 3),
+('bx_persons_submenu', 'bx_persons', 'persons-search', '_bx_persons_menu_item_title_system_entries_search', '_bx_persons_menu_item_title_entries_search', 'page.php?i=persons-search', '', '', '', '', 2147483647, 1, 1, 4),
+('bx_persons_submenu', 'bx_persons', 'persons-manage', '_bx_persons_menu_item_title_system_entries_manage', '_bx_persons_menu_item_title_entries_manage', 'page.php?i=persons-manage', '', '', '', '', 2147483646, 1, 1, 5);
+
+-- MENU: view submenu
+
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_persons_view_submenu', '_bx_persons_menu_title_view_profile_submenu', 'bx_persons_view_submenu', 'bx_persons', 18, 0, 1, 'BxPersonsMenuView', 'modules/boonex/persons/classes/BxPersonsMenuView.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_persons_view_submenu', 'bx_persons', '_bx_persons_menu_set_title_view_profile_submenu', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `addon`, `submenu_object`, `submenu_popup`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('bx_persons_view_submenu', 'bx_persons', 'view-persons-profile', '_bx_persons_menu_item_title_system_view_profile_view', '_bx_persons_menu_item_title_view_profile_view', 'page.php?i=view-persons-profile&id={content_id}', '', '', 'user col-blue3', '', '', 0, 2147483647, 1, 0, 1),
+('bx_persons_view_submenu', 'bx_persons', 'persons-profile-info', '_bx_persons_menu_item_title_system_view_profile_info', '_bx_persons_menu_item_title_view_profile_info', 'page.php?i=persons-profile-info&id={content_id}', '', '', 'info-circle col-gray', '', '', 0, 2147483647, 1, 0, 2),
+('bx_persons_view_submenu', 'bx_persons', 'persons-profile-friends', '_bx_persons_menu_item_title_system_view_profile_friends', '_bx_persons_menu_item_title_view_profile_friends', 'page.php?i=persons-profile-friends&profile_id={profile_id}', '', '', 'users col-blue3', '', '', 0, 2147483647, 1, 0, 3),
+('bx_persons_view_submenu', 'bx_persons', 'persons-profile-relations', '_bx_persons_menu_item_title_system_view_profile_relations', '_bx_persons_menu_item_title_view_profile_relations', 'page.php?i=persons-profile-relations&profile_id={profile_id}', '', '', 'sync col-blue3', '', '', 0, 2147483647, 1, 0, 4),
+('bx_persons_view_submenu', 'bx_persons', 'persons-profile-subscriptions', '_bx_persons_menu_item_title_system_view_profile_subscriptions', '_bx_persons_menu_item_title_view_profile_subscriptions', 'page.php?i=persons-profile-subscriptions&profile_id={profile_id}', '', '', 'check col-blue3', '', '', 0, 2147483647, 1, 0, 5),
+('bx_persons_view_submenu', 'bx_persons', 'persons-profile-comments', '_bx_persons_menu_item_title_system_view_profile_comments', '_bx_persons_menu_item_title_view_profile_comments', 'page.php?i=persons-profile-comments&id={content_id}', '', '', '', '', '', 0, 2147483647, 0, 0, 6),
+('bx_persons_view_submenu', 'bx_persons', 'more-auto', '_bx_persons_menu_item_title_system_view_profile_more_auto', '_bx_persons_menu_item_title_view_profile_more_auto', 'javascript:void(0)', '', '', 'ellipsis-v', '', '', 0, 2147483647, 1, 0, 9999);
+
+-- MENU: custom menu for snippet meta info
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_persons_snippet_meta', '_sys_menu_title_snippet_meta', 'bx_persons_snippet_meta', 'bx_persons', 15, 0, 1, 'BxPersonsMenuSnippetMeta', 'modules/boonex/persons/classes/BxPersonsMenuSnippetMeta.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_persons_snippet_meta', 'bx_persons', '_sys_menu_set_title_snippet_meta', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `editable`, `order`) VALUES
+('bx_persons_snippet_meta', 'bx_persons', 'friends-mutual', '_sys_menu_item_title_system_sm_friends_mutual', '_sys_menu_item_title_sm_friends_mutual', '', '', '', '', '', 2147483647, 0, 0, 1, 0),
+('bx_persons_snippet_meta', 'bx_persons', 'date', '_sys_menu_item_title_system_sm_date', '_sys_menu_item_title_sm_date', '', '', '', '', '', 2147483647, 0, 0, 1, 1),
+('bx_persons_snippet_meta', 'bx_persons', 'tags', '_sys_menu_item_title_system_sm_tags', '_sys_menu_item_title_sm_tags', '', '', '', '', '', 2147483647, 0, 0, 1, 2),
+('bx_persons_snippet_meta', 'bx_persons', 'views', '_sys_menu_item_title_system_sm_views', '_sys_menu_item_title_sm_views', '', '', '', '', '', 2147483647, 0, 0, 1, 3),
+('bx_persons_snippet_meta', 'bx_persons', 'comments', '_sys_menu_item_title_system_sm_comments', '_sys_menu_item_title_sm_comments', '', '', '', '', '', 2147483647, 0, 0, 1, 4),
+('bx_persons_snippet_meta', 'bx_persons', 'friends', '_sys_menu_item_title_system_sm_friends', '_sys_menu_item_title_sm_friends', '', '', '', '', '', 2147483647, 1, 0, 1, 5),
+('bx_persons_snippet_meta', 'bx_persons', 'subscribers', '_sys_menu_item_title_system_sm_subscribers', '_sys_menu_item_title_sm_subscribers', '', '', '', '', '', 2147483647, 1, 0, 1, 6),
+('bx_persons_snippet_meta', 'bx_persons', 'membership', '_sys_menu_item_title_system_sm_membership', '_sys_menu_item_title_sm_membership', '', '', '', '', '', 2147483647, 0, 0, 1, 7),
+('bx_persons_snippet_meta', 'bx_persons', 'nl', '_sys_menu_item_title_system_sm_nl', '_sys_menu_item_title_sm_nl', '', '', '', '', '', 2147483647, 1, 0, 1, 8),
+('bx_persons_snippet_meta', 'bx_persons', 'befriend', '_sys_menu_item_title_system_sm_befriend', '_sys_menu_item_title_sm_befriend', '', '', '', '', '', 2147483647, 1, 0, 1, 9),
+('bx_persons_snippet_meta', 'bx_persons', 'unfriend', '_sys_menu_item_title_system_sm_unfriend', '_sys_menu_item_title_sm_unfriend', '', '', '', '', '', 2147483647, 0, 0, 1, 10),
+('bx_persons_snippet_meta', 'bx_persons', 'subscribe', '_sys_menu_item_title_system_sm_subscribe', '_sys_menu_item_title_sm_subscribe', '', '', '', '', '', 2147483647, 1, 0, 1, 11),
+('bx_persons_snippet_meta', 'bx_persons', 'unsubscribe', '_sys_menu_item_title_system_sm_unsubscribe', '_sys_menu_item_title_sm_unsubscribe', '', '', '', '', '', 2147483647, 0, 0, 1, 12);
+
+-- MENU: notifications menu in account popup
+SET @iNotifMenuOrder = (SELECT IFNULL(MAX(`order`), 0) FROM `sys_menu_items` WHERE `set_name` = 'sys_account_notifications' AND `active` = 1 AND `order` < 9999 ORDER BY `order` DESC LIMIT 1);
+INSERT INTO `sys_menu_items` (`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `addon`, `submenu_object`, `visible_for_levels`, `visibility_custom`, `active`, `copyable`, `order`) VALUES
+('sys_account_notifications', 'bx_persons', 'notifications-friend-requests', '_bx_persons_menu_item_title_system_friends', '_bx_persons_menu_item_title_friends', 'page.php?i=persons-profile-friends&profile_id={member_id}', '', '', 'users col-blue3', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:31:"get_unconfirmed_connections_num";s:6:"params";a:1:{i:0;s:20:"sys_profiles_friends";}s:5:"class";s:23:"TemplServiceConnections";}', '', 2147483646, '', 1, 0, @iNotifMenuOrder + 1),
+('sys_account_notifications', 'bx_persons', 'notifications-relation-requests', '_bx_persons_menu_item_title_system_relations', '_bx_persons_menu_item_title_relations', 'page.php?i=persons-profile-relations&profile_id={member_id}', '', '', 'sync col-blue3', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:31:"get_unconfirmed_connections_num";s:6:"params";a:1:{i:0;s:22:"sys_profiles_relations";}s:5:"class";s:23:"TemplServiceConnections";}', '', 2147483646, 'a:2:{s:6:"module";s:10:"bx_persons";s:6:"method";s:19:"is_enable_relations";}', 1, 0, @iNotifMenuOrder + 2);
+
+-- MENU: profile stats
+SET @iNotifMenuOrder = (SELECT IFNULL(MAX(`order`), 0) FROM `sys_menu_items` WHERE `set_name` = 'sys_profile_stats' AND `active` = 1 LIMIT 1);
+INSERT INTO `sys_menu_items` (`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `addon`, `submenu_object`, `visible_for_levels`, `visibility_custom`, `active`, `copyable`, `order`) VALUES
+('sys_profile_stats', 'bx_persons', 'profile-stats-friend-requests', '_bx_persons_menu_item_title_system_friend_requests', '_bx_persons_menu_item_title_friend_requests', 'page.php?i=persons-profile-friends&profile_id={member_id}', '', '', 'users col-blue3', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:31:"get_unconfirmed_connections_num";s:6:"params";a:1:{i:0;s:20:"sys_profiles_friends";}s:5:"class";s:23:"TemplServiceConnections";}', '', 2147483646, '', 1, 0, @iNotifMenuOrder + 1),
+('sys_profile_stats', 'bx_persons', 'profile-stats-manage-profiles', '_bx_persons_menu_item_title_system_manage_my_profiles', '_bx_persons_menu_item_title_manage_my_profiles', 'page.php?i=persons-manage', '', '_self', 'users col-blue3', 'a:2:{s:6:"module";s:10:"bx_persons";s:6:"method";s:41:"get_menu_addon_manage_tools_profile_stats";}', '', 2147483646, '', 1, 0, @iNotifMenuOrder + 2),
+('sys_profile_stats', 'bx_persons', 'profile-stats-favorite-persons', '_bx_persons_menu_item_title_system_favorites', '_bx_persons_menu_item_title_favorites', 'page.php?i=persons-profile-favorites&profile_id={member_id}', '', '', 'star col-blue3', 'a:2:{s:6:"module";s:10:"bx_persons";s:6:"method";s:38:"get_menu_addon_favorites_profile_stats";}', '', 2147483646, '', 1, 0, @iNotifMenuOrder + 3);
+
+INSERT INTO `sys_menu_items` (`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `addon`, `addon_cache`, `submenu_object`, `visible_for_levels`, `visibility_custom`, `active`, `copyable`, `order`) VALUES
+('sys_profile_stats', 'bx_persons', 'profile-stats-subscriptions', '_bx_persons_menu_item_title_system_subscriptions', '_bx_persons_menu_item_title_subscriptions', 'page.php?i=persons-profile-subscriptions&profile_id={member_id}#subscriptions', '', '_self', 'rss col-blue3', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:25:"get_connected_content_num";s:6:"params";a:1:{i:0;s:26:"sys_profiles_subscriptions";}s:5:"class";s:23:"TemplServiceConnections";}', 0, '', 2147483646, '', 1, 0, @iNotifMenuOrder + 4),
+('sys_profile_stats', 'bx_persons', 'profile-stats-subscribed-me', '_bx_persons_menu_item_title_system_subscribed_me', '_bx_persons_menu_item_title_subscribed_me', 'page.php?i=persons-profile-subscriptions&profile_id={member_id}#subscribers', '', '_self', 'rss col-blue3', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:28:"get_connected_initiators_num";s:6:"params";a:1:{i:0;s:26:"sys_profiles_subscriptions";}s:5:"class";s:23:"TemplServiceConnections";}', 1, '', 2147483646, '', 1, 0, @iNotifMenuOrder + 5);
+
+INSERT INTO `sys_menu_items` (`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `addon`, `submenu_object`, `visible_for_levels`, `visibility_custom`, `active`, `copyable`, `order`) VALUES
+('sys_profile_stats', 'bx_persons', 'profile-stats-relations', '_bx_persons_menu_item_title_system_relations', '_bx_persons_menu_item_title_relations', 'page.php?i=persons-profile-relations&profile_id={member_id}#relations', '', '_self', 'sync col-blue3', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:25:"get_connected_content_num";s:6:"params";a:3:{i:0;s:22:"sys_profiles_relations";i:1;i:0;i:2;i:1;}s:5:"class";s:23:"TemplServiceConnections";}', '', 2147483646, 'a:2:{s:6:"module";s:10:"bx_persons";s:6:"method";s:19:"is_enable_relations";}', 1, 0, @iNotifMenuOrder + 6),
+('sys_profile_stats', 'bx_persons', 'profile-stats-related-me', '_bx_persons_menu_item_title_system_related_me', '_bx_persons_menu_item_title_related_me', 'page.php?i=persons-profile-relations&profile_id={member_id}#related-me', '', '_self', 'sync col-blue3', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:28:"get_connected_initiators_num";s:6:"params";a:3:{i:0;s:22:"sys_profiles_relations";i:1;i:0;i:2;i:1;}s:5:"class";s:23:"TemplServiceConnections";}', '', 2147483646, 'a:2:{s:6:"module";s:10:"bx_persons";s:6:"method";s:19:"is_enable_relations";}', 1, 0, @iNotifMenuOrder + 7);
+
+-- MENU: profile followings
+SET @iFollowingsMenuOrder = (SELECT IFNULL(MAX(`order`), 0) FROM `sys_menu_items` WHERE `set_name`='sys_profile_followings' LIMIT 1);
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `addon`, `submenu_object`, `visible_for_levels`, `collapsed`, `active`, `copyable`, `order`) VALUES 
+('sys_profile_followings', 'bx_persons', 'persons', '_bx_persons_menu_item_title_system_followings', '_bx_persons_menu_item_title_followings', 'javascript:void(0)', '', '_self', 'users col-blue3', '', '', 2147483647, 0, 1, 0, @iFollowingsMenuOrder + 1);
+
+-- MENU: manage tools submenu
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_persons_menu_manage_tools', '_bx_persons_menu_title_manage_tools', 'bx_persons_menu_manage_tools', 'bx_persons', 6, 0, 1, 'BxPersonsMenuManageTools', 'modules/boonex/persons/classes/BxPersonsMenuManageTools.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_persons_menu_manage_tools', 'bx_persons', '_bx_persons_menu_set_title_manage_tools', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('bx_persons_menu_manage_tools', 'bx_persons', 'clear-reports', '_bx_persons_menu_item_title_system_clear_reports', '_bx_persons_menu_item_title_clear_reports', 'javascript:void(0)', 'javascript:{js_object}.onClickClearReports({content_id});', '_self', 'eraser', '', 2147483647, 1, 0, 1),
+('bx_persons_menu_manage_tools', 'bx_persons', 'manage-cf', '_bx_persons_menu_item_title_system_manage_cf', '_bx_persons_menu_item_title_manage_cf', 'javascript:void(0)', 'javascript:{js_object}.onClickManageCf({content_id});', '_self', 'filter', '', 2147483647, 1, 0, 6),
+('bx_persons_menu_manage_tools', 'bx_persons', 'delete-with-content', '_bx_persons_menu_item_title_system_delete_with_content', '_bx_persons_menu_item_title_delete_with_content', 'javascript:void(0)', 'javascript:{js_object}.onClickDeleteWithContent({content_id});', '_self', 'far trash-alt', '', 2147483647, 1, 0, 99);
+
+-- MENU: dashboard manage tools
+SET @iManageMenuOrder = (SELECT IFNULL(MAX(`order`), 0) FROM `sys_menu_items` WHERE `set_name`='sys_account_dashboard_manage_tools' LIMIT 1);
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `addon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('sys_account_dashboard_manage_tools', 'bx_persons', 'persons-administration', '_bx_persons_menu_item_title_system_admt_persons', '_bx_persons_menu_item_title_admt_persons', 'page.php?i=persons-administration', '', '_self', 'user', 'a:2:{s:6:"module";s:10:"bx_persons";s:6:"method";s:27:"get_menu_addon_manage_tools";}', '', 192, 1, 0, @iManageMenuOrder + 1);
+
+
+-- ACL
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_persons', 'create entry', NULL, '_bx_persons_acl_action_create_profile', '', 1, 1);
+SET @iIdActionProfileCreate = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_persons', 'delete entry', NULL, '_bx_persons_acl_action_delete_profile', '', 1, 1);
+SET @iIdActionProfileDelete = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_persons', 'view entry', NULL, '_bx_persons_acl_action_view_profile', '', 1, 0);
+SET @iIdActionProfileView = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_persons', 'edit any entry', NULL, '_bx_persons_acl_action_edit_any_profile', '', 1, 3);
+SET @iIdActionProfileEditAny = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_persons', 'delete any entry', NULL, '_bx_persons_acl_action_delete_any_profile', '', 1, 3);
+SET @iIdActionProfileDeleteAny = LAST_INSERT_ID();
+
+SET @iUnauthenticated = 1;
+SET @iAccount = 2;
+SET @iStandard = 3;
+SET @iUnconfirmed = 4;
+SET @iPending = 5;
+SET @iSuspended = 6;
+SET @iModerator = 7;
+SET @iAdministrator = 8;
+SET @iPremium = 9;
+
+
+INSERT INTO `sys_acl_matrix` (`IDLevel`, `IDAction`) VALUES
+
+-- profile create
+(@iAccount, @iIdActionProfileCreate),
+(@iStandard, @iIdActionProfileCreate),
+(@iUnconfirmed, @iIdActionProfileCreate),
+(@iPending, @iIdActionProfileCreate),
+(@iModerator, @iIdActionProfileCreate),
+(@iAdministrator, @iIdActionProfileCreate),
+(@iPremium, @iIdActionProfileCreate),
+
+-- profile delete
+(@iAccount, @iIdActionProfileDelete),
+(@iStandard, @iIdActionProfileDelete),
+(@iUnconfirmed, @iIdActionProfileDelete),
+(@iPending, @iIdActionProfileDelete),
+(@iModerator, @iIdActionProfileDelete),
+(@iAdministrator, @iIdActionProfileDelete),
+(@iPremium, @iIdActionProfileDelete),
+
+-- profile view
+(@iUnauthenticated, @iIdActionProfileView),
+(@iAccount, @iIdActionProfileView),
+(@iStandard, @iIdActionProfileView),
+(@iUnconfirmed, @iIdActionProfileView),
+(@iPending, @iIdActionProfileView),
+(@iModerator, @iIdActionProfileView),
+(@iAdministrator, @iIdActionProfileView),
+(@iPremium, @iIdActionProfileView),
+
+-- any profile edit
+(@iModerator, @iIdActionProfileEditAny),
+(@iAdministrator, @iIdActionProfileEditAny),
+
+-- any profile delete
+(@iAdministrator, @iIdActionProfileDeleteAny);
+
+-- METATAGS
+INSERT INTO `sys_objects_metatags` (`object`, `module`, `table_keywords`, `table_locations`, `table_mentions`, `override_class_name`, `override_class_file`) VALUES
+('bx_persons', 'bx_persons', 'bx_persons_meta_keywords', 'bx_persons_meta_locations', 'bx_persons_meta_mentions', '', '');
+
+-- SEARCH
+SET @iSearchOrder = (SELECT IFNULL(MAX(`Order`), 0) FROM `sys_objects_search`);
+INSERT INTO `sys_objects_search` (`ObjectName`, `Title`, `Order`, `ClassName`, `ClassPath`) VALUES
+('bx_persons', '_bx_persons', @iSearchOrder + 1, 'BxPersonsSearchResult', 'modules/boonex/persons/classes/BxPersonsSearchResult.php'),
+('bx_persons_cmts', '_bx_persons_cmts', @iSearchOrder + 2, 'BxPersonsCmtsSearchResult', 'modules/boonex/persons/classes/BxPersonsCmtsSearchResult.php');
+
+-- STATS
+SET @iMaxOrderStats = (SELECT IFNULL(MAX(`order`), 0) FROM `sys_statistics`);
+INSERT INTO `sys_statistics` (`module`, `name`, `title`, `link`, `icon`, `query`, `order`) VALUES 
+('bx_persons', 'bx_persons', '_bx_persons', 'page.php?i=persons-home', 'user col-blue3', 'SELECT COUNT(*) FROM `bx_persons_data` AS `td` LEFT JOIN `sys_profiles` AS `tp` ON `td`.`id` = `tp`.`content_id` AND `tp`.`type`=''bx_persons'' WHERE 1 AND `tp`.`status`=''active''', @iMaxOrderStats + 1);
+
+-- CHARTS
+SET @iMaxOrderCharts = (SELECT IFNULL(MAX(`order`), 0) FROM `sys_objects_chart`);
+INSERT INTO `sys_objects_chart` (`object`, `title`, `table`, `field_date_ts`, `field_date_dt`, `field_status`, `query`, `active`, `order`, `class_name`, `class_file`) VALUES
+('bx_persons_growth', '_bx_persons_chart_growth', 'bx_persons_data', 'added', '', '', 'SELECT {field_date_formatted} AS `period`, COUNT(*) AS {object} FROM {table} LEFT JOIN `sys_profiles` AS `tp` ON {table}.`id` = `tp`.`content_id` AND `tp`.`type`=''bx_persons'' WHERE 1 AND `tp`.`status`=''active'' {where_inteval} GROUP BY `period` ORDER BY {table}.{field_date} ASC', 1, @iMaxOrderCharts + 1, 'BxDolChartGrowth', ''),
+('bx_persons_growth_speed', '_bx_persons_chart_growth_speed', 'bx_persons_data', 'added', '', '', 'SELECT {field_date_formatted} AS `period`, COUNT(*) AS {object} FROM {table} LEFT JOIN `sys_profiles` AS `tp` ON {table}.`id` = `tp`.`content_id` AND `tp`.`type`=''bx_persons'' WHERE 1 AND `tp`.`status`=''active'' {where_inteval} GROUP BY `period` ORDER BY {table}.{field_date} ASC', 1, @iMaxOrderCharts + 2, 'BxDolChartGrowthSpeed', '');
+
+-- GRIDS: administration
+INSERT INTO `sys_objects_grid` (`object`, `source_type`, `source`, `table`, `field_id`, `field_order`, `field_active`, `paginate_url`, `paginate_per_page`, `paginate_simple`, `paginate_get_start`, `paginate_get_per_page`, `filter_fields`, `filter_fields_translatable`, `filter_mode`, `sorting_fields`, `sorting_fields_translatable`, `visible_for_levels`, `override_class_name`, `override_class_file`) VALUES
+('bx_persons_administration', 'Sql', 'SELECT `td`.*, `ta`.`email` AS `account`, `ta`.`logged` AS `last_online`, `tp`.`status` AS `status`, `tp`.`id` as `profile_id` FROM `bx_persons_data` AS `td` LEFT JOIN `sys_profiles` AS `tp` ON `td`.`id`=`tp`.`content_id` AND `tp`.`type`=''bx_persons'' LEFT JOIN `sys_accounts` AS `ta` ON `tp`.`account_id`=`ta`.`id` WHERE 1 ', 'bx_persons_data', 'id', 'last_online', 'status', '', 20, NULL, 'start', '', 'fullname,email', '', 'like', 'reports', '', 192, 'BxPersonsGridAdministration', 'modules/boonex/persons/classes/BxPersonsGridAdministration.php'),
+('bx_persons_common', 'Sql', 'SELECT `td`.*, `ta`.`email` AS `account`, `ta`.`logged` AS `last_online`, `tp`.`status` AS `status` FROM `bx_persons_data` AS `td` LEFT JOIN `sys_profiles` AS `tp` ON `td`.`id`=`tp`.`content_id` AND `tp`.`type`=''bx_persons'' LEFT JOIN `sys_accounts` AS `ta` ON `tp`.`account_id`=`ta`.`id` WHERE 1 ', 'bx_persons_data', 'id', 'last_online', 'status', '', 20, NULL, 'start', '', 'fullname', '', 'like', '', '', 2147483647, 'BxPersonsGridCommon', 'modules/boonex/persons/classes/BxPersonsGridCommon.php');
+
+INSERT INTO `sys_grid_fields` (`object`, `name`, `title`, `width`, `translatable`, `chars_limit`, `params`, `order`) VALUES
+('bx_persons_administration', 'checkbox', '_sys_select', '2%', 0, '', '', 1),
+('bx_persons_administration', 'switcher', '_bx_persons_grid_column_title_adm_active', '8%', 0, '', '', 2),
+('bx_persons_administration', 'reports', '_sys_txt_reports_title', '5%', 0, '', '', 3),
+('bx_persons_administration', 'fullname', '_bx_persons_grid_column_title_adm_fullname', '25%', 0, '', '', 4),
+('bx_persons_administration', 'last_online', '_bx_persons_grid_column_title_adm_last_online', '20%', 1, '25', '', 5),
+('bx_persons_administration', 'account', '_bx_persons_grid_column_title_adm_account', '20%', 0, '25', '', 6),
+('bx_persons_administration', 'actions', '', '20%', 0, '', '', 7),
+
+('bx_persons_common', 'checkbox', '_sys_select', '2%', 0, '', '', 1),
+('bx_persons_common', 'fullname', '_bx_persons_grid_column_title_adm_fullname', '48%', 0, '', '', 2),
+('bx_persons_common', 'last_online', '_bx_persons_grid_column_title_adm_last_online', '30%', 1, '25', '', 3),
+('bx_persons_common', 'actions', '', '20%', 0, '', '', 4);
+
+INSERT INTO `sys_grid_actions` (`object`, `type`, `name`, `title`, `icon`, `icon_only`, `confirm`, `order`) VALUES
+('bx_persons_administration', 'bulk', 'set_acl_level', '_bx_persons_grid_action_title_adm_set_acl_level', '', 0, 0, 1),
+('bx_persons_administration', 'bulk', 'delete_with_content', '_bx_persons_grid_action_title_adm_delete_with_content', '', 0, 1, 2),
+('bx_persons_administration', 'bulk', 'clear_reports', '_bx_persons_grid_action_title_adm_clear_reports', '', 0, 1, 3),
+('bx_persons_administration', 'single', 'set_acl_level', '_bx_persons_grid_action_title_adm_set_acl_level', 'certificate', 1, 0, 1),
+('bx_persons_administration', 'single', 'settings', '_bx_persons_grid_action_title_adm_more_actions', 'cog', 1, 0, 2),
+('bx_persons_administration', 'single', 'audit_content', '_bx_persons_grid_action_title_adm_audit_content', 'search', 1, 0, 3),
+('bx_persons_administration', 'single', 'audit_profile', '_bx_persons_grid_action_title_adm_audit_profile', 'search-location', 1, 0, 4),
+
+('bx_persons_common', 'bulk', 'delete_with_content', '_bx_persons_grid_action_title_adm_delete_with_content', '', 0, 1, 1),
+('bx_persons_common', 'single', 'settings', '_bx_persons_grid_action_title_adm_more_actions', 'cog', 1, 0, 1);
+
+-- LIVE UPDATES
+INSERT INTO `sys_objects_live_updates`(`name`, `frequency`, `service_call`, `active`) VALUES
+('bx_persons_friend_requests', 1, 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:40:"get_live_updates_unconfirmed_connections";s:6:"params";a:5:{i:0;s:10:"bx_persons";i:1;s:20:"sys_profiles_friends";i:2;a:2:{s:11:"menu_object";s:18:"sys_toolbar_member";s:9:"menu_item";s:7:"account";}i:3;a:2:{s:11:"menu_object";s:25:"sys_account_notifications";s:9:"menu_item";s:29:"notifications-friend-requests";}i:4;s:7:"{count}";}s:5:"class";s:23:"TemplServiceConnections";}', 1);
+
+-- ALERTS
+INSERT INTO `sys_alerts_handlers` (`name`, `class`, `file`, `service_call`) VALUES 
+('bx_persons', 'BxPersonsAlertsResponse', 'modules/boonex/persons/classes/BxPersonsAlertsResponse.php', '');
+SET @iHandler := LAST_INSERT_ID();
+
+INSERT INTO `sys_alerts` (`unit`, `action`, `handler_id`) VALUES
+('system', 'save_setting', @iHandler),
+('sys_profiles_friends', 'connection_added', @iHandler),
+('bx_timeline', 'post_common', @iHandler),
+('bx_persons_pictures', 'file_deleted', @iHandler),
+('bx_persons', 'timeline_view', @iHandler),
+('bx_persons', 'timeline_post', @iHandler),
+('bx_persons', 'timeline_delete', @iHandler),
+('bx_persons', 'timeline_comment', @iHandler),
+('bx_persons', 'timeline_vote', @iHandler),
+('bx_persons', 'timeline_score', @iHandler),
+('bx_persons', 'timeline_report', @iHandler),
+('bx_persons', 'timeline_repost', @iHandler),
+('bx_persons', 'timeline_pin', @iHandler),
+('bx_persons', 'timeline_promote', @iHandler);
+
+-- PRIVACY 
+INSERT INTO `sys_objects_privacy` (`object`, `module`, `action`, `title`, `default_group`, `spaces`, `table`, `table_field_id`, `table_field_author`, `override_class_name`, `override_class_file`) VALUES
+('bx_persons_allow_view_to', 'bx_persons', 'view', '_bx_persons_form_profile_input_allow_view_to', '3', '', 'bx_persons_data', 'id', 'author', 'BxPersonsPrivacy', 'modules/boonex/persons/classes/BxPersonsPrivacy.php'),
+('bx_persons_allow_post_to', 'bx_persons', 'post', '_bx_persons_form_profile_input_allow_post_to', '5', '', 'bx_persons_data', 'id', 'author', 'BxPersonsPrivacyPost', 'modules/boonex/persons/classes/BxPersonsPrivacyPost.php'),
+('bx_persons_allow_contact_to', 'bx_persons', 'contact', '_bx_persons_form_profile_input_allow_contact_to', '3', '', 'bx_persons_data', 'id', 'author', 'BxPersonsPrivacyContact', 'modules/boonex/persons/classes/BxPersonsPrivacyContact.php');
+
+-- EMAIL TEMPLATES
+INSERT INTO `sys_email_templates` (`Module`, `NameSystem`, `Name`, `Subject`, `Body`) VALUES
+('bx_persons', '_bx_persons_email_friend_request', 'bx_persons_friend_request', '_bx_persons_email_friend_request_subject', '_bx_persons_email_friend_request_body');
+
+-- UPLOADERS
+INSERT INTO `sys_objects_uploader` (`object`, `active`, `override_class_name`, `override_class_file`) VALUES
+('bx_persons_cover_crop', 1, 'BxPersonsUploaderCoverCrop', 'modules/boonex/persons/classes/BxPersonsUploaderCoverCrop.php'),
+('bx_persons_picture_crop', 1, 'BxPersonsUploaderPictureCrop', 'modules/boonex/persons/classes/BxPersonsUploaderPictureCrop.php');

+ 51 - 0
modules/boonex/profiler/updates/12.0.0_13.0.0/install/config.php

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

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

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

+ 4 - 0
modules/boonex/profiler/updates/12.0.0_13.0.0/install/sql/enable.sql

@@ -0,0 +1,4 @@
+-- SETTINGS
+UPDATE `sys_options` SET `caption`='Log additional debug info with each long sql query' WHERE `name`='bx_profiler_long_sql_queries_debug';
+UPDATE `sys_options` SET `caption`='Log additional debug info with each long module query' WHERE `name`='bx_profiler_long_module_query_debug';
+UPDATE `sys_options` SET `caption`='Log additional debug info with each long page open' WHERE `name`='bx_profiler_long_page_debug';

+ 68 - 0
modules/boonex/profiler/updates/12.0.0_13.0.0/source/install/config.php

@@ -0,0 +1,68 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Profiler Profiler
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_profiler',
+    'title' => 'Profiler',
+    'note' => 'Measure different site timings.',
+    'version' => '13.0.0',
+    'vendor' => 'Boonex',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '13.0.0-B4'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/profiler/',
+    'home_uri' => 'profiler',
+
+    'db_prefix' => 'bx_profiler_',
+    'class_prefix' => 'BxProfiler',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Boonex Profiler',
+
+    /**
+     * 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(),
+);
+
+/** @} */

+ 49 - 0
modules/boonex/profiler/updates/12.0.0_13.0.0/source/install/sql/enable.sql

@@ -0,0 +1,49 @@
+-- settings
+SET @iTypeOrder = (SELECT MAX(`order`) FROM `sys_options_types` WHERE `group` = 'modules');
+INSERT INTO `sys_options_types` (`group`, `name`, `caption`, `icon`, `order`) VALUES 
+('modules', 'bx_profiler', 'Profiler', 'bx_profiler@modules/boonex/profiler/|std-icon.svg', IF(NOT ISNULL(@iTypeOrder), @iTypeOrder + 1, 1));
+SET @iTypeId = LAST_INSERT_ID();
+
+
+INSERT INTO `sys_options_categories` (`type_id`, `name`, `caption`, `order` )  
+VALUES (@iTypeId, 'bx_profiler', 'Debug Panel', 1);
+SET @iCategoryId = LAST_INSERT_ID();
+INSERT INTO `sys_options` (`category_id`, `name`, `value`, `caption`, `type`, `extra`, `check`, `check_error`, `order`) VALUES
+(@iCategoryId, 'bx_profiler_show_debug_panel', 'none', 'Show debug panel below the page for', 'select', 'none,admins,all', '', '', 1);
+
+
+INSERT INTO `sys_options_categories` (`type_id`, `name`, `caption`, `order` )  
+VALUES (@iTypeId, 'bx_profiler_sql_querues', 'SQL Queries', 2);
+SET @iCategoryId = LAST_INSERT_ID();
+INSERT INTO `sys_options` (`category_id`, `name`, `value`, `caption`, `type`, `extra`, `check`, `check_error`, `order`) VALUES
+(@iCategoryId, 'bx_profiler_long_sql_queries_log', 'on', 'Log long sql queries', 'checkbox', '', '', '', 1),
+(@iCategoryId, 'bx_profiler_long_sql_queries_time', '2', 'Time in seconds of long sql query', 'digit', '', '', '', 2),
+(@iCategoryId, 'bx_profiler_long_sql_queries_debug', '', 'Log additional debug info with each long sql query', 'checkbox', '', '', '', 3);
+
+
+INSERT INTO `sys_options_categories` (`type_id`, `name`, `caption`, `order` )  
+VALUES (@iTypeId, 'bx_profiler_modules_queries', 'Modules Queries', 3);
+SET @iCategoryId = LAST_INSERT_ID();
+INSERT INTO `sys_options` (`category_id`, `name`, `value`, `caption`, `type`, `extra`, `check`, `check_error`, `order`) VALUES
+(@iCategoryId, 'bx_profiler_long_module_query_log', 'on', 'Log long modules queries', 'checkbox', '', '', '', 1),
+(@iCategoryId, 'bx_profiler_long_module_query_time', '3', 'Time in seconds of long module query', 'digit', '', '', '', 2),
+(@iCategoryId, 'bx_profiler_long_module_query_debug', '', 'Log additional debug info with each long module query', 'checkbox', '', '', '', 3);
+
+
+INSERT INTO `sys_options_categories` (`type_id`, `name`, `caption`, `order` )  
+VALUES (@iTypeId, 'bx_profiler_page_opens', 'Pages opens', 4);
+SET @iCategoryId = LAST_INSERT_ID();
+INSERT INTO `sys_options` (`category_id`, `name`, `value`, `caption`, `type`, `extra`, `check`, `check_error`, `order`) VALUES
+(@iCategoryId, 'bx_profiler_long_page_log', 'on', 'Log long page opens', 'checkbox', '', '', '', 1),
+(@iCategoryId, 'bx_profiler_long_page_time', '5', 'Time in seconds of long page open', 'digit', '', '', '', 2),
+(@iCategoryId, 'bx_profiler_long_page_debug', '', 'Log additional debug info with each long page open', 'checkbox', '', '', '', 3);
+
+-- ALERTS
+
+INSERT INTO `sys_alerts_handlers` (`name`, `class`, `file`, `service_call`) VALUES 
+('bx_profiler', 'BxProfilerAlertsResponse', 'modules/boonex/profiler/classes/BxProfilerAlertsResponse.php', '');
+SET @iHandler := LAST_INSERT_ID();
+
+INSERT INTO `sys_alerts` (`unit`, `action`, `handler_id`) VALUES
+('system', 'begin', @iHandler);
+

+ 51 - 0
modules/boonex/smtpmailer/updates/13.0.0_13.0.1/install/config.php

@@ -0,0 +1,51 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'title' => 'SMTP Mailer',
+    'version_from' => '13.0.0',
+    'version_to' => '13.0.1',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '13.0.0-B4'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/smtpmailer/updates/update_13.0.0_13.0.1/',
+    'home_uri' => 'smtpmailer_update_1300_1301',
+
+    'module_dir' => 'boonex/smtpmailer/',
+    'module_uri' => 'smtpmailer',
+
+    'db_prefix' => 'bx_smtp_',
+    'class_prefix' => 'BxSMTP',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_files' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'SMTP Mailer',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

+ 13 - 0
modules/boonex/smtpmailer/updates/13.0.0_13.0.1/install/installer.php

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

+ 6 - 0
modules/boonex/smtpmailer/updates/13.0.0_13.0.1/install/langs/en.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources name="en" flag="gb" title="English">
+	<string_add name="_bx_smtp_option_test_mode"><![CDATA[Test mode (reroute all emails to single email address)]]></string_add>
+    <string_add name="_bx_smtp_option_test_email"><![CDATA[Test email]]></string_add>
+    <string_add name="_bx_smtp_option_test_subj"><![CDATA[Test subject prefix]]></string_add>
+</resources>

+ 7 - 0
modules/boonex/smtpmailer/updates/13.0.0_13.0.1/install/sql/enable.sql

@@ -0,0 +1,7 @@
+-- SETTINGS
+SET @iCategId = (SELECT `id` FROM `sys_options_categories` WHERE `name`='bx_smtp_general' LIMIT  1);
+
+INSERT IGNORE INTO `sys_options` (`name`, `value`, `category_id`, `caption`, `type`, `check`, `check_error`, `order`, `extra`) VALUES
+('bx_smtp_test_mode', '', @iCategId, '_bx_smtp_option_test_mode', 'checkbox', '', '', 100, ''),
+('bx_smtp_test_email', '', @iCategId, '_bx_smtp_option_test_email', 'digit', '', '', 102, ''),
+('bx_smtp_test_subj', '[TEST] ', @iCategId, '_bx_smtp_option_test_subj', 'digit', '', '', 104, '');

+ 210 - 0
modules/boonex/smtpmailer/updates/13.0.0_13.0.1/source/classes/BxSMTPModule.php

@@ -0,0 +1,210 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    SMTPMailer SMTP Mailer
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxSMTPModule extends BxDolModule
+{
+    function __construct(&$aModule)
+    {
+        parent::__construct($aModule);
+    }
+
+    function serviceSend ($sRecipientEmail, $sMailSubject, $sMailBody, $sMailHeader, $sMailParameters, $isHtml, $aRecipientInfo = array(), $aCustomHeaders = array())
+    {
+        $iRet = true;
+        $sErrorMessage = '';
+
+        if ($sRecipientEmail) {
+
+            try {
+
+                $mail = new PHPMailer\PHPMailer\PHPMailer(true);
+
+                if ('on' == getParam('bx_smtp_on'))
+                    $mail->IsSMTP();
+                // $mail->SMTPDebug = 2;
+
+                $mail->CharSet = 'UTF-8';
+
+                // smtp server auth or not
+                $mail->SMTPAuth = 'on' == getParam('bx_smtp_auth') ? true : false;
+
+                // from settings, smtp server secure ssl/tls
+                $sParamSecure = getParam('bx_smtp_secure');
+                if ('SSL' == $sParamSecure || 'TLS' == $sParamSecure) {
+
+                    $mail->SMTPSecure = strtolower($sParamSecure);
+
+                    if ('on' == getParam('bx_smtp_allow_selfsigned')) {
+                        $mail->SMTPOptions = array(
+                            'ssl' => array(
+                                'verify_peer' => false,
+                                'verify_peer_name' => false,
+                                'allow_self_signed' => true
+                            )
+                        );
+                    }
+                }
+
+                // from settings, smtp server
+                $sParamHost = getParam('bx_smtp_host');
+                if ($sParamHost)
+                    $mail->Host = $sParamHost;
+
+                // smtp port 25, 465
+                $sParamPort = getParam('bx_smtp_port');
+                if ((int)$sParamPort > 0)
+                    $mail->Port = $sParamPort;
+
+                // from settings, username and passord of smtp server
+                $mail->Username = getParam ('bx_smtp_username');
+                $mail->Password = getParam ('bx_smtp_password');
+
+                if (!isset($aCustomHeaders['From'])) {
+                    $sParamSender = trim(getParam('bx_smtp_from_email'));
+                    if ($sParamSender)
+                        $mail->From = $sParamSender;
+                    else
+                        $mail->From = getParam('site_email_notify');
+
+                    // get site name or some other name as sender's name
+                    $mail->FromName = getParam ('bx_smtp_from_name');
+                } 
+
+                if (!isset($aCustomHeaders['Subject']))
+                    $mail->Subject = $sMailSubject;
+
+                if ($isHtml) {
+                    $mail->Body = $sMailBody;
+                    $mail->AltBody = $isHtml ? strip_tags($sMailBody) : $sMailBody;
+                } else {
+                    $mail->Body = $sMailBody;
+                }
+
+                $mail->WordWrap = 50; // set word wrap
+
+                if (getParam('bx_smtp_test_mode')) {
+                    $aCustomHeaders['X-Original-To'] = $sRecipientEmail;
+                    if (isset($aCustomHeaders['Subject']))
+                        $aCustomHeaders['Subject'] = getParam('bx_smtp_test_subj') . $aCustomHeaders['Subject'];
+                    else
+                        $mail->Subject = getParam('bx_smtp_test_subj') . $mail->Subject;
+                }
+
+                $mail->AddAddress(getParam('bx_smtp_test_mode') ? getParam('bx_smtp_test_email') : $sRecipientEmail);
+
+                $mail->IsHTML($isHtml ? true : false);
+
+                foreach ($aCustomHeaders as $sHeaderName => $sHeaderValue) {
+                    if ('From' == $sHeaderName) {
+                        if (preg_match('/(.+)<(.+)>/', $sHeaderValue, $m)) {
+                            $mail->setFrom($m[2], trim($m[1]), false);
+                        }
+                        else {
+                            $mail->setFrom($sHeaderValue, '', false);
+                        }
+                    } 
+                    else {
+                        $mail->addCustomHeader($sHeaderName, $sHeaderValue);
+                    }
+                }
+
+                $mail->Send();
+                
+            } catch (PHPMailer\PHPMailer\Exception $e) {
+                $iRet = false;
+                $sErrorMessage = $e->getMessage();
+                $this->log("Mailer Error ($sRecipientEmail): " . $sErrorMessage);
+            }
+        }
+
+        //--- create system event [begin]
+        $aAlertData = array(
+            'test_mode' => (bool)getParam('bx_smtp_test_mode'),
+            'email'     => $sRecipientEmail,
+            'subject'   => $sMailSubject,
+            'body'      => $sMailBody,
+            'header'    => $sMailHeader,
+            'params'    => $sMailParameters,
+            'recipient' => $aRecipientInfo,
+            'html'      => $isHtml,
+            'ret'       => $iRet,
+            'error_message' => $sErrorMessage,            
+        );
+        bx_alert('profile', 'send_mail', $aRecipientInfo && isset($aRecipientInfo['ID']) ? $aRecipientInfo['ID'] : 0, '', $aAlertData);
+        //--- create system event [ end ]
+
+        return $iRet;
+    }
+
+    function formTester()
+    {
+        $sMsg  = '';
+        if (isset($_POST['tester_submit']) && $_POST['tester_submit']) {
+
+            $isHTML = bx_get('html') == 'on' ? true : false;
+            $sRecipient = bx_process_pass(bx_get('recipient'));
+            $sSubj = bx_get('subject');
+            $sBody = bx_process_pass(bx_get('body'), $isHTML ? BX_DATA_HTML : BX_DATA_TEXT);
+
+            if (sendMail($sRecipient, $sSubj, $sBody, 0, array(), BX_EMAIL_SYSTEM, $isHTML ? 'html' : ''))
+                $sMsg = MsgBox(_t('_bx_smtp_send_ok'));
+            else
+                $sMsg = MsgBox(_t('_bx_smtp_send_fail'));
+        }
+
+        $aForm = array(
+            'form_attrs' => array(
+                'method'   => 'post',
+            ),
+            'inputs' => array (
+                'recipient' => array(
+                    'type' => 'text',
+                    'name' => 'recipient',
+                    'caption' => _t('_bx_smtp_recipient'),
+                    'value' => '',
+                ),
+                'subject' => array(
+                    'type' => 'text',
+                    'name' => 'subject',
+                    'caption' => _t('_bx_smtp_subject'),
+                    'value' => '',
+                ),
+                'body' => array(
+                    'type' => 'textarea',
+                    'name' => 'body',
+                    'caption' => _t('_bx_smtp_body'),
+                    'value' => '',
+                ),
+                'html' => array(
+                    'type' => 'checkbox',
+                    'name' => 'html',
+                    'caption' => _t('_bx_smtp_is_html'),
+                    'checked' => false,
+                ),
+                'Submit' => array(
+                    'type' => 'submit',
+                    'name' => 'tester_submit',
+                    'value' => _t("_Submit"),
+                ),
+            )
+        );
+
+        $oForm = new BxTemplFormView($aForm);
+        return $sMsg . $oForm->getCode();
+    }
+
+    function log ($s)
+    {
+        bx_log('bx_smtp_mailer', $s);
+    }
+}
+
+/** @} */

+ 68 - 0
modules/boonex/smtpmailer/updates/13.0.0_13.0.1/source/install/config.php

@@ -0,0 +1,68 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    SMTPMailer SMTP Mailer
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_smtp',
+    'title' => 'SMTP Mailer',
+    'note' => 'Use remote SMTP server for sending mails.',
+    'version' => '13.0.1',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '13.0.0-B4'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/smtpmailer/',
+    'home_uri' => 'smtpmailer',
+
+    'db_prefix' => 'bx_smtp_',
+    'class_prefix' => 'BxSMTP',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'SMTP Mailer',
+
+    /**
+     * 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(),
+);
+
+/** @} */

+ 59 - 0
modules/boonex/smtpmailer/updates/13.0.0_13.0.1/source/install/langs/en.xml

@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources name="en" flag="gb" title="English">
+	<string name="_bx_smtp"><![CDATA[SMTP Mailer]]></string>
+	<string name="_bx_smtp_tester"><![CDATA[Test]]></string>
+	<string name="_bx_smtp_recipient"><![CDATA[Recipient]]></string>
+	<string name="_bx_smtp_subject"><![CDATA[Subject]]></string>
+	<string name="_bx_smtp_body"><![CDATA[Body]]></string>
+	<string name="_bx_smtp_is_html"><![CDATA[Is HTML?]]></string>
+	<string name="_bx_smtp_send_ok"><![CDATA[Mail has been successfully sent]]></string>
+	<string name="_bx_smtp_send_fail"><![CDATA[Mail send failed]]></string>
+	<string name="_bx_smtp_help"><![CDATA[Help]]></string>
+	<string name="_bx_smtp_help_text"><![CDATA[
+        <b>SMTP authentication </b> - most SMTP servers requires SMTP authentication, most probably you need to enable it.
+        <br />
+        <b>SMTP server name</b> - is it better to send mail from your site SMTP server, so it is probably the name of your site or localhost.
+        <br />
+        <b>SMTP username/SMTP password</b> - registered email account username and password, it is better to create different account for this purpose, like no-reply@mysite.com.
+        <br />
+        <b>From name of the message</b> - recipients will see this name as email sender, so it is probably your site name.
+        <br />
+        <b>Is your SMTP server requires secure connection</b> - you can disable it if your hostname is localhost, secure connection is not needed if you send mails from localhost.
+        <br />
+        <b>Enable SMTP mailer</b> - it is possible to disable SMTP mailer at all, for example if you have temporary problems with your SMTP server. 
+        <br />
+        <b>Override default sender email address</b> - set this the same as <b>SMTP username</b> email address, to avoid problems with mail marked as spam.
+        <br />
+        <br />
+        Alternatively, you can get above options from your desktop mail client, if you are going to use the same email address for sending mail from your site.
+        
+        <hr class="bx-def-hr" />
+
+        If emails still go to spam folder, check the following:
+        <ul>
+            <li>Try to set "Override default sender email address" field the same as "SMTP username" email address</li>
+            <li>Make sure that "Override default sender email address" is valid and exists</li>
+            <li>Try to change default email templates, it maybe that standard ones can be in spam filters, since they are used on a lot of sites by default</li>
+            <li>Ask your members to add your site email to their contacts - when email is in user's contact list it always goes to inbox</li>
+            <li><a href="http://www.boonex.com/trac/dolphin/wiki/TutorialTweakingSpamFilters" target="_blank">This is great tutorial</a> on how to whitelist your server in many popular webmail services, including yahoo</li>
+        </ul>
+]]></string>
+    <string name="_bx_smtp_adm_stg_cpt_type"><![CDATA[SMTP Mailer]]></string>
+    <string name="_bx_smtp_adm_stg_cpt_category_general"><![CDATA[General]]></string>
+    
+    <string name="_bx_smtp_option_on"><![CDATA[Enable SMTP mailer]]></string>
+    <string name="_bx_smtp_option_auth"><![CDATA[SMTP authentication (Is your SMTP server requires username and password?)]]></string>
+    <string name="_bx_smtp_option_username"><![CDATA[SMTP username (only if SMTP authentication is enabled)]]></string>
+    <string name="_bx_smtp_option_password"><![CDATA[SMTP password (only if SMTP authentication is enabled)]]></string>
+    <string name="_bx_smtp_option_host"><![CDATA[SMTP server name or IP address]]></string>
+    <string name="_bx_smtp_option_port"><![CDATA[SMTP server port number (25 - default, 465 - for secure ssl connection, 587 - for secure tls connection)]]></string>
+    <string name="_bx_smtp_option_secure"><![CDATA[Is your SMTP server requires secure connection]]></string>
+    <string name="_bx_smtp_option_allow_selfsigned"><![CDATA[Allow self-signed certificates]]></string>
+    <string name="_bx_smtp_option_from_name"><![CDATA['From' name of the message]]></string>
+    <string name="_bx_smtp_option_from_email"><![CDATA[Override default sender email address]]></string>
+    <string name="_bx_smtp_option_test_mode"><![CDATA[Test mode (reroute all emails to single email address)]]></string>
+    <string name="_bx_smtp_option_test_email"><![CDATA[Test email]]></string>
+    <string name="_bx_smtp_option_test_subj"><![CDATA[Test subject prefix]]></string>
+    <string name="_bx_smtp_mailer_log"><![CDATA[SMTP Mailer: sending errors]]></string>
+</resources>
+

+ 41 - 0
modules/boonex/smtpmailer/updates/13.0.0_13.0.1/source/install/sql/enable.sql

@@ -0,0 +1,41 @@
+
+-- settings
+
+SET @iTypeOrder = (SELECT MAX(`order`) FROM `sys_options_types` WHERE `group` = 'modules');
+INSERT INTO `sys_options_types` (`group`, `name`, `caption`, `icon`, `order`) VALUES 
+('modules', 'bx_smtp', '_bx_smtp_adm_stg_cpt_type', 'bx_smtpmailer@modules/boonex/smtpmailer/|std-icon.svg', IF(NOT ISNULL(@iTypeOrder), @iTypeOrder + 1, 1));
+SET @iTypeId = LAST_INSERT_ID();
+
+INSERT INTO `sys_options_categories` (`type_id`, `name`, `caption`, `order` )  
+VALUES (@iTypeId, 'bx_smtp_general', '_bx_smtp_adm_stg_cpt_category_general', 1);
+SET @iCategId = LAST_INSERT_ID();
+
+INSERT INTO `sys_options` (`name`, `value`, `category_id`, `caption`, `type`, `check`, `check_error`, `order`, `extra`) VALUES
+('bx_smtp_on', '', @iCategId, '_bx_smtp_option_on', 'checkbox', '', '', 10, ''),
+('bx_smtp_auth', '', @iCategId, '_bx_smtp_option_auth', 'checkbox', '', '', 20, ''),
+('bx_smtp_username', '', @iCategId, '_bx_smtp_option_username', 'digit', '', '', 30, ''),
+('bx_smtp_password', '', @iCategId, '_bx_smtp_option_password', 'digit', '', '', 40, ''),
+('bx_smtp_host', '', @iCategId, '_bx_smtp_option_host', 'digit', '', '', 50, ''),
+('bx_smtp_port', '25', @iCategId, '_bx_smtp_option_port', 'digit', '', '', 60, ''),
+('bx_smtp_secure', 'Not Secure', @iCategId, '_bx_smtp_option_secure', 'select', '', '', 70, 'Not Secure,SSL,TLS'), 
+('bx_smtp_allow_selfsigned', '', @iCategId, '_bx_smtp_option_allow_selfsigned', 'checkbox', '', '', 74, ''),
+('bx_smtp_from_name', '', @iCategId, '_bx_smtp_option_from_name', 'digit', '', '', 80, ''),
+('bx_smtp_from_email', '', @iCategId, '_bx_smtp_option_from_email', 'digit', '', '', 90, ''),
+('bx_smtp_test_mode', '', @iCategId, '_bx_smtp_option_test_mode', 'checkbox', '', '', 100, ''),
+('bx_smtp_test_email', '', @iCategId, '_bx_smtp_option_test_email', 'digit', '', '', 102, ''),
+('bx_smtp_test_subj', '[TEST] ', @iCategId, '_bx_smtp_option_test_subj', 'digit', '', '', 104, '');
+
+-- logs
+
+INSERT INTO `sys_objects_logs` (`object`, `module`, `logs_storage`, `title`, `active`, `class_name`, `class_file`) VALUES
+('bx_smtp_mailer', 'system', 'Auto', '_bx_smtp_mailer_log', 1, '', '');
+
+-- alerts
+
+INSERT INTO `sys_alerts_handlers` (`name`, `class`, `file`, `service_call`) VALUES 
+('bx_smtp', 'BxSMTPAlertsResponse', 'modules/boonex/smtpmailer/classes/BxSMTPAlertsResponse.php', '');
+SET @iHandler := LAST_INSERT_ID();
+
+INSERT INTO `sys_alerts` (`unit`, `action`, `handler_id`) VALUES
+('system', 'before_send_mail', @iHandler);
+

+ 51 - 0
modules/boonex/spaces/updates/13.0.2_13.0.3/install/config.php

@@ -0,0 +1,51 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'title' => 'Spaces',
+    'version_from' => '13.0.2',
+    'version_to' => '13.0.3',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '13.0.0-B4'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/spaces/updates/update_13.0.2_13.0.3/',
+    'home_uri' => 'spaces_update_1302_1303',
+
+    'module_dir' => 'boonex/spaces/',
+    'module_uri' => 'spaces',
+
+    'db_prefix' => 'bx_spaces_',
+    'class_prefix' => 'BxSpaces',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_files' => 1,
+        'update_languages' => 0,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Spaces',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

+ 13 - 0
modules/boonex/spaces/updates/13.0.2_13.0.3/install/installer.php

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

+ 7 - 0
modules/boonex/spaces/updates/13.0.2_13.0.3/install/sql/enable.sql

@@ -0,0 +1,7 @@
+-- MENUS
+UPDATE `sys_menu_items` SET `active`='0' WHERE `set_name`='bx_spaces_menu_manage_tools' AND `name`='delete-with-content';
+
+
+-- GRIDS
+UPDATE `sys_grid_actions` SET `active`='0' WHERE `object`='bx_spaces_administration' AND `type`='bulk' AND `name`='delete_with_content';
+UPDATE `sys_grid_actions` SET `active`='0' WHERE `object`='bx_spaces_common' AND `type`='bulk' AND `name`='delete_with_content';

+ 152 - 0
modules/boonex/spaces/updates/13.0.2_13.0.3/source/install/config.php

@@ -0,0 +1,152 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defdroup    Spaces Spaces
+ * @indroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_spaces',
+    'title' => 'Spaces',
+    'note' => 'Spaces functionality.',
+    'version' => '13.0.3',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '13.0.0-B4'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/spaces/',
+    'home_uri' => 'spaces',
+
+    'db_prefix' => 'bx_spaces_',
+    'class_prefix' => 'BxSpaces',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Spaces',
+
+    /**
+     * 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_spaces_pics'
+    ),
+
+    /**
+     * Transcoders.
+     */
+    'transcoders' => array(
+        'bx_spaces_icon',
+        'bx_spaces_thumb',
+        'bx_spaces_avatar',
+        'bx_spaces_avatar_big',
+        'bx_spaces_picture',
+        'bx_spaces_cover',
+        'bx_spaces_cover_thumb',
+        'bx_spaces_gallery'
+    ),
+
+    /**
+     * Extended Search Forms.
+     */
+    'esearches' => array(
+        'bx_spaces',
+        'bx_spaces_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',
+    ),
+);
+
+/** @} */

+ 681 - 0
modules/boonex/spaces/updates/13.0.2_13.0.3/source/install/sql/enable.sql

@@ -0,0 +1,681 @@
+
+-- SETTINGS
+
+SET @iTypeOrder = (SELECT MAX(`order`) FROM `sys_options_types` WHERE `group` = 'modules');
+INSERT INTO `sys_options_types`(`group`, `name`, `caption`, `icon`, `order`) VALUES 
+('modules', 'bx_spaces', '_bx_spaces', 'bx_spaces@modules/boonex/spaces/|std-icon.svg', IF(ISNULL(@iTypeOrder), 1, @iTypeOrder + 1));
+SET @iTypeId = LAST_INSERT_ID();
+
+INSERT INTO `sys_options_categories` (`type_id`, `name`, `caption`, `order`)
+VALUES (@iTypeId, 'bx_spaces', '_bx_spaces', 1);
+SET @iCategId = LAST_INSERT_ID();
+
+INSERT INTO `sys_options` (`name`, `value`, `category_id`, `caption`, `type`, `extra`, `check`, `check_error`, `order`) VALUES
+('bx_spaces_enable_multilevel_hierarchy', '', @iCategId, '_bx_spaces_option_enable_multilevel_hierarchy', 'checkbox', '', '', '', 0),
+('bx_spaces_enable_auto_approve', 'on', @iCategId, '_bx_spaces_option_enable_auto_approve', 'checkbox', '', '', '', 1),
+('bx_spaces_num_connections_quick', '6', @iCategId, '_bx_spaces_option_num_connections_quick', 'digit', '', '', '', 10),
+('bx_spaces_per_page_browse', '24', @iCategId, '_bx_spaces_option_per_page_browse', 'digit', '', '', '', 11),
+('bx_spaces_num_rss', '10', @iCategId, '_bx_spaces_option_num_rss', 'digit', '', '', '', 12),
+('bx_spaces_per_page_browse_showcase', '32', @iCategId, '_sys_option_per_page_browse_showcase', 'digit', '', '', '', 15),
+('bx_spaces_per_page_browse_recommended', '10', @iCategId, '_sys_option_per_page_browse_recommended', 'digit', '', '', '', 16),
+('bx_spaces_per_page_for_favorites_lists', '5', @iCategId, '_bx_spaces_option_per_page_for_favorites_lists', 'digit', '', '', '', 17),
+('bx_spaces_searchable_fields', 'space_name,space_desc', @iCategId, '_bx_spaces_option_searchable_fields', 'list', 'a:2:{s:6:"module";s:9:"bx_spaces";s:6:"method";s:21:"get_searchable_fields";}', '', '', 30),
+('bx_spaces_members_mode', '', @iCategId, '_bx_spaces_option_members_mode', 'select', 'a:2:{s:6:"module";s:9:"bx_spaces";s:6:"method";s:24:"get_options_members_mode";}', '', '', 40),
+('bx_spaces_internal_notifications', '', @iCategId, '_bx_spaces_option_internal_notifications', 'checkbox', '', '', '', 50);
+
+
+-- PAGES
+
+-- PAGE: create profile
+
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_spaces_create_profile', 'create-space-profile', '_bx_spaces_page_title_sys_create_profile', '_bx_spaces_page_title_create_profile', 'bx_spaces', 5, 2147483647, 1, 'page.php?i=create-space-profile', '', '', '', 0, 1, 0, '', '');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_spaces_create_profile', 1, 'bx_spaces', '_bx_spaces_page_block_title_create_profile', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_spaces\";s:6:\"method\";s:13:\"entity_create\";}', 0, 1, 1);
+
+-- PAGE: view profile
+
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_spaces_view_profile', 'view-space-profile', '_bx_spaces_page_title_sys_view_profile', '_bx_spaces_page_title_view_profile', 'bx_spaces', 10, 2147483647, 1, 'page.php?i=view-space-profile', '', '', '', 0, 1, 0, 'BxSpacesPageEntry', 'modules/boonex/spaces/classes/BxSpacesPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES
+('bx_spaces_view_profile', 1, 'bx_spaces', '', '_bx_spaces_page_block_title_entry_social_sharing', 13, 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_spaces\";s:6:\"method\";s:21:\"entity_social_sharing\";}', 0, 0, 0, 0),
+('bx_spaces_view_profile', 1, 'bx_spaces', '', '_bx_spaces_page_block_title_entry_all_actions', 13, 2147483647, 'service', 'a:2:{s:6:"module";s:9:"bx_spaces";s:6:"method";s:18:"entity_all_actions";}', 0, 0, 0, 0),
+('bx_spaces_view_profile', 2, 'bx_spaces', '', '_bx_spaces_page_block_title_profile_info', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_spaces\";s:6:\"method\";s:11:\"entity_info\";}', 0, 0, 1, 0),
+('bx_spaces_view_profile', 2, 'bx_spaces', '', '_bx_spaces_page_block_title_parent', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_spaces\";s:6:\"method\";s:13:\"entity_parent\";}', 0, 0, 1, 1),
+('bx_spaces_view_profile', 2, 'bx_spaces', '', '_bx_spaces_page_block_title_childs', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_spaces\";s:6:\"method\";s:13:\"entity_childs\";}', 0, 0, 1, 2),
+('bx_spaces_view_profile', 3, 'bx_spaces', '', '_bx_spaces_page_block_title_profile_location', 13, 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_spaces\";s:6:\"method\";s:15:\"entity_location\";}', 0, 0, 0, 0),
+('bx_spaces_view_profile', 3, 'bx_spaces', '', '_bx_spaces_page_block_title_fans', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_spaces\";s:6:\"method\";s:4:\"fans\";}', 0, 0, 1, 0),
+('bx_spaces_view_profile', 3, 'bx_spaces', '', '_bx_spaces_page_block_title_admins', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_spaces\";s:6:\"method\";s:6:\"admins\";}', 0, 0, 1, 1),
+('bx_spaces_view_profile', 3, 'bx_spaces', '', '_bx_spaces_page_block_title_profile_location', 3, 2147483647, 'service', 'a:4:{s:6:\"module\";s:6:\"system\";s:6:\"method\";s:13:\"locations_map\";s:6:\"params\";a:2:{i:0;s:9:\"bx_spaces\";i:1;s:12:\"{content_id}\";}s:5:\"class\";s:20:\"TemplServiceMetatags\";}', 0, 0, 1, 2),
+('bx_spaces_view_profile', 4, 'bx_spaces', '', '_bx_spaces_page_block_title_profile_description', 13, 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_spaces\";s:6:\"method\";s:17:\"entity_text_block\";}', 0, 0, 1, 0),
+('bx_spaces_view_profile', 4, 'bx_spaces', '', '_bx_spaces_page_block_title_profile_comments', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_spaces\";s:6:\"method\";s:15:\"entity_comments\";}', 0, 0, 0, 0),
+('bx_spaces_view_profile', 2, 'bx_spaces', '', '_bx_spaces_page_block_title_entry_reports', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_spaces\";s:6:\"method\";s:14:\"entity_reports\";}', 0, 0, 1, 6);
+
+
+-- PAGE: view closed profile 
+
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_spaces_view_profile_closed', 'view-space-profile-closed', '_bx_spaces_page_title_sys_view_profile_closed', '_bx_spaces_page_title_view_profile', 'bx_spaces', 10, 2147483647, 1, 'page.php?i=view-space-profile', '', '', '', 0, 1, 0, 'BxSpacesPageEntry', 'modules/boonex/spaces/classes/BxSpacesPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_spaces_view_profile_closed', 2, 'bx_spaces', '', '_bx_spaces_page_block_title_profile_info', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_spaces\";s:6:\"method\";s:11:\"entity_info\";}', 0, 0, 1, 0),
+('bx_spaces_view_profile_closed', 3, 'bx_spaces', '', '_bx_spaces_page_block_title_fans', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_spaces\";s:6:\"method\";s:4:\"fans\";}', 0, 0, 1, 0);
+
+-- PAGE: edit profile
+
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_spaces_edit_profile', 'edit-space-profile', '_bx_spaces_page_title_sys_edit_profile', '_bx_spaces_page_title_edit_profile', 'bx_spaces', 5, 2147483647, 1, 'page.php?i=edit-space-profile', '', '', '', 0, 1, 0, 'BxSpacesPageEntry', 'modules/boonex/spaces/classes/BxSpacesPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_spaces_edit_profile', 1, 'bx_spaces', '_bx_spaces_page_block_title_edit_profile', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_spaces\";s:6:\"method\";s:11:\"entity_edit\";}', 0, 0, 0);
+
+-- PAGE: edit profile cover
+
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_spaces_edit_profile_cover', 'edit-space-cover', '_bx_spaces_page_title_sys_edit_profile_cover', '_bx_spaces_page_title_edit_profile_cover', 'bx_spaces', 5, 2147483647, 1, 'page.php?i=edit-space-cover', '', '', '', 0, 1, 0, 'BxSpacesPageEntry', 'modules/boonex/spaces/classes/BxSpacesPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_spaces_edit_profile_cover', 1, 'bx_spaces', '_bx_spaces_page_block_title_edit_profile_cover', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_spaces\";s:6:\"method\";s:17:\"entity_edit_cover\";}', 0, 0, 0);
+
+-- PAGE: invite members
+
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_spaces_invite', 'invite-to-space', '_bx_spaces_page_title_sys_invite_to_space', '_bx_spaces_page_title_invite_to_space', 'bx_spaces', 5, 2147483647, 1, 'page.php?i=invite-to-space', '', '', '', 0, 1, 0, 'BxSpacesPageEntry', 'modules/boonex/spaces/classes/BxSpacesPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_spaces_invite', 1, 'bx_spaces', '_bx_spaces_page_block_title_invite_to_space', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_spaces\";s:6:\"method\";s:13:\"entity_invite\";}', 0, 0, 0);
+
+-- PAGE: delete profile
+
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_spaces_delete_profile', 'delete-space-profile', '_bx_spaces_page_title_sys_delete_profile', '_bx_spaces_page_title_delete_profile', 'bx_spaces', 5, 2147483647, 1, 'page.php?i=delete-space-profile', '', '', '', 0, 1, 0, 'BxSpacesPageEntry', 'modules/boonex/spaces/classes/BxSpacesPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_spaces_delete_profile', 1, 'bx_spaces', '_bx_spaces_page_block_title_delete_profile', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_spaces\";s:6:\"method\";s:13:\"entity_delete\";}', 0, 0, 0);
+
+-- PAGE: join profile
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_spaces_join_profile', 'join-space-profile', '_bx_spaces_page_title_sys_join_profile', '_bx_spaces_page_title_join_profile', 'bx_spaces', 5, 2147483647, 1, 'page.php?i=join-space-profile', '', '', '', 0, 1, 0, 'BxSpacesPageEntry', 'modules/boonex/spaces/classes/BxSpacesPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_spaces_join_profile', 1, 'bx_spaces', '_bx_spaces_page_block_title_join_profile', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:9:"bx_spaces";s:6:"method";s:11:"entity_join";s:6:"params";a:1:{i:0;s:12:"{profile_id}";}}', 0, 0, 0);
+
+-- PAGE: profile info
+
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_spaces_profile_info', 'space-profile-info', '_bx_spaces_page_title_sys_profile_info', '_bx_spaces_page_title_profile_info', 'bx_spaces', 5, 2147483647, 1, 'page.php?i=space-profile-info', '', '', '', 0, 1, 0, 'BxSpacesPageEntry', 'modules/boonex/spaces/classes/BxSpacesPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_spaces_profile_info', 1, 'bx_spaces', '_bx_spaces_page_block_title_system_profile_info', '_bx_spaces_page_block_title_profile_info_link', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_spaces\";s:6:\"method\";s:16:\"entity_info_full\";}', 0, 0, 1, 1),
+('bx_spaces_profile_info', 1, 'bx_spaces', '', '_bx_spaces_page_block_title_profile_description', 13, 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_spaces\";s:6:\"method\";s:17:\"entity_text_block\";}', 0, 0, 1, 2);
+
+-- PAGE: manage profile pricing
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_spaces_profile_pricing', 'edit-space-pricing', '_bx_spaces_page_title_sys_profile_pricing', '_bx_spaces_page_title_profile_pricing', 'bx_spaces', 5, 2147483647, 1, 'page.php?i=edit-space-pricing', '', '', '', 0, 1, 0, 'BxSpacesPageEntry', 'modules/boonex/spaces/classes/BxSpacesPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_spaces_profile_pricing', 1, 'bx_spaces', '_bx_spaces_page_block_title_system_profile_pricing', '_bx_spaces_page_block_title_profile_pricing_link', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:9:"bx_spaces";s:6:"method";s:14:"entity_pricing";s:6:"params";a:1:{i:0;s:12:"{profile_id}";}}', 0, 0, 1, 1);
+
+-- PAGE: space fans
+
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_spaces_fans', 'space-fans', '_bx_spaces_page_title_sys_space_fans', '_bx_spaces_page_title_space_fans', 'bx_spaces', 5, 2147483647, 1, 'page.php?i=space-fans', '', '', '', 0, 1, 0, 'BxSpacesPageEntry', 'modules/boonex/spaces/classes/BxSpacesPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_spaces_fans', 1, 'bx_spaces', '_bx_spaces_page_block_title_system_fans', '_bx_spaces_page_block_title_fans_link', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:9:"bx_spaces";s:6:"method";s:10:"fans_table";}', 0, 0, 1, 1),
+('bx_spaces_fans', 1, 'bx_spaces', '_bx_spaces_page_block_title_system_invites', '_bx_spaces_page_block_title_fans_invites', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:9:"bx_spaces";s:6:"method";s:13:"invites_table";}', 0, 0, 1, 2);
+
+-- PAGE: view entry comments
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_spaces_profile_comments', '_bx_spaces_page_title_sys_profile_comments', '_bx_spaces_page_title_profile_comments', 'bx_spaces', 5, 2147483647, 1, 'space-profile-comments', '', '', '', '', 0, 1, 0, 'BxSpacesPageEntry', 'modules/boonex/spaces/classes/BxSpacesPageEntry.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_spaces_profile_comments', 1, 'bx_spaces', '_bx_spaces_page_block_title_profile_comments', '_bx_spaces_page_block_title_profile_comments_link', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_spaces\";s:6:\"method\";s:15:\"entity_comments\";}', 0, 0, 0, 1);
+
+-- PAGE: module home
+
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_spaces_home', '_bx_spaces_page_title_sys_recent', '_bx_spaces_page_title_recent', 'bx_spaces', 5, 2147483647, 1, 'spaces-home', 'page.php?i=spaces-home', '', '', '', 0, 1, 0, 'BxSpacesPageBrowse', 'modules/boonex/spaces/classes/BxSpacesPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`, `active`) VALUES
+('bx_spaces_home', 1, 'bx_spaces', '_bx_spaces_page_block_title_featured_profiles', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:9:"bx_spaces";s:6:"method";s:15:"browse_featured";s:6:"params";a:1:{i:0;s:7:"gallery";}}', 0, 1, 0, 1),
+('bx_spaces_home', 1, 'bx_spaces', '_bx_spaces_page_block_title_latest_profiles', 11, 2147483647, 'service', 'a:3:{s:6:\"module\";s:9:\"bx_spaces\";s:6:\"method\";s:22:\"browse_recent_profiles\";s:6:"params";a:1:{i:0;b:1;}}', 0, 1, 1, 1),
+('bx_spaces_home', 1, 'bx_spaces', '_bx_spaces_page_block_title_top_level_spaces', 11, 2147483647, 'service', 'a:3:{s:6:\"module\";s:9:\"bx_spaces\";s:6:\"method\";s:16:\"browse_top_level\";s:6:"params";a:1:{i:0;b:1;}}', 0, 1, 2, 0);
+
+-- PAGE: top profiles
+
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_spaces_top', '_bx_spaces_page_title_sys_top', '_bx_spaces_page_title_top', 'bx_spaces', 5, 2147483647, 1, 'spaces-top', 'page.php?i=spaces-top', '', '', '', 0, 1, 0, 'BxSpacesPageBrowse', 'modules/boonex/spaces/classes/BxSpacesPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_spaces_top', 1, 'bx_spaces', '_bx_spaces_page_block_title_top_profiles', 11, 2147483647, 'service', 'a:3:{s:6:\"module\";s:9:\"bx_spaces\";s:6:\"method\";s:19:\"browse_top_profiles\";s:6:"params";a:1:{i:0;b:1;}}', 0, 1, 0);
+
+-- PAGE: search for entries
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_spaces_search', '_bx_spaces_page_title_sys_entries_search', '_bx_spaces_page_title_entries_search', 'bx_spaces', 5, 2147483647, 1, 'spaces-search', 'page.php?i=spaces-search', '', '', '', 0, 1, 0, 'BxSpacesPageBrowse', 'modules/boonex/spaces/classes/BxSpacesPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('bx_spaces_search', 1, 'bx_spaces', '_bx_spaces_page_block_title_search_form', 11, 2147483647, 'service', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:8:"get_form";s:6:"params";a:1:{i:0;a:1:{s:6:"object";s:9:"bx_spaces";}}s:5:"class";s:27:"TemplSearchExtendedServices";}', 0, 1, 1, 1),
+('bx_spaces_search', 1, 'bx_spaces', '_bx_spaces_page_block_title_search_results', 11, 2147483647, 'service', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:11:"get_results";s:6:"params";a:1:{i:0;a:2:{s:6:"object";s:9:"bx_spaces";s:10:"show_empty";b:1;}}s:5:"class";s:27:"TemplSearchExtendedServices";}', 0, 1, 1, 2),
+('bx_spaces_search', 1, 'bx_spaces', '_bx_spaces_page_block_title_search_form_cmts', 11, 2147483647, 'service', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:8:"get_form";s:6:"params";a:1:{i:0;a:1:{s:6:"object";s:14:"bx_spaces_cmts";}}s:5:"class";s:27:"TemplSearchExtendedServices";}', 0, 1, 0, 3),
+('bx_spaces_search', 1, 'bx_spaces', '_bx_spaces_page_block_title_search_results_cmts', 11, 2147483647, 'service', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:11:"get_results";s:6:"params";a:1:{i:0;a:2:{s:6:"object";s:14:"bx_spaces_cmts";s:10:"show_empty";b:1;}}s:5:"class";s:27:"TemplSearchExtendedServices";}', 0, 1, 0, 4);
+
+-- PAGE: joined profiles
+
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_joined_spaces', '_bx_spaces_page_title_sys_joined', '_bx_spaces_page_title_joined', 'bx_spaces', 5, 2147483647, 1, 'spaces-joined', 'page.php?i=spaces-joined', '', '', '', 0, 1, 0, 'BxSpacesPageBrowse', 'modules/boonex/spaces/classes/BxSpacesPageBrowse.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `order`) VALUES 
+('bx_joined_spaces', 1, 'bx_spaces', '_bx_spaces_page_block_title_joined_entries', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:9:"bx_spaces";s:6:"method";s:21:"browse_joined_entries";s:6:"params";a:2:{i:0;s:12:"{profile_id}";i:1;b:1;}}', 0, 1, 0);
+
+
+-- PAGE: module manage own
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_spaces_manage', '_bx_spaces_page_title_sys_manage', '_bx_spaces_page_title_manage', 'bx_spaces', 5, 2147483647, 1, 'spaces-manage', 'page.php?i=spaces-manage', '', '', '', 0, 1, 0, 'BxSpacesPageBrowse', 'modules/boonex/spaces/classes/BxSpacesPageBrowse.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_spaces_manage', 1, 'bx_spaces', '_bx_spaces_page_block_title_system_manage', '_bx_spaces_page_block_title_manage', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_spaces\";s:6:\"method\";s:12:\"manage_tools\";}}', 0, 1, 0);
+
+-- PAGE: module manage all
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_spaces_administration', '_bx_spaces_page_title_sys_manage_administration', '_bx_spaces_page_title_manage', 'bx_spaces', 5, 192, 1, 'spaces-administration', 'page.php?i=spaces-administration', '', '', '', 0, 1, 0, 'BxSpacesPageBrowse', 'modules/boonex/spaces/classes/BxSpacesPageBrowse.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_spaces_administration', 1, 'bx_spaces', '_bx_spaces_page_block_title_system_manage_administration', '_bx_spaces_page_block_title_manage', 11, 192, 'service', 'a:3:{s:6:\"module\";s:9:\"bx_spaces\";s:6:\"method\";s:12:\"manage_tools\";s:6:\"params\";a:1:{i:0;s:14:\"administration\";}}', 0, 1, 0);
+
+-- PAGE: user's spaces
+INSERT INTO `sys_objects_page`(`object`, `uri`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_spaces_joined', 'joined-spaces', '_bx_spaces_page_title_sys_joined_entries', '_bx_spaces_page_title_joined_entries', 'bx_spaces', 5, 2147483647, 1, '', '', '', '', 0, 1, 0, 'BxSpacesPageJoinedEntries', 'modules/boonex/spaces/classes/BxSpacesPageJoinedEntries.php');
+
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES
+('bx_spaces_joined', 1, 'bx_spaces', '_bx_spaces_page_block_title_sys_entries_actions', '_bx_spaces_page_block_title_entries_actions', 13, 2147483647, 'service', 'a:2:{s:6:"module";s:9:"bx_spaces";s:6:"method";s:18:"my_entries_actions";}', 0, 0, 1, 1),
+('bx_spaces_joined', 1, 'bx_spaces', '_bx_spaces_page_block_title_sys_entries_of_author', '_bx_spaces_page_block_title_entries_of_author', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:9:"bx_spaces";s:6:"method";s:22:"browse_created_entries";}', 0, 0, 0, 2),
+('bx_spaces_joined', 1, 'bx_spaces', '_bx_spaces_page_block_title_sys_favorites_of_author', '_bx_spaces_page_block_title_favorites_of_author', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:9:"bx_spaces";s:6:"method";s:15:"browse_favorite";s:6:"params";a:1:{i:0;s:12:"{profile_id}";}}', 0, 1, 1, 3),
+('bx_spaces_joined', 1, 'bx_spaces', '_bx_spaces_page_block_title_sys_joined_entries', '_bx_spaces_page_block_title_joined_entries', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:9:"bx_spaces";s:6:"method";s:21:"browse_joined_entries";s:6:"params";a:2:{i:0;i:0;i:1;b:1;}}', 0, 0, 1, 4);
+
+-- PAGE: favorites by list
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_spaces_favorites', '_bx_spaces_page_title_sys_entries_favorites', '_bx_spaces_page_title_entries_favorites', 'bx_spaces', 12, 2147483647, 1, 'spaces-favorites', 'page.php?i=spaces-favorites', '', '', '', 0, 1, 0, 'BxSpacesPageListEntry', 'modules/boonex/spaces/classes/BxSpacesPageListEntry.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_spaces_favorites', 2, 'bx_spaces', '_bx_spaces_page_block_title_sys_favorites_entries', '_bx_spaces_page_block_title_favorites_entries', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:9:"bx_spaces";s:6:"method";s:15:"browse_favorite";s:6:"params";a:2:{s:10:"profile_id";s:12:"{profile_id}";s:6:"params";a:3:{s:9:"unit_view";s:7:"gallery";s:13:"empty_message";b:0;s:13:"ajax_paginate";b:0;}}}', 0, 1, 1),
+('bx_spaces_favorites', 3, 'bx_spaces', '', '_bx_spaces_page_block_title_favorites_entries_info', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:9:"bx_spaces";s:6:"method";s:19:"favorites_list_info";}', 0, 0, 0),
+('bx_spaces_favorites', 3, 'bx_spaces', '', '_bx_spaces_page_block_title_favorites_entries_actions', 13, 2147483647, 'service', 'a:2:{s:6:"module";s:9:"bx_spaces";s:6:"method";s:22:"favorites_list_actions";}', 0, 0, 1);
+
+-- PAGE: add block to homepage
+SET @iBlockOrder = (SELECT `order` FROM `sys_pages_blocks` WHERE `object` = 'sys_home' AND `cell_id` = 1 ORDER BY `order` DESC LIMIT 1);
+INSERT INTO `sys_pages_blocks` (`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES
+('sys_home', 1, 'bx_spaces', '', '_bx_spaces_page_block_title_latest_profiles', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:9:"bx_spaces";s:6:"method";s:22:"browse_recent_profiles";}', 1, 0, 0, IFNULL(@iBlockOrder, 0) + 1),
+('sys_home', 1, 'bx_spaces', '_bx_spaces_page_block_title_sys_recommended_entries_view_showcase', '_bx_spaces_page_block_title_recommended_entries_view_showcase', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:9:"bx_spaces";s:6:"method";s:18:"browse_recommended";}', 1, 0, 0, IFNULL(@iBlockOrder, 0) + 2);
+
+-- PAGE: service blocks
+SET @iBlockOrder = (SELECT `order` FROM `sys_pages_blocks` WHERE `object` = '' AND `cell_id` = 0 ORDER BY `order` DESC LIMIT 1);
+INSERT INTO `sys_pages_blocks` (`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES
+('', 0, 'bx_spaces', '', '_bx_spaces_page_block_title_categories', 11, 2147483647, 'service', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:15:"categories_list";s:6:"params";a:2:{i:0;s:14:"bx_spaces_cats";i:1;a:2:{s:10:\"show_empty\";b:1;s:21:\"show_empty_categories\";b:1;}}s:5:"class";s:20:"TemplServiceCategory";}', 1, 1, 1, IFNULL(@iBlockOrder, 0) + 1),
+('', 0, 'bx_spaces', '_bx_spaces_page_block_title_sys_featured_entries_view_showcase', '_bx_spaces_page_block_title_featured_entries_view_showcase', 11, 2147483647, 'service', 'a:3:{s:6:\"module\";s:9:\"bx_spaces\";s:6:\"method\";s:15:\"browse_featured\";s:6:\"params\";a:3:{s:9:\"unit_view\";s:8:\"showcase\";s:13:\"empty_message\";b:0;s:13:\"ajax_paginate\";b:0;}}', 0, 1, 1, IFNULL(@iBlockOrder, 0) + 2),
+('', 0, 'bx_spaces', '_bx_spaces_page_block_title_sys_recommended_entries_view_showcase', '_bx_spaces_page_block_title_recommended_entries_view_showcase', 11, 2147483647, 'service', 'a:3:{s:6:\"module\";s:9:\"bx_spaces\";s:6:\"method\";s:18:\"browse_recommended\";s:6:\"params\";a:3:{s:9:\"unit_view\";s:8:\"showcase\";s:13:\"empty_message\";b:0;s:13:\"ajax_paginate\";b:0;}}', 0, 1, 1, IFNULL(@iBlockOrder, 0) + 3),
+('', 0, 'bx_spaces', '_bx_spaces_page_block_title_sys_cover_block', '_bx_spaces_page_block_title_cover_block', 3, 2147483647, 'service', 'a:2:{s:6:\"module\";s:9:\"bx_spaces\";s:6:\"method\";s:12:\"entity_cover\";}', 0, 1, 1, IFNULL(@iBlockOrder, 0) + 4);
+
+-- MENU
+
+-- MENU: add to site menu
+
+SET @iSiteMenuOrder = (SELECT `order` FROM `sys_menu_items` WHERE `set_name` = 'sys_site' AND `active` = 1 AND `order` < 9999 ORDER BY `order` DESC LIMIT 1);
+INSERT INTO `sys_menu_items` (`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('sys_site', 'bx_spaces', 'spaces-home', '_bx_spaces_menu_item_title_system_entries_home', '_bx_spaces_menu_item_title_entries_home', 'page.php?i=spaces-home', '', '', 'object-group col-red2', 'bx_spaces_submenu', 2147483647, 1, 1, IFNULL(@iSiteMenuOrder, 0) + 1);
+
+-- MENU: add to homepage menu
+
+SET @iHomepageMenuOrder = (SELECT `order` FROM `sys_menu_items` WHERE `set_name` = 'sys_homepage' AND `active` = 1 ORDER BY `order` DESC LIMIT 1);
+INSERT INTO `sys_menu_items` (`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('sys_homepage', 'bx_spaces', 'spaces-home', '_bx_spaces_menu_item_title_system_entries_home', '_bx_spaces_menu_item_title_entries_home', 'page.php?i=spaces-home', '', '', 'object-group col-red2', 'bx_spaces_submenu', 2147483647, 1, 1, IFNULL(@iHomepageMenuOrder, 0) + 1);
+
+-- MENU: add to "add content" menu
+
+SET @iAddMenuOrder = (SELECT `order` FROM `sys_menu_items` WHERE `set_name` = 'sys_add_content_links' AND `active` = 1 ORDER BY `order` DESC LIMIT 1);
+INSERT INTO `sys_menu_items` (`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('sys_add_content_links', 'bx_spaces', 'create-space-profile', '_bx_spaces_menu_item_title_system_create_profile', '_bx_spaces_menu_item_title_create_profile', 'page.php?i=create-space-profile', '', '', 'object-group col-red2', '', 2147483647, 1, 1, IFNULL(@iAddMenuOrder, 0) + 1);
+
+-- MENU: view actions
+
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_spaces_view_actions', '_bx_spaces_menu_title_view_profile_actions', 'bx_spaces_view_actions', 'bx_spaces', 9, 0, 1, 'BxSpacesMenuViewActions', 'modules/boonex/spaces/classes/BxSpacesMenuViewActions.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_spaces_view_actions', 'bx_spaces', '_bx_spaces_menu_set_title_view_profile_actions', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `submenu_popup`, `visible_for_levels`, `visibility_custom`, `active`, `copyable`, `editable`, `order`) VALUES 
+('bx_spaces_view_actions', 'bx_spaces', 'join-space-profile', '_bx_spaces_menu_item_title_system_pay_and_join', '_bx_spaces_menu_item_title_pay_and_join', 'page.php?i=join-space-profile&profile_id={profile_id}', '', '', 'sign-in-alt', '', 0, 2147483647, 'a:3:{s:6:"module";s:9:"bx_spaces";s:6:"method";s:22:"is_paid_join_avaliable";s:6:"params";a:1:{i:0;s:12:"{profile_id}";}}', 1, 0, 0, 5),
+('bx_spaces_view_actions', 'bx_spaces', 'profile-fan-add', '_bx_spaces_menu_item_title_system_become_fan', '{title_add_fan}', 'javascript:void(0)', 'bx_conn_action(this, \'bx_spaces_fans\', \'add\', \'{profile_id}\')', '', 'sign-in-alt', '', 0, 2147483647, 'a:3:{s:6:"module";s:9:"bx_spaces";s:6:"method";s:22:"is_free_join_avaliable";s:6:"params";a:1:{i:0;s:12:"{profile_id}";}}', 1, 0, 0, 5),
+('bx_spaces_view_actions', 'bx_spaces', 'profile-subscribe-add', '_bx_spaces_menu_item_title_system_subscribe', '_bx_spaces_menu_item_title_subscribe', 'javascript:void(0)', 'bx_conn_action(this, \'sys_profiles_subscriptions\', \'add\', \'{profile_id}\')', '', 'check', '', 0, 2147483647, '', 1, 0, 1, 20),
+('bx_spaces_view_actions', 'bx_spaces', 'profile-set-badges', '_sys_menu_item_title_system_set_badges', '_sys_menu_item_title_set_badges', 'javascript:void(0)', 'bx_menu_popup(''sys_set_badges'', window, {}, {module: ''bx_spaces'', content_id: {content_id}});', '', 'check-circle', '', 0, 192, 'a:2:{s:6:"module";s:9:"bx_spaces";s:6:"method";s:19:"is_badges_avaliable";}', 1, 0, 1, 30),
+('bx_spaces_view_actions', 'bx_spaces', 'profile-actions-more', '_bx_spaces_menu_item_title_system_more_actions', '_bx_spaces_menu_item_title_more_actions', 'javascript:void(0)', 'bx_menu_popup(''bx_spaces_view_actions_more'', this, {}, {profile_id:{profile_id}});', '', 'cog', 'bx_spaces_view_actions_more', 1, 2147483647, '', 1, 0, 1, 9999);
+
+-- MENU: view actions more
+
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_spaces_view_actions_more', '_bx_spaces_menu_title_view_profile_actions_more', 'bx_spaces_view_actions_more', 'bx_spaces', 6, 0, 1, 'BxSpacesMenuViewActions', 'modules/boonex/spaces/classes/BxSpacesMenuViewActions.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_spaces_view_actions_more', 'bx_spaces', '_bx_spaces_menu_set_title_view_profile_actions_more', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `visibility_custom`, `active`, `copyable`, `order`) VALUES 
+('bx_spaces_view_actions_more', 'bx_spaces', 'profile-fan-remove', '_bx_spaces_menu_item_title_system_leave_space', '{title_remove_fan}', 'javascript:void(0)', 'bx_conn_action(this, \'bx_spaces_fans\', \'remove\', \'{profile_id}\')', '', 'sign-out-alt', '', 2147483647, '', 1, 0, 10),
+('bx_spaces_view_actions_more', 'bx_spaces', 'profile-subscribe-remove', '_bx_spaces_menu_item_title_system_unsubscribe', '_bx_spaces_menu_item_title_unsubscribe', 'javascript:void(0)', 'bx_conn_action(this, \'sys_profiles_subscriptions\', \'remove\', \'{profile_id}\')', '', 'check', '', 2147483647, '', 1, 0, 20),
+('bx_spaces_view_actions_more', 'bx_spaces', 'edit-space-cover', '_bx_spaces_menu_item_title_system_edit_cover', '_bx_spaces_menu_item_title_edit_cover', 'page.php?i=edit-space-cover&id={content_id}', '', '', 'edit', '', 2147483647, '', 1, 0, 30),
+('bx_spaces_view_actions_more', 'bx_spaces', 'edit-space-profile', '_bx_spaces_menu_item_title_system_edit_profile', '_bx_spaces_menu_item_title_edit_profile', 'page.php?i=edit-space-profile&id={content_id}', '', '', 'pencil-alt', '', 2147483647, '', 1, 0, 40),
+('bx_spaces_view_actions_more', 'bx_spaces', 'edit-space-pricing', '_bx_spaces_menu_item_title_system_edit_pricing', '_bx_spaces_menu_item_title_edit_pricing', 'page.php?i=edit-space-pricing&profile_id={profile_id}', '', '', 'money-check-alt', '', 2147483647, 'a:3:{s:6:"module";s:9:"bx_spaces";s:6:"method";s:20:"is_pricing_avaliable";s:6:"params";a:1:{i:0;s:12:"{profile_id}";}}', 1, 0, 41),
+('bx_spaces_view_actions_more', 'bx_spaces', 'invite-to-space', '_bx_spaces_menu_item_title_system_invite', '_bx_spaces_menu_item_title_invite', 'page.php?i=invite-to-space&id={content_id}', '', '', 'user-friends', '', 2147483647, '', 1, 0, 42),
+('bx_spaces_view_actions_more', 'bx_spaces', 'delete-space-profile', '_bx_spaces_menu_item_title_system_delete_profile', '_bx_spaces_menu_item_title_delete_profile', 'page.php?i=delete-space-profile&id={content_id}', '', '', 'remove', '', 2147483647, '', 1, 0, 50),
+('bx_spaces_view_actions_more', 'bx_spaces', 'approve-space-profile', '_sys_menu_item_title_system_va_approve', '_sys_menu_item_title_va_approve', 'javascript:void(0)', 'javascript:bx_approve(this, ''{module_uri}'', {content_id});', '', 'check', '', 2147483647, '', 1, 0, 60);
+
+-- MENU: all actions menu for view entry 
+
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_spaces_view_actions_all', '_sys_menu_title_view_actions', 'bx_spaces_view_actions_all', 'bx_spaces', 15, 0, 1, 'BxSpacesMenuViewActionsAll', 'modules/boonex/spaces/classes/BxSpacesMenuViewActionsAll.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_spaces_view_actions_all', 'bx_spaces', '_sys_menu_set_title_view_actions', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `addon`, `submenu_object`, `submenu_popup`, `visible_for_levels`, `visibility_custom`, `active`, `copyable`, `order`) VALUES 
+('bx_spaces_view_actions_all', 'bx_spaces', 'join-space-profile', '_bx_spaces_menu_item_title_system_pay_and_join', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 5),
+('bx_spaces_view_actions_all', 'bx_spaces', 'profile-fan-add', '_bx_spaces_menu_item_title_system_become_fan', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 10),
+('bx_spaces_view_actions_all', 'bx_spaces', 'profile-fan-remove', '_bx_spaces_menu_item_title_system_leave_group', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 20),
+('bx_spaces_view_actions_all', 'bx_spaces', 'profile-subscribe-add', '_bx_spaces_menu_item_title_system_subscribe', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 30),
+('bx_spaces_view_actions_all', 'bx_spaces', 'profile-subscribe-remove', '_bx_spaces_menu_item_title_system_unsubscribe', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 40),
+('bx_spaces_view_actions_all', 'bx_spaces', 'profile-set-badges', '_sys_menu_item_title_system_set_badges', '', '', '', '', '', '', '', 0, 192, 'a:2:{s:6:"module";s:9:"bx_spaces";s:6:"method";s:19:"is_badges_avaliable";}', 1, 0, 50),
+('bx_spaces_view_actions_all', 'bx_spaces', 'comment', '_sys_menu_item_title_system_va_comment', '', '', '', '', '', '', '', 0, 2147483647, '', 0, 0, 200),
+('bx_spaces_view_actions_all', 'bx_spaces', 'view', '_sys_menu_item_title_system_va_view', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 210),
+('bx_spaces_view_actions_all', 'bx_spaces', 'vote', '_sys_menu_item_title_system_va_vote', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 220),
+('bx_spaces_view_actions_all', 'bx_spaces', 'score', '_sys_menu_item_title_system_va_score', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 230),
+('bx_spaces_view_actions_all', 'bx_spaces', 'favorite', '_sys_menu_item_title_system_va_favorite', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 240),
+('bx_spaces_view_actions_all', 'bx_spaces', 'feature', '_sys_menu_item_title_system_va_feature', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 250),
+('bx_spaces_view_actions_all', 'bx_spaces', 'repost', '_sys_menu_item_title_system_va_repost', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 260),
+('bx_spaces_view_actions_all', 'bx_spaces', 'report', '_sys_menu_item_title_system_va_report', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 270),
+('bx_spaces_view_actions_all', 'bx_spaces', 'notes', '_sys_menu_item_title_system_va_notes', '_sys_menu_item_title_va_notes', 'javascript:void(0)', 'javascript:bx_get_notes(this,  ''{module_uri}'', {content_id});', '', 'exclamation-triangle', '', '', 0, 2147483647, '', 1, 0, 280),
+('bx_spaces_view_actions_all', 'bx_spaces', 'audit', '_sys_menu_item_title_system_va_audit', '_sys_menu_item_title_va_audit', 'page.php?i=dashboard-audit&module=bx_spaces&content_id={content_id}', '', '', 'history', '', '', 0, 192, '', 1, 0, 290),
+('bx_spaces_view_actions_all', 'bx_spaces', 'social-sharing', '_sys_menu_item_title_system_social_sharing', '_sys_menu_item_title_social_sharing', 'javascript:void(0)', 'oBxDolPage.share(this, \'{url_encoded}\')', '', 'share', '', '', 0, 2147483647, '', 1, 0, 300),
+('bx_spaces_view_actions_all', 'bx_spaces', 'edit-space-cover', '_bx_spaces_menu_item_title_system_edit_cover', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 400),
+('bx_spaces_view_actions_all', 'bx_spaces', 'edit-space-profile', '_bx_spaces_menu_item_title_system_edit_profile', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 410),
+('bx_spaces_view_actions_all', 'bx_spaces', 'edit-space-pricing', '_bx_spaces_menu_item_title_system_edit_pricing', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 415),
+('bx_spaces_view_actions_all', 'bx_spaces', 'invite-to-space', '_bx_spaces_menu_item_title_system_invite', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 420),
+('bx_spaces_view_actions_all', 'bx_spaces', 'delete-space-profile', '_bx_spaces_menu_item_title_system_delete_profile', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 430),
+('bx_spaces_view_actions_all', 'bx_spaces', 'approve-space-profile', '_sys_menu_item_title_system_va_approve', '', '', '', '', '', '', '', 0, 2147483647, '', 1, 0, 440),
+('bx_spaces_view_actions_all', 'bx_spaces', 'more-auto', '_sys_menu_item_title_system_va_more_auto', '_sys_menu_item_title_va_more_auto', 'javascript:void(0)', '', '', 'ellipsis-v', '', '', 0, 2147483647, '', 1, 0, 9999);
+
+-- MENU: meta (counters) menu for view entry
+
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_spaces_view_meta', '_bx_spaces_menu_title_view_profile_meta', 'bx_spaces_view_meta', 'bx_spaces', 15, 0, 1, 'BxSpacesMenuViewMeta', 'modules/boonex/spaces/classes/BxSpacesMenuViewMeta.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_spaces_view_meta', 'bx_spaces', '_bx_spaces_menu_set_title_view_profile_meta', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `submenu_popup`, `visible_for_levels`, `visibility_custom`, `active`, `copyable`, `order`) VALUES 
+('bx_spaces_view_meta', 'bx_spaces', 'members', '_sys_menu_item_title_system_sm_members', '_sys_menu_item_title_sm_members', '', '', '', '', '', 0, 2147483647, '', 1, 0, 10),
+('bx_spaces_view_meta', 'bx_spaces', 'subscribers', '_sys_menu_item_title_system_sm_subscribers', '_sys_menu_item_title_sm_subscribers', '', '', '', '', '', 0, 2147483647, '', 1, 0, 20),
+('bx_spaces_view_meta', 'bx_spaces', 'views', '_sys_menu_item_title_system_sm_views', '_sys_menu_item_title_sm_views', '', '', '', '', '', 0, 2147483647, '', 1, 0, 30),
+('bx_spaces_view_meta', 'bx_spaces', 'votes', '_sys_menu_item_title_system_sm_votes', '_sys_menu_item_title_sm_votes', '', '', '', '', '', 0, 2147483647, '', 1, 0, 40),
+('bx_spaces_view_meta', 'bx_spaces', 'comments', '_sys_menu_item_title_system_sm_comments', '_sys_menu_item_title_sm_comments', '', '', '', '', '', 0, 2147483647, '', 1, 0, 50);
+
+-- MENU: actions menu for my entries
+
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_spaces_my', '_bx_spaces_menu_title_entries_my', 'bx_spaces_my', 'bx_spaces', 9, 0, 1, 'BxSpacesMenu', 'modules/boonex/spaces/classes/BxSpacesMenu.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_spaces_my', 'bx_spaces', '_bx_spaces_menu_set_title_entries_my', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('bx_spaces_my', 'bx_spaces', 'create-space-profile', '_bx_spaces_menu_item_title_system_create_profile', '_bx_spaces_menu_item_title_create_profile', 'page.php?i=create-space-profile', '', '', 'plus', '', 2147483647, 1, 0, 0);
+
+-- MENU: module sub-menu
+
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_spaces_submenu', '_bx_spaces_menu_title_submenu', 'bx_spaces_submenu', 'bx_spaces', 8, 0, 1, '', '');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_spaces_submenu', 'bx_spaces', '_bx_spaces_menu_set_title_submenu', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('bx_spaces_submenu', 'bx_spaces', 'spaces-home', '_bx_spaces_menu_item_title_system_entries_recent', '_bx_spaces_menu_item_title_entries_recent', 'page.php?i=spaces-home', '', '', '', '', 2147483647, 1, 1, 1),
+('bx_spaces_submenu', 'bx_spaces', 'spaces-top', '_bx_spaces_menu_item_title_system_entries_top', '_bx_spaces_menu_item_title_entries_top', 'page.php?i=spaces-top', '', '', '', '', 2147483647, 1, 1, 2),
+('bx_spaces_submenu', 'bx_spaces', 'spaces-search', '_bx_spaces_menu_item_title_system_entries_search', '_bx_spaces_menu_item_title_entries_search', 'page.php?i=spaces-search', '', '', '', '', 2147483647, 1, 1, 3),
+('bx_spaces_submenu', 'bx_spaces', 'spaces-joined', '_bx_spaces_menu_item_title_system_entries_joined', '_bx_spaces_menu_item_title_entries_joined', 'page.php?i=spaces-joined', '', '', '', '', 2147483647, 1, 1, 4),
+('bx_spaces_submenu', 'bx_spaces', 'spaces-manage', '_bx_spaces_menu_item_title_system_entries_manage', '_bx_spaces_menu_item_title_entries_manage', 'page.php?i=spaces-manage', '', '', '', '', 2147483646, 1, 1, 5);
+
+-- MENU: view submenu
+
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_spaces_view_submenu', '_bx_spaces_menu_title_view_profile_submenu', 'bx_spaces_view_submenu', 'bx_spaces', 18, 0, 1, 'BxSpacesMenuView', 'modules/boonex/spaces/classes/BxSpacesMenuView.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_spaces_view_submenu', 'bx_spaces', '_bx_spaces_menu_set_title_view_profile_submenu', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `addon`, `submenu_object`, `submenu_popup`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('bx_spaces_view_submenu', 'bx_spaces', 'view-space-profile', '_bx_spaces_menu_item_title_system_view_profile_view', '_bx_spaces_menu_item_title_view_profile_view', 'page.php?i=view-space-profile&id={content_id}', '', '', 'object-group col-red2', '', '', 0, 2147483647, 1, 0, 1),
+('bx_spaces_view_submenu', 'bx_spaces', 'space-profile-info', '_bx_spaces_menu_item_title_system_view_profile_info', '_bx_spaces_menu_item_title_view_profile_info', 'page.php?i=space-profile-info&id={content_id}', '', '', 'info-circle col-gray', '', '', 0, 2147483647, 1, 0, 2),
+('bx_spaces_view_submenu', 'bx_spaces', 'space-profile-comments', '_bx_spaces_menu_item_title_system_view_profile_comments', '_bx_spaces_menu_item_title_view_profile_comments', 'page.php?i=space-profile-comments&id={content_id}', '', '', '', '', '', 0, 2147483647, 0, 0, 3),
+('bx_spaces_view_submenu', 'bx_spaces', 'space-fans', '_bx_spaces_menu_item_title_system_view_fans', '_bx_spaces_menu_item_title_view_fans', 'page.php?i=space-fans&profile_id={profile_id}', '', '', 'object-group col-blue3', '', '', 0, 2147483647, 1, 0, 4),
+('bx_spaces_view_submenu', 'bx_spaces', 'more-auto', '_bx_spaces_menu_item_title_system_view_profile_more_auto', '_bx_spaces_menu_item_title_view_profile_more_auto', 'javascript:void(0)', '', '', 'ellipsis-v', '', '', 0, 2147483647, 1, 0, 9999);
+
+-- MENU: custom menu for snippet meta info
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_spaces_snippet_meta', '_sys_menu_title_snippet_meta', 'bx_spaces_snippet_meta', 'bx_spaces', 15, 0, 1, 'BxSpacesMenuSnippetMeta', 'modules/boonex/spaces/classes/BxSpacesMenuSnippetMeta.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_spaces_snippet_meta', 'bx_spaces', '_sys_menu_set_title_snippet_meta', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `visibility_custom`, `active`, `copyable`, `editable`, `order`) VALUES
+('bx_spaces_snippet_meta', 'bx_spaces', 'parent', '_bx_spaces_menu_item_title_system_sm_parent', '_bx_spaces_menu_item_title_sm_parent', '', '', '', '', '', 2147483647, '', 0, 0, 1, 0),
+('bx_spaces_snippet_meta', 'bx_spaces', 'date', '_sys_menu_item_title_system_sm_date', '_sys_menu_item_title_sm_date', '', '', '', '', '', 2147483647, '', 0, 0, 1, 1),
+('bx_spaces_snippet_meta', 'bx_spaces', 'category', '_sys_menu_item_title_system_sm_category', '_sys_menu_item_title_sm_category', '', '', '', '', '', 2147483647, '', 0, 0, 1, 5),
+('bx_spaces_snippet_meta', 'bx_spaces', 'tags', '_sys_menu_item_title_system_sm_tags', '_sys_menu_item_title_sm_tags', '', '', '', '', '', 2147483647, '', 0, 0, 1, 10),
+('bx_spaces_snippet_meta', 'bx_spaces', 'views', '_sys_menu_item_title_system_sm_views', '_sys_menu_item_title_sm_views', '', '', '', '', '', 2147483647, '', 0, 0, 1, 15),
+('bx_spaces_snippet_meta', 'bx_spaces', 'comments', '_sys_menu_item_title_system_sm_comments', '_sys_menu_item_title_sm_comments', '', '', '', '', '', 2147483647, '', 0, 0, 1, 20),
+('bx_spaces_snippet_meta', 'bx_spaces', 'members', '_sys_menu_item_title_system_sm_members', '_sys_menu_item_title_sm_members', '', '', '', '', '', 2147483647, '', 0, 0, 1, 25),
+('bx_spaces_snippet_meta', 'bx_spaces', 'subscribers', '_sys_menu_item_title_system_sm_subscribers', '_sys_menu_item_title_sm_subscribers', '', '', '', '', '', 2147483647, '', 1, 0, 1, 30),
+('bx_spaces_snippet_meta', 'bx_spaces', 'nl', '_sys_menu_item_title_system_sm_nl', '_sys_menu_item_title_sm_nl', '', '', '', '', '', 2147483647, '', 1, 0, 1, 35),
+('bx_spaces_snippet_meta', 'bx_spaces', 'join-paid', '_sys_menu_item_title_system_sm_join_paid', '_sys_menu_item_title_sm_join_paid', '', '', '', '', '', 2147483647, 'a:3:{s:6:"module";s:9:"bx_spaces";s:6:"method";s:33:"is_paid_join_avaliable_by_content";s:6:"params";a:1:{i:0;s:12:"{content_id}";}}', 1, 0, 1, 40),
+('bx_spaces_snippet_meta', 'bx_spaces', 'join', '_sys_menu_item_title_system_sm_join', '_sys_menu_item_title_sm_join', '', '', '', '', '', 2147483647, 'a:3:{s:6:"module";s:9:"bx_spaces";s:6:"method";s:33:"is_free_join_avaliable_by_content";s:6:"params";a:1:{i:0;s:12:"{content_id}";}}', 0, 0, 1, 45),
+('bx_spaces_snippet_meta', 'bx_spaces', 'leave', '_sys_menu_item_title_system_sm_leave', '_sys_menu_item_title_sm_leave', '', '', '', '', '', 2147483647, '', 0, 0, 1, 50),
+('bx_spaces_snippet_meta', 'bx_spaces', 'subscribe', '_sys_menu_item_title_system_sm_subscribe', '_sys_menu_item_title_sm_subscribe', '', '', '', '', '', 2147483647, '', 1, 0, 1, 55),
+('bx_spaces_snippet_meta', 'bx_spaces', 'unsubscribe', '_sys_menu_item_title_system_sm_unsubscribe', '_sys_menu_item_title_sm_unsubscribe', '', '', '', '', '', 2147483647, '', 0, 0, 1, 60);
+
+-- MENU: profile stats
+SET @iNotifMenuOrder = (SELECT IFNULL(MAX(`order`), 0) FROM `sys_menu_items` WHERE `set_name` = 'sys_profile_stats' AND `active` = 1 LIMIT 1);
+INSERT INTO `sys_menu_items` (`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `addon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES
+('sys_profile_stats', 'bx_spaces', 'profile-stats-my-spaces', '_bx_spaces_menu_item_title_system_manage_my_spaces', '_bx_spaces_menu_item_title_manage_my_spaces', 'page.php?i=joined-spaces&profile_id={member_id}', '', '_self', 'object-group col-red2', 'a:2:{s:6:"module";s:9:"bx_spaces";s:6:"method";s:41:"get_menu_addon_manage_tools_profile_stats";}', '', 2147483646, 1, 0, @iNotifMenuOrder + 2);
+
+-- MENU: profile followings
+SET @iFollowingsMenuOrder = (SELECT IFNULL(MAX(`order`), 0) FROM `sys_menu_items` WHERE `set_name`='sys_profile_followings' LIMIT 1);
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `addon`, `submenu_object`, `visible_for_levels`, `collapsed`, `active`, `copyable`, `order`) VALUES 
+('sys_profile_followings', 'bx_spaces', 'spaces', '_bx_spaces_menu_item_title_system_followings', '_bx_spaces_menu_item_title_followings', 'javascript:void(0)', '', '_self', 'object-group col-red2', '', '', 2147483647, 0, 1, 0, @iFollowingsMenuOrder + 1);
+
+-- MENU: manage tools submenu
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_spaces_menu_manage_tools', '_bx_spaces_menu_title_manage_tools', 'bx_spaces_menu_manage_tools', 'bx_spaces', 6, 0, 1, 'BxSpacesMenuManageTools', 'modules/boonex/spaces/classes/BxSpacesMenuManageTools.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_spaces_menu_manage_tools', 'bx_spaces', '_bx_spaces_menu_set_title_manage_tools', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('bx_spaces_menu_manage_tools', 'bx_spaces', 'clear-reports', '_bx_spaces_menu_item_title_system_clear_reports', '_bx_spaces_menu_item_title_clear_reports', 'javascript:void(0)', 'javascript:{js_object}.onClickClearReports({content_id});', '_self', 'eraser', '', 2147483647, 1, 0, 1),
+('bx_spaces_menu_manage_tools', 'bx_spaces', 'delete', '_bx_spaces_menu_item_title_system_delete', '_bx_spaces_menu_item_title_delete', 'javascript:void(0)', 'javascript:{js_object}.onClickDelete({content_id});', '_self', 'far trash-alt', '', 2147483647, 1, 0, 2),
+('bx_spaces_menu_manage_tools', 'bx_spaces', 'delete-with-content', '_bx_spaces_menu_item_title_system_delete_with_content', '_bx_spaces_menu_item_title_delete_with_content', 'javascript:void(0)', 'javascript:{js_object}.onClickDeleteWithContent({content_id});', '_self', 'far trash-alt', '', 2147483647, 0, 0, 3);
+
+-- MENU: dashboard manage tools
+SET @iManageMenuOrder = (SELECT IFNULL(MAX(`order`), 0) FROM `sys_menu_items` WHERE `set_name`='sys_account_dashboard_manage_tools' LIMIT 1);
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `addon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('sys_account_dashboard_manage_tools', 'bx_spaces', 'spaces-administration', '_bx_spaces_menu_item_title_system_admt_spaces', '_bx_spaces_menu_item_title_admt_spaces', 'page.php?i=spaces-administration', '', '_self', 'object-group', 'a:2:{s:6:"module";s:9:"bx_spaces";s:6:"method";s:27:"get_menu_addon_manage_tools";}', '', 192, 1, 0, @iManageMenuOrder + 1);
+
+-- MENU: add menu item to profiles modules (trigger* menu sets are processed separately upon modules enable/disable)
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('trigger_profile_view_submenu', 'bx_spaces', 'joined-spaces', '_bx_spaces_menu_item_title_system_view_joined_spaces', '_bx_spaces_menu_item_title_view_joined_spaces', 'page.php?i=joined-spaces&profile_id={profile_id}', '', '', 'object-group col-red2', '', 2147483647, 1, 0, 0);
+
+-- ACL
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_spaces', 'create entry', NULL, '_bx_spaces_acl_action_create_profile', '', 1, 1);
+SET @iIdActionProfileCreate = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_spaces', 'use paid join', NULL, '_bx_spaces_acl_action_use_paid_join', '', 1, 1);
+SET @iIdActionUsePaidJoin = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_spaces', 'delete entry', NULL, '_bx_spaces_acl_action_delete_profile', '', 1, 1);
+SET @iIdActionProfileDelete = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_spaces', 'view entry', NULL, '_bx_spaces_acl_action_view_profile', '', 1, 0);
+SET @iIdActionProfileView = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_spaces', 'edit any entry', NULL, '_bx_spaces_acl_action_edit_any_profile', '', 1, 3);
+SET @iIdActionProfileEditAny = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_spaces', 'delete any entry', NULL, '_bx_spaces_acl_action_delete_any_profile', '', 1, 3);
+SET @iIdActionProfileDeleteAny = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_spaces', 'delete invites', NULL, '_bx_spaces_acl_action_delete_invites', '', 1, 3);
+SET @iIdActionProfileDeleteInvites = LAST_INSERT_ID();
+
+SET @iUnauthenticated = 1;
+SET @iAccount = 2;
+SET @iStandard = 3;
+SET @iUnconfirmed = 4;
+SET @iPending = 5;
+SET @iSuspended = 6;
+SET @iModerator = 7;
+SET @iAdministrator = 8;
+SET @iPremium = 9;
+
+INSERT INTO `sys_acl_matrix` (`IDLevel`, `IDAction`) VALUES
+
+-- profile create
+(@iAccount, @iIdActionProfileCreate),
+(@iStandard, @iIdActionProfileCreate),
+(@iUnconfirmed, @iIdActionProfileCreate),
+(@iPending, @iIdActionProfileCreate),
+(@iModerator, @iIdActionProfileCreate),
+(@iAdministrator, @iIdActionProfileCreate),
+(@iPremium, @iIdActionProfileCreate),
+
+-- use paid join
+(@iStandard, @iIdActionUsePaidJoin),
+(@iModerator, @iIdActionUsePaidJoin),
+(@iAdministrator, @iIdActionUsePaidJoin),
+(@iPremium, @iIdActionUsePaidJoin),
+
+-- profile delete
+(@iAccount, @iIdActionProfileDelete),
+(@iStandard, @iIdActionProfileDelete),
+(@iUnconfirmed, @iIdActionProfileDelete),
+(@iPending, @iIdActionProfileDelete),
+(@iModerator, @iIdActionProfileDelete),
+(@iAdministrator, @iIdActionProfileDelete),
+(@iPremium, @iIdActionProfileDelete),
+
+-- profile view
+(@iUnauthenticated, @iIdActionProfileView),
+(@iAccount, @iIdActionProfileView),
+(@iStandard, @iIdActionProfileView),
+(@iUnconfirmed, @iIdActionProfileView),
+(@iPending, @iIdActionProfileView),
+(@iModerator, @iIdActionProfileView),
+(@iAdministrator, @iIdActionProfileView),
+(@iPremium, @iIdActionProfileView),
+
+-- any profile edit
+(@iModerator, @iIdActionProfileEditAny),
+(@iAdministrator, @iIdActionProfileEditAny),
+
+-- any profile delete
+(@iAdministrator, @iIdActionProfileDeleteAny),
+
+-- any invites edit
+(@iModerator, @iIdActionProfileDeleteInvites),
+(@iAdministrator, @iIdActionProfileDeleteInvites);
+
+-- METATAGS
+INSERT INTO `sys_objects_metatags` (`object`, `module`, `table_keywords`, `table_locations`, `table_mentions`, `override_class_name`, `override_class_file`) VALUES
+('bx_spaces', 'bx_spaces', 'bx_spaces_meta_keywords', 'bx_spaces_meta_locations', 'bx_spaces_meta_mentions', '', '');
+
+-- CATEGORY
+INSERT INTO `sys_objects_category` (`object`, `module`, `search_object`, `form_object`, `list_name`, `table`, `field`, `join`, `where`, `override_class_name`, `override_class_file`) VALUES
+('bx_spaces_cats', 'bx_spaces', 'bx_spaces', 'bx_space', 'bx_spaces_cats', 'bx_spaces_data', 'space_cat', 'INNER JOIN `sys_profiles` ON (`sys_profiles`.`content_id` = `bx_spaces_data`.`id` AND `sys_profiles`.`type` = ''bx_spaces'')', 'AND `sys_profiles`.`status` = ''active''', '', '');
+
+-- SEARCH
+SET @iSearchOrder = (SELECT IFNULL(MAX(`Order`), 0) FROM `sys_objects_search`);
+INSERT INTO `sys_objects_search` (`ObjectName`, `Title`, `Order`, `ClassName`, `ClassPath`) VALUES
+('bx_spaces', '_bx_spaces', @iSearchOrder + 1, 'BxSpacesSearchResult', 'modules/boonex/spaces/classes/BxSpacesSearchResult.php');
+
+-- CONNECTIONS
+INSERT INTO `sys_objects_connection` (`object`, `table`, `profile_initiator`, `profile_content`, `type`, `override_class_name`, `override_class_file`) VALUES
+('bx_spaces_fans', 'bx_spaces_fans', 1, 1, 'mutual', '', '');
+
+-- STATS
+SET @iMaxOrderStats = (SELECT IFNULL(MAX(`order`), 0) FROM `sys_statistics`);
+INSERT INTO `sys_statistics` (`module`, `name`, `title`, `link`, `icon`, `query`, `order`) VALUES 
+('bx_spaces', 'bx_spaces', '_bx_spaces', 'page.php?i=spaces-home', 'object-group col-red2', 'SELECT COUNT(*) FROM `bx_spaces_data` AS `td` LEFT JOIN `sys_profiles` AS `tp` ON `td`.`id` = `tp`.`content_id` AND `tp`.`type`=''bx_spaces'' WHERE 1 AND `tp`.`status`=''active''', @iMaxOrderStats + 1);
+
+-- CHARTS
+SET @iMaxOrderCharts = (SELECT IFNULL(MAX(`order`), 0) FROM `sys_objects_chart`);
+INSERT INTO `sys_objects_chart` (`object`, `title`, `table`, `field_date_ts`, `field_date_dt`, `field_status`, `query`, `active`, `order`, `class_name`, `class_file`) VALUES
+('bx_spaces_growth', '_bx_spaces_chart_growth', 'bx_spaces_data', 'added', '', '', 'SELECT {field_date_formatted} AS `period`, COUNT(*) AS {object} FROM {table} LEFT JOIN `sys_profiles` AS `tp` ON {table}.`id` = `tp`.`content_id` AND `tp`.`type`=''bx_spaces'' WHERE 1 AND `tp`.`status`=''active'' {where_inteval} GROUP BY `period` ORDER BY {table}.{field_date} ASC', 1, @iMaxOrderCharts + 1, 'BxDolChartGrowth', ''),
+('bx_spaces_growth_speed', '_bx_spaces_chart_growth_speed', 'bx_spaces_data', 'added', '', '', 'SELECT {field_date_formatted} AS `period`, COUNT(*) AS {object} FROM {table} LEFT JOIN `sys_profiles` AS `tp` ON {table}.`id` = `tp`.`content_id` AND `tp`.`type`=''bx_spaces'' WHERE 1 AND `tp`.`status`=''active'' {where_inteval} GROUP BY `period` ORDER BY {table}.{field_date} ASC', 1, @iMaxOrderCharts + 2, 'BxDolChartGrowthSpeed', '');
+
+-- GRID: connections
+INSERT INTO `sys_objects_grid` (`object`, `source_type`, `source`, `table`, `field_id`, `field_order`, `field_active`, `paginate_url`, `paginate_per_page`, `paginate_simple`, `paginate_get_start`, `paginate_get_per_page`, `filter_fields`, `filter_fields_translatable`, `filter_mode`, `sorting_fields`, `sorting_fields_translatable`, `visible_for_levels`, `responsive`, `override_class_name`, `override_class_file`) VALUES
+('bx_spaces_fans', 'Sql', 'SELECT `p`.`id`, `c`.`added`, `c`.`mutual` FROM `sys_profiles` AS `p` INNER JOIN `sys_accounts` AS `a` ON (`a`.`id` = `p`.`account_id`) {join_connections}', 'sys_profiles', 'id', 'c`.`added', '', '', 10, NULL, 'start', '', 'name,email', '', 'auto', '', '', 2147483647, 1, 'BxSpacesGridConnections', 'modules/boonex/spaces/classes/BxSpacesGridConnections.php');
+
+INSERT INTO `sys_grid_fields` (`object`, `name`, `title`, `width`, `params`, `order`) VALUES
+('bx_spaces_fans', 'name', '_sys_name', '50%', '', 10),
+('bx_spaces_fans', 'role', '_bx_spaces_txt_role', '10%', '', 15),
+('bx_spaces_fans', 'role_added', '_bx_spaces_txt_role_added', '10%', '', 16),
+('bx_spaces_fans', 'role_expired', '_bx_spaces_txt_role_expired', '10%', '', 17),
+('bx_spaces_fans', 'actions', '', '20%', '', 20);
+
+INSERT INTO `sys_grid_actions` (`object`, `type`, `name`, `title`, `icon`, `confirm`, `order`) VALUES
+('bx_spaces_fans', 'single', 'accept', '_sys_accept', '', 0, 10),
+('bx_spaces_fans', 'single', 'set_role', '_bx_spaces_txt_set_role', '', 0, 20),
+('bx_spaces_fans', 'single', 'set_role_submit', '', '', 0, 21),
+('bx_spaces_fans', 'single', 'delete', '', 'remove', 1, 40);
+
+-- GRID: invites
+INSERT INTO `sys_objects_grid` (`object`, `source_type`, `source`, `table`, `field_id`, `field_order`, `field_active`, `paginate_url`, `paginate_per_page`, `paginate_simple`, `paginate_get_start`, `paginate_get_per_page`, `filter_fields`, `filter_fields_translatable`, `filter_mode`, `sorting_fields`, `sorting_fields_translatable`, `visible_for_levels`, `responsive`, `override_class_name`, `override_class_file`) VALUES
+('bx_spaces_invites', 'Sql', 'SELECT `bx_spaces_invites`.`id`, `bx_spaces_invites`.`invited_profile_id`, `bx_spaces_invites`.`added`, `bx_spaces_invites`.`author_profile_id` FROM `sys_profiles` AS `p` INNER JOIN `sys_accounts` AS `a` ON (`a`.`id` = `p`.`account_id`) INNER JOIN `bx_spaces_invites` ON `bx_spaces_invites`.`invited_profile_id` = `p`.`id` ', 'bx_spaces_invites', 'id', 'bx_spaces_invites`.`added', '', '', 10, NULL, 'start', '', 'name,email', '', 'auto', '', '', 2147483647, 0, 'BxSpacesGridInvites', 'modules/boonex/spaces/classes/BxSpacesGridInvites.php');
+
+INSERT INTO `sys_grid_fields` (`object`, `name`, `title`, `width`, `params`, `order`) VALUES
+('bx_spaces_invites', 'name', '_sys_name', '33%', '', 10),
+('bx_spaces_invites', 'added', '_sys_added', '33%', '', 20),
+('bx_spaces_invites', 'actions', '', '34%', '', 30);
+
+INSERT INTO `sys_grid_actions` (`object`, `type`, `name`, `title`, `icon`, `confirm`, `order`) VALUES
+('bx_spaces_invites', 'single', 'delete', '', 'remove', 1, 10);
+
+-- GRIDS: administration
+
+INSERT INTO `sys_objects_grid` (`object`, `source_type`, `source`, `table`, `field_id`, `field_order`, `field_active`, `paginate_url`, `paginate_per_page`, `paginate_simple`, `paginate_get_start`, `paginate_get_per_page`, `filter_fields`, `filter_fields_translatable`, `filter_mode`, `sorting_fields`, `sorting_fields_translatable`, `visible_for_levels`, `override_class_name`, `override_class_file`) VALUES
+('bx_spaces_administration', 'Sql', 'SELECT `td`.*, `td`.`space_name` AS `name`, `ta`.`email` AS `account`, `td`.`added` AS `added_ts`, `tp`.`status` AS `status` FROM `bx_spaces_data` AS `td` LEFT JOIN `sys_profiles` AS `tp` ON `td`.`id`=`tp`.`content_id` AND `tp`.`type`=''bx_spaces'' LEFT JOIN `sys_accounts` AS `ta` ON `tp`.`account_id`=`ta`.`id` WHERE 1 ', 'bx_spaces_data', 'id', 'added', 'status_admin', '', 20, NULL, 'start', '', 'space_name', '', 'like', 'reports', '', 192, 'BxSpacesGridAdministration', 'modules/boonex/spaces/classes/BxSpacesGridAdministration.php'),
+('bx_spaces_common', 'Sql', 'SELECT `td`.*, `td`.`space_name` AS `name`, `ta`.`email` AS `account`, `td`.`added` AS `added_ts`, `tp`.`status` AS `status` FROM `bx_spaces_data` AS `td` LEFT JOIN `sys_profiles` AS `tp` ON `td`.`id`=`tp`.`content_id` AND `tp`.`type`=''bx_spaces'' LEFT JOIN `sys_accounts` AS `ta` ON `tp`.`account_id`=`ta`.`id` WHERE 1 ', 'bx_spaces_data', 'id', 'added', 'status', '', 20, NULL, 'start', '', 'space_name', '', 'like', '', '', 2147483647, 'BxSpacesGridCommon', 'modules/boonex/spaces/classes/BxSpacesGridCommon.php');
+
+INSERT INTO `sys_grid_fields` (`object`, `name`, `title`, `width`, `translatable`, `chars_limit`, `params`, `order`) VALUES
+('bx_spaces_administration', 'checkbox', '_sys_select', '2%', 0, '', '', 1),
+('bx_spaces_administration', 'switcher', '_bx_spaces_grid_column_title_adm_active', '8%', 0, '', '', 2),
+('bx_spaces_administration', 'reports', '_sys_txt_reports_title', '5%', 0, '', '', 3),
+('bx_spaces_administration', 'name', '_bx_spaces_grid_column_title_adm_name', '25%', 0, '', '', 4),
+('bx_spaces_administration', 'added_ts', '_bx_spaces_grid_column_title_adm_added', '20%', 1, '25', '', 5),
+('bx_spaces_administration', 'account', '_bx_spaces_grid_column_title_adm_account', '20%', 0, '25', '', 6),
+('bx_spaces_administration', 'actions', '', '20%', 0, '', '', 7),
+
+('bx_spaces_common', 'checkbox', '_sys_select', '2%', 0, '', '', 1),
+('bx_spaces_common', 'switcher', '_bx_spaces_grid_column_title_adm_active', '8%', 0, '', '', 2),
+('bx_spaces_common', 'name', '_bx_spaces_grid_column_title_adm_name', '40%', 0, '', '', 3),
+('bx_spaces_common', 'added_ts', '_bx_spaces_grid_column_title_adm_added', '30%', 1, '25', '', 4),
+('bx_spaces_common', 'actions', '', '20%', 0, '', '', 5);
+
+INSERT INTO `sys_grid_actions` (`object`, `type`, `name`, `title`, `icon`, `icon_only`, `confirm`, `active`, `order`) VALUES
+('bx_spaces_administration', 'bulk', 'clear_reports', '_bx_spaces_grid_action_title_adm_clear_reports', '', 0, 1, 1, 1),
+('bx_spaces_administration', 'bulk', 'delete', '_bx_spaces_grid_action_title_adm_delete', '', 0, 1, 1, 2),
+('bx_spaces_administration', 'bulk', 'delete_with_content', '_bx_spaces_grid_action_title_adm_delete_with_content', '', 0, 1, 0, 3),
+('bx_spaces_administration', 'single', 'settings', '_bx_spaces_grid_action_title_adm_more_actions', 'cog', 1, 0, 1, 2),
+('bx_spaces_administration', 'single', 'audit_content', '_bx_spaces_grid_action_title_adm_audit_content', 'search', 1, 0, 1, 3),
+('bx_spaces_administration', 'single', 'audit_context', '_bx_spaces_grid_action_title_adm_audit_context', 'search-location', 1, 0, 1, 4),
+
+('bx_spaces_common', 'bulk', 'delete', '_bx_spaces_grid_action_title_adm_delete', '', 0, 1, 1, 1),
+('bx_spaces_common', 'bulk', 'delete_with_content', '_bx_spaces_grid_action_title_adm_delete_with_content', '', 0, 1, 0, 2),
+('bx_spaces_common', 'single', 'settings', '_bx_spaces_grid_action_title_adm_more_actions', 'cog', 1, 0, 1, 1);
+
+-- GRIDS: Pricing
+INSERT INTO `sys_objects_grid` (`object`, `source_type`, `source`, `table`, `field_id`, `field_order`, `field_active`, `paginate_url`, `paginate_per_page`, `paginate_simple`, `paginate_get_start`, `paginate_get_per_page`, `filter_fields`, `filter_fields_translatable`, `filter_mode`, `sorting_fields`, `sorting_fields_translatable`, `visible_for_levels`, `override_class_name`, `override_class_file`) VALUES
+('bx_spaces_prices_manage', 'Sql', 'SELECT * FROM `bx_spaces_prices` WHERE 1 ', 'bx_spaces_prices', 'id', 'order', '', '', 100, NULL, 'start', '', 'period,period_unit,price', '', 'like', '', '', 2147483647, 'BxSpacesGridPricesManage', 'modules/boonex/spaces/classes/BxSpacesGridPricesManage.php'),
+('bx_spaces_prices_view', 'Sql', 'SELECT * FROM `bx_spaces_prices` WHERE 1 ', 'bx_spaces_prices', 'id', 'order', '', '', 100, NULL, 'start', '', 'period,period_unit,price', '', 'like', '', '', 2147483647, 'BxSpacesGridPricesView', 'modules/boonex/spaces/classes/BxSpacesGridPricesView.php');
+
+INSERT INTO `sys_grid_fields` (`object`, `name`, `title`, `width`, `translatable`, `chars_limit`, `params`, `order`) VALUES
+('bx_spaces_prices_manage', 'checkbox', '_sys_select', '1%', 0, '', '', 1),
+('bx_spaces_prices_manage', 'order', '', '1%', 0, '', '', 2),
+('bx_spaces_prices_manage', 'name', '_bx_spaces_grid_column_title_name', '38%', 0, 32, '', 3),
+('bx_spaces_prices_manage', 'price', '_bx_spaces_grid_column_title_price', '20%', 0, 16, '', 4),
+('bx_spaces_prices_manage', 'period', '_bx_spaces_grid_column_title_period', '20%', 0, 16, '', 5),
+('bx_spaces_prices_manage', 'actions', '', '20%', 0, '', '', 6),
+
+('bx_spaces_prices_view', 'role_id', '_bx_spaces_grid_column_title_role_id', '40%', 0, 32, '', 1),
+('bx_spaces_prices_view', 'price', '_bx_spaces_grid_column_title_price', '20%', 0, 16, '', 2),
+('bx_spaces_prices_view', 'period', '_bx_spaces_grid_column_title_period', '20%', 0, 16, '', 3),
+('bx_spaces_prices_view', 'actions', '', '20%', 0, '', '', 4);
+
+INSERT INTO `sys_grid_actions` (`object`, `type`, `name`, `title`, `icon`, `icon_only`, `confirm`, `order`) VALUES
+('bx_spaces_prices_manage', 'independent', 'add', '_bx_spaces_grid_action_title_add', '', 0, 0, 1),
+('bx_spaces_prices_manage', 'single', 'edit', '_bx_spaces_grid_action_title_edit', 'pencil-alt', 1, 0, 1),
+('bx_spaces_prices_manage', 'single', 'delete', '_bx_spaces_grid_action_title_delete', 'remove', 1, 1, 2),
+('bx_spaces_prices_manage', 'bulk', 'delete', '_bx_spaces_grid_action_title_delete', '', 0, 1, 1),
+
+('bx_spaces_prices_view', 'single', 'buy', '_bx_spaces_grid_action_title_buy', 'cart-plus', 0, 0, 1),
+('bx_spaces_prices_view', 'single', 'subscribe', '_bx_spaces_grid_action_title_subscribe', 'credit-card', 0, 0, 2),
+('bx_spaces_prices_view', 'single', 'choose', '_bx_spaces_grid_action_title_choose', 'far check-square', 0, 0, 3);
+
+
+-- ALERTS
+
+INSERT INTO `sys_alerts_handlers` (`name`, `class`, `file`, `service_call`) VALUES 
+('bx_spaces', 'BxSpacesAlertsResponse', 'modules/boonex/spaces/classes/BxSpacesAlertsResponse.php', '');
+SET @iHandler := LAST_INSERT_ID();
+
+INSERT INTO `sys_alerts` (`unit`, `action`, `handler_id`) VALUES
+('system', 'save_setting', @iHandler),
+('bx_timeline', 'post_common', @iHandler),
+('bx_spaces_pics', 'file_deleted', @iHandler),
+('bx_spaces_fans', 'connection_added', @iHandler),
+('bx_spaces_fans', 'connection_removed', @iHandler),
+('profile', 'delete', @iHandler),
+('bx_spaces', 'fan_added', @iHandler),
+('bx_spaces', 'join_invitation', @iHandler),
+('bx_spaces', 'join_request', @iHandler),
+('bx_spaces', 'join_request_accepted', @iHandler),
+('bx_spaces', 'timeline_view', @iHandler),
+('bx_spaces', 'timeline_post', @iHandler),
+('bx_spaces', 'timeline_delete', @iHandler),
+('bx_spaces', 'timeline_comment', @iHandler),
+('bx_spaces', 'timeline_vote', @iHandler),
+('bx_spaces', 'timeline_score', @iHandler),
+('bx_spaces', 'timeline_report', @iHandler),
+('bx_spaces', 'timeline_repost', @iHandler),
+('bx_spaces', 'timeline_pin', @iHandler),
+('bx_spaces', 'timeline_promote', @iHandler);
+
+-- PRIVACY 
+
+INSERT INTO `sys_objects_privacy` (`object`, `module`, `action`, `title`, `default_group`, `spaces`, `table`, `table_field_id`, `table_field_author`, `override_class_name`, `override_class_file`) VALUES
+('bx_spaces_allow_view_to', 'bx_spaces', 'view', '_bx_spaces_form_profile_input_allow_view_to', '3', '', 'bx_spaces_data', 'id', 'author', 'BxSpacesPrivacy', 'modules/boonex/spaces/classes/BxSpacesPrivacy.php'),
+('bx_spaces_allow_view_notification_to', 'bx_spaces', 'view_event', '_bx_spaces_form_profile_input_allow_view_notification_to', '3', '', 'bx_notifications_events', 'id', 'object_owner_id', 'BxSpacesPrivacyNotifications', 'modules/boonex/spaces/classes/BxSpacesPrivacyNotifications.php'),
+('bx_spaces_allow_post_to', 'bx_spaces', 'post', '_bx_spaces_form_profile_input_allow_post_to', '3', '', 'bx_spaces_data', 'id', 'author', 'BxSpacesPrivacyPost', 'modules/boonex/spaces/classes/BxSpacesPrivacyPost.php'),
+('bx_spaces_allow_view_favorite_list', 'bx_spaces', 'view_favorite_list', '_bx_spaces_form_profile_input_allow_view_favorite_list', '3', '', 'bx_spaces_favorites_lists', 'id', 'author_id', 'BxSpacesPrivacy', 'modules/boonex/spaces/classes/BxSpacesPrivacy.php');
+
+-- EMAIL TEMPLATES
+
+INSERT INTO `sys_email_templates` (`Module`, `NameSystem`, `Name`, `Subject`, `Body`) VALUES
+('bx_spaces', '_bx_spaces_email_join_request', 'bx_spaces_join_request', '_bx_spaces_email_join_request_subject', '_bx_spaces_email_join_request_body'),
+('bx_spaces', '_bx_spaces_email_join_reject', 'bx_spaces_join_reject', '_bx_spaces_email_join_reject_subject', '_bx_spaces_email_join_reject_body'),
+('bx_spaces', '_bx_spaces_email_join_confirm', 'bx_spaces_join_confirm', '_bx_spaces_email_join_confirm_subject', '_bx_spaces_email_join_confirm_body'),
+('bx_spaces', '_bx_spaces_email_fan_remove', 'bx_spaces_fan_remove', '_bx_spaces_email_fan_remove_subject', '_bx_spaces_email_fan_remove_body'),
+('bx_spaces', '_bx_spaces_email_fan_become_admin', 'bx_spaces_fan_become_admin', '_bx_spaces_email_fan_become_admin_subject', '_bx_spaces_email_fan_become_admin_body'),
+('bx_spaces', '_bx_spaces_email_admin_become_fan', 'bx_spaces_admin_become_fan', '_bx_spaces_email_admin_become_fan_subject', '_bx_spaces_email_admin_become_fan_body'),
+('bx_spaces', '_bx_spaces_email_set_role', 'bx_spaces_set_role', '_bx_spaces_email_set_role_subject', '_bx_spaces_email_set_role_body'),
+('bx_spaces', '_bx_spaces_email_invitation', 'bx_spaces_invitation', '_bx_spaces_email_invitation_subject', '_bx_spaces_email_invitation_body');
+
+-- UPLOADERS
+
+INSERT INTO `sys_objects_uploader` (`object`, `active`, `override_class_name`, `override_class_file`) VALUES
+('bx_spaces_cover_crop', 1, 'BxSpacesUploaderCoverCrop', 'modules/boonex/spaces/classes/BxSpacesUploaderCoverCrop.php'),
+('bx_spaces_picture_crop', 1, 'BxSpacesUploaderPictureCrop', 'modules/boonex/spaces/classes/BxSpacesUploaderPictureCrop.php');
+
+
+-- CRON
+INSERT INTO `sys_cron_jobs` (`name`, `time`, `class`, `file`, `service_call`) VALUES
+('bx_spaces_pruning', '0 0 * * *', 'BxSpacesCronPruning', 'modules/boonex/spaces/classes/BxSpacesCronPruning.php', '');

+ 16 - 0
modules/boonex/spaces/updates/13.0.2_13.0.3/source/js/invite_popup.js

@@ -0,0 +1,16 @@
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Spaces Spaces
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+function BxSpacesInvitePopup(oOptions) {
+    BxBaseModGroupsInvitePopup.call(this, oOptions);
+}
+
+BxSpacesInvitePopup.prototype = Object.create(BxBaseModGroupsInvitePopup.prototype);
+BxSpacesInvitePopup.prototype.constructor = BxSpacesInvitePopup;

+ 51 - 0
modules/boonex/timeline/updates/13.0.4_13.0.5/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' => 'Timeline',
+    'version_from' => '13.0.4',
+    'version_to' => '13.0.5',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '13.0.0-B4'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/timeline/updates/update_13.0.4_13.0.5/',
+    'home_uri' => 'timeline_update_1304_1305',
+
+    'module_dir' => 'boonex/timeline/',
+    'module_uri' => 'timeline',
+
+    'db_prefix' => 'bx_timeline_',
+    'class_prefix' => 'BxTimeline',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_files' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Timeline',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

+ 26 - 0
modules/boonex/timeline/updates/13.0.4_13.0.5/install/installer.php

@@ -0,0 +1,26 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ */
+
+class BxTimelineUpdater extends BxDolStudioUpdater
+{
+    function __construct($aConfig)
+    {
+        parent::__construct($aConfig);
+    }
+
+    public function actionExecuteSql($sOperation)
+    {
+        if($sOperation == 'install') {
+            if(!$this->oDb->isFieldExists('bx_timeline_events', 'reacted'))
+                $this->oDb->query("ALTER TABLE `bx_timeline_events` ADD `reacted` int(11) NOT NULL default '0' AFTER `published`");
+
+            if(!$this->oDb->isFieldExists('bx_timeline_reposts_track', 'active'))
+                $this->oDb->query("ALTER TABLE `bx_timeline_reposts_track` ADD `active` tinyint(4) NOT NULL default '1' AFTER `date`");
+        }
+
+        return parent::actionExecuteSql($sOperation);
+    }
+}

+ 9 - 0
modules/boonex/timeline/updates/13.0.4_13.0.5/install/langs/en.xml

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources name="en" flag="gb" title="English">
+	<string_add name="_bx_timeline_option_enable_hide_upon_delete"><![CDATA[Inactivate items upon hiding instead of deletion]]></string_add>
+	<string_add name="_bx_timeline_option_title_chars"><![CDATA[Number of characters in auto-generated update's title]]></string_add>
+    <string_add name="_bx_timeline_option_title_chars_short"><![CDATA[Number of characters in auto-generated update's short title]]></string_add>
+	<string_add name="_bx_timeline_option_enable_sort_by_reaction"><![CDATA[Sort by the date of last comment (experimental, works for updates only)]]></string_add>
+    <string_add name="_bx_timeline_option_enable_sort_by_unread"><![CDATA[Sort by 'unread' state (show unread first).]]></string_add>
+	<string_add name="_bx_timeline_alert_action_repost_personal"><![CDATA[New content repost]]></string_add>
+</resources>

+ 37 - 0
modules/boonex/timeline/updates/13.0.4_13.0.5/install/sql/enable.sql

@@ -0,0 +1,37 @@
+SET @sName = 'bx_timeline';
+
+
+-- PAGES
+UPDATE `sys_objects_page` SET `url`='' WHERE `object`='bx_timeline_item';
+UPDATE `sys_objects_page` SET `url`='' WHERE `object`='bx_timeline_item_brief';
+
+
+-- SETTINGS
+SET @iHdrIdComment = (SELECT `id` FROM `bx_timeline_handlers` WHERE `group`='comment' AND `type`='insert' AND `alert_unit`='comment' AND `alert_action`='added' LIMIT 1);
+UPDATE `sys_options` SET `value`=CONCAT_WS(',', @iHdrIdComment) WHERE `name`='bx_timeline_events_hide';
+
+
+SET @iCategId = (SELECT `id` FROM `sys_options_categories` WHERE `name`='bx_timeline_general' LIMIT 1);
+DELETE FROM `sys_options` WHERE `name`='bx_timeline_enable_hide_upon_delete';
+INSERT INTO `sys_options` (`name`, `value`, `category_id`, `caption`, `type`, `check`, `check_params`, `check_error`, `extra`, `order`) VALUES
+('bx_timeline_enable_hide_upon_delete', '', @iCategId, '_bx_timeline_option_enable_hide_upon_delete', 'checkbox', '', '', '', '', 5);
+
+
+SET @iCategId = (SELECT `id` FROM `sys_options_categories` WHERE `name`='bx_timeline_browse' LIMIT 1);
+DELETE FROM `sys_options` WHERE `name` IN ('bx_timeline_enable_sort_by_reaction', 'bx_timeline_enable_sort_by_unread');
+INSERT INTO `sys_options` (`name`, `value`, `category_id`, `caption`, `type`, `check`, `check_params`, `check_error`, `extra`, `order`) VALUES
+('bx_timeline_enable_sort_by_reaction', '', @iCategId, '_bx_timeline_option_enable_sort_by_reaction', 'checkbox', '', '', '', '', 3),
+('bx_timeline_enable_sort_by_unread', '', @iCategId, '_bx_timeline_option_enable_sort_by_unread', 'checkbox', '', '', '', '', 4);
+
+
+SET @iCategId = (SELECT `id` FROM `sys_options_categories` WHERE `name`='bx_timeline_card' LIMIT 1);
+DELETE FROM `sys_options` WHERE `name` IN ('bx_timeline_title_chars', 'bx_timeline_title_chars_short');
+INSERT INTO `sys_options` (`name`, `value`, `category_id`, `caption`, `type`, `check`, `check_params`, `check_error`, `extra`, `order`) VALUES
+('bx_timeline_title_chars', '64', @iCategId, '_bx_timeline_option_title_chars', 'digit', '', '', '', '', 5),
+('bx_timeline_title_chars_short', '32', @iCategId, '_bx_timeline_option_title_chars_short', 'digit', '', '', '', '', 6);
+
+
+-- CRON
+DELETE FROM `sys_cron_jobs` WHERE `name`='bx_timeline_clean';
+INSERT INTO `sys_cron_jobs` (`name`, `time`, `class`, `file`, `service_call`) VALUES
+('bx_timeline_clean', '0 0 * * *', 'BxTimelineCronClean', 'modules/boonex/timeline/classes/BxTimelineCronClean.php', '');

+ 11 - 0
modules/boonex/timeline/updates/13.0.4_13.0.5/install/sql/install.sql

@@ -0,0 +1,11 @@
+SET @sName = 'bx_timeline';
+
+
+-- TABLES
+CREATE TABLE IF NOT EXISTS `bx_timeline_events2users` (
+  `id` int(11) NOT NULL auto_increment,
+  `user_id` int(11) NOT NULL DEFAULT '0',
+  `event_id` int(11) NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`),
+  UNIQUE `view` (`user_id`, `event_id`)
+);

+ 39 - 0
modules/boonex/timeline/updates/13.0.4_13.0.5/source/classes/BxTimelineCmts.php

@@ -0,0 +1,39 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Timeline Timeline
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxTimelineCmts extends BxTemplCmts
+{
+    protected $_sModule;
+    protected $_oModule;
+
+    function __construct($sSystem, $iId, $iInit = 1)
+    {
+        parent::__construct($sSystem, $iId, $iInit);
+
+        $this->_sModule = 'bx_timeline';
+        $this->_oModule = BxDolModule::getInstance($this->_sModule);
+
+        $this->_aSystem['trigger_field_privacy_view'] = 'object_privacy_view';
+    }
+    
+    public function onPostAfter($iCmtId)
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        $mixedResult = parent::onPostAfter($iCmtId);
+        if($mixedResult !== false)
+            $this->_oModule->_oDb->updateEvent([$CNF['FIELD_REACTED'] => time()], [$CNF['FIELD_ID'] => $this->getId()]);
+
+        return $mixedResult;
+    }
+}
+
+/** @} */

+ 941 - 0
modules/boonex/timeline/updates/13.0.4_13.0.5/source/classes/BxTimelineConfig.php

@@ -0,0 +1,941 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Timeline Timeline
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+bx_import('BxDolPrivacy');
+
+class BxTimelineConfig extends BxBaseModNotificationsConfig
+{
+    protected $_aTypeToFormDisplay;
+
+    protected $_bAllowEdit;
+    protected $_bAllowDelete;
+    protected $_bShowAll;
+    protected $_bCountAllViews;
+    protected $_bRepostOwnActions;
+    protected $_bHideUponDelete;
+
+    protected $_bCacheItem;
+    protected $_sCacheItemEngine;
+    protected $_iCacheItemLifetime;
+
+    protected $_bInfScroll;
+    protected $_iInfScrollAutoPreloads;
+
+    protected $_iRssLength;
+    protected $_iLiveUpdateLength;
+    protected $_iCharsDisplayMinTitle;
+    protected $_iCharsDisplayMaxTitle;
+
+    protected $_bBriefCards;
+    protected $_aBriefCardsTags;
+    protected $_sVideosPreload;
+    protected $_sVideosAutoplay;
+    protected $_iPreloadComments;
+    protected $_iPreloadCommentsMax;
+    protected $_bJumpTo;
+    protected $_bSortByReaction;
+    protected $_bSortByUnread;
+    protected $_sAttachmentsLayout;
+
+    protected $_bHot;
+    protected $_iHotInterval;
+    protected $_iHotThresholdContent;
+    protected $_iHotThresholdComment;
+    protected $_iHotThresholdVote;
+    protected $_aHotSources;
+    protected $_aHotSourcesList;
+    protected $_aHotList;
+
+    protected $_bEditorToolbar;
+    protected $_bEditorAutoAttach;
+    protected $_iLimitAttachLinks;
+
+    protected $_bUnhideRestored;
+
+    protected $_sStorageObject;
+    protected $_sTranscoderObjectPreview;
+    protected $_sTranscoderObjectView;
+    protected $_aPhotoUploaders;
+    protected $_aVideoUploaders;
+    protected $_aItemToUploader;
+
+    protected $_sMenuItemManage;
+    protected $_sMenuItemActions;
+
+    protected $_aRepostDefaults;
+
+    protected $_iTimelineVisibilityThreshold;
+    protected $_aPregPatterns;
+
+    protected $_sSessionKeyType;
+
+    /**
+     * Constructor
+     */
+    public function __construct($aModule)
+    {
+        parent::__construct($aModule);
+
+        $this->CNF = array (
+            'ICON' => 'far clock col-green1',
+
+            // database tables
+            'TABLE_ENTRIES' => $aModule['db_prefix'] . 'events',
+
+            // database fields
+            'FIELD_ID' => 'id',
+            'FIELD_AUTHOR' => 'object_owner_id',
+            'FIELD_OWNER_ID' => 'owner_id',
+            'FIELD_SYSTEM' => 'system',
+            'FIELD_OBJECT_ID' => 'object_id', //Note. For 'Direct Timeline Posts' ('system' db field == 0) this field contains post's author profile ID.
+            'FIELD_OBJECT_OWNER_ID' => 'object_owner_id',
+            'FIELD_OBJECT_PRIVACY_VIEW' => 'object_privacy_view',
+            'FIELD_CF' => 'object_cf',
+            'FIELD_ADDED' => 'date',
+            'FIELD_PUBLISHED' => 'published',
+            'FIELD_TITLE' => 'title',
+            'FIELD_TEXT' => 'description',
+            'FIELD_ATTACHMENTS' => 'attachments',
+            'FIELD_LINK' => 'link',
+            'FIELD_PHOTO' => 'photo',
+            'FIELD_VIDEO' => 'video',
+            'FIELD_FILE' => 'file',
+            'FIELD_STATUS' => 'status',
+            'FIELD_STATUS_ADMIN' => 'status_admin',
+            'FIELD_STICKED' => 'sticked',
+            'FIELD_DATE' => 'date',
+            'FIELD_REACTED' => 'reacted',
+            'FIELD_ANONYMOUS' => 'anonymous',
+            'FIELD_CONTROLS' => 'controls',
+            'FIELD_LOCATION' => 'location',
+            'FIELD_LOCATION_PREFIX' => 'location',
+            'FIELDS_DELAYED_PROCESSING' => 'video', // can be array of fields or comma separated string of field names
+
+            // page URIs
+            'URI_VIEW_LIST' => 'timeline-view',
+            'URI_VIEW_ENTRY' => 'item',
+
+            'URL_HOME' => 'page.php?i=timeline-view-home',
+
+            // some params
+            'PARAM_AUTO_APPROVE' => $this->_sName . '_enable_auto_approve',
+
+            // objects
+            'OBJECT_STORAGE' => $this->_sName . '_photos',
+            'OBJECT_STORAGE_VIDEOS' => $this->_sName . '_videos',
+            'OBJECT_STORAGE_FILES' => $this->_sName . '_files',
+            'OBJECT_IMAGES_TRANSCODER_PREVIEW' => $this->_sName . '_photos_preview',
+            'OBJECT_VIDEOS_TRANSCODER_PREVIEW' => $this->_sName . '_proxy_preview',
+            'OBJECT_VIDEOS_TRANSCODERS' => array(
+                'poster' => 'bx_timeline_videos_poster_view', 
+                'poster_preview' => 'bx_timeline_videos_poster_preview', 
+            	'mp4' => 'bx_timeline_videos_mp4', 
+            	'mp4_hd' => 'bx_timeline_videos_mp4_hd'
+            ),
+            'OBJECT_UPLOADER_PHOTO_SIMPLE' => $this->_sName . '_simple_photo',
+            'OBJECT_UPLOADER_PHOTO_HTML5' => $this->_sName . '_html5_photo',
+            'OBJECT_UPLOADER_VIDEO_SIMPLE' => $this->_sName . '_simple_video',
+            'OBJECT_UPLOADER_VIDEO_HTML5' => $this->_sName . '_html5_video',
+            'OBJECT_UPLOADER_VIDEO_RECORD' => $this->_sName . '_record_video',
+            'OBJECT_UPLOADER_FILE_HTML5' => $this->_sName . '_html5_file',
+            'OBJECT_UPLOADER_FILE_SIMPLE' => $this->_sName . '_simple_file',
+            'OBJECT_GRID_ADMINISTRATION' => $this->_sName . '_administration',
+            'OBJECT_GRID_COMMON' => $this->_sName . '_common',
+            'OBJECT_GRID_MUTE' => $this->_sName . '_mute',
+            'OBJECT_MENU_ENTRY_ATTACHMENTS' => $this->_sName . '_menu_post_attachments',
+            'OBJECT_METATAGS' => $this->_sName,
+            'OBJECT_COMMENTS' => $this->_sName,
+            'OBJECT_NOTES' => $this->_sName . '_notes',
+            'OBJECT_VIEWS' => $this->_sName,
+            'OBJECT_VOTES' => $this->_sName,
+            'OBJECT_REACTIONS' => $this->_sName . '_reactions',
+            'OBJECT_SCORES' => $this->_sName,
+            'OBJECT_REPORTS' => $this->_sName,
+            'OBJECT_PRIVACY_VIEW' => $this->_sName . '_privacy_view',
+            'OBJECT_CONNECTIONS_MUTE' => $this->_sName . '_mute',
+
+            // some language keys
+            'T' => array (
+                'txt_status_deleted' => '_bx_timeline_txt_status_deleted',
+                'txt_sample_single' => '_bx_timeline_txt_sample',
+                'txt_sample_single_ext' => '_bx_timeline_txt_sample_ext',
+            	'txt_sample_comment_single' => '_bx_timeline_txt_sample_comment_single',
+                'txt_sample_vote_single' => '_bx_timeline_txt_sample_vote_single',
+                'txt_sample_reaction_single' => '_bx_timeline_txt_sample_reaction_single',
+                'txt_sample_score_up_single' => '_bx_timeline_txt_sample_score_up_single',
+                'txt_sample_score_down_single' => '_bx_timeline_txt_sample_score_down_single',
+                'txt_sample_with_link' => '_bx_timeline_txt_sample_with_link',
+                'txt_sample_with_image' => '_bx_timeline_txt_sample_with_image',
+                'txt_sample_with_video' => '_bx_timeline_txt_sample_with_video',
+                'txt_sample_with_file' => '_bx_timeline_txt_sample_with_file',
+                'txt_sample_with_media' => '_bx_timeline_txt_sample_with_media',
+                'grid_action_err_delete' => '_bx_timeline_grid_action_err_delete', 
+                'grid_txt_account_manager' => '_bx_timeline_grid_txt_account_manager',
+                'filter_item_active' => '_bx_timeline_grid_filter_item_title_adm_active',
+            	'filter_item_hidden' => '_bx_timeline_grid_filter_item_title_adm_hidden',
+                'filter_item_pending' => '_bx_timeline_grid_filter_item_title_adm_pending',
+            	'filter_item_select_one_filter1' => '_bx_timeline_grid_filter_item_title_adm_select_one_filter1',
+                'form_input_title_object_privacy_view' => '_bx_timeline_form_post_input_object_privacy_view',
+                'option_vp_auto' => '_bx_timeline_option_videos_preload_auto',
+                'option_vp_metadata' => '_bx_timeline_option_videos_preload_metadata',
+                'option_vp_none' => '_bx_timeline_option_videos_preload_none',
+                'option_vap_off' => '_bx_timeline_option_videos_autoplay_off',
+                'option_vap_on_mute' => '_bx_timeline_option_videos_autoplay_on_mute',
+                'option_vap_on' => '_bx_timeline_option_videos_autoplay_on',
+                'option_al_gallery' => '_bx_timeline_option_attachments_layout_gallery',
+                'option_al_showcase' => '_bx_timeline_option_attachments_layout_showcase',
+                'option_hs_content' => '_bx_timeline_option_hot_sources_content',
+                'option_hs_comment' => '_bx_timeline_option_hot_sources_comment',
+                'option_hs_vote' => '_bx_timeline_option_hot_sources_vote',
+            ),
+        );
+
+        $this->_aTypeToFormDisplay = array(
+            BX_BASE_MOD_NTFS_TYPE_OWNER => 'form_display_post_add_profile',
+            BX_BASE_MOD_NTFS_TYPE_PUBLIC => 'form_display_post_add_public',
+            BX_TIMELINE_TYPE_CHANNELS => 'form_display_post_add',
+            BX_TIMELINE_TYPE_FEED => 'form_display_post_add',
+            BX_TIMELINE_TYPE_OWNER_AND_CONNECTIONS => 'form_display_post_add'
+        );
+
+        $this->_aPrefixes = array(
+            'style' => 'bx-tl',
+            'language' => '_bx_timeline',
+            'option' => 'bx_timeline_',
+            'common_post' => 'timeline_common_',
+            'cache_list_hot' => 'bx_timeline_list_hot',
+            'cache_item' => 'bx_timeline_item_'
+        );
+
+        $this->_aObjects = array_merge($this->_aObjects, array(
+            'comment' => $this->CNF['OBJECT_COMMENTS'],
+            'view' => $this->CNF['OBJECT_VIEWS'],
+            'vote' => $this->CNF['OBJECT_VOTES'],
+            'reaction' => $this->CNF['OBJECT_REACTIONS'],
+            'score' => $this->CNF['OBJECT_SCORES'],
+            'report' => $this->CNF['OBJECT_REPORTS'],
+            'privacy_view' => $this->CNF['OBJECT_PRIVACY_VIEW'],
+            'metatags' => $this->_sName,
+
+            'storage_photos' => $this->CNF['OBJECT_STORAGE'],
+            'storage_videos' => $this->CNF['OBJECT_STORAGE_VIDEOS'],
+            'storage_files' => $this->CNF['OBJECT_STORAGE_FILES'],
+            'transcoder_photos_preview' => $this->CNF['OBJECT_IMAGES_TRANSCODER_PREVIEW'],
+            'transcoder_photos_view' => $this->_sName . '_photos_view',
+            'transcoder_photos_medium' => $this->_sName . '_photos_medium',
+            'transcoder_photos_big' => $this->_sName . '_photos_big',
+            'transcoder_videos_preview' => $this->CNF['OBJECT_VIDEOS_TRANSCODER_PREVIEW'],
+            'transcoder_videos_poster' => $this->CNF['OBJECT_VIDEOS_TRANSCODERS']['poster'],
+            'transcoder_videos_mp4' => $this->CNF['OBJECT_VIDEOS_TRANSCODERS']['mp4'],
+            'transcoder_videos_mp4_hd' => $this->CNF['OBJECT_VIDEOS_TRANSCODERS']['mp4_hd'],
+            'transcoder_videos_photo_view' => $this->_sName . '_videos_photo_view',
+            'transcoder_videos_photo_big' => $this->_sName . '_videos_photo_big',
+
+            'page_item_brief' => $this->_sName . '_item_brief',
+
+            'menu_view' => $this->_sName . '_menu_view',
+            'menu_feeds' => $this->_sName . '_menu_feeds',
+            'menu_set_feeds' => $this->_sName . '_menu_feeds',
+            'menu_item_manage' => $this->_sName . '_menu_item_manage',
+            'menu_item_actions' => $this->_sName . '_menu_item_actions',
+            'menu_item_actions_all' => $this->_sName . '_menu_item_actions_all',
+            'menu_item_counters' => $this->_sName . '_menu_item_counters',
+            'menu_item_meta' => $this->_sName . '_menu_item_meta',
+            'menu_post_attachments' => $this->CNF['OBJECT_MENU_ENTRY_ATTACHMENTS'],
+
+            'form_post' => $this->_sName . '_post',
+            'form_attach_link' => $this->_sName . '_attach_link',
+            'form_repost' => $this->_sName . '_repost',
+            'form_display_post_add' => $this->_sName . '_post_add',
+            'form_display_post_add_public' => $this->_sName . '_post_add_public',
+            'form_display_post_add_profile' => $this->_sName . '_post_add_profile',
+            'form_display_post_edit' => $this->_sName . '_post_edit',
+            'form_display_post_view' => $this->_sName . '_post_view',
+            'form_display_attach_link_add' => $this->_sName . '_attach_link_add',
+            'form_display_repost_with' => $this->_sName . '_repost_with',
+            'form_display_repost_to' => $this->_sName . '_repost_to',
+
+            'grid_mute' => $this->CNF['OBJECT_GRID_MUTE'],
+
+            'connection_mute' => $this->CNF['OBJECT_CONNECTIONS_MUTE'],
+        ));
+
+        $this->_aHandlerDescriptor = array('module_name' => '', 'module_method' => '', 'module_class' => '', 'groupable' => '', 'group_by' => '');
+        $this->_sHandlersMethod = 'get_timeline_data';
+
+        $this->_aPhotoUploaders = array($this->CNF['OBJECT_UPLOADER_PHOTO_SIMPLE']);
+        $this->_aVideoUploaders = array($this->CNF['OBJECT_UPLOADER_VIDEO_SIMPLE']);
+        $this->_aFilesUploaders = array($this->CNF['OBJECT_UPLOADER_FILE_SIMPLE']);
+
+        $this->_aItemToUploader = array(
+            'add-photo-simple' => $this->CNF['OBJECT_UPLOADER_PHOTO_SIMPLE'],
+            'add-photo-html5' => $this->CNF['OBJECT_UPLOADER_PHOTO_HTML5'],
+            'add-video-simple' => $this->CNF['OBJECT_UPLOADER_VIDEO_SIMPLE'],
+            'add-video-html5' => $this->CNF['OBJECT_UPLOADER_VIDEO_HTML5'],
+            'add-video-record' => $this->CNF['OBJECT_UPLOADER_VIDEO_RECORD'],
+            'add-file-simple' => $this->CNF['OBJECT_UPLOADER_FILE_SIMPLE'],
+            'add-file-html5' => $this->CNF['OBJECT_UPLOADER_FILE_HTML5'],
+        );
+
+        $this->_bJsMode = false;
+        $this->_aJsClasses = array(
+            'main' => 'BxTimelineMain',
+            'view' => 'BxTimelineView',
+            'post' => 'BxTimelinePost',
+            'repost' => 'BxTimelineRepost',
+            'manage_tools' => 'BxTimelineManageTools'
+        );
+        $this->_aJsObjects = array(
+            'view' => 'oTimelineView',
+            'post' => 'oTimelinePost',
+            'repost' => 'oTimelineRepost',
+            'manage_tools' => 'oBxTimelineManageTools'
+        );
+
+        $this->_aGridObjects = array(
+            'administration' => $this->CNF['OBJECT_GRID_ADMINISTRATION'],
+            'common' => $this->CNF['OBJECT_GRID_COMMON']
+        );
+
+        $sHp = str_replace('_', '-', $this->_sName);
+        $sHpT = BX_TIMELINE_VIEW_TIMELINE;
+        $sHpO = BX_TIMELINE_VIEW_OUTLINE;
+        $this->_aHtmlIds = array(
+            'view' => array(
+                'edit_form' => $sHp . '-edit-',
+                'attach_link_form_field' => $sHp . '-attach-link-form-field-',
+
+                'menu_popup' => $sHp . '-menu-popup-',
+
+                'video_iframe' => $sHp . '-video-iframe-',
+                'video' => $sHp . '-video-',
+
+                'live_update_popup' => $sHp . '-live-update-popup-',
+            ),
+            'post' => array(
+                'attach_link_popup' =>  $sHp . '-attach-link-popup',
+                'attach_link_form_field' => $sHp . '-attach-link-form-field-',
+                'attach_link_item' => $sHp . '-attach-link-item-',
+                'textarea' => $sHp . '-textarea-',
+
+                'main_' . $sHpT => $sHp . '-' . $sHpT,
+                'main_' . $sHpO => $sHp . '-' . $sHpO,
+            ),
+            'repost' => array(
+                'main' => $sHp . '-repost-',
+                'counter' => $sHp . '-repost-counter-',
+                'by_popup' => $sHp . '-repost-by-',
+                'with_popup' => $sHp . '-repost-with',
+                'to_popup' => $sHp . '-repost-to',
+            )
+        );
+
+        $this->_aRepostDefaults = array(
+            'do' => 'repost',
+
+            'show_do_repost_as_button' => false,
+            'show_do_repost_as_button_small' => false,
+            'show_do_repost_icon' => true,
+            'show_do_repost_text' => false,
+
+            //--- Counter
+            'show_counter_label_icon' => false,
+            'show_counter_label_text' => true,
+            'show_counter' => true,
+
+            //--- JS script
+            'show_script' => true,
+
+            //--- Icons
+            'icon_do_repost' => 'redo',
+            'icon_do_repost_with' => 'redo',
+            'icon_do_repost_to' => 'redo',
+
+            //--- Texts
+            'text_do_repost' => '_bx_timeline_txt_do_repost',
+            'text_do_repost_with' => '_bx_timeline_txt_do_repost_with',
+            'text_do_repost_to' => '_bx_timeline_txt_do_repost_to',
+
+            //--- Templates
+            'template_do_repost_label' => '',
+            'template_do_repost_label_name' => 'repost_do_repost_label.html',
+        );
+
+        $this->_iTimelineVisibilityThreshold = 0;
+
+        $this->_aPregPatterns = array(
+            "meta_title" => "/<title>(.*)<\/title>/",
+            "meta_description" => "/<meta[\s]+[^>]*?name[\s]?=[\s\"\']+description[\s\"\']+content[\s]?=[\s\"\']+(.*?)[\"\']+.*?>/",
+            "url" => "/(([A-Za-z]{3,9}:(?:\/\/)?)(?:[\-;:&=\+\$,\w]+@)?[A-Za-z0-9\.\-]+|(?:www\.|[\-;:&=\+\$,\w]+@)[A-Za-z0-9\.\-]+)((?:\/[\+~%#\/\.\w\-_!\(\)]*)?\??(?:[\-\+=&;%@\.\w_]*)#?(?:[\.\!\/\\\w]*))?/"
+        );
+
+        $this->_aBriefCardsTags = array('a', 'b', 'i');
+
+        $this->_sSessionKeyType = $this->_sName . '_type_';
+
+        $this->_aHotSourcesList = [
+            BX_TIMELINE_HFS_CONTENT, 
+            BX_TIMELINE_HFS_COMMENT,
+            BX_TIMELINE_HFS_VOTE
+        ];
+    }
+
+    public function init(&$oDb)
+    {
+    	parent::init($oDb);
+
+    	$sOptionPrefix = $this->getPrefix('option');
+    	$this->_bAllowEdit = getParam($sOptionPrefix . 'enable_edit') == 'on';
+        $this->_bAllowDelete = getParam($sOptionPrefix . 'enable_delete') == 'on';
+        $this->_bShowAll = getParam($sOptionPrefix . 'enable_show_all') == 'on';
+        $this->_bCountAllViews = getParam($sOptionPrefix . 'enable_count_all_views') == 'on';
+        $this->_bRepostOwnActions = getParam($sOptionPrefix . 'enable_repost_own_actions') == 'on';
+        $this->_bHideUponDelete = getParam($sOptionPrefix . 'enable_hide_upon_delete') == 'on';
+
+        $this->_bCacheItem = getParam($sOptionPrefix . 'enable_cache_item') == 'on';
+        $this->_sCacheItemEngine = getParam($sOptionPrefix . 'cache_item_engine');
+        $this->_iCacheItemLifetime = (int)getParam($sOptionPrefix . 'cache_item_lifetime');
+
+        $this->_aPerPage = array(
+            'default' => (int)getParam($sOptionPrefix . 'events_per_page'),
+            'profile' => (int)getParam($sOptionPrefix . 'events_per_page_profile'),
+            'account' => (int)getParam($sOptionPrefix . 'events_per_page_account'),
+            'home' => (int)getParam($sOptionPrefix . 'events_per_page_home'),
+            'preload' => (int)getParam($sOptionPrefix . 'events_per_preload')
+    	);
+
+        $this->_bInfScroll = getParam($sOptionPrefix . 'enable_infinite_scroll') == 'on';
+        $this->_iInfScrollAutoPreloads = (int)getParam($sOptionPrefix . 'auto_preloads');
+
+        $this->_iRssLength = (int)getParam($sOptionPrefix . 'rss_length');       
+
+        $this->_bBriefCards = getParam($sOptionPrefix . 'enable_brief_cards') == 'on';
+
+        $this->_iLiveUpdateLength = 10;
+        $this->_iCharsDisplayMinTitle = (int)getParam($sOptionPrefix . 'title_chars_short');
+        $this->_iCharsDisplayMaxTitle = (int)getParam($sOptionPrefix . 'title_chars');
+
+        $this->_sVideosPreload = getParam($sOptionPrefix . 'videos_preload');
+        $this->_sVideosAutoplay = getParam($sOptionPrefix . 'videos_autoplay');
+
+        $this->_iPreloadCommentsMax = 7;
+        $this->_iPreloadComments = (int)getParam($sOptionPrefix . 'preload_comments');
+        if($this->_iPreloadComments > $this->_iPreloadCommentsMax)
+            $this->_iPreloadComments = $this->_iPreloadCommentsMax;
+
+        $this->_bJumpTo = getParam($sOptionPrefix . 'enable_jump_to_switcher') == 'on';
+        $this->_bSortByReaction = getParam($sOptionPrefix . 'enable_sort_by_reaction') == 'on';
+        $this->_bSortByUnread = getParam($sOptionPrefix . 'enable_sort_by_unread') == 'on';
+        $this->_sAttachmentsLayout = getParam($sOptionPrefix . 'attachments_layout');
+
+        $this->_bHot = getParam($sOptionPrefix . 'enable_hot') == 'on';
+        $this->_iHotThresholdContent = (int)getParam($sOptionPrefix . 'hot_threshold_age');
+        $this->_iHotThresholdComment = (int)getParam($sOptionPrefix . 'hot_threshold_comment');
+        $this->_iHotThresholdVote = (int)getParam($sOptionPrefix . 'hot_threshold_vote');
+        $this->_iHotInterval = (int)getParam($sOptionPrefix . 'hot_interval');
+        $this->_aHotSources = explode(',', getParam($sOptionPrefix . 'hot_sources'));
+        $this->_aHotList = $this->_bHot ? $this->_oDb->getHot() : array();
+
+        $this->_bEditorToolbar = getParam($sOptionPrefix . 'enable_editor_toolbar') == 'on';
+        $this->_bEditorAutoAttach = getParam($sOptionPrefix . 'editor_auto_attach_insertion') == 'on';
+        $this->_iLimitAttachLinks = (int)getParam($sOptionPrefix . 'limit_attach_links');
+
+        $this->_bUnhideRestored = false;
+    }
+
+    /**
+     * Generate name from parameters.
+     * 
+     * @param type $aParams - parameters whose values will be used during generation.
+     * @param type $aRules - generation rules.
+     * @return string
+     */
+    protected function getNameView($aParams, $aRules = array())
+    {
+        $bWithView = !isset($aRules['with_view']) || $aRules['with_view'] === true;
+        $bWithType = !isset($aRules['with_type']) || $aRules['with_type'] === true;
+        $bWithOwner = isset($aRules['with_owner']) && $aRules['with_owner'] === true;
+        $sGlue = !empty($aRules['glue']) ? $aRules['glue'] : '_';
+
+        $aAddons = array();
+        if(!empty($aParams['name']))
+            $aAddons[] = bx_process_output($aParams['name']);
+        else {
+            if($bWithView && !empty($aParams['view']))
+                $aAddons[] = bx_process_output($aParams['view']);
+
+            if($bWithType && !empty($aParams['type']))
+                $aAddons[] = bx_process_output($aParams['type']);
+        }
+
+        if($bWithOwner)
+            $aAddons[] = (int)$aParams['owner_id'];
+
+        return !empty($aAddons) ? implode($sGlue, $aAddons) : '';
+    }
+
+    /**
+     * Generates unique JS object name for View events block.
+     * 
+     * @param array $aParams - an array with browsing params received in View block service method
+     * @return string with JS object name
+     */
+    public function getJsObjectView($aParams = array())
+    {
+        return parent::getJsObject('view') . bx_gen_method_name($this->getNameView($aParams));
+    }
+
+    public function getHtmlIdView($sKey, $aParams, $aRules = array())
+    {
+        $bWhole = !isset($aRules['whole']) || $aRules['whole'] === true;
+        $sGlue = !empty($aRules['glue']) ? $aRules['glue'] : '_';
+
+        return str_replace($sGlue, '-', $this->_sName  . $sGlue . $sKey . $sGlue . $this->getNameView($aParams, $aRules) . (!$bWhole ? $sGlue : ''));
+    }
+
+    public function isAllowEdit()
+    {
+        return $this->_bAllowEdit;
+    }
+
+    public function isAllowDelete()
+    {
+        return $this->_bAllowDelete;
+    }
+
+    public function isInfiniteScroll()
+    {
+        return $this->_bInfScroll;
+    }
+
+    public function isShowAll()
+    {
+        return $this->_bShowAll;
+    }
+
+    public function isCountAllViews()
+    {
+        return $this->_bCountAllViews;
+    }
+
+    public function isRepostOwnActions()
+    {
+        return $this->_bRepostOwnActions;
+    }
+
+    public function isHideUponDelete()
+    {
+        return $this->_bHideUponDelete;
+    }
+
+    public function isBriefCards()
+    {
+        return $this->_bBriefCards;
+    }
+
+    public function isJumpTo()
+    {
+        return $this->_bJumpTo;
+    }
+
+    public function isSortByReaction()
+    {
+        return $this->_bSortByReaction;
+    }
+
+    public function isSortByUnread()
+    {
+        return $this->_bSortByUnread;
+    }
+
+    public function isHot()
+    {
+        return $this->_bHot;
+    }
+
+    public function getHotSourcesList()
+    {
+        return $this->_aHotSourcesList;
+    }
+
+    public function getHotSources()
+    {
+        return $this->_aHotSources;
+    }
+
+    public function isHotSource($sName)
+    {
+        return in_array($sName, $this->_aHotSources);
+    }
+
+    public function getHotThreshold($sSource)
+    {
+        if(!in_array($sSource, [BX_TIMELINE_HFS_CONTENT, BX_TIMELINE_HFS_COMMENT, BX_TIMELINE_HFS_VOTE]))
+            return false;
+
+        return $this->{'_iHotThreshold' . ucfirst($sSource)};
+    }
+
+    public function isHotEvent($iEventId)
+    {
+        return in_array($iEventId, $this->_aHotList);
+    }
+
+    public function isEmoji()
+    {
+        $oMenu = BxDolMenu::getObjectInstance($this->getObject('menu_post_attachments'));
+        if(!$oMenu)
+            return false;
+
+        return $oMenu->isMenuItem('add-emoji');
+    }
+
+    public function isEditorToolbar()
+    {
+    	return $this->_bEditorToolbar;
+    }
+
+    public function isEditorAutoAttach()
+    {
+    	return $this->_bEditorAutoAttach;
+    }
+
+    public function isUnhideRestored()
+    {
+        return $this->_bUnhideRestored;
+    }
+
+    public function isCacheItem()
+    {
+        return $this->_bCacheItem;
+    }
+
+    public function getCacheItemEngine()
+    {
+        return $this->_sCacheItemEngine;
+    }
+
+    public function getCacheItemLifetime()
+    {
+        return $this->_iCacheItemLifetime;
+    }
+
+    public function getCacheItemKey($iId, $sPostfix = '')
+    {
+        return $this->getPrefix('cache_item') . $iId . (bx_is_mobile() ? '_m' : '') . '_r' . bx_get_device_pixel_ratio() . '_' . (!empty($sPostfix) ? '_' . $sPostfix : '') . '.php';
+    }
+
+    public function getCacheHotKey()
+    {
+        return $this->getPrefix('cache_list_hot');
+    }
+
+    public function getPostFormDisplay($sType)
+    {
+        if(empty($sType) || !array_key_exists($sType, $this->_aTypeToFormDisplay))
+            $sType = BX_TIMELINE_TYPE_DEFAULT;
+
+        return $this->_aTypeToFormDisplay[$sType];
+    }
+
+    public function getUploaders($sField)
+    {
+        $aResult = array();
+
+        switch($sField) {
+            case 'photo':
+                $aResult = $this->_aPhotoUploaders;
+                break;
+            case 'video':
+                $aResult = $this->_aVideoUploaders;
+                break;
+            case 'file':
+                $aResult = $this->_aFilesUploaders;
+                break;
+        }
+
+        return $aResult;
+    }
+
+    public function getUploaderByMenuItem($sMenuItem)
+    {
+        if(!isset($this->_aItemToUploader[$sMenuItem]))
+            return false;
+    
+        return $this->_aItemToUploader[$sMenuItem];
+    }
+
+    public function getPerPage($sType = 'default')
+    {
+        if($this->isInfiniteScroll())
+            $sType = 'preload';
+
+        return parent::getPerPage($sType);
+    }
+
+    public function getExtenalsEvery($sType = 'default')
+    {
+        if($this->isInfiniteScroll())
+            $sType .= '_preload';
+
+        $iExtenalsEvery = (int)getParam($this->getPrefix('option') . 'extenals_every_' . $sType);
+        if(!$iExtenalsEvery)
+            return $iExtenalsEvery;
+
+        $iPerPage = $this->getPerPage($sType);
+        if(empty($iPerPage))
+            $iPerPage = $this->getPerPage();
+
+        if($iExtenalsEvery > $iPerPage)
+            $iExtenalsEvery = $iPerPage;
+
+        return $iExtenalsEvery;
+    }
+
+    public function getAutoPreloads()
+    {
+        return $this->_iInfScrollAutoPreloads;
+    }
+
+    public function getRssLength()
+    {
+        return $this->_iRssLength;
+    }
+
+    public function getLiveUpdateLength()
+    {
+        return $this->_iLiveUpdateLength;
+    }
+
+    public function getCharsDisplayMinTitle()
+    {
+        return $this->_iCharsDisplayMinTitle;
+    }
+
+    public function getCharsDisplayMaxTitle()
+    {
+        return $this->_iCharsDisplayMaxTitle;
+    }
+
+    public function getBriefCardsTags($bAsString = false)
+    {
+        return !$bAsString ? $this->_aBriefCardsTags : '<' . implode('><', $this->_aBriefCardsTags) . '>';
+    }
+
+    public function getVideosPreload()
+    {
+        return $this->_sVideosPreload;
+    }
+
+    public function getVideosAutoplay()
+    {
+        return $this->_sVideosAutoplay;
+    }
+
+    public function getPreloadComments()
+    {
+        return $this->_iPreloadComments;
+    }
+
+    public function getAttachmentsLayout()
+    {
+        return $this->_sAttachmentsLayout;
+    }
+
+    public function getHotInterval()
+    {
+        return $this->_iHotInterval;
+    }
+
+    public function getLimitAttachLinks()
+    {
+        return $this->_iLimitAttachLinks;
+    }
+
+    public function getRepostDefaults()
+    {
+        return $this->_aRepostDefaults;
+    }
+
+    public function getPregPattern($sType)
+    {
+        return $this->_aPregPatterns[$sType];
+    }
+
+    /**
+     * Ancillary functions
+     */
+    public function getTitle($s, $mixedProfile = false, $sMethodLength = 'getCharsDisplayMaxTitle')
+    {
+        if(get_mb_substr($s, 0, 1) == '_' && strcmp($s, _t($s)) != 0)
+            return $s;
+
+        if($mixedProfile !== false) {
+            if(is_numeric($mixedProfile))
+                $mixedProfile = BxDolProfile::getInstanceMagic((int)$mixedProfile);
+
+            if($mixedProfile instanceof BxDolProfile)
+                $s = bx_replace_markers($s, array(
+                    'profile_name' => $mixedProfile->getDisplayName()
+                ));
+        }
+
+        if(!method_exists($this, $sMethodLength))
+            $sMethodLength = 'getCharsDisplayMaxTitle';
+
+        return strmaxtextlen($s, $this->$sMethodLength(), '...');
+    }
+
+    public function getTitleShort($s, $mixedProfile = false)
+    {
+        return $this->getTitle($s, $mixedProfile, 'getCharsDisplayMinTitle');
+    }
+
+    public function getTitleDefault($bL, $bP, $bV, $bF)
+    {
+        $sResult = '';
+
+        if($bL && !$bP && !$bV && !$bF)
+            $sResult = 'link';
+        else if(!$bL && $bP && !$bV && !$bF)
+            $sResult = 'image';
+        else if(!$bL && !$bP && $bV && !$bF)
+            $sResult = 'video';
+        else if(!$bL && !$bP && !$bV && $bF)
+            $sResult = 'file';
+        else 
+            $sResult = 'media';
+
+        return $this->CNF['T']['txt_sample_with_' . $sResult];
+    }
+
+    public function getViewUrl($iOwnerId, $bAbsolute = true)
+    {
+        return ($bAbsolute ? BX_DOL_URL_ROOT : '') . BxDolPermalinks::getInstance()->permalink('page.php?i=' . $this->CNF['URI_VIEW_LIST'], [
+            'id' => $iOwnerId
+        ]);
+    }
+
+    public function getHomeViewUrl($bAbsolute = true)
+    {
+        return ($bAbsolute ? BX_DOL_URL_ROOT : '') . BxDolPermalinks::getInstance()->permalink($this->CNF['URL_HOME']);
+    }
+
+    public function getItemViewUrl($aEvent, $bAbsolute = true)
+    {
+        return ($bAbsolute ? BX_DOL_URL_ROOT : '') . BxDolPermalinks::getInstance()->permalink('page.php?i=' . $this->CNF['URI_VIEW_ENTRY'], [
+            'id' => $aEvent['id']
+        ]);
+    }
+
+    public function getLiveUpdateKey($aParams)
+    {
+        return $this->getName() . '_live_update_' . $this->getNameView($aParams, array('with_owner' => true));
+    }
+
+    public function isCommon($sType, $sAction)
+    {
+        return !$this->isSystem($sType, $sAction);
+    }
+
+    public function isSystem($sType, $sAction)
+    {
+        $sPrefix = $this->getPrefix('common_post');
+        return strpos($sType, $sPrefix) === false && !empty($sAction);
+    }
+
+    public function getSystemData(&$aEvent, $aBrowseParams = array())
+    {
+        $aHandler = $this->getHandler($aEvent);
+        if($aHandler === false)
+            return false;
+
+        return BxDolService::call($aHandler['module_name'], $aHandler['module_method'], array($aEvent, $aBrowseParams), $aHandler['module_class']);
+    }
+
+    public function getSystemDataByDescriptor($sType, $sAction, $iObjectId)
+    {
+    	$aDescriptor = array(
+            'type' => $sType, 
+            'action' => $sAction,
+            'object_id' => $iObjectId
+    	);
+    	return $this->getSystemData($aDescriptor);
+    }
+
+    public function isEqualUrls($sUrl1, $sUrl2)
+    {
+        $sUrl1 = trim($sUrl1, "/");
+        $sUrl2 = trim($sUrl2, "/");
+
+        return strncmp($sUrl1, $sUrl2, strlen($sUrl1)) === 0;
+    }
+
+    public function addBrowseParams($sUrl, $aParams, $sKey = 'bp')
+    {
+        return bx_append_url_params($sUrl, [$sKey => base64_encode(json_encode($aParams))]);
+    }
+
+    public function getBrowseParams($sValue)
+    {
+        return json_decode(base64_decode(urldecode($sValue)), true);
+    }
+
+    public function setUserChoice($aChoices = array())
+    {
+        if(!isLogged() || empty($aChoices))
+            return;
+
+        $iUserId = bx_get_logged_profile_id();
+
+        $oSession = BxDolSession::getInstance();
+        foreach($aChoices as $sKey => $mixedValue) {
+            $sField = '_sSessionKey' . bx_gen_method_name($sKey);
+            if(isset($this->$sField) && !empty($mixedValue))
+                $oSession->setValue($this->$sField . $iUserId, $mixedValue);
+        }
+    }
+
+    public function getUserChoice($sKey, $iUserId = 0)
+    {
+        $sField = '_sSessionKey' . bx_gen_method_name($sKey);
+        if(!isLogged() || !isset($this->$sField))
+            return false;
+
+        if(!$iUserId)
+            $iUserId = bx_get_logged_profile_id();
+
+        return BxDolSession::getInstance()->getValue($this->$sField . $iUserId);
+    }
+
+    public function prepareParam($sName, $sPattern = "/^[\d\w_]+$/")
+    {
+        return $this->processParam(bx_get($sName), $sPattern);
+    }
+
+    public function prepareParamWithDefault($sName, $sDefault, $sPattern = "/^[\d\w_]+$/")
+    {
+        return ($sValue = $this->prepareParam($sName, $sPattern)) != '' ? $sValue : $sDefault;
+    }
+
+    public function processParam($sValue, $sPattern = "/^[\d\w_]+$/")
+    {
+        $mixedValue = bx_process_input($sValue);
+        return $mixedValue !== false && preg_match($sPattern, $mixedValue) ? $mixedValue : '';
+    }
+
+    public function processParamWithDefault($sValue, $sDefault, $sPattern = "/^[\d\w_]+$/")
+    {
+        return ($sValue = $this->processParam($sValue, $sPattern)) != '' ? $sValue : $sDefault;
+    }
+}
+
+/** @} */

+ 36 - 0
modules/boonex/timeline/updates/13.0.4_13.0.5/source/classes/BxTimelineCronClean.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    Timeline Timeline
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxTimelineCronClean extends BxDolCron
+{
+    protected $_sModule;
+    protected $_oModule;
+
+    protected $_iLimitRead;
+
+    public function __construct()
+    {
+    	$this->_sModule = 'bx_timeline';
+    	$this->_oModule = BxDolModule::getInstance($this->_sModule);
+
+        parent::__construct();
+
+        $this->_iLimitRead = 1000;
+    }
+
+    public function processing()
+    {
+        if($this->_iLimitRead > 0)
+            $this->_oModule->_oDb->cleanRead($this->_iLimitRead);
+    }
+}
+
+/** @} */

+ 1197 - 0
modules/boonex/timeline/updates/13.0.4_13.0.5/source/classes/BxTimelineDb.php

@@ -0,0 +1,1197 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Timeline Timeline
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxTimelineDb extends BxBaseModNotificationsDb
+{
+    protected $_sTableEvent2User;
+
+    protected $_sTableRepostsTrack;
+    protected $_sTableHotTrack;
+
+    protected $_aTablesMedia;
+    protected $_aTablesMedia2Events;
+
+    /*
+     * Constructor.
+     */
+    function __construct(&$oConfig)
+    {
+        parent::__construct($oConfig);
+
+        $CNF = &$this->_oConfig->CNF;
+
+        $this->_sTableEvent2User = $this->_sPrefix . 'events2users';
+
+        $this->_sTableRepostsTrack = $this->_sPrefix . 'reposts_track';
+        $this->_sTableHotTrack = $this->_sPrefix . 'hot_track';
+
+        $this->_aTablesMedia = array(
+            $CNF['FIELD_PHOTO'] => $this->_sPrefix . 'photos',
+            $CNF['FIELD_VIDEO'] => $this->_sPrefix . 'videos',
+			$CNF['FIELD_FILE'] => $this->_sPrefix . 'files' 
+        );
+        $this->_aTablesMedia2Events = array(
+            $CNF['FIELD_PHOTO'] => $this->_sPrefix . 'photos2events',
+            $CNF['FIELD_VIDEO'] => $this->_sPrefix . 'videos2events',
+			$CNF['FIELD_FILE'] => $this->_sPrefix . 'files2events'
+        );
+    }
+
+    public function deleteModuleEvents($aData)
+    {
+        foreach($aData['handlers'] as $aHandler) {
+            //Delete system events.
+            $this->deleteEvent(array('type' => $aHandler['alert_unit'], 'action' => $aHandler['alert_action']));
+
+            //Delete reposted events.
+            $aEvents = $this->getEvents(array('browse' => 'reposted_by_descriptor', 'type' => $aHandler['alert_unit'], 'action' => $aHandler['alert_action']));
+                foreach($aEvents as $aEvent) {
+                    $aContent = unserialize($aEvent['content']);
+                    if(isset($aContent['type']) && $aContent['type'] == $aHandler['alert_unit'] && isset($aContent['action']) && $aContent['action'] == $aHandler['alert_action'])
+                        $this->deleteEvent(array('id' => (int)$aEvent['id']));
+                }
+        }
+    }
+    
+    public function updateStatusAdmin($iContentId, $isActive)
+    {
+        $CNF = $this->_oConfig->CNF;
+        $sQuery = $this->prepare("UPDATE `" . $CNF['TABLE_ENTRIES'] . "` SET `active` = ? WHERE `" . $CNF['FIELD_ID'] . "` = ?", $isActive ? '1' : '0', $iContentId);
+        return $this->query($sQuery);
+    }
+
+    public function activateModuleEvents($aData, $bActivate = true)
+    {
+        $iActivate = $bActivate ? 1 : 0;
+
+        foreach($aData['handlers'] as $aHandler) {
+            //Activate (deactivate) system events.
+            $this->updateEvent(array('active' => $iActivate), array('type' => $aHandler['alert_unit'], 'action' => $aHandler['alert_action']));
+
+            //Activate (deactivate) reposted events.
+            $aEvents = $this->getEvents(array('browse' => 'reposted_by_descriptor', 'type' => $aHandler['alert_unit'], 'action' => $aHandler['alert_action']));
+            foreach($aEvents as $aEvent) {
+                $aContent = unserialize($aEvent['content']);
+                if(isset($aContent['type']) && $aContent['type'] == $aHandler['alert_unit'] && isset($aContent['action']) && $aContent['action'] == $aHandler['alert_action'])
+                    $this->updateEvent(array('active' => $iActivate), array('id' => (int)$aEvent['id']));
+            }
+        }
+    }
+
+    public function getMaxDuration($aParams)
+    {
+        $aParams['browse'] = 'last';
+        if(isset($aParams['timeline']))
+            unset($aParams['timeline']);
+
+        $aEvent = $this->getEvents($aParams);
+        if(empty($aEvent) || !is_array($aEvent))
+            return 0;
+
+        $iNowYear = date('Y', time());
+        return (int)$aEvent['year'] < $iNowYear ? (int)$aEvent['year'] : 0;
+    }
+
+    public function markAsRead($iUserId, $iEventId)
+    {
+        return (int)$this->query("INSERT IGNORE INTO `{$this->_sTableEvent2User}` SET `user_id` = :user_id, `event_id` = :event_id", [
+            'user_id' => $iUserId,
+            'event_id' => $iEventId
+        ]) !== false;
+    }
+
+    public function cleanRead($iLimit)
+    {
+        $aUsers = $this->getAll("SELECT `user_id` AS `id`, COUNT(`event_id`) AS `reads` FROM `{$this->_sTableEvent2User}` WHERE 1 GROUP BY `user_id` HAVING `reads`>:limit", [
+            'limit' => $iLimit
+        ]);
+        
+        foreach($aUsers as $aUser)
+            $this->query("DELETE FROM `{$this->_sTableEvent2User}` WHERE `user_id`=:user_id ORDER BY `event_id` LIMIT :limit", [
+                'user_id' => $aUser['id'],
+                'limit' => (int)$aUser['reads'] - $iLimit
+            ]);
+    }
+
+    //--- Repost related methods ---//
+    public function insertRepostTrack($iEventId, $iAuthorId, $sAuthorIp, $iRepostedId)
+    {
+        $iNow = time();
+        $iAuthorNip = bx_get_ip_hash($sAuthorIp);
+        $sQuery = $this->prepare("INSERT INTO `{$this->_sTableRepostsTrack}` SET `event_id` = ?, `author_id` = ?, `author_nip` = ?, `reposted_id` = ?, `date` = ?", $iEventId, $iAuthorId, $iAuthorNip, $iRepostedId, $iNow);
+        return (int)$this->query($sQuery) > 0;
+    }
+
+    public function updateRepostTrack($aParamsSet, $aParamsWhere)
+    {
+        if(empty($aParamsSet) || empty($aParamsWhere))
+            return false;
+
+        $sSql = "UPDATE `{$this->_sTableRepostsTrack}` SET " . $this->arrayToSQL($aParamsSet) . " WHERE " . $this->arrayToSQL($aParamsWhere, " AND ");
+        return $this->query($sSql);
+    }
+
+    public function deleteRepostTrack($iEventId)
+    {
+        $sQuery = $this->prepare("DELETE FROM `{$this->_sTableRepostsTrack}` WHERE `event_id` = ?", $iEventId);
+        return (int)$this->query($sQuery) > 0;
+    }
+
+    public function updateRepostCounter($iId, $iCounter, $iIncrement = 1)
+    {
+        return (int)$this->updateEvent(array('reposts' => (int)$iCounter + $iIncrement), array('id' => $iId)) > 0;
+    }
+
+    public function getReposted($sType, $sAction, $iObjectId)
+    {
+    	$bSystem = $this->_oConfig->isSystem($sType, $sAction);
+
+        if($bSystem)
+            $aParams = array('browse' => 'descriptor', 'type' => $sType, 'action' => $sAction, 'object_id' => $iObjectId);
+        else
+            $aParams = array('browse' => 'id', 'value' => $iObjectId);
+
+        $aReposted = $this->getEvents($aParams);
+        if($bSystem && (empty($aReposted) || !is_array($aReposted))) {
+            $iOwnerId = 0;
+            $iDate = 0;
+            $sStatus = BX_TIMELINE_STATUS_DELETED;
+
+            $mixedResult = $this->_oConfig->getSystemDataByDescriptor($sType, $sAction, $iObjectId);
+            if(is_array($mixedResult)) {
+                $iOwnerId = !empty($mixedResult['owner_id']) ? (int)$mixedResult['owner_id'] : 0;
+                $iDate = !empty($mixedResult['date']) ? (int)$mixedResult['date'] : 0;
+                if($this->_oConfig->isUnhideRestored() && !empty($iOwnerId) && !empty($iDate))
+                    $sStatus = BX_TIMELINE_STATUS_ACTIVE;
+            }
+
+            $iId = $this->insertEvent(array(
+                'owner_id' => $iOwnerId,
+                'type' => $sType,
+                'action' => $sAction,
+                'object_id' => $iObjectId,
+                'object_owner_id' => $iOwnerId,
+                'object_privacy_view' => $this->_oConfig->getPrivacyViewDefault('object'),
+                'content' => '',
+                'title' => '',
+                'description' => '',
+                'date' => $iDate,
+                'reacted' => $iDate,
+                'status' => $sStatus
+            ));
+
+            $aReposted = $this->getEvents(array('browse' => 'id', 'value' => $iId));
+        }
+
+        return $aReposted;
+    }
+
+    function getRepostedBy($iRepostedId)
+    {
+        $sQuery = $this->prepare("SELECT `author_id` FROM `{$this->_sTableRepostsTrack}` WHERE `reposted_id`=?", $iRepostedId);
+        return $this->getColumn($sQuery);
+    }
+
+    function getReposts($iRepostedId)
+    {
+        return $this->getAll("SELECT * FROM `{$this->_sTableRepostsTrack}` WHERE `reposted_id`=:reposted_id", array(
+            'reposted_id' => $iRepostedId
+        ));
+    }
+
+    function isReposted($iRepostedId, $iOwnerId, $iAuthorId)
+    {
+    	$sQuery = $this->prepare("SELECT 
+    			`te`.`id`
+    		FROM `{$this->_sTableRepostsTrack}` AS `tst` 
+    		LEFT JOIN `{$this->_sTable}` AS `te` ON `tst`.`event_id`=`te`.`id` 
+    		WHERE `tst`.`author_id`=? AND `tst`.`reposted_id`=? AND `te`.`owner_id`=?", $iAuthorId, $iRepostedId, $iOwnerId);
+
+    	return (int)$this->getOne($sQuery) > 0;
+    }
+
+    //--- Photo uploader related methods ---//
+    public function saveMedia($sType, $iEventId, $iItemId)
+    {
+        return (int)$this->query("INSERT INTO `" . $this->_aTablesMedia2Events[$sType] . "` SET `event_id`=:event_id, `media_id`=:media_id", array(
+            'event_id' => $iEventId,
+            'media_id' => $iItemId
+        )) > 0;
+    }
+
+    public function deleteMedia($sType, $iEventId)
+    {
+        return (int)$this->query("DELETE FROM `" . $this->_aTablesMedia2Events[$sType] . "` WHERE `event_id`=:event_id", array(
+            'event_id' => $iEventId
+        )) > 0;
+    }
+
+    public function getMedia($sType, $iEventId, $iOffset = 0, $bFullInfo = false)
+    {
+    	$sTableMedia = $this->_aTablesMedia[$sType];
+    	$sTableMedia2Events = $this->_aTablesMedia2Events[$sType];
+
+        $sMethod = 'getColumn';
+        $sSelectClause = "`tme`.`media_id` AS `id`";
+        if($bFullInfo) {
+            $sMethod = 'getAll';
+            $sSelectClause = "`tm`.*, `tme`.`event_id` AS `event_id`";
+        }
+
+        $sLimitAddon = '';
+        if($iOffset != 0)
+            $sLimitAddon = $this->prepareAsString(" OFFSET ?", $iOffset);
+
+        $sQuery = $this->prepare("SELECT " . $sSelectClause . " 
+            FROM `" . $sTableMedia2Events . "` AS `tme`
+            LEFT JOIN `" . $sTableMedia . "` AS `tm` ON `tme`.`media_id`=`tm`.`id`
+            WHERE `tme`.`event_id`=?" . $sLimitAddon, $iEventId);
+
+        return $this->$sMethod($sQuery);
+    }
+
+    public function getMediaById($sType, $iMediaId)
+    {
+        $sTableMedia = $this->_aTablesMedia[$sType];
+    	$sTableMedia2Events = $this->_aTablesMedia2Events[$sType];
+
+        return $this->getRow("SELECT `tm`.*, `tme`.`event_id` AS `event_id` FROM `" . $sTableMedia2Events . "` AS `tme` LEFT JOIN `" . $sTableMedia . "` AS `tm` ON `tme`.`media_id`=`tm`.`id` WHERE `tme`.`media_id`=:media_id LIMIT 1", array(
+            'media_id' => $iMediaId
+        ));
+    }
+
+    //--- Link attach related methods ---//
+    public function getUnusedLinks($iUserId)
+    {
+        return $this->getLinksBy(array(
+            'type' => 'unused',
+            'profile_id' => $iUserId
+        ));
+    }
+
+    public function deleteUnusedLinks($iUserId, $iLinkId = 0)
+    {
+    	$aBindings = array(
+    		'profile_id' => $iUserId
+    	);
+
+        $sWhereAddon = '';
+        if(!empty($iLinkId)) {
+        	$aBindings['id'] = $iLinkId;
+
+            $sWhereAddon = " AND `id`=:id";
+        }
+
+        return $this->query("DELETE FROM `" . $this->_sPrefix . "links` WHERE `profile_id`=:profile_id" . $sWhereAddon, $aBindings);
+    }
+
+    public function saveLink($iEventId, $iLinkId)
+    {
+        $aBindings = array(
+            'event_id' => $iEventId,
+            'link_id' => $iLinkId
+        );
+
+        $iId = $this->getOne("SELECT `id` FROM `" . $this->_sPrefix . "links2events` WHERE `event_id`=:event_id AND `link_id`=:link_id LIMIT 1", $aBindings);
+        if(!empty($iId))
+            return true;
+
+        return (int)$this->query("INSERT INTO `" . $this->_sPrefix . "links2events` SET `event_id`=:event_id, `link_id`=:link_id", $aBindings) > 0;
+    }
+
+    public function deleteLink($iId)
+    {
+        return (int)$this->query("DELETE FROM `tl`, `tle` USING `" . $this->_sPrefix . "links` AS `tl` LEFT JOIN `" . $this->_sPrefix . "links2events` AS `tle` ON `tl`.`id`=`tle`.`link_id` WHERE `tl`.`id` = :id", array(
+            'id' => $iId
+        )) > 0;
+    }
+
+    public function deleteLinks($iEventId)
+    {
+        return (int)$this->query("DELETE FROM `tl`, `tle` USING `" . $this->_sPrefix . "links` AS `tl` LEFT JOIN `" . $this->_sPrefix . "links2events` AS `tle` ON `tl`.`id`=`tle`.`link_id` WHERE `tle`.`event_id` = :event_id", array(
+            'event_id' => $iEventId
+        )) > 0;
+    }
+
+    public function getLinks($iEventId)
+    {
+        return $this->getLinksBy(array('type' => 'event_id', 'event_id' => $iEventId));
+    }
+
+    public function getLinksBy($aParams = array())
+    {
+        $CNF = &$this->_oConfig->CNF;
+    	$aMethod = array('name' => 'getAll', 'params' => array(0 => 'query'));
+
+    	$sSelectClause = "`tl`.*";
+    	$sJoinClause = $sWhereClause = $sGroupClause = $sOrderClause = $sLimitClause = "";
+        switch($aParams['type']) {
+            case 'id':
+            	$aMethod['name'] = 'getRow';
+            	$aMethod['params'][1] = array(
+                    'id' => $aParams['id']
+                );
+
+                $sWhereClause = " AND `tl`.`id`=:id";
+
+                if(!empty($aParams['profile_id'])) {
+                    $aMethod['params'][1]['profile_id'] = $aParams['profile_id'];
+
+                    $sWhereClause .= " AND `tl`.`profile_id`=:profile_id";
+                }
+                break;
+
+            case 'event_id':
+            	$aMethod['params'][1] = array(
+                    'event_id' => $aParams['event_id']
+                );
+
+                $sJoinClause = "LEFT JOIN `" . $this->_sPrefix . "links2events` AS `tle` ON `tl`.`id`=`tle`.`link_id`";
+                $sWhereClause = " AND `tle`.`event_id`=:event_id";
+                break;
+
+            case 'unused':
+                $aBindings = array(
+                    'profile_id' => $aParams['profile_id']
+                );
+
+                if(isset($aParams['short']) && $aParams['short'] === true) {
+                    $aMethod['name'] = 'getPairs';
+                    $aMethod['params'][1] = 'url';
+                    $aMethod['params'][2] = 'id';
+                    $aMethod['params'][3] = $aBindings;
+                }
+                else
+                    $aMethod['params'][1] = $aBindings;
+
+                $sJoinClause = "LEFT JOIN `" . $this->_sPrefix . "links2events` AS `tle` ON `tl`.`id`=`tle`.`link_id`";
+                $sWhereClause = " AND `tl`.`profile_id`=:profile_id AND ISNULL(`tle`.`event_id`)";
+                $sOrderClause = "`tl`.`added` DESC";
+                break;
+        }
+
+        $sOrderClause = !empty($sOrderClause) ? "ORDER BY " . $sOrderClause : $sOrderClause;
+        $sLimitClause = !empty($sLimitClause) ? "LIMIT " . $sLimitClause : $sLimitClause;
+
+        $aMethod['params'][0] = "SELECT
+                " . $sSelectClause . "
+            FROM `" . $this->_sPrefix . "links` AS `tl` " . $sJoinClause . "
+            WHERE 1" . $sWhereClause . " " . $sGroupClause . " " . $sOrderClause . " " . $sLimitClause;
+
+        return call_user_func_array(array($this, $aMethod['name']), $aMethod['params']);
+    }
+
+    public function getHot()
+    {
+        return $this->fromCache($this->_oConfig->getCacheHotKey(), 'getColumn', "SELECT `event_id` FROM `" . $this->_sTableHotTrack . "`");
+    }
+
+    public function clearHot()
+    {
+        $this->cleanCache($this->_oConfig->getCacheHotKey());
+
+        return $this->query("TRUNCATE TABLE `" . $this->_sTableHotTrack . "`");
+    }
+
+    public function getHotTrackByDate($iInterval = 24)
+    {
+        $aBindings = [
+            'interval' => $iInterval
+        ];
+
+        $sQuery = "SELECT 
+                `te`.`id` AS `event_id`,
+                `te`.`date` AS `value`
+            FROM `" . $this->_sTable . "` AS `te`
+            WHERE (`te`.`system` <> 0 OR `te`.`owner_id` = 0) AND `te`.`date` > (UNIX_TIMESTAMP() - 3600 * :interval)";
+
+        return $this->getPairs($sQuery, 'event_id', 'value', $aBindings);
+    }
+
+    public function getHotTrackByCommentsDate($sModule, $sTableTrack, $iInterval = 24, $iThresholdAge = 0, $iThresholdCount = 0)
+    {
+        $aBindings = [
+            'module' => $sModule, 
+            'interval' => $iInterval
+        ];
+
+        $sQueryWhere = " AND (`te`.`system` <> 0 OR `te`.`owner_id` = 0) AND `tt`.`cmt_time` > (UNIX_TIMESTAMP() - 3600 * :interval)";
+
+        if($iThresholdAge != 0) {
+            $aBindings['threshold_age'] = $iThresholdAge;
+
+            $sQueryWhere .= " AND (UNIX_TIMESTAMP() - `te`.`date`) / 86400 <= :threshold_age";
+        }
+
+        $sQueryGroup = "`te`.`id`";
+        if($iThresholdCount != 0) {
+            $aBindings['threshold_count'] = $iThresholdCount;
+
+            $sQueryGroup .= " HAVING COUNT(DISTINCT `tt`.`cmt_author_id`) >= :threshold_count";
+        }
+
+        $sQuery = "SELECT 
+                `te`.`id` as `event_id`,
+                MAX(`tt`.`cmt_time`) AS `value`
+            FROM `" . $this->_sTable . "` AS `te`
+            INNER JOIN `" . $sTableTrack . "` AS `tt` ON `te`.`id`=`tt`.`cmt_object_id` AND `te`.`object_owner_id`<>`tt`.`cmt_author_id` AND `te`.`type`=:module 
+            WHERE 1 " . $sQueryWhere . " 
+            GROUP BY " . $sQueryGroup;
+
+        return $this->getPairs($sQuery, 'event_id', 'value', $aBindings);
+    }
+
+    public function getHotTrackByCommentsDateModule($sModule, $sTableTrack, $iInterval = 24, $iThresholdAge = 0, $iThresholdCount = 0)
+    {
+        $aBindings = [
+            'module' => $sModule, 
+            'interval' => $iInterval
+        ];
+
+        $sQueryWhere = " AND (`te`.`system` <> 0 OR `te`.`owner_id` = 0) AND `tt`.`cmt_time` > (UNIX_TIMESTAMP() - 3600 * :interval)";
+
+        if($iThresholdAge != 0) {
+            $aBindings['threshold_age'] = $iThresholdAge;
+
+            $sQueryWhere .= " AND (UNIX_TIMESTAMP() - `te`.`date`) / 86400 <= :threshold_age";
+        }
+
+        $sQueryGroup = "`te`.`object_id`";
+        if($iThresholdCount != 0) {
+            $aBindings['threshold_count'] = $iThresholdCount;
+
+            $sQueryGroup .= " HAVING COUNT(DISTINCT `tt`.`cmt_author_id`) >= :threshold_count";
+        }
+
+        $sQuery = "SELECT 
+                `te`.`id` as `event_id`,
+                MAX(`tt`.`cmt_time`) AS `value`
+            FROM `" . $this->_sTable . "` AS `te`
+            INNER JOIN `" . $sTableTrack . "` AS `tt` ON `te`.`object_id`=`tt`.`cmt_object_id` AND `te`.`object_owner_id`<>`tt`.`cmt_author_id` AND `te`.`type`=:module
+            WHERE 1 " . $sQueryWhere . " 
+            GROUP BY " . $sQueryGroup;
+
+        return $this->getPairs($sQuery, 'event_id', 'value', $aBindings);
+    }
+
+    public function getHotTrackByVotesDate($sModule, $sTableTrack, $iInterval = 24, $iThresholdAge = 0, $iThresholdCount = 0)
+    {
+        $aBindings = [
+            'module' => $sModule, 
+            'interval' => $iInterval
+        ];
+
+        $sQueryWhere = " AND (`te`.`system` <> 0 OR `te`.`owner_id` = 0) AND `tt`.`date` > (UNIX_TIMESTAMP() - 3600 * :interval)";
+
+        if($iThresholdAge != 0) {
+            $aBindings['threshold_age'] = $iThresholdAge;
+
+            $sQueryWhere .= " AND (UNIX_TIMESTAMP() - `te`.`date`) / 86400 <= :threshold_age";
+        }
+
+        $sQueryGroup = "`te`.`id`";
+        if($iThresholdCount != 0) {
+            $aBindings['threshold_count'] = $iThresholdCount;
+
+            $sQueryGroup .= " HAVING COUNT(DISTINCT `tt`.`author_id`) >= :threshold_count";
+        }
+
+        $sQuery = "SELECT 
+                `te`.`id` as `event_id`,
+                MAX(`tt`.`date`) AS `value`
+            FROM `" . $this->_sTable . "` AS `te`
+            INNER JOIN `" . $sTableTrack . "` AS `tt` ON `te`.`id`=`tt`.`object_id` AND `te`.`object_owner_id`<>`tt`.`author_id` AND `te`.`type`=:module 
+            WHERE 1 " . $sQueryWhere . " 
+            GROUP BY " . $sQueryGroup;
+
+        return $this->getPairs($sQuery, 'event_id', 'value', $aBindings);
+    }
+
+    public function getHotTrackByVotesDateModule($sModule, $sTableTrack, $iInterval = 24, $iThresholdAge = 0, $iThresholdCount = 0)
+    {
+        $aBindings = [
+            'module' => $sModule, 
+            'interval' => $iInterval
+        ];
+
+        $sQueryWhere = " AND (`te`.`system` <> 0 OR `te`.`owner_id` = 0) AND `tt`.`date` > (UNIX_TIMESTAMP() - 3600 * :interval)";
+
+        if($iThresholdAge != 0) {
+            $aBindings['threshold_age'] = $iThresholdAge;
+
+            $sQueryWhere .= " AND (UNIX_TIMESTAMP() - `te`.`date`) / 86400 <= :threshold_age";
+        }
+
+        $sQueryGroup = "`te`.`object_id`";
+        if($iThresholdCount != 0) {
+            $aBindings['threshold_count'] = $iThresholdCount;
+
+            $sQueryGroup .= " HAVING COUNT(DISTINCT `tt`.`author_id`) >= :threshold_count";
+        }
+
+        $sQuery = "SELECT 
+                `te`.`id` as `event_id`,
+                MAX(`tt`.`date`) AS `value`
+            FROM `" . $this->_sTable . "` AS `te`
+            INNER JOIN `" . $sTableTrack . "` AS `tt` ON `te`.`object_id`=`tt`.`object_id` AND `te`.`object_owner_id`<>`tt`.`author_id` AND `te`.`type`=:module 
+            WHERE 1 " . $sQueryWhere . " 
+            GROUP BY " . $sQueryGroup;
+
+        return $this->getPairs($sQuery, 'event_id', 'value', $aBindings);
+    }
+
+    /**
+     * Hot Track by Sum of Votes during specified Period is currently disabled.
+     */
+    public function getHotTrackByVotesSum($sModule, $sTableTrack, $iInterval = 24)
+    {
+        $sQuery = "SELECT 
+                `te`.`id` as `event_id`,
+                SUM(`tt`.`value`) AS `value`
+            FROM `" . $this->_sTable . "` AS `te`
+            INNER JOIN `" . $sTableTrack . "` AS `tt` ON `te`.`id`=`tt`.`object_id` AND `te`.`type`=:module 
+            WHERE (`te`.`system` <> 0 OR `te`.`owner_id` = 0) AND `tt`.`date` > (UNIX_TIMESTAMP() - 3600 * :interval) 
+            GROUP BY `te`.`id`";
+
+        return $this->getAll($sQuery, array('module' => $sModule, 'interval' => $iInterval));
+    }
+
+    /**
+     * Hot Track by Sum of Votes during specified Period is currently disabled.
+     */
+    public function getHotTrackByVotesSumModule($sModule, $sTableTrack, $iInterval = 24)
+    {
+        $sQuery = "SELECT 
+                `te`.`id` as `event_id`,
+                SUM(`tt`.`value`) AS `value`
+            FROM `" . $this->_sTable . "` AS `te`
+            INNER JOIN `" . $sTableTrack . "` AS `tt` ON `te`.`object_id`=`tt`.`object_id` AND `te`.`type`=:module 
+            WHERE (`te`.`system` <> 0 OR `te`.`owner_id` = 0) AND `tt`.`date` > (UNIX_TIMESTAMP() - 3600 * :interval) 
+            GROUP BY `te`.`object_id`";
+
+        return $this->getAll($sQuery, array('module' => $sModule, 'interval' => $iInterval));
+    }
+
+    public function updateHotTrack($aTrack)
+    {
+        return (int)$this->query("REPLACE INTO `" . $this->_sTableHotTrack . "` SET " . $this->arrayToSQL($aTrack)) > 0;
+    }
+
+    public function getEvents($aParams)
+    {
+        bx_alert($this->_oConfig->getName(), 'get_events_before', 0, 0, array(
+            'params' => &$aParams,
+        ));
+
+        list($sMethod, $sSelectClause, $mixedJoinClause, $mixedWhereClause, $sOrderClause, $sLimitClause) = $this->_getSqlPartsEvents($aParams);
+
+        $bCount = isset($aParams['count']) && $aParams['count'] === true;
+        if($bCount) {
+            $sMethod = 'getOne';
+            $sSelectClause = 'COUNT(*)';
+            $sOrderClause = '';
+            $sLimitClause = '';
+        }
+
+        $aAlertParams = $aParams;
+        unset($aAlertParams['browse']);
+
+        bx_alert($this->_oConfig->getName(), 'get_events', 0, 0, array(
+            'browse' => $aParams['browse'],
+            'params' => $aAlertParams,
+            'table' => $this->_sTable,
+            'method' => &$sMethod,
+            'select_clause' => &$sSelectClause,
+            'join_clause' => &$mixedJoinClause,
+            'where_clause' => &$mixedWhereClause,
+            'order_clause' => &$sOrderClause,
+            'limit_clause' => &$sLimitClause
+        ));
+
+        $sJoinClauseAddon = '';
+        if($this->_oConfig->isSortByUnread() && $this->_isList($aParams))
+            $sJoinClauseAddon = $this->prepareAsString(" LEFT JOIN `{$this->_sTableEvent2User}` AS `teu` ON `{$this->_sTable}`.`id`=`teu`.`event_id` AND `teu`.`user_id`=? ", $aParams['viewer_id']);
+
+        $sSqlMask = "SELECT {select}
+            FROM `{$this->_sTable}`
+            INNER JOIN `sys_profiles` ON `{$this->_sTable}`.`object_owner_id`=`sys_profiles`.`id` AND `sys_profiles`.`status`='active' LEFT JOIN `{$this->_sTableHandlers}` ON `{$this->_sTable}`.`type`=`{$this->_sTableHandlers}`.`alert_unit` AND `{$this->_sTable}`.`action`=`{$this->_sTableHandlers}`.`alert_action` {$sJoinClauseAddon} {join}
+            WHERE 1 {where} {order} {limit}";
+
+        if(is_string($mixedWhereClause)) {
+            $aSqlMarkers = array(
+                'select' => $sSelectClause, 
+                'join' => $mixedJoinClause, 
+                'where' => $mixedWhereClause, 
+                'order' => $sOrderClause, 
+                'limit' => $sLimitClause
+            );
+
+            return $this->$sMethod(bx_replace_markers($sSqlMask, $aSqlMarkers));
+        }
+
+        $bJoinAsArray = !empty($mixedJoinClause) && is_array($mixedJoinClause);
+
+        $sOrderSubclause = $sLimitSubclause = '';
+        if(!$bCount) {
+            $sOrderSubclause = $sOrderClause;
+            $sLimitSubclause = isset($aParams['per_page']) ? 'LIMIT 0, ' . ($aParams['start'] + $aParams['per_page']) : '';
+        }
+
+        $aSqlParts = array();
+        foreach($mixedWhereClause as $sKey => $sValue) {
+            $aSqlMarkers = array(
+                'select' => $sSelectClause, 
+                'join' => $bJoinAsArray ? (isset($mixedJoinClause[$sKey]) ? $mixedJoinClause[$sKey] : '') : $mixedJoinClause, 
+                'where' => $sValue, 
+                'order' => $sOrderSubclause, 
+                'limit' => $sLimitSubclause
+            );
+            $sSqlPart = bx_replace_markers($sSqlMask, $aSqlMarkers);
+
+            $aSqlParts[] = !$bCount ? $sSqlPart : (int)$this->$sMethod($sSqlPart);
+        }
+
+        return $bCount ? array_sum($aSqlParts) : $this->$sMethod(bx_replace_markers('(' . implode(') UNION (', $aSqlParts) . ') {order} {limit}', array(
+            'order' => str_replace('`' . $this->_sTable . '`.', '', $sOrderClause),
+            'limit' => str_replace('`' . $this->_sTable . '`.', '', $sLimitClause),
+        )));
+    }
+
+    protected function _getFilterAddon($iOwnerId, $sFilter)
+    {
+        switch($sFilter) {
+            /**
+             * Direct posts in Timeline made by a timeline owner ($iOwnerId)
+             */
+            case BX_TIMELINE_FILTER_OWNER:
+                $sFilterAddon = $this->prepareAsString(" AND `{$this->_sTable}`.`action`='' AND `{$this->_sTable}`.`object_id`=? ", $iOwnerId);
+                break;
+
+            /**
+             * Direct posts in Timeline made by users except a timeline owner ($iOwnerId)
+             */
+            case BX_TIMELINE_FILTER_OTHER:
+                $sFilterAddon = $this->prepareAsString(" AND `{$this->_sTable}`.`action`='' AND `{$this->_sTable}`.`object_id`<>? ", $iOwnerId);
+                break;
+
+            /**
+             * All (Direct and System) posts in Timeline (owned by $iOwnerId) made by users except the viewer
+             */
+            case BX_TIMELINE_FILTER_OTHER_VIEWER:
+                $sFilterAddon = $this->prepareAsString(" AND (`{$this->_sTable}`.`action`<>'' OR (`{$this->_sTable}`.`action`='' AND `{$this->_sTable}`.`object_id`<>?)) ", bx_get_logged_profile_id());
+                break;
+                
+
+            case BX_TIMELINE_FILTER_ALL:
+            default:
+                $sFilterAddon = "";
+        }
+        return $sFilterAddon;
+    }
+
+    protected function _getSqlPartsEvents($aParams)
+    {
+    	$sMethod = 'getAll';
+    	$sSelectClause = "`{$this->_sTable}`.*";
+        $sJoinClause = $sWhereClause = $sOrderClause = $sLimitClause = "";
+
+        switch($aParams['browse']) {
+            case 'owner_id':
+                $sWhereClause = $this->prepareAsString("AND `{$this->_sTable}`.`owner_id`=? ", $aParams['value']);
+                break;
+
+            case 'common_by_object':
+                $sCommonPostPrefix = $this->_oConfig->getPrefix('common_post');
+                $sWhereClause = $this->prepareAsString("AND `{$this->_sTable}`.`system`='0' AND `{$this->_sTable}`.`object_id`=? ", $aParams['value']);
+                break;
+
+            case 'descriptor':
+                $sMethod = 'getRow';
+                $sWhereClause = "";
+
+                if(isset($aParams['type']))
+                    $sWhereClause .= $this->prepareAsString("AND `{$this->_sTable}`.`type`=? ", $aParams['type']);
+                if(isset($aParams['action']))
+                    $sWhereClause .= $this->prepareAsString("AND `{$this->_sTable}`.`action`=? ", $aParams['action']);
+                if(isset($aParams['object_id']))
+                    $sWhereClause .= $this->prepareAsString("AND `{$this->_sTable}`.`object_id`=? ", $aParams['object_id']);
+
+                $sLimitClause = "LIMIT 1";
+                break;
+
+            case 'reposted_by_track':
+                $sJoinClause = $this->prepareAsString("INNER JOIN `" . $this->_sTableRepostsTrack . "` AS `trt` ON `{$this->_sTable}`.`id`=`trt`.`event_id` AND `trt`.`reposted_id`=?", $aParams['value']);
+                break;
+
+            case 'reposted_by_descriptor':
+            	$sWhereClause = "";
+
+            	if(isset($aParams['type']))
+                    $sWhereClause .= "AND `{$this->_sTable}`.`content` LIKE " . $this->escape('%' . $aParams['type'] . '%');
+
+                if(isset($aParams['action']))
+                    $sWhereClause .= "AND `{$this->_sTable}`.`content` LIKE " . $this->escape('%' . $aParams['action'] . '%');
+                break;
+
+            case 'list':
+                list($sMethod, $sSelectClause, $sJoinClause, $sWhereClause, $sOrderClause, $sLimitClause) = parent::_getSqlPartsEvents($aParams);
+                if(in_array($aParams['type'], array(BX_TIMELINE_TYPE_CHANNELS, BX_TIMELINE_TYPE_FEED, BX_BASE_MOD_NTFS_TYPE_CONNECTIONS, BX_TIMELINE_TYPE_OWNER_AND_CONNECTIONS)))
+                    $sSelectClause  = "DISTINCT " . $sSelectClause;
+                break;
+
+            case 'ids':
+                $sWhereClause = "AND `{$this->_sTable}`.`id` IN (" . $this->implode_escape($aParams['ids']) . ") ";
+                break;
+
+            default:
+            	list($sMethod, $sSelectClause, $sJoinClause, $sWhereClause, $sOrderClause, $sLimitClause) = parent::_getSqlPartsEvents($aParams);
+        }
+
+        $sSelectClause .= ", DAYOFYEAR(FROM_UNIXTIME(`{$this->_sTable}`.`date`)) AS `days`, DAYOFYEAR(NOW()) AS `today`, ROUND((UNIX_TIMESTAMP() - `{$this->_sTable}`.`date`)/86400) AS `ago_days`, YEAR(FROM_UNIXTIME(`{$this->_sTable}`.`date`)) AS `year`";
+        if($this->_isList($aParams)) {
+            $sOrderClause = "";
+
+            switch($aParams['type']) {
+                case BX_TIMELINE_TYPE_HOT:
+                    $sOrderClause = "`{$this->_sTable}`.`sticked` DESC, `{$this->_sTableHotTrack}`.`value` DESC, ";
+                    break;
+
+                    case BX_BASE_MOD_NTFS_TYPE_PUBLIC:
+                    case BX_BASE_MOD_NTFS_TYPE_CONNECTIONS:
+                    case BX_TIMELINE_TYPE_CHANNELS:
+                    case BX_TIMELINE_TYPE_FEED:
+                    case BX_TIMELINE_TYPE_OWNER_AND_CONNECTIONS:
+                        $sOrderClause = "`{$this->_sTable}`.`sticked` DESC, ";
+                        break;
+
+                    case BX_BASE_MOD_NTFS_TYPE_OWNER:
+                        $sOrderClause = "`{$this->_sTable}`.`pinned` DESC, ";
+                        break;
+            }
+            
+            if($this->_oConfig->isSortByUnread()) {
+                $sSelectClause .= ", IF(NOT ISNULL(`teu`.`id`), 1, 0) AS `read`";
+                $sOrderClause .= "`read` ASC, ";
+            }
+
+            if($this->_oConfig->isSortByReaction())
+                $sOrderClause .= "`{$this->_sTable}`.`reacted` DESC, ";
+            else
+                $sOrderClause .= "`{$this->_sTable}`.`date` DESC, ";
+
+            $sOrderClause = "ORDER BY " . $sOrderClause . "`{$this->_sTable}`.`id` DESC";
+        }
+
+        return array($sMethod, $sSelectClause, $sJoinClause, $sWhereClause, $sOrderClause, $sLimitClause);
+    }
+
+    protected function _getSqlPartsEventsListStatusAdmin($aParams)
+    {
+        $iViewerId = !empty($aParams['viewer_id']) ? $aParams['viewer_id'] : bx_get_logged_profile_id();
+
+        if(isset($aParams['moderator']) && $aParams['moderator'] === true)
+            return '';
+
+        //--- Check viewer as event author.
+        $sWhereClause = $this->prepareAsString("`{$this->_sTable}`.`object_owner_id`=?", $iViewerId);
+
+        //--- Check viewer as an administrator/moderator of event author.
+        $aGroups = [];
+        $aModules = bx_srv('system', 'get_modules_by_type', ['profile']);
+        foreach($aModules as $aModule) {
+            $oModule = BxDolModule::getInstance($aModule['name']);
+            if(!$oModule || !($oModule instanceof BxBaseModGroupsModule))
+                continue;
+
+            $aGroups = array_merge($aGroups, $oModule->getGroupsByFan($iViewerId, [
+                BX_BASE_MOD_GROUPS_ROLE_ADMINISTRATOR,
+                BX_BASE_MOD_GROUPS_ROLE_MODERATOR
+            ]));
+        }
+
+        if(!empty($aGroups))
+            $sWhereClause .= " OR `{$this->_sTable}`.`object_owner_id` IN (" . $this->implode_escape($aGroups) . ")";
+
+        return $this->prepareAsString(" AND IF(`{$this->_sTable}`.`system`='0' AND (" . $sWhereClause . "), 1, `{$this->_sTable}`.`status_admin`=?) ", isset($aParams['status_admin']) ? $aParams['status_admin'] : BX_TIMELINE_STATUS_ACTIVE);
+    }
+
+    protected function _getSqlPartsEventsList($aParams)
+    {
+        $sCommonPostPrefix = $this->_oConfig->getPrefix('common_post');
+
+    	$mixedJoinClause = $mixedWhereClause = "";
+
+        $sWhereClauseStatus = "AND `{$this->_sTable}`.`active`='1' ";
+        $sWhereClauseStatus .= $this->prepareAsString("AND `{$this->_sTable}`.`status`=? ", isset($aParams['status']) ? $aParams['status'] : BX_TIMELINE_STATUS_ACTIVE);
+        $sWhereClauseStatus .= $this->_getSqlPartsEventsListStatusAdmin($aParams);
+
+        //--- Apply filter
+        $sWhereClauseFilter = "";
+        if(isset($aParams['filter']))
+            $sWhereClauseFilter = $this->_getFilterAddon($aParams['owner_id'], $aParams['filter']);
+
+        //--- Apply timeline
+        $sWhereClauseTimeline = "";
+        if(isset($aParams['timeline']) && !empty($aParams['timeline']) && strpos($aParams['timeline'], '-') !== false) {
+            list($iY, $iM, $iD) = explode('-', $aParams['timeline']);
+
+            $sWhereClauseTimeline = $this->prepareAsString("AND `date`<=? ", mktime(23, 59, 59, (int)$iM, (int)$iD, (int)$iY));
+        }
+
+        //--- Apply modules or handlers filter
+        $sWhereClauseModules = "";
+        if(!empty($aParams['modules']) && is_array($aParams['modules']))
+            $sWhereClauseModules = "AND `" . $this->_sTable . "`.`type` IN (" . $this->implode_escape($aParams['modules']) . ") ";
+        
+        $sWhereClauseHidden = "";
+        if(empty($sWhereClauseModules)) {
+            $aHidden = $this->_oConfig->getHandlersHidden();
+            $sWhereClauseHidden = !empty($aHidden) && is_array($aHidden) ? "AND `" . $this->_sTableHandlers . "`.`id` NOT IN (" . $this->implode_escape($aHidden) . ") " : "";
+        }
+
+        //--- Apply mute filter
+        $sWhereClauseMuted = "";
+        $oConnection = BxDolConnection::getObjectInstance($this->_oConfig->getObject('connection_mute'));
+        if($oConnection) {
+            $aMuted = $oConnection->getConnectedContent(bx_get_logged_profile_id());
+            if(!empty($aMuted) && is_array($aMuted)) {
+                $sMuted = "NOT IN (". $this->implode_escape($aMuted) . ")";
+
+                $sWhereClauseMuted = "AND `{$this->_sTable}`.`owner_id` $sMuted AND `{$this->_sTable}`.`object_owner_id` $sMuted ";
+            }
+        }
+
+        //--- Apply unpublished (date in future) filter
+        $sWhereClauseUnpublished = $this->prepareAsString("AND IF(`{$this->_sTable}`.`system`='0' AND `{$this->_sTable}`.`object_id` = ?, 1, `{$this->_sTable}`.`date` <= UNIX_TIMESTAMP()) ", bx_get_logged_profile_id());
+
+        //--- Apply content filter
+        $oCf = BxDolContentFilter::getInstance();
+        $sWhereClauseCf = $oCf->isEnabled() ? $oCf->getSQLParts($this->_sTable, 'object_cf') . ' ' : '';
+
+        //--- Check type
+        $mixedWhereSubclause = "";
+        switch($aParams['type']) {
+            //--- Feed: Hot
+            case BX_TIMELINE_TYPE_HOT:
+                //--- Apply privacy filter
+                $aPrivacyGroups = array(BX_DOL_PG_ALL);
+                if(isLogged())
+                    $aPrivacyGroups[] = BX_DOL_PG_MEMBERS;
+
+                $aQueryParts = BxDolPrivacy::getObjectInstance($this->_oConfig->getObject('privacy_view'))->getContentByGroupAsSQLPart($aPrivacyGroups);
+                $mixedWhereClause .= $aQueryParts['where'] . " ";
+
+                //--- Select Hot posts.
+                $mixedJoinClause .= " LEFT JOIN `{$this->_sTableHotTrack}` ON `{$this->_sTable}`.`id`=`{$this->_sTableHotTrack}`.`event_id`";
+                $mixedWhereSubclause = "NOT ISNULL(`{$this->_sTableHotTrack}`.`value`)";
+
+                //--- Select Promoted posts.
+                $mixedWhereSubclause .= " OR `{$this->_sTable}`.`promoted` <> '0'";
+                break;
+
+            //--- Feed: Public
+            case BX_BASE_MOD_NTFS_TYPE_PUBLIC:
+                //--- Apply privacy filter
+                $aPrivacyGroups = array(BX_DOL_PG_ALL);
+                if(isLogged())
+                    $aPrivacyGroups[] = BX_DOL_PG_MEMBERS;
+
+                $aQueryParts = BxDolPrivacy::getObjectInstance($this->_oConfig->getObject('privacy_view'))->getContentByGroupAsSQLPart($aPrivacyGroups);
+                $mixedWhereClause .= $aQueryParts['where'] . " ";
+
+                if($this->_oConfig->isShowAll())
+                    break;
+
+                //--- Select All System posts
+                $mixedWhereSubclause = "`{$this->_sTable}`.`system`='1'";
+
+                //--- Select Public (Direct) posts created on Home Page Timeline (Public Feed) 
+                $mixedWhereSubclause .= $this->prepareAsString(" OR `{$this->_sTable}`.`owner_id`=?", 0);
+
+                //--- Select Promoted posts.
+                $mixedWhereSubclause .= " OR `{$this->_sTable}`.`promoted` <> '0'";
+                break;
+
+            //--- Feed: Profile
+            case BX_BASE_MOD_NTFS_TYPE_OWNER:
+                if(empty($aParams['owner_id']))
+                    break;
+
+                //--- Select Own (System and Direct) posts from Profile's Timeline.
+                $mixedWhereSubclause = $this->prepareAsString("(`{$this->_sTable}`.`owner_id` = ?)", $aParams['owner_id']);
+
+                //--- Select Own Public (Direct) posts from Home Page Timeline (Public Feed).
+                $mixedWhereSubclause .= $this->prepareAsString(" OR (`{$this->_sTable}`.`owner_id` = '0' AND IF(`{$this->_sTable}`.`system`='0', `{$this->_sTable}`.`object_id` = ?, 1))", $aParams['owner_id']);
+                break;
+
+            //--- Feed: All Profile Connections 
+            case BX_BASE_MOD_NTFS_TYPE_CONNECTIONS:
+                if(empty($aParams['owner_id']))
+                    break;
+
+                $mixedJoinClause = array();
+                $mixedWhereSubclause = array();
+
+                $oConnection = BxDolConnection::getObjectInstance($this->_oConfig->getObject('conn_subscriptions'));
+
+                //--- Join System and Direct posts received by and made by following members. 'LEFT' join is essential to apply different conditions.
+                $aQueryParts = $oConnection->getConnectedContentAsSQLPartsExt($this->_sPrefix . 'events', 'owner_id', $aParams['owner_id']);
+                $aJoin1 = $aQueryParts['join'];
+
+                $mixedJoinClause['p1'] = "LEFT JOIN `" . $aJoin1['table'] . "` AS `" . $aJoin1['table_alias'] . "` ON " . $aJoin1['condition'];
+                $mixedWhereSubclause['p1'] = "NOT ISNULL(`" . $aJoin1['table_alias'] . "`.`content`)";
+
+                //--- Exclude Own (Direct) posts on timelines of following members.
+                //--- Note. Disabled for now.
+                //$mixedWhereSubclause['p1'] .= $this->prepareAsString(" AND IF(`{$this->_sTable}`.`system`='0', `{$this->_sTable}`.`object_id` <> ?, 1)", $aParams['owner_id']);
+
+                $aQueryParts = $oConnection->getConnectedContentAsSQLPartsExt($this->_sPrefix . 'events', 'object_id', $aParams['owner_id']);
+                $aJoin2 = $aQueryParts['join'];
+
+                $aQueryParts = $oConnection->getConnectedContentAsSQLPartsExt($this->_sPrefix . 'events', 'object_id', $aParams['owner_id']);
+                $aJoin2 = $aQueryParts['join'];
+                $aJoin2['table_alias'] = 'cc';
+                $aJoin2['condition'] = str_replace('`c`', '`' . $aJoin2['table_alias'] . '`', $aJoin2['condition']);
+
+                $mixedJoinClause['p2'] = "LEFT JOIN `" . $aJoin2['table'] . "` AS `" . $aJoin2['table_alias'] . "` ON `" . $this->_sTable . "`.`system`='0' AND " . $aJoin2['condition'];
+                $mixedWhereSubclause['p2'] = "NOT ISNULL(`" . $aJoin2['table_alias'] . "`.`content`)";
+
+                //--- Select Promoted posts.
+                $mixedWhereSubclause['p3'] = "`{$this->_sTable}`.`promoted` <> '0'";
+                break;
+
+            //--- Feed: Profile Connections to Channel contexts only
+            case BX_TIMELINE_TYPE_CHANNELS:
+                if(empty($aParams['owner_id']))
+                    break;
+
+                $mixedJoinClause = array();
+                $mixedWhereSubclause = array();
+
+                $oConnection = BxDolConnection::getObjectInstance($this->_oConfig->getObject('conn_subscriptions'));
+
+                //--- Join System posts received by following channels.
+                $aQueryParts = $oConnection->getConnectedContentAsSQLPartsExt($this->_sPrefix . 'events', 'owner_id', $aParams['owner_id']);
+                $aJoin1 = $aQueryParts['join'];
+
+                $mixedJoinClause['p1'] = "LEFT JOIN `" . $aJoin1['table'] . "` AS `" . $aJoin1['table_alias'] . "` ON " . $aJoin1['condition'];
+                $mixedWhereSubclause['p1'] = "`{$this->_sTable}`.`type`='bx_channels' AND NOT ISNULL(`" . $aJoin1['table_alias'] . "`.`content`)";
+
+                //--- Exclude Own (Direct) posts on timelines of following members.
+                //--- Note. Disabled for now.
+                //$mixedWhereSubclause['p1'] = $this->prepareAsString(" AND IF(`{$this->_sTable}`.`system`='0', `{$this->_sTable}`.`object_id` <> ?, 1)", $aParams['owner_id']);
+
+                //--- Select Promoted posts.
+                $mixedWhereSubclause['p2'] = "`{$this->_sTable}`.`promoted` <> '0'";
+                break;
+
+            //--- Feed: Profile + Profile Connections to Non-Channel contexts
+            case BX_TIMELINE_TYPE_FEED:
+                if(empty($aParams['owner_id']))
+                    break;
+
+                $mixedJoinClause = array();
+                $mixedWhereSubclause = array();
+
+                $oConnection = BxDolConnection::getObjectInstance($this->_oConfig->getObject('conn_subscriptions'));
+
+                //--- Select Own (System and Direct) posts from Profile's Timeline.
+                $sWhereSubclauseOwnProfile = $this->prepareAsString("(`{$this->_sTable}`.`owner_id` = ?)", $aParams['owner_id']);
+
+                //--- Select Own Public (Direct) posts from Home Page Timeline (Public Feed).
+                $sWhereSubclauseOwnPublic = $this->prepareAsString("(`{$this->_sTable}`.`owner_id` = '0' AND IF(`{$this->_sTable}`.`system`='0', `{$this->_sTable}`.`object_id` = ?, 1))", $aParams['owner_id']);
+
+                $mixedWhereSubclause['p1'] = "(" . $sWhereSubclauseOwnProfile . " OR " . $sWhereSubclauseOwnPublic . ")";
+
+                //--- Join System and Direct posts received by and made by following members. 'LEFT' join is essential to apply different conditions.
+                $aQueryParts = $oConnection->getConnectedContentAsSQLPartsExt($this->_sPrefix . 'events', 'owner_id', $aParams['owner_id']);
+                $aJoin1 = $aQueryParts['join'];
+
+                $mixedJoinClause['p2'] = "LEFT JOIN `" . $aJoin1['table'] . "` AS `" . $aJoin1['table_alias'] . "` ON " . $aJoin1['condition'];
+                $mixedWhereSubclause['p2'] = "`{$this->_sTable}`.`type`<>'bx_channels' AND NOT ISNULL(`" . $aJoin1['table_alias'] . "`.`content`)";
+                
+                //--- Exclude Own (Direct) posts on timelines of following members.
+                //--- Note. Disabled for now and next check is used instead. 
+                //$mixedWhereSubclause['p2'] = $this->prepareAsString(" AND IF(`{$this->_sTable}`.`system`='0', `{$this->_sTable}`.`object_id` <> ?, 1))", $aParams['owner_id']);
+
+                $aQueryParts = $oConnection->getConnectedContentAsSQLPartsExt($this->_sPrefix . 'events', 'object_owner_id', $aParams['owner_id']);
+                $aJoin2 = $aQueryParts['join'];
+                $aJoin2['table_alias'] = 'cc';
+                $aJoin2['condition'] = str_replace('`c`', '`' . $aJoin2['table_alias'] . '`', $aJoin2['condition']);
+
+                $mixedJoinClause['p3'] = "LEFT JOIN `" . $aJoin2['table'] . "` AS `" . $aJoin2['table_alias'] . "` ON `" . $this->_sTable . "`.`system` = 0 AND `" . $this->_sTable . "`.`object_privacy_view` > 0 AND " . $aJoin2['condition'];
+                $mixedWhereSubclause['p3'] = "NOT ISNULL(`" . $aJoin2['table_alias'] . "`.`content`)";
+
+                //--- Select Promoted posts.
+                $mixedWhereSubclause['p4'] = "`{$this->_sTable}`.`promoted` <> '0'";
+                break;
+
+            //--- Feed: Profile + All Profile Connections
+            case BX_TIMELINE_TYPE_OWNER_AND_CONNECTIONS:
+                if(empty($aParams['owner_id']))
+                    break;
+
+                $mixedJoinClause = array();
+                $mixedWhereSubclause = array();
+
+                $oConnection = BxDolConnection::getObjectInstance($this->_oConfig->getObject('conn_subscriptions'));
+
+                //--- Select Own (System and Direct) posts from Profile's Timeline.
+                $sWhereSubclauseOwnProfile = $this->prepareAsString("(`{$this->_sTable}`.`owner_id` = ?)", $aParams['owner_id']);
+
+                //--- Select Own Public (Direct) posts from Home Page Timeline (Public Feed).
+                $sWhereSubclauseOwnPublic = $this->prepareAsString("(`{$this->_sTable}`.`owner_id` = '0' AND IF(`{$this->_sTable}`.`system`='0', `{$this->_sTable}`.`object_id` = ?, 1))", $aParams['owner_id']);
+
+                $mixedWhereSubclause['p1'] = "(" . $sWhereSubclauseOwnProfile . " OR " . $sWhereSubclauseOwnPublic . ")";
+
+                //--- Join System and Direct posts received by and made by following members. 'LEFT' join is essential to apply different conditions.
+                $aQueryParts = $oConnection->getConnectedContentAsSQLPartsExt($this->_sPrefix . 'events', 'owner_id', $aParams['owner_id']);
+                $aJoin1 = $aQueryParts['join'];
+
+                $mixedJoinClause['p2'] = "LEFT JOIN `" . $aJoin1['table'] . "` AS `" . $aJoin1['table_alias'] . "` ON " . $aJoin1['condition'];
+                $mixedWhereSubclause['p2'] = "NOT ISNULL(`" . $aJoin1['table_alias'] . "`.`content`)";
+                
+                //--- Exclude Own (Direct) posts on timelines of following members.
+                //--- Note. Disabled for now and next check is used instead. 
+                //$mixedWhereSubclause['p2'] = $this->prepareAsString(" AND IF(`{$this->_sTable}`.`system`='0', `{$this->_sTable}`.`object_id` <> ?, 1))", $aParams['owner_id']);
+
+                $aQueryParts = $oConnection->getConnectedContentAsSQLPartsExt($this->_sPrefix . 'events', 'object_id', $aParams['owner_id']);
+                $aJoin2 = $aQueryParts['join'];
+                $aJoin2['table_alias'] = 'cc';
+                $aJoin2['condition'] = str_replace('`c`', '`' . $aJoin2['table_alias'] . '`', $aJoin2['condition']);
+
+                $mixedJoinClause['p3'] = "LEFT JOIN `" . $aJoin2['table'] . "` AS `" . $aJoin2['table_alias'] . "` ON `" . $this->_sTable . "`.`system`='0' AND " . $aJoin2['condition'];
+                $mixedWhereSubclause['p3'] = "NOT ISNULL(`" . $aJoin2['table_alias'] . "`.`content`)";
+
+                //--- Select Promoted posts.
+                $mixedWhereSubclause['p4'] = "`{$this->_sTable}`.`promoted` <> '0'";
+                break;
+
+            //--- Feed: Profile Connections to contexts from Selected module
+            default:
+                if(empty($aParams['owner_id']))
+                    break;
+
+                $mixedJoinClause = [];
+                $mixedWhereSubclause = [];
+
+                $oConnection = BxDolConnection::getObjectInstance($this->_oConfig->getObject('conn_subscriptions'));
+
+                //--- Join System posts received by following channels.
+                $aQueryParts = $oConnection->getConnectedContentAsSQLPartsExt($this->_sPrefix . 'events', 'owner_id', $aParams['owner_id']);
+                $aJoin1 = $aQueryParts['join'];
+
+                $mixedJoinClause['p1'] = "INNER JOIN `sys_profiles` AS `p` ON `" . $this->_sTable ."`.`owner_id`=`p`.`id` AND `p`.`type`='" . $aParams['type'] . "'";
+                $mixedJoinClause['p1'] .= " LEFT JOIN `" . $aJoin1['table'] . "` AS `" . $aJoin1['table_alias'] . "` ON " . $aJoin1['condition'];
+
+                $mixedWhereSubclause['p1'] = "NOT ISNULL(`" . $aJoin1['table_alias'] . "`.`content`)";
+                if(!empty($aParams['context']))
+                    $mixedWhereSubclause['p1'] .= $this->prepareAsString(" AND `" . $aJoin1['table_alias'] . "`.`content`=?", $aParams['context']);
+
+                //--- Exclude Own (Direct) posts on timelines of following members.
+                //--- Note. Disabled for now.
+                //$mixedWhereSubclause['p1'] = $this->prepareAsString(" AND IF(`{$this->_sTable}`.`system`='0', `{$this->_sTable}`.`object_id` <> ?, 1)", $aParams['owner_id']);
+
+                //--- Select Promoted posts.
+                $mixedWhereSubclause['p2'] = "`" . $this->_sTable . "`.`promoted` <> '0'";
+                break;
+        }
+
+        $aAlertParams = $aParams;
+        unset($aAlertParams['type'], $aAlertParams['owner_id']);
+
+        bx_alert($this->_oConfig->getName(), 'get_list_by_type', 0, 0, array(
+            'type' => $aParams['type'],
+            'owner_id' => $aParams['owner_id'],
+            'params' => $aAlertParams,
+            'table' => $this->_sTable,
+            'join_clause' => &$mixedJoinClause,
+            'where_clause' => &$mixedWhereClause,
+            'where_clause_status' => &$sWhereClauseStatus,
+            'where_clause_filter' => &$sWhereClauseFilter,
+            'where_clause_timeline' => &$sWhereClauseTimeline,
+            'where_clause_modules' => &$sWhereClauseModules,
+            'where_clause_hidden' => &$sWhereClauseHidden,
+            'where_clause_muted' => &$sWhereClauseMuted,
+            'where_clause_unpublished' => &$sWhereClauseUnpublished,
+            'where_clause_cf' => &$sWhereClauseCf,
+            'where_subclause' => &$mixedWhereSubclause
+        ));
+
+        $mixedWhereClause .= $sWhereClauseStatus;
+        $mixedWhereClause .= $sWhereClauseFilter;
+        $mixedWhereClause .= $sWhereClauseTimeline;
+        $mixedWhereClause .= $sWhereClauseModules;
+        $mixedWhereClause .= $sWhereClauseHidden;
+        $mixedWhereClause .= $sWhereClauseMuted;
+        $mixedWhereClause .= $sWhereClauseUnpublished;
+        $mixedWhereClause .= $sWhereClauseCf;
+
+        if(!empty($mixedWhereSubclause)) {
+            if(is_array($mixedWhereSubclause)) {
+                $aWhereClause = array();
+                foreach($mixedWhereSubclause as $sKey => $sValue)
+                    $aWhereClause[$sKey] = $mixedWhereClause . "AND " . $sValue . " ";
+                $mixedWhereClause = $aWhereClause;
+            }
+            else
+                $mixedWhereClause .= "AND (" . $mixedWhereSubclause . ") ";
+        }
+
+        return array($mixedJoinClause, $mixedWhereClause);
+    }
+
+    protected function _isList($aParams)
+    {
+        return in_array($aParams['browse'], ['list', 'ids']) && (!isset($aParams['newest']) || $aParams['newest'] === false);
+    }
+
+    public function getMenuItemMaxOrder($sSetName)
+    {
+        return $this->getOne("SELECT IFNULL(MAX(`order`), 0) FROM `sys_menu_items` WHERE `set_name`=:set_name LIMIT 1", [
+            'set_name' => $sSetName
+        ]);
+    }
+
+    public function getMenuItemId($sSetName, $sName)
+    {
+        return (int)$this->getOne("SELECT `id` FROM `sys_menu_items` WHERE `set_name`=:set_name AND `name`=:name LIMIT 1", [
+            'set_name' => $sSetName,
+            'name' => $sName
+        ]);
+    }
+
+    public function insertMenuItem($sSetName, $sModule, $sName, $sTitle, $iOrder)
+    {
+        return $this->query("INSERT INTO `sys_menu_items` SET " . $this->arrayToSQL([
+            'set_name' => $sSetName, 
+            'module' => $sModule, 
+            'name' => $sName, 
+            'title_system' => $sTitle,
+            'title' => $sTitle,
+            'link' => 'javascript:void(0)', 
+            'onclick' => "javascript:{js_object_view}.changeFeed(this, '" . $sModule . "')", 
+            'target' => '_self',
+            'collapsed' => 1,
+            'order' => $iOrder
+        ]));
+    }
+    
+    public function deleteMenuItem($sSetName, $sName)
+    {
+        return $this->query("DELETE FROM `sys_menu_items` WHERE `set_name`=:set_name AND `name`=:name LIMIT 1", [
+            'set_name' => $sSetName,
+            'name' => $sName
+        ]);
+    }
+}
+
+/** @} */

+ 397 - 0
modules/boonex/timeline/updates/13.0.4_13.0.5/source/classes/BxTimelineFormPost.php

@@ -0,0 +1,397 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Timeline Timeline
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+/**
+ * Create/Edit entry form
+ */
+class BxTimelineFormPost extends BxBaseModGeneralFormEntry
+{
+    protected $_bAccountMode;
+    protected $_bPublicMode;
+    protected $_bProfileMode;
+
+    protected $_bVisibilityAutoselect;
+
+    protected $_aUploadersInfo;
+
+    public function __construct($aInfo, $oTemplate = false)
+    {
+        $this->MODULE = 'bx_timeline';
+
+        parent::__construct($aInfo, $oTemplate);
+
+        $this->_sGhostTemplate = 'uploader_nfw.html';
+
+        $this->_bAccountMode = isset($this->aParams['display']) && $this->aParams['display'] == $this->_oModule->_oConfig->getObject('form_display_post_add');
+        $this->_bPublicMode = isset($this->aParams['display']) && $this->aParams['display'] == $this->_oModule->_oConfig->getObject('form_display_post_add_public');
+        $this->_bProfileMode = isset($this->aParams['display']) && $this->aParams['display'] == $this->_oModule->_oConfig->getObject('form_display_post_add_profile');
+
+        $this->_bVisibilityAutoselect = true;
+
+        $this->_aUploadersInfo = array();
+    }
+
+    public function getUploadersInfo($sField = '')
+    {
+        if(empty($sField))
+            return $this->_aUploadersInfo;
+
+        $aUploaders = !empty($this->aInputs[$sField]['value']) ? unserialize($this->aInputs[$sField]['value']) : $this->_oModule->_oConfig->getUploaders($sField);
+
+        return $this->_aUploadersInfo[array_shift($aUploaders)];
+    }
+
+    public function initChecker($aValues = array (), $aSpecificValues = array())
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+        
+        $iUserId = $this->_oModule->getUserId();
+        $bValueId = $aValues && !empty($aValues['id']);
+        $iValueId = $bValueId ? (int)$aValues['id'] : 0;
+
+        if(isset($this->aInputs[$CNF['FIELD_ATTACHMENTS']]) && ($oMenu = $this->_oModule->getAttachmentsMenuObject()) !== false) {
+            $oMenu->setEventById($iValueId);
+            $oMenu->setUploadersInfo($this->_aUploadersInfo);
+
+            $this->aInputs['attachments']['content'] = $oMenu->getCode();
+        }
+
+        if(isset($this->aInputs[$CNF['FIELD_LINK']]))
+            $this->aInputs[$CNF['FIELD_LINK']]['content'] = $this->_oModule->_oTemplate->getAttachLinkField($iUserId, $iValueId);
+
+        foreach(['FIELD_VIDEO', 'FIELD_FILE'] as $sSetting){
+            if(!isset($CNF[$sSetting]) || !isset($this->aInputs[$CNF[$sSetting]])) 
+                continue;
+
+            $aContentInfo = false;
+            if($bValueId) {
+                $aContentInfo = $this->_oModule->_oDb->getContentInfoById ($iValueId);
+                $this->aInputs[$CNF[$sSetting]]['content_id'] = $iValueId;
+            }
+
+            $this->aInputs[$CNF[$sSetting]]['ghost_template'] = $this->_oModule->_oTemplate->parseHtmlByName($this->_sGhostTemplate, $this->_getGhostTmplVars($CNF[$sSetting], $aContentInfo));
+        }
+
+        if($this->aParams['display'] == $this->_oModule->_oConfig->getObject('form_display_post_edit') && isset($CNF['FIELD_PUBLISHED']) && isset($this->aInputs[$CNF['FIELD_PUBLISHED']]))
+            if(isset($aValues[$CNF['FIELD_STATUS']]) && in_array($aValues[$CNF['FIELD_STATUS']], array(BX_TIMELINE_STATUS_ACTIVE, BX_TIMELINE_STATUS_HIDDEN)))
+                unset($this->aInputs[$CNF['FIELD_PUBLISHED']]);
+
+        if(isset($CNF['FIELD_ANONYMOUS']) && isset($this->aInputs[$CNF['FIELD_ANONYMOUS']]) && isset($aValues[$CNF['FIELD_OBJECT_ID']]))
+            $this->aInputs[$CNF['FIELD_ANONYMOUS']]['checked'] = $aValues[$CNF['FIELD_OBJECT_ID']] < 0;
+
+        parent::initChecker ($aValues, $aSpecificValues);
+    }
+
+    public function insert($aValsToAdd = array(), $isIgnore = false)
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        $aValsToAdd[$CNF['FIELD_SYSTEM']] = 0;
+        $aValsToAdd[$CNF['FIELD_OBJECT_ID']] *= isset($CNF['FIELD_ANONYMOUS']) && isset($this->aInputs[$CNF['FIELD_ANONYMOUS']]) && $this->getCleanValue($CNF['FIELD_ANONYMOUS']) ? -1 : 1;
+
+        if(isset($CNF['FIELD_ADDED']) && empty($aValsToAdd[$CNF['FIELD_ADDED']])) {
+            $iAdded = 0;
+            if(isset($this->aInputs[$CNF['FIELD_ADDED']]))
+                $iAdded = $this->getCleanValue($CNF['FIELD_ADDED']);
+            
+            if(empty($iAdded))
+                 $iAdded = time();
+
+            $aValsToAdd[$CNF['FIELD_ADDED']] = $iAdded;
+            if(isset($CNF['FIELD_REACTED']))
+                $aValsToAdd[$CNF['FIELD_REACTED']] = $iAdded;
+        }
+
+        if(empty($aValsToAdd[$CNF['FIELD_PUBLISHED']])) {
+            $iPublished = 0;
+            if(isset($this->aInputs[$CNF['FIELD_PUBLISHED']]))
+                $iPublished = $this->getCleanValue($CNF['FIELD_PUBLISHED']);
+                
+             if(empty($iPublished))
+                 $iPublished = time();
+
+             $aValsToAdd[$CNF['FIELD_PUBLISHED']] = $iPublished;
+        }
+
+        $aValsToAdd[$CNF['FIELD_STATUS']] = $aValsToAdd[$CNF['FIELD_PUBLISHED']] > $aValsToAdd[$CNF['FIELD_ADDED']] ? BX_TIMELINE_STATUS_AWAITING : BX_TIMELINE_STATUS_ACTIVE;
+
+        return parent::insert ($aValsToAdd, $isIgnore);
+    }
+
+    function update($iContentId, $aValsToAdd = array(), &$aTrackTextFieldsChanges = null)
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        if (isset($CNF['FIELD_ANONYMOUS']) && isset($this->aInputs[$CNF['FIELD_ANONYMOUS']])) {
+            $aContentInfo = $this->_oModule->_oDb->getContentInfoById($iContentId);
+
+            $aValsToAdd[$CNF['FIELD_OBJECT_ID']] = ($this->getCleanValue($CNF['FIELD_ANONYMOUS']) ? -1 : 1) * abs($aContentInfo[$CNF['FIELD_OBJECT_ID']]);
+        }
+
+        if(empty($aValsToAdd[$CNF['FIELD_PUBLISHED']]) && isset($this->aInputs[$CNF['FIELD_PUBLISHED']])) {
+            $iPublished = $this->getCleanValue($CNF['FIELD_PUBLISHED']);
+            if(empty($iPublished))
+                $iPublished = time();
+
+            $aValsToAdd[$CNF['FIELD_PUBLISHED']] = $iPublished;
+        }
+
+        return parent::update($iContentId, $aValsToAdd, $aTrackTextFieldsChanges);
+    }
+
+    public function addHtmlEditor($iViewMode, &$aInput, $sUniq)
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        $oEditor = BxDolEditor::getObjectInstance(false, $this->oTemplate);
+        if (!$oEditor)
+            return false;
+
+        if(in_array($this->aParams['display'], array($this->_oModule->_oConfig->getObject('form_display_post_add'), $this->_oModule->_oConfig->getObject('form_display_post_add_public'))))
+            $oEditor->setCustomConf("
+                placeholderText: '" . _t('_bx_timeline_txt_some_text_here') . "',
+                initOnClick: false,
+            ");
+
+        if(!$this->_oModule->_oConfig->isEditorToolbar())
+        	$oEditor->setCustomToolbarButtons('');
+
+        $this->_sCodeAdd .= $oEditor->attachEditor ('#' . $this->aFormAttrs['id'] . ' [name=' . $aInput['name'] . ']', $iViewMode, $this->_bDynamicMode, ['form_id' => $this->aFormAttrs['id'], 'element_name' => $aInput['name'], 'query_params' => $this->getHtmlEditorQueryParams($aInput), 'uniq' => $sUniq]);
+
+        return true;
+    }
+
+    public function init()
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        $iUserId = $this->_oModule->getUserId();
+        $iOwnerId = $this->_oModule->getOwnerId();
+
+        $this->aFormAttrs['action'] = BX_DOL_URL_ROOT . $this->_oModule->_oConfig->getBaseUri() . 'post/';
+
+        $this->aInputs['owner_id']['value'] = $iOwnerId;
+
+        if(isset($this->aInputs['text'])) {
+            if(empty($this->aInputs['text']['attrs']) || !is_array($this->aInputs['text']['attrs']))
+                $this->aInputs['text']['attrs'] = array();
+
+            $this->aInputs['text']['attrs']['id'] = $this->_oModule->_oConfig->getHtmlIds('post', 'textarea') . time();
+        }
+
+        $aPrivacyFields = $this->_getPrivacyFields();
+        foreach($aPrivacyFields as $sField => $sPrivacyObject)
+            $this->_initPrivacyField($sField, $sPrivacyObject);
+
+        if(isset($this->aInputs[$CNF['FIELD_PHOTO']])) {
+            $sStorage = $this->_oModule->_oConfig->getObject('storage_photos');
+            $sUploadersId = genRndPwd(8, false);
+            $aUploaders = !empty($this->aInputs[$CNF['FIELD_PHOTO']]['value']) ? unserialize($this->aInputs[$CNF['FIELD_PHOTO']]['value']) : $this->_oModule->_oConfig->getUploaders($CNF['FIELD_PHOTO']);
+
+            foreach($aUploaders as $sUploader)
+                $this->_aUploadersInfo[$sUploader] = array(
+                    'id' => $sUploadersId, 
+                    'name' => $sUploader,
+                    'js_object' => BxDolUploader::getObjectInstance($sUploader, $sStorage, $sUploadersId)->getNameJsInstanceUploader()
+                );
+
+            $this->aInputs[$CNF['FIELD_PHOTO']]['storage_object'] = $sStorage;
+            $this->aInputs[$CNF['FIELD_PHOTO']]['images_transcoder'] = $this->_oModule->_oConfig->getObject('transcoder_photos_preview');
+            $this->aInputs[$CNF['FIELD_PHOTO']]['uploaders_id'] = $sUploadersId;
+            $this->aInputs[$CNF['FIELD_PHOTO']]['uploaders'] = $aUploaders;
+            $this->aInputs[$CNF['FIELD_PHOTO']]['upload_buttons_titles'] = array('Simple' => 'camera');
+            $this->aInputs[$CNF['FIELD_PHOTO']]['multiple'] = true;
+            $this->aInputs[$CNF['FIELD_PHOTO']]['content_id'] = 0;
+            $this->aInputs[$CNF['FIELD_PHOTO']]['ghost_template'] = '';
+        }
+
+        if(isset($this->aInputs[$CNF['FIELD_VIDEO']])) {
+            $sStorage = $this->_oModule->_oConfig->getObject('storage_videos');
+            $sUploadersId = genRndPwd(8, false);
+            $aUploaders = !empty($this->aInputs[$CNF['FIELD_VIDEO']]['value']) ? unserialize($this->aInputs[$CNF['FIELD_VIDEO']]['value']) : $this->_oModule->_oConfig->getUploaders($CNF['FIELD_VIDEO']);
+
+            foreach($aUploaders as $sUploader)
+                $this->_aUploadersInfo[$sUploader] = array(
+                    'id' => $sUploadersId,
+                    'name' => $sUploader,
+                    'js_object' => BxDolUploader::getObjectInstance($sUploader, $sStorage, $sUploadersId)->getNameJsInstanceUploader()
+                );
+
+            $this->aInputs[$CNF['FIELD_VIDEO']]['storage_object'] = $sStorage;
+            $this->aInputs[$CNF['FIELD_VIDEO']]['images_transcoder'] = $this->_oModule->_oConfig->getObject('transcoder_videos_preview');
+            $this->aInputs[$CNF['FIELD_VIDEO']]['uploaders_id'] = $sUploadersId;
+            $this->aInputs[$CNF['FIELD_VIDEO']]['uploaders'] = $aUploaders;
+            $this->aInputs[$CNF['FIELD_VIDEO']]['upload_buttons_titles'] = array('Simple' => 'video');
+            $this->aInputs[$CNF['FIELD_VIDEO']]['multiple'] = true;
+            $this->aInputs[$CNF['FIELD_VIDEO']]['content_id'] = 0;
+            $this->aInputs[$CNF['FIELD_VIDEO']]['ghost_template'] = '';
+        }
+        
+        if(isset($this->aInputs[$CNF['FIELD_FILE']])) {
+            $sStorage = $this->_oModule->_oConfig->getObject('storage_files');
+            $sUploadersId = genRndPwd(8, false);
+            $aUploaders = !empty($this->aInputs[$CNF['FIELD_FILE']]['value']) ? unserialize($this->aInputs[$CNF['FIELD_FILE']]['value']) : $this->_oModule->_oConfig->getUploaders($CNF['FIELD_FILE']);
+          
+            foreach($aUploaders as $sUploader){
+                $this->_aUploadersInfo[$sUploader] = array(
+                    'id' => $sUploadersId,
+                    'name' => $sUploader,
+                    'js_object' => BxDolUploader::getObjectInstance($sUploader, $sStorage, $sUploadersId)->getNameJsInstanceUploader()
+                );
+            }
+            
+            $this->aInputs[$CNF['FIELD_FILE']]['storage_object'] = $sStorage;
+            $this->aInputs[$CNF['FIELD_FILE']]['images_transcoder'] = '';
+            $this->aInputs[$CNF['FIELD_FILE']]['uploaders_id'] = $sUploadersId;
+            $this->aInputs[$CNF['FIELD_FILE']]['uploaders'] = $aUploaders;
+            $this->aInputs[$CNF['FIELD_FILE']]['upload_buttons_titles'] = array('Simple' => 'file');
+            $this->aInputs[$CNF['FIELD_FILE']]['multiple'] = true;
+            $this->aInputs[$CNF['FIELD_FILE']]['content_id'] = 0;
+            $this->aInputs[$CNF['FIELD_FILE']]['ghost_template'] = '';
+        }
+
+        if (isset($this->_oModule->_oConfig->CNF['FIELD_LOCATION_PREFIX']) && isset($this->aInputs[$this->_oModule->_oConfig->CNF['FIELD_LOCATION_PREFIX']]))
+            $this->aInputs[$this->_oModule->_oConfig->CNF['FIELD_LOCATION_PREFIX']]['manual_input'] = false;
+    }
+
+    public function setVisibilityAutoselect($bVisibilityAutoselect)
+    {
+        $this->_bVisibilityAutoselect = $bVisibilityAutoselect;
+    }
+
+    protected function genCustomRowObjectCf(&$aInput)
+    {
+        return parent::genCustomRowCf($aInput);
+    }
+
+    protected function _getPrivacyFields($aKeysF2O = array())
+    {
+        if(empty($aKeysF2O))
+            $aKeysF2O = array(
+                'FIELD_OBJECT_PRIVACY_VIEW' => 'OBJECT_PRIVACY_VIEW'
+            );
+
+        return parent::_getPrivacyFields($aKeysF2O);
+    }
+
+    /**
+     * The method inherited from BxBaseModGeneralFormEntry class is disabled
+     * because own variant (method BxTimelineFormPost::_initPrivacyField) is
+     * used instead.
+     */
+    protected function _preparePrivacyField($sField, $sPrivacyObject)
+    {
+        return;
+    }
+
+    protected function _initPrivacyField($sField, $sPrivacyObject)
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+    	$iUserId = $this->_oModule->getUserId();
+        $iOwnerId = $this->_oModule->getOwnerId();
+
+        $this->aInputs[$sField] = array_merge($this->aInputs[$sField], BxDolPrivacy::getGroupChooser($sPrivacyObject, 0, array(
+            'object' => $this->aParams['object'],
+            'display' => $this->aParams['display'],
+            'title' => _t($CNF['T']['form_input_title_' . $sField]),
+            'dynamic_mode' => $this->_bDynamicMode
+        )));
+
+        //--- Show field as is when 'Autoselect' is disabled.
+        if(!$this->_bVisibilityAutoselect)
+            return;
+
+        //--- Show default privacy groups and followed contexts on Account (Profile + Connections) post form.
+        if($this->_bAccountMode)
+            return;
+
+        //--- Preselect Context and hide privacy selector when posting in some context (profile, group, space, etc).
+        if($this->_bProfileMode && $iOwnerId != $iUserId) {
+            $this->aInputs[$sField]['type'] = 'hidden';
+	    $this->aInputs[$sField]['value'] = -$iOwnerId;
+
+            return;
+        }
+
+        $bProfileModeOwner = $this->_bProfileMode && $iOwnerId == $iUserId;
+        if($this->_bPublicMode || $bProfileModeOwner) {
+            $iGc = 0;
+            $iKeyGh = false;
+            foreach($this->aInputs[$sField]['values'] as $iKey => $aValue) {
+                if(isset($aValue['type']) && in_array($aValue['type'], array('group_header', 'group_end'))) {
+                    if($iKeyGh !== false && $iGc == 0) {
+                        unset($this->aInputs[$sField]['values'][$iKeyGh]);
+                        $iKeyGh = false;
+
+                        if($aValue['type'] == 'group_end')
+                            unset($this->aInputs[$sField]['values'][$iKey]);
+                    }
+
+                    if($aValue['type'] == 'group_header') {
+                        $iGc = 0;
+                        $iKeyGh = $iKey;
+                    }
+
+                    continue;
+                }
+
+                //--- Show 'Public' privacy group only in Public post form. 
+                if($this->_bPublicMode && $aValue['key'] == BX_DOL_PG_ALL) {
+                    $iGc += 1;
+                    continue;
+                }
+
+                //--- Show a default privacy groups in Profile (for Owner) post form.
+                if($bProfileModeOwner && (int)$aValue['key'] >= 0) {
+                    $iGc += 1;
+                    continue;
+                }
+
+                unset($this->aInputs[$sField]['values'][$iKey]);
+            }
+        }
+    }
+    
+    protected function _preloadPrivacyField($sField, $sPrivacyObject, $aValues)
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        $oPrivacy = BxDolPrivacy::getObjectInstance($sPrivacyObject);
+        if(!$oPrivacy) 
+            return;
+
+        $iContentId = !empty($aValues[$CNF['FIELD_ID']]) ? (int)$aValues[$CNF['FIELD_ID']] : 0;
+        $iProfileId = !empty($iContentId) ? (int)$this->getContentOwnerProfileId($iContentId) : bx_get_logged_profile_id();
+        $iGroupId = !empty($aValues[$sField]) ? $aValues[$sField] : 0;
+
+        if(!isset($this->aInputs[$sField]['content']))
+            $this->aInputs[$sField]['content'] = '';
+
+        $this->aInputs[$sField]['content'] .= $oPrivacy->initGroupChooser($sPrivacyObject, $iProfileId, array(
+            'content_id' => $iContentId,
+            'group_id' => $iGroupId,
+            'html_ids' => array(
+                'form' => $this->getId()
+            )
+        ));
+    }
+
+    protected function _getGhostTmplVars($sName, $aContentInfo = array())
+    {
+    	return array (
+            'name' => $this->aInputs[$sName]['name'],
+            'content_id' => (int)$this->aInputs[$sName]['content_id'],
+        );
+    }
+}
+
+/** @} */

+ 82 - 0
modules/boonex/timeline/updates/13.0.4_13.0.5/source/classes/BxTimelineGridCommon.php

@@ -0,0 +1,82 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Timeline Timeline
+ * @ingroup     UnaModules
+ * 
+ * @{
+ */
+
+require_once('BxTimelineGridManageTools.php');
+
+class BxTimelineGridCommon extends BxTimelineGridManageTools
+{
+    public function __construct ($aOptions, $oTemplate = false)
+    {
+    	$this->MODULE = 'bx_timeline';
+        parent::__construct ($aOptions, $oTemplate);
+
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        $this->_sStatusField = $CNF['FIELD_STATUS'];
+        $this->_aStatusValues = array('active', 'hidden');
+
+        $this->_sManageType = BX_DOL_MANAGE_TOOLS_COMMON;
+    }
+
+    protected function _enable ($mixedId, $isChecked)
+    {
+        $bResult = parent::_enable($mixedId, $isChecked);
+        if(!$bResult) 
+            return $bResult;
+        
+        $aEvent = $this->_oModule->_oDb->getEvents(['browse' => 'id', 'value' => (int)$mixedId]);
+        if(empty($aEvent) || !is_array($aEvent))
+            return $bResult;
+
+        $this->_oModule->{$isChecked ? 'onUnhide' : 'onHide'}($aEvent);
+
+        return $bResult;
+    }
+
+    protected function _getCellSwitcher ($mixedValue, $sKey, $aField, $aRow)
+    {
+        if(!$this->_switcherState2Checked($aRow['status_admin']))
+            return parent::_getCellDefault('', $sKey, $aField, $aRow);
+
+        return parent::_getCellSwitcher ($mixedValue, $sKey, $aField, $aRow);
+    }
+
+    protected function _getCellStatusAdmin($mixedValue, $sKey, $aField, $aRow)
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        if(!empty($CNF['T']['filter_item_' . $mixedValue]))
+            $mixedValue = $CNF['T']['filter_item_' . $mixedValue];
+        else
+            $mixedValue = '_undefined';
+
+        return parent::_getCellDefault(_t($mixedValue), $sKey, $aField, $aRow);
+    }
+
+    protected function _isRowDisabled($aRow)
+    {
+        if(parent::_isRowDisabled($aRow))
+            return true;
+
+        return !$this->_switcherState2Checked($aRow['status_admin']);
+    }
+
+    protected function _getDataSql($sFilter, $sOrderField, $sOrderDir, $iStart, $iPerPage)
+    {
+        $iProfileId = bx_get_logged_profile_id();
+
+        $this->_aOptions['source'] .= $this->_oModule->_oDb->prepareAsString(" AND (`owner_id`=? OR (`system`='0' AND `object_owner_id`=?))", $iProfileId, $iProfileId);
+
+        return parent::_getDataSql($sFilter, $sOrderField, $sOrderDir, $iStart, $iPerPage);
+    }
+}
+
+/** @} */

+ 395 - 0
modules/boonex/timeline/updates/13.0.4_13.0.5/source/classes/BxTimelineMenuItemActions.php

@@ -0,0 +1,395 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Timeline Timeline
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+/**
+ * 'Item' menu.
+ */
+class BxTimelineMenuItemActions extends BxTemplMenuCustom
+{
+    protected static $_sModeActions = 'actions';
+    protected static $_sModeCounters = 'counters';
+
+    protected $_sModule;
+    protected $_oModule;
+
+    protected $_iEvent;
+    protected $_aEvent;
+
+    protected $_sType;
+    protected $_sView;
+
+    protected $_sMode;
+    protected $_bShowTitles;
+    protected $_bShowCounters;
+    protected $_bShowCountersEmpty;
+    protected $_bShowCountersIcons;
+
+    protected $_sTmplNameItem;
+
+    protected $_aItem2CheckFunc;
+
+    public function __construct($aObject, $oTemplate = false)
+    {
+        $this->_sModule = 'bx_timeline';
+        $this->_oModule = BxDolModule::getInstance($this->_sModule);
+
+        parent::__construct($aObject, $this->_oModule->_oTemplate);
+
+        $this->_setBrowseParams();
+
+        $this->_sMode = self::$_sModeActions;
+        $this->_bShowTitles = true;
+        $this->_bShowCounters = false;
+        $this->_bShowCountersEmpty = false;
+        $this->_bShowCountersIcons = true;
+        $this->_sTmplNameItem = 'menu_custom_item_hor.html';
+
+        $this->_aItem2CheckFunc = array(
+            'item-view' => 'isAllowedViewCounter',
+            'item-comment' => 'isAllowedComment',
+            'item-vote' => 'isAllowedVote',
+            'item-reaction' => 'isAllowedReaction',
+            'item-score' => 'isAllowedScore',
+            'item-report' => 'isAllowedReport',
+            'item-mute' => 'isAllowedMute',
+            'item-more' => 'isAllowedMore',
+            'item-pin' => 'isAllowedPin',
+            'item-unpin' => 'isAllowedUnpin',
+            'item-stick' => 'isAllowedStick',
+            'item-unstick' => 'isAllowedUnstick',
+            'item-promote' => 'isAllowedPromote',
+            'item-unpromote' => 'isAllowedUnpromote',
+            'item-edit' => 'isAllowedEdit',
+            'item-delete' => 'isAllowedDelete',
+            'item-notes' => 'isAllowedNotes',
+        );
+    }
+
+    public function setEvent($aEvent, $aBrowseParams = array())
+    {
+        if(empty($aEvent) || !is_array($aEvent))
+            return false;
+
+        $this->_aEvent = $aEvent;
+        $this->_iEvent = (int)$this->_aEvent['id'];
+
+        $sType = $this->_aEvent['type'];
+        $sAction = $this->_aEvent['action'];
+
+        $this->_setBrowseParams($aBrowseParams);
+
+        //--- Comment item
+        $iCommentsObject = 0;
+        $sCommentsSystem = $sCommentsOnclick = '';
+        if(isset($aEvent['comments']) && is_array($aEvent['comments']) && isset($aEvent['comments']['system'])) {
+            $sCommentsSystem = $aEvent['comments']['system'];
+            $iCommentsObject = $aEvent['comments']['object_id'];
+            $sCommentsOnclick = bx_replace_markers("{js_object_view}.commentItem(this, '" . $sCommentsSystem . "', " . $iCommentsObject . ")", $this->_aMarkers);
+        }
+
+        //--- Repost item
+        $iOwnerId = $this->_oModule->getUserId(); //--- in whose timeline the content will be reposted
+        $iObjectId = $this->_oModule->_oConfig->isSystem($sType, $sAction) ? $this->_aEvent['object_id'] : $this->_aEvent['id'];
+        $sRepostOnclick = $this->_oModule->serviceGetRepostJsClick($iOwnerId, $sType, $sAction, $iObjectId);
+
+        $bSystem = $this->_oModule->_oConfig->isSystem($sType, $sAction);
+
+        $this->addMarkers(array(
+            'content_id' => $this->_iEvent,
+
+            'comment_system' => $sCommentsSystem,
+            'comment_object' => $iCommentsObject,
+            'comment_onclick' => $sCommentsOnclick,
+
+            'repost_onclick' => $sRepostOnclick,
+
+            'delete_title' => _t('_bx_timeline_menu_item_title_item_delete_' . ($bSystem || $this->_oModule->_oConfig->isHideUponDelete() ? 'system' : 'common'))
+        ));
+
+        return true;
+    }
+
+    public function setEventById($iEventId, $aBrowseParams = array())
+    {
+    	$aEvent = $this->_oModule->_oDb->getEvents(array('browse' => 'id', 'value' => $iEventId));
+    	if(empty($aEvent) || !is_array($aEvent))
+            return;
+
+    	$aEventData = $this->_oModule->_oTemplate->getDataCached($aEvent);
+    	if($aEventData === false)
+            return;
+
+    	$aEvent['views'] = $aEventData['views'];
+        $aEvent['votes'] = $aEventData['votes'];
+        $aEvent['reactions'] = $aEventData['reactions'];
+        $aEvent['scores'] = $aEventData['scores'];
+        $aEvent['reports'] = $aEventData['reports'];
+        $aEvent['comments'] = $aEventData['comments'];
+
+    	$this->setEvent($aEvent, $aBrowseParams);
+    }
+
+    public function setTemplateNameItem($sName)
+    {
+        $this->_sTmplNameItem = $sName;
+    }
+
+    protected function _setBrowseParams($aBrowseParams = array())
+    {
+        $this->_sType = !empty($aBrowseParams['type']) ? $aBrowseParams['type'] : BX_TIMELINE_TYPE_DEFAULT;
+        $this->_sView = !empty($aBrowseParams['view']) ? $aBrowseParams['view'] : BX_TIMELINE_VIEW_DEFAULT;
+
+        $aMarkers = array();
+        foreach($aBrowseParams as $sKey => $mixedValue)
+            if(!is_array($mixedValue))
+                $aMarkers[$sKey] = $mixedValue;
+
+        $this->addMarkers($aMarkers);
+        $this->addMarkers(array(
+            'js_object_view' => $this->_oModule->_oConfig->getJsObjectView($aBrowseParams)
+        ));
+    }
+
+    protected function _getMenuItemItemView($aItem)
+    {
+        if(!isset($this->_aEvent['views']) || !is_array($this->_aEvent['views']) || !isset($this->_aEvent['views']['system'])) 
+            return false;
+
+        $sViewsSystem = $this->_aEvent['views']['system'];
+        $iViewsObject = $this->_aEvent['views']['object_id'];
+        $aViewsParams = array(
+            'show_do_view_label' => $this->_bShowTitles,
+            'show_counter' => $this->_bShowCounters, 
+            'show_counter_label_icon' => $this->_bShowCountersIcons,
+            'dynamic_mode' => $this->_bDynamicMode
+        );
+
+        switch($this->_sMode) {
+            case self::$_sModeActions:
+                $sViewsMethod = 'getElementInline';
+                break;
+
+            case self::$_sModeCounters:
+                $sViewsMethod = 'getCounter';
+                break;
+        }
+
+        return $this->_oModule->getViewObject($sViewsSystem, $iViewsObject)->$sViewsMethod($aViewsParams);
+    }
+
+    protected function _getMenuItemItemVote($aItem)
+    {
+        if(!isset($this->_aEvent['votes']) || !is_array($this->_aEvent['votes']) || !isset($this->_aEvent['votes']['system'])) 
+            return false;
+
+        $sVotesSystem = $this->_aEvent['votes']['system'];
+        $iVotesObject = $this->_aEvent['votes']['object_id'];
+        $aVotesParams = array(
+            'show_do_vote_label' => $this->_bShowTitles,
+            'show_counter' => $this->_bShowCounters,
+            'show_counter_empty' => $this->_bShowCountersEmpty,
+            'show_counter_label_icon' => $this->_bShowCountersIcons,
+            'dynamic_mode' => $this->_bDynamicMode
+        );
+
+        switch($this->_sMode) {
+            case self::$_sModeActions:
+                $sVotesMethod = 'getElementInline';
+                break;
+
+            case self::$_sModeCounters:
+                $sVotesMethod = 'getCounter';
+                break;
+        }
+
+        return $this->_oModule->getVoteObject($sVotesSystem, $iVotesObject)->$sVotesMethod($aVotesParams);
+    }
+
+    protected function _getMenuItemItemReaction($aItem)
+    {
+        if(!isset($this->_aEvent['reactions']) || !is_array($this->_aEvent['reactions']) || !isset($this->_aEvent['reactions']['system'])) 
+            return false;
+
+        $sReactionsSystem = $this->_aEvent['reactions']['system'];
+        $iReactionsObject = $this->_aEvent['reactions']['object_id'];
+        $aReactionsParams = array(
+            'show_do_vote_label' => $this->_bShowTitles,
+            'show_counter' => $this->_bShowCounters,
+            'show_counter_empty' => $this->_bShowCountersEmpty,
+            'show_counter_style' => 'compound',
+            'show_counter_label_icon' => $this->_bShowCountersIcons,
+            'dynamic_mode' => $this->_bDynamicMode
+        );
+        
+        switch($this->_sMode) {
+            case self::$_sModeActions:
+                $sReactionsMethod = 'getElementInline';
+                break;
+
+            case self::$_sModeCounters:
+                $sReactionsMethod = 'getCounter';
+                break;
+        }
+
+    	return $this->_oModule->getReactionObject($sReactionsSystem, $iReactionsObject)->$sReactionsMethod($aReactionsParams);
+    }
+
+    protected function _getMenuItemItemScore($aItem)
+    {
+        if(!isset($this->_aEvent['scores']) || !is_array($this->_aEvent['scores']) || !isset($this->_aEvent['scores']['system'])) 
+            return false;
+
+        $sScoresSystem = $this->_aEvent['scores']['system'];
+        $iScoresObject = $this->_aEvent['scores']['object_id'];
+        $aScoresParams = array(
+            'show_do_vote_label' => $this->_bShowTitles,
+            'show_counter' => $this->_bShowCounters,
+            'show_counter_empty' => $this->_bShowCountersEmpty,
+            'show_counter_label_icon' => $this->_bShowCountersIcons,
+            'dynamic_mode' => $this->_bDynamicMode
+        );
+
+        switch($this->_sMode) {
+            case self::$_sModeActions:
+                $sScoresMethod = 'getElementInline';
+                break;
+
+            case self::$_sModeCounters:
+                $sScoresMethod = 'getCounter';
+                break;
+        }
+
+        return $this->_oModule->getScoreObject($sScoresSystem, $iScoresObject)->$sScoresMethod($aScoresParams);
+    }
+
+    protected function _getMenuItemItemReport($aItem)
+    {
+        if(!isset($this->_aEvent['reports']) || !is_array($this->_aEvent['reports']) || !isset($this->_aEvent['reports']['system'])) 
+            return false;
+
+        $sReportsSystem = $this->_aEvent['reports']['system'];
+        $iReportsObject = $this->_aEvent['reports']['object_id'];
+        $aReportsParams = array(
+            'show_do_report_label' => $this->_bShowTitles,
+            'show_counter' => $this->_bShowCounters,
+            'dynamic_mode' => $this->_bDynamicMode
+        );
+        
+        switch($this->_sMode) {
+            case self::$_sModeActions:
+                $sReportsMethod = 'getElementInline';
+                break;
+
+            case self::$_sModeCounters:
+                $sReportsMethod = 'getCounter';
+                break;
+        }
+
+        return $this->_oModule->getReportObject($sReportsSystem, $iReportsObject)->$sReportsMethod($aReportsParams);
+    }
+
+    protected function _getMenuItemItemRepost($aItem)
+    {
+        if(!isset($this->_aEvent['reposts'])) 
+            return false;
+
+        $aRepostsParams = array(
+            'show_do_repost_text' => $this->_bShowTitles,
+            'show_counter' => $this->_bShowCounters,
+            'show_counter_label_icon' => $this->_bShowCountersIcons,
+            'dynamic_mode' => $this->_bDynamicMode
+        );
+
+        $sType = $this->_aEvent['type'];
+        $sAction = $this->_aEvent['action'];
+        $iObjectId = $this->_oModule->_oConfig->isSystem($sType, $sAction) ? $this->_aEvent['object_id'] : $this->_aEvent['id'];
+
+        $sMethodName = '';
+        $aMethodParams = [];
+        switch($this->_sMode) {
+            case self::$_sModeActions:
+                $sMethodName = 'serviceGetRepostElementBlock';
+                $aMethodParams = [$this->_aEvent['owner_id'], $sType, $sAction, $iObjectId, $aRepostsParams];
+                break;
+
+            case self::$_sModeCounters:
+                $sMethodName = 'serviceGetRepostCounter';
+                $aMethodParams = [$sType, $sAction, $iObjectId, $aRepostsParams];
+                break;
+        }
+
+        return call_user_func_array([$this->_oModule, $sMethodName], $aMethodParams);
+    }
+
+    protected function _getMenuItemDefault ($aItem)
+    {
+        if(!isset($aItem['class_link']))
+            $aItem['class_link'] = '';
+
+        $aItem['class_link'] = 'bx-menu-item-link' . (!empty($aItem['class_link']) ? ' ' : '') . $aItem['class_link'];
+
+        return parent::_getMenuItemDefault ($aItem);
+    }
+
+    /**
+     * Check if menu items is visible.
+     * @param $a menu item array
+     * @return boolean
+     */
+    protected function _isVisible ($a)
+    {
+        if(!parent::_isVisible($a) || empty($this->_aEvent) || !is_array($this->_aEvent))
+            return false;
+
+        $sCheckFuncName = '';
+        $aCheckFuncParams = array($this->_aEvent);
+        switch ($a['name']) {
+            case 'item-comment':
+                if($this->_sView == BX_TIMELINE_VIEW_ITEM)
+                    return false;
+
+                $sCheckFuncName = $this->_aItem2CheckFunc[$a['name']];
+                break;
+
+            case 'item-pin':
+                if($this->_sType != BX_BASE_MOD_NTFS_TYPE_OWNER)
+                    return false;
+
+                $sCheckFuncName = $this->_aItem2CheckFunc[$a['name']];
+                break;
+
+            case 'item-unpin':
+                if($this->_sType != BX_BASE_MOD_NTFS_TYPE_OWNER)
+                    return false;
+
+                $sCheckFuncName = $this->_aItem2CheckFunc[$a['name']];
+                break;
+        }
+
+        if(empty($sCheckFuncName) && isset($this->_aItem2CheckFunc[$a['name']]))
+            $sCheckFuncName = $this->_aItem2CheckFunc[$a['name']];
+
+        if(!$sCheckFuncName || !method_exists($this->_oModule, $sCheckFuncName))
+            return true;
+
+        return call_user_func_array(array($this->_oModule, $sCheckFuncName), $aCheckFuncParams) === true;
+    }
+    
+    protected function _getTmplContentItem()
+    {
+        if(empty($this->_sTmplNameItem))
+           return parent::_getTmplContentItem();
+
+        return $this->_oModule->_oTemplate->getHtml($this->_sTmplNameItem);
+    }
+}
+
+/** @} */

+ 5467 - 0
modules/boonex/timeline/updates/13.0.4_13.0.5/source/classes/BxTimelineModule.php

@@ -0,0 +1,5467 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Timeline Timeline
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+bx_import('BxDolAcl');
+bx_import('BxBaseModNotificationsModule');
+
+/**
+ * SLTMODE - Silent mode:
+ * It is needed for alert sending module to tell that the alert should be ignored 
+ * with Timeline module completely or partially. Available values: 
+ * 1. disabled (global, value = 0) - all events are registered;
+ * 2. absolute (global, value = 1) - alert isn't registered which means that event won't appear in timelines at all;
+ * 3. absolute (for Timeline only, value = 21) - the same as global absolute.
+ * 4. partial registration might be added in the future versions.
+ * 
+ * @see BxBaseModNotificationsModule and BxTimelineResponse::response - 'silent_mode' parameter in Alerts Extras array.
+ */
+define('BX_TIMELINE_SLTMODE_ABSOLUTE', 21);
+
+define('BX_TIMELINE_NAME_VIEWS_DB', 'views_db'); //--- Dynamic browsing feeds.
+
+define('BX_TIMELINE_TYPE_ITEM', 'view_item');
+define('BX_TIMELINE_TYPE_OWNER_AND_CONNECTIONS', 'owner_and_connections');
+define('BX_TIMELINE_TYPE_CHANNELS', 'channels'); //--- Followed channels only.
+define('BX_TIMELINE_TYPE_FEED', 'feed'); //--- Owner and folloved contexts excluding channels.
+define('BX_TIMELINE_TYPE_HOT', 'hot'); //--- Aggrigated hot content.
+define('BX_TIMELINE_TYPE_DEFAULT', BX_BASE_MOD_NTFS_TYPE_OWNER);
+
+define('BX_TIMELINE_VIEW_ITEM', 'item');
+define('BX_TIMELINE_VIEW_TIMELINE', 'timeline');
+define('BX_TIMELINE_VIEW_OUTLINE', 'outline');
+define('BX_TIMELINE_VIEW_SEARCH', 'search');
+define('BX_TIMELINE_VIEW_DEFAULT', BX_TIMELINE_VIEW_OUTLINE);
+
+define('BX_TIMELINE_FILTER_ALL', 'all');
+define('BX_TIMELINE_FILTER_OWNER', 'owner');
+define('BX_TIMELINE_FILTER_OTHER', 'other');
+define('BX_TIMELINE_FILTER_OTHER_VIEWER', 'other_viewer');
+
+define('BX_TIMELINE_PARSE_TYPE_POST', 'post');
+define('BX_TIMELINE_PARSE_TYPE_REPOST', 'repost');
+define('BX_TIMELINE_PARSE_TYPE_DEFAULT', BX_TIMELINE_PARSE_TYPE_POST);
+
+define('BX_TIMELINE_STATUS_ACTIVE', 'active');
+define('BX_TIMELINE_STATUS_PENDING', 'pending');
+define('BX_TIMELINE_STATUS_AWAITING', 'awaiting');
+define('BX_TIMELINE_STATUS_FAILED', 'failed');
+define('BX_TIMELINE_STATUS_HIDDEN', 'hidden');
+define('BX_TIMELINE_STATUS_DELETED', 'deleted');
+
+//--- Video Auto Play 
+define('BX_TIMELINE_VAP_OFF', 'off');
+define('BX_TIMELINE_VAP_ON_MUTE', 'on_mute');
+define('BX_TIMELINE_VAP_ON', 'on');
+
+//--- Media Layouts
+define('BX_TIMELINE_ML_SINGLE', 'single');
+define('BX_TIMELINE_ML_GALLERY', 'gallery');
+define('BX_TIMELINE_ML_SHOWCASE', 'showcase');
+
+//--- Default Attachments Media Layout
+define('BX_TIMELINE_AML_DEFAULT', BX_TIMELINE_ML_GALLERY);
+
+//--- Hot Feed sources
+define('BX_TIMELINE_HFS_CONTENT', 'content');
+define('BX_TIMELINE_HFS_COMMENT', 'comment');
+define('BX_TIMELINE_HFS_VOTE', 'vote');
+
+class BxTimelineModule extends BxBaseModNotificationsModule implements iBxDolContentInfoService
+{
+    protected $_sJsPostObject;
+    protected $_sJsViewObject;
+    protected $_aPostElements;
+    protected $_sJsOutlineObject;
+
+    protected $_sDividerTemplate;
+    protected $_sBalloonTemplate;
+    protected $_sCmtPostTemplate;
+    protected $_sCmtViewTemplate;
+    protected $_sCmtTemplate;
+
+    /**
+     * Constructor
+     */
+    function __construct($aModule)
+    {
+        parent::__construct($aModule);
+    }
+
+    /**
+     * ACTION METHODS
+     */
+    public function actionGetContexts($iLimit = 20)
+    {
+        $oConnection = BxDolConnection::getObjectInstance('sys_profiles_subscriptions');
+        if(!$oConnection)
+            return echoJson(array());
+
+        $iProfileId = bx_get_logged_profile_id();
+        $aConnected = $oConnection->getConnectedContent($iProfileId);
+
+        $sTerm = bx_get('term');
+        if(!$sTerm)
+            return array_slice($aConnected, 0, $iLimit);
+
+        $aResults = array();
+        $aModules = bx_srv('system', 'get_profiles_modules', array(false), 'TemplServiceProfiles');
+        foreach($aModules as $aModule) {
+            if(!BxDolRequest::serviceExists($aModule['name'], 'act_as_profile'))
+                continue;
+
+            $aContexts = bx_srv($aModule['name'], 'profiles_search', array($sTerm, PHP_INT_MAX));
+            foreach($aContexts as $aContext) {
+                if(!in_array($aContext['value'], $aConnected))
+                    continue;
+
+                $aResults[] = $aContext;
+            }
+        }
+
+        usort($aResults, function($r1, $r2) {
+            return strcmp($r1['label'], $r2['label']);
+        });
+
+        echoJson(array_slice($aResults, 0, $iLimit));
+    }
+
+    public function actionVideo($iEventId, $iVideoId)
+    {
+        $aEvent = $this->_oDb->getEvents(array('browse' => 'id', 'value' => $iEventId));
+        if(empty($aEvent) || !is_array($aEvent))
+            return;
+
+        $aData = $this->_oTemplate->getDataCached($aEvent);
+        if($aData === false || !isset($aData['content']['videos'][$iVideoId]))
+            return;
+
+        $oTemplate = BxDolTemplate::getInstance();
+        $oTemplate->addJs(array(
+            'embedly-player.min.js'
+        ));
+        $oTemplate->setPageNameIndex (BX_PAGE_EMBED);
+        $oTemplate->setPageContent ('page_main_code', $this->_oTemplate->getVideo($aEvent, $aData['content']['videos'][$iVideoId]));
+        $oTemplate->getPageCode();
+    }
+
+    public function actionPost()
+    {
+        $this->_iOwnerId = bx_process_input(bx_get('owner_id'), BX_DATA_INT);
+
+        $mixedAllowed = $this->isAllowedPost(true);
+        if($mixedAllowed !== true)
+            return echoJson(array('message' => strip_tags($mixedAllowed)));
+
+        echoJson($this->getFormPost());
+    }
+
+    public function actionEdit($iId)
+    {
+        $this->_iOwnerId = bx_process_input(bx_get('owner_id'), BX_DATA_INT);
+
+        $aBrowseParams = [];
+        if(bx_get('bp') !== false) {
+            $aBrowseParams = $this->_oConfig->getBrowseParams(bx_process_input(bx_get('bp')));
+            $aBrowseParams = $this->_prepareParamsGet($aBrowseParams);
+        }
+
+        $mixedAllowed = $this->isAllowedPost(true);
+        if($mixedAllowed !== true)
+            return echoJson(array('message' => strip_tags($mixedAllowed)));
+
+        echoJson($this->getFormEdit($iId, array('dynamic_mode' => true), $aBrowseParams));
+    }
+
+    function actionPin()
+    {
+        $iId = bx_process_input(bx_get('id'), BX_DATA_INT);
+        $aEvent = $this->_oDb->getEvents(array('browse' => 'id', 'value' => $iId));
+        if(empty($aEvent) || !is_array($aEvent))
+            return echoJson(array('code' => 1));
+
+        $aParams = $this->_prepareParamsGet();
+        $this->_iOwnerId = $aParams['owner_id'];
+        
+        $mixedAllowed = $this->{'isAllowed' . ((int)$aEvent['pinned'] == 0 ? 'Pin' : 'Unpin')}($aEvent, true);
+        if($mixedAllowed !== true)
+            return echoJson(array('code' => 2, 'message' => strip_tags($mixedAllowed)));
+
+        $aEvent['pinned'] = (int)$aEvent['pinned'] == 0 ? time() : 0;
+        if(!$this->_oDb->updateEvent(array('pinned' => $aEvent['pinned']), array('id' => $iId)))
+            return echoJson(array('code' => 3));
+
+        echoJson(array(
+            'code' => 0, 
+            'id' => $iId, 
+            'eval' => $this->_oConfig->getJsObjectView($aParams) . '.onPinPost(oData)'
+        ));
+    }
+
+    function actionStick()
+    {
+    	$iId = bx_process_input(bx_get('id'), BX_DATA_INT);
+    	$aEvent = $this->_oDb->getEvents(array('browse' => 'id', 'value' => $iId));
+        if(empty($aEvent) || !is_array($aEvent))
+            return echoJson(array('code' => 1));
+
+        $aParams = $this->_prepareParamsGet();
+        $this->_iOwnerId = $aParams['owner_id'];
+
+    	$mixedAllowed = $this->{'isAllowed' . ((int)$aEvent['sticked'] == 0 ? 'Stick' : 'Unstick')}($aEvent, true);
+    	if($mixedAllowed !== true)
+            return echoJson(array('code' => 2, 'message' => strip_tags($mixedAllowed)));
+
+    	$aEvent['sticked'] = (int)$aEvent['sticked'] == 0 ? time() : 0;
+    	if(!$this->_oDb->updateEvent(array('sticked' => $aEvent['sticked']), array('id' => $iId)))
+            return echoJson(array('code' => 3));
+
+        bx_audit(
+            $iId, 
+            $this->getName(), 
+            '_sys_audit_action_' . ((int)$aEvent['sticked'] == 0 ? 'stick' : 'unstick'),  
+            $this->_prepareAuditParams($aEvent, false)
+        );
+        
+    	echoJson(array(
+            'code' => 0,
+            'id' => $iId,
+            'eval' => $this->_oConfig->getJsObjectView($aParams) . '.onStickPost(oData)'
+        ));
+    }
+
+    function actionPromote()
+    {
+        $this->_iOwnerId = bx_process_input(bx_get('owner_id'), BX_DATA_INT);
+
+        $iId = bx_process_input(bx_get('id'), BX_DATA_INT);
+        $aEvent = $this->_oDb->getEvents(array('browse' => 'id', 'value' => $iId));
+
+        $sAction = (int)$aEvent['promoted'] == 0 ? 'promote' : 'unpromote';
+
+        $mixedAllowed = $this->{'isAllowed' . ucfirst($sAction)}($aEvent, true);
+        if($mixedAllowed !== true)
+            return echoJson(array('code' => 1, 'message' => strip_tags($mixedAllowed)));
+
+        $aEvent['promoted'] = (int)$aEvent['promoted'] == 0 ? time() : 0;
+        if(!$this->_oDb->updateEvent(array('promoted' => $aEvent['promoted']), array('id' => $iId)))
+            return echoJson(array('code' => 2));
+
+        bx_alert($this->_oConfig->getObject('alert'), $sAction . 'd', $iId, (int)$this->getUserId(), array(
+            'owner_id' => $aEvent['owner_id'],
+            'object_id' => $aEvent['object_id'],
+            'object_author_id' => $this->_oConfig->isSystem($aEvent['type'], $aEvent['action']) ? $aEvent['owner_id'] : $aEvent['object_id']
+        ));
+        
+        bx_audit(
+            $iId, 
+            $this->getName(), 
+            '_sys_audit_action_' . ((int)$aEvent['promoted'] == 0 ? 'promote' : 'unpromote'),  
+            $this->_prepareAuditParams($aEvent, false)
+        );
+
+        echoJson(array(
+            'code' => 0, 
+            'message' => _t('_bx_timeline_txt_msg_performed_action')
+        ));
+    }
+
+    function actionMarkAsRead()
+    {
+        $iId = bx_process_input(bx_get('id'), BX_DATA_INT);
+        $aEvent = $this->_oDb->getEvents(['browse' => 'id', 'value' => $iId]);
+        if(empty($aEvent) || !is_array($aEvent))
+            return echoJson(['code' => 1]);
+
+        $aParams = $this->_prepareParamsGet();
+        if(!$this->_oDb->markAsRead($aParams['viewer_id'], $iId))
+            return echoJson(['code' => 2]);
+
+        echoJson([
+            'code' => 0, 
+            'id' => $iId
+        ]);
+    }
+
+    function actionMute()
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $this->_iOwnerId = bx_process_input(bx_get('owner_id'), BX_DATA_INT);
+
+        $iId = bx_process_input(bx_get('id'), BX_DATA_INT);
+        $aEvent = $this->_oDb->getEvents(array('browse' => 'id', 'value' => $iId));
+
+        $mixedAllowed = $this->isAllowedMute($aEvent, true);
+        if($mixedAllowed !== true)
+            return echoJson(array('code' => 1, 'message' => strip_tags($mixedAllowed)));
+
+        $iAuthor = (int)$aEvent[$CNF['FIELD_OWNER_ID']];
+        if(!$this->_oConfig->isSystem($aEvent['type'], $aEvent['action']))
+            $iAuthor = (int)$aEvent[$CNF['FIELD_OBJECT_ID']];
+
+        if(!$this->getConnectionMuteObject()->addConnection($this->_iProfileId, $iAuthor))
+            return echoJson(array('code' => 2));
+
+        bx_alert($this->_oConfig->getObject('alert'), 'muted', $iAuthor, $this->_iProfileId, array(
+            'owner_id' => $aEvent['owner_id'],
+            'object_id' => $aEvent['object_id'],
+            'object_author_id' => $this->_oConfig->isSystem($aEvent['type'], $aEvent['action']) ? $aEvent['owner_id'] : $aEvent['object_id']
+        ));
+
+        echoJson(array('code' => 0, 'message' => _t('_bx_timeline_txt_msg_performed_action'), 'reload' => 1));
+    }
+
+    function actionDelete()
+    {
+        $iId = bx_process_input(bx_get('id'), BX_DATA_INT);
+        $aEvent = $this->_oDb->getEvents(array('browse' => 'id', 'value' => $iId));
+        if(empty($aEvent) || !is_array($aEvent))
+            return echoJson(array('code' => 1));
+
+        $aParams = $this->_prepareParamsGet();
+        $this->_iOwnerId = $aParams['owner_id'];
+
+        $mixedAllowed = $this->isAllowedDelete($aEvent, true);
+        if($mixedAllowed !== true)
+            return echoJson(array('code' => 2, 'message' => strip_tags($mixedAllowed)));
+
+        if(!$this->{$this->_oConfig->isHideUponDelete() ? 'hideEvent' : 'deleteEvent'}($aEvent))
+            return echoJson(array('code' => 3));
+
+        echoJson(array(
+            'code' => 0, 
+            'id' => $aEvent['id'], 
+            'eval' => $this->_oConfig->getJsObjectView($aParams) . '.onDeletePost(oData)'
+        ));
+    }
+
+    public function actionRepost()
+    {
+    	$iAuthorId = $this->getUserId();
+        $iOwnerId = bx_process_input(bx_get('owner_id'), BX_DATA_INT);
+        $sType = bx_process_input(bx_get('type'), BX_DATA_TEXT);
+        $sAction = bx_process_input(bx_get('action'), BX_DATA_TEXT);
+        $iObjectId = bx_process_input(bx_get('object_id'), BX_DATA_INT);
+
+        $aResult = $this->repost($iAuthorId, $iOwnerId, $sType, $sAction, $iObjectId);
+        if(!empty($aResult) && is_array($aResult))
+            return echoJson($aResult);
+
+        $aParams = $this->_oConfig->getRepostDefaults();
+        $aReposted = $this->_oDb->getReposted($sType, $sAction, $iObjectId);
+
+        echoJson([
+            'code' => 0, 
+            'message' => _t('_bx_timeline_txt_msg_success_repost'), 
+            'count' => $aReposted['reposts'], 
+            'countf' => (int)$aReposted['reposts'] > 0 ? $this->_oTemplate->getRepostCounterLabel($aReposted['reposts'], $aParams) : '',
+            'counter' => $this->_oTemplate->getRepostCounter($aReposted, $aParams),
+            'disabled' => true
+        ]);
+    }
+
+    public function actionRepostWith()
+    {
+        if(($iReposterId = bx_get('reposter_id')) !== false)
+            $iReposterId = bx_process_input($iReposterId, BX_DATA_INT);
+
+        $iUserId = $this->getUserId();
+        if(!$iReposterId || $iReposterId != $iUserId)
+            $iReposterId = $iUserId;
+
+        $iOwnerId = bx_process_input(bx_get('owner_id'), BX_DATA_INT);
+        $sType = bx_process_input(bx_get('type'), BX_DATA_TEXT);
+        $sAction = bx_process_input(bx_get('action'), BX_DATA_TEXT);
+        $iObjectId = bx_process_input(bx_get('object_id'), BX_DATA_INT);
+
+        $oForm = BxDolForm::getObjectInstance($this->_oConfig->getObject('form_repost'), $this->_oConfig->getObject('form_display_repost_with'));
+        $oForm->initChecker(array(
+            'reposter_id' => $iReposterId,
+            'owner_id' => $iOwnerId,
+            'type' => $sType,
+            'action' => $sAction, 
+            'object_id' => $iObjectId
+        ));
+
+        if($oForm->isSubmitted()) {
+            if(!$oForm->isValid())
+                return echoJson(array('popup' => array(
+                    'html' => BxTemplFunctions::getInstance()->transBox($this->_oConfig->getHtmlIds('repost', 'with_popup'), $this->_oTemplate->getRepostWith($oForm)), 
+                    'options' => array('closeOnOuterClick' => false, 'removeOnClose' => true)
+                )));
+
+            $this->repost($iReposterId, $iOwnerId, $sType, $sAction, $iObjectId, ['text' => $oForm->getCleanValue('text')]);
+
+            $aReposted = $this->_oDb->getReposted($sType, $sAction, $iObjectId);
+            $sCounter = $this->_oTemplate->getRepostCounter($aReposted);
+
+            return echoJson(array(
+                'code' => 0, 
+                'message' => _t('_bx_timeline_txt_msg_success_repost'), 
+                'count' => $aReposted['reposts'], 
+                'countf' => (int)$aReposted['reposts'] > 0 ? $this->_oTemplate->getRepostCounterLabel($aReposted['reposts']) : '',
+                'counter' => $sCounter,
+            ));
+        }
+
+        echo $this->_oTemplate->getRepostTo($oForm);
+    }
+
+    public function actionRepostTo()
+    {
+        $iReposterId = bx_process_input(bx_get('reposter_id'), BX_DATA_INT);
+        if($iReposterId != $this->getUserId())
+            return;
+
+        $sType = bx_process_input(bx_get('type'), BX_DATA_TEXT);
+        $sAction = bx_process_input(bx_get('action'), BX_DATA_TEXT);
+        $iObjectId = bx_process_input(bx_get('object_id'), BX_DATA_INT);
+
+        $oForm = BxDolForm::getObjectInstance($this->_oConfig->getObject('form_repost'), $this->_oConfig->getObject('form_display_repost_to'));
+        $oForm->initChecker(array(
+            'reposter_id' => $iReposterId,
+            'type' => $sType,
+            'action' => $sAction, 
+            'object_id' => $iObjectId
+        ));
+
+        if($oForm->isSubmitted()) {
+            if(!$oForm->isValid())
+                return echoJson(array('popup' => array(
+                    'html' => BxTemplFunctions::getInstance()->transBox($this->_oConfig->getHtmlIds('repost', 'to_popup'), $this->_oTemplate->getRepostTo($oForm)), 
+                    'options' => array('closeOnOuterClick' => false, 'removeOnClose' => true)
+                )));
+
+            $aContexts = array();
+            if(($aContextsSearch = $oForm->getCleanValue('search')) !== false)
+                $aContexts = array_merge($aContexts, $aContextsSearch);
+
+            if(($aContextsList = $oForm->getCleanValue('list')) !== false)
+                $aContexts = array_merge($aContexts, $aContextsList);
+
+            $aContexts = array_unique($aContexts);
+            if(empty($aContexts) || !is_array($aContexts))
+                return echoJson(array());
+
+            foreach($aContexts as $iContextId)
+                $this->repost($iReposterId, $iContextId, $sType, $sAction, $iObjectId);
+
+            $aReposted = $this->_oDb->getReposted($sType, $sAction, $iObjectId);
+            $sCounter = $this->_oTemplate->getRepostCounter($aReposted);
+
+            return echoJson(array(
+                'code' => 0, 
+                'message' => _t('_bx_timeline_txt_msg_success_repost'), 
+                'count' => $aReposted['reposts'], 
+                'countf' => (int)$aReposted['reposts'] > 0 ? $this->_oTemplate->getRepostCounterLabel($aReposted['reposts']) : '',
+                'counter' => $sCounter,
+            ));
+        }
+
+        echo $this->_oTemplate->getRepostTo($oForm);
+    }
+
+    function actionGetView()
+    {
+        $aParams = $this->_prepareParamsGet();
+
+        $sContent = $this->_oTemplate->getViewBlock($aParams);
+        if(empty($sContent))
+            return echoJson(array());
+
+        if(!empty($aParams['type']))
+            $this->_oConfig->setUserChoice(array('type' => $aParams['type']));
+
+        echoJson(array(
+            'code' => 0, 
+            'content' => $sContent,
+        ));
+    }
+
+    function actionGetViewFilters()
+    {
+        $aParams = $this->_prepareParamsGet();
+
+        $sContent = $this->_oTemplate->getViewFilters($aParams);
+        if(empty($sContent))
+            return echoJson([]);
+
+        echoJson([
+            'code' => 0,
+            'popup' => [
+                'html' => $sContent,
+                'options' => [
+                    'closeOnOuterClick' => true,
+                    'removeOnClose' => false,
+                ]
+            ],
+        ]);
+    }
+
+    function actionGetPost()
+    {
+        $aParams = $this->_prepareParamsGet();
+        $aParams['dynamic_mode'] = true;
+
+        $this->_iOwnerId = $aParams['owner_id'];
+
+        $sJsObject = '';
+        if(bx_get('js_object') !== false)
+            $sJsObject = $this->_oConfig->prepareParam('js_object');
+        if(empty($sJsObject))
+            $sJsObject = $this->_oConfig->getJsObject('post');
+
+        $aEvent = $this->_oDb->getEvents(['browse' => 'id', 'value' => (int)bx_get('id')]);
+        if(empty($aEvent) || !is_array($aEvent))
+            return echoJson([]);
+
+        /**
+         * Note. Disabled for now, because Own posts on Timelines of Following members 
+         * became visible on posts' author Dashboard Timeline.
+         * 
+        $bAfpsLoading = (int)bx_get('afps_loading') === 1;
+        if($bAfpsLoading && $this->_iOwnerId != $aEvent['owner_id'])
+            return echoJson(array('message' => _t('_bx_timeline_txt_msg_posted')));
+         * 
+         */
+
+        $aResult = [
+            'id' => (int)$aEvent['id'],
+            'name' => $aParams['name'],
+            'view' => $aParams['view'],
+            'type' => $aParams['type'],
+            'item' => $this->_oTemplate->getPost($aEvent, $aParams),
+            'eval' => $sJsObject . "._onGetPost(oData)"
+        ];
+
+        bx_alert($this->getName(), 'on_get_post', 0, 0, [
+            'params' => $aParams,
+            'override_result' => &$aResult,
+        ]);
+
+        echoJson($aResult);
+    }
+
+    function actionGetPosts()
+    {
+        $aParams = $this->_prepareParamsGet();
+        list($sItems, $sLoadMore, $sBack, $sEmpty, $iEvent, $bEventsToLoad) = $this->_oTemplate->getPosts($aParams);
+
+        echoJson(array(
+            'view' => $aParams['view'],
+            'items' => $sItems,
+            'load_more' => $sLoadMore, 
+            'back' => $sBack,
+            'empty' => $sEmpty,
+            'events_to_load' => $bEventsToLoad,
+            'eval' => $this->_oConfig->getJsObjectView($aParams) . "._onGetPosts(oData)"
+        ));
+    }
+
+    public function actionGetPostForm()
+    {
+        $this->_iOwnerId = bx_process_input(bx_get('owner_id'), BX_DATA_INT);
+        $sType = bx_process_input(bx_get('type'));
+
+        echoJson($this->getFormPost(array(
+            'type' => $sType,
+            'form_display' => $this->_oConfig->getPostFormDisplay($sType)
+        )));
+    }
+
+    public function actionGetEditForm($iId)
+    {
+        $aParams = $this->_prepareParamsGet();
+        $this->_iOwnerId = $aParams['owner_id'];
+
+        echoJson($this->getFormEdit($iId, array('dynamic_mode' => true), $aParams));
+    }
+
+    public function actionGetComments()
+    {
+        $this->_iOwnerId = bx_process_input(bx_get('owner_id'), BX_DATA_INT);
+
+        $sSystem = bx_process_input(bx_get('system'), BX_DATA_TEXT);
+        $iId = bx_process_input(bx_get('id'), BX_DATA_INT);
+        $sComments = $this->_oTemplate->getComments($sSystem, $iId, array('dynamic_mode' => true));
+
+        echoJson(array('content' => $sComments));
+    }
+
+    public function actionAddAttachLink()
+    {
+        $sUrl = bx_process_input(bx_get('url'));
+        if(empty($sUrl))
+            return echoJson([]);
+        
+        $sUrl = htmlspecialchars_decode($sUrl);
+
+        $aHeaders = @get_headers($sUrl, 1);
+        if($aHeaders === false)
+            return echoJson([]);
+
+        $sHeader = 'Content-Type';
+        if(!empty($aHeaders[$sHeader])) {
+            $mixedContentType = $aHeaders[$sHeader];
+            if(!is_array($mixedContentType))
+                $mixedContentType = [$mixedContentType];
+
+            foreach($mixedContentType as $sContentType)
+                if(strpos($sContentType, 'image') !== false) 
+                    return echoJson([]);
+        }
+
+        $iEventId = 0;
+        if(bx_get('event_id') !== false)
+            $iEventId = (int)bx_get('event_id');
+
+        echoJson($this->addAttachLink([
+            'event_id' => $iEventId,
+            'url' => $sUrl
+        ]));
+    }
+
+    public function actionDeleteAttachLink()
+    {
+    	$iUserId = $this->getUserId();
+        $iLinkId = bx_process_input(bx_get('id'), BX_DATA_INT);
+        if(empty($iLinkId))
+            return echoJson(array());
+
+        $aLink = $this->_oDb->getLinksBy(array('type' => 'id', 'id' => $iLinkId, 'profile_id' => $iUserId));
+    	if(empty($aLink) || !is_array($aLink))
+            return echoJson(array());
+
+        if(!empty($aLink['media_id']))
+            BxDolStorage::getObjectInstance($this->_oConfig->getObject('storage_photos'))->deleteFile($aLink['media_id']);
+
+        $aResult = array();
+        if($this->_oDb->deleteLink($iLinkId))
+            $aResult = array('code' => 0);
+        else
+            $aResult = array('code' => 1, 'message' => _t('_bx_timeline_form_post_input_link_err_delete'));
+
+        echoJson($aResult);
+    }
+
+    public function actionGetAttachLinkForm()
+    {
+        $iEventId = 0;
+        if(bx_get('event_id') !== false)
+            $iEventId = (int)bx_get('event_id');
+
+        echo $this->_oTemplate->getAttachLinkForm($iEventId);
+    }
+
+    public function actionSubmitAttachLinkForm()
+    {
+        echoJson($this->getFormAttachLink());
+    }
+
+    public function actionAutoAttachInsertion()
+    {
+        $sTxtError = _t('_bx_timeline_txt_err_cannot_perform_insertion');
+
+        $sUploader = bx_process_input(bx_get('u'));
+        $sResultContainerId = bx_process_input(bx_get('uid'));
+
+        $sStorage = $this->_oConfig->getObject('storage_photos');
+        $oUploader = BxDolUploader::getObjectInstance($sUploader, $sStorage, $sResultContainerId, $this->_oTemplate);
+        if(!$oUploader)
+            return echoJson(['code' => 1, 'msg' => $sTxtError]);
+
+        ob_start();
+        $oUploader->handleUploads(bx_get_logged_profile_id(), isset($_FILES['file']) ? $_FILES['file'] : null, false, false, false);
+        ob_end_clean();
+
+        $sError = $oUploader->getUploadErrorMessages();
+        if(!empty($sError))
+            return echoJson(['code' => 2, 'msg' => $sError]);
+
+        return echoJson(['code' => 0, 'eval' => $oUploader->getNameJsInstanceUploader() . '.restoreGhosts()']);
+    }
+
+    public function actionGetRepostedBy()
+    {
+        $iRepostedId = bx_process_input(bx_get('id'), BX_DATA_INT);
+
+        echo $this->_oTemplate->getRepostedBy($iRepostedId);
+    }
+
+    public function actionGetItemBrief()
+    {
+        $aParams = $this->_prepareParamsGet();
+
+        $iEvent = bx_process_input(bx_get('id'), BX_DATA_INT);
+        $aEvent = $this->_oDb->getEvents(array('browse' => 'id', 'value' => $iEvent));
+        if(empty($aEvent) || !is_array($aEvent)) {
+            echo MsgBox(_t('_Empty'));
+            return;
+        }
+
+        if(!$this->isAllowedView($aEvent)) {
+            echo MsgBox(_t('_sys_access_denied_to_private_content'));
+            return;
+        }        
+
+        $sName = $this->_oConfig->getHtmlIdView('item_popup', $aParams, array('whole' => false, 'hash' => false)) . $iEvent;
+        $sTitle = _t('_bx_timeline_page_title_item_brief');
+        $sContent = BxDolPage::getObjectInstance($this->_oConfig->getObject('page_item_brief'), $this->_oTemplate)->getCodeDynamic();
+        echo PopupBox($sName, $sTitle, $sContent, true);
+                
+    }
+
+    public function actionGetJumpTo()
+    {
+        $aParams = $this->_prepareParamsGet();
+        $this->_iOwnerId = $aParams['owner_id'];
+
+        $sJsObjectView = $this->_oConfig->getJsObjectView($aParams);
+
+        echoJson(array(
+            'content' => $this->_oTemplate->getJumpTo($aParams),
+            'eval' => $sJsObjectView . '.onGetJumpTo(oData)'
+        ));
+    }
+
+    public function actionResumeLiveUpdate()
+    {
+        $aParams = $this->_prepareParamsGet();
+    	$sKey = $this->_oConfig->getLiveUpdateKey($aParams);
+
+    	bx_import('BxDolSession');
+    	BxDolSession::getInstance()->unsetValue($sKey);
+    }
+
+    public function actionPauseLiveUpdate()
+    {
+        $aParams = $this->_prepareParamsGet();
+    	$sKey = $this->_oConfig->getLiveUpdateKey($aParams);
+
+    	bx_import('BxDolSession');
+    	BxDolSession::getInstance()->setValue($sKey, 1);
+    }
+
+    function actionRss()
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $iLength = $this->_oConfig->getRssLength();
+        if(!$iLength)
+            return;
+
+        $iOwnerId = 0;
+
+        $aArgs = func_get_args();
+        $sType = array_shift($aArgs);
+        switch($sType) {
+            case BX_BASE_MOD_NTFS_TYPE_OWNER:
+                $iOwnerId = array_shift($aArgs);
+                $sOwnerName = $this->getObjectUser($iOwnerId)->getDisplayName();
+
+                $sRssCaption = _t('_bx_timeline_txt_rss_caption', $sOwnerName);
+                $sRssLink = $this->_oConfig->getViewUrl($iOwnerId);
+                break;
+
+            case BX_BASE_MOD_NTFS_TYPE_PUBLIC:
+                $sRssCaption = _t('_bx_timeline_page_title_view_home');
+                $sRssLink = $this->_oConfig->getHomeViewUrl();
+                break;
+        }
+
+        $aParams = $this->_prepareParams(array(
+            'view' => BX_TIMELINE_VIEW_DEFAULT,
+            'type' => $sType,
+            'owner_id' => $iOwnerId,
+            'start' => 0, 
+            'per_page' => $iLength, 
+            'timeline' => 0, 
+            'filter' => '', 
+            'modules' => array()
+        ));
+        $aEvents = $this->_oDb->getEvents($aParams);
+
+        $oPrivacy = BxDolPrivacy::getObjectInstance($this->_oConfig->getObject('privacy_view'));
+
+        $aRssData = array();
+        foreach($aEvents as $aEvent) {
+            if(empty($aEvent['title'])) 
+                continue;
+
+            $iEventId = (int)$aEvent[$CNF['FIELD_ID']];
+            $sEventFieldAuthor = $this->_oConfig->isSystem($aEvent['type'], $aEvent['action']) ? 'owner_id' : 'object_id';
+
+            if($oPrivacy) {
+                $oPrivacy->setTableFieldAuthor($sEventFieldAuthor);
+                if(!$oPrivacy->check($iEventId))
+                    continue;
+            }
+
+            $iOwner = $aEvent[$sEventFieldAuthor];
+            $oOwner = BxDolProfile::getInstanceMagic($iOwner);
+
+            $aRssData[$iEventId] = array(
+               'UnitID' => $iEventId,
+               'UnitTitle' => $aEvent['title'],
+               'UnitLink' => $this->_oConfig->getItemViewUrl($aEvent),
+               'UnitDesc' => bx_replace_markers($aEvent['description'], array(
+                    'profile_name' => $oOwner->getDisplayName()
+                )),
+               'UnitDateTimeUTS' => $aEvent['date'],
+            );
+        }
+
+        $oRss = new BxDolRssFactory();
+
+        header('Content-Type: application/xml; charset=utf-8');
+        echo $oRss->GenRssByData($aRssData, $sRssCaption, $sRssLink);
+    }
+
+
+    /**
+     * SERVICE METHODS
+     */
+
+    public function serviceGetSafeServices()
+    {
+        $a = parent::serviceGetSafeServices();
+        return array_merge($a, array (
+            'GetCreatePostForm' => '',
+            'GetSearchResultUnit' => '',
+            'GetBlockPost' => '',
+            'GetBlockPostProfile' => '',
+            'GetBlockPostHome' => '',
+            'GetBlockPostAccount' => '',
+            'GetBlockView' => '',
+            'GetBlockViewOutline' => '',
+            'GetBlockViewProfile' => '',
+            'GetBlockViewProfileOutline' => '',
+            'GetBlockViewsTimeline' => '',
+            'GetBlockViewsOutline' => '',
+            'GetBlockViewHome' => '',
+            'GetBlockViewHomeOutline' => '',
+            'GetBlockViewHot' => '',
+            'GetBlockViewHotOutline' => '',
+            'GetBlockViewAccount' => '',
+            'GetBlockViewAccountOutline' => '',
+        ));
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Timeline
+     * @subsection bx_timeline-other Other
+     * @subsubsection bx_timeline-get_hot_sources_checklist get_hot_sources_checklist
+     * 
+     * @code bx_srv('bx_timeline', 'get_hot_sources_checklist', [...]); @endcode
+     * 
+     * Get a list of available sources for Hot feed. Is used in module settings in Studio.
+     *
+     * @return an array with available sources represented as key => value pairs.
+     * 
+     * @see BxTimelineModule::serviceGetHotSourcesChecklist
+     */
+    /** 
+     * @ref bx_timeline-get_hot_sources_checklist "get_hot_sources_checklist"
+     */
+    function serviceGetHotSourcesChecklist()
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+    	$aSources = $this->_oConfig->getHotSourcesList();
+
+        $aResults = [];
+        foreach($aSources as $sSource) 
+            $aResults[$sSource] = _t($CNF['T']['option_hs_' . $sSource]);
+
+        return $aResults;
+    }
+
+    public function serviceManageTools($sType = 'common')
+    {
+        $sResult = parent::serviceManageTools($sType);
+        if(!empty($sResult))
+            $this->_oTemplate->addJsSystem(['modules/base/text/js/|manage_tools.js']);
+
+        return $sResult;
+    }
+
+    public function serviceFeedsMenuAdd($mixedModule = false)
+    {
+        $sSetName = $this->_oConfig->getObject('menu_set_feeds');
+
+        $iOrder = $this->_oDb->getMenuItemMaxOrder($sSetName);
+
+        $aModules = !empty($mixedModule) ? [$this->_oDb->getModuleByName($mixedModule)] : bx_srv('system', 'get_modules_by_type', ['context']);
+        foreach($aModules as $aModule) {
+            $sModuleName = $aModule['name'];
+            $sModuleUri = $aModule['uri'];
+            if($sModuleName == 'system' && $sModuleUri == 'system')
+                continue;
+
+            $iMenuItem = $this->_oDb->getMenuItemId($sSetName, $sModuleUri);
+            if(!empty($iMenuItem))
+                continue;
+
+            $sTitleKey = '_' . $sModuleName;
+            if(strcmp($sTitleKey, _t($sTitleKey)) == 0)
+                $sTitleKey = $aModule['title'];
+
+            $this->_oDb->insertMenuItem($sSetName, $sModuleName, $sModuleUri, $sTitleKey, ++$iOrder);
+        }
+
+        return true;
+    }
+
+    public function serviceFeedsMenuDelete($mixedModule = false)
+    {
+        $sSetName = $this->_oConfig->getObject('menu_set_feeds');
+
+        $aModules = !empty($mixedModule) ? [$this->_oDb->getModuleByName($mixedModule)] : bx_srv('system', 'get_modules_by_type', ['context']);
+        foreach($aModules as $aModule)
+            $this->_oDb->deleteMenuItem($sSetName, $aModule['uri']);
+
+        return true;
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Timeline
+     * @subsection bx_timeline-other Other
+     * @subsubsection bx_timeline-get_content_owner_profile_id get_content_owner_profile_id
+     * 
+     * @code bx_srv('bx_timeline', 'get_content_owner_profile_id', [...]); @endcode
+     * 
+     * Get event's owner profile id.
+     * 
+     * @param $mixedEvent integer value with event ID or an array with event info.
+     * @return event's owner profile id.
+     * 
+     * @see BxTimelineModule::serviceGetContentOwnerProfileId
+     */
+    /** 
+     * @ref bx_timeline-get_content_owner_profile_id "get_content_owner_profile_id"
+     */
+    public function serviceGetContentOwnerProfileId($mixedEvent)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $iProfile = (int)bx_get_logged_profile_id();
+        if(empty($mixedEvent))
+            return $iProfile;
+
+        if(!is_array($mixedEvent))
+            $mixedEvent = $this->_oDb->getContentInfoById((int)$mixedEvent);
+
+        if(empty($mixedEvent) || !is_array($mixedEvent) || !isset($mixedEvent[$CNF['FIELD_SYSTEM']]))
+            return $iProfile;
+
+        if((int)$mixedEvent[$CNF['FIELD_SYSTEM']] == 0)
+            return (int)$mixedEvent[$CNF['FIELD_OBJECT_ID']];
+
+        if(!empty($mixedEvent['object_owner_id']))
+            return (int)$mixedEvent['object_owner_id'];
+
+        if(!empty($mixedEvent['content'])) {
+            $aContent = unserialize($mixedEvent['content']);
+
+            if(!empty($aContent) && is_array($aContent) && !empty($aContent['object_author_id']))
+                return (int)$aContent['object_author_id'];
+        }
+
+        $aEventData = $this->_oTemplate->getData($mixedEvent);
+        if(!empty($aEventData) && is_array($aEventData) && !empty($aEventData['object_owner_id']))
+            return (int)$aEventData['object_owner_id'];
+
+        return $iProfile;
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Timeline
+     * @subsection bx_timeline-other Other
+     * @subsubsection bx_timeline-get_create_post_form get_create_post_form
+     * 
+     * @code bx_srv('bx_timeline', 'get_create_post_form', [...]); @endcode
+     * 
+     * Get form code for add content. Is needed for United Post Form.
+     * 
+     * @param $aParams optional array with parameters(display name, etc)
+     * @return form code or error
+     * 
+     * @see BxTimelineModule::serviceGetCreatePostForm
+     */
+    /** 
+     * @ref bx_timeline-get_create_post_form "get_create_post_form"
+     */
+    public function serviceGetCreatePostForm($aParams = array())
+    {
+    	$aParams = array_merge($this->_aFormParams, $aParams);
+
+        $bContext = $aParams['context_id'] !== false;
+        $this->_iOwnerId = $bContext ? abs($aParams['context_id']) : 0;
+
+    	$oForm = $this->serviceGetObjectForm('add', $aParams);
+    	if(!$oForm)
+            return '';
+
+        $aParams['type'] = BX_BASE_MOD_NTFS_TYPE_PUBLIC;
+        $aParams['form_display'] = 'form_display_post_add_public';
+        if($bContext) {
+            if($aParams['context_id'] < 0) {
+                $aParams['type'] = BX_BASE_MOD_NTFS_TYPE_OWNER;
+                $aParams['form_display'] = 'form_display_post_add_profile';
+            }
+            else {
+                $aParams['type'] = BX_TIMELINE_TYPE_FEED;
+                $aParams['form_display'] = 'form_display_post_add';
+            }
+        }
+
+        if(!empty($aParams['display']))
+            $aParams['form_display'] = $aParams['display'];
+
+    	$aResult = $this->getFormPost($aParams);
+    	if(!empty($aResult['form'])) {
+            $bDynamicMode = isset($aParams['dynamic_mode']) && $aParams['dynamic_mode'];
+
+            $sCode = '';
+            $sCode .= $this->_oTemplate->getJsCodePost($this->_iOwnerId, $aParams, true, $bDynamicMode);
+            $sCode .= $aResult['form'];
+            return $sCode;
+        }
+
+        if(!empty($aResult['message']))
+            return $aResult['message'];
+
+        return '';
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Timeline
+     * @subsection bx_timeline-other Other
+     * @subsubsection bx_timeline-get_object_form get_object_form
+     * 
+     * @code bx_srv('bx_timeline', 'get_object_form', [...]); @endcode
+     * 
+     * Get form object for add, edit, view or delete the content.
+     * 
+     * @param $sType 'add' is supported only 
+     * @param $aParams optional array with parameters(display name, etc)
+     * @return form object or false on error
+     * 
+     * @see BxTimelineModule::serviceGetObjectForm
+     */
+    /** 
+     * @ref bx_timeline-get_object_form "get_object_form"
+     */
+    public function serviceGetObjectForm ($sType, $aParams = array())
+    {
+    	if(!in_array($sType, array('add')))
+            return false;
+
+        $bContext = $aParams['context_id'] !== false;
+        if($bContext && ($oContextProfile = BxDolProfile::getInstance(abs($aParams['context_id']))) !== false)
+            if($oContextProfile->checkAllowedPostInProfile() !== CHECK_ACTION_RESULT_ALLOWED)
+                return false;
+
+        $aParams['type'] = BX_BASE_MOD_NTFS_TYPE_PUBLIC;
+        $aParams['form_display'] = 'form_display_post_add_public';
+        if($bContext) {
+            if($aParams['context_id'] < 0) {
+                $aParams['type'] = BX_BASE_MOD_NTFS_TYPE_OWNER;
+                $aParams['form_display'] = 'form_display_post_add_profile';
+            }
+            else {
+                $aParams['type'] = BX_TIMELINE_TYPE_OWNER_AND_CONNECTIONS;
+                $aParams['form_display'] = 'form_display_post_add';
+            }
+        }
+
+        if(!empty($aParams['display']))
+            $aParams['form_display'] = $aParams['display'];
+
+        $oForm = $this->getFormPostObject($aParams);
+
+        bx_alert('system', 'get_object_form', 0, 0, array(
+            'module' => $this->_oConfig->getName(),
+            'type' => $sType,
+            'params' => $aParams,
+            'form' => &$oForm
+        ));
+
+    	return $oForm;
+    }
+    
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Timeline
+     * @subsection get_timeline_post
+     * @see BxTimelineModule::serviceGetTimelinePost
+     *
+     * Get Timeline post. It's needed for Timeline module.
+     * 
+     * @param $aEvent timeline event array from Timeline module
+     * @return array in special format which is needed specifically for Timeline module to display the data.
+     */
+    public function serviceGetTimelinePost($aEvent, $aBrowseParams = array())
+    {
+        $aContentInfo = $this->_oDb->getContentInfoById($aEvent['object_id']);
+        if(empty($aContentInfo) || !is_array($aContentInfo))
+            return false;
+
+        $aEvent = array_merge($aEvent, array(
+            'owner_id' => $aContentInfo['owner_id'],
+            'object_privacy_view' => $aContentInfo['object_privacy_view']
+        ));
+
+        /*
+         * Note. For 'Direct Timeline Posts' FIELD_OBJECT_ID contains post's author profile ID.
+         */
+        $this->_oConfig->CNF['FIELD_AUTHOR'] = $this->_oConfig->CNF['FIELD_OBJECT_ID'];
+        return parent::serviceGetTimelinePost($aEvent, $aBrowseParams);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Timeline
+     * @subsection get_timeline_post
+     * @see BxTimelineModule::serviceGetTimelinePostAllowedView
+     *
+     * Check Timeline post's visibility. It's needed for Timeline module, when its events 
+     * are accessed and checked from outside. For example, when they are referenced 
+     * from Channels module.
+     * 
+     * @param $aEvent timeline event array from Timeline module
+     * @return mixed value: CHECK_ACTION_RESULT_ALLOWED or text of some error message.
+     */
+    public function serviceGetTimelinePostAllowedView($aEvent)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $iOwnerId = (int)$aEvent[$CNF['FIELD_OWNER_ID']];
+        if($iOwnerId == 0)
+            return CHECK_ACTION_RESULT_ALLOWED;
+
+        $oOwner = BxDolProfile::getInstance($iOwnerId);
+        if(!$oOwner)
+            return CHECK_ACTION_RESULT_ALLOWED;
+
+        $sModule = $oOwner->getModule();
+        $aOwnerInfo = BxDolService::call($sModule, 'get_info', array($oOwner->getContentId(), false));
+        if(empty($aOwnerInfo) || !is_array($aOwnerInfo))
+            return CHECK_ACTION_RESULT_ALLOWED;
+
+        return BxDolService::call($sModule, 'check_allowed_view_for_profile', array($aOwnerInfo));
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Timeline
+     * @subsection bx_timeline-other Other
+     * @subsubsection bx_timeline-get_author get_author
+     * 
+     * @code bx_srv('bx_timeline', 'get_author', [...]); @endcode
+     * 
+     * Get author ID from content info by content ID. Is used in "Content Info Objects" system.
+     * 
+     * @param $iContentId integer value with content ID.
+     * @return integer value with author ID.
+     * 
+     * @see BxTimelineModule::serviceGetAuthor
+     */
+    /** 
+     * @ref bx_timeline-get_author "get_author"
+     */
+    public function serviceGetAuthor ($iContentId)
+    {
+        $aEvent = $this->_oDb->getEvents(array('browse' => 'id', 'value' => $iContentId));
+        if(empty($aEvent) || !is_array($aEvent))
+            return 0;
+
+        return $this->_oConfig->isSystem($aEvent['type'], $aEvent['action']) ? (int)$aEvent['owner_id'] : (int)$aEvent['object_id'];
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Timeline
+     * @subsection bx_timeline-other Other
+     * @subsubsection bx_timeline-get_date_changed get_date_changed
+     * 
+     * @code bx_srv('bx_timeline', 'get_date_changed', [...]); @endcode
+     * 
+     * Get date when the content was changed last time. Is used in "Content Info Objects" system.
+     * Note. In case of Timeline event 0 is returned everytime.
+     * 
+     * @param $iContentId integer value with content ID.
+     * @return integer value with changing date.
+     * 
+     * @see BxTimelineModule::serviceGetDateChanged
+     */
+    /** 
+     * @ref bx_timeline-get_date_changed "get_date_changed"
+     */
+    public function serviceGetDateChanged ($iContentId)
+    {
+        return 0;
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Timeline
+     * @subsection bx_timeline-other Other
+     * @subsubsection bx_timeline-get_link get_link
+     * 
+     * @code bx_srv('bx_timeline', 'get_link', [...]); @endcode
+     * 
+     * Get content view page link. Is used in "Content Info Objects" system.
+     * 
+     * @param $iContentId integer value with content ID.
+     * @return string value with view page link.
+     * 
+     * @see BxTimelineModule::serviceGetLink
+     */
+    /** 
+     * @ref bx_timeline-get_link "get_link"
+     */
+    public function serviceGetLink ($iContentId)
+    {
+        $aEvent = $this->_oDb->getEvents(array('browse' => 'id', 'value' => $iContentId));
+        if(empty($aEvent) || !is_array($aEvent))
+            return '';
+
+        return $this->_oConfig->getItemViewUrl($aEvent);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Timeline
+     * @subsection bx_timeline-other Other
+     * @subsubsection bx_timeline-get_thumb get_thumb
+     * 
+     * @code bx_srv('bx_timeline', 'get_thumb', [...]); @endcode
+     * 
+     * Get content thumbnail link. Is used in "Content Info Objects" system.
+     * Note. In case of Timeline event an empty string is returned everytime.
+     * 
+     * @param $iContentId integer value with content ID.
+     * @param $sTranscoder (optional) string value with transcoder name which should be applied to thumbnail image.
+     * @return string value with thumbnail link.
+     * 
+     * @see BxTimelineModule::serviceGetThumb
+     */
+    /** 
+     * @ref bx_timeline-get_thumb "get_thumb"
+     */
+    public function serviceGetThumb ($iContentId, $sTranscoder = '') 
+    {
+        return '';
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Timeline
+     * @subsection bx_timeline-other Other
+     * @subsubsection bx_timeline-get_info get_info
+     * 
+     * @code bx_srv('bx_timeline', 'get_info', [...]); @endcode
+     * 
+     * Get content info by content ID. Is used in "Content Info Objects" system.
+     * 
+     * @param $iContentId integer value with content ID.
+     * @param $bSearchableFieldsOnly (optional) boolean value determining all info or "searchable fields" only will be returned.
+     * @return an array with content info. Empty array is returned if something is wrong.
+     * 
+     * @see BxTimelineModule::serviceGetInfo
+     */
+    /** 
+     * @ref bx_timeline-get_info "get_info"
+     */
+    public function serviceGetInfo ($iContentId, $bSearchableFieldsOnly = true)
+    {
+        $aContentInfo = $this->_oDb->getEvents(array(
+        	'browse' => 'id', 
+        	'value' => $iContentId)
+        );
+
+        return BxDolContentInfo::formatFields($aContentInfo);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Timeline
+     * @subsection bx_timeline-other Other
+     * @subsubsection bx_timeline-get_title get_title
+     * 
+     * @code bx_srv('bx_timeline', 'get_title', [...]); @endcode
+     * 
+     * Get content title by content ID. Is used in "Content Info Objects" system.
+     * 
+     * @param $iContentId integer value with content ID.
+     * @return an array with content info. Empty array is returned if something is wrong.
+     * 
+     * @see BxTimelineModule::serviceGetTitle
+     */
+    /** 
+     * @ref bx_timeline-get_title "get_title"
+     */
+    public function serviceGetTitle ($iContentId)
+    {
+        $sResult = parent::serviceGetTitle($iContentId);
+
+        if($sResult != '' && get_mb_substr($sResult, 0, 1) == '_')
+            $sResult = _t($sResult);
+
+        return $sResult;
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Timeline
+     * @subsection bx_timeline-other Other
+     * @subsubsection bx_timeline-get_search_result_unit get_search_result_unit
+     * 
+     * @code bx_srv('bx_timeline', 'get_search_result_unit', [...]); @endcode
+     * 
+     * Get search result unit by content ID. Is used in "Content Info Objects" system.
+     * 
+     * @param $iContentId integer value with content ID.
+     * @param $sUnitTemplate (optional) string value with template name.
+     * @return HTML string with search result unit. Empty string is returned if something is wrong.
+     * 
+     * @see BxTimelineModule::serviceGetSearchResultUnit
+     */
+    /** 
+     * @ref bx_timeline-get_search_result_unit "get_search_result_unit"
+     */
+    public function serviceGetSearchResultUnit ($iContentId, $sUnitTemplate = '')
+    {
+        $aEvent = $this->_oDb->getEvents(array('browse' => 'id', 'value' => $iContentId));
+        if(empty($aEvent) || !is_array($aEvent))
+            return '';
+
+        if(empty($sUnitTemplate))
+            $sUnitTemplate = 'unit.html';
+
+        return $this->_oTemplate->unit($aEvent, true, $sUnitTemplate);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Timeline
+     * @subsection bx_timeline-page_blocks Page Blocks
+     * @subsubsection bx_timeline-get_block_post get_block_post
+     * 
+     * @code bx_srv('bx_timeline', 'get_block_post', [...]); @endcode
+     * 
+     * Get Post block for a separate page.
+     *
+     * @param $iProfileId (optional) profile 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. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
+     * 
+     * @see BxTimelineModule::serviceGetBlockPost
+     */
+    /** 
+     * @ref bx_timeline-get_block_post "get_block_post"
+     */
+    public function serviceGetBlockPost($iProfileId = 0)
+    {
+    	if(empty($iProfileId) && bx_get('profile_id') !== false)
+            $iProfileId = bx_process_input(bx_get('profile_id'), BX_DATA_INT);
+
+        if(empty($iProfileId) && isLogged())
+            $iProfileId = bx_get_logged_profile_id();
+
+        if(!$iProfileId)
+            return array();
+
+        $sType = BX_BASE_MOD_NTFS_TYPE_OWNER;
+        return $this->_getBlockPost($iProfileId, array(
+            'type' => $sType,
+            'form_display' => $this->_oConfig->getPostFormDisplay($sType)
+        ));
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Timeline
+     * @subsection bx_timeline-page_blocks Page Blocks
+     * @subsubsection bx_timeline-get_block_post_profile get_block_post_profile
+     * 
+     * @code bx_srv('bx_timeline', 'get_block_post_profile', [...]); @endcode
+     * 
+     * Get Post block for the Profile page.
+     *
+     * @param $sProfileModule (optional) string value with profile based module name. Persons module is used by default.
+     * @param $iProfileContentId (optional) profile's content 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. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
+     * 
+     * @see BxTimelineModule::serviceGetBlockPostProfile
+     */
+    /** 
+     * @ref bx_timeline-get_block_post_profile "get_block_post_profile"
+     */
+    public function serviceGetBlockPostProfile($sProfileModule = 'bx_persons', $iProfileContentId = 0)
+    {
+        if(empty($sProfileModule))
+            return array();
+
+    	if(empty($iProfileContentId) && bx_get('id') !== false)
+            $iProfileContentId = bx_process_input(bx_get('id'), BX_DATA_INT);
+
+        $oProfile = BxDolProfile::getInstanceByContentAndType($iProfileContentId, $sProfileModule);
+        if(empty($oProfile))
+            return array();
+
+        $iProfileId = $oProfile->id();
+        $sType = BX_BASE_MOD_NTFS_TYPE_OWNER;
+        return $this->_getBlockPost($iProfileId, array(
+            'type' => $sType,
+            'form_display' => $this->_oConfig->getPostFormDisplay($sType)
+        ));
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Timeline
+     * @subsection bx_timeline-page_blocks Page Blocks
+     * @subsubsection bx_timeline-get_block_post_home get_block_post_home
+     * 
+     * @code bx_srv('bx_timeline', 'get_block_post_home', [...]); @endcode
+     * 
+     * Get Post block for site's Home page.
+     *
+     * @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 BxTimelineModule::serviceGetBlockPostHome
+     */
+    /** 
+     * @ref bx_timeline-get_block_post_home "get_block_post_home"
+     */
+    public function serviceGetBlockPostHome()
+    {
+        $iProfileId = 0;
+        $sType = BX_BASE_MOD_NTFS_TYPE_PUBLIC;
+        return $this->_getBlockPost($iProfileId, array(
+            'type' => $sType,
+            'form_display' => $this->_oConfig->getPostFormDisplay($sType)
+        ));
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Timeline
+     * @subsection bx_timeline-page_blocks Page Blocks
+     * @subsubsection bx_timeline-get_block_post_account get_block_post_account
+     * 
+     * @code bx_srv('bx_timeline', 'get_block_post_account', [...]); @endcode
+     * 
+     * Get Post block for the Dashboard page.
+     *
+     * @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 BxTimelineModule::serviceGetBlockPostAccount
+     */
+    /** 
+     * @ref bx_timeline-get_block_post_account "get_block_post_account"
+     */
+    public function serviceGetBlockPostAccount()
+    {
+        if(!isLogged())
+            return '';
+
+        $iProfileId = $this->getProfileId();
+        $sType = BX_TIMELINE_TYPE_FEED;
+        return $this->_getBlockPost($iProfileId, array(
+            'type' => $sType,
+            'form_display' => $this->_oConfig->getPostFormDisplay($sType)
+        ));
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Timeline
+     * @subsection bx_timeline-page_blocks Page Blocks
+     * @subsubsection bx_timeline-get_block_post_custom get_block_post_custom
+     * 
+     * @code bx_srv('bx_timeline', 'get_block_post_custom', [...]); @endcode
+     * 
+     * Get Post block for the Custom timeline.
+     *
+     * @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 BxTimelineModule::serviceGetBlockPostCustom
+     */
+    /** 
+     * @ref bx_timeline-get_block_post_custom "get_block_post_custom"
+     */
+    public function serviceGetBlockPostCustom($aParams)
+    {
+        if(!isLogged())
+            return '';
+
+        $iProfileId = $this->getProfileId();
+
+        if (!isset($aParams['form_display']))
+            $aParams['form_display'] = $this->_oConfig->getPostFormDisplay($aParams['type']);
+
+        return $this->_getBlockPost($iProfileId, $aParams);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Timeline
+     * @subsection bx_timeline-page_blocks Page Blocks
+     * @subsubsection bx_timeline-get_block_view get_block_view
+     * 
+     * @code bx_srv('bx_timeline', 'get_block_view', [...]); @endcode
+     * 
+     * Get Timeline View block for a separate page.
+     *
+     * @param $iProfileId (optional) profile 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. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
+     * 
+     * @see BxTimelineModule::serviceGetBlockView
+     */
+    /** 
+     * @ref bx_timeline-get_block_view "get_block_view"
+     */
+    public function serviceGetBlockView($iProfileId = 0)
+    {
+    	return $this->_serviceGetBlockView($iProfileId, array(
+            'view' => BX_TIMELINE_VIEW_TIMELINE, 
+            'type' => BX_BASE_MOD_NTFS_TYPE_OWNER, 
+            'start' => -1, 
+            'per_page' => -1, 
+            'per_page_default' => $this->_oConfig->getPerPage('profile'), 
+            'timeline' => -1, 
+            'filter' => '', 
+            'modules' => array()
+        ));
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Timeline
+     * @subsection bx_timeline-page_blocks Page Blocks
+     * @subsubsection bx_timeline-get_block_view_outline get_block_view_outline
+     * 
+     * @code bx_srv('bx_timeline', 'get_block_view_outline', [...]); @endcode
+     * 
+     * Get Outline View block for a separate page.
+     * 
+     * @param $iProfileId (optional) profile 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. All necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
+     * 
+     * @see BxTimelineModule::serviceGetBlockViewOutline
+     */
+    /** 
+     * @ref bx_timeline-get_block_view_outline "get_block_view_outline"
+     */
+    public function serviceGetBlockViewOutline($iProfileId = 0)
+    {
+        return $this->_serviceGetBlockView($iProfileId, array(
+            'view' => BX_TIMELINE_VIEW_OUTLINE, 
+            'type' => BX_BASE_MOD_NTFS_TYPE_OWNER, 
+            'start' => -1, 
+            'per_page' => -1, 
+            'per_page_default' => $this->_oConfig->getPerPage('profile'), 
+            'timeline' => -1, 
+            'filter' => '', 
+            'modules' => array()
+        ));
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Timeline
+     * @subsection bx_timeline-page_blocks Page Blocks
+     * @subsubsection bx_timeline-get_block_view_profile get_block_view_profile
+     * 
+     * @code bx_srv('bx_timeline', 'get_block_view_profile', [...]); @endcode
+     * 
+     * Get Timeline View block for the Profile page.
+     * 
+     * @param $sProfileModule (optional) string value with profile based module name. Persons module is used by default.
+     * @param $iProfileContentId (optional) profile's content ID. If empty value is provided, an attempt to get it from GET/POST arrays will be performed.
+     * @param $iStart (optional) integer value with a page number. Is used in pagination.
+     * @param $iPerPage (optional) integer value with a number of items per page. Is used in pagination. 
+     * @param $sFilter (optional) string value with filter name.
+     * @param $aModules (optional) an array of modules from which the events should be displayed. All available modules are used by default.
+     * @param $iTimeline (optional) integer value determining whether the timeline should be displayed or not.
+     * @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 BxTimelineModule::serviceGetBlockViewProfile
+     */
+    /** 
+     * @ref bx_timeline-get_block_view_profile "get_block_view_profile"
+     */
+    public function serviceGetBlockViewProfile($sProfileModule = 'bx_persons', $iProfileContentId = 0, $iStart = -1, $iPerPage = -1, $sFilter = '', $aModules = array(), $iTimeline = -1)
+    {
+        return $this->_serviceGetBlockViewProfile($sProfileModule, $iProfileContentId, array(
+            'view' => BX_TIMELINE_VIEW_TIMELINE, 
+            'type' => BX_BASE_MOD_NTFS_TYPE_OWNER, 
+            'start' => $iStart, 
+            'per_page' => $iPerPage, 
+            'per_page_default' => $this->_oConfig->getPerPage('profile'), 
+            'timeline' => $iTimeline, 
+            'filter' => $sFilter, 
+            'modules' => $aModules
+        ));
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Timeline
+     * @subsection bx_timeline-page_blocks Page Blocks
+     * @subsubsection bx_timeline-get_block_view_profile_outline get_block_view_profile_outline
+     * 
+     * @code bx_srv('bx_timeline', 'get_block_view_profile_outline', [...]); @endcode
+     * 
+     * Get Outline View block for the Profile page.
+     * 
+     * @param $sProfileModule (optional) string value with profile based module name. Persons module is used by default.
+     * @param $iProfileContentId (optional) profile's content ID. If empty value is provided, an attempt to get it from GET/POST arrays will be performed.
+     * @param $iStart (optional) integer value with a page number. Is used in pagination.
+     * @param $iPerPage (optional) integer value with a number of items per page. Is used in pagination. 
+     * @param $sFilter (optional) string value with filter name.
+     * @param $aModules (optional) an array of modules from which the events should be displayed. All available modules are used by default.
+     * @param $iTimeline (optional) integer value determining whether the timeline should be displayed or not.
+     * @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 BxTimelineModule::serviceGetBlockViewProfileOutline
+     */
+    /** 
+     * @ref bx_timeline-get_block_view_profile_outline "get_block_view_profile_outline"
+     */
+    public function serviceGetBlockViewProfileOutline($sProfileModule = 'bx_persons', $iProfileContentId = 0, $iStart = -1, $iPerPage = -1, $sFilter = '', $aModules = array(), $iTimeline = -1)
+    {
+        return $this->_serviceGetBlockViewProfile($sProfileModule, $iProfileContentId, array(
+            'view' => BX_TIMELINE_VIEW_OUTLINE, 
+            'type' => BX_BASE_MOD_NTFS_TYPE_OWNER, 
+            'start' => $iStart, 
+            'per_page' => $iPerPage, 
+            'per_page_default' => $this->_oConfig->getPerPage('profile'), 
+            'timeline' => $iTimeline, 
+            'filter' => $sFilter, 
+            'modules' => $aModules
+        ));
+    }
+
+    public function serviceGetBlockViewsCustom($aParams = array())
+    {
+        $aParams = array_merge(array(
+            'view' => BX_TIMELINE_VIEW_TIMELINE, 
+            'type' => BX_BASE_MOD_NTFS_TYPE_PUBLIC,
+            'owner_id' => 0,
+        ), $aParams);
+
+    	return $this->_serviceGetBlockViews($aParams);
+    }
+
+    public function serviceGetBlockViewsTimeline($sType = BX_BASE_MOD_NTFS_TYPE_PUBLIC, $iProfileId = 0, $iStart = -1, $iPerPage = -1, $iTimeline = -1, $sFilter = '', $aModules = array())
+    {
+        return $this->_serviceGetBlockViews(array(
+            'view' => BX_TIMELINE_VIEW_TIMELINE, 
+            'type' => $sType,
+            'owner_id' => $iProfileId,
+            'start' => $iStart, 
+            'per_page' => $iPerPage, 
+            'per_page_default' => $this->_oConfig->getPerPage(), 
+            'timeline' => $iTimeline, 
+            'filter' => $sFilter, 
+            'modules' => $aModules
+        ));
+    }
+    
+    public function serviceGetBlockViewsOutline($sType = BX_BASE_MOD_NTFS_TYPE_PUBLIC, $iProfileId = 0, $iStart = -1, $iPerPage = -1, $iTimeline = -1, $sFilter = '', $aModules = array())
+    {
+        return $this->_serviceGetBlockViews(array(
+            'view' => BX_TIMELINE_VIEW_OUTLINE, 
+            'type' => $sType,
+            'owner_id' => $iProfileId,
+            'start' => $iStart, 
+            'per_page' => $iPerPage, 
+            'per_page_default' => $this->_oConfig->getPerPage(), 
+            'timeline' => $iTimeline, 
+            'filter' => $sFilter, 
+            'modules' => $aModules
+        ));
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Timeline
+     * @subsection bx_timeline-page_blocks Page Blocks
+     * @subsubsection bx_timeline-get_block_view_home get_block_view_home
+     * 
+     * @code bx_srv('bx_timeline', 'get_block_view_home', [...]); @endcode
+     * 
+     * Get Timeline View block for site's Home page.
+     * 
+     * @param $iProfileId (optional) profile ID. 0 should be used here.
+     * @param $iStart (optional) integer value with a page number. Is used in pagination.
+     * @param $iPerPage (optional) integer value with a number of items per page. Is used in pagination.
+     * @param $iTimeline (optional) integer value determining whether the timeline should be displayed or not. 
+     * @param $sFilter (optional) string value with filter name.
+     * @param $aModules (optional) an array of modules from which the events should be displayed. All available modules are used by default.
+     * @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 BxTimelineModule::serviceGetBlockViewHome
+     */
+    /** 
+     * @ref bx_timeline-get_block_view_home "get_block_view_home"
+     */
+    public function serviceGetBlockViewHome($iProfileId = 0, $iStart = -1, $iPerPage = -1, $iTimeline = -1, $sFilter = '', $aModules = array())
+    {
+        return $this->_serviceGetBlockViewHome(array(
+            'view' => BX_TIMELINE_VIEW_TIMELINE, 
+            'type' => BX_BASE_MOD_NTFS_TYPE_PUBLIC,
+            'owner_id' => $iProfileId,
+            'start' => $iStart, 
+            'per_page' => $iPerPage, 
+            'per_page_default' => $this->_oConfig->getPerPage('home'), 
+            'timeline' => $iTimeline, 
+            'filter' => $sFilter, 
+            'modules' => $aModules
+        ));
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Timeline
+     * @subsection bx_timeline-page_blocks Page Blocks
+     * @subsubsection bx_timeline-get_block_view_home_outline get_block_view_home_outline
+     * 
+     * @code bx_srv('bx_timeline', 'get_block_view_home_outline', [...]); @endcode
+     * 
+     * Get Outline View block for site's Home page.
+     * 
+     * @param $iProfileId (optional) profile ID. 0 should be used here.
+     * @param $iStart (optional) integer value with a page number. Is used in pagination.
+     * @param $iPerPage (optional) integer value with a number of items per page. Is used in pagination.
+     * @param $iTimeline (optional) integer value determining whether the timeline should be displayed or not. 
+     * @param $sFilter (optional) string value with filter name.
+     * @param $aModules (optional) an array of modules from which the events should be displayed. All available modules are used by default.
+     * @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 BxTimelineModule::serviceGetBlockViewHomeOutline
+     */
+    /** 
+     * @ref bx_timeline-get_block_view_home_outline "get_block_view_home_outline"
+     */
+    public function serviceGetBlockViewHomeOutline($iProfileId = 0, $iStart = -1, $iPerPage = -1, $iTimeline = -1, $sFilter = '', $aModules = array())
+    {
+        return $this->_serviceGetBlockViewHome(array(
+            'view' => BX_TIMELINE_VIEW_OUTLINE, 
+            'type' => BX_BASE_MOD_NTFS_TYPE_PUBLIC,
+            'owner_id' => $iProfileId,
+            'start' => $iStart, 
+            'per_page' => $iPerPage, 
+            'per_page_default' => $this->_oConfig->getPerPage('home'), 
+            'timeline' => $iTimeline, 
+            'filter' => $sFilter, 
+            'modules' => $aModules
+        ));
+    }
+
+	/**
+     * @page service Service Calls
+     * @section bx_timeline Timeline
+     * @subsection bx_timeline-page_blocks Page Blocks
+     * @subsubsection bx_timeline-get_block_view_hot get_block_view_hot
+     * 
+     * @code bx_srv('bx_timeline', 'get_block_view_hot', [...]); @endcode
+     * 
+     * Get Timeline View block with Hot public events.
+     * 
+     * @param $iProfileId (optional) profile ID. 0 should be used here.
+     * @param $iStart (optional) integer value with a page number. Is used in pagination.
+     * @param $iPerPage (optional) integer value with a number of items per page. Is used in pagination.
+     * @param $iTimeline (optional) integer value determining whether the timeline should be displayed or not. 
+     * @param $sFilter (optional) string value with filter name.
+     * @param $aModules (optional) an array of modules from which the events should be displayed. All available modules are used by default.
+     * @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 BxTimelineModule::serviceGetBlockViewHot
+     */
+    /** 
+     * @ref bx_timeline-get_block_view_hot "get_block_view_hot"
+     */
+    public function serviceGetBlockViewHot($iProfileId = 0, $iStart = -1, $iPerPage = -1, $iTimeline = -1, $sFilter = '', $aModules = array())
+    {
+        return $this->_serviceGetBlockViewHot(array(
+            'view' => BX_TIMELINE_VIEW_TIMELINE, 
+            'type' => BX_TIMELINE_TYPE_HOT,
+            'owner_id' => $iProfileId,
+            'start' => $iStart, 
+            'per_page' => $iPerPage, 
+            'per_page_default' => $this->_oConfig->getPerPage('home'), 
+            'timeline' => $iTimeline, 
+            'filter' => $sFilter, 
+            'modules' => $aModules
+        ));
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Timeline
+     * @subsection bx_timeline-page_blocks Page Blocks
+     * @subsubsection bx_timeline-get_block_view_hot_outline get_block_view_hot_outline
+     * 
+     * @code bx_srv('bx_timeline', 'get_block_view_hot_outline', [...]); @endcode
+     * 
+     * Get Outline View block with Hot public events.
+     * 
+     * @param $iProfileId (optional) profile ID. 0 should be used here.
+     * @param $iStart (optional) integer value with a page number. Is used in pagination.
+     * @param $iPerPage (optional) integer value with a number of items per page. Is used in pagination.
+     * @param $iTimeline (optional) integer value determining whether the timeline should be displayed or not. 
+     * @param $sFilter (optional) string value with filter name.
+     * @param $aModules (optional) an array of modules from which the events should be displayed. All available modules are used by default.
+     * @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 BxTimelineModule::serviceGetBlockViewHotOutline
+     */
+    /** 
+     * @ref bx_timeline-get_block_view_hot_outline "get_block_view_hot_outline"
+     */
+    public function serviceGetBlockViewHotOutline($iProfileId = 0, $iStart = -1, $iPerPage = -1, $iTimeline = -1, $sFilter = '', $aModules = array())
+    {
+        return $this->_serviceGetBlockViewHot(array(
+            'view' => BX_TIMELINE_VIEW_OUTLINE, 
+            'type' => BX_TIMELINE_TYPE_HOT, 
+            'owner_id' => $iProfileId, 
+            'start' => $iStart, 
+            'per_page' => $iPerPage, 
+            'per_page_default' => $this->_oConfig->getPerPage('home'), 
+            'timeline' => $iTimeline, 
+            'filter' => $sFilter, 
+            'modules' => $aModules
+        ));
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Timeline
+     * @subsection bx_timeline-page_blocks Page Blocks
+     * @subsubsection bx_timeline-get_block_view_account get_block_view_account
+     * 
+     * @code bx_srv('bx_timeline', 'get_block_view_account', [...]); @endcode
+     * 
+     * Get Timeline View block for the Dashboard page.
+     * 
+     * @param $iProfileId (optional) profile ID. 0 should be used here.
+     * @param $iStart (optional) integer value with a page number. Is used in pagination.
+     * @param $iPerPage (optional) integer value with a number of items per page. Is used in pagination.
+     * @param $iTimeline (optional) integer value determining whether the timeline should be displayed or not. 
+     * @param $sFilter (optional) string value with filter name.
+     * @param $aModules (optional) an array of modules from which the events should be displayed. All available modules are used by default.
+     * @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 BxTimelineModule::serviceGetBlockViewAccount
+     */
+    /** 
+     * @ref bx_timeline-get_block_view_account "get_block_view_account"
+     */
+    public function serviceGetBlockViewAccount($iProfileId = 0, $iStart = -1, $iPerPage = -1, $iTimeline = -1, $sFilter = '', $aModules = array())
+    {
+        if(!isLogged())
+            return '';
+
+        return $this->_serviceGetBlockViewByType(array(
+            'view' => BX_TIMELINE_VIEW_TIMELINE, 
+            'type' => BX_TIMELINE_TYPE_FEED, 
+            'owner_id' => $iProfileId, 
+            'start' => $iStart, 
+            'per_page' => $iPerPage, 
+            'per_page_default' => $this->_oConfig->getPerPage('account'), 
+            'timeline' => $iTimeline, 
+            'filter' => $sFilter, 
+            'modules' => $aModules
+        ));
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Timeline
+     * @subsection bx_timeline-page_blocks Page Blocks
+     * @subsubsection bx_timeline-get_block_view_account_outline get_block_view_account_outline
+     * 
+     * @code bx_srv('bx_timeline', 'get_block_view_account_outline', [...]); @endcode
+     * 
+     * Get Outline View block for the Dashboard page.
+     * 
+     * @param $iProfileId (optional) profile ID. 0 should be used here.
+     * @param $iStart (optional) integer value with a page number. Is used in pagination.
+     * @param $iPerPage (optional) integer value with a number of items per page. Is used in pagination.
+     * @param $iTimeline (optional) integer value determining whether the timeline should be displayed or not. 
+     * @param $sFilter (optional) string value with filter name.
+     * @param $aModules (optional) an array of modules from which the events should be displayed. All available modules are used by default.
+     * @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 BxTimelineModule::serviceGetBlockViewAccountOutline
+     */
+    /** 
+     * @ref bx_timeline-get_block_view_account_outline "get_block_view_account_outline"
+     */
+    public function serviceGetBlockViewAccountOutline($iProfileId = 0, $iStart = -1, $iPerPage = -1, $iTimeline = -1, $sFilter = '', $aModules = array())
+    {
+        if(!isLogged())
+            return '';
+
+        return $this->_serviceGetBlockViewByType(array(
+            'view' => BX_TIMELINE_VIEW_OUTLINE, 
+            'type' => BX_TIMELINE_TYPE_FEED,
+            'owner_id' => $iProfileId, 
+            'start' => $iStart, 
+            'per_page' => $iPerPage, 
+            'per_page_default' => $this->_oConfig->getPerPage('account'), 
+            'timeline' => $iTimeline, 
+            'filter' => $sFilter, 
+            'modules' => $aModules
+        ));
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Timeline
+     * @subsection bx_timeline-page_blocks Page Blocks
+     * @subsubsection bx_timeline-get_block_view_custom get_block_view_custom
+     * 
+     * @code bx_srv('bx_timeline', 'get_block_view_custom', [...]); @endcode
+     * 
+     * Get custom Timeline View block.
+     *
+     * @param $aParams (optional) an array with block parameneters.
+     * @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 BxTimelineModule::serviceGetBlockViewCustom
+     */
+    /** 
+     * @ref bx_timeline-get_block_view_custom "get_block_view_custom"
+     */
+    public function serviceGetBlockViewCustom($aParams = array())
+    {
+    	return $this->_serviceGetBlockViewByType($aParams);
+    }
+
+    public function serviceGetBlockMenuDb($aParams = array())
+    {
+        $aParams = $this->_prepareParams(array_merge($aParams, [
+            'name' => BX_TIMELINE_NAME_VIEWS_DB,
+            'view' => BX_TIMELINE_VIEW_TIMELINE,
+            'type' => BX_TIMELINE_TYPE_FEED,
+            'owner_id' => $this->getProfileId()
+        ]));
+
+        if(($sType = $this->_oConfig->getUserChoice('type')) !== false)
+            $aParams['type'] = $sType;
+
+        $sMenu = $this->_oConfig->getObject('menu_feeds');
+        if(isset($aParams['menu_feeds'])) {
+            $sMenu = $aParams['menu_feeds'];
+            unset($aParams['menu_feeds']);
+        }
+        $oMenu = BxDolMenu::getObjectInstance($sMenu);
+        if(!$oMenu)
+            return '';
+
+        $sSelectedModule = $this->getName();
+        $sSelectedName = $aParams['type'];
+        if(($aModule = $this->_oDb->getModuleByName($aParams['type']))) {
+            $sSelectedModule = $aModule['name'];
+            $sSelectedName = $aModule['uri'];
+        }
+
+        $oMenu->setSelected($sSelectedModule, $sSelectedName);
+        $oMenu->setBrowseParams($aParams);
+        return $oMenu->getCode();
+    }
+
+    public function serviceGetBlockViewsDb($aParams = [])
+    {
+        if(!isset($aParams['viewer_id']))
+            $aParams['viewer_id'] = $this->getUserId();
+
+        if(!isset($aParams['owner_id']))
+            $aParams['owner_id'] = $this->getUserId();
+
+        if(!isset($aParams['type']) && ($sType = $this->_oConfig->getUserChoice('type', $aParams['viewer_id'])) !== false)
+            $aParams['type'] = $sType;
+
+        $aParams = $this->_prepareParams(array_merge([
+            'name' => BX_TIMELINE_NAME_VIEWS_DB,
+            'view' => BX_TIMELINE_VIEW_TIMELINE,
+            'type' => BX_TIMELINE_TYPE_FEED,
+        ], $aParams));
+
+        $this->_iOwnerId = $aParams['owner_id'];
+        return $this->_oTemplate->getViewsDbBlock($aParams);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Timeline
+     * @subsection bx_timeline-page_blocks Page Blocks
+     * @subsubsection bx_timeline-get_block_item get_block_item
+     * 
+     * @code bx_srv('bx_timeline', 'get_block_item', [...]); @endcode
+     * 
+     * Get View Item block.
+     * 
+     * @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 BxTimelineModule::serviceGetBlockItem
+     */
+    /** 
+     * @ref bx_timeline-get_block_item "get_block_item"
+     */
+    public function serviceGetBlockItem()
+    {
+        $iItemId = bx_process_input(bx_get('id'), BX_DATA_INT);
+        if(!$iItemId)
+            return array();
+
+        $aParams = $this->_prepareParams(array(
+            'view' => BX_TIMELINE_VIEW_ITEM, 
+            'type' => BX_TIMELINE_TYPE_ITEM
+        ));
+
+        $aItemData = $this->getItemData($iItemId, $aParams);
+        return $this->_oTemplate->getItemBlock($aItemData, $aParams);
+    }
+    
+    public function serviceGetBlockItemContent()
+    {
+        $iItemId = bx_process_input(bx_get('id'), BX_DATA_INT);
+        $sMode = bx_process_input(bx_get('mode'));
+        if(!$iItemId || !$sMode)
+            return '';
+            
+        return $this->_oTemplate->getItemBlockContent($iItemId, $sMode);
+    }
+    
+    public function serviceGetBlockItemInfo()
+    {
+        $iItemId = bx_process_input(bx_get('id'), BX_DATA_INT);
+        if(!$iItemId)
+            return '';
+
+        return $this->_oTemplate->getItemBlockInfo($iItemId);
+    }
+
+    public function serviceGetBlockItemComments()
+    {
+        $iItemId = bx_process_input(bx_get('id'), BX_DATA_INT);
+        if(!$iItemId)
+            return '';
+
+        return $this->_oTemplate->getItemBlockComments($iItemId);
+    }
+
+    public function serviceGetBlockMuted($iProfileId = 0)
+    {
+        if(!isLogged())
+            return MsgBox(_t('_Access denied'));
+
+        if($iProfileId == 0)
+            $iProfileId = $this->_iProfileId;
+
+        $oGrid = BxDolGrid::getObjectInstance($this->_oConfig->getObject('grid_mute'));
+        if(!$oGrid)
+            return MsgBox('_Empty');
+
+        $oGrid->setProfile($iProfileId);
+        return $oGrid->getCode();
+    }
+
+    public function serviceGetPost($mixedEvent, $aParams = array())
+    {
+        if(!empty($mixedEvent) && !is_array($mixedEvent))
+            $mixedEvent = $this->_oDb->getContentInfoById((int)$mixedEvent);
+
+        if(empty($mixedEvent) || !is_array($mixedEvent))
+            return '';
+
+        $aParams = $this->_prepareParams(array_merge(array(
+            'view' => BX_TIMELINE_VIEW_ITEM, 
+            'type' => BX_TIMELINE_TYPE_ITEM
+        ), $aParams));
+
+        return $this->_oTemplate->getPost($mixedEvent, $aParams);
+    }
+
+    public function serviceGetTimelineRepostAllowedView($aEvent)
+    {
+        return isset($aEvent['content']['allowed_view']) ? $aEvent['content']['allowed_view'] : CHECK_ACTION_RESULT_ALLOWED;
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Timeline
+     * @subsection bx_timeline-integration_notifications Integration with Notifications
+     * @subsubsection bx_timeline-get_notifications_data get_notifications_data
+     * 
+     * @code bx_srv('bx_timeline', 'get_notifications_data', [...]); @endcode
+     * 
+     * Data for Notifications module.
+     * 
+     * @return an array with special format.
+     * 
+     * @see BxTimelineModule::serviceGetNotificationsData
+     */
+    /** 
+     * @ref bx_timeline-get_notifications_data "get_notifications_data"
+     */
+    public function serviceGetNotificationsData()
+    {
+    	$sModule = $this->_aModule['name'];
+
+        return array(
+            'handlers' => array(
+                array('group' => $sModule . '_object', 'type' => 'insert', 'alert_unit' => $sModule, 'alert_action' => 'post_common', 'module_name' => $sModule, 'module_method' => 'get_notifications_post', 'module_class' => 'Module'),
+                array('group' => $sModule . '_object', 'type' => 'delete', 'alert_unit' => $sModule, 'alert_action' => 'delete'),
+
+                array('group' => $sModule . '_object_publish_failed', 'type' => 'insert', 'alert_unit' => $sModule, 'alert_action' => 'publish_failed', 'module_name' => $sModule, 'module_method' => 'get_notifications_post_publish_failed', 'module_class' => 'Module'),
+                array('group' => $sModule . '_object_publish_succeeded', 'type' => 'insert', 'alert_unit' => $sModule, 'alert_action' => 'publish_succeeded', 'module_name' => $sModule, 'module_method' => 'get_notifications_post_publish_succeeded', 'module_class' => 'Module'),
+
+                array('group' => $sModule . '_repost', 'type' => 'insert', 'alert_unit' => $sModule, 'alert_action' => 'repost', 'module_name' => $sModule, 'module_method' => 'get_notifications_repost', 'module_class' => 'Module'),
+                array('group' => $sModule . '_repost', 'type' => 'delete', 'alert_unit' => $sModule, 'alert_action' => 'delete_repost'),
+
+                array('group' => $sModule . '_comment', 'type' => 'insert', 'alert_unit' => $sModule, 'alert_action' => 'commentPost', 'module_name' => $sModule, 'module_method' => 'get_notifications_comment', 'module_class' => 'Module'),
+                array('group' => $sModule . '_comment', 'type' => 'delete', 'alert_unit' => $sModule, 'alert_action' => 'commentRemoved'),
+
+                array('group' => $sModule . '_reply', 'type' => 'insert', 'alert_unit' => $sModule, 'alert_action' => 'replyPost', 'module_name' => $sModule, 'module_method' => 'get_notifications_reply', 'module_class' => 'Module'),
+                array('group' => $sModule . '_reply', 'type' => 'delete', 'alert_unit' => $sModule, 'alert_action' => 'replyRemoved'),
+
+                array('group' => $sModule . '_vote', 'type' => 'insert', 'alert_unit' => $sModule, 'alert_action' => 'doVote', 'module_name' => $sModule, 'module_method' => 'get_notifications_vote', 'module_class' => 'Module'),
+                array('group' => $sModule . '_vote', 'type' => 'delete', 'alert_unit' => $sModule, 'alert_action' => 'undoVote'),
+
+                array('group' => $sModule . '_reaction', 'type' => 'insert', 'alert_unit' => $sModule . '_reactions', 'alert_action' => 'doVote', 'module_name' => $sModule, 'module_method' => 'get_notifications_reaction', 'module_class' => 'Module'),
+                array('group' => $sModule . '_reaction', 'type' => 'delete', 'alert_unit' => $sModule . '_reactions', 'alert_action' => 'undoVote'),
+
+                array('group' => $sModule . '_score_up', 'type' => 'insert', 'alert_unit' => $sModule, 'alert_action' => 'doVoteUp', 'module_name' => $sModule, 'module_method' => 'get_notifications_score_up', 'module_class' => 'Module'),
+
+                array('group' => $sModule . '_score_down', 'type' => 'insert', 'alert_unit' => $sModule, 'alert_action' => 'doVoteDown', 'module_name' => $sModule, 'module_method' => 'get_notifications_score_down', 'module_class' => 'Module'),
+            ),
+            'settings' => array(
+                array('group' => 'content', 'unit' => $sModule, 'action' => 'post_common', 'types' => array('personal', 'follow_member', 'follow_context')),
+                array('group' => 'content', 'unit' => $sModule, 'action' => 'publish_failed', 'types' => array('personal')),
+                array('group' => 'content', 'unit' => $sModule, 'action' => 'publish_succeeded', 'types' => array('personal')),
+                array('group' => 'content', 'unit' => $sModule, 'action' => 'repost', 'types' => array('personal', 'follow_member', 'follow_context')),
+                array('group' => 'comment', 'unit' => $sModule, 'action' => 'commentPost', 'types' => array('personal', 'follow_member', 'follow_context')),
+                array('group' => 'reply', 'unit' => $sModule, 'action' => 'replyPost', 'types' => array('personal')),
+                array('group' => 'vote', 'unit' => $sModule, 'action' => 'doVote', 'types' => array('personal', 'follow_member', 'follow_context')),
+                array('group' => 'vote', 'unit' => $sModule . '_reactions', 'action' => 'doVote', 'types' => array('personal', 'follow_member', 'follow_context')),
+                array('group' => 'score_up', 'unit' => $sModule, 'action' => 'doVoteUp', 'types' => array('personal', 'follow_member', 'follow_context')),
+                array('group' => 'score_down', 'unit' => $sModule, 'action' => 'doVoteDown', 'types' => array('personal', 'follow_member', 'follow_context'))
+            ),
+            'alerts' => array(
+                array('unit' => $sModule, 'action' => 'post_common'),
+                array('unit' => $sModule, 'action' => 'publish_failed'),
+                array('unit' => $sModule, 'action' => 'publish_succeeded'),
+                array('unit' => $sModule, 'action' => 'delete'),
+
+                array('unit' => $sModule, 'action' => 'repost'),
+                array('unit' => $sModule, 'action' => 'delete_repost'),
+                
+                array('unit' => $sModule, 'action' => 'commentPost'),
+                array('unit' => $sModule, 'action' => 'commentRemoved'),
+
+                array('unit' => $sModule, 'action' => 'replyPost'),
+                array('unit' => $sModule, 'action' => 'replyRemoved'),
+
+                array('unit' => $sModule, 'action' => 'doVote'),
+                array('unit' => $sModule, 'action' => 'undoVote'),
+
+                array('unit' => $sModule . '_reactions', 'action' => 'doVote'),
+                array('unit' => $sModule . '_reactions', 'action' => 'undoVote'),
+
+                array('unit' => $sModule, 'action' => 'doVoteUp'),
+                array('unit' => $sModule, 'action' => 'doVoteDown'),
+            )
+        );
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Timeline
+     * @subsection bx_timeline-integration_notifications Integration with Notifications
+     * @subsubsection bx_timeline-get_notifications_repost get_notifications_repost
+     * 
+     * @code bx_srv('bx_timeline', 'get_notifications_repost', [...]); @endcode
+     * 
+     * Get data for Repost event to display in Notifications module.
+     * 
+     * @param $aEvent an array with event description.
+     * @return an array with special format.
+     * 
+     * @see BxTimelineModule::serviceGetNotificationsRepost
+     */
+    /** 
+     * @ref bx_timeline-get_notifications_repost "get_notifications_repost"
+     */
+    public function serviceGetNotificationsRepost($aEvent)
+    {
+        $aResult = $this->serviceGetNotificationsPost($aEvent);
+        $aResult['lang_key'] = '_bx_timeline_txt_object_reposted';
+
+        return $aResult;
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Timeline
+     * @subsection bx_timeline-integration_notifications Integration with Notifications
+     * @subsubsection bx_timeline-get_notifications_post get_notifications_post
+     * 
+     * @code bx_srv('bx_timeline', 'get_notifications_post', [...]); @endcode
+     * 
+     * Get data for Post event to display in Notifications module.
+     * 
+     * @param $aEvent an array with event description.
+     * @return an array with special format.
+     * 
+     * @see BxTimelineModule::serviceGetNotificationsPost
+     */
+    /** 
+     * @ref bx_timeline-get_notifications_post "get_notifications_post"
+     */
+    public function serviceGetNotificationsPost($aEvent)
+    {
+    	$CNF = &$this->_oConfig->CNF;
+
+        $iContent = (int)$aEvent['object_id'];
+        $aContent = $this->_oDb->getEvents(array('browse' => 'id', 'value' => $iContent));
+        if(empty($aContent) || !is_array($aContent))
+            return array();
+
+        if($this->_oConfig->isSystem($aContent['type'], $aContent['action']))
+            $iEntryAuthor = (int)$aContent['owner_id'];
+        else
+            $iEntryAuthor = (int)$aContent['object_id'];
+
+        $sEntryCaption = call_user_func_array(array($this->_oConfig, 'getTitleShort'), !empty($aContent['title']) ? array($aContent['title']) : array($aContent['description'], $aContent['object_id']));
+
+        return array(
+            'entry_sample' => $CNF['T']['txt_sample_single_ext'],
+            'entry_url' => '{bx_url_root}' . $this->_oConfig->getItemViewUrl($aContent, false),
+            'entry_caption' => $sEntryCaption,
+            'entry_author' => $iEntryAuthor,
+            'lang_key' => '' //may be empty or not specified. In this case the default one from Notification module will be used.
+        );
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Timeline
+     * @subsection bx_timeline-integration_notifications Integration with Notifications
+     * @subsubsection bx_timeline-get_notifications_comment get_notifications_comment
+     * 
+     * @code bx_srv('bx_timeline', 'get_notifications_comment', [...]); @endcode
+     * 
+     * Get data for Post Comment event to display in Notifications module.
+     * 
+     * @param $aEvent an array with event description.
+     * @return an array with special format.
+     * 
+     * @see BxTimelineModule::serviceGetNotificationsComment
+     */
+    /** 
+     * @ref bx_timeline-get_notifications_comment "get_notifications_comment"
+     */
+    public function serviceGetNotificationsComment($aEvent)
+    {
+    	$CNF = &$this->_oConfig->CNF;
+
+        $iContent = (int)$aEvent['object_id'];
+        $aContent = $this->_oDb->getEvents(array('browse' => 'id', 'value' => $iContent));
+        if(empty($aContent) || !is_array($aContent))
+            return array();
+
+        $oComment = BxDolCmts::getObjectInstance($CNF['OBJECT_COMMENTS'], $iContent);
+        if(!$oComment || !$oComment->isEnabled())
+            return array();
+
+        $sEntryCaption = call_user_func_array(array($this->_oConfig, 'getTitleShort'), !empty($aContent['title']) ? array($aContent['title']) : array($aContent['description'], $aContent['object_id']));
+
+        return array(
+            'entry_sample' => $CNF['T']['txt_sample_single'],
+            'entry_url' => '{bx_url_root}' . $this->_oConfig->getItemViewUrl($aContent, false),
+            'entry_caption' => $sEntryCaption,
+            'entry_author' => $aContent['owner_id'],
+            'subentry_sample' => $CNF['T']['txt_sample_comment_single'],
+            'subentry_url' => '{bx_url_root}' . $oComment->getViewUrl((int)$aEvent['subobject_id'], false),
+            'lang_key' => '', //may be empty or not specified. In this case the default one from Notification module will be used.
+        );
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Timeline
+     * @subsection bx_timeline-integration_notifications Integration with Notifications
+     * @subsubsection bx_timeline-get_notifications_reply get_notifications_reply
+     * 
+     * @code bx_srv('bx_timeline', 'get_notifications_reply', [...]); @endcode
+     * 
+     * Get data for Reply to Comment event to display in Notifications module.
+     * 
+     * @param $aEvent an array with event description.
+     * @return an array with special format.
+     * 
+     * @see BxTimelineModule::serviceGetNotificationsReply
+     */
+    /** 
+     * @ref bx_timeline-get_notifications_reply "get_notifications_reply"
+     */
+    public function serviceGetNotificationsReply($aEvent)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $oComment = BxDolCmts::getObjectInstance($CNF['OBJECT_COMMENTS'], 0, false);
+        if(!$oComment || !$oComment->isEnabled())
+            return array();
+
+        $iParentId = (int)$aEvent['object_id'];
+        $aParentInfo = $oComment->getQueryObject()->getCommentsBy(array('type' => 'id', 'id' => $iParentId));
+        if(empty($aParentInfo) || !is_array($aParentInfo))
+            return array();
+
+        $iObjectId = (int)$aParentInfo['cmt_object_id'];
+        $oComment->init($iObjectId);
+
+        return array(
+            'object_id' => $iObjectId,
+            'entry_sample' => '_cmt_txt_sample_comment_single',
+            'entry_url' => '{bx_url_root}' . $oComment->getViewUrl($iParentId, false),
+            'entry_caption' => strmaxtextlen($aParentInfo['cmt_text'], 20, '...'),
+            'entry_author' => (int)$aParentInfo['cmt_author_id'],
+            'subentry_sample' => '_cmt_txt_sample_reply_to',
+            'subentry_url' => '{bx_url_root}' . $oComment->getViewUrl((int)$aEvent['subobject_id'], false),
+            'lang_key' => '', //may be empty or not specified. In this case the default one from Notification module will be used.
+        );
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Timeline
+     * @subsection bx_timeline-integration_notifications Integration with Notifications
+     * @subsubsection bx_timeline-get_notifications_vote get_notifications_vote
+     * 
+     * @code bx_srv('bx_timeline', 'get_notifications_vote', [...]); @endcode
+     * 
+     * Get data for Vote event to display in Notifications module.
+     * 
+     * @param $aEvent an array with event description.
+     * @return an array with special format.
+     * 
+     * @see BxTimelineModule::serviceGetNotificationsVote
+     */
+    /** 
+     * @ref bx_timeline-get_notifications_vote "get_notifications_vote"
+     */
+    public function serviceGetNotificationsVote($aEvent)
+    {
+    	$CNF = &$this->_oConfig->CNF;
+
+        $iContent = (int)$aEvent['object_id'];
+        $aContent = $this->_oDb->getEvents(array('browse' => 'id', 'value' => $iContent));
+        if(empty($aContent) || !is_array($aContent))
+            return array();
+
+        $oVote = BxDolVote::getObjectInstance($CNF['OBJECT_VOTES'], $iContent);
+        if(!$oVote || !$oVote->isEnabled())
+            return array();
+
+        $sEntryCaption = call_user_func_array(array($this->_oConfig, 'getTitleShort'), !empty($aContent['title']) ? array($aContent['title']) : array($aContent['description'], $aContent['object_id']));
+
+        return array(
+            'entry_sample' => $CNF['T']['txt_sample_single'],
+            'entry_url' => '{bx_url_root}' . $this->_oConfig->getItemViewUrl($aContent, false),
+            'entry_caption' => $sEntryCaption,
+            'entry_author' => $aContent['owner_id'],
+            'subentry_sample' => $CNF['T']['txt_sample_vote_single'],
+            'lang_key' => '', //may be empty or not specified. In this case the default one from Notification module will be used.
+        );
+    }
+
+    /**
+     * Entry post vote for Notifications module
+     */
+    public function serviceGetNotificationsReaction($aEvent)
+    {
+    	$CNF = &$this->_oConfig->CNF;
+
+    	$iContent = (int)$aEvent['object_id'];
+        $aContent = $this->_oDb->getEvents(array('browse' => 'id', 'value' => $iContent));
+        if(empty($aContent) || !is_array($aContent))
+            return array();
+
+        $oReaction = BxDolVote::getObjectInstance($CNF['OBJECT_REACTIONS'], $iContent);
+        if(!$oReaction || !$oReaction->isEnabled())
+            return array();
+
+        $aSubentry = $oReaction->getTrackBy(array('type' => 'id', 'id' => (int)$aEvent['subobject_id']));
+        if(empty($aSubentry) || !is_array($aSubentry))
+            return array();
+
+        $aSubentrySampleParams = array();
+        $aReaction = $oReaction->getReaction($aSubentry['reaction']);
+        if(!empty($aReaction['title']))
+            $aSubentrySampleParams[] = $aReaction['title'];
+        else
+            $aSubentrySampleParams[] = '_undefined';
+
+        $sEntryCaption = call_user_func_array(array($this->_oConfig, 'getTitleShort'), !empty($aContent['title']) ? array($aContent['title']) : array($aContent['description'], $aContent['object_id']));
+
+        return array(
+            'entry_sample' => $CNF['T']['txt_sample_single'],
+            'entry_url' => '{bx_url_root}' . $this->_oConfig->getItemViewUrl($aContent, false),
+            'entry_caption' => $sEntryCaption,
+            'entry_author' => $aContent['owner_id'],
+            'subentry_sample' => $CNF['T']['txt_sample_reaction_single'],
+            'subentry_sample_params' => $aSubentrySampleParams,
+            'lang_key' => '', //may be empty or not specified. In this case the default one from Notification module will be used.
+        );
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Timeline
+     * @subsection bx_timeline-integration_notifications Integration with Notifications
+     * @subsubsection bx_timeline-get_notifications_score_up get_notifications_score_up
+     * 
+     * @code bx_srv('bx_timeline', 'get_notifications_score_up', [...]); @endcode
+     * 
+     * Get data for Score Up Vote event to display in Notifications module.
+     * 
+     * @param $aEvent an array with event description.
+     * @return an array with special format.
+     * 
+     * @see BxTimelineModule::serviceGetNotificationsScoreUp
+     */
+    /** 
+     * @ref bx_timeline-get_notifications_score_up "get_notifications_score_up"
+     */
+    public function serviceGetNotificationsScoreUp($aEvent)
+    {
+    	return $this->_serviceGetNotificationsScore('up', $aEvent);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Timeline
+     * @subsection bx_timeline-integration_notifications Integration with Notifications
+     * @subsubsection bx_timeline-get_notifications_score_down get_notifications_score_down
+     * 
+     * @code bx_srv('bx_timeline', 'get_notifications_score_down', [...]); @endcode
+     * 
+     * Get data for Score Down Vote event to display in Notifications module.
+     * 
+     * @param $aEvent an array with event description.
+     * @return an array with special format.
+     * 
+     * @see BxTimelineModule::serviceGetNotificationsScoreDown
+     */
+    /** 
+     * @ref bx_timeline-get_notifications_score_down "get_notifications_score_down"
+     */
+    public function serviceGetNotificationsScoreDown($aEvent)
+    {
+    	return $this->_serviceGetNotificationsScore('down', $aEvent);
+    }
+
+
+    protected function _serviceGetNotificationsScore($sType, $aEvent)
+    {
+    	$CNF = &$this->_oConfig->CNF;
+
+        $iContent = (int)$aEvent['object_id'];
+        $aContent = $this->_oDb->getEvents(array('browse' => 'id', 'value' => $iContent));
+        if(empty($aContent) || !is_array($aContent))
+            return array();
+
+        $oScore = BxDolScore::getObjectInstance($CNF['OBJECT_SCORES'], $iContent);
+        if(!$oScore || !$oScore->isEnabled())
+            return array();
+
+        $sEntryCaption = call_user_func_array(array($this->_oConfig, 'getTitleShort'), !empty($aContent['title']) ? array($aContent['title']) : array($aContent['description'], $aContent['object_id']));
+
+        return array(
+            'entry_sample' => $CNF['T']['txt_sample_single'],
+            'entry_url' => '{bx_url_root}' . $this->_oConfig->getItemViewUrl($aContent, false),
+            'entry_caption' => $sEntryCaption,
+            'entry_author' => $aContent['owner_id'],
+            'subentry_sample' => $CNF['T']['txt_sample_score_' . $sType . '_single'],
+            'lang_key' => '', //may be empty or not specified. In this case the default one from Notification module will be used.
+        );
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Timeline
+     * @subsection bx_timeline-repost Repost
+     * @subsubsection bx_timeline-get_repost_element_block get_repost_element_block
+     * 
+     * @code bx_srv('bx_timeline', 'get_repost_element_block', [...]); @endcode
+     * 
+     * Get repost element for content based modules.
+     * 
+     * @param $iOwnerId integer value with owner profile ID.
+     * @param $sType string value with type (module name). 
+     * @param $sAction string value with action (module action). 
+     * @param $iObjectId integer value with object ID to be reposted. 
+     * @param $aParams (optional) an array with additional params.
+     * @return HTML string with repost element to display on the site, all necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
+     * 
+     * @see BxTimelineModule::serviceGetRepostElementBlock
+     */
+    /** 
+     * @ref bx_timeline-get_repost_element_block "get_repost_element_block"
+     */
+    public function serviceGetRepostElementBlock($iOwnerId, $sType, $sAction, $iObjectId, $aParams = [])
+    {
+    	if(!$this->isEnabled())
+            return '';
+
+        $aParams = array_merge($this->_oConfig->getRepostDefaults(), $aParams);
+        return $this->_oTemplate->getRepostElement($iOwnerId, $sType, $sAction, $iObjectId, $aParams);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Timeline
+     * @subsection bx_timeline-repost Repost
+     * @subsubsection bx_timeline-get_repost_counter get_repost_counter
+     * 
+     * @code bx_srv('bx_timeline', 'get_repost_counter', [...]); @endcode
+     * 
+     * Get repost counter.
+     * 
+     * @param $sType string value with type (module name). 
+     * @param $sAction string value with action (module action). 
+     * @param $iObjectId integer value with object ID to be reposted. 
+     * @return HTML string with repost counter to display on the site, all necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
+     * 
+     * @see BxTimelineModule::serviceGetRepostCounter
+     */
+    /** 
+     * @ref bx_timeline-get_repost_counter "get_repost_counter"
+     */
+    public function serviceGetRepostCounter($sType, $sAction, $iObjectId, $aParams = [])
+    {
+    	if(!$this->isEnabled())
+            return '';
+
+        $aReposted = $this->_oDb->getReposted($sType, $sAction, $iObjectId);
+
+        $aParams = array_merge($this->_oConfig->getRepostDefaults(), $aParams);
+        return $this->_oTemplate->getRepostCounter($aReposted, $aParams);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Timeline
+     * @subsection bx_timeline-repost Repost
+     * @subsubsection bx_timeline-get_repost_js_script get_repost_js_script
+     * 
+     * @code bx_srv('bx_timeline', 'get_repost_js_script', [...]); @endcode
+     * 
+     * Get repost JavaScript code.
+     * 
+     * @return HTML string with JavaScript code to display on the site, all necessary CSS and JS files are automatically added to the HEAD section of the site HTML.
+     * 
+     * @see BxTimelineModule::serviceGetRepostJsScript
+     */
+    /** 
+     * @ref bx_timeline-get_repost_js_script "get_repost_js_script"
+     */
+    public function serviceGetRepostJsScript()
+    {
+    	if(!$this->isEnabled())
+    		return '';
+
+        return $this->_oTemplate->getRepostJsScript();
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Timeline
+     * @subsection bx_timeline-repost Repost
+     * @subsubsection bx_timeline-get_repost_js_click get_repost_js_click
+     * 
+     * @code bx_srv('bx_timeline', 'get_repost_js_click', [...]); @endcode
+     * 
+     * Get repost JavaScript code for OnClick event.
+     * 
+     * @param $iOwnerId integer value with owner profile ID.
+     * @param $sType string value with type (module name). 
+     * @param $sAction string value with action (module action). 
+     * @param $iObjectId integer value with object ID to be reposted. 
+     * @return HTML string with JavaScript code to display in OnClick events of HTML elements.
+     * 
+     * @see BxTimelineModule::serviceGetRepostJsClick
+     */
+    /** 
+     * @ref bx_timeline-get_repost_js_click "get_repost_js_click"
+     */
+    public function serviceGetRepostJsClick($iOwnerId, $sType, $sAction, $iObjectId)
+    {
+    	if(!$this->isEnabled())
+            return '';
+
+        return $this->_oTemplate->getRepostJsClick($iOwnerId, $sType, $sAction, $iObjectId);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Timeline
+     * @subsection bx_timeline-repost Repost
+     * @subsubsection bx_timeline-get_repost_with_js_click get_repost_with_js_click
+     * 
+     * @code bx_srv('bx_timeline', 'get_repost_with_js_click', [...]); @endcode
+     * 
+     * Get 'repost with' JavaScript code for OnClick event.
+     * 
+     * @param $iReposterId integer value with reposter profile ID.
+     * @param $sType string value with type (module name). 
+     * @param $sAction string value with action (module action). 
+     * @param $iObjectId integer value with object ID to be reposted. 
+     * @return HTML string with JavaScript code to display in OnClick events of HTML elements.
+     * 
+     * @see BxTimelineModule::serviceGetRepostWithJsClick
+     */
+    /** 
+     * @ref bx_timeline-get_repost_with_js_click "get_repost_with_js_click"
+     */
+    public function serviceGetRepostWithJsClick($iReposterId, $sType, $sAction, $iObjectId)
+    {
+    	if(!$this->isEnabled())
+            return '';
+
+        return $this->_oTemplate->getRepostWithJsClick($iReposterId, $sType, $sAction, $iObjectId);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Timeline
+     * @subsection bx_timeline-repost Repost
+     * @subsubsection bx_timeline-get_repost_to_js_click get_repost_to_js_click
+     * 
+     * @code bx_srv('bx_timeline', 'get_repost_to_js_click', [...]); @endcode
+     * 
+     * Get 'repost to' JavaScript code for OnClick event.
+     * 
+     * @param $iReposterId integer value with reposter profile ID.
+     * @param $sType string value with type (module name). 
+     * @param $sAction string value with action (module action). 
+     * @param $iObjectId integer value with object ID to be reposted. 
+     * @return HTML string with JavaScript code to display in OnClick events of HTML elements.
+     * 
+     * @see BxTimelineModule::serviceGetRepostToJsClick
+     */
+    /** 
+     * @ref bx_timeline-get_repost_to_js_click "get_repost_to_js_click"
+     */
+    public function serviceGetRepostToJsClick($iReposterId, $sType, $sAction, $iObjectId)
+    {
+    	if(!$this->isEnabled())
+            return '';
+
+        return $this->_oTemplate->getRepostToJsClick($iReposterId, $sType, $sAction, $iObjectId);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Timeline
+     * @subsection bx_timeline-repost Repost
+     * @subsubsection bx_timeline-repost repost
+     * 
+     * @code bx_srv('bx_timeline', 'repost', [...]); @endcode
+     * 
+     * Perform repost action.
+     * 
+     * @param $iAuthorId integer value with performer profile ID.
+     * @param $iOwnerId integer value with repost event owner profile ID.
+     * @param $sType string value with type (module name). 
+     * @param $sAction string value with action (module action). 
+     * @param $iObjectId integer value with object ID to be reposted. 
+     * @parem $bForce boolean value force reposting without ACL check.
+     * @return an array with error (code and message) or integer with newly created repost event ID.
+     * 
+     * @see BxTimelineModule::serviceRepost
+     */
+    /** 
+     * @ref bx_timeline-repost "repost"
+     */
+    public function serviceRepost($iAuthorId, $iOwnerId, $sType, $sAction, $iObjectId, $bForce = false)
+    {
+        return $this->repost($iAuthorId, $iOwnerId, $sType, $sAction, $iObjectId, false, $bForce);
+    }
+    
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Timeline
+     * @subsection bx_timeline-repost Repost
+     * @subsubsection bx_timeline-repost_with repost_with
+     * 
+     * @code bx_srv('bx_timeline', 'repost_with', [...]); @endcode
+     * 
+     * Perform repost action passing additional data.
+     * 
+     * @param $iAuthorId integer value with performer profile ID.
+     * @param $iOwnerId integer value with repost event owner profile ID.
+     * @param $sType string value with type (module name). 
+     * @param $sAction string value with action (module action). 
+     * @param $iObjectId integer value with object ID to be reposted. 
+     * @param $mixedData array with some data to attach to repost event or false. 
+     * @parem $bForce boolean value force reposting without ACL check.
+     * @return an array with error (code and message) or integer with newly created repost event ID.
+     * 
+     * @see BxTimelineModule::serviceRepostWith
+     */
+    /** 
+     * @ref bx_timeline-repost_with "repost_with"
+     */
+    public function serviceRepostWith($iAuthorId, $iOwnerId, $sType, $sAction, $iObjectId, $mixedData = false, $bForce = false)
+    {
+        return $this->repost($iAuthorId, $iOwnerId, $sType, $sAction, $iObjectId, $mixedData, $bForce);
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Timeline
+     * @subsection bx_timeline-repost Repost
+     * @subsubsection bx_timeline-repost_by_id repost_by_id
+     * 
+     * @code bx_srv('bx_timeline', 'repost_by_id', [...]); @endcode
+     * 
+     * Perform repost action by Timeline event ID.
+     * 
+     * @param $iAuthorId integer value with performer profile ID.
+     * @param $iOwnerId integer value with repost event owner profile ID.
+     * @param $iEventId integer value with event ID which will be reposted.
+     * @parem $bForce boolean value force reposting without ACL check.
+     * @return an array with error (code and message) or integer with newly created repost event ID.
+     * 
+     * @see BxTimelineModule::serviceRepostById
+     */
+    /** 
+     * @ref bx_timeline-repost_by_id "repost_by_id"
+     */
+    public function serviceRepostById($iAuthorId, $iOwnerId, $iEventId, $bForce = false)
+    {
+        $aEvent = $this->_oDb->getEntriesBy(array('type' => 'id', 'id' => $iEventId));
+        if(empty($aEvent) || !is_array($aEvent))
+            return array('code' => 1, 'message' => _t('_bx_timeline_txt_err_cannot_repost'));
+
+        $sType = $aEvent['type'];
+        $sAction = $aEvent['action'];
+        $iObjectId = $this->_oConfig->isSystem($sType, $sAction) ? $aEvent['object_id'] : $aEvent['id'];
+
+        $sCommonPrefix = $this->_oConfig->getPrefix('common_post');
+        if(str_replace($sCommonPrefix, '', $sType) == BX_TIMELINE_PARSE_TYPE_REPOST) {
+            $aReposted = $this->_oDb->getReposted($sType, $sAction, $iObjectId);
+            if(empty($aReposted) || !is_array($aReposted))
+                return array('code' => 1, 'message' => _t('_bx_timeline_txt_err_cannot_repost'));
+
+            $aRepostedData = unserialize($aEvent['content']);
+
+            $sType = $aRepostedData['type'];
+            $sAction = $aRepostedData['action'];
+            $iObjectId = $aRepostedData['object_id'];
+        }
+
+        return $this->repost($iAuthorId, $iOwnerId, $sType, $sAction, $iObjectId, false, $bForce);
+    }
+
+    public function repost($iAuthorId, $iOwnerId, $sType, $sAction, $iObjectId, $mixedData = false, $bForce = false)
+    {
+        $aReposted = $this->_oDb->getReposted($sType, $sAction, $iObjectId);
+        if(empty($aReposted) || !is_array($aReposted))
+            return array('code' => 1, 'message' => _t('_bx_timeline_txt_err_cannot_repost'));
+
+        $mixedAllowed = $this->isAllowedRepost($aReposted, true);
+        if(!$bForce && $mixedAllowed !== true)
+            return array('code' => 2, 'message' => strip_tags($mixedAllowed));
+
+        $bReposted = $this->_oDb->isReposted($aReposted['id'], $iOwnerId, $iAuthorId);
+        if($bReposted)
+            return array('code' => 3, 'message' => _t('_bx_timeline_txt_err_already_reposted'));
+
+        $iDate = time();
+        $iId = $this->_oDb->insertEvent([
+            'owner_id' => $iOwnerId,
+            'system' => 0,
+            'type' => $this->_oConfig->getPrefix('common_post') . 'repost',
+            'action' => '',
+            'object_id' => $iAuthorId,
+            'object_owner_id' => $iAuthorId,
+            'object_privacy_view' => $this->_oConfig->getPrivacyViewDefault('object'),
+            'content' => serialize([
+                'type' => $sType,
+                'action' => $sAction,
+                'object_id' => $iObjectId,
+                'rdata' => $mixedData
+            ]),
+            'title' => '',
+            'description' => '',
+            'date' => $iDate,
+            'reacted' => $iDate,
+            'status_admin' => $this->getStatusAdmin()
+        ]);
+
+        if(empty($iId))
+            return array('code' => 4, 'message' => _t('_bx_timeline_txt_err_cannot_repost'));
+
+        $this->onRepost($iId, $aReposted);
+
+        return $iId;
+    }
+    
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Timeline
+     * @subsection bx_timeline-other Other
+     * @subsubsection bx_timeline-update update
+     * 
+     * @code bx_srv('bx_timeline', 'update', [...]); @endcode
+     * 
+     * Update timeline event by ID.
+     * 
+     * @param $iEventId integer value with event ID.
+     * @param $aSet an array with key=>value pairs for fields which should be updated. 
+     * @return boolean value with the result of operation.
+     * 
+     * @see BxTimelineModule::serviceUpdate
+     */
+    /** 
+     * @ref bx_timeline-update "update"
+     */
+    public function serviceUpdate($iEventId, $aSet)
+    {
+        if(empty($iEventId))
+            return false;
+
+        return (int)$this->_oDb->updateEvent($aSet, array('id' => $iEventId)) > 0;
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Timeline
+     * @subsection bx_timeline-other Other
+     * @subsubsection bx_timeline-delete delete
+     * 
+     * @code bx_srv('bx_timeline', 'delete', [...]); @endcode
+     * 
+     * Delete timeline event by ID.
+     * 
+     * @param $iId integer value with event ID.
+     * @return boolean value with the result of operation.
+     * 
+     * @see BxTimelineModule::serviceDelete
+     */
+    /** 
+     * @ref bx_timeline-delete "delete"
+     */
+    public function serviceDelete($iId)
+    {
+        $aEvent = $this->_oDb->getEvents(array('browse' => 'id', 'value' => $iId));
+        if(empty($aEvent) || !is_array($aEvent))
+            return true;
+
+        if($this->isAllowedDelete($aEvent, true) !== true || !$this->deleteEvent($aEvent))
+            return false;
+
+        $this->_oDb->deleteCache(array('event_id' => $iId));
+
+        return true;
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Timeline
+     * @subsection bx_timeline-other Other
+     * @subsubsection bx_timeline-get_menu_item_addon_comment get_menu_item_addon_comment
+     * 
+     * @code bx_srv('bx_timeline', 'get_menu_item_addon_comment', [...]); @endcode
+     * 
+     * Get addon for Comment menu item.
+     * NOTE. The service isn't used for now because comment functionality in card was updated.
+     * 
+     * @param $sSystem string value with comments engine system.
+     * @param $iObjectId integer value with object ID. 
+     * @return HTML string to display in menu item.
+     * 
+     * @see BxTimelineModule::serviceGetMenuItemAddonComment
+     */
+    /** 
+     * @ref bx_timeline-get_menu_item_addon_comment "get_menu_item_addon_comment"
+     */
+    public function serviceGetMenuItemAddonComment($sSystem, $iObjectId, $aBrowseParams = array())
+    {
+        if(empty($sSystem) || empty($iObjectId))
+            return '';
+        
+        $oCmts = $this->getCmtsObject($sSystem, $iObjectId);
+        if($oCmts === false)
+            return '';
+
+        $iCounter = (int)$oCmts->getCommentsCount();
+        if(empty($iCounter))
+            return '';
+
+        return  $this->_oTemplate->parseLink('javascript:void(0)', $iCounter, array(
+            'class' => 'bx-menu-item-addon',
+            'title' => _t('_bx_timeline_menu_item_title_item_comment'),
+            'onclick' => "javascript:" . $this->_oConfig->getJsObjectView($aBrowseParams) . ".commentItem(this, '" . $sSystem . "', " . $iObjectId . ")" 
+        ));
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Timeline
+     * @subsection bx_timeline-other Other
+     * @subsubsection bx_timeline-get_settings_checker_helper get_settings_checker_helper
+     * 
+     * @code bx_srv('bx_timeline', 'get_settings_checker_helper', [...]); @endcode
+     * 
+     * Get Checker Helper class name for Forms engine.
+     * 
+     * @return string with Checker Helper class name.
+     * 
+     * @see BxTimelineModule::serviceGetSettingsCheckerHelper
+     */
+    /** 
+     * @ref bx_timeline-get_settings_checker_helper "get_settings_checker_helper"
+     */
+    public function serviceGetSettingsCheckerHelper()
+    {
+        bx_import('FormCheckerHelper', $this->_aModule);
+        return 'BxTimelineFormCheckerHelper';
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Timeline
+     * @subsection bx_timeline-other Other
+     * @subsubsection bx_timeline-get_options_videos_preload get_options_videos_preload
+     * 
+     * @code bx_srv('bx_timeline', 'get_options_videos_preload', [...]); @endcode
+     * 
+     * Get an array with available options for 'Videos preload in Timeline' setting.
+     *
+     * @return an array with available options represented as key => value pairs.
+     * 
+     * @see BxTimelineModule::serviceGetOptionsVideosPreload
+     */
+    /** 
+     * @ref bx_timeline-get_options_videos_preload "get_options_videos_preload"
+     */
+    public function serviceGetOptionsVideosPreload()
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $aOptions = array('auto', 'metadata', 'none');
+
+        $aResult = array();
+        foreach($aOptions as $sOption)
+            $aResult[] = array(
+                'key' => $sOption,
+                'value' => _t($CNF['T']['option_vp_' . $sOption])
+            );
+
+        return $aResult;
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Timeline
+     * @subsection bx_timeline-other Other
+     * @subsubsection bx_timeline-get_options_videos_autoplay get_options_videos_autoplay
+     * 
+     * @code bx_srv('bx_timeline', 'get_options_videos_autoplay', [...]); @endcode
+     * 
+     * Get an array with available options for 'Videos autoplay in Timeline' setting.
+     *
+     * @return an array with available options represented as key => value pairs.
+     * 
+     * @see BxTimelineModule::serviceGetOptionsVideosAutoplay
+     */
+    /** 
+     * @ref bx_timeline-get_options_videos_autoplay "get_options_videos_autoplay"
+     */
+    public function serviceGetOptionsVideosAutoplay()
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $aOptions = array(BX_TIMELINE_VAP_OFF, BX_TIMELINE_VAP_ON_MUTE, BX_TIMELINE_VAP_ON);
+
+        $aResult = array();
+        foreach($aOptions as $sOption)
+            $aResult[] = array(
+                'key' => $sOption,
+                'value' => _t($CNF['T']['option_vap_' . $sOption])
+            );
+
+        return $aResult;
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Timeline
+     * @subsection bx_timeline-other Other
+     * @subsubsection bx_timeline-get_options_attachments_layout get_options_attachments_layout
+     * 
+     * @code bx_srv('bx_timeline', 'get_options_attachments_layout', [...]); @endcode
+     * 
+     * Get an array with available options for 'Show attachments as' setting.
+     *
+     * @return an array with available options represented as key => value pairs.
+     * 
+     * @see BxTimelineModule::serviceGetOptionsAttachmentsLayout
+     */
+    /** 
+     * @ref bx_timeline-get_options_attachments_layout "get_options_attachments_layout"
+     */
+    public function serviceGetOptionsAttachmentsLayout()
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $aOptions = array(BX_TIMELINE_ML_GALLERY, BX_TIMELINE_ML_SHOWCASE);
+
+        $aResult = array();
+        foreach($aOptions as $sOption)
+            $aResult[] = array(
+                'key' => $sOption,
+                'value' => _t($CNF['T']['option_al_' . $sOption])
+            );
+
+        return $aResult;
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Timeline
+     * @subsection bx_timeline-other Other
+     * @subsubsection bx_timeline-get_live_update get_live_update
+     * 
+     * @code bx_srv('bx_timeline', 'get_live_update', [...]); @endcode
+     * 
+     * Get an array with actual Live Update info. Only one live update notification for all new events.
+     *
+     * @return an array with Live Update info.
+     * 
+     * @see BxTimelineModule::serviceGetLiveUpdate
+     */
+    /** 
+     * @ref bx_timeline-get_live_update "get_live_update"
+     */
+    public function serviceGetLiveUpdate($aBrowseParams, $iProfileId, $iValue = 0, $iInit = 0)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $sKey = $this->_oConfig->getLiveUpdateKey($aBrowseParams);
+
+        bx_import('BxDolSession');
+        if((int)BxDolSession::getInstance()->getValue($sKey) == 1)
+            return false;
+
+        $aParams = $this->_prepareParams($aBrowseParams);
+        $aParams = array_merge($aParams, array(
+            'filter' => BX_TIMELINE_FILTER_OTHER_VIEWER
+        ));
+        $aEvents = $this->_oDb->getEvents($aParams);
+        if(empty($aEvents) || !is_array($aEvents))
+            return false;
+
+        $iValueNew = 0;
+        foreach($aEvents as $aEvent) {
+            if((int)$aEvent[$CNF['FIELD_STICKED']] != 0)
+                continue;
+
+            $sContent = $this->_oTemplate->getPost($aEvent, $aParams);
+            if(empty($sContent)) 
+                continue;
+
+            $iValueNew = $aEvent['id'];
+            break;
+        }
+
+        if($iValueNew == $iValue)
+            return false;
+
+        if((int)$iInit != 0)
+            return array('count' => $iValueNew);
+
+        return array(
+            'count' => $iValueNew, // required (for initialization and visualization)
+            'method' => $this->_oConfig->getJsObjectView($aBrowseParams) . '.showLiveUpdate(oData)', // required (for visualization)
+            'data' => array(
+                'code' => $this->_oTemplate->getLiveUpdate($aBrowseParams, $iProfileId, $iValue, $iValueNew)
+            ),  // optional, may have some additional data to be passed in JS method provided using 'method' param above.
+        );
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Timeline
+     * @subsection bx_timeline-other Other
+     * @subsubsection bx_timeline-get_live_updates get_live_updates
+     * 
+     * @code bx_srv('bx_timeline', 'get_live_updates', [...]); @endcode
+     * 
+     * Get an array with actual Live Update info. Separate live update notification for each new Event.
+     * Note. This method isn't used for now. @see BxTimelineModule::serviceGetLiveUpdate method instead.
+     * 
+     * Note. This way to display live update notifications isn't used for now. 
+     * See BxTimelineModule::serviceGetLiveUpdate method instead.
+     *
+     * @return an array with Live Update info.
+     * 
+     * @see BxTimelineModule::serviceGetLiveUpdates
+     */
+    /** 
+     * @ref bx_timeline-get_live_updates "get_live_updates"
+     */
+    public function serviceGetLiveUpdates($aBrowseParams, $iProfileId, $iCount = 0, $iInit = 0)
+    {
+        $sKey = $this->_oConfig->getLiveUpdateKey($aBrowseParams);
+
+        bx_import('BxDolSession');
+        if((int)BxDolSession::getInstance()->getValue($sKey) == 1)
+            return false;
+
+        $aParams = $this->_prepareParams($aBrowseParams);
+        $aParams['filter'] = BX_TIMELINE_FILTER_OTHER_VIEWER;
+        $aParams['count'] = true;
+
+        $iCountNew = $this->_oDb->getEvents($aParams);
+        if($iCountNew == $iCount)
+            return false;
+
+        if((int)$iInit != 0)
+            return array('count' => $iCountNew);
+
+        return array(
+            'count' => $iCountNew, // required (for initialization and visualization)
+            'method' => $this->_oConfig->getJsObjectView($aBrowseParams) . '.showLiveUpdates(oData)', // required (for visualization)
+            'data' => array(
+                'code' => $this->_oTemplate->getLiveUpdates($aBrowseParams, $iProfileId, $iCount, $iCountNew)
+            ),  // optional, may have some additional data to be passed in JS method provided using 'method' param above.
+        );
+    }
+    
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Accounts
+     * @subsection bx_timeline-other Other
+     * @subsubsection bx_timeline-get_menu_addon_manage_tools get_menu_addon_manage_tools
+     * 
+     * @code bx_srv('bx_timeline', 'get_menu_addon_manage_tools', [...]); @endcode
+     * 
+     * Get number of 'hidden' events for User End -> Dasboard page -> Manage block.
+     *
+     * @return integer number of 'hidden' events
+     * 
+     * @see BxTimelineModule::serviceGetMenuAddonManageTools
+     */
+    /** 
+     * @ref bx_timeline-get_menu_addon_manage_tools "get_menu_addon_manage_tools"
+     */
+    public function serviceGetMenuAddonManageTools()
+    {
+        $iNum1 = $this->_oDb->getEntriesNumByParams([
+            [
+                'key' => 'status', 
+                'value' => BX_TIMELINE_STATUS_HIDDEN, 
+                'operator' => '='
+            ]
+        ]);
+        
+        $iNum2 = $this->_oDb->getEntriesNumByParams([
+            [
+                'key' => 'reports',
+                'value' => '0', 
+                'operator' => '>'
+            ]
+        ]);
+        
+        return array(
+            'counter1_value' => $iNum1, 
+            'counter2_value' => $iNum2, 
+            'counter3_value' => 0
+        );
+    }
+
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Accounts
+     * @subsection bx_timeline-other Other
+     * @subsubsection bx_timeline-get_menu_addon_profile_stats get_menu_addon_profile_stats
+     * 
+     * @code bx_srv('bx_timeline', 'get_menu_addon_profile_stats', [...]); @endcode
+     * 
+     * Get number of 'muted' events for currently logged in user. User End -> Profile Stats.
+     *
+     * @return integer number of 'muted' events
+     * 
+     * @see BxTimelineModule::serviceGetMenuAddonProfileStats
+     */
+    /** 
+     * @ref bx_timeline-get_menu_addon_profile_stats "get_menu_addon_profile_stats"
+     */
+    public function serviceGetMenuAddonProfileStats($iProfileId = 0)
+    {
+        if(empty($iProfileId))
+            $iProfileId = $this->_iProfileId;
+
+        return $this->getConnectionMuteObject()->getConnectedContentCount($iProfileId);
+    }
+
+    public function serviceGet($aParams)
+    {
+        $aParams = $this->_prepareParams($aParams);
+
+        $aParams['return_data_type'] = 'array';
+        return $this->_oTemplate->getPosts($aParams);
+
+    }
+
+    public function serviceAdd($aValues)
+    {
+        return $this->getFormPost(array(
+            'values' => $aValues
+        ));
+    }
+
+    public function serviceEdit($iId, $aValues)
+    {
+        return $this->getFormEdit($iId, array(
+            'values' => $aValues
+        ));
+    }
+
+    /**
+     * Delete content entry
+     * @param $iContentId content id 
+     * @return error message or empty string on success
+     */
+    public function serviceDeleteEntity ($iContentId, $sFuncDelete = 'deleteData')
+    {
+        $aEvent = $this->_oDb->getEvents(array('browse' => 'id', 'value' => $iContentId));
+        if(empty($aEvent) || !is_array($aEvent))
+            return _t('_Empty');
+
+        if(!$this->deleteEvent($aEvent))
+            return _t('_bx_timeline_txt_err_cannot_perform_action');
+
+        return '';
+    }
+
+    /*
+     * COMMON METHODS
+     */
+    public function getStatusAdmin()
+    {
+        return $this->isModerator() || $this->_oConfig->isAutoApproveEnabled() ? BX_TIMELINE_STATUS_ACTIVE : BX_TIMELINE_STATUS_PENDING;
+    }
+
+    public function getItemData($iId, $aParams = array())
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        if(empty($aParams))
+            $aParams = $this->_prepareParams(array(
+                'view' => BX_TIMELINE_VIEW_ITEM, 
+                'type' => BX_TIMELINE_TYPE_ITEM
+            ));
+
+        $aEvent = $this->_oDb->getEvents(array('browse' => 'id', 'value' => $iId));
+        if(empty($aEvent))
+            return array('code' => 1, 'content' => _t('_Empty'));
+
+        $iProfile = (int)$aEvent[$CNF['FIELD_OWNER_ID']];
+        if(!empty($iProfile)) {
+            $oProfile = BxDolProfile::getInstance($iProfile);
+            if(!$oProfile)
+                return array('code' => 1, 'content' => _t('_Empty'));
+
+            $mixedResult = $oProfile->checkAllowedProfileView();
+            if($mixedResult !== CHECK_ACTION_RESULT_ALLOWED)
+                return array('code' => 2, 'content' => $mixedResult);
+        }
+
+        $sContent = $this->_oTemplate->getPost($aEvent, $aParams);
+        if(empty($sContent))
+            return array('code' => 2, 'content' => _t('_Access denied'));
+
+        $sKey = 'allowed_view';
+        if(isset($aEvent[$sKey]) && $aEvent[$sKey] !== CHECK_ACTION_RESULT_ALLOWED) 
+            return array('code' => 2, 'content' => $aEvent[$sKey]);
+
+        if($this->isAllowedView($aEvent) !== true)
+            return array('code' => 2, 'content' => _t('_Access denied'));
+
+        return array('code' => 0, 'content' => $sContent, 'event' => $aEvent);
+    }
+
+    public function hideEvent($aEvent)
+    {
+    	if(empty($aEvent) || !is_array($aEvent) || !$this->_oDb->updateEvent(['status' => 'hidden'], ['id' => (int)$aEvent['id']]))
+            return false;
+
+        $this->onHide($aEvent);
+        return true;
+    }
+
+    public function deleteEvent($aEvent)
+    {
+    	if(empty($aEvent) || !is_array($aEvent) || !$this->_oDb->deleteEvent(array('id' => (int)$aEvent['id'])))
+            return false;
+
+        $this->onDelete($aEvent);
+        return true;
+    }
+    
+
+    public function addAttachLink($aValues, $sDisplay = false)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        if(!$sDisplay)
+            $sDisplay = $this->_oConfig->getObject('form_display_attach_link_add');
+
+        $oForm = BxDolForm::getObjectInstance($this->_oConfig->getObject('form_attach_link'), $sDisplay, $this->_oTemplate);
+        if(!$oForm)
+            return array('message' => '_sys_txt_error_occured');
+
+        $oForm->aFormAttrs['method'] = BX_DOL_FORM_METHOD_SPECIFIC;
+        $oForm->aParams['csrf']['disable'] = true;
+        if(!empty($oForm->aParams['db']['submit_name'])) {
+            $sSubmitName = $oForm->aParams['db']['submit_name'];
+            if(!isset($oForm->aInputs[$sSubmitName])) {
+                if(isset($oForm->aInputs[$CNF['FIELD_CONTROLS']]))
+                    foreach($oForm->aInputs[$CNF['FIELD_CONTROLS']] as $mixedIndex => $aInput) {
+                        if(!is_numeric($mixedIndex) || empty($aInput['name']) || $aInput['name'] != $sSubmitName)
+                            continue;
+    
+                        $aValues[$sSubmitName] = $aInput['value'];
+                    }
+            }
+            else            
+                $aValues[$sSubmitName] = $oForm->aInputs[$sSubmitName]['value'];
+        }
+
+        $oForm->aInputs['url']['checker']['params']['preg'] = $this->_oConfig->getPregPattern('url');
+
+        $oForm->initChecker(array(), $aValues);
+        if(!$oForm->isSubmittedAndValid())
+            return array('message' => '_sys_txt_error_occured');
+
+        return $this->_addLink($oForm);
+    }
+
+    public function getFormAttachLink($iEventId = 0)
+    {
+        $oForm = BxDolForm::getObjectInstance($this->_oConfig->getObject('form_attach_link'), $this->_oConfig->getObject('form_display_attach_link_add'), $this->_oTemplate);
+        $oForm->aFormAttrs['action'] = BX_DOL_URL_ROOT . $this->_oConfig->getBaseUri() . 'submit_attach_link_form/';
+        $oForm->aInputs['event_id']['value'] = $iEventId;
+        $oForm->aInputs['url']['checker']['params']['preg'] = $this->_oConfig->getPregPattern('url');
+
+        $oForm->initChecker();
+        if($oForm->isSubmittedAndValid())
+            return $this->_addLink($oForm);
+
+        return array('form' => $oForm->getCode(), 'form_id' => $oForm->id);
+    }
+
+    public function getFormPost($aParams = [])
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $iUserId = $this->getUserId();
+
+        $oForm = $this->getFormPostObject($aParams);
+        $aFormInitCheckerParams = [];
+
+        $bValues = !empty($aParams['values']) && is_array($aParams['values']);
+        if($bValues) {
+            $this->_prepareFormForAutoSubmit($oForm, $aParams['values']);
+
+            $aFormInitCheckerParams = [[], $aParams['values']];
+            unset($aParams['values']);
+        }
+
+        call_user_func_array([$oForm, 'initChecker'], $aFormInitCheckerParams);
+
+        $bAjaxMode = $oForm->isAjaxMode();
+        $bDynamicMode = $bAjaxMode;
+
+        if($oForm->isSubmittedAndValid()) {
+            $sType = $oForm->getCleanValue('type');
+            $sType = $this->_oConfig->getPrefix('common_post') . $sType;
+            BxDolForm::setSubmittedValue('type', $sType, $oForm->aFormAttrs['method']);
+
+            $aContent = [];
+
+            //--- Process Text ---//
+            $sText = $oForm->getCleanValue('text');
+            $sText = $this->_prepareTextForSave($sText);
+            $bText = !empty($sText);
+
+            if($bText)
+            	$aContent['text'] = $sText;
+
+            //--- Process Context and Privacy ---//
+            $iOwnerId = (int)$oForm->getCleanValue('owner_id');
+            $iObjectPrivacyView = (int)$oForm->getCleanValue('object_privacy_view');
+            $iObjectPrivacyViewDefault = $this->_oConfig->getPrivacyViewDefault('object');
+            if(empty($iObjectPrivacyView))
+                $iObjectPrivacyView = $iObjectPrivacyViewDefault;
+            else if($iObjectPrivacyView < 0)
+                $iOwnerId = abs($iObjectPrivacyView);
+
+            //--- Process Link ---//
+            $aLinkIds = $oForm->getCleanValue($CNF['FIELD_LINK']);
+            $bLinkIds = !empty($aLinkIds) && is_array($aLinkIds);
+
+            //--- Process Photos ---//
+            $aPhotoIds = $oForm->getCleanValue($CNF['FIELD_PHOTO']);
+            $bPhotoIds = !empty($aPhotoIds) && is_array($aPhotoIds);
+
+            //--- Process Videos ---//
+            $aVideoIds = $oForm->getCleanValue($CNF['FIELD_VIDEO']);
+            $bVideoIds = !empty($aVideoIds) && is_array($aVideoIds);
+
+            //--- Process Files ---//
+            $aFileIds = $oForm->getCleanValue($CNF['FIELD_FILE']);
+            $bFileIds = !empty($aFileIds) && is_array($aFileIds);
+
+            if(!$bText && !$bLinkIds && !$bPhotoIds && !$bVideoIds && !$bFileIds) {
+                $oForm->aInputs['text']['error'] =  _t('_bx_timeline_txt_err_empty_post');
+                $oForm->setValid(false);
+
+            	return $this->_prepareResponse([
+                    'form' => $oForm->getCode($bDynamicMode), 
+                    'form_id' => $oForm->id
+                ], $bAjaxMode);
+            }
+
+            $sTitle = $bText ? $this->_oConfig->getTitle($sText) : $this->_oConfig->getTitleDefault($bLinkIds, $bPhotoIds, $bVideoIds, $bFileIds);
+            $sDescription = _t('_bx_timeline_txt_user_added_sample', '{profile_name}', _t('_bx_timeline_txt_sample_with_article'));
+
+            /**
+             * Unset 'text' input because its data was already processed 
+             * and will be saved via additional values which were passed 
+             * to BxDolForm::insert method.
+             */
+            unset($oForm->aInputs['text']);
+
+            $iId = $oForm->insert([
+                'owner_id' => $iOwnerId,
+                'object_id' => $iUserId,
+                'object_owner_id' => $iUserId,
+                'object_privacy_view' => $iObjectPrivacyView,
+                'content' => serialize($aContent),
+                'title' => $sTitle,
+                'description' => $sDescription,
+                'status_admin' => $this->getStatusAdmin()
+            ]);
+
+            if(!empty($iId)) {
+                $this->isAllowedPost(true);
+
+                $aContent = array_merge($aContent, [
+                    'timeline_group' => [
+                        'by' => $this->getName() . '_' . $iUserId . '_' . $iId,
+                        'field' => 'owner_id'
+                    ]
+                ]);
+                $this->_oDb->updateEvent(['content' => serialize($aContent)], ['id' => $iId]);
+
+                //--- Process Meta ---//
+            	$oMetatags = BxDolMetatags::getObjectInstance($this->_oConfig->getObject('metatags'));
+            	if($bText)
+                    $oMetatags->metaAdd($iId, $sText);
+                $oMetatags->locationsAddFromForm($iId, $this->_oConfig->CNF['FIELD_LOCATION_PREFIX']);
+
+                //--- Process Link ---//
+                if($bLinkIds)
+                    foreach($aLinkIds as $iLinkId)
+                        $this->_oDb->saveLink($iId, $iLinkId);
+
+                //--- Process Media ---//
+                $this->_saveMedia($CNF['FIELD_PHOTO'], $iId, $aPhotoIds, $iUserId, true);
+                $this->_saveMedia($CNF['FIELD_VIDEO'], $iId, $aVideoIds, $iUserId, true);
+                $this->_saveMedia($CNF['FIELD_FILE'], $iId, $aFileIds, $iUserId, true);
+
+                $this->onPost($iId);
+
+                return $this->_prepareResponse(['id' => $iId], $bAjaxMode, [
+                    'redirect' => $this->_oConfig->getItemViewUrl(['id' => $iId])
+                ]);
+            }
+
+            return $this->_prepareResponse(['message' => _t('_bx_timeline_txt_err_cannot_perform_action')], $bAjaxMode);
+        }
+
+        $mixedResult = $this->_prepareResponse([
+            'form' => $oForm->getCode($bDynamicMode), 
+            'form_id' => $oForm->id
+        ], $bAjaxMode && $oForm->isSubmitted());
+
+        if(is_array($mixedResult))
+            $mixedResult['form_object'] = $oForm;
+
+        return $mixedResult;
+    }
+
+    public function getFormEdit($iId, $aParams = [], $aBrowseParams = [])
+    {
+        $CNF = &$this->_oConfig->CNF;
+        $sJsObjectView = $this->_oConfig->getJsObjectView($aBrowseParams);
+
+        $iUserId = $this->getUserId();
+
+        $aEvent = $this->_oDb->getEvents(['browse' => 'id', 'value' => $iId]);
+        if(empty($aEvent) || !is_array($aEvent))
+            return [];
+
+        if(($mixedCheck = $this->isAllowedEdit($aEvent)) !== true)
+            return ['message' => $mixedCheck !== false ? $mixedCheck : _t('_sys_txt_access_denied')];
+        
+        $aContent = unserialize($aEvent['content']);
+        if(is_array($aContent) && !empty($aContent['text']))
+            $aEvent['text'] = $aContent['text'];
+
+        if(empty($aParams['form_object']))
+            $aParams['form_object'] = 'form_post';
+        if(empty($aParams['form_display']))
+            $aParams['form_display'] = 'form_display_post_edit';
+
+        $oForm = $this->getFormPostObject($aParams);
+        $oForm->setId($this->_oConfig->getHtmlIds('view', 'edit_form') . $iId);
+        $aFormInitCheckerParams = [];
+
+        $bValues = !empty($aParams['values']) && is_array($aParams['values']);
+        if($bValues) {
+            $this->_prepareFormForAutoSubmit($oForm, $aParams['values']);
+
+            $aFormInitCheckerParams = [[], array_merge($aEvent, $aParams['values'])];
+            unset($aParams['values']);
+        }
+        else {
+            $oForm->aFormAttrs['action'] = BX_DOL_URL_ROOT . $this->_oConfig->getBaseUri() . 'edit/' . $iId ;
+            if(!empty($aBrowseParams) && is_array($aBrowseParams))
+                $oForm->aFormAttrs['action'] = $this->_oConfig->addBrowseParams($oForm->aFormAttrs['action'], $aBrowseParams);
+
+            foreach($oForm->aInputs[$CNF['FIELD_CONTROLS']] as $mixedIndex => $aInput) {
+                if(!is_numeric($mixedIndex))
+                    continue;
+
+                $oForm->aInputs[$CNF['FIELD_CONTROLS']][$mixedIndex]['attrs'] = bx_replace_markers($aInput['attrs'], [
+                    'js_object_view' => $sJsObjectView,
+                    'content_id' => $iId
+                ]);
+            }
+
+            $aFormInitCheckerParams = [$aEvent];
+        }
+
+        call_user_func_array([$oForm, 'initChecker'], $aFormInitCheckerParams);
+
+        $bAjaxMode = $oForm->isAjaxMode();
+        $bDynamicMode = $bAjaxMode || bx_is_dynamic_request();
+        
+        $sCodeAdd = '';
+        if($bDynamicMode) {
+            $sCodeAdd .= $this->_oTemplate->getAddedJs('post', $bDynamicMode);
+            $sCodeAdd .= $this->_oTemplate->getJsCode('post', [], true, $bDynamicMode);
+        }
+
+        if($oForm->isSubmittedAndValid()) {
+            $aContent = [];
+
+            //--- Process Text ---//
+            $sText = $oForm->getCleanValue('text');
+            $sText = $this->_prepareTextForSave($sText);
+            $bText = !empty($sText);
+            unset($oForm->aInputs['text']);
+
+            if($bText)
+            	$aContent['text'] = $sText;
+
+            $aValsToAdd = [
+            	'content' => serialize($aContent),
+                'status_admin' => $this->getStatusAdmin()
+            ];
+
+            //--- Process Privacy ---//
+            if(isset($oForm->aInputs[$CNF['FIELD_OBJECT_PRIVACY_VIEW']])) {
+                $iObjectPrivacyView = (int)$oForm->getCleanValue('object_privacy_view');
+                $iObjectPrivacyViewDefault = $this->_oConfig->getPrivacyViewDefault('object');
+                if(empty($iObjectPrivacyView))
+                    $aValsToAdd = array_merge($aValsToAdd, [
+                        'object_privacy_view' => $iObjectPrivacyViewDefault
+                    ]);
+                else if($iObjectPrivacyView < 0) 
+                    $aValsToAdd = array_merge($aValsToAdd, [
+                        'owner_id' => abs($iObjectPrivacyView)
+                    ]);
+            }
+
+            //--- Process Link ---//
+            $aLinkIds = $oForm->getCleanValue($CNF['FIELD_LINK']);
+            $bLinkIds = !empty($aLinkIds) && is_array($aLinkIds);
+
+            //--- Process Media ---//
+            $aPhotoIds = $oForm->getCleanValue($CNF['FIELD_PHOTO']);
+            $bPhotoIds = !empty($aPhotoIds) && is_array($aPhotoIds);
+
+            $aVideoIds = $oForm->getCleanValue($CNF['FIELD_VIDEO']);
+            $bVideoIds = !empty($aVideoIds) && is_array($aVideoIds);
+            if($bVideoIds)
+                $aValsToAdd[$CNF['FIELD_STATUS']] = 'awaiting';
+
+            $aFileIds = $oForm->getCleanValue($CNF['FIELD_FILE']);
+            $bFileIds = !empty($aFileIds) && is_array($aFileIds);
+
+            if(!$bText && !$bLinkIds && !$bPhotoIds && !$bVideoIds && !$bFileIds) {
+                $oForm->aInputs['text']['error'] =  _t('_bx_timeline_txt_err_empty_post');
+                $oForm->setValid(false);
+
+            	return $this->_prepareResponse([
+                    'form' => $sCodeAdd . $oForm->getCode($bDynamicMode), 
+                    'form_id' => $oForm->id
+                ], $bAjaxMode);
+            }
+
+            if($oForm->update($iId, $aValsToAdd) === false)
+                return ['message' => _t('_bx_timeline_txt_err_cannot_perform_action')];
+
+            $this->isAllowedEdit($aEvent, true);
+
+            $oMetatags = BxDolMetatags::getObjectInstance($this->_oConfig->getObject('metatags'));
+            if($bText)
+                $oMetatags->metaAdd($iId, $sText);
+            $oMetatags->locationsAddFromForm($iId, $this->_oConfig->CNF['FIELD_LOCATION_PREFIX']);
+
+            //--- Process Link ---//
+            if($bLinkIds)
+                foreach($aLinkIds as $iLinkId)
+                    $this->_oDb->saveLink($iId, $iLinkId);
+
+            //--- Process Media ---//
+            $this->_saveMedia($CNF['FIELD_PHOTO'], $iId, $aPhotoIds, $iUserId);
+            $this->_saveMedia($CNF['FIELD_VIDEO'], $iId, $aVideoIds, $iUserId);
+            $this->_saveMedia($CNF['FIELD_FILE'], $iId, $aFileIds, $iUserId);
+
+            $this->getCacheItemObject()->removeAllByPrefix($this->_oConfig->getPrefix('cache_item') . $iId);
+
+            return [
+                'id' => $iId
+            ];
+        }
+
+        return [
+            'id' => $iId, 
+            'form' => $sCodeAdd . $oForm->getCode($bDynamicMode), 
+            'form_id' => $oForm->id,
+            'eval' => $sJsObjectView . '.onEditPost(oData)'
+        ];
+    }
+
+    public function getFormPostObject($aParams)
+    {
+    	$sFormObject = !empty($aParams['form_object']) ? $aParams['form_object'] : 'form_post';
+        $sFormDisplay = !empty($aParams['form_display']) ? $aParams['form_display'] : 'form_display_post_add';
+
+        $oForm = BxDolForm::getObjectInstance($this->_oConfig->getObject($sFormObject), $this->_oConfig->getObject($sFormDisplay), $this->_oTemplate);
+        $oForm->aFormAttrs = bx_replace_markers($oForm->aFormAttrs, [
+            'js_object_post' => $this->_oConfig->getJsObject('post')
+        ]);
+
+        /**
+         * Note. 'ajax_mode' parameter isn't checked because
+         * timeline post form works as Ajax form by default.
+         */
+        $sParamsKey = 'visibility_autoselect';
+        if(isset($aParams[$sParamsKey]) && (bool)$aParams[$sParamsKey] === true)
+            $oForm->setVisibilityAutoselect((bool)$aParams[$sParamsKey]);
+
+        $oForm->init();
+        return $oForm;
+    }
+
+    public function getCmtsObject($sSystem, $iId)
+    {
+        if(empty($sSystem) || (int)$iId == 0)
+            return false;
+
+        $oCmts = BxDolCmts::getObjectInstance($sSystem, $iId, true, $this->_oTemplate);
+        if(!$oCmts || !$oCmts->isEnabled())
+            return false;
+
+        return $oCmts;
+    }
+
+    public function getViewObject($sSystem, $iId)
+    {
+        if(empty($sSystem) || (int)$iId == 0)
+            return false;
+
+        $oView = BxDolView::getObjectInstance($sSystem, $iId, true, $this->_oTemplate);
+        if(!$oView || !$oView->isEnabled())
+            return false;
+
+        return $oView;
+    }
+
+    public function getVoteObject($sSystem, $iId)
+    {
+        if(empty($sSystem) || (int)$iId == 0)
+            return false;
+
+        $oVote = BxDolVote::getObjectInstance($sSystem, $iId, true, $this->_oTemplate);
+        if(!$oVote || !$oVote->isEnabled())
+            return false;
+
+        return $oVote;
+    }
+    
+    public function getReactionObject($sSystem, $iId)
+    {
+        if(empty($sSystem) || (int)$iId == 0)
+            return false;
+
+        $oReaction = BxDolVote::getObjectInstance($sSystem, $iId, true, $this->_oTemplate);
+        if(!$oReaction || !$oReaction->isEnabled())
+            return false;
+
+        return $oReaction;
+    }
+
+    public function getScoreObject($sSystem, $iId)
+    {
+        if(empty($sSystem) || (int)$iId == 0)
+            return false;
+
+        $oScore = BxDolScore::getObjectInstance($sSystem, $iId, true, $this->_oTemplate);
+        if(!$oScore || !$oScore->isEnabled())
+            return false;
+
+        return $oScore;
+    }
+
+    public function getReportObject($sSystem, $iId)
+    {
+        if(empty($sSystem) || (int)$iId == 0)
+            return false;
+
+        $oReport = BxDolReport::getObjectInstance($sSystem, $iId, true, $this->_oTemplate);
+        if(!$oReport || !$oReport->isEnabled())
+            return false;
+
+        return $oReport;
+    }
+
+    public function getAttachmentsMenuObject()
+    {
+        return BxDolMenu::getObjectInstance($this->_oConfig->getObject('menu_post_attachments'), $this->_oTemplate);
+    }
+
+    public function getManageMenuObject()
+    {
+        return BxDolMenu::getObjectInstance($this->_oConfig->getObject('menu_item_manage'), $this->_oTemplate);
+    }
+
+    public function getCacheItemObject()
+    {
+        $oCacheEngine = bx_instance('BxDolCache' . $this->_oConfig->getCacheItemEngine());
+        if(!$oCacheEngine->isAvailable())
+            $oCacheEngine = bx_instance('BxDolCacheFile');
+
+        return $oCacheEngine;
+    }
+
+    public function getConnectionMuteObject()
+    {
+        return BxDolConnection::getObjectInstance($this->_oConfig->getObject('connection_mute'));
+    }
+
+    //--- Check permissions methods ---//
+    public function serviceCheckAllowedViewForProfile ($aDataEntry, $isPerformAction = false, $iProfileId = false)
+    {
+        if(!$iProfileId)
+            $iProfileId = $this->_iProfileId;
+
+        $CNF = &$this->_oConfig->CNF;
+
+        // moderator and owner always have access
+        $iOwnerId = (int)$aDataEntry['owner_id'];
+        if(!empty($iProfileId) && (abs($iOwnerId) == (int)$iProfileId || $this->isModerator()))
+            return CHECK_ACTION_RESULT_ALLOWED;
+
+        // check ACL
+        if($iOwnerId != 0 && ($oOwner = BxDolProfile::getInstanceMagic($iOwnerId)) !== false && !($oOwner instanceof BxDolProfileUndefined)) {
+            $mixedCheckResult = bx_srv($oOwner->getModule(), 'check_allowed_with_content_for_profile', ['view', $oOwner->getContentId(), $iProfileId]);
+            if($mixedCheckResult !== CHECK_ACTION_RESULT_ALLOWED)
+                return $mixedCheckResult;
+        }
+
+        // check privacy
+        if(!empty($CNF['OBJECT_PRIVACY_VIEW'])) {
+            $oPrivacy = BxDolPrivacy::getObjectInstance($CNF['OBJECT_PRIVACY_VIEW']);
+            if($oPrivacy && !$oPrivacy->check($aDataEntry[$CNF['FIELD_ID']], $iProfileId))
+                return _t('_sys_access_denied_to_private_content');
+        }
+
+        // check alert to allow custom checks
+        $mixedResult = null;
+        bx_alert('system', 'check_allowed_view', 0, 0, array('module' => $this->getName(), 'content_info' => $aDataEntry, 'profile_id' => $iProfileId, 'override_result' => &$mixedResult));
+        if($mixedResult !== null)
+            return $mixedResult;
+
+        return CHECK_ACTION_RESULT_ALLOWED;
+    }
+
+    public function isModerator()
+    {
+        return $this->isModeratorForProfile((int)$this->getUserId());
+    }
+
+    public function isModeratorForProfile($iUserId)
+    {
+        if($this->checkAllowedEditAnyEntryForProfile(false, $iUserId) === CHECK_ACTION_RESULT_ALLOWED)
+            return true;
+
+        if($this->checkAllowedDeleteAnyEntryForProfile(false, $iUserId) === CHECK_ACTION_RESULT_ALLOWED)
+            return true;
+
+        return false;
+    }
+
+    public function isAllowedPost($bPerform = false)
+    {
+        if(isAdmin())
+            return true;
+
+        $iUserId = $this->getUserId();
+
+        $aCheckResult = checkActionModule($iUserId, 'post', $this->getName(), $bPerform);
+        if($aCheckResult[CHECK_ACTION_RESULT] !== CHECK_ACTION_RESULT_ALLOWED)
+            return $aCheckResult[CHECK_ACTION_MESSAGE];
+        
+        if(!empty($this->_iOwnerId) && ($oProfileOwner = BxDolProfile::getInstance($this->_iOwnerId)) !== false) {
+            if($oProfileOwner->checkAllowedPostInProfile($this->_iOwnerId, $this->getName()) !== CHECK_ACTION_RESULT_ALLOWED)
+                return _t('_sys_txt_access_denied');
+
+            bx_alert($oProfileOwner->getModule(), $this->_oConfig->getUri() . '_post', $oProfileOwner->id(), $iUserId, array('check_result' => &$aCheckResult));
+        }
+
+        return $aCheckResult[CHECK_ACTION_RESULT] !== CHECK_ACTION_RESULT_ALLOWED ? $aCheckResult[CHECK_ACTION_MESSAGE] : true;
+    }
+
+    public function isAllowedView($aEvent, $bPerform = false)
+    {
+        $CNF = $this->_oConfig->CNF;
+
+        if((int)$aEvent[$CNF['FIELD_OWNER_ID']] == 0)
+            return true;
+
+        $oProfileOwner = BxDolProfile::getInstance($aEvent[$CNF['FIELD_OWNER_ID']]);
+        if($oProfileOwner && $oProfileOwner->checkAllowedProfileView() !== CHECK_ACTION_RESULT_ALLOWED)
+            return false;
+
+        $oPrivacy = BxDolPrivacy::getObjectInstance($this->_oConfig->getObject('privacy_view'));
+        if(!$oPrivacy) 
+            return true;
+
+        $oPrivacy->setTableFieldAuthor($this->_oConfig->isSystem($aEvent['type'], $aEvent['action']) ? 'owner_id' : 'object_id');
+
+        return $oPrivacy->check($aEvent[$CNF['FIELD_ID']]);
+    }
+
+    public function isAllowedEdit($aEvent, $bPerform = false)
+    {
+        if(!isLogged())
+            return false;
+            
+        //--- System posts and Reposts cannot be edited at all.
+        if(!$this->_oConfig->isCommon($aEvent['type'], $aEvent['action']) || $aEvent['type'] == $this->_oConfig->getPrefix('common_post') . 'repost')
+            return false;
+
+        if(isAdmin())
+            return true;
+
+        $iUserId = (int)$this->getUserId();
+        $iOwnerId = (int)$aEvent['owner_id'];
+        $iObjectId = abs((int)$aEvent['object_id']);
+        if($iObjectId == $iUserId && $this->_oConfig->isAllowEdit())
+           return true;
+
+        $aCheckResult = checkActionModule($iUserId, 'edit', $this->getName(), $bPerform);
+        if(!empty($iOwnerId) && ($oProfileOwner = BxDolProfile::getInstance($iOwnerId)) !== false) {
+            if(BxDolService::call($oProfileOwner->getModule(), 'check_allowed_module_action_in_profile', array($oProfileOwner->getContentId(), $this->getName(), 'edit_any')) === CHECK_ACTION_RESULT_ALLOWED)
+                return true;
+
+            bx_alert($oProfileOwner->getModule(), $this->_oConfig->getUri() . '_edit', $oProfileOwner->id(), $iUserId, array('check_result' => &$aCheckResult));
+        }
+
+        return $aCheckResult[CHECK_ACTION_RESULT] !== CHECK_ACTION_RESULT_ALLOWED ? $aCheckResult[CHECK_ACTION_MESSAGE] : true;
+    }
+
+    public function isAllowedDelete($aEvent, $bPerform = false)
+    {
+        if(!isLogged())
+            return false;
+
+        if(isAdmin())
+            return true;
+
+        $iUserId = (int)$this->getUserId();
+        $iOwnerId = (int)$aEvent['owner_id'];
+        $iObjectId = abs((int)$aEvent['object_id']);
+        if((($iOwnerId == $iUserId && $this->_oConfig->isAllowDelete()) || ($this->_oConfig->isCommon($aEvent['type'], $aEvent['action']) && $iObjectId == $iUserId)))
+           return true;
+
+        $aCheckResult = checkActionModule($iUserId, 'delete', $this->getName(), $bPerform);
+        if(!empty($iOwnerId) && ($oProfileOwner = BxDolProfile::getInstance($iOwnerId)) !== false) {
+            if(BxDolService::call($oProfileOwner->getModule(), 'check_allowed_module_action_in_profile', array($oProfileOwner->getContentId(), $this->getName(), 'delete_any')) === CHECK_ACTION_RESULT_ALLOWED)
+                return true;
+
+            bx_alert($oProfileOwner->getModule(), $this->_oConfig->getUri() . '_delete', $oProfileOwner->id(), $iUserId, array('check_result' => &$aCheckResult));
+        }
+
+        return $aCheckResult[CHECK_ACTION_RESULT] !== CHECK_ACTION_RESULT_ALLOWED ? $aCheckResult[CHECK_ACTION_MESSAGE] : true;
+    }
+
+    public function isAllowedComment($aEvent, $bPerform = false)
+    {
+        $mixedComments = $this->getCommentsData($aEvent['comments']);
+        if($mixedComments === false)
+            return false;
+
+        list($sSystem, $iObjectId) = $mixedComments;
+        $oCmts = $this->getCmtsObject($sSystem, $iObjectId);
+        
+        if($oCmts->isViewAllowed() !== CHECK_ACTION_RESULT_ALLOWED)
+            return false;
+
+        $oCmts->addCssJs();
+        return true;
+    }
+
+    public function isAllowedViewCounter($aEvent, $bPerform = false)
+    {
+        $mixedViews = $this->getViewsData($aEvent['views']);
+        if($mixedViews === false)
+            return false;
+
+        list($sSystem, $iObjectId) = $mixedViews;
+        $oView = $this->getViewObject($sSystem, $iObjectId);
+
+        if(!$oView->isAllowedViewView($bPerform))
+        	return false;
+
+        $bResult = true;
+        if(!empty($aEvent['owner_id']) && ($oProfileOwner = BxDolProfile::getInstance($aEvent['owner_id'])) !== false)
+            bx_alert($oProfileOwner->getModule(), $this->_oConfig->getUri() . '_view_counter', $oProfileOwner->id(), (int)$this->getUserId(), array('result' => &$bResult));
+
+        return $bResult;
+    }
+
+    public function isAllowedVote($aEvent, $bPerform = false)
+    {
+        $mixedVotes = $this->getVotesData($aEvent['votes']);
+        if($mixedVotes === false)
+            return false;
+
+        list($sSystem, $iObjectId) = $mixedVotes;
+        $oVote = $this->getVoteObject($sSystem, $iObjectId);
+
+        if(!$oVote->isAllowedVote($bPerform))
+            return false;
+
+        $bResult = true;
+        if(!empty($aEvent['owner_id']) && ($oProfileOwner = BxDolProfile::getInstance($aEvent['owner_id'])) !== false)
+            bx_alert($oProfileOwner->getModule(), $this->_oConfig->getUri() . '_vote', $oProfileOwner->id(), (int)$this->getUserId(), array('result' => &$bResult));
+
+        return $bResult;
+    }
+    
+    public function isAllowedVoteView($aEvent, $bPerform = false)
+    {
+        $mixedVotes = $this->getVotesData($aEvent['votes']);
+        if($mixedVotes === false)
+            return false;
+
+        list($sSystem, $iObjectId) = $mixedVotes;
+        $oVote = $this->getVoteObject($sSystem, $iObjectId);
+
+        if(!$oVote->isAllowedVoteView($bPerform))
+            return false;
+
+        $bResult = true;
+        if(!empty($aEvent['owner_id']) && ($oProfileOwner = BxDolProfile::getInstance($aEvent['owner_id'])) !== false)
+            bx_alert($oProfileOwner->getModule(), $this->_oConfig->getUri() . '_vote_view', $oProfileOwner->id(), (int)$this->getUserId(), array('result' => &$bResult));
+
+        return $bResult;
+    }
+
+    public function isAllowedReaction($aEvent, $bPerform = false)
+    {
+        $mixedReactions = $this->getReactionsData($aEvent['reactions']);
+        if($mixedReactions === false)
+            return false;
+
+        list($sSystem, $iObjectId) = $mixedReactions;
+        $oReaction = $this->getReactionObject($sSystem, $iObjectId);
+
+        if(!$oReaction->isAllowedVote($bPerform))
+            return false;
+
+        $bResult = true;
+        if(!empty($aEvent['owner_id']) && ($oProfileOwner = BxDolProfile::getInstance($aEvent['owner_id'])) !== false)
+            bx_alert($oProfileOwner->getModule(), $this->_oConfig->getUri() . '_reaction', $oProfileOwner->id(), (int)$this->getUserId(), array('result' => &$bResult));
+
+        return $bResult;
+    }
+
+    public function isAllowedReactionView($aEvent, $bPerform = false)
+    {
+        $mixedReactions = $this->getReactionsData($aEvent['reactions']);
+        if($mixedReactions === false)
+            return false;
+
+        list($sSystem, $iObjectId) = $mixedReactions;
+        $oReaction = $this->getReactionObject($sSystem, $iObjectId);
+
+        if(!$oReaction->isAllowedVoteView($bPerform))
+            return false;
+
+        $bResult = true;
+        if(!empty($aEvent['owner_id']) && ($oProfileOwner = BxDolProfile::getInstance($aEvent['owner_id'])) !== false)
+            bx_alert($oProfileOwner->getModule(), $this->_oConfig->getUri() . '_reaction_view', $oProfileOwner->id(), (int)$this->getUserId(), array('result' => &$bResult));
+
+        return $bResult;
+    }
+
+    public function isAllowedScore($aEvent, $bPerform = false)
+    {
+        $mixedScores = $this->getScoresData($aEvent['scores']);
+        if($mixedScores === false)
+            return false;
+
+        list($sSystem, $iObjectId) = $mixedScores;
+        $oScore = $this->getScoreObject($sSystem, $iObjectId);
+
+        if(!$oScore->isAllowedVote($bPerform))
+        	return false;
+
+        $bResult = true;
+        if(!empty($aEvent['owner_id']) && ($oProfileOwner = BxDolProfile::getInstance($aEvent['owner_id'])) !== false)
+            bx_alert($oProfileOwner->getModule(), $this->_oConfig->getUri() . '_score', $oProfileOwner->id(), (int)$this->getUserId(), array('result' => &$bResult));
+
+        return $bResult;
+    }
+
+    public function isAllowedReport($aEvent, $bPerform = false)
+    {
+        $mixedReports = $this->getReportsData($aEvent['reports']);
+        if($mixedReports === false)
+            return false;
+
+        list($sSystem, $iObjectId) = $mixedReports;
+        $oReport = $this->getReportObject($sSystem, $iObjectId);
+
+        if(!$oReport->isAllowedReport($bPerform))
+        	return false;
+
+        $bResult = true;
+        if(!empty($aEvent['owner_id']) && ($oProfileOwner = BxDolProfile::getInstance($aEvent['owner_id'])) !== false)
+            bx_alert($oProfileOwner->getModule(), $this->_oConfig->getUri() . '_report', $oProfileOwner->id(), (int)$this->getUserId(), array('result' => &$bResult));
+
+        return $bResult;
+    }
+
+    public function isAllowedRepost($aEvent, $bPerform = false)
+    {
+        $mixedResult = $this->_isAllowedRepost($aEvent, $bPerform);
+
+        bx_alert($this->getName(), 'is_allowed_repost', 0, 0, [
+            'content_info' => $aEvent, 
+            'override_result' => &$mixedResult
+        ]);
+
+        return $mixedResult;
+    }
+
+    public function isAllowedSend($aEvent, $bPerform = false)
+    {
+        if(!$this->_oDb->isEnabledByName('bx_convos'))
+            return false;
+
+        if(isAdmin())
+            return true;
+
+        $iUserId = (int)$this->getUserId();
+        if($iUserId == 0)
+            return false;
+
+        $aCheckResult = checkActionModule($iUserId, 'send', $this->getName(), $bPerform);
+        if(!empty($aEvent['owner_id']) && ($oProfileOwner = BxDolProfile::getInstance($aEvent['owner_id'])) !== false)
+            bx_alert($oProfileOwner->getModule(), $this->_oConfig->getUri() . '_send', $oProfileOwner->id(), $iUserId, array('check_result' => &$aCheckResult));
+
+        return $aCheckResult[CHECK_ACTION_RESULT] !== CHECK_ACTION_RESULT_ALLOWED ? $aCheckResult[CHECK_ACTION_MESSAGE] : true;
+    }
+
+    public function isAllowedMute($aEvent, $bPerform = false)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        if(!empty($aEvent[$CNF['FIELD_OWNER_ID']]) && $aEvent[$CNF['FIELD_OWNER_ID']] != $this->_iProfileId)
+            return false;
+
+        $iAuthor = (int)$aEvent[$CNF['FIELD_OWNER_ID']];
+        if(!$this->_oConfig->isSystem($aEvent['type'], $aEvent['action']))
+            $iAuthor = (int)$aEvent[$CNF['FIELD_OBJECT_ID']];
+
+        if($this->_iProfileId == $iAuthor || $this->getConnectionMuteObject()->isConnected($this->_iProfileId, $iAuthor))
+            return false;
+
+        return $this->_isAllowedMute($bPerform);
+    }
+
+    public function isAllowedUnmute($iAuthor, $bPerform = false)
+    {
+    	if(!$this->getConnectionMuteObject()->isConnected($this->_iProfileId, $iAuthor))
+            return false;
+
+        return $this->_isAllowedMute($bPerform);
+    }
+
+    /**
+     * Pin - "Pin here" - pin the post on Profile Timeline for profile owner.
+     * Can be done by profile owner for himself or by admin for profile owner to see.
+     * @param type $aEvent
+     * @param type $bPerform
+     * @return boolean
+     */
+    public function isAllowedPin($aEvent, $bPerform = false)
+    {
+    	if((int)$aEvent['pinned'] != 0)
+    		return false;
+
+        return $this->_isAllowedPin($aEvent, $bPerform);
+    }
+
+    public function isAllowedUnpin($aEvent, $bPerform = false)
+    {
+    	if((int)$aEvent['pinned'] == 0)
+    		return false;
+
+        return $this->_isAllowedPin($aEvent, $bPerform);
+    }
+
+    /**
+     * Stick - "Pin for All" - pin the post on Public Timeline for everybody to see.
+     * Is available for Administrators/Moderators only.
+     * @param type $aEvent
+     * @param type $bPerform
+     * @return boolean
+     */
+    public function isAllowedStick($aEvent, $bPerform = false)
+    {
+    	if((int)$aEvent['sticked'] != 0)
+    		return false;
+    
+    	return $this->_isAllowedStick($aEvent, $bPerform);
+    }
+    
+    public function isAllowedUnstick($aEvent, $bPerform = false)
+    {
+    	if((int)$aEvent['sticked'] == 0)
+            return false;
+    
+    	return $this->_isAllowedStick($aEvent, $bPerform);
+    }
+    
+    public function isAllowedPromote($aEvent, $bPerform = false)
+    {
+    	if((int)$aEvent['promoted'] != 0)
+            return false;
+
+        return $this->_isAllowedPromote($aEvent, $bPerform);
+    }
+
+    public function isAllowedUnpromote($aEvent, $bPerform = false)
+    {
+    	if((int)$aEvent['promoted'] == 0)
+            return false;
+
+        return $this->_isAllowedPromote($aEvent, $bPerform);
+    }
+
+    public function isAllowedNotes($aEvent, $bPerform = false)
+    {
+        return $this->isModerator();
+    }
+
+    public function isAllowedMore($aEvent, $bPerform = false)
+    {
+    	$oMoreMenu = $this->getManageMenuObject();
+        if(!$oMoreMenu)
+            return false;
+
+    	$oMoreMenu->setEvent($aEvent);
+    	return $oMoreMenu->isVisible();
+    }
+
+    public function checkAllowedView ($aContentInfo, $isPerformAction = false)
+    {
+        if(!$this->isAllowedView($aContentInfo, $isPerformAction))
+            return _t('_sys_txt_access_denied');
+
+        return CHECK_ACTION_RESULT_ALLOWED;
+    }
+
+    public function checkAllowedDelete (&$aDataEntry, $isPerformAction = false)
+    {
+        if(($mixedResult = $this->isAllowedDelete($aDataEntry, $isPerformAction)) !== true)
+            return is_string($mixedResult) ? $mixedResult : _t('_sys_txt_access_denied');
+
+        return CHECK_ACTION_RESULT_ALLOWED;
+    }
+
+    public function checkAllowedCommentsView ($aContentInfo, $isPerformAction = false)
+    {
+        $CNF = $this->_oConfig->CNF;
+
+        $iOwner = (int)$aContentInfo[$CNF['FIELD_OWNER_ID']];
+        if($iOwner == 0) //--- in case of Public Timeline.
+            return CHECK_ACTION_RESULT_ALLOWED;
+
+        $oOwner = BxDolProfile::getInstance($iOwner);
+        if(!$oOwner) //--- in case of non-existed Timeline owner.
+            return _t('_sys_txt_access_denied');
+
+        $mixedResult = $oOwner->checkAllowedProfileView();
+        if($mixedResult !== CHECK_ACTION_RESULT_ALLOWED)
+            return $mixedResult;
+
+        return $this->checkAllowedView($aContentInfo, $isPerformAction);
+    }
+
+    public function checkAllowedCommentsPost ($aContentInfo, $isPerformAction = false)
+    {
+        $sError = '_sys_txt_access_denied';
+
+        $aContentInfo = array_merge($aContentInfo, $this->_oTemplate->getDataCached($aContentInfo));
+        if($aContentInfo === false)
+            return _t($sError);
+
+        if(!$this->isAllowedComment($aContentInfo, $isPerformAction))
+            return _t($sError);
+
+        return CHECK_ACTION_RESULT_ALLOWED;
+    }
+
+    public function checkAllowedEditAnyEntryForProfile ($isPerformAction = false, $iProfileId = false)
+    {
+        if(!$iProfileId)
+            $iProfileId = $this->_iProfileId;
+
+    	$aCheck = checkActionModule($iProfileId, 'edit', $this->getName(), $isPerformAction);
+    	if($aCheck[CHECK_ACTION_RESULT] === CHECK_ACTION_RESULT_ALLOWED)
+            return CHECK_ACTION_RESULT_ALLOWED;
+
+    	return _t('_sys_txt_access_denied');
+    }
+
+    public function checkAllowedDeleteAnyEntryForProfile ($isPerformAction = false, $iProfileId = false)
+    {
+        if(!$iProfileId)
+            $iProfileId = $this->_iProfileId;
+
+    	$aCheck = checkActionModule($iProfileId, 'delete', $this->getName(), $isPerformAction);
+    	if($aCheck[CHECK_ACTION_RESULT] === CHECK_ACTION_RESULT_ALLOWED)
+            return CHECK_ACTION_RESULT_ALLOWED;
+
+    	return _t('_sys_txt_access_denied');
+    }
+
+    public function onPost($iContentId)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $aEvent = $this->_oDb->getEvents(array('browse' => 'id', 'value' => $iContentId));
+
+        if($this->_oConfig->isSystem($aEvent['type'], $aEvent['action'])) {
+            //--- Request event's data from content module and update it in the Timeline DB.
+            $this->_oTemplate->getDataCached($aEvent);
+
+            $sPostType = 'system';
+            $iSenderId = $iObjectAuthorId = (int)$aEvent['owner_id'];
+        } 
+        else {
+            $sPostType = 'common';
+            $iSenderId = $iObjectAuthorId = (int)$aEvent['object_id'];
+        }
+
+        //--- Event -> Post/Defer for Alerts Engine ---//
+        $sAction = ($aEvent[$CNF['FIELD_STATUS']] == BX_TIMELINE_STATUS_AWAITING ? 'defer' : 'post') . '_' . $sPostType;
+        bx_alert($this->_oConfig->getObject('alert'), $sAction, $iContentId, $iSenderId, array(
+            'source' => $this->_oConfig->getName() . '_' . $iContentId,
+            'owner_id' => $aEvent['owner_id'],
+            'object_author_id' => $iObjectAuthorId,
+            'privacy_view' => $aEvent['object_privacy_view'],
+        ));
+        //--- Event -> Post for Alerts Engine ---//
+    }
+
+    public function onPublished($iContentId)
+    {
+        //--- Clear Item cache
+        $this->getCacheItemObject()->removeAllByPrefix($this->_oConfig->getPrefix('cache_item') . $iContentId);
+
+        $this->onPost($iContentId);
+    }
+    
+    public function onFailed($iContentId)
+    {
+        $aEvent = $this->_oDb->getEvents(array('browse' => 'id', 'value' => $iContentId));
+
+        //--- Clear Item cache
+        $this->getCacheItemObject()->removeAllByPrefix($this->_oConfig->getPrefix('cache_item') . $iContentId);
+
+        if($this->_oConfig->isSystem($aEvent['type'], $aEvent['action'])) {
+            //--- Request event's data from content module and update it in the Timeline DB.
+            $this->_oTemplate->getDataCached($aEvent);
+
+            $sPostType = 'system';
+            $iSenderId = $iObjectAuthorId = (int)$aEvent['owner_id'];
+        } 
+        else {
+            $sPostType = 'common';
+            $iSenderId = $iObjectAuthorId = (int)$aEvent['object_id'];
+        }
+
+        //--- Event -> Fail for Alerts Engine ---//
+        bx_alert($this->_oConfig->getObject('alert'), 'fail_' . $sPostType, $iContentId, $iSenderId, array(
+            'owner_id' => $aEvent['owner_id'],
+            'object_author_id' => $iObjectAuthorId,
+            'privacy_view' => $aEvent['object_privacy_view'],
+        ));
+        //--- Event -> Post for Alerts Engine ---//
+    }
+
+    public function onRepost($iContentId, $aReposted = array())
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $aEvent = $this->_oDb->getEvents(array('browse' => 'id', 'value' => $iContentId));
+
+        if(empty($aReposted)) {
+            $aContent = unserialize($aEvent['content']);
+
+            $aReposted = $this->_oDb->getReposted($aContent['type'], $aContent['action'], $aContent['object_id']);
+            if(empty($aReposted) || !is_array($aReposted))
+                return;
+        }
+
+        $iUserId = (int)$aEvent[$CNF['FIELD_OBJECT_OWNER_ID']];
+        $this->_oDb->insertRepostTrack($aEvent['id'], $iUserId, $this->getUserIp(), $aReposted['id']);
+        $this->_oDb->updateRepostCounter($aReposted['id'], $aReposted['reposts']);
+
+        //--- Timeline -> Update for Alerts Engine ---//
+        bx_alert($this->_oConfig->getObject('alert'), 'repost', $aReposted['id'], $iUserId, array(
+            'privacy_view' => $aEvent['object_privacy_view'],
+            'object_author_id' => $aReposted['owner_id'],
+            'repost_id' => $iContentId,
+        ));
+        //--- Timeline -> Update for Alerts Engine ---//
+    }
+
+    public function onHide($aEvent)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $iUserId = $this->getUserId();
+    	$sCommonPostPrefix = $this->_oConfig->getPrefix('common_post');
+
+    	//--- Update parent event when repost event was deactivated.
+    	$bRepost = $aEvent['type'] == $sCommonPostPrefix . BX_TIMELINE_PARSE_TYPE_REPOST;
+        if($bRepost) {
+            $this->_oDb->updateRepostTrack(['active' => 0], ['event_id' => $aEvent[$CNF['FIELD_ID']]]);
+
+            $aContent = unserialize($aEvent['content']);
+            $aReposted = $this->_oDb->getReposted($aContent['type'], $aContent['action'], $aContent['object_id']);
+            if(!empty($aReposted) && is_array($aReposted))
+                $this->_oDb->updateRepostCounter($aReposted[$CNF['FIELD_ID']], $aReposted['reposts'], -1);
+        }
+
+        //--- Find and hide repost events when parent event was deactivated.
+        $aRepostEvents = $this->_oDb->getEvents(['browse' => 'reposted_by_track', 'value' => $aEvent[$CNF['FIELD_ID']]]);
+        foreach($aRepostEvents as $aRepostEvent) {
+            if((int)$this->_oDb->updateEvent(['active' => 0], ['id' => (int)$aRepostEvent[$CNF['FIELD_ID']]]) == 0) 
+                continue;
+
+            $this->_oDb->updateRepostTrack(['active' => 0], ['event_id' => $aRepostEvent[$CNF['FIELD_ID']]]);
+
+            bx_alert($this->_oConfig->getObject('alert'), 'hide_repost', $aEvent[$CNF['FIELD_ID']], $iUserId, array(
+                'repost_id' => $aRepostEvent[$CNF['FIELD_ID']],
+            ));
+        }
+
+        //--- Delete associated meta for Common events.
+        if($this->_oConfig->isCommon($aEvent['type'], $aEvent['action'])) {
+            $oMetatags = BxDolMetatags::getObjectInstance($this->_oConfig->getObject('metatags'));
+            $oMetatags->onDeleteContent($aEvent[$CNF['FIELD_ID']]);
+        }
+
+        //--- Delete item cache.
+        $sCacheItemKey = $this->_oConfig->getCacheItemKey($aEvent[$CNF['FIELD_ID']]);
+        $this->getCacheItemObject()->delData($sCacheItemKey);
+
+        //--- Event -> Hide for Alerts Engine ---//
+        if($bRepost)
+            bx_alert($this->_oConfig->getObject('alert'), 'hide_repost', $aReposted[$CNF['FIELD_ID']], $iUserId, array(
+                'repost_id' => $aEvent[$CNF['FIELD_ID']],
+            ));
+        else
+            bx_alert($this->_oConfig->getObject('alert'), 'hide', $aEvent[$CNF['FIELD_ID']], $iUserId);
+        //--- Event -> Hide for Alerts Engine ---//
+    }
+
+    public function onUnhide($aEvent)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $iUserId = $this->getUserId();
+    	$sCommonPostPrefix = $this->_oConfig->getPrefix('common_post');
+
+    	//--- Update parent event when repost event was activated back.
+    	$bRepost = $aEvent['type'] == $sCommonPostPrefix . BX_TIMELINE_PARSE_TYPE_REPOST;
+        if($bRepost) {
+            $this->_oDb->updateRepostTrack(['active' => 1], ['event_id' => $aEvent[$CNF['FIELD_ID']]]);
+
+            $aContent = unserialize($aEvent['content']);
+            $aReposted = $this->_oDb->getReposted($aContent['type'], $aContent['action'], $aContent['object_id']);
+            if(!empty($aReposted) && is_array($aReposted))
+                $this->_oDb->updateRepostCounter($aReposted[$CNF['FIELD_ID']], $aReposted['reposts'], 1);
+        }
+
+        //--- Find and hide repost events when parent event was activated back.
+        $aRepostEvents = $this->_oDb->getEvents(['browse' => 'reposted_by_track', 'value' => $aEvent[$CNF['FIELD_ID']]]);
+        foreach($aRepostEvents as $aRepostEvent) {
+            if((int)$this->_oDb->updateEvent(['active' => 1], ['id' => (int)$aRepostEvent[$CNF['FIELD_ID']]]) == 0) 
+                continue;
+
+            $this->_oDb->updateRepostTrack(['active' => 1], ['event_id' => $aRepostEvent[$CNF['FIELD_ID']]]);
+
+            bx_alert($this->_oConfig->getObject('alert'), 'unhide_repost', $aEvent[$CNF['FIELD_ID']], $iUserId, array(
+                'repost_id' => $aRepostEvent[$CNF['FIELD_ID']],
+            ));
+        }
+
+        //--- Process meta for Common events.
+        if($this->_oConfig->isCommon($aEvent['type'], $aEvent['action'])) {
+            $aContent = unserialize($aEvent['content']);
+
+            $oMetatags = BxDolMetatags::getObjectInstance($this->_oConfig->getObject('metatags'));
+            if(!empty($aContent['text']))
+                $oMetatags->metaAdd($aEvent[$CNF['FIELD_ID']], $aContent['text']);
+            $oMetatags->locationsAddFromForm($aEvent[$CNF['FIELD_ID']], $CNF['FIELD_LOCATION_PREFIX']);
+        }
+
+        //--- Event -> Unhide for Alerts Engine ---//
+        if($bRepost)
+            bx_alert($this->_oConfig->getObject('alert'), 'unhide_repost', $aReposted[$CNF['FIELD_ID']], $iUserId, array(
+                'repost_id' => $aEvent[$CNF['FIELD_ID']],
+            ));
+        else
+            bx_alert($this->_oConfig->getObject('alert'), 'unhide', $aEvent[$CNF['FIELD_ID']], $iUserId);
+        //--- Event -> Unhide for Alerts Engine ---//
+    }
+
+    public function onDelete($aEvent)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $iUserId = $this->getUserId();
+    	$sCommonPostPrefix = $this->_oConfig->getPrefix('common_post');
+    	$sCommonPostComment = $this->_oConfig->getObject('comment');
+    	
+    	//--- Delete comments for Common posts.
+    	if($this->_oConfig->isCommon($aEvent['type'], $aEvent['action'])) {
+            $oComments = $this->getCmtsObject($sCommonPostComment, $aEvent[$CNF['FIELD_ID']]);
+            if($oComments !== false)
+                $oComments->onObjectDelete($aEvent[$CNF['FIELD_ID']]);
+    	}
+
+    	//--- Delete attached photos, videos and links when common event was deleted.
+    	if($aEvent['type'] == $sCommonPostPrefix . BX_TIMELINE_PARSE_TYPE_POST) {
+            $this->_deleteMedia($CNF['FIELD_PHOTO'], $aEvent[$CNF['FIELD_ID']]);
+            $this->_deleteMedia($CNF['FIELD_VIDEO'], $aEvent[$CNF['FIELD_ID']]);
+			$this->_deleteMedia($CNF['FIELD_FILE'], $aEvent[$CNF['FIELD_ID']]);
+            $this->_deleteLinks($aEvent[$CNF['FIELD_ID']]);
+    	}
+
+    	//--- Update parent event when repost event was deleted.
+    	$bRepost = $aEvent['type'] == $sCommonPostPrefix . BX_TIMELINE_PARSE_TYPE_REPOST;
+        if($bRepost) {
+            $this->_oDb->deleteRepostTrack($aEvent[$CNF['FIELD_ID']]);
+
+            $aContent = unserialize($aEvent['content']);
+            $aReposted = $this->_oDb->getReposted($aContent['type'], $aContent['action'], $aContent['object_id']);
+            if(!empty($aReposted) && is_array($aReposted))
+                $this->_oDb->updateRepostCounter($aReposted[$CNF['FIELD_ID']], $aReposted['reposts'], -1);
+        }
+
+        //--- Find and delete repost events when parent event was deleted.
+        $aRepostEvents = $this->_oDb->getEvents(array('browse' => 'reposted_by_track', 'value' => $aEvent[$CNF['FIELD_ID']]));
+        foreach($aRepostEvents as $aRepostEvent) {
+            if((int)$this->_oDb->deleteEvent(array('id' => (int)$aRepostEvent[$CNF['FIELD_ID']])) == 0) 
+                continue;
+
+            $this->_oDb->deleteRepostTrack($aRepostEvent[$CNF['FIELD_ID']]);
+
+            $oComments = $this->getCmtsObject($sCommonPostComment, $aRepostEvent[$CNF['FIELD_ID']]);
+            if($oComments !== false)
+                $oComments->onObjectDelete($aRepostEvent[$CNF['FIELD_ID']]);
+
+            bx_alert($this->_oConfig->getObject('alert'), 'delete_repost', $aEvent[$CNF['FIELD_ID']], $iUserId, array(
+                'repost_id' => $aRepostEvent[$CNF['FIELD_ID']],
+            ));
+        }
+
+        //--- Delete associated meta for Common events.
+        if($this->_oConfig->isCommon($aEvent['type'], $aEvent['action'])) {
+            $oMetatags = BxDolMetatags::getObjectInstance($this->_oConfig->getObject('metatags'));
+            $oMetatags->onDeleteContent($aEvent[$CNF['FIELD_ID']]);
+        }
+        
+        //--- Delete item cache.
+        $sCacheItemKey = $this->_oConfig->getCacheItemKey($aEvent[$CNF['FIELD_ID']]);
+        $this->getCacheItemObject()->delData($sCacheItemKey);
+
+        //--- Event -> Delete for Alerts Engine ---//
+        if($bRepost)
+            bx_alert($this->_oConfig->getObject('alert'), 'delete_repost', $aReposted[$CNF['FIELD_ID']], $iUserId, array(
+                'repost_id' => $aEvent[$CNF['FIELD_ID']],
+            ));
+        else
+            bx_alert($this->_oConfig->getObject('alert'), 'delete', $aEvent[$CNF['FIELD_ID']], $iUserId);
+        //--- Event -> Delete for Alerts Engine ---//
+    }
+
+    public function getParams($sView = '', $sType = '', $iOwnerId = 0, $iStart = 0, $iPerPage = 0, $sFilter = BX_TIMELINE_FILTER_ALL, $aModules = array(), $iTimeline = 0)
+    {
+        return $this->_prepareParams(array(
+            'view' => $sView,
+            'type' => $sType,
+            'owner_id' => $iOwnerId,
+            'start' => $iStart, 
+            'per_page' => $iPerPage, 
+            'timeline' => $iTimeline, 
+            'filter' => $sFilter, 
+            'modules' => $aModules
+        ));
+    }
+
+    public function getParamsExt($aParams = array())
+    {
+        return $this->_prepareParams($aParams);
+    }
+
+    public function getViewsData(&$aViews)
+    {
+        if(empty($aViews) || !is_array($aViews))
+            return false;
+
+        $sSystem = isset($aViews['system']) ? $aViews['system'] : '';
+        $iObjectId = isset($aViews['object_id']) ? (int)$aViews['object_id'] : 0;
+        $iCount = isset($aViews['count']) ? (int)$aViews['count'] : 0;
+        if($sSystem == '' || $iObjectId == 0)
+            return false;
+
+        return array($sSystem, $iObjectId, $iCount);
+    }
+
+    public function getVotesData(&$aVotes)
+    {
+        if(empty($aVotes) || !is_array($aVotes))
+            return false;
+
+        $sSystem = isset($aVotes['system']) ? $aVotes['system'] : '';
+        $iObjectId = isset($aVotes['object_id']) ? (int)$aVotes['object_id'] : 0;
+        $iCount = isset($aVotes['count']) ? (int)$aVotes['count'] : 0;
+        if($sSystem == '' || $iObjectId == 0)
+            return false;
+
+        return array($sSystem, $iObjectId, $iCount);
+    }
+
+    public function getReactionsData(&$aReactions)
+    {
+        if(empty($aReactions) || !is_array($aReactions))
+            return false;
+
+        $sSystem = isset($aReactions['system']) ? $aReactions['system'] : '';
+        $iObjectId = isset($aReactions['object_id']) ? (int)$aReactions['object_id'] : 0;
+        $iCount = isset($aReactions['count']) ? (int)$aReactions['count'] : 0;
+        if($sSystem == '' || $iObjectId == 0)
+            return false;
+
+        return array($sSystem, $iObjectId, $iCount);
+    }
+
+    public function getScoresData(&$aScores)
+    {
+        if(empty($aScores) || !is_array($aScores))
+            return false;
+
+        $sSystem = isset($aScores['system']) ? $aScores['system'] : '';
+        $iObjectId = isset($aScores['object_id']) ? (int)$aScores['object_id'] : 0;
+        $iScore = isset($aScores['score']) ? (int)$aScores['score'] : 0;
+        if($sSystem == '' || $iObjectId == 0)
+            return false;
+
+        return array($sSystem, $iObjectId, $iScore);
+    }
+
+    public function getReportsData(&$aReports)
+    {
+        if(empty($aReports) || !is_array($aReports))
+            return false;
+
+        $sSystem = isset($aReports['system']) ? $aReports['system'] : '';
+        $iObjectId = isset($aReports['object_id']) ? (int)$aReports['object_id'] : 0;
+        $iCount = isset($aReports['count']) ? (int)$aReports['count'] : 0;
+        if($sSystem == '' || $iObjectId == 0)
+            return false;
+
+        return array($sSystem, $iObjectId, $iCount);
+    }
+
+    public function getCommentsData(&$aComments)
+    {
+        if(empty($aComments) || !is_array($aComments))
+            return false;
+
+        $sSystem = isset($aComments['system']) ? $aComments['system'] : '';
+        $iObjectId = isset($aComments['object_id']) ? (int)$aComments['object_id'] : 0;
+        $iCount = isset($aComments['count']) ? (int)$aComments['count'] : 0;
+        if($sSystem == '' || $iObjectId == 0 || ($iCount == 0 && !isLogged()))
+            return false;
+
+        return array($sSystem, $iObjectId, $iCount);
+    }
+
+    public function getEventLinks($iEventId)
+    {
+        $aLinks = $this->_oDb->getLinks($iEventId);
+        if(empty($aLinks) || !is_array($aLinks))
+            return array();
+
+        $oTranscoder = BxDolTranscoderImage::getObjectInstance($this->_oConfig->getObject('transcoder_photos_preview'));
+
+        $aResult = array();
+        foreach($aLinks as $aLink)
+            $aResult[] = array(
+                'url' => $aLink['url'],
+                'title' => $aLink['title'],
+                'text' => $aLink['text'],
+                'thumbnail' => (int)$aLink['media_id'] != 0 ? $oTranscoder->getFileUrl($aLink['media_id']) : ''
+            );
+
+        return $aResult;
+    }
+
+    public function getEventImages($iEventId)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $aPhotos = $this->_oDb->getMedia($CNF['FIELD_PHOTO'], $iEventId);
+        if(empty($aPhotos) || !is_array($aPhotos))
+            return array();
+
+        $oTranscoder = BxDolTranscoderImage::getObjectInstance($this->_oConfig->getObject('transcoder_photos_view'));
+        $oTranscoderMedium = BxDolTranscoderImage::getObjectInstance($this->_oConfig->getObject('transcoder_photos_medium'));
+        $oTranscoderBig = BxDolTranscoderImage::getObjectInstance($this->_oConfig->getObject('transcoder_photos_big'));
+
+        $aResult = array();
+        foreach($aPhotos as $iPhotoId) {
+            $sPhotoSrc = $oTranscoder->getFileUrl($iPhotoId);
+            $sPhotoSrcMedium = $oTranscoderMedium->getFileUrl($iPhotoId);
+            $sPhotoSrcBig = $oTranscoderBig->getFileUrl($iPhotoId);
+            if(empty($sPhotoSrcMedium) && !empty($sPhotoSrc))
+                $sPhotoSrcMedium = $sPhotoSrc;
+            if(empty($sPhotoSrcBig) && !empty($sPhotoSrcMedium))
+                $sPhotoSrcBig = $sPhotoSrcMedium;
+
+            $aResult[] = array(
+                'id' => $iPhotoId,
+                'src' => $sPhotoSrc,
+                'src_medium' => $sPhotoSrcMedium,
+                'src_orig' => $sPhotoSrcBig,
+            );
+        }
+
+        return $aResult;
+    }
+
+    public function getEventVideos($iEventId)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $aMediaIds = $this->_oDb->getMedia($CNF['FIELD_VIDEO'], $iEventId);
+        if(empty($aMediaIds) || !is_array($aMediaIds))
+            return array();
+
+        $oStorage = BxDolStorage::getObjectInstance($this->_oConfig->getObject('storage_videos'));
+
+        $oTranscoderPoster = BxDolTranscoderVideo::getObjectInstance($this->_oConfig->getObject('transcoder_videos_poster'));
+        $oTranscoderMp4 = BxDolTranscoderVideo::getObjectInstance($this->_oConfig->getObject('transcoder_videos_mp4'));
+        $oTranscoderMp4Hd = BxDolTranscoderVideo::getObjectInstance($this->_oConfig->getObject('transcoder_videos_mp4_hd'));
+
+        $oTranscoderPhoto = BxDolTranscoderImage::getObjectInstance($this->_oConfig->getObject('transcoder_videos_photo_view'));
+        $oTranscoderPhotoBig = BxDolTranscoderImage::getObjectInstance($this->_oConfig->getObject('transcoder_videos_photo_big'));
+
+        $aResult = array();
+        foreach($aMediaIds as $iMediaId) {
+            $aMediaFile = $oStorage->getFile($iMediaId);
+
+            $bVideoFile = strncmp('video/', $aMediaFile['mime_type'], 6) === 0 && $oTranscoderPoster->isMimeTypeSupported($aMediaFile['mime_type']);
+            if($bVideoFile) {
+                $sVideoUrlHd = '';
+                if (!empty($aMediaFile['dimensions']) && $oTranscoderMp4Hd->isProcessHD($aMediaFile['dimensions']))
+                    $sVideoUrlHd = $oTranscoderMp4Hd->getFileUrl($iMediaId);
+
+                $aResult[$iMediaId] = array(
+                    'id' => $iMediaId,
+                    'src_poster' => $oTranscoderPoster->getFileUrl($iMediaId),
+                    'src_mp4' => $oTranscoderMp4->getFileUrl($iMediaId),
+                    'src_mp4_hd' => $sVideoUrlHd,
+                );
+            }
+
+            $bImageFile = strncmp('image/', $aMediaFile['mime_type'], 6) === 0 && $oTranscoderPhoto->isMimeTypeSupported($aMediaFile['mime_type']);
+            if($bImageFile) {
+                $sPhotoSrc = $oTranscoderPhoto->getFileUrl($iMediaId);
+                $sPhotoSrcBig = $oTranscoderPhotoBig->getFileUrl($iMediaId);
+                if(empty($sPhotoSrcBig) && !empty($sPhotoSrc))
+                    $sPhotoSrcBig = $sPhotoSrc;
+
+                $aResult[$iMediaId] = array(
+                    'id' => $iMediaId,
+                    'src' => $sPhotoSrc,
+                    'src_orig' => $sPhotoSrcBig,
+                );
+            }
+        }
+
+        return $aResult;
+    }
+	
+    public function getEventFiles($iEventId)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $aFiles = $this->_oDb->getMedia($CNF['FIELD_FILE'], $iEventId);
+		
+        if(empty($aFiles) || !is_array($aFiles))
+            return [];
+
+        $oStorage = BxDolStorage::getObjectInstance($this->_oConfig->getObject('storage_files'));
+		
+        $aResult = [];
+        foreach($aFiles as $iFileId) {
+            $sFileUrl = $oStorage->getFileUrlById($iFileId);
+            $aFileFile = $oStorage->getFile($iFileId);
+
+            $aResult[$iFileId] = [
+                'id' => $iFileId,
+                'src' => $this->_oTemplate->getIconUrl($oStorage->getIconNameByFileName($aFileFile['file_name'])),
+                'src_medium' => '',
+                'src_orig' => '',
+                'url' => $sFileUrl,
+                'title' => $aFileFile['file_name']
+            ];
+        }
+
+        return $aResult;
+    }
+
+    /**
+     * Protected Methods 
+     */
+    protected function _serviceGetBlockView($iProfileId = 0, $aBrowseParams = array())
+    {
+        if(empty($iProfileId) && bx_get('profile_id') !== false)
+            $iProfileId = bx_process_input(bx_get('profile_id'), BX_DATA_INT);
+
+        if(empty($iProfileId) && isLogged())
+            $iProfileId = bx_get_logged_profile_id();
+
+        $aBrowseParams['owner_id'] = $iProfileId;
+
+        $aBlock = $this->_getBlockView($aBrowseParams);
+        if(!empty($aBlock))
+            return $aBlock;
+
+        return array('content' => MsgBox(_t('_bx_timeline_txt_msg_no_results')));
+    }
+
+    protected function _serviceGetBlockViewProfile($sProfileModule = 'bx_persons', $iProfileContentId = 0, $aBrowseParams = array())
+    {
+        if(empty($sProfileModule))
+            return array();
+
+        if(empty($iProfileContentId) && bx_get('id') !== false)
+            $iProfileContentId = bx_process_input(bx_get('id'), BX_DATA_INT);
+
+        $oProfile = BxDolProfile::getInstanceByContentAndType($iProfileContentId, $sProfileModule);
+        if(empty($oProfile))
+            return array();
+
+        $aBrowseParams['owner_id'] = $oProfile->id();
+
+        return $this->_getBlockView($aBrowseParams);
+    }
+
+    protected function _serviceGetBlockViews($aBrowseParams = array())
+    {
+        $aParams = $this->_prepareParams($aBrowseParams);
+
+        if(($sType = $this->_oConfig->getUserChoice('type')) !== false)
+            $aParams['type'] = $sType;
+
+        $this->_iOwnerId = $aParams['owner_id'];
+
+        return $this->_oTemplate->getViewsBlock($aParams);
+    }
+
+    protected function _serviceGetBlockViewHome($aBrowseParams = array())
+    {
+        $sRssUrl = BX_DOL_URL_ROOT . $this->_oConfig->getBaseUri() . 'rss/' . $aBrowseParams['type'] . '/';
+        BxDolTemplate::getInstance()->addPageRssLink(_t('_bx_timeline_page_title_view_home'), $sRssUrl);
+
+        return $this->_serviceGetBlockViewByType($aBrowseParams);
+    }
+
+    protected function _serviceGetBlockViewHot($aBrowseParams = array())
+    {
+        $sRssUrl = BX_DOL_URL_ROOT . $this->_oConfig->getBaseUri() . 'rss/' . $aBrowseParams['type'] . '/';
+        BxDolTemplate::getInstance()->addPageRssLink(_t('_bx_timeline_page_title_view_hot'), $sRssUrl);
+
+        return $this->_serviceGetBlockViewByType($aBrowseParams);
+    }
+
+    protected function _serviceGetBlockViewByType($aBrowseParams = array())
+    {
+        $aParams = $this->_prepareParams($aBrowseParams);
+
+        $this->_iOwnerId = $aParams['owner_id'];
+
+        return array(
+            'content' => $this->_oTemplate->getViewBlock($aParams)
+        );
+    }
+
+    protected function _getBlockPost($iProfileId, $aParams = array())
+    {
+        $this->_iOwnerId = $iProfileId;
+
+        if($this->isAllowedPost() !== true)
+            return array();
+
+        return array(
+            'content' => $this->_oTemplate->getPostBlock($this->_iOwnerId, $aParams)
+        );
+    }
+
+    protected function _getBlockView($aBrowseParams = array())
+    {
+        if(empty($aBrowseParams['owner_id']))
+            return array();
+
+        $aParams = $this->_prepareParams($aBrowseParams);
+        if(empty($aParams['per_page']))
+            $aParams['per_page'] = $this->_oConfig->getPerPage('profile');
+
+        $this->_iOwnerId = $aParams['owner_id'];
+        $oProfileOwner = BxDolProfile::getInstance($this->_iOwnerId);
+        if(!$oProfileOwner)
+            return array();
+
+        $mixedResult = $oProfileOwner->checkAllowedProfileView();
+        if($mixedResult !== CHECK_ACTION_RESULT_ALLOWED) {
+            $this->_oTemplate->displayAccessDenied($mixedResult);
+            exit;
+        }
+
+        $sUserName = $this->getObjectUser($aParams['owner_id'])->getDisplayName();
+
+        $sView = $aParams['view'];
+        $sRssUrl = BX_DOL_URL_ROOT . $this->_oConfig->getBaseUri() . 'rss/' . BX_BASE_MOD_NTFS_TYPE_OWNER . '/' . $this->_iOwnerId . '/';
+        $sJsObject = $this->_oConfig->getJsObjectView($aParams);
+        $aMenu = array(
+            array('id' => $sView . '-view-all', 'name' => $sView . '-view-all', 'class' => '', 'link' => 'javascript:void(0)', 'onclick' => 'javascript:' . $sJsObject . '.changeFilter(this)', 'target' => '_self', 'title' => _t('_bx_timeline_menu_item_view_all'), 'active' => 1),
+            array('id' => $sView . '-view-owner', 'name' => $sView . '-view-owner', 'class' => '', 'link' => 'javascript:void(0)', 'onclick' => 'javascript:' . $sJsObject . '.changeFilter(this)', 'target' => '_self', 'title' => _t('_bx_timeline_menu_item_view_owner', $sUserName)),
+            array('id' => $sView . '-view-other', 'name' => $sView . '-view-other', 'class' => '', 'link' => 'javascript:void(0)', 'onclick' => 'javascript:' . $sJsObject . '.changeFilter(this)', 'target' => '_self', 'title' => _t('_bx_timeline_menu_item_view_other')),
+            array('id' => $sView . '-get-rss', 'name' => $sView . '-get-rss', 'class' => '', 'link' => $sRssUrl, 'onclick' => '', 'target' => '_blank', 'title' => _t('_bx_timeline_menu_item_get_rss')),
+        );
+
+        $sContent = '';
+        bx_alert($oProfileOwner->getModule(), $this->_oConfig->getUri() . '_view', $this->_iOwnerId, $this->getUserId(), array('override_content' => &$sContent, 'params' => &$aParams, 'menu' => &$aMenu));
+
+        $oMenu = new BxTemplMenuInteractive(array('template' => 'menu_interactive_vertical.html', 'menu_id'=> $sView . '-view-all', 'menu_items' => $aMenu));
+        $oMenu->setSelected('', $sView . '-view-all');
+
+        if (!$sContent)
+            $sContent = $this->_oTemplate->getViewBlock($aParams);
+
+        BxDolTemplate::getInstance()->addPageRssLink(_t('_bx_timeline_page_title_view'), $sRssUrl);
+
+        return array('content' => $sContent, 'menu' => $oMenu);
+    }
+    
+    protected function _getContentForTimelinePost($aEvent, $aContentInfo, $aBrowseParams = array())
+    {
+    	$CNF = &$this->_oConfig->CNF;
+
+        $iId = (int)$aContentInfo[$CNF['FIELD_ID']];
+    	$sUrl = BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink('page.php?i=' . $CNF['URI_VIEW_ENTRY'] . '&id=' . $iId);
+
+        $sText = ''; 
+        if(isset($aContentInfo['content'])){
+            $aTmp = unserialize($aContentInfo['content']);
+            if(isset($aTmp['text']))
+                $sText = $aTmp['text'];
+        }
+
+        if(empty($sText) && !empty($aContentInfo[$CNF['FIELD_TITLE']]))
+            $sText = $aContentInfo[$CNF['FIELD_TITLE']];
+
+        if(!empty($CNF['OBJECT_METATAGS']) && !empty($sText)) {
+            $oMetatags = BxDolMetatags::getObjectInstance($CNF['OBJECT_METATAGS']);
+            $sText = $oMetatags->metaParse($iId, $sText);
+        }
+
+        return array(
+            'sample' => isset($CNF['T']['txt_sample_single_with_article']) ? $CNF['T']['txt_sample_single_with_article'] : $CNF['T']['txt_sample_single'],
+            'sample_wo_article' => $CNF['T']['txt_sample_single'],
+            'sample_action' => isset($CNF['T']['txt_sample_action']) ? $CNF['T']['txt_sample_action'] : '',
+            'url' => $sUrl,
+            'title' => '',
+            'text' => $sText,
+            'links' => $this->getEventLinks($iId),
+            'images' => array(),
+            'images_attach' => $this->getEventImages($iId),
+            'videos' => array(),
+            'videos_attach' => $this->getEventVideos($iId),
+            'files' => array(),
+            'files_attach' => $this->getEventFiles($iId)
+        );
+    }
+
+    protected function _isAllowedRepost($aEvent, $bPerform = false)
+    {
+        $iUserId = (int)$this->getUserId();
+        if($iUserId == 0)
+            return false;
+
+        $iPrivacy = (int)$aEvent['object_privacy_view'];
+        if($iPrivacy >= 0 && !in_array($iPrivacy, [BX_DOL_PG_ALL, BX_DOL_PG_MEMBERS]))
+            return false;         
+
+        if(isAdmin())
+            return true;
+
+        $aCheckResult = checkActionModule($iUserId, 'repost', $this->getName(), $bPerform);
+        if(!empty($aEvent['owner_id']) && ($oProfileOwner = BxDolProfile::getInstance($aEvent['owner_id'])) !== false)
+            bx_alert($oProfileOwner->getModule(), $this->_oConfig->getUri() . '_repost', $oProfileOwner->id(), $iUserId, array('check_result' => &$aCheckResult));
+
+        return $aCheckResult[CHECK_ACTION_RESULT] !== CHECK_ACTION_RESULT_ALLOWED ? $aCheckResult[CHECK_ACTION_MESSAGE] : true;
+    }
+
+    protected function _isAllowedMute($bPerform = false)
+    {
+    	if($this->_iProfileId == 0)
+            return false;
+
+        if(isAdmin())
+           return true;
+
+        $aCheckResult = checkActionModule($this->_iProfileId, 'mute', $this->getName(), $bPerform);
+        return $aCheckResult[CHECK_ACTION_RESULT] !== CHECK_ACTION_RESULT_ALLOWED ? $aCheckResult[CHECK_ACTION_MESSAGE] : true;
+    }
+
+    protected function _isAllowedPin($aEvent, $bPerform = false)
+    {
+    	$iUserId = (int)$this->getUserId();
+    	if($iUserId == 0)
+    		return false;
+
+		if(isAdmin() || (int)$aEvent['owner_id'] == $iUserId || ((int)$aEvent['owner_id'] == 0 && $this->_oConfig->isCommon($aEvent['type'], $aEvent['action']) && (int)$aEvent['object_id'] == $iUserId))
+           return true;
+
+        $aCheckResult = checkActionModule($iUserId, 'pin', $this->getName(), $bPerform);
+        if(!empty($aEvent['owner_id']) && ($oProfileOwner = BxDolProfile::getInstance($aEvent['owner_id'])) !== false) {
+            if (BxDolService::call($oProfileOwner->getModule(), 'check_allowed_module_action_in_profile', array($oProfileOwner->getContentId(), $this->getName(), 'pin')) === CHECK_ACTION_RESULT_ALLOWED) {
+                return true;
+            }
+            bx_alert($oProfileOwner->getModule(), $this->_oConfig->getUri() . '_pin', $oProfileOwner->id(), $iUserId, array('check_result' => &$aCheckResult));
+        }
+
+        return $aCheckResult[CHECK_ACTION_RESULT] !== CHECK_ACTION_RESULT_ALLOWED ? $aCheckResult[CHECK_ACTION_MESSAGE] : true;
+    }
+
+    protected function _isAllowedStick($aEvent, $bPerform = false)
+    {
+    	$iUserId = (int)$this->getUserId();
+    	if($iUserId == 0)
+    		return false;
+
+    	if(isAdmin())
+    		return true;
+
+    	$aCheckResult = checkActionModule($iUserId, 'stick', $this->getName(), $bPerform);
+    	if(!empty($aEvent['owner_id']) && ($oProfileOwner = BxDolProfile::getInstance($aEvent['owner_id'])) !== false)
+            bx_alert($oProfileOwner->getModule(), $this->_oConfig->getUri() . '_stick', $oProfileOwner->id(), $iUserId, array('check_result' => &$aCheckResult));
+    
+    	return $aCheckResult[CHECK_ACTION_RESULT] !== CHECK_ACTION_RESULT_ALLOWED ? $aCheckResult[CHECK_ACTION_MESSAGE] : true;
+    }
+
+    protected function _isAllowedPromote($aEvent, $bPerform = false)
+    {
+        if(isAdmin())
+            return true;
+
+        $iUserId = (int)$this->getUserId();
+        if($iUserId == 0)
+            return false;
+
+        $aCheckResult = checkActionModule($iUserId, 'promote', $this->getName(), $bPerform);
+        if(!empty($aEvent['owner_id']) && ($oProfileOwner = BxDolProfile::getInstance($aEvent['owner_id'])) !== false)
+            bx_alert($oProfileOwner->getModule(), $this->_oConfig->getUri() . '_promote', $oProfileOwner->id(), $iUserId, array('check_result' => &$aCheckResult));
+
+        return $aCheckResult[CHECK_ACTION_RESULT] !== CHECK_ACTION_RESULT_ALLOWED ? $aCheckResult[CHECK_ACTION_MESSAGE] : true;
+    }
+
+    protected function _addLink(&$oForm)
+    {
+        $iUserId = $this->getUserId();
+
+        $iEventId = (int)$oForm->getCleanValue('event_id');
+        $sLink = rtrim($oForm->getCleanValue('url'), '/');
+        $sHost = parse_url($sLink, PHP_URL_HOST);
+        if ($sHost && is_private_ip(gethostbyname($sHost)))
+            return array('message' => _t('_sys_txt_error_occured'));
+
+        $aMatches = array();
+        preg_match($this->_oConfig->getPregPattern('url'), $sLink, $aMatches);
+        $sLink = (empty($aMatches[2]) ? 'http://' : '') . $aMatches[0];
+
+        $aSiteInfo = bx_get_site_info($sLink, array(
+            'thumbnailUrl' => array('tag' => 'link', 'content_attr' => 'href'),
+            'OGImage' => array('name_attr' => 'property', 'name' => 'og:image'),
+        ));
+
+        $sTitle = !empty($aSiteInfo['title']) ? $aSiteInfo['title'] : _t('_Empty');
+        $sDescription = !empty($aSiteInfo['description']) ? $aSiteInfo['description'] : _t('_Empty');
+
+        $sMediaUrl = '';
+        if(!empty($aSiteInfo['thumbnailUrl']))
+            $sMediaUrl = $aSiteInfo['thumbnailUrl'];
+        else if(!empty($aSiteInfo['OGImage']))
+            $sMediaUrl = $aSiteInfo['OGImage'];
+
+        $iMediaId = 0;
+        $oStorage = null;
+        if(!empty($sMediaUrl)) {
+            $oStorage = BxDolStorage::getObjectInstance($this->_oConfig->getObject('storage_photos'));
+
+            $iMediaId = $oStorage->storeFileFromUrl($sMediaUrl, true, $iUserId);
+        }
+
+        $iId = (int)$oForm->insert(array('profile_id' => $iUserId, 'media_id' => $iMediaId, 'url' => $sLink, 'title' => $sTitle, 'text' => $sDescription, 'added' => time()));
+        if(!empty($iId)) {
+            if(!empty($oStorage) && !empty($iMediaId))
+                $oStorage->afterUploadCleanup($iMediaId, $iUserId);
+
+            return array(
+                'id' => $iId, 
+                'event_id' => $iEventId, 
+                'url' => $sLink,
+                'item' => $this->_oTemplate->getAttachLinkItem($iUserId, $iId)
+            );
+        }
+
+        return array('message' => _t('_bx_timeline_txt_err_cannot_perform_action'));
+    }
+
+    protected function _deleteLinks($iId)
+    {
+        $aLinks = $this->_oDb->getLinks($iId);
+        if(empty($aLinks) || !is_array($aLinks))
+            return;
+
+        $oStorage = BxDolStorage::getObjectInstance($this->_oConfig->getObject('storage_photos'));
+        foreach($aLinks as $aLink)
+            if(!empty($aLink['media_id']))
+                $oStorage->deleteFile($aLink['media_id']);
+
+        $this->_oDb->deleteLinks($iId);
+    }
+
+    protected function _saveMedia($sType, $iContentId, $aItemIds, $iProfileId = 0, $isAssociateWithContent = false)
+    {
+        if(empty($iContentId))
+            return;
+
+        if(!$isAssociateWithContent)
+            $this->_oDb->deleteMedia($sType, $iContentId);
+
+    	if(empty($aItemIds) || !is_array($aItemIds))
+            return; 
+
+        if(empty($iProfileId))
+            $iProfileId = $this->_iProfileId;
+
+        $oStorage = BxDolStorage::getObjectInstance($this->_oConfig->getObject('storage_' . strtolower($sType) . 's'));
+        $aGhostFiles = $oStorage->getGhosts ($iProfileId, !$isAssociateWithContent ? $iContentId : 0, true, $this->_isModerator());
+        if(empty($aGhostFiles) || !is_array($aGhostFiles))
+            return;
+
+        foreach($aGhostFiles as $aFile) {
+            if(is_array($aItemIds) && !in_array($aFile['id'], $aItemIds))
+                continue;
+
+            $iFileId = (int)$aFile['id'];
+
+            if($aFile['private'])
+                $oStorage->setFilePrivate($iFileId, 1);
+
+            $oStorage->updateGhostsContentId($iFileId, $iProfileId, $iContentId, $this->_isModerator());
+
+            $this->_oDb->saveMedia($sType, $iContentId, $iFileId);
+        }
+    }
+
+    protected function _deleteMedia($sType, $iContentId)
+    {
+        $aItems = $this->_oDb->getMedia($sType, $iContentId);
+        if(empty($aItems) || !is_array($aItems))
+            return;
+
+        $oStorage = BxDolStorage::getObjectInstance($this->_oConfig->getObject('storage_' . strtolower($sType) . 's'));
+        foreach($aItems as $iItemId)
+            $oStorage->deleteFile($iItemId);
+
+        $this->_oDb->deleteMedia($sType, $iContentId);
+    }
+
+    protected function _prepareParams($aParams)
+    {
+        if(empty($aParams['name']))
+            $aParams['name'] = '';
+        
+        if(empty($aParams['view']))
+            $aParams['view'] = BX_TIMELINE_VIEW_DEFAULT;
+
+        if(empty($aParams['type']))
+            $aParams['type'] = BX_TIMELINE_TYPE_DEFAULT;
+
+        if(empty($aParams['owner_id']))
+            $aParams['owner_id'] = $this->getUserId();
+
+        if(!isset($aParams['start']) || (int)$aParams['start'] < 0)
+            $aParams['start'] = 0;
+
+        if(!isset($aParams['per_page']) || (int)$aParams['per_page'] <= 0)
+            $aParams['per_page'] = isset($aParams['per_page_default']) && (int)$aParams['per_page_default'] > 0 ? $aParams['per_page_default'] : $this->_oConfig->getPerPage();
+
+        if(empty($aParams['timeline']) || (int)$aParams['timeline'] < 0)
+            $aParams['timeline'] = 0;
+
+        if(empty($aParams['filter']))
+            $aParams['filter'] = BX_TIMELINE_FILTER_ALL;
+
+        if(empty($aParams['modules']) || !is_array($aParams['modules']))
+            $aParams['modules'] = array();
+
+        if(empty($aParams['context']))
+            $aParams['context'] = 0;
+
+        if(empty($aParams['blink']) || !is_array($aParams['blink']))
+            $aParams['blink'] = array();
+
+        $iViewerId = $this->getUserId();
+        if(empty($aParams['viewer_id']) || (int)$aParams['viewer_id'] != $iViewerId)
+            $aParams['viewer_id'] = $iViewerId;
+
+        $aParams = array_merge($aParams, array(
+            'browse' => 'list',
+            'status' => BX_TIMELINE_STATUS_ACTIVE,
+            'moderator' => $this->isModeratorForProfile($aParams['viewer_id']),
+            'dynamic_mode' => false,
+        ));
+
+        return $aParams;
+    }
+
+    protected function _prepareParamsGet($mParams = false)
+    {
+        $aKeys = ['name', 'view', 'type', 'owner_id', 'start', 'per_page', 'timeline', 'filter', 'modules', 'context', 'blink', 'viewer_id'];
+
+        $aParams = [];
+        if(!empty($mParams) && is_array($mParams))
+            foreach($aKeys as $sKey)
+                $aParams[$sKey] = isset($mParams[$sKey]) ? $mParams[$sKey] : false;
+        else
+            foreach($aKeys as $sKey)
+                $aParams[$sKey] = bx_get($sKey);
+
+        $aParams['name'] = $this->_oConfig->processParam($aParams['name']);
+        $aParams['view'] = $this->_oConfig->processParamWithDefault($aParams['view'], BX_TIMELINE_VIEW_DEFAULT);
+        $aParams['type'] = $this->_oConfig->processParamWithDefault($aParams['type'], BX_TIMELINE_TYPE_DEFAULT);
+        $aParams['owner_id'] = $aParams['owner_id'] !== false ? bx_process_input($aParams['owner_id'], BX_DATA_INT) : $this->getUserId();
+        $aParams['start'] = $aParams['start'] !== false ? bx_process_input($aParams['start'], BX_DATA_INT) : 0;
+        $aParams['per_page'] = $aParams['per_page'] !== false ? bx_process_input($aParams['per_page'], BX_DATA_INT) : $this->_oConfig->getPerPage();
+        $aParams['timeline'] = $aParams['timeline'] !== false ? bx_process_input($aParams['timeline']) : '';
+        $aParams['filter'] = $aParams['filter'] !== false ? bx_process_input($aParams['filter'], BX_DATA_TEXT) : BX_TIMELINE_FILTER_ALL;
+        $aParams['modules'] = $aParams['modules'] !== false ? bx_process_input($aParams['modules'], BX_DATA_TEXT) : [];
+        $aParams['context'] = $aParams['context'] !== false ? bx_process_input($aParams['context'], BX_DATA_INT) : 0;
+
+        if($aParams['blink'] !== false)
+            $aParams['blink'] = bx_process_input(is_string($aParams['blink']) ? explode(',', $aParams['blink']) : $aParams['blink'], BX_DATA_TEXT);
+        else
+            $aParams['blink'] = [];
+
+        $iViewerId = $this->getUserId();
+        if($aParams['viewer_id'] !== false)
+            $aParams['viewer_id'] = bx_process_input($aParams['viewer_id'], BX_DATA_INT);
+        if(!$aParams['viewer_id'] || $aParams['viewer_id'] != $iViewerId)
+            $aParams['viewer_id'] = $iViewerId;
+
+        $aParams = array_merge($aParams, [
+            'browse' => 'list',
+            'status' => BX_TIMELINE_STATUS_ACTIVE,
+            'moderator' => $this->isModeratorForProfile($aParams['viewer_id']),
+            'dynamic_mode' => true,
+        ]);
+
+        return $aParams;
+    }
+
+    protected function _prepareTextForSave($s)
+    {
+        return bx_process_input($s, BX_DATA_HTML);
+    }
+
+    protected function _prepareFormForAutoSubmit(&$oForm, &$aValues)
+    {
+        $oForm->aFormAttrs['method'] = BX_DOL_FORM_METHOD_SPECIFIC;
+        $oForm->aParams['csrf']['disable'] = true;
+        if(!empty($oForm->aParams['db']['submit_name'])) {
+            $sSubmitName = $sSubmitValue = false;
+            if(is_array($oForm->aParams['db']['submit_name'])) {
+                foreach ($oForm->aParams['db']['submit_name'] as $sName) {
+                    if(isset($oForm->aInputs[$sName])) {
+                        $sSubmitName = $sName;
+                        $sSubmitValue = $oForm->aInputs[$sName]['value'];
+                        break;
+                    }
+                    else if(isset($oForm->aInputs['controls'])) 
+                        foreach($oForm->aInputs['controls'] as $mixedKey => $mixedInput)
+                            if(is_numeric($mixedKey) && isset($mixedInput['name']) && $mixedInput['name'] == $sName) {
+                                $sSubmitName = $sName;
+                                $sSubmitValue = $mixedInput['value'];
+                                break 2;
+                            }
+                }
+            }
+            else {
+                $sName = $oForm->aParams['db']['submit_name'];
+                if(isset($oForm->aInputs[$sName])) {
+                    $sSubmitName = $sName;
+                    $sSubmitValue = $oForm->aInputs[$sName]['value'];
+                }
+                else if(isset($oForm->aInputs['controls']))
+                    foreach($oForm->aInputs['controls'] as $mixedKey => $mixedInput)
+                        if(is_numeric($mixedKey) && isset($mixedInput['name']) && $mixedInput['name'] == $sName) {
+                            $sSubmitName = $sName;
+                            $sSubmitValue = $mixedInput['value'];
+                            break;
+                        }
+            }
+
+            if($sSubmitName && $sSubmitValue)
+                $aValues[$sSubmitName] = $sSubmitValue;
+        }
+    }
+
+    protected function _getFieldValue($sField, $iContentId)
+    {
+        $CNF = &$this->_oConfig->CNF;
+        if(empty($CNF[$sField]))
+            return false;
+
+        $aEvent = $this->_oDb->getEvents(array('browse' => 'id', 'value' => $iContentId));
+        if(empty($aEvent) || empty($aEvent[$CNF[$sField]]))
+            return false;
+
+        return $aEvent[$CNF[$sField]];
+    }
+
+    /**
+     * Returns records for React Jot using OAuth2
+     * @param int $iProfileId
+     * @param string $sPage
+     * @param string $sTab
+     * @param int $iStart
+     * @param int $iPerPage
+     * @return array
+     */
+    public function serviceGetUserPosts($iProfileId = 0, $sPage = 'home', $sTab = 'hot', $iStart = 0, $iPerPage = 0)
+    {
+        $iProfileId = (int)$iProfileId ? (int)$iProfileId : bx_get_logged_profile_id();
+        if(empty($iProfileId))
+            return array(
+                'code' => 1,
+                'result' => array(),
+                'message' => _t('_bx_timeline_txt_msg_no_profile_id'),
+                'page' => $sPage,
+                'tab' => $sTab
+            );
+
+        $sType = BX_TIMELINE_TYPE_OWNER_AND_CONNECTIONS;
+        $sView = BX_TIMELINE_VIEW_DEFAULT;
+        $sFilter = BX_TIMELINE_FILTER_ALL;
+
+        $aModules = array();
+
+        switch($sPage){
+            case 'profile':
+                $sType = BX_BASE_MOD_NTFS_TYPE_OWNER;
+                $sFilter = BX_TIMELINE_FILTER_OWNER;
+                break;
+            default:
+                if ($this -> _oDb -> isModuleByName($sPage))
+                   $aModules = array($sPage);
+        }
+
+        switch($sTab)
+        {
+            case 'latest':
+                $sType = BX_BASE_MOD_NTFS_TYPE_PUBLIC;
+                break;
+            case 'popular':
+                $sType = BX_TIMELINE_TYPE_HOT;
+                break;
+            case 'feed':
+                $sType = BX_TIMELINE_TYPE_OWNER_AND_CONNECTIONS;
+                break;
+            default:
+                if ($this -> _oDb -> isModuleByName($sTab))
+                    $aModules = array($sTab);
+        }
+
+        $aParams = $this->getParams($sView, $sType, $iProfileId, $iStart, $iPerPage, $sFilter, $aModules);
+        $aEvents = $this->_oDb->getEvents($aParams);
+        $iCount = $this->_oDb->getEvents(array_merge($aParams, array('count' => true)));
+
+        if(empty($aEvents) || !is_array($aEvents))
+            return array(
+                'code' => 0,
+                'result' => array(),
+                'message' => _t('_bx_timeline_txt_msg_no_results'),
+                'page' => $sPage,
+                'tab' => $sTab
+            );
+
+        $aBrowseParams = array();
+        $aItems = array();
+
+        foreach($aEvents as $aEvent) {
+            $aResult = $this->_oTemplate->getData($aEvent, $aBrowseParams);
+
+            if($aResult === false)
+                continue;
+
+            $oOwnerProfile = BxDolProfile::getInstance($aResult['owner_id']);
+
+            $aFiles = array();
+            $aContent = &$aResult['content'];
+
+            if (!empty($aContent['image']))
+                $aFiles['images'] = array_values($aContent['images']);
+            if (!empty($aContent['images_attach']))
+                $aFiles['images'] = array_values($aContent['images_attach']);
+
+            if (!empty($aContent['videos']))
+                $aFiles['videos'] = array_values($aContent['videos']);
+            else
+            if (!empty($aContent['videos_attach']))
+                $aFiles['videos'] = array_values($aContent['videos_attach']);
+
+            if (!empty($aContent['files']))
+                $aFiles['files'] = array_values($aContent['files']);
+            else
+                if (!empty($aContent['files_attach']))
+                    $aFiles['files'] = array_values($aContent['files_attach']);
+
+            $aItems[$aEvent['id']] = array_merge(array(
+                'owner' => array(
+                    'icon' => $oOwnerProfile -> getThumb(),
+                    'name' => $oOwnerProfile -> getDisplayName(),
+                    'url' => $oOwnerProfile -> getUrl()
+                ),
+                'sample' => !empty($aResult['sample']) ? _t($aResult['sample']) : _t('_bx_timeline_txt_sample'),
+                'sample_action' => !empty($aResult['sample_action']) ? _t($aResult['sample_action']) : _t('_bx_timeline_txt_added_sample'),
+                'url' => isset($aResult['url']) ? $aResult['url'] : '',
+                'raw' => isset($aContent['raw']) ? strip_tags($aContent['raw']) : '',
+                'text' => isset($aContent['text']) ? strip_tags($aContent['text']) : '',
+                'views' => isset($aResult['views']['count']) ? (int)$aResult['views']['count'] : 0,
+                'votes' => isset($aResult['votes']['count']) ? (int)$aResult['votes']['count'] : 0,
+                'reactions' => isset($aResult['reactions']['count']) ? (int)$aResult['reactions']['count'] : 0,
+                'scores' => isset($aResult['scores']['count']) ? (int)$aResult['scores']['count'] : 0,
+                'reports' => isset($aResult['reports']['count']) ? (int)$aResult['reports']['count'] : 0,
+                'comments' => isset($aResult['comments']['count']) ? (int)$aResult['comments']['count'] : 0,
+                'date' => isset($aResult['date']) ? $aResult['date'] : $aEvent['date'],
+                'type' => stripos($aEvent['type'], 'timeline') !== false ? 'bx_timeline' : $aEvent['type'],
+                'event_type' => $aEvent['type'],
+                'id' => $aEvent['id'],
+                'content' => $aResult['content'],
+                'title' => isset($aResult['title']) ? _t($aResult['title']) : '',
+                'description' => isset($aResult['description']) ? $aResult['description'] : ''
+            ), $aFiles);
+        }
+
+        return array(
+            'result' => $aItems,
+            'code' => 0,
+            'message' => '',
+            'page' => $sPage,
+            'tab' => $sTab,
+            'total' => $iCount,
+            'start' => (int)$iStart
+        );
+    }
+}
+
+/** @} */

+ 51 - 0
modules/boonex/timeline/updates/13.0.4_13.0.5/source/classes/BxTimelinePageViewItem.php

@@ -0,0 +1,51 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Timeline Timeline
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxTimelinePageViewItem extends BxBaseModTextPageAuthor
+{
+    protected $_sModule;
+    protected $_oModule;
+
+    protected $_iItemId;
+
+    public function __construct($aObject, $oTemplate = false)
+    {
+        $this->_sModule = 'bx_timeline';
+        $this->_oModule = BxDolModule::getInstance($this->_sModule);
+
+        parent::__construct($aObject, $this->_oModule->_oTemplate);
+
+        $iItemId = bx_process_input(bx_get('id'), BX_DATA_INT);
+        if(!$iItemId) 
+            return;
+
+        $this->_iItemId = $iItemId;
+    }
+
+    public function getCode()
+    {
+        $aItemData = $this->_oModule->getItemData($this->_iItemId);
+
+        if($aItemData['code'] != 0) {
+            if($aItemData['code'] == 1)
+                $this->_oTemplate->displayPageNotFound();
+            else
+                $this->_oTemplate->displayMsg($aItemData['content']);
+            exit;
+        }
+
+        BxDolTemplate::getInstance()->setPageUrl('page.php?i=' . $this->_aObject['uri'] . '&id=' . $this->_iItemId);
+
+        return parent::getCode();
+    }
+}
+
+/** @} */

+ 349 - 0
modules/boonex/timeline/updates/13.0.4_13.0.5/source/classes/BxTimelineResponse.php

@@ -0,0 +1,349 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Timeline Timeline
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxTimelineResponse extends BxBaseModNotificationsResponse
+{
+    public function __construct()
+    {
+        parent::__construct();
+
+        $this->_oModule = BxDolModule::getInstance('bx_timeline');
+    }
+
+    /**
+     * Overwtire the method of parent class.
+     *
+     * @param BxDolAlerts $oAlert an instance of alert.
+     */
+    public function response($oAlert)
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        $sMethod = '_process' . bx_gen_method_name($oAlert->sUnit . '_' . $oAlert->sAction);           	
+        if(method_exists($this, $sMethod))
+            return $this->$sMethod($oAlert);
+
+        $iObjectAuthorId = $this->_getObjectOwnerId($oAlert->aExtras);
+    	$iObjectPrivacyView = $this->_getObjectPrivacyView($oAlert->aExtras);
+        if($iObjectPrivacyView == BX_DOL_PG_HIDDEN)
+            return;
+
+        $aHandler = $this->_oModule->_oConfig->getHandlers($oAlert->sUnit . '_' . $oAlert->sAction);
+        if(empty($aHandler) || !is_array($aHandler))
+            return;
+
+        $iSilentMode = $this->_oModule->getSilentMode($oAlert->aExtras);
+        if(in_array($iSilentMode, array(BX_BASE_MOD_NTFS_SLTMODE_ABSOLUTE, BX_TIMELINE_SLTMODE_ABSOLUTE)))
+            return;
+
+        switch($aHandler['type']) {
+            case BX_BASE_MOD_NTFS_HANDLER_TYPE_INSERT:
+                $iOwnerId = abs($oAlert->iSender);
+                if($iObjectPrivacyView < 0)
+                    $iOwnerId = abs($iObjectPrivacyView);
+
+                $sContent = '';
+                if(!empty($oAlert->aExtras) && is_array($oAlert->aExtras))
+                    $sContent = serialize(bx_process_input($oAlert->aExtras));
+
+                $iDate = time();
+                $aEvent = [
+                    'owner_id' => $iOwnerId,
+                    'type' => $oAlert->sUnit,
+                    'action' => $oAlert->sAction,
+                    'object_id' => $oAlert->iObject,
+                    'object_owner_id' => $iObjectAuthorId,
+                    'object_privacy_view' => $iObjectPrivacyView,
+                    'object_cf' => $this->_getObjectCf($oAlert->aExtras),
+                    'content' => $sContent,
+                    'title' => '',
+                    'description' => '',
+                    'date' => $iDate,
+                    'reacted' => $iDate,
+                ];
+
+                $sMethod = '_prepareEvent' . bx_gen_method_name($oAlert->sUnit . '_' . $oAlert->sAction);
+                if(method_exists($this, $sMethod))
+                    $this->$sMethod($oAlert, $aEvent);
+
+                $iId = $this->_oModule->_oDb->insertEvent($aEvent);
+                if(!empty($iId))
+                    $this->_oModule->onPost($iId);
+                break;
+
+            case BX_BASE_MOD_NTFS_HANDLER_TYPE_UPDATE:
+                $sMethod = '_getEventUpdate' . bx_gen_method_name($oAlert->sUnit . '_' . $oAlert->sAction);           	
+                if(!method_exists($this, $sMethod))
+                    $sMethod = '_getEventUpdate';
+
+                $aEvent = $this->$sMethod($oAlert, $aHandler);
+                if(empty($aEvent) || !is_array($aEvent))
+                    break;
+
+                $aParamsSet = [
+                    'content' => !empty($oAlert->aExtras) && is_array($oAlert->aExtras) ? serialize(bx_process_input($oAlert->aExtras)) : ''
+                ];
+
+                if($iObjectPrivacyView > 0 && !empty($iObjectAuthorId) && $iObjectAuthorId == $oAlert->iSender)
+                    $aParamsSet = array_merge($aParamsSet, [
+                        'owner_id' => $oAlert->iSender,
+                        'object_privacy_view' => $iObjectPrivacyView
+                    ]);
+                else if($iObjectPrivacyView < 0)
+                    $aParamsSet = array_merge($aParamsSet, [
+                        'owner_id' => abs($iObjectPrivacyView),
+                        'object_privacy_view' => $iObjectPrivacyView 
+                    ]);
+
+                $this->_oModule->_oDb->updateEvent($aParamsSet, ['id' => $aEvent[$CNF['FIELD_ID']]]);
+
+                //--- Delete item cache.
+                $oCacheItem = $this->_oModule->getCacheItemObject();
+                $oCacheItem->delData($this->_oModule->_oConfig->getCacheItemKey($aEvent['id']));
+
+                //--- Delete item cache for repost.
+                $aReposts = $this->_oModule->_oDb->getReposts($aEvent[$CNF['FIELD_ID']]);
+                foreach($aReposts as $aRepost)
+                    $oCacheItem->delData($this->_oModule->_oConfig->getCacheItemKey($aRepost['event_id']));
+                break;
+
+            case BX_BASE_MOD_NTFS_HANDLER_TYPE_DELETE:
+                if($oAlert->sUnit == 'profile' && $oAlert->sAction == 'delete') {
+                    $aEvents = $this->_oModule->_oDb->getEvents(array('browse' => 'owner_id', 'value' => $oAlert->iObject));
+                    foreach($aEvents as $aEvent)
+                        $this->_oModule->deleteEvent($aEvent);
+
+                    if(!isset($oAlert->aExtras['delete_with_content']) || !$oAlert->aExtras['delete_with_content']) 
+                        break;
+
+                    $aEvents = $this->_oModule->_oDb->getEvents(array('browse' => 'common_by_object', 'value' => $oAlert->iObject));
+                    foreach($aEvents as $aEvent)
+                        $this->_oModule->deleteEvent($aEvent);
+                    break;
+                }
+
+                $sMethod = '_getEventDelete' . bx_gen_method_name($oAlert->sUnit . '_' . $oAlert->sAction);           	
+                if(!method_exists($this, $sMethod))
+                    $sMethod = '_getEventDelete';
+
+                $aEvent = $this->$sMethod($oAlert, $aHandler);
+                if(empty($aEvent) || !is_array($aEvent))
+                    break;
+
+                $this->_oModule->deleteEvent($aEvent);
+                break;
+        }
+    }
+
+    protected function _prepareEventCommentAdded($oAlert, &$aEvent)
+    {
+        $aEvent = array_merge($aEvent, array(
+            'object_id' => $oAlert->aExtras['comment_uniq_id'],
+            'object_owner_id' => $oAlert->aExtras['comment_author_id'],
+        ));
+    }
+
+    protected function _getEventUpdate(&$oAlert, &$aHandler)
+    {
+        $aHandlers = $this->_oModule->_oDb->getHandlers([
+            'type' => 'by_group_key_type', 
+            'group' => $aHandler['group']
+        ]);
+
+        return $this->_oModule->_oDb->getEvents([
+            'browse' => 'descriptor', 
+            'type' => $oAlert->sUnit, 
+            'action' => $aHandlers[BX_BASE_MOD_NTFS_HANDLER_TYPE_INSERT]['alert_action'],
+            'object_id' => $oAlert->iObject
+        ]);
+    }
+
+    protected function _getEventUpdateCommentEdited(&$oAlert, &$aHandler)
+    {
+        $aHandlers = $this->_oModule->_oDb->getHandlers([
+            'type' => 'by_group_key_type', 
+            'group' => $aHandler['group']
+        ]);
+
+        return $this->_oModule->_oDb->getEvents([
+            'browse' => 'descriptor', 
+            'type' => $oAlert->sUnit, 
+            'action' => $aHandlers[BX_BASE_MOD_NTFS_HANDLER_TYPE_INSERT]['alert_action'],
+            'object_id' => $oAlert->aExtras['comment_uniq_id']
+        ]);
+    }
+
+    protected function _getEventDelete(&$oAlert, &$aHandler)
+    {
+        $aHandlers = $this->_oModule->_oDb->getHandlers([
+            'type' => 'by_group_key_type', 
+            'group' => $aHandler['group']
+        ]);
+
+        return $this->_oModule->_oDb->getEvents([
+            'browse' => 'descriptor', 
+            'type' => $oAlert->sUnit,
+            'action' => $aHandlers[BX_BASE_MOD_NTFS_HANDLER_TYPE_INSERT]['alert_action'], 
+            'object_id' => $oAlert->iObject
+        ]);
+    }
+    
+    protected function _getEventDeleteCommentDeleted(&$oAlert, &$aHandler)
+    {
+        $aHandlers = $this->_oModule->_oDb->getHandlers([
+            'type' => 'by_group_key_type', 
+            'group' => $aHandler['group']
+        ]);
+
+        return $this->_oModule->_oDb->getEvents([
+            'browse' => 'descriptor', 
+            'type' => $oAlert->sUnit,
+            'action' => $aHandlers[BX_BASE_MOD_NTFS_HANDLER_TYPE_INSERT]['alert_action'], 
+            'object_id' => $oAlert->aExtras['comment_uniq_id']
+        ]);
+    }
+
+    protected function _processSystemClearCache($oAlert)
+    {
+        if(!in_array($oAlert->aExtras['type'], array('all', 'custom')))
+            return;
+
+        $this->_clearCache();
+    }
+
+    protected function _processSystemEnable($oAlert)
+    {
+        $aModuleConfig = $oAlert->aExtras['config'];
+        if(empty($aModuleConfig) || !is_array($aModuleConfig))
+            return false;
+
+        $sName = $aModuleConfig['name'];
+        if(!bx_srv_ii('system', 'is_module_context', [$sName]))
+            return false;
+
+        return $this->_oModule->serviceFeedsMenuAdd($sName);
+    }
+
+    protected function _processSystemDisable($oAlert)
+    {
+        $aModuleConfig = $oAlert->aExtras['config'];
+        if(empty($aModuleConfig) || !is_array($aModuleConfig))
+            return false;
+
+        $sName = $aModuleConfig['name'];
+        if(!bx_srv_ii('system', 'is_module_context', [$sName]))
+            return false;
+
+        return $this->_oModule->serviceFeedsMenuDelete($sName);
+    }
+
+    protected function _processAccountConfirm($oAlert)
+    {
+        $this->_clearCache();
+    }
+
+    protected function _processAccountUnconfirm($oAlert)
+    {
+        $this->_clearCache();
+    }
+
+    protected function _processProfileApprove($oAlert)
+    {
+        $this->_clearCache();
+    }
+
+    protected function _processProfileDisapprove($oAlert)
+    {
+        $this->_clearCache();
+    }
+
+    protected function _processProfileActivate($oAlert)
+    {
+        $this->_clearCache();
+    }
+
+    protected function _processProfileSuspend($oAlert)
+    {
+        $this->_clearCache();
+    }
+
+    protected function _clearCache()
+    {
+        //--- Clear item cache.
+        $this->_oModule->getCacheItemObject()->removeAllByPrefix($this->_oModule->_oConfig->getPrefix('cache_item'));
+    }
+
+    protected function _processBxTimelineVideosMp4Transcoded($oAlert)
+    {
+        $this->_onVideoTranscoded($oAlert->iObject, $oAlert->aExtras['ret']);
+    }
+
+    protected function _onVideoTranscoded($iMediaId, $bResult, $aParams = array())
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        if(!isset($CNF['FIELD_STATUS']))
+            return;
+
+        $aMedia = $this->_oModule->_oDb->getMediaById($CNF['FIELD_VIDEO'], $iMediaId);
+        if(empty($aMedia) || !is_array($aMedia))
+            return;
+
+        $iContentId = (int)$aMedia['event_id'];
+        $aContentInfo = $this->_oModule->_oDb->getContentInfoById($iContentId);
+        if(empty($aContentInfo) || !is_array($aContentInfo))
+            return;
+
+        if(!isset($aContentInfo[$CNF['FIELD_STATUS']]) || $aContentInfo[$CNF['FIELD_STATUS']] != 'awaiting')
+            return;
+
+        $iNow = time();
+        $bNotify = $iNow - $aContentInfo[$CNF['FIELD_ADDED']] > $this->_oModule->_oConfig->getDpnTime();
+        $iSystemBotProfileId = (int)getParam('sys_profile_bot');
+        $iAuthorProfileId = $aContentInfo[$CNF['FIELD_' . ((int)$aContentInfo[$CNF['FIELD_SYSTEM']] == 0 ? 'OBJECT_ID' : 'OWNER_ID')]];
+
+        if(!$bResult) {
+            if((int)$this->_oModule->_oDb->updateEntriesBy(array($CNF['FIELD_STATUS'] => 'failed'), array($CNF['FIELD_ID'] => $iContentId)) > 0) {
+                $this->_oModule->onFailed($iContentId);
+
+                if($bNotify)
+                    bx_alert($this->_oModule->getName(), 'publish_failed', $aContentInfo[$CNF['FIELD_ID']], $iSystemBotProfileId, array(
+                        'object_author_id' => $iAuthorProfileId,
+                        'privacy_view' => BX_DOL_PG_ALL
+                    ));
+            }
+
+            return;
+        }
+
+        if(isset($CNF['FIELD_PUBLISHED']) && isset($aContentInfo[$CNF['FIELD_PUBLISHED']]) && $aContentInfo[$CNF['FIELD_PUBLISHED']] > $iNow)
+            return;
+
+        $oTranscoder = BxDolTranscoder::getObjectInstance($CNF['OBJECT_VIDEOS_TRANSCODERS']['mp4']);
+        $aMediasToCheck = $this->_oModule->_oDb->getMedia($CNF['FIELD_VIDEO'], $iContentId, 0, true);
+        foreach($aMediasToCheck as $aMediaToCheck)
+            if($oTranscoder->isMimeTypeSupported($aMediaToCheck['mime_type']) && !$oTranscoder->isFileReady($aMediaToCheck['id']))
+                return;
+
+        if(!$this->_oModule->_oDb->updateEntriesBy(array($CNF['FIELD_STATUS'] => 'active'), array($CNF['FIELD_ID'] => $iContentId)))
+            return;
+
+        $this->_oModule->onPublished($iContentId);
+
+        if($bNotify)
+            bx_alert($this->_oModule->getName(), 'publish_succeeded', $aContentInfo[$CNF['FIELD_ID']], $iSystemBotProfileId, array(
+                'object_author_id' => $iAuthorProfileId,
+                'privacy_view' => BX_DOL_PG_ALL
+            ));
+    }
+}
+
+/** @} */

+ 3134 - 0
modules/boonex/timeline/updates/13.0.4_13.0.5/source/classes/BxTimelineTemplate.php

@@ -0,0 +1,3134 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Timeline Timeline
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxTimelineTemplate extends BxBaseModNotificationsTemplate
+{
+    protected static $_aMemoryCacheItems;
+    protected static $_aMemoryCacheItemsData;
+    protected static $_sMemoryCacheItemsKeyMask;
+
+    protected static $_sTmplContentItemItem;
+    protected static $_sTmplContentItemOutline;
+    protected static $_sTmplContentItemOutlineSample;
+    protected static $_sTmplContentItemTimeline;
+    protected static $_sTmplContentItemTimelineSample;
+    protected static $_sTmplContentItemSearch;
+    protected static $_sTmplContentTypePost;
+    protected static $_sTmplContentTypeRepost;
+
+    protected $_bShowTimelineDividers;
+    protected $_aAclId2Name;
+
+    function __construct(&$oConfig, &$oDb)
+    {
+        parent::__construct($oConfig, $oDb);
+
+        $this->_bShowTimelineDividers = false;
+
+        $this->_aAclId2Name = array();
+
+        bx_import('BxTemplAcl');
+        $aAclLevels = BxDolAcl::getInstance()->getMemberships(false, false, false);
+        foreach($aAclLevels as $iAclId => $sAclName)
+            $this->_aAclId2Name[$iAclId] = str_replace('_', '-', str_replace('_adm_prm_txt_level_', '', $sAclName));
+    }
+
+    public function init()
+    {
+        parent::init();
+
+        self::$_aMemoryCacheItems = array();
+        self::$_aMemoryCacheItemsData = array();
+        self::$_sMemoryCacheItemsKeyMask = "%s_%d";
+    }
+
+    public function getAddedCss($sType = '', $bDynamic = false)
+    {
+        $aCss = array();
+        switch($sType) {
+            case 'view':
+                $aCss = array(
+                    BX_DIRECTORY_PATH_PLUGINS_PUBLIC . 'flickity/|flickity.css',
+                    'cmts.css',
+                    'view.css',
+                    'view-media-tablet.css',
+                    'view-media-desktop.css',
+                    'repost.css',
+                );
+
+                if($this->_oConfig->isJumpTo()) {
+                    list($aCssCalendar, $aJsCalendar) = BxBaseFormView::getCssJsCalendar();
+                    $aCss = array_merge($aCss, $aCssCalendar);
+                }
+                break;
+
+            case 'post':
+                if($this->_oConfig->isEmoji())
+                    $aCss[] = BX_DIRECTORY_PATH_PLUGINS_PUBLIC . 'emoji/css/|emoji.css';
+
+                $aCss[] = 'post.css';
+                break;
+        }
+
+        $mixedResult = $this->addCss($aCss, $bDynamic);
+        if($bDynamic)
+            return $mixedResult; 
+    }
+
+    public function getAddedJs($sType = '', $bDynamic = false)
+    {
+        $aJs = array(
+            'autosize.min.js',
+            'jquery.anim.js',
+            'main.js',
+        );
+        switch($sType) {
+            case 'view':
+                $aJs = array_merge($aJs, array(
+                    'masonry.pkgd.min.js',
+                    'flickity/flickity.pkgd.min.js',
+                    'embedly-player.min.js',
+                    'BxDolCmts.js',
+                    'view.js',
+                    'repost.js',
+                ));
+
+                if ($this->_oConfig->isJumpTo()) {
+                    list($aCssCalendar, $aJsCalendar) = BxBaseFormView::getCssJsCalendar();
+                    $aJs = array_merge($aJs, $aJsCalendar);
+                }
+                break;
+
+            case 'post':
+                $aJs = array_merge($aJs, array(
+                    'jquery.form.min.js',
+                    'post.js',
+                ));
+                break;
+        }
+
+        $mixedResult = $this->addJs($aJs, $bDynamic);
+        if($bDynamic)
+            return $mixedResult; 
+    }
+
+    public function getJsCodeView($aParams = array(), $bWrap = true, $bDynamic = false)
+    {
+        $aParams = array_merge([
+            'sObjNameMenuFeeds' => $this->_oConfig->getObject('menu_feeds'),
+            'bInfScroll' => $this->_oConfig->isInfiniteScroll(),
+            'iInfScrollAutoPreloads' => $this->_oConfig->getAutoPreloads(),
+            'iLimitAttachLinks' => $this->_oConfig->getLimitAttachLinks(),
+            'sLimitAttachLinksErr' => bx_js_string(_t('_bx_timeline_txt_err_attach_links')),
+            'oAttachedLinks' => []
+        ], $aParams);
+
+        return parent::getJsCode('view', $aParams, $bWrap, $bDynamic);
+    }
+
+    public function getJsCodePost($iOwnerId, $aParams = array(), $bWrap = true, $bDynamic = false)
+    {
+        $aGeneralParams = [];
+        $aRequestParams = $aParams;
+        if(isset($aParams['gparams'], $aParams['rparams'])) {
+            $aGeneralParams = $aParams['gparams'];
+            $aRequestParams = $aParams['rparams'];
+        }
+
+        return $this->getJsCode('post', array_merge(array(
+            'bEmoji' => $this->_oConfig->isEmoji(),
+            'bAutoAttach' => $this->_oConfig->isEditorAutoAttach(),
+            'iLimitAttachLinks' => $this->_oConfig->getLimitAttachLinks(),
+            'sLimitAttachLinksErr' => bx_js_string(_t('_bx_timeline_txt_err_attach_links')),
+            'oAttachedLinks' => $this->_oDb->getLinksBy(array(
+                'type' => 'unused', 
+                'profile_id' => $this->getModule()->getUserId(), 
+                'short' => true
+            )),
+            'sVideosAutoplay' => $this->_oConfig->getVideosAutoplay(),
+            'oRequestParams' => array_merge(array(
+                'type' => isset($aRequestParams['type']) ? $aRequestParams['type'] : BX_TIMELINE_TYPE_DEFAULT, 
+                'owner_id' => $iOwnerId
+            ), $aRequestParams)
+        ), $aGeneralParams), $bWrap, $bDynamic);
+    }
+
+    public function getPostBlock($iOwnerId, $aParams = array())
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $aForm = $this->getModule()->getFormPost($aParams);
+
+        if($this->_oConfig->isEditorAutoattach() && !empty($aForm['form_object'])) {
+            $aUploadersInfo = $aForm['form_object']->getUploadersInfo($CNF['FIELD_PHOTO']);
+            if(!empty($aUploadersInfo) && is_array($aUploadersInfo))
+                $aParams = [
+                    'gparams' => ['sAutoUploader' => $aUploadersInfo['name'], 'sAutoUploaderId' => $aUploadersInfo['id']],
+                    'rparams' => $aParams
+                ];
+        }
+
+        return $this->parseHtmlByName('block_post.html', array (
+            'style_prefix' => $this->_oConfig->getPrefix('style'),
+            'js_object' => $this->_oConfig->getJsObject('post'),
+            'js_content' => $this->getJsCodePost($iOwnerId, $aParams),
+            'form' => $aForm['form']
+        ));
+    }
+
+    public function getViewsBlock($aParams)
+    {
+        $sStylePrefix = $this->_oConfig->getPrefix('style');
+        $sJsObject = $this->_oConfig->getJsObjectView($aParams);
+        
+        $sType = isset($aParams['type']) ? $aParams['type'] : '';
+
+        $sMenu = $this->_oConfig->getObject('menu_view');
+        $oMenu = BxDolMenu::getObjectInstance($sMenu);
+
+    	$aMenuItems = $oMenu->getMenuItems();
+    	if(empty($aMenuItems) || !is_array($aMenuItems))
+            return '';
+
+    	if(empty($sType)) {
+            $aMenuItem = array_shift($aMenuItems);
+            $sType = $aMenuItem['name'];
+    	}
+    	$oMenu->setSelected($this->_oConfig->getName(), $sType);
+        $oMenu->addMarkers(array(
+            'js_object_view' => $sJsObject
+        ));
+
+        $sTitle = _t('_bx_timeline_page_block_title_views_' . $aParams['view']);
+
+        return [
+            'content' => $this->parseHtmlByName('block_views.html', [
+                'style_prefix' => $sStylePrefix,
+                'html_id' => $this->_oConfig->getHtmlIdView('views', $aParams, ['with_type' => false]),
+                'html_id_content' => $this->_oConfig->getHtmlIdView('views_content', $aParams, ['with_type' => false]),
+                'html_id_view_placeholder' => $this->_oConfig->getHtmlIdView('main', array_merge($aParams, ['type' => 'placeholder'])),
+                'title' => $sTitle,
+                'content' => $this->getViewBlock($aParams)
+            ]),
+            'menu' => $oMenu
+        ];
+    }
+
+    public function getViewsDbBlock($aParams)
+    {
+        $sStylePrefix = $this->_oConfig->getPrefix('style');
+
+        $sJsObject = $this->_oConfig->getJsObjectView($aParams);
+        $sJsContent = $this->getJsCodeView([
+            'sObjName' => $sJsObject,
+            'sName' => $aParams['name'],
+            'sView' => $aParams['view'],
+            'sType' => $aParams['type'],
+            'sVideosAutoplay' => $this->_oConfig->getVideosAutoplay(),
+            'oRequestParams' => $aParams
+        ], [
+            'wrap' => true,
+            'mask_markers' => ['object' => $sJsObject]
+        ]);
+
+        return array(
+            'content' => $this->parseHtmlByName('block_views_db.html', array(
+                'style_prefix' => $sStylePrefix,
+                'html_id' => $this->_oConfig->getHtmlIdView('views', $aParams, array('with_type' => false)),
+                'html_id_content' => $this->_oConfig->getHtmlIdView('views_content', $aParams, array('with_type' => false)),
+                'content' => $this->getViewBlock(array_merge($aParams, ['name' => ''])),
+                'js_content' => $sJsContent
+            )),
+            'buttons' => [
+                ['title' => _t('_bx_timeline_txt_filters'), 'href' => 'javascript:void(0)', 'onclick' => 'javascript:' . $sJsObject . '.changeFeedFilters(this)']
+            ]
+        );
+    }
+
+    public function getViewFilters($aParams)
+    {
+        $sStylePrefix = $this->_oConfig->getPrefix('style');
+        $sJsObject = $this->_oConfig->getJsObjectView($aParams);
+
+        $aHandlers = $this->_oDb->getHandlers(['type' => 'by_type', 'value' => 'insert']);       
+
+        $aModules = [];
+        foreach($aHandlers as $aHandler) {
+            $sModule = $aHandler['alert_unit'];
+            if(isset($aModules[$sModule]))
+                continue;
+
+            $aModule = $this->_oDb->getModuleByName($sModule);
+            if(empty($aModule) || !is_array($aModule))
+                continue;
+
+            $sTitleKey = '_' . $sModule;
+            $sTitleValue = _t($sTitleKey);
+            if(strcmp($sTitleKey, $sTitleValue) == 0)
+                $sTitleValue = $aModule['title'];
+
+            $aModules[$sModule] = [
+                'key' => $aHandler['alert_unit'],
+                'value' => $sTitleValue
+            ];
+        }
+
+        uasort($aModules, function($aV1, $aV2) {
+            return strcmp($aV1['value'], $aV2['value']);
+        });
+
+        $aForm = [
+            'inputs' => [
+                'by_module' => [
+                    'name' => 'by_module',
+                    'type' => 'radio_set',
+                    'caption' => _t('_bx_timeline_form_filters_input_by_modules'),
+                    'values' => [
+                        ['key' => 'all', 'value' => _t('_bx_timeline_form_filters_input_by_modules_all')],
+                        ['key' => 'selected', 'value' => _t('_bx_timeline_form_filters_input_by_modules_selected')]
+                    ],
+                    'value' => 'all',
+                    'attrs' => ['onchange' => $sJsObject . '.onFilterByModuleChange(this)'],
+                    'dv_thd' => 1
+                ],
+                'modules' => [
+                    'name' => 'modules',
+                    'type' => 'checkbox_set',
+                    'values' => array_values($aModules),
+                    'tr_attrs' => ['class' => 'modules', 'style' => 'display:none']
+                ],
+                'apply' => [
+                    'name' => 'apply',
+                    'type' => 'button',
+                    'value' => _t('_bx_timeline_form_filters_input_do_apply'),
+                    'attrs' => ['onclick' => $sJsObject . '.onFilterApply(this)']
+                ]
+            ]
+        ];
+        $oForm = new BxTemplFormView($aForm);
+        
+
+        $sViewFiltersPopupId = $this->_oConfig->getHtmlIdView('filters_popup', $aParams);
+        $sViewFiltersPopupContent = $this->parseHtmlByName('block_view_filters.html', array(
+            'style_prefix' => $sStylePrefix,
+            'js_object' => $sJsObject,
+            'content' => $oForm->genRows()
+    	));
+
+    	return BxTemplFunctions::getInstance()->transBox($sViewFiltersPopupId, $sViewFiltersPopupContent, true);
+    }
+
+    public function getViewBlock($aParams)
+    {
+        $oModule = $this->getModule();
+
+        list($sContent, $sLoadMore, $sBack, $sEmpty, $iEvent, $bEventsToLoad) = $this->getPosts($aParams);
+
+        //--- Add live update
+        $oModule->actionResumeLiveUpdate($aParams['type'], $aParams['owner_id']);
+
+        $sModuleName = $oModule->getName();
+        $sModuleMethod = !empty($aParams['get_live_updates']) ? $aParams['get_live_updates'] : 'get_live_update';
+        $sService = BxDolService::getSerializedService($sModuleName, $sModuleMethod, array($aParams, $oModule->getUserId(), '{count}', '{init}'));
+
+        $aLiveUpdateParams = array($this->_oConfig->getLiveUpdateKey($aParams), 1, $sService, true);
+        if($sModuleMethod == 'get_live_update')
+            $aLiveUpdateParams[] = $iEvent;
+
+        $sLiveUpdateCode = null;
+        bx_alert($sModuleName, 'add_live_update', 0, 0, array(
+            'browse_params' => $aParams,
+            'live_update_params' => &$aLiveUpdateParams,
+            'override_result' => &$sLiveUpdateCode,
+        ));
+
+        if($sLiveUpdateCode === null)
+            $sLiveUpdateCode = call_user_func_array(array(BxDolLiveUpdates::getInstance(), 'add'), $aLiveUpdateParams);
+        //--- Add live update
+
+        $sContentBefore = '';
+        $sContentAfter = '';
+
+        $sJsObject = $this->_oConfig->getJsObjectView($aParams);
+        $sJsContent = $this->getJsCodeView(array(
+            'sObjName' => $sJsObject,
+            'sName' => $aParams['name'],
+            'sView' => $aParams['view'],
+            'sType' => $aParams['type'],
+            'sVideosAutoplay' => $this->_oConfig->getVideosAutoplay(),
+            'bEventsToLoad' => $bEventsToLoad,
+            'bAutoMarkAsViewed' => $this->_oConfig->isSortByUnread(),
+            'oRequestParams' => $aParams
+        ), array(
+            'wrap' => true,
+            'mask_markers' => array('object' => $sJsObject)
+        )) . $this->getJsCode('repost');
+
+        bx_alert($sModuleName, 'get_view', 0, 0, array(
+            'params' => $aParams,
+            'event_first' => $iEvent,
+            'back' => &$sBack,
+            'empty' => &$sEmpty,
+            'content_before' => &$sContentBefore,
+            'content' => &$sContent,
+            'content_after' => &$sContentAfter,
+            'load_more' => &$sLoadMore,
+            'js_content' => &$sJsContent
+        ));
+
+        return $this->parseHtmlByName('block_view.html', array(
+            'style_prefix' => $this->_oConfig->getPrefix('style'),
+            'html_id' => $this->_oConfig->getHtmlIdView('main', $aParams),
+            'view' => $aParams['view'],
+            'back' => $sBack,
+            'empty' => $sEmpty,
+            'content_before' => $sContentBefore,
+            'content' => $sContent,
+            'content_after' => $sContentAfter,
+            'load_more' =>  $sLoadMore,
+            'show_more' => $this->_getShowMore($aParams),
+            'view_image_popup' => $this->_getImagePopup($aParams),
+            'live_update_code' => $sLiveUpdateCode,
+            'js_content' => $sJsContent
+        ));
+    }
+
+    public function getSearchBlock($sContent)
+    {
+        $oModule = $this->getModule();
+        $aParams = $oModule->getParams(BX_TIMELINE_VIEW_SEARCH);
+
+        return $this->parseHtmlByName('block_search.html', array(
+            'style_prefix' => $this->_oConfig->getPrefix('style'),
+            'html_id' => $this->_oConfig->getHtmlIdView('main', $aParams),
+            'view' => $aParams['view'],
+            'content' => $sContent,
+            'view_image_popup' => $this->_getImagePopup($aParams),
+            'js_content' => $this->getJsCodeView(array(
+            	'oRequestParams' => $aParams
+            ))
+        ));
+    }
+
+    public function getItemBlock($mixedId, $aBrowseParams = array())
+    {
+        $CNF = $this->_oConfig->CNF;
+        $oModule = $this->getModule();
+
+        if(is_numeric($mixedId))
+            $mixedId = $oModule->getItemData($mixedId);
+
+        if(empty($mixedId) || !is_array($mixedId))
+            return array('content' => MsgBox(_t('_Empty')), 'designbox_id' => 13);
+
+        if($mixedId['code'] != 0)
+            return array('content' => MsgBox($mixedId['content']), 'designbox_id' => 13);
+
+        $aEvent = $mixedId['event'];
+        $sContent = $mixedId['content'];
+
+        if(!$this->_oConfig->isSystem($aEvent['type'], $aEvent['action'])) {
+            $mixedViews = $oModule->getViewsData($aEvent['views']);
+            if($mixedViews !== false) {
+                list($sSystem, $iObjectId) = $mixedViews;
+                $oModule->getViewObject($sSystem, $iObjectId)->doView();
+            }
+        }
+
+        $sAuthorName = $oModule->getObjectUser($aEvent['object_owner_id'])->getDisplayName();
+
+        $sTitle = $sAuthorName . ' ' . _t($aEvent['sample_action'], _t($aEvent['sample']));
+        $sDescription = $aEvent['title'];
+        if(get_mb_substr($sDescription, 0, 1) == '_')
+            $sDescription = _t($sDescription);
+
+        $oTemplate = BxDolTemplate::getInstance();
+        $oTemplate->setPageHeader(strip_tags($sTitle));
+        $oTemplate->setPageDescription(strip_tags($sDescription));
+
+        $oMetatags = BxDolMetatags::getObjectInstance($this->_oConfig->getObject('metatags'));
+        if($oMetatags)
+            $oMetatags->addPageMetaInfo($aEvent[$CNF['FIELD_ID']]);
+
+        $sReferrer = '';
+        if(isset($_SERVER['HTTP_REFERER']) && mb_stripos($_SERVER['HTTP_REFERER'], BX_DOL_URL_ROOT) === 0)
+            $sReferrer = $_SERVER['HTTP_REFERER'];
+        else 
+            $sReferrer = BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink($this->_oConfig->CNF['URL_HOME']);
+
+        $sJsObject = $this->_oConfig->getJsObjectView($aBrowseParams);
+        return array('content' => $this->parseHtmlByName('block_item.html', array(
+            'style_prefix' => $this->_oConfig->getPrefix('style'),
+            'html_id' => $this->_oConfig->getHtmlIdView('main', $aBrowseParams),
+            'content' => $sContent,
+            'show_more' => $this->_getShowMore($aBrowseParams),
+            'view_image_popup' => $this->_getImagePopup($aBrowseParams),
+            'js_content' => $this->getJsCodeView(array(
+                'sObjName' => $sJsObject,
+                'sVideosAutoplay' => $this->_oConfig->getVideosAutoplay(),
+                'sReferrer' => $sReferrer,
+                'oRequestParams' => $aBrowseParams
+            ), array(
+                'wrap' => true,
+                'mask_markers' => array('object' => $sJsObject)
+            )) . $this->getJsCode('repost')
+        )));
+    }
+
+    /**
+     * Get event's content.
+     * @param integer $iId - event ID.
+     * @param string $sMode - 'file'/'photo'/'video' are available for now. But only images will be shown.
+     */
+    public function getItemBlockContent($iId, $sMode) {
+        $oModule = $this->getModule();
+        $sStylePrefix = $this->_oConfig->getPrefix('style');
+
+        $aItemData = $oModule->getItemData($iId);
+        if(empty($aItemData) || $aItemData['code'] != 0)
+            return '';
+
+        $aEvent = $aItemData['event'];       
+
+        $sKeyMain = $sKeyAttach = '';
+        switch($sMode) {
+            case 'file':
+                $sKeyMain = 'files';
+                $sKeyAttach = 'files_attach';
+                break;
+
+            case 'photo':
+                $sKeyMain = 'images';
+                $sKeyAttach = 'images_attach';
+                break;
+
+            case 'video':
+                $sKeyMain = 'videos';
+                $sKeyAttach = 'videos_attach';
+                break;
+        }
+
+        $aImages = [];
+        if(!empty($aEvent['content'][$sKeyMain]) && is_array($aEvent['content'][$sKeyMain]))
+            $aImages = $aEvent['content'][$sKeyMain];
+        else if(!empty($aEvent['content'][$sKeyAttach]) && is_array($aEvent['content'][$sKeyAttach]))
+            $aImages = $aEvent['content'][$sKeyAttach];
+
+        if(isset($aImages['total']) && isset($aImages['items']))
+            $aImages = $aImages['items'];
+
+        $bImageSingle = count($aImages) == 1;
+        $sImageSelected = base64_decode(bx_process_input(bx_get('src')));
+
+        $aTmplVarsImages = [];
+        if(!$bImageSingle) {
+            $iIndex = 1;
+            foreach($aImages as $aImage)  {
+                if(!isset($aImage['src'], $aImage['src_orig']))
+                    continue;
+
+                $iCurrent = $iIndex;
+                if(strcmp($aImage['src'], $sImageSelected) == 0 || strcmp($aImage['src_orig'], $sImageSelected) == 0)
+                    $iCurrent = 0;
+
+                $aTmplVarsImages[$iCurrent] = [
+                    'style_prefix' => $sStylePrefix,
+                    'url' => $aImage['url'],
+                    'src' => $aImage[!empty($aImage['src_orig']) ? 'src_orig' : 'src']
+                ];
+
+                $iIndex++;
+            }
+
+            ksort($aTmplVarsImages);
+            $aTmplVarsImages = array_values($aTmplVarsImages);
+        }
+
+        $aTmplVars = [
+            'style_prefix' => $sStylePrefix,
+            'bx_if:show_image' => [
+                'condition' => $bImageSingle,
+                'content' => [
+                    'style_prefix' => $sStylePrefix,
+                    'src' => $sImageSelected,
+                ]
+            ],
+            'bx_if:show_images' => [
+                'condition' => !$bImageSingle,
+                'content' => [
+                    'style_prefix' => $sStylePrefix,
+                    'bx_repeat:images' => $aTmplVarsImages
+                ]
+            ]
+        ];
+
+        return $this->parseHtmlByName('block_item_content.html', $aTmplVars);
+    }
+
+    public function getItemBlockInfo($iId) {
+        $CNF = $this->_oConfig->CNF;
+
+        $aEvent = $this->_oDb->getEvents(array('browse' => 'id', 'value' => $iId));
+        if(empty($aEvent))
+            return '';
+
+        $aResult = $this->getDataCached($aEvent);
+        if($aResult === false)
+            return '';
+
+        $sAuthorUnit = $this->getModule()->getObjectUser($aResult['object_owner_id'])->getUnit();
+
+        $oForm = BxDolForm::getObjectInstance($this->_oConfig->getObject('form_post'), $this->_oConfig->getObject('form_display_post_view'), $this);
+        $oForm->initChecker($aEvent);
+
+        return $this->parseHtmlByName('block_item_info.html', array(
+            'style_prefix' => $this->_oConfig->getPrefix('style'),
+            'author' => $sAuthorUnit,
+            'fields' => $oForm->getCode()
+        ));
+    }
+
+    public function getItemBlockComments($iId) {
+        $CNF = &$this->_oConfig->CNF;
+
+        $aEvent = $this->_oDb->getEvents(array('browse' => 'id', 'value' => $iId));
+        if(empty($aEvent))
+            return '';
+
+        $aResult = $this->getDataCached($aEvent);
+        if($aResult === false)
+            return '';
+
+        return $this->parseHtmlByName('block_item_comments.html', array(
+            'style_prefix' => $this->_oConfig->getPrefix('style'),
+            'content' => $this->_getComments($aResult['comments'])
+        ));
+                
+    }
+
+    public function getUnit(&$aEvent, $aBrowseParams = array())
+    {
+        $oModule = $this->getModule();
+
+        if(empty($aBrowseParams) || !is_array($aBrowseParams))
+            $aBrowseParams = $oModule->getParams(BX_TIMELINE_VIEW_SEARCH);
+
+        return $this->getPost($aEvent, $aBrowseParams);
+    }
+
+    public function getPost(&$aEvent, $aBrowseParams = array())
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $iEventId = (int)$aEvent[$CNF['FIELD_ID']];
+        $iViewerId = isset($aBrowseParams['viewer_id']) ? (int)$aBrowseParams['viewer_id'] : bx_get_logged_profile_id();
+
+        $sMemoryCacheItemsKey = sprintf(self::$_sMemoryCacheItemsKeyMask, $aBrowseParams['view'], $iEventId);
+        if(array_key_exists($sMemoryCacheItemsKey, self::$_aMemoryCacheItems)) {
+            if(array_key_exists($sMemoryCacheItemsKey, self::$_aMemoryCacheItemsData))
+                $aEvent = self::$_aMemoryCacheItemsData[$sMemoryCacheItemsKey];
+
+            return self::$_aMemoryCacheItems[$sMemoryCacheItemsKey];
+        }
+
+        /**
+         * Add all items in memory cache even if they are empty.
+         */
+        self::$_aMemoryCacheItems[$sMemoryCacheItemsKey] = '';
+        self::$_aMemoryCacheItemsData[$sMemoryCacheItemsKey] = array();
+
+        $oPrivacy = BxDolPrivacy::getObjectInstance($this->_oConfig->getObject('privacy_view'));
+        if($oPrivacy) {
+            $oPrivacy->setTableFieldAuthor($this->_oConfig->isSystem($aEvent['type'], $aEvent['action']) ? 'owner_id' : 'object_id');
+            if(!$oPrivacy->check($iEventId, $iViewerId))
+                return '';
+        }
+
+        $aResult = $this->getDataCached($aEvent, $aBrowseParams);
+        if($aResult === false)
+            return '';
+
+        if(isset($aResult['owner_id']))
+            $aEvent['owner_id'] = $aResult['owner_id'];
+
+        $aEvent['object_owner_id'] = $aResult['object_owner_id'];
+        $aEvent['icon'] = !empty($aResult['icon']) ? $aResult['icon'] : '';
+        $aEvent['sample'] = !empty($aResult['sample']) ? $aResult['sample'] : '_bx_timeline_txt_sample';
+        $aEvent['sample_action'] = !empty($aResult['sample_action']) ? $aResult['sample_action'] : '_bx_timeline_txt_added_sample';
+        if(isset($aResult['sample_action_custom']))
+            $aEvent['sample_action_custom'] = $aResult['sample_action_custom'];
+        $aEvent['content'] = $aResult['content'];
+        $aEvent['content_type'] = !empty($aResult['content_type']) ? $aResult['content_type'] : BX_TIMELINE_PARSE_TYPE_DEFAULT;
+        $aEvent['views'] = $aResult['views'];
+        $aEvent['votes'] = $aResult['votes'];
+        $aEvent['reactions'] = $aResult['reactions'];
+        $aEvent['scores'] = $aResult['scores'];
+        $aEvent['reports'] = $aResult['reports'];
+        $aEvent['comments'] = $aResult['comments'];
+
+        $sKey = 'allowed_view';
+        $aEvent[$sKey] = $this->_preparePrivacy($sKey, $aEvent, $aResult);
+        if(isset($aEvent[$sKey]) && $aEvent[$sKey] !== CHECK_ACTION_RESULT_ALLOWED) 
+            return '';
+
+        self::$_aMemoryCacheItems[$sMemoryCacheItemsKey] = $this->_getPost($aEvent['content_type'], $aEvent, $aBrowseParams);
+        self::$_aMemoryCacheItemsData[$sMemoryCacheItemsKey] = $aEvent;
+
+        return self::$_aMemoryCacheItems[$sMemoryCacheItemsKey];
+    }
+
+    public function getPosts($aParams)
+    {
+        $bReturnArray = isset($aParams['return_data_type']) && $aParams['return_data_type'] == 'array';
+        $bViewTimeline = $aParams['view'] == BX_TIMELINE_VIEW_TIMELINE;
+
+        $iStart = $aParams['start'];
+        $iPerPage = $aParams['per_page'];
+
+        $aParamsDb = $aParams;
+
+        //--- Before: Check for Previous
+        $iDays = -1;
+        $bPrevious = false;
+        if($iStart - 1 >= 0) {
+            $aParamsDb['start'] -= 1;
+            $aParamsDb['per_page'] += 1;
+            $bPrevious = true;
+        }
+
+        //--- Before: Check for Next
+        $aParamsDb['per_page'] += 1;
+        $aEvents = $this->_oDb->getEvents($aParamsDb);
+
+        //--- After: Check for Previous
+        if($bPrevious) {
+            $aEvent = array_shift($aEvents);
+            $iDays = (int)$aEvent['days'];
+        }
+
+        //--- After: Check for Next
+        $bNext = false;
+        if(count($aEvents) > $iPerPage) {
+            $aEvent = array_pop($aEvents);
+            $bNext = true;
+        }
+
+        $sContent = '';
+        $sContent .= $this->getSizer($aParams);
+
+        $iFirst = 0;
+        $iEvents = count($aEvents);
+        if($iEvents > 0)
+            $iFirst = $this->_getFirst($aEvents, $aParams);
+        else 
+            $sContent .= $bViewTimeline ? $this->getDividerToday() : '';
+
+        //--- Check for Visual Grouping
+        $aGroups = array();
+        foreach($aEvents as $iIndex => $aEvent) {
+            $aContent = unserialize($aEvent['content']);
+            if(!isset($aContent['timeline_group']))
+                continue;
+
+            $aGroup = $aContent['timeline_group'];
+            $sGroup = $aGroup['by'];
+            if(!isset($aGroups[$sGroup]))
+               $aGroups[$sGroup] = array('field' => $aGroup['field'], 'indexes' => array(), 'processed' => false);
+
+            $aGroups[$sGroup]['indexes'][] = $iIndex;
+        }
+
+        //--- Perform Visual Grouping
+        foreach($aGroups as $sGroup => $aGroup) {
+            if(empty($aGroup['field']) || empty($aGroup['indexes']))
+                continue;
+
+            switch($aGroup['field']) {
+                case 'owner_id':
+                    $aOwnerIds = array();
+                    foreach($aGroup['indexes'] as $iIndex)
+                        if(!in_array($aEvents[$iIndex]['owner_id'], $aOwnerIds))
+                            $aOwnerIds[] = $aEvents[$iIndex]['owner_id'];
+
+                    $iGroupIndex = (int)array_shift($aGroup['indexes']);
+                    if(is_null($iGroupIndex))
+                        break;
+
+                    foreach($aGroup['indexes'] as $iIndex)
+                        unset($aEvents[$iIndex]);
+
+                    $aEvents[$iGroupIndex]['owner_id_grouped'] = $aOwnerIds;
+                    break;
+            }
+        }
+
+        $iExtenalsEvery = $this->_oConfig->getExtenalsEvery($aParams['type']);
+
+        $bFirst = true;
+        $iEventIndex = 0;
+        $mixedEvents = $bReturnArray ? array() : '';
+        foreach($aEvents as $aEvent) {
+            $iEvent = (int)$aEvent['id'];
+
+            $sEvent = $this->getPost($aEvent, $aParams);
+            if(empty($sEvent))
+                continue;
+
+            if($bReturnArray) {
+                $mixedEvents[] = $aEvent;
+                continue;
+            }
+
+            if($bFirst && $bViewTimeline) {
+                $mixedEvents .= $this->getDividerToday($aEvent);
+
+                $bFirst = false;
+            }
+
+            $mixedEvents .= $bViewTimeline ? $this->getDivider($iDays, $aEvent) : '';
+            $mixedEvents .= $sEvent;
+
+            $iEventIndex++;
+            if($iExtenalsEvery > 0 && $iEventIndex % $iExtenalsEvery == 0) {
+                $sExternalPost = false;
+                bx_alert($this->_oConfig->getName(), 'get_external_post', 0, 0, array(
+                    'params' => $aParams,
+                    'override_result' => &$sExternalPost,
+                ));
+
+                if($sExternalPost !== false)
+                    $mixedEvents .= $sExternalPost;
+            }
+        }
+
+        if($bReturnArray)
+            return $mixedEvents;
+
+        $sContent .= $mixedEvents;
+
+        $bEvents = !empty($mixedEvents);
+
+        $sBack = $this->getBack($aParams);
+
+        $iPerPage = $this->_oConfig->getPerPage();
+        $iPreloads = $this->_oConfig->getAutoPreloads();
+        if(!$this->_oConfig->isInfiniteScroll() || (($aParams['start'] - $iPerPage * ($iPreloads - 1)) % ($iPerPage * $iPreloads) == 0))
+            $sLoadMore = $this->getLoadMore($aParams, $bNext, $iEvents > 0 && $bEvents);
+        else
+            $sLoadMore = $this->getLoadMoreAuto($aParams, $bNext, $iEvents > 0 && $bEvents);
+
+        $sEmpty = $this->getEmpty($iEvents <= 0 || !$bEvents);
+
+        return array($sContent, $sLoadMore, $sBack, $sEmpty, $iFirst, $bNext);
+    }
+
+    public function getEmpty($bVisible)
+    {
+        return $this->parseHtmlByName('empty.html', array(
+            'style_prefix' => $this->_oConfig->getPrefix('style'),
+            'visible' => $bVisible ? 'block' : 'none',
+            'content' => MsgBox(_t('_bx_timeline_txt_msg_no_results'))
+        ));
+    }
+
+    public function getDivider(&$iDays, &$aEvent)
+    {
+        if(!$this->_bShowTimelineDividers || $iDays == $aEvent['days'])
+            return '';
+
+        $iDays = $aEvent['days'];
+        $iDaysAgo = (int)$aEvent['ago_days'];
+        if($aEvent['today'] == $aEvent['days'] || (($aEvent['today'] - $aEvent['days']) == 1 && $iDaysAgo == 0))
+            return '';
+
+        return $this->parseHtmlByName('divider.html', array(
+        	'style_prefix' => $this->_oConfig->getPrefix('style'),
+            'type' => 'common',
+            'bx_if:show_hidden' => array(
+                'condition' => false,
+                'content' => array()
+            ),
+            'content' => bx_time_js($aEvent['date'])
+        ));
+    }
+
+    public function getDividerToday($aEvent = array())
+    {
+        if(!$this->_bShowTimelineDividers)
+            return '';
+
+    	$bToday = !empty($aEvent) && ($aEvent['today'] == $aEvent['days'] || (($aEvent['today'] - $aEvent['days']) == 1 && (int)$aEvent['ago_days'] == 0));
+
+        return $this->parseHtmlByName('divider.html', array(
+        	'style_prefix' => $this->_oConfig->getPrefix('style'),
+            'type' => 'today',
+        	'bx_if:show_hidden' => array(
+                'condition' => !$bToday,
+                'content' => array()
+            ),
+            'content' => _t('_bx_timeline_txt_today')
+        ));
+    }
+
+    public function getSizer($aParams)
+    {
+        if($aParams['view'] != BX_TIMELINE_VIEW_OUTLINE)
+            return '';
+
+        return $this->parseHtmlByName('sizer_' . $aParams['view'] . '.html', array(
+        	'style_prefix' => $this->_oConfig->getPrefix('style')
+        ));
+    }
+
+    public function getBack($aParams)
+    {
+        $iYearSel = (int)$aParams['timeline'];
+        if($iYearSel == 0)
+            return '';
+
+        $sStylePrefix = $this->_oConfig->getPrefix('style');
+        $sJsObject = $this->_oConfig->getJsObjectView($aParams);
+
+        $iYearNow = date('Y', time());
+        return $this->parseHtmlByName('back.html', array(
+        	'style_prefix' => $sStylePrefix,
+            'content' => $this->parseLink('javascript:void(0)', _t('_bx_timeline_txt_jump_to_recent'), array(
+                'title' => _t('_bx_timeline_txt_jump_to_n_year', $iYearNow),
+        		'onclick' => 'javascript:' . $sJsObject . '.changeTimeline(this, 0)'
+            ))
+        ));
+    }
+
+    public function getLoadMore($aParams, $bEnabled, $bVisible = true)
+    {
+        $sStylePrefix = $this->_oConfig->getPrefix('style');
+        $sJsObject = $this->_oConfig->getJsObjectView($aParams);
+
+        $iStart = $aParams['start'];
+        $iPerPage = $aParams['per_page'];
+
+        $aTmplVars = array(
+            'style_prefix' => $sStylePrefix,
+            'visible' => ($aParams['view'] == BX_TIMELINE_VIEW_TIMELINE && $bVisible) || ($aParams['view'] == BX_TIMELINE_VIEW_OUTLINE && $bEnabled && $bVisible) ? 'block' : 'none',
+            'bx_if:is_disabled' => array(
+                'condition' => !$bEnabled,
+                'content' => array()
+            ),
+            'bx_if:show_on_click' => array(
+                'condition' => $bEnabled,
+                'content' => array(
+                    'on_click' => 'javascript:' . $sJsObject . '.changePage(this, ' . ($iStart + $iPerPage) . ', ' . $iPerPage . ')'
+                )
+            ),
+            'bx_if:show_jump_to' => array(
+                'condition' => $this->_oConfig->isJumpTo(),
+                'content' => array(
+                    'style_prefix' => $sStylePrefix,
+                    'content' => $this->getJumpTo($aParams)
+                )
+            )
+        );
+        return $this->parseHtmlByName('load_more.html', $aTmplVars);
+    }
+
+    public function getLoadMoreAuto($aParams, $bEnabled, $bVisible = true)
+    {
+        $sStylePrefix = $this->_oConfig->getPrefix('style');
+
+        return $this->parseHtmlByName('load_more_auto.html', array(
+            'style_prefix' => $sStylePrefix,
+            'visible' => ($aParams['view'] == BX_TIMELINE_VIEW_TIMELINE && $bVisible) || ($aParams['view'] == BX_TIMELINE_VIEW_OUTLINE && $bEnabled && $bVisible) ? 'block' : 'none',
+            'loading' => _t('_bx_timeline_txt_loading' . ($bEnabled ? '' : '_complete'))
+        ));
+    }
+
+    /**
+     * Note. For now both List and Caledar based Jump To elements are available.
+     * Calendar based element is used by default. List based one can be removed 
+     * later if it won't be used completely.
+     */
+    public function getJumpTo($aParams)
+    {
+        if(!$this->_oConfig->isJumpTo())
+            return '';
+
+        $bList = false;
+        $bDynamicMode = isset($aParams['dynamic_mode']) && (bool)$aParams['dynamic_mode'] === true;
+
+        if($bList && !$bDynamicMode)
+            return '';
+
+        return $this->{'_getJumpTo' . ($bList ? 'List' : 'Caledar')}($aParams);
+    }
+
+    public function getComments($sSystem, $iId, $aBrowseParams = array())
+    {
+        $oModule = $this->getModule();
+        $sStylePrefix = $this->_oConfig->getPrefix('style');
+
+        $oCmts = $oModule->getCmtsObject($sSystem, $iId);
+        if($oCmts === false)
+            return '';
+
+        $aCmtsBp = array();
+        if(!empty($aBrowseParams['cmts_preload_number']))
+            $aCmtsBp['init_view'] = $aBrowseParams['cmts_preload_number'];
+
+        $aCmtsDp = array(
+            'in_designbox' => false, 
+            'dynamic_mode' => isset($aBrowseParams['dynamic_mode']) && $aBrowseParams['dynamic_mode'] === true
+        );
+        if(!empty($aBrowseParams['cmts_min_post_form']))
+            $aCmtsDp['min_post_form'] = $aBrowseParams['cmts_min_post_form'];
+
+        $aComments = $oCmts->getCommentsBlock($aCmtsBp, $aCmtsDp);
+        if(empty($aComments) || !is_array($aComments))
+            return '';
+
+        return $this->parseHtmlByName('comments.html', array(
+            'style_prefix' => $sStylePrefix,
+            'id' => $iId,
+            'content' => $aComments['content']
+        ));
+    }
+
+    public function getRepostElement($iOwnerId, $sType, $sAction, $iObjectId, $aParams = [])
+    {
+        $aReposted = $this->_oDb->getReposted($sType, $sAction, $iObjectId);
+        if(empty($aReposted) || !is_array($aReposted))
+            return '';
+
+        $oModule = $this->getModule();
+        $bDisabled = $oModule->isAllowedRepost($aReposted) !== true || $this->_oDb->isReposted($aReposted['id'], $iOwnerId, $oModule->getUserId());
+        if($bDisabled && (int)$aReposted['reposts'] == 0)
+            return '';
+
+        $sStylePrefix = $this->_oConfig->getPrefix('style');
+        $sStylePrefixRepost = $sStylePrefix . '-repost-';
+
+        $sDo = isset($aParams['do']) ? $aParams['do'] : 'repost';
+        $bDynamicMode = isset($aParams['dynamic_mode']) && $aParams['dynamic_mode'] === true;       
+
+        $bShowDoRepostAsButtonSmall = isset($aParams['show_do_repost_as_button_small']) && $aParams['show_do_repost_as_button_small'] == true;
+        $bShowDoRepostAsButton = !$bShowDoRepostAsButtonSmall && isset($aParams['show_do_repost_as_button']) && $aParams['show_do_repost_as_button'] == true;
+
+        $bShowDoRepostIcon = isset($aParams['show_do_repost_icon']) && $aParams['show_do_repost_icon'] == true && !empty($aParams['icon_do_repost']);
+        $bShowDoRepostText = isset($aParams['show_do_repost_text']) && $aParams['show_do_repost_text'] == true && !empty($aParams['text_do_repost']);
+        $bShowCounter = isset($aParams['show_counter']) && $aParams['show_counter'] === true;
+
+        //--- Do repost link ---//
+        $sClass = $sStylePrefixRepost . 'do-repost';
+        if($bShowDoRepostAsButton)
+            $sClass .= ' bx-btn';
+        else if($bShowDoRepostAsButtonSmall)
+            $sClass .= ' bx-btn bx-btn-small';
+
+        $sOnClick = '';
+        if(!$bDisabled) {
+            $sMethod = '_get' . bx_gen_method_name($sDo) . 'JsClick';
+            if(!method_exists($this, $sMethod))
+                $sMethod = '_getRepostJsClick';
+
+            $sCommonPrefix = $this->_oConfig->getPrefix('common_post');
+            if(str_replace($sCommonPrefix, '', $sType) == BX_TIMELINE_PARSE_TYPE_REPOST) {
+                $aRepostedData = unserialize($aReposted['content']);
+
+                $sOnClick = $this->$sMethod($iOwnerId, $aRepostedData['type'], $aRepostedData['action'], $aRepostedData['object_id']);
+            }
+            else
+                $sOnClick = $this->$sMethod($iOwnerId, $sType, $sAction, $iObjectId);
+        }
+        else
+            $sClass .= $bShowDoRepostAsButton || $bShowDoRepostAsButtonSmall ? ' bx-btn-disabled' : ' ' . $sStylePrefixRepost . 'disabled';
+
+        $aOnClickAttrs = array(
+            'title' => _t('_bx_timeline_txt_do_' . $sDo)
+        );
+        if(!empty($sClass))
+            $aOnClickAttrs['class'] = $sClass;
+        if(!empty($sOnClick))
+            $aOnClickAttrs['onclick'] = $sOnClick;
+
+        //--- Do repost label ---//
+        $sMethodDoRepostLabel = ''; 
+        $sTemplateDoRepostLabel = '';
+        if(!empty($aParams['template_do_repost_label'])) {
+            $sMethodDoRepostLabel = 'parseHtmlByContent';
+            $sTemplateDoRepostLabel = $aParams['template_do_repost_label'];
+        }
+        else {
+            $sMethodDoRepostLabel = 'parseHtmlByName';
+            $sTemplateDoRepostLabel = $aParams['template_do_repost_label_name'];
+        }
+
+        $sDoRepost = $this->$sMethodDoRepostLabel($sTemplateDoRepostLabel, array(
+            'style_prefix' => $sStylePrefix,
+            'bx_if:show_icon' => array(
+                'condition' => $bShowDoRepostIcon,
+                'content' => array(
+                    'style_prefix' => $sStylePrefix,
+                    'icon' => $this->getImageAuto($aParams['icon_do_' . $sDo])
+                )
+            ),
+            'bx_if:show_text' => array(
+                'condition' => $bShowDoRepostText,
+                'content' => array(
+                    'style_prefix' => $sStylePrefix,
+                    'text' => _t($aParams['text_do_' . $sDo])
+                )
+            )
+        ));
+
+        return $this->parseHtmlByName('repost_element_block.html', array(
+            'style_prefix' => $sStylePrefix,
+            'html_id' => $this->_oConfig->getHtmlIds('repost', 'main') . $aReposted['id'],
+            'class' => ($bShowDoRepostAsButton ? $sStylePrefixRepost . 'button' : '') . ($bShowDoRepostAsButtonSmall ? $sStylePrefixRepost . 'button-small' : ''),
+            'count' => $aReposted['reposts'],
+            'do_repost' => $this->parseLink('javascript:void(0)', $sDoRepost, $aOnClickAttrs),
+            'bx_if:show_counter' => array(
+                'condition' => $bShowCounter,
+                'content' => array(
+                    'style_prefix' => $sStylePrefix,
+                    'bx_if:show_hidden' => array(
+                        'condition' => (int)$aReposted['reposts'] == 0,
+                        'content' => array()
+                    ),
+                    'counter' => $this->getRepostCounter($aReposted, array_merge($aParams, ['show_script' => false]))
+                )
+            ),
+            'script' => $this->getRepostJsScript($bDynamicMode)
+        ));
+    }
+
+    public function getRepostCounter($aEvent, $aParams = [])
+    {
+        $sStylePrefix = $this->_oConfig->getPrefix('style');
+        $sJsObject = $this->_oConfig->getJsObject('repost');
+
+        $bDynamicMode = isset($aParams['dynamic_mode']) && $aParams['dynamic_mode'] === true;
+
+        $bShowDoRepostAsButtonSmall = isset($aParams['show_do_repost_as_button_small']) && $aParams['show_do_repost_as_button_small'] == true;
+        $bShowDoRepostAsButton = !$bShowDoRepostAsButtonSmall && isset($aParams['show_do_repost_as_button']) && $aParams['show_do_repost_as_button'] == true;
+        $bShowScript = !isset($aParams['show_script']) || (bool)$aParams['show_script'] === true;
+
+        $sClass = $sStylePrefix . '-repost-counter';
+        if($bShowDoRepostAsButtonSmall)
+            $sClass .= ' bx-btn-small-height';
+        if($bShowDoRepostAsButton)
+            $sClass .= ' bx-btn-height';
+
+        return $this->parseHtmlByName('repost_counter.html', [
+            'class' => $sClass,
+            'bx_repeat:attrs' => [
+                ['key' => 'id', 'value' => $this->_oConfig->getHtmlIds('repost', 'counter') . $aEvent['id']],
+                ['key' => 'title', 'value' => _t('_bx_timeline_txt_reposted_by')],
+                ['key' => 'href', 'value' => 'javascript:void(0)'],
+                ['key' => 'onclick', 'value' => 'javascript:' . $sJsObject . '.toggleByPopup(this, ' . $aEvent['id'] . ')']
+            ],
+            'content' => !empty($aEvent['reposts']) && (int)$aEvent['reposts'] > 0 ? $this->getRepostCounterLabel($aEvent['reposts'], $aParams) : '',
+            'script' => $bShowScript ? $this->getRepostJsScript($bDynamicMode) : ''
+        ]);
+    }
+
+    public function getRepostCounterLabel($iCount, $aParams = [])
+    {
+        $sStylePrefix = $this->_oConfig->getPrefix('style');
+
+        return $this->parseHtmlByName('repost_counter_label.html', [
+            'style_prefix' => $sStylePrefix,
+            'bx_if:show_icon' => array(
+                'condition' => !isset($aParams['show_counter_label_icon']) || (bool)$aParams['show_counter_label_icon'] === true,
+                'content' => array(
+                    'style_prefix' => $sStylePrefix,
+                    'icon' => $this->_getCounterIcon($aParams),
+                )
+            ),
+            'bx_if:show_text' => array(
+                'condition' => !isset($aParams['show_counter_label_text']) || (bool)$aParams['show_counter_label_text'] === true,
+                'content' => array(
+                    'style_prefix' => $sStylePrefix,
+                    'text' => $this->_getCounterLabel($iCount, $aParams)
+                )
+            )
+        ]);
+    }
+
+    public function getRepostedBy($iId)
+    {
+        $aTmplUsers = array();
+        $oModule = $this->getModule();
+        $sStylePrefix = $this->_oConfig->getPrefix('style');
+
+        $aUserIds = $this->_oDb->getRepostedBy($iId);
+        foreach($aUserIds as $iUserId)
+            $aTmplUsers[] = array(
+                'style_prefix' => $sStylePrefix,
+                'user_unit' => $oModule->getObjectUser($iUserId)->getUnit()
+            );
+
+        bx_alert($this->_oConfig->getName(), 'get_reposted_by', 0, 0, array(
+            'content_id' => $iId,
+            'user_ids' => $aUserIds,
+            'users' => &$aTmplUsers
+        ));
+        
+        if(empty($aTmplUsers))
+            $aTmplUsers = MsgBox(_t('_Empty'));
+
+        return $this->parseHtmlByName('repost_by_list.html', array(
+            'style_prefix' => $sStylePrefix,
+            'bx_repeat:list' => $aTmplUsers
+        ));
+    }
+
+    public function getRepostWith($oForm)
+    {
+        $sStylePrefix = $this->_oConfig->getPrefix('style');
+        $sJsObject = $this->_oConfig->getJsObject('repost');
+
+        return $this->parseHtmlByName('repost_with_popup.html', array(
+            'style_prefix' => $sStylePrefix,
+            'js_object' => $sJsObject,
+            'form' => $oForm->getCode(),
+            'form_id' => $oForm->getId()
+        ));
+    }
+
+    public function getRepostWithFieldReposted($oForm, $aInput)
+    {
+        $sStylePrefix = $this->_oConfig->getPrefix('style');
+        $aBrowseParams = $this->getModule()->getParams();
+
+        $aReposted = $oForm->getReposted();
+        $sReposted = $this->getPost($aReposted, $aBrowseParams);
+
+        $sContent = '';
+        if(!empty($sReposted))
+            $sContent = $this->_getContent($aReposted['content_type'], $aReposted, $aBrowseParams);
+        else
+            $sContent = MsgBox(_t('_Empty'));
+
+        return $this->parseHtmlByName('repost_with_reposted.html', array(
+            'style_prefix' => $sStylePrefix,
+            'content' => $sContent
+        ));
+    }
+
+    public function getRepostTo($oForm)
+    {
+        $sStylePrefix = $this->_oConfig->getPrefix('style');
+        $sJsObject = $this->_oConfig->getJsObject('repost');
+
+        return $this->parseHtmlByName('repost_to_popup.html', array(
+            'style_prefix' => $sStylePrefix,
+            'js_object' => $sJsObject,
+            'form' => $oForm->getCode(),
+            'form_id' => $oForm->getId()
+        ));
+    }
+
+    public function getRepostToFieldList($oForm, $aInput)
+    {
+        $sStylePrefix = $this->_oConfig->getPrefix('style');
+
+        $oConnection = BxDolConnection::getObjectInstance('sys_profiles_subscriptions');
+        if(!$oConnection)
+            return '';
+
+        $iProfileId = bx_get_logged_profile_id();
+        $aConnectedIds = $oConnection->getConnectedContent($iProfileId);
+
+        $aSelected = array();
+        $aTmplVarsModules = array();
+        if(!empty($aConnectedIds) && is_array($aConnectedIds)) {
+            $aCheckbox = $aInput;
+            $aCheckbox['type'] = 'checkbox';
+            $aCheckbox['name'] .= '[]';
+
+            foreach($aConnectedIds as $iConnectedId) {
+                $oProfile = BxDolProfile::getInstanceMagic($iConnectedId);
+                if(!$oProfile)
+                    continue;
+
+                $sProfileModule = $oProfile->getModule();
+                if(!isset($aTmplVarsModules[$sProfileModule]))
+                    $aTmplVarsModules[$sProfileModule] = array(
+                        'style_prefix' => $sStylePrefix,
+                        'title' => _t('_' . $sProfileModule),
+                        'bx_repeat:contexts' => array()
+                    );
+                        
+                $aCheckbox['value'] = $iConnectedId;
+                $aCheckbox['checked'] = in_array($iConnectedId, $aSelected) ? 1 : 0;
+
+                $aTmplVarsModules[$sProfileModule]['bx_repeat:contexts'][] = array(
+                    'style_prefix' => $sStylePrefix,
+                    'checkbox' => $oForm->genInput($aCheckbox),
+                    'unit' => $oProfile->getUnit(0, array('template' => 'unit_wo_cover'))
+                );
+            }
+        }      
+
+        return $this->parseHtmlByName('repost_to_list.html', array(
+            'style_prefix' => $sStylePrefix,
+            'bx_repeat:modules' => !empty($aTmplVarsModules)? array_values($aTmplVarsModules) : MsgBox(_t('_Empty'))
+        ));
+    }
+
+    public function getRepostJsScript($bDynamicMode = false)
+    {
+        $sCode = $this->getJsCode('repost', array(), array('mask' => '{object} = new {class}({params});', 'wrap' => false));
+
+        if($bDynamicMode) {
+            $sJsObject = $this->_oConfig->getJsObject('repost');
+
+            $sCode = "var " . $sJsObject . " = null; 
+            $.getScript('" . bx_js_string($this->getJsUrl('main.js'), BX_ESCAPE_STR_APOS) . "', function(data, textStatus, jqxhr) {
+                $.getScript('" . bx_js_string($this->getJsUrl('repost.js'), BX_ESCAPE_STR_APOS) . "', function(data, textStatus, jqxhr) {
+                    bx_get_style('" . bx_js_string($this->getCssUrl('repost.css'), BX_ESCAPE_STR_APOS) . "');
+                    " . $sCode . "
+                });
+            }); ";
+        }
+        else {
+            $sCode = "var " . $sCode;
+
+            $this->addCss(array('repost.css'));
+            $this->addJs(array('main.js', 'repost.js'));
+        }
+
+        return $this->_wrapInTagJsCode($sCode);
+    }
+
+    public function getRepostJsClick($iOwnerId, $sType, $sAction, $iObjectId)
+    {
+        $aReposted = $this->_oDb->getReposted($sType, $sAction, $iObjectId);
+        if(empty($aReposted) || !is_array($aReposted))
+            return '';
+
+        $sResult = '';
+        $sCommonPrefix = $this->_oConfig->getPrefix('common_post');
+        if(str_replace($sCommonPrefix, '', $sType) == BX_TIMELINE_PARSE_TYPE_REPOST) {
+            $aRepostedData = unserialize($aReposted['content']);
+
+            $sResult = $this->_getRepostJsClick($iOwnerId, $aRepostedData['type'], $aRepostedData['action'], $aRepostedData['object_id']);
+        }
+        else
+            $sResult = $this->_getRepostJsClick($iOwnerId, $sType, $sAction, $iObjectId);
+
+        return $sResult;
+    }
+
+    public function getRepostWithJsClick($iReposterId, $sType, $sAction, $iObjectId)
+    {
+        $aReposted = $this->_oDb->getReposted($sType, $sAction, $iObjectId);
+        if(empty($aReposted) || !is_array($aReposted))
+            return '';
+
+        $sResult = '';
+        $sCommonPrefix = $this->_oConfig->getPrefix('common_post');
+        if(str_replace($sCommonPrefix, '', $sType) == BX_TIMELINE_PARSE_TYPE_REPOST) {
+            $aRepostedData = unserialize($aReposted['content']);
+
+            $sResult = $this->_getRepostWithJsClick($iReposterId, $aRepostedData['type'], $aRepostedData['action'], $aRepostedData['object_id']);
+        }
+        else
+            $sResult = $this->_getRepostWithJsClick($iReposterId, $sType, $sAction, $iObjectId);
+
+        return $sResult;
+    }
+
+    public function getRepostToJsClick($iReposterId, $sType, $sAction, $iObjectId)
+    {
+        $aReposted = $this->_oDb->getReposted($sType, $sAction, $iObjectId);
+        if(empty($aReposted) || !is_array($aReposted))
+            return '';
+
+        $sResult = '';
+        $sCommonPrefix = $this->_oConfig->getPrefix('common_post');
+        if(str_replace($sCommonPrefix, '', $sType) == BX_TIMELINE_PARSE_TYPE_REPOST) {
+            $aRepostedData = unserialize($aReposted['content']);
+
+            $sResult = $this->_getRepostToJsClick($iReposterId, $aRepostedData['type'], $aRepostedData['action'], $aRepostedData['object_id']);
+        }
+        else
+            $sResult = $this->_getRepostToJsClick($iReposterId, $sType, $sAction, $iObjectId);
+
+        return $sResult;
+    }
+
+    public function getAttachLinkForm($iEventId = 0)
+    {
+        $sStylePrefix = $this->_oConfig->getPrefix('style');
+        $sJsObject = $this->_oConfig->getJsObject('post');
+
+        $aForm = $this->getModule()->getFormAttachLink($iEventId);
+
+        return $this->parseHtmlByName('attach_link_form.html', array(
+            'style_prefix' => $sStylePrefix,
+            'js_object' => $sJsObject,
+            'form_id' => $aForm['form_id'],
+            'form' => $aForm['form'],
+        ));
+    }
+
+    public function getAttachLinkField($iUserId, $iEventId = 0)
+    {
+        $sStylePrefix = $this->_oConfig->getPrefix('style');
+
+        if(!$iEventId)
+            $aLinks = $this->_oDb->getUnusedLinks($iUserId);
+        else
+            $aLinks = $this->_oDb->getLinks($iEventId);
+
+        $sLinks = '';
+        foreach($aLinks as $aLink)
+            $sLinks .= $this->getAttachLinkItem($iUserId, $aLink);
+
+        return $this->parseHtmlByName('attach_link_form_field.html', array(
+            'html_id' => $this->_oConfig->getHtmlIds('post', 'attach_link_form_field') . $iEventId,
+            'style_prefix' => $sStylePrefix,
+            'links' => $sLinks
+        ));
+    }
+
+    public function getAttachLinkItem($iUserId, $mixedLink)
+    {
+        $aLink = is_array($mixedLink) ? $mixedLink : $this->_oDb->getLinksBy(array('type' => 'id', 'id' => (int)$mixedLink, 'profile_id' => $iUserId));
+        if(empty($aLink) || !is_array($aLink))
+            return '';
+
+        $sLinkIdPrefix = $this->_oConfig->getHtmlIds('post', 'attach_link_item');
+        $sStylePrefix = $this->_oConfig->getPrefix('style');
+        $sClass = $sStylePrefix . '-al-item';
+        $sJsObject = $this->_oConfig->getJsObject('post');
+
+        $oEmbed = BxDolEmbed::getObjectInstance();
+        $bEmbed = $oEmbed !== false;
+
+        $sThumbnail = '';
+        $aLinkAttrs = array();
+        if(!$bEmbed) {
+            $aLinkAttrs = array(
+            	'title' => bx_html_attribute($aLink['title'])
+            );
+            if(!$this->_oConfig->isEqualUrls(BX_DOL_URL_ROOT, $aLink['url'])) {
+                $aLinkAttrs['target'] = '_blank';
+    
+                if($this->_oDb->getParam('sys_add_nofollow') == 'on')
+            	    $aLinkAttrs['rel'] = 'nofollow';
+            }
+
+            if((int)$aLink['media_id'] != 0)
+                $sThumbnail = BxDolTranscoderImage::getObjectInstance($this->_oConfig->getObject('transcoder_photos_preview'))->getFileUrl($aLink['media_id']);
+        }
+        else
+            $sClass .= ' embed';
+
+        return $this->parseHtmlByName('attach_link_item.html', array(
+            'html_id' => $sLinkIdPrefix . $aLink['id'],
+            'style_prefix' => $sStylePrefix,
+            'class' => $sClass,
+            'js_object' => $sJsObject,
+            'id' => $aLink['id'],
+            'bx_if:show_embed_outer' => array(
+                'condition' => $bEmbed,
+                'content' => array(
+                    'style_prefix' => $sStylePrefix,
+                    'embed' => $bEmbed ? $oEmbed->getLinkHTML($aLink['url'], $aLink['title'], 300) : '',
+                )
+            ),
+            'bx_if:show_embed_inner' => array(
+                'condition' => !$bEmbed,
+                'content' => array(
+                    'style_prefix' => $sStylePrefix,
+                    'bx_if:show_thumbnail' => array(
+                        'condition' => !empty($sThumbnail),
+                        'content' => array(
+                            'style_prefix' => $sStylePrefix,
+                            'thumbnail' => $sThumbnail
+                        )
+                    ),
+                    'url' => $aLink['url'],
+                    'link' => $this->parseLink($aLink['url'], $aLink['title'], $aLinkAttrs)
+                )
+            ),
+        ));
+    }
+
+    public function getData(&$aEvent, $aBrowseParams = array())
+    {
+        $aResult = $this->_oConfig->isSystem($aEvent['type'], $aEvent['action']) ? $this->_getSystemData($aEvent, $aBrowseParams) : $this->_getCommonData($aEvent, $aBrowseParams);
+        if(empty($aResult) || empty($aResult['object_owner_id']) || empty($aResult['content']))
+            return false;
+
+        $sSample = !empty($aResult['sample']) ? $aResult['sample'] : '_bx_timeline_txt_sample';
+
+        $aUpdate = array(
+            'object_owner_id' => $aResult['object_owner_id']
+        );
+
+        //--- Update Title if empty.
+        if(empty($aEvent['title'])) {
+            $sTitle = !empty($aResult['title']) ? $this->_oConfig->getTitle($aResult['title']) : _t($sSample);
+
+            $aUpdate['title'] = bx_process_input(strip_tags($sTitle));
+        }
+
+        //--- Update Description if empty.
+        if(empty($aEvent['description'])) {
+            $sUserName = $this->getModule()->getObjectUser($aResult['object_owner_id'])->getDisplayName();
+
+            $sDescription = !empty($aResult['description']) ? $aResult['description'] : _t('_bx_timeline_txt_user_added_sample', $sUserName, _t($sSample));
+            if($sDescription == '' && !empty($aResult['content']['text']))
+                $sDescription = $aResult['content']['text'];
+
+            $aUpdate['description'] = bx_process_input(strip_tags($sDescription));
+        }
+
+        if(!empty($aUpdate) && is_array($aUpdate)) 
+            $this->_oDb->updateEvent($aUpdate, array('id' => $aEvent['id']));
+
+        return $aResult;
+    }
+
+    public function getDataCached($aEvent, $aBrowseParams = array())
+    {
+        if(!$this->_oConfig->isCacheItem()) 
+            return $this->getData($aEvent, $aBrowseParams);
+
+        /**
+         * For now parameters from $aBrowseParams array aren't used during data retrieving.
+         * If they will then the cache should be created depending on their values.
+         */
+        $sCacheKey = $this->_oConfig->getCacheItemKey($aEvent['id']);
+        $iCacheLifetime = $this->_oConfig->getCacheItemLifetime();
+
+        $oCache = $this->getModule()->getCacheItemObject();
+        $aCached = $oCache->getData($sCacheKey, $iCacheLifetime);
+        if(!empty($aCached)) 
+            return unserialize($aCached);
+
+        $aBrowseParams['dynamic_mode'] = true;
+        $aResult = $this->getData($aEvent, $aBrowseParams);
+        if(!empty($aResult) && isset($aResult['_cache']) && (bool)$aResult['_cache'] === false)
+            return $aResult;
+
+        $oCache->setData($sCacheKey, serialize($aResult), $iCacheLifetime);           
+        return $aResult;
+    }
+
+    public function getVideo($aEvent, $aVideo)
+    {
+        $sVideoId = $this->_oConfig->getHtmlIds('view', 'video') . $aEvent['id'] . '-' . $aVideo['id'];
+        $oPlayer = BxDolPlayer::getObjectInstance();
+        if (!$oPlayer)
+            return '';
+
+        $sPlayer = $oPlayer->getCodeVideo (BX_PLAYER_EMBED, array(
+            'poster' => $aVideo['src_poster'],
+            'mp4' => array('sd' => $aVideo['src_mp4'], 'hd' => $aVideo['src_mp4_hd']),
+            'attrs' => array('id' => $sVideoId),
+        ));
+        return $this->parseHtmlByName('video_player.html', array(
+            'player' => $sPlayer,
+            'html_id' => $sVideoId
+        ));
+    }
+
+    /*
+     * Show only one Live Update notification for all new Events.
+     */
+    function getLiveUpdate($aBrowseParams, $iProfileId, $iCountOld = 0, $iCountNew = 0)
+    {
+        $oModule = $this->getModule();
+
+    	$iCount = (int)$iCountNew - (int)$iCountOld;
+    	if($iCount < 0)
+            return '';
+
+        $aParams = $oModule->getParamsExt($aBrowseParams);
+        $aParams['start'] = 0;
+        $aParams['per_page'] = 1;
+        $aParams['newest'] = true;
+        $aParams['filter'] = BX_TIMELINE_FILTER_OTHER_VIEWER;
+        $aEvents = $this->_oDb->getEvents($aParams);
+        if(empty($aEvents) || !is_array($aEvents))
+            return '';
+
+        $aEvent = array_shift($aEvents);
+        if(empty($aEvent) || !is_array($aEvent))
+            return '';
+
+        $sJsObject = $this->_oConfig->getJsObjectView($aParams);
+        $sStylePrefix = $this->_oConfig->getPrefix('style');
+
+        return $this->parseHtmlByName('live_update_button.html', array(
+            'style_prefix' => $sStylePrefix,
+            'html_id' => $this->_oConfig->getHtmlIds('view', 'live_update_popup') . $aBrowseParams['type'],
+            'onclick_show' => "javascript:" . $sJsObject . ".goToBtn(this, 'timeline-event-" . $aEvent['id'] . "', '" . $aEvent['id'] . "');",
+        ));
+    }
+
+    /*
+     * Show Live Update notification separately for each new Event. Popup Chain is used here.
+     * 
+     * Note. This way to display live update notifications isn't used for now. 
+     * See BxTimelineTemplate::getLiveUpdate method instead.
+     */
+    function getLiveUpdates($aBrowseParams, $iProfileId, $iCountOld = 0, $iCountNew = 0)
+    {
+        $bShowAll = true;
+        $bShowActions = false;
+        $oModule = $this->getModule();
+
+    	$iCount = (int)$iCountNew - (int)$iCountOld;
+    	if($iCount < 0)
+            return '';
+
+        $iCountMax = $this->_oConfig->getLiveUpdateLength();
+        if($iCount > $iCountMax)
+            $iCount = $iCountMax;
+
+        $aParams = $oModule->getParamsExt($aBrowseParams);
+        $aParams['start'] = 0;
+        $aParams['per_page'] = $iCount;
+        $aParams['filter'] = BX_TIMELINE_FILTER_OTHER_VIEWER;
+        $aEvents = $this->_oDb->getEvents($aParams);
+        if(empty($aEvents) || !is_array($aEvents))
+            return '';
+
+        $sJsObject = $this->_oConfig->getJsObjectView($aParams);
+        $sStylePrefix = $this->_oConfig->getPrefix('style');
+
+        $iUserId = $oModule->getUserId();
+        $bModerator = $oModule->isModerator();
+
+        $aEvents = array_reverse($aEvents);
+        $iEvents = count($aEvents);
+
+        $aTmplVarsItems = array();
+        foreach($aEvents as $iIndex => $aEvent) {
+            $aData = $this->getDataCached($aEvent);
+            if($aData === false)
+                continue;
+
+            $iEventId = $aEvent['id'];
+            $iEventAuthorId = $this->_oConfig->isSystem($aEvent['type'], $aEvent['action']) ? (int)$aEvent['owner_id'] : (int)$aEvent['object_id'];
+            if($iEventAuthorId < 0) {
+                if(abs($iEventAuthorId) == $iUserId)
+                    continue;
+                else if($bModerator)
+                    $iEventAuthorId *= -1;
+            }
+
+            $oAuthor = $oModule->getObjectUser($iEventAuthorId);
+            $sAuthorName = $oAuthor->getDisplayName();
+
+            $aTmplVarsItems[] = array(
+                'bx_if:show_as_hidden' => array(
+                    'condition' => !$bShowAll && $iIndex < ($iEvents - 1),
+                    'content' => array(),
+                ),
+                'item' => $this->parseHtmlByName('live_update_notification.html', array(
+                    'style_prefix' => $sStylePrefix,
+                    'onclick_show' => "javascript:" . $sJsObject . ".goTo(this, 'timeline-event-" . $iEventId . "', '" . $iEventId . "');",
+                    'author_link' => $oAuthor->getUrl(), 
+                    'author_title' => bx_html_attribute($sAuthorName),
+                    'author_name' => $sAuthorName,
+                    'author_unit' => $oAuthor->getUnit(0, array('template' => 'unit_wo_info_links')), 
+                    'text' => _t($aData['sample_action'], _t($aData['sample'])),
+                )),
+                'bx_if:show_previous' => array(
+                    'condition' => $bShowActions && $iIndex > 0,
+                    'content' => array(
+                        'onclick_previous' => $sJsObject . '.previousLiveUpdate(this)'
+                    )
+                ),
+                'bx_if:show_close' => array(
+                    'condition' => $bShowActions,
+                    'content' => array(
+                        'onclick_close' => $sJsObject . '.hideLiveUpdate(this)'
+                    )
+                )
+            );
+        }
+
+        return $this->parseHtmlByName('popup_chain.html', array(
+            'html_id' => $this->_oConfig->getHtmlIds('view', 'live_update_popup') . $aBrowseParams['type'],
+            'bx_repeat:items' => $aTmplVarsItems
+        ));
+    }
+
+    protected function _getPost($sType, $aEvent, $aBrowseParams = array())
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $oModule = $this->getModule();
+        $sStylePrefix = $this->_oConfig->getPrefix('style');
+        $sJsObject = $this->_oConfig->getJsObjectView($aBrowseParams);
+
+        $bViewItem = isset($aBrowseParams['view']) && $aBrowseParams['view'] == BX_TIMELINE_VIEW_ITEM;
+        $bViewOutline = isset($aBrowseParams['view']) && $aBrowseParams['view'] == BX_TIMELINE_VIEW_OUTLINE;
+
+        $oAuthor = $oModule->getObjectUser($aEvent['object_owner_id']);
+        $sAuthorName = $oAuthor->getDisplayName(); 
+        $sAuthorUrl = $oAuthor->getUrl();
+        $sAuthorUnit = $oAuthor->getUnit(0, array('template' => 'unit_wo_info'));
+        $sAuthorBadges = $oAuthor->getBadges();
+        $sAuthorAction = '';
+
+        if(!empty($aEvent['sample_action_custom']) && is_array($aEvent['sample_action_custom'])) {
+            $aAuthorAction = $aEvent['sample_action_custom'];
+
+            foreach($aAuthorAction['markers'] as $iIndex => $sMarker)
+                if(get_mb_substr($sMarker, 0, 1) == '_')
+                    $aAuthorAction['markers'][$iIndex] = _t($sMarker);
+
+            $sAuthorAction = bx_replace_markers(_t($aAuthorAction['content']), $aAuthorAction['markers']);
+        }
+        else
+            $sAuthorAction = _t($aEvent['sample_action'], _t($aEvent['sample']));
+
+        if(($bViewItem || $this->_oConfig->isCountAllViews()) && !empty($aEvent['views']) && is_array($aEvent['views']) && isset($aEvent['views']['system']))
+            $oModule->getViewObject($aEvent['views']['system'], $aEvent['views']['object_id'])->doView();
+
+        $aTmplVarsNote = $this->_getTmplVarsNote($aEvent);
+        $aTmplVarsMenuItemCounters = $this->_getTmplVarsMenuItemCounters($aEvent, $aBrowseParams);
+        $aTmplVarsMenuItemActions = $this->_getTmplVarsMenuItemActions($aEvent, $aBrowseParams);
+        $aTmplVarsMenuItemMeta = $this->_getTmplVarsMenuItemMeta($aEvent, $aBrowseParams);
+
+        $aTmplVarsManage = $this->_getTmplVarsManage($aEvent, $aBrowseParams);
+
+        $aTmplVarsTimelineOwner = $this->_getTmplVarsTimelineOwner($aEvent);
+        $bTmplVarsTimelineOwner = !empty($aTmplVarsTimelineOwner);
+
+        $aTmplVarsOwnerActions = $this->_getTmplVarsOwnerActions($aEvent, $aBrowseParams);
+        $bTmplVarsOwnerActions = !empty($aTmplVarsOwnerActions); 
+
+        $bPinned = $aBrowseParams['type'] == BX_BASE_MOD_NTFS_TYPE_OWNER && (int)$aEvent['pinned'] > 0;
+        $bSticked = (int)$aEvent['sticked'] > 0;
+        $bPromoted = (int)$aEvent['promoted'] > 0;
+
+        $sClass = $sStylePrefix . '-view-sizer';
+        if($bViewOutline) {
+            $sClass = $sStylePrefix . '-grid-item-sizer';
+            if($bPinned || $bSticked || $bPromoted) {
+                $sClass .= ' ' . $sStylePrefix . '-gis';
+
+            if($bPinned)
+                $sClass .= '-pnd';
+            if($bSticked)
+                $sClass .= '-psd';
+            if($bPromoted)
+                $sClass .= '-pmd';
+            }
+        }
+
+        $sClass .= ' ' . $aEvent['type'] . (!empty($aEvent['action']) ? ' ' . $aEvent['action'] : '');
+        $aAuthorAcl = BxDolAcl::getInstance()->getMemberMembershipInfo($aEvent['object_owner_id']);
+        if(!empty($aAuthorAcl) && isset($this->_aAclId2Name[$aAuthorAcl['id']]))
+            $sClass .= ' ' . $sStylePrefix . '-aml-' . $this->_aAclId2Name[$aAuthorAcl['id']];
+
+        if(!empty($aBrowseParams['blink']) && in_array($aEvent['id'], $aBrowseParams['blink']))
+            $sClass .= ' ' . $sStylePrefix . '-blink';
+        if($bPinned)
+            $sClass .= ' ' . $sStylePrefix . '-pinned';
+        if($bSticked)
+            $sClass .= ' ' . $sStylePrefix . '-sticked';
+        if($bPromoted)
+            $sClass .= ' ' . $sStylePrefix . '-promoted';
+
+        $sClassOwner = $bTmplVarsOwnerActions ? $sStylePrefix . '-io-with-actions' : '';
+
+        $oMetatags = BxDolMetatags::getObjectInstance($this->_oConfig->getObject('metatags'));
+        $sLocation = $oMetatags->locationsString($aEvent['id']);
+ 
+        $sFields = '';
+        if(!$bViewItem) {
+            $oForm = BxDolForm::getObjectInstance($this->_oConfig->getObject('form_post'), $this->_oConfig->getObject('form_display_post_view'), $this, $aEvent['id']);
+            $oForm->initChecker($aEvent);
+
+            if(!empty($oForm->aInputs) && is_array($oForm->aInputs))
+                foreach($oForm->aInputs as $aInput)
+                    if($aInput['type'] != 'hidden' && !empty($aInput['value'])) {
+                        $sFields = $oForm->getCode();
+                        break;
+                    }
+        }
+
+        $sIcon = !empty($aEvent['icon']) ? $aEvent['icon'] : $CNF['ICON'];
+
+        $aTmplVars = array (
+            'style_prefix' => $sStylePrefix,
+            'js_object' => $sJsObject,
+            'html_id' => $this->_oConfig->getHtmlIdView('item', $aBrowseParams, array('whole' => false)) . $aEvent['id'],
+            'class' => $sClass,
+            'class_owner' => $sClassOwner,
+            'class_content' => $bViewItem ? 'bx-def-color-bg-block' : 'bx-def-color-bg-box',
+            'id' => $aEvent['id'],
+            'bx_if:show_note' => array(
+                'condition' => !empty($aTmplVarsNote),
+                'content' => $aTmplVarsNote
+            ),
+            'bx_if:show_owner_actions' => array(
+                'condition' => $bTmplVarsOwnerActions,
+                'content' => $aTmplVarsOwnerActions
+            ),
+            'item_icon' => $sIcon,
+            'item_owner_url' => $sAuthorUrl,
+            'item_owner_title' => bx_html_attribute($sAuthorName),
+            'item_owner_name' => $sAuthorName .' '. $sAuthorBadges,
+            'item_owner_unit' => $sAuthorUnit,
+            'item_view_url' => $this->_oConfig->getItemViewUrl($aEvent),
+            'item_date' => bx_time_js($aEvent['date']),
+            'bx_if:show_pinned' => array(
+            	'condition' => $bPinned,
+            	'content' => array(
+                    'style_prefix' => $sStylePrefix,
+            	)
+            ),
+            'bx_if:show_sticked' => array(
+            	'condition' => $bSticked,
+            	'content' => array(
+                    'style_prefix' => $sStylePrefix,
+            	)
+            ),
+            'bx_if:show_hot' => array(
+            	'condition' => $this->_oConfig->isHotEvent($aEvent['id']),
+            	'content' => array(
+                    'style_prefix' => $sStylePrefix,
+            	)
+            ),
+            'bx_if:show_manage' => array(
+                'condition' => !empty($aTmplVarsManage),
+                'content' => $aTmplVarsManage
+            ),
+            'bx_if:show_item_action' => array(
+                'condition' => $this->_oConfig->isSystem($aEvent['type'], $aEvent['action']) || $bTmplVarsTimelineOwner,
+                'content' => array(
+                    'style_prefix' => $sStylePrefix,
+                    'item_icon' => $sIcon,
+                    'item_owner_action' => $sAuthorAction,
+                    'bx_if:show_timeline_owner' => array(
+                        'condition' => $bTmplVarsTimelineOwner,
+                        'content' => $aTmplVarsTimelineOwner
+                    ),
+                )
+            ),
+            'content_type' => $sType,
+            'content' => is_string($aEvent['content']) ? $aEvent['content'] : $this->_getContent($sType, $aEvent, $aBrowseParams),
+            'bx_if:show_location' => array(
+            	'condition' => !empty($sLocation),
+            	'content' => array(
+                    'style_prefix' => $sStylePrefix,
+                    'location' => $sLocation
+            	)
+            ),
+            'bx_if:show_fields' => array(
+                'condition' => !empty($sFields),
+                'content' => array(
+                    'style_prefix' => $sStylePrefix,
+                    'fields' => $sFields
+            	)
+            ),
+            'bx_if:show_menu_item_counters' => array(
+                'condition' => !empty($aTmplVarsMenuItemCounters),
+                'content' => $aTmplVarsMenuItemCounters
+            ),
+            'bx_if:show_menu_item_actions' => array(
+                'condition' => !empty($aTmplVarsMenuItemActions),
+                'content' => $aTmplVarsMenuItemActions
+            ),
+            'bx_if:show_menu_item_meta' => array(
+                'condition' => !empty($aTmplVarsMenuItemMeta),
+                'content' => $aTmplVarsMenuItemMeta
+            ),
+            'comments' => '',
+        );
+
+        $iPreloadComments = $this->_oConfig->getPreloadComments();
+        if($iPreloadComments > 0 && $oModule->isAllowedComment($aEvent) && in_array($aBrowseParams['view'], array(BX_TIMELINE_VIEW_TIMELINE, BX_TIMELINE_VIEW_OUTLINE)))
+            $aTmplVars['comments'] = $this->_getComments($aEvent['comments'], array_merge($aBrowseParams, array(
+                'cmts_preload_number' => $iPreloadComments,
+                'cmts_min_post_form' => false
+            )));       
+
+        $sVariable = '_sTmplContentItem' . bx_gen_method_name($aBrowseParams['view']);
+        if(empty(self::$$sVariable))
+            self::$$sVariable = $this->getHtml('item_' . $aBrowseParams['view'] . '.html');
+
+        $sTmplCode = self::$$sVariable;
+        bx_alert($this->_oConfig->getName(), 'get_post', 0, 0, array(
+            'type' => $sType,
+            'event' => $aEvent,
+            'browse_params' => $aBrowseParams,
+            'tmpl_code' => &$sTmplCode,
+            'tmpl_vars' => &$aTmplVars
+        ));
+
+        return $this->parseHtmlByContent($sTmplCode, $aTmplVars);
+    }
+
+    protected function _getContent($sType, $aEvent, $aBrowseParams = array())
+    {
+        $sMethod = '_getTmplVarsContent' . ucfirst($sType);
+        if(!method_exists($this, $sMethod))
+            return '';
+
+        $aTmplVars = $this->$sMethod($aEvent, $aBrowseParams);
+
+        $sVariable = '_sTmplContentType' . bx_gen_method_name($sType);
+        if(empty(self::$$sVariable))
+            self::$$sVariable = $this->getHtml('type_' . $sType . '.html');
+
+        $sTmplCode = self::$$sVariable;
+        bx_alert($this->_oConfig->getName(), 'get_post_content', 0, 0, array(
+            'type' => $sType,
+            'event' => $aEvent,
+            'browse_params' => $aBrowseParams,
+            'tmpl_code' => &$sTmplCode,
+            'tmpl_vars' => &$aTmplVars
+        ));
+
+        return $this->parseHtmlByContent($sTmplCode, $aTmplVars);
+    }
+
+    protected function _getComments($aComments, $aBrowseParams = array())
+    {
+        $mixedComments = $this->getModule()->getCommentsData($aComments);
+        if($mixedComments === false)
+            return '';
+
+        list($sSystem, $iObjectId, $iCount) = $mixedComments;
+        return $this->getComments($sSystem, $iObjectId, $aBrowseParams);
+    }
+
+    protected function _getShowMore($aParams)
+    {
+        return $this->parseHtmlByName('show_more.html', array(
+            'style_prefix' => $this->_oConfig->getPrefix('style'),
+            'js_object' => $this->_oConfig->getJsObjectView($aParams),
+        ));
+    }
+
+    protected function _getImagePopup($aParams)
+    {
+        $sViewImagePopupId = $this->_oConfig->getHtmlIdView('photo_popup', $aParams);
+        $sViewImagePopupContent = $this->parseHtmlByName('popup_image.html', array(
+            'image_url' => ''
+    	));
+
+    	return BxTemplFunctions::getInstance()->transBox($sViewImagePopupId, $sViewImagePopupContent, true);
+    }
+
+    protected function _getRepostJsClick($iOwnerId, $sType, $sAction, $iObjectId)
+    {
+        $sJsObject = $this->_oConfig->getJsObject('repost');
+        $sFormat = "%s.repostItem(this, %d, '%s', '%s', %d);";
+
+        $iOwnerId = !empty($iOwnerId) ? (int)$iOwnerId : $this->getModule()->getUserId(); //--- in whose timeline the content will be reposted
+        return sprintf($sFormat, $sJsObject, $iOwnerId, $sType, $sAction, (int)$iObjectId);
+    }
+
+    protected function _getRepostWithJsClick($iReposterId, $sType, $sAction, $iObjectId)
+    {
+        $sJsObject = $this->_oConfig->getJsObject('repost');
+        $sFormat = "%s.repostItemWith(this, %d, '%s', '%s', %d);";
+
+        $iReposterId = !empty($iReposterId) ? (int)$iReposterId : $this->getModule()->getUserId();
+        return sprintf($sFormat, $sJsObject, $iReposterId, $sType, $sAction, (int)$iObjectId);
+    }
+
+    protected function _getRepostToJsClick($iReposterId, $sType, $sAction, $iObjectId)
+    {
+        $sJsObject = $this->_oConfig->getJsObject('repost');
+        $sFormat = "%s.repostItemTo(this, %d, '%s', '%s', %d);";
+
+        $iReposterId = !empty($iReposterId) ? (int)$iReposterId : $this->getModule()->getUserId();
+        return sprintf($sFormat, $sJsObject, $iReposterId, $sType, $sAction, (int)$iObjectId);
+    }
+
+    protected function _getJumpToList($aParams)
+    {
+        $iYearSel = (int)$aParams['timeline'];
+        $iYearMin = $this->_oDb->getMaxDuration($aParams);      
+        if(empty($iYearMin))
+            return '';
+
+        $sStylePrefix = $this->_oConfig->getPrefix('style');
+        $sJsObject = $this->_oConfig->getJsObjectView($aParams);
+
+        $aYears = array();
+        $iYearMax = date('Y', time()) - 1;
+        for($i = $iYearMax; $i >= $iYearMin; $i--) {
+            $bCurrent = $i == $iYearSel;
+            $aYears[] = array(
+                'style_prefix' => $sStylePrefix,
+                'bx_if:show_link' => array(
+                    'condition' => !$bCurrent,
+                    'content' => array(
+                        'title' => _t('_bx_timeline_txt_jump_to_n_year', $i),
+                        'onclick' => 'javascript:' . $sJsObject . '.changeTimeline(this, \'' . $i . '-12-31\')',
+                        'content' => $i
+                    )
+                ),
+                'bx_if:show_text' => array(
+                    'condition' => $bCurrent,
+                    'content' => array(
+                        'content' => $i
+                    )
+                ),
+            );
+        }
+
+        return $this->parseHtmlByName('jump_to.html', array(
+            'bx_if:show_list' => array(
+                'condition' => true,
+                'content' => array(
+                    'style_prefix' => $sStylePrefix,
+                    'bx_repeat:links' => $aYears,
+                )
+            ),
+            'bx_if:show_calendar' => array(
+                'condition' => false,
+                'content' => array()
+            )
+        ));
+    }
+
+    protected function _getJumpToCaledar($aParams)
+    {
+        $sStylePrefix = $this->_oConfig->getPrefix('style');
+        $sJsObject = $this->_oConfig->getJsObjectView($aParams);
+                
+        return $this->parseHtmlByName('jump_to.html', array(
+            'bx_if:show_list' => array(
+                'condition' => false,
+                'content' => array()
+            ),
+            'bx_if:show_calendar' => array(
+                'condition' => true,
+                'content' => array(
+                    'style_prefix' => $sStylePrefix,
+                    'onclick' => 'javascript:' . $sJsObject . '.showCalendar(this)',
+                )
+            )
+        ));
+    }
+
+    protected function _getTmplVarsMenuItemActions(&$aEvent, $aBrowseParams = array())
+    {
+        $oMenu = BxDolMenu::getObjectInstance($this->_oConfig->getObject('menu_item_actions_all'));
+        if(!$oMenu) {
+            $oMenu = BxDolMenu::getObjectInstance($this->_oConfig->getObject('menu_item_actions'));
+            if(!$oMenu)
+                return array();
+        }
+
+        $oMenu->setEvent($aEvent, $aBrowseParams);
+        $oMenu->setDynamicMode(isset($aBrowseParams['dynamic_mode']) && $aBrowseParams['dynamic_mode'] === true);
+
+        $sMenu = $oMenu->getCode();
+        if(empty($sMenu))
+            return array();
+
+        return array(
+            'style_prefix' => $this->_oConfig->getPrefix('style'),
+            'js_object' => $this->_oConfig->getJsObjectView($aBrowseParams),
+            'menu_item_actions' => $sMenu
+        );
+    }
+
+    protected function _getTmplVarsManage(&$aEvent, $aBrowseParams = array())
+    {
+        $oMenu = BxDolMenu::getObjectInstance($this->_oConfig->getObject('menu_item_actions_all'));
+        if($oMenu)
+            return array();
+
+        $oMenu = BxDolMenu::getObjectInstance($this->_oConfig->getObject('menu_item_manage'));
+        if(!$oMenu)
+            return array();
+
+        $oMenu->setEvent($aEvent, $aBrowseParams);
+        $oMenu->setDynamicMode(isset($aBrowseParams['dynamic_mode']) && $aBrowseParams['dynamic_mode'] === true);
+        if(!$oMenu->isVisible())
+            return array();
+
+        $sOnclick = "bx_menu_popup('bx_timeline_menu_item_manage', this, {'id':'bx_timeline_menu_item_manage_{content_id}'}, {content_id:{content_id}, name:'{name}', view:'{view}', type:'{type}'});";
+        $sOnclick = bx_replace_markers($sOnclick, array(
+            'content_id' => (int)$aEvent['id'],            
+            'view' => bx_process_output($aBrowseParams['view']),
+            'type' => bx_process_output($aBrowseParams['type']),
+            'name' => bx_process_output($aBrowseParams['name']),
+        ));
+
+        return array(
+            'style_prefix' => $this->_oConfig->getPrefix('style'),
+            'onclick' => $sOnclick
+        );
+    }
+
+    protected function _getTmplVarsMenuItemCounters(&$aEvent, $aBrowseParams = array())
+    {
+        $oMenu = BxDolMenu::getObjectInstance($this->_oConfig->getObject('menu_item_counters'));
+        if(!$oMenu)
+            return array();
+
+        $oMenu->setEvent($aEvent, $aBrowseParams);
+        $oMenu->setDynamicMode(isset($aBrowseParams['dynamic_mode']) && $aBrowseParams['dynamic_mode'] === true);
+        $sMenu = $oMenu->getCode();
+        if(empty($sMenu))
+            return array();
+
+        return array(
+            'style_prefix' => $this->_oConfig->getPrefix('style'),
+            'js_object' => $this->_oConfig->getJsObjectView($aBrowseParams),
+            'menu_item_counters' => $sMenu
+        );
+    }
+
+    protected function _getTmplVarsMenuItemMeta(&$aEvent, $aBrowseParams = array())
+    {
+        $oMenu = BxDolMenu::getObjectInstance($this->_oConfig->getObject('menu_item_meta'));
+        if(!$oMenu)
+            return array();
+
+        $oMenu->setEvent($aEvent);
+
+        $sMenu = $oMenu->getCode();
+        if(empty($sMenu))
+            return array();
+
+        return array(
+            'style_prefix' => $this->_oConfig->getPrefix('style'),
+            'meta' => $sMenu
+        );
+    }
+
+    protected function _getTmplVarsTimelineOwner(&$aEvent)
+    {
+        $sStylePrefix = $this->_oConfig->getPrefix('style');
+        $iUser = bx_get_logged_profile_id();
+        $oModule = $this->getModule();
+
+        $sConnection = $this->_oConfig->getObject('conn_subscriptions');
+        $oConnection = BxDolConnection::getObjectInstance($sConnection);
+        $sConnectionTitle = _t('_sys_menu_item_title_sm_subscribe');
+
+        $sKeyOwnerId = isset($aEvent['owner_id_grouped']) ? 'owner_id_grouped' : 'owner_id';
+        $aOwnerIds = is_array($aEvent[$sKeyOwnerId]) ? $aEvent[$sKeyOwnerId] : array($aEvent[$sKeyOwnerId]);
+
+        $aTmplVarsOwners = array();
+        foreach($aOwnerIds as $iOwnerId) {
+            $iOwnerId = (int)$iOwnerId;
+            $iObjectOwner = (int)$aEvent['object_owner_id'];
+            if($iObjectOwner < 0 && abs($iObjectOwner) == $iUser)
+                $iObjectOwner *= -1;
+
+            if($iOwnerId == 0 || $iOwnerId == $iObjectOwner)
+                continue;
+
+            $oOwner = $oModule->getObjectUser($iOwnerId);
+            $sToType = $oOwner->getModule();
+            $sToName = $oOwner->getDisplayName();
+            $sToUrl = $oOwner->getUrl();
+
+            $aTmplVarsActions = array();
+            if(!empty($iUser) && $iUser != $iOwnerId && $oConnection->checkAllowedConnect($iUser, $iOwnerId) === CHECK_ACTION_RESULT_ALLOWED) {
+                $aTmplVarsActions[] = array(
+                    'href' => "javascript:void(0)",
+                    'onclick' => "bx_conn_action(this, '" . $sConnection . "', 'add', '" . $iOwnerId . "')",
+                    'title' => bx_html_attribute($sConnectionTitle),
+                    'content' => $sConnectionTitle,
+                    'icon' => 'check'
+                );
+            }
+
+            $aTmplVarsOwners[] =  array(
+                'style_prefix' => $sStylePrefix,
+                'owner_type' => _t('_' . $sToType),
+                'owner_url' => $sToUrl,
+                'owner_username' => $sToName,
+                'bx_if:show_timeline_owner_actions' => array(
+                    'condition' => !empty($aTmplVarsActions),
+                    'content' => array(
+                        'style_prefix' => $sStylePrefix,
+                        'bx_repeat:timeline_owner_actions' => $aTmplVarsActions
+                    )
+                )
+            );
+        }
+
+        if(empty($aTmplVarsOwners))
+            return array();
+
+        return array(
+            'style_prefix' => $sStylePrefix,
+            'bx_repeat:owners' => $aTmplVarsOwners
+        );
+    }
+
+    protected function _getTmplVarsContentPost(&$aEvent, $aBrowseParams = array())
+    {
+    	$aContent = &$aEvent['content'];
+        $sStylePrefix = $this->_oConfig->getPrefix('style');
+
+        $bViewItem = isset($aBrowseParams['view']) && $aBrowseParams['view'] == BX_TIMELINE_VIEW_ITEM;
+        $bViewSearch = isset($aBrowseParams['view']) && $aBrowseParams['view'] == BX_TIMELINE_VIEW_SEARCH;
+
+        //--- Process Top Raw ---//
+        $sTopRaw = isset($aContent['top_raw']) ? $aContent['top_raw'] : '';
+
+        //--- Process Raw ---//
+        $sRaw = isset($aContent['raw']) ? $aContent['raw'] : '';
+
+        //--- Process Text ---//
+        $sUrl = isset($aContent['url']) ? bx_html_attribute($aContent['url']) : '';
+        $sTitle = '';
+        if(isset($aContent['title']))
+            $sTitle = bx_process_output($aContent['title']);
+
+        if(!empty($sUrl) && !empty($sTitle))
+            $sTitle = $this->parseLink($sUrl, $sTitle, array(
+            	'class' => $sStylePrefix . '-title',
+                'title' => $sTitle
+            ));
+
+        $sMethodPrepare = '_prepareTextForOutput';
+        if($this->_oConfig->isBriefCards() && !$bViewItem)
+            $sMethodPrepare .= 'BriefCard';
+
+        $sText = isset($aContent['text']) ? $aContent['text'] : '';
+        $sText = $this->$sMethodPrepare($sText, $aEvent['id']);
+
+        //--- Process Links ---//
+        $bAddNofollow = $this->_oDb->getParam('sys_add_nofollow') == 'on';
+
+        $aTmplVarsLinks = [];
+        if(!empty($aContent['links']))
+            foreach($aContent['links'] as $aLink) {
+                $sLink = '';
+
+                $oEmbed = BxDolEmbed::getObjectInstance();
+                if ($oEmbed) {
+                    $sLink = $this->parseHtmlByName('link_embed_provider.html', array(
+                        'style_prefix' => $sStylePrefix,
+                        'embed' => $oEmbed->getLinkHTML($aLink['url'], $aLink['title']),
+                    ));
+                }
+                else {
+                    $aLinkAttrs = array(
+                    	'title' => $aLink['title']
+                    );
+                    if(!$this->_oConfig->isEqualUrls(BX_DOL_URL_ROOT, $aLink['url'])) {
+                        $aLinkAttrs['target'] = '_blank';
+    
+                        if($bAddNofollow)
+                    	    $aLinkAttrs['rel'] = 'nofollow';
+                    }
+
+                    $sLinkAttrs = '';
+                    foreach($aLinkAttrs as $sKey => $sValue)
+                        $sLinkAttrs .= ' ' . $sKey . '="' . bx_html_attribute($sValue) . '"';
+
+                    $sLink = $this->parseHtmlByName('link_embed_common.html', array(
+                        'bx_if:show_thumbnail' => [
+                            'condition' => !empty($aLink['thumbnail']),
+                            'content' => [
+                                'style_prefix' => $sStylePrefix,
+                                'thumbnail' => $aLink['thumbnail'],
+                                'link' => !empty($aLink['url']) ? $aLink['url'] : 'javascript:void(0)',
+                                'attrs' => $sLinkAttrs
+                            ]
+                        ],
+                        'link' => !empty($aLink['url']) ? $aLink['url'] : 'javascript:void(0)',
+                        'attrs' => $sLinkAttrs,
+                        'content' => $aLink['title'],
+                        'bx_if:show_text' => [
+                            'condition' => !empty($aLink['text']),
+                            'content' => [
+                                'style_prefix' => $sStylePrefix,
+                                'text' => $aLink['text']
+                            ]
+                        ]
+                    ));
+                }
+
+                $aTmplVarsLinks[] = [
+                    'style_prefix' => $sStylePrefix,
+                    'link' => $sLink
+                ];
+            }
+
+        /*
+         * View Item page and Snippet in Search Results should use Gallery layout.
+         */
+        $sAttachmentsLayout = $this->_oConfig->getAttachmentsLayout();
+        if($bViewItem || $bViewSearch)
+            $sAttachmentsLayout = BX_TIMELINE_ML_GALLERY;
+
+        $iAttachmentsTotal = 0;
+        $aTmplVarsImages = $aTmplVarsVideos = $aTmplVarsFiles = $aTmplVarsAttachments = $aTmplVarsAttachmentsFiles = array();
+
+        //--- Process Photos ---//
+        $bImages = !empty($aContent['images']) && is_array($aContent['images']);
+        if($bImages) {
+            $aImages = $this->_getTmplVarsImages($aContent['images'], true, $aEvent, $aBrowseParams);
+            if(!empty($aImages))
+                $aTmplVarsImages = array(
+                    'style_prefix' => $sStylePrefix,
+                    'display' => $aImages['display'],
+                    'bx_repeat:items' => $aImages['items']
+                );
+        }
+        $bImagesAttach = !empty($aContent['images_attach']) && is_array($aContent['images_attach']);
+        if($bImagesAttach) {
+            $aImagesAttach = $this->_getTmplVarsImages($aContent['images_attach'], ['layout' => $sAttachmentsLayout, 'first' => empty($aTmplVarsAttachments)], $aEvent, $aBrowseParams);
+            if(!empty($aImagesAttach)) {
+                $iAttachmentsTotal += $aImagesAttach['total'];
+                $aTmplVarsAttachments = array_merge($aTmplVarsAttachments, $aImagesAttach['items']);
+            }
+        }
+
+        //--- Add Meta Image when Item is viewed on a separate page ---//
+        if($bViewItem) {
+            $sMetaImageSrc = '';
+            if($bImages && !empty($aContent['images'][0]['src']))
+                $sMetaImageSrc = $aContent['images'][0]['src'];
+            else if($bImagesAttach && !empty($aContent['images_attach'][0]['src']))
+                $sMetaImageSrc = $aContent['images_attach'][0]['src'];
+
+            if(!empty($sMetaImageSrc))
+                BxDolTemplate::getInstance()->addPageMetaImage($sMetaImageSrc);
+        }
+
+    	//--- Process Videos ---//
+        $bVideos = !empty($aContent['videos']) && is_array($aContent['videos']);
+        if($bVideos) {
+            $aVideos = $this->_getTmplVarsVideos($aContent['videos'], true, $aEvent, $aBrowseParams);
+            if(!empty($aVideos))
+                $aTmplVarsVideos = [
+                    'style_prefix' => $sStylePrefix,
+                    'display' => $aVideos['display'],
+                    'bx_repeat:items' => $aVideos['items']
+                ];
+        }
+
+        $bVideosAttach = !empty($aContent['videos_attach']) && is_array($aContent['videos_attach']);
+        if($bVideosAttach) {
+            $aVideosAttach = $this->_getTmplVarsVideos($aContent['videos_attach'], ['layout' => $sAttachmentsLayout, 'first' => empty($aTmplVarsAttachments)], $aEvent, $aBrowseParams);
+            if(!empty($aVideosAttach)) {
+                $iAttachmentsTotal += $aVideosAttach['total'];
+                $aTmplVarsAttachments = array_merge($aTmplVarsAttachments, $aVideosAttach['items']);
+            }
+        }
+ 
+        //--- Process Files ---//
+        $bFiles = !empty($aContent['files']) && is_array($aContent['files']);
+        if($bFiles) {
+            $aFiles = $this->_getTmplVarsFiles($aContent['files'], $aEvent, $aBrowseParams);
+            if(!empty($aFiles))
+                $aTmplVarsFiles = [
+                    'style_prefix' => $sStylePrefix,
+                    'display' => $aFiles['display'],
+                    'bx_repeat:items' => $aFiles['items']
+                ];
+        }
+
+        $bFilesAttach = !empty($aContent['files_attach']) && is_array($aContent['files_attach']);
+        if($bFilesAttach) {
+            $aFilesAttach = $this->_getTmplVarsFiles($aContent['files_attach'], $aEvent, $aBrowseParams);
+            if(!empty($aFilesAttach)) {
+                $aTmplVarsAttachmentsFiles = [
+                    'style_prefix' => $sStylePrefix,
+                    'display' => BX_TIMELINE_ML_GALLERY,
+                    'count' => count($aFilesAttach['items']),
+                    'bx_repeat:items' => $aFilesAttach['items']
+                ];
+            }
+        }
+
+        /*
+         *  Process collected attachments in case of Showcase layout.
+         */
+        $iAttachmentsShow = 4;
+        $iAttachmentsCount = count($aTmplVarsAttachments);
+        if($sAttachmentsLayout == BX_TIMELINE_ML_SHOWCASE && $iAttachmentsCount > 0) {
+            $aTmplVarsAttachments[0]['class'] .= ' ' . $sStylePrefix . '-ia-first';
+
+            if($iAttachmentsCount > $iAttachmentsShow)
+                $aTmplVarsAttachments = array_slice($aTmplVarsAttachments, 0, $iAttachmentsShow);
+
+            if($iAttachmentsTotal > $iAttachmentsShow)
+                $aTmplVarsAttachments[$iAttachmentsShow - 1]['item'] .= $this->parseHtmlByName('attach_more.html', [
+                    'style_prefix' => $sStylePrefix,
+                    'link' => $this->_oConfig->getItemViewUrl($aEvent),
+                    'more' => $iAttachmentsTotal - $iAttachmentsShow
+                ]);
+        }
+
+        return [
+            'style_prefix' => $sStylePrefix,
+            'bx_if:show_title' => [
+                'condition' => !empty($sTitle),
+                'content' => [
+                    'style_prefix' => $sStylePrefix,
+                    'title' => $sTitle,
+                ]
+            ],
+            'bx_if:show_content' => [
+                'condition' => !empty($sText),
+                'content' => [
+                    'style_prefix' => $sStylePrefix,
+                    'item_content' => $sText
+                ]
+            ],
+            'bx_if:show_top_raw' => [
+                'condition' => !empty($sTopRaw),
+                'content' => [
+                    'style_prefix' => $sStylePrefix,
+                    'item_content_top_raw' => $sTopRaw
+                ]
+            ],
+            'bx_if:show_raw' => [
+                'condition' => !empty($sRaw),
+                'content' => [
+                    'style_prefix' => $sStylePrefix,
+                    'item_content_raw' => $sRaw
+                ]
+            ],
+            'bx_if:show_links' => [
+                'condition' => !empty($aTmplVarsLinks),
+                'content' => [
+                    'style_prefix' => $sStylePrefix,
+                    'bx_repeat:links' => $aTmplVarsLinks
+                ]
+            ],
+            'bx_if:show_images' => [
+                'condition' => !empty($aTmplVarsImages),
+                'content' => $aTmplVarsImages
+            ],
+            'bx_if:show_videos' => [
+                'condition' => !empty($aTmplVarsVideos),
+                'content' => $aTmplVarsVideos
+            ],
+            'bx_if:show_files' => [
+                'condition' => !empty($aTmplVarsFiles),
+                'content' => $aTmplVarsFiles
+            ],
+            'bx_if:show_attachments' => [
+                'condition' => !empty($aTmplVarsAttachments),
+                'content' => [
+                    'style_prefix' => $sStylePrefix,
+                    'display' => $sAttachmentsLayout,
+                    'count' => count($aTmplVarsAttachments),
+                    'bx_repeat:items' => $aTmplVarsAttachments
+                ]
+            ],
+            'bx_if:show_attachments_files' => [
+                'condition' => !empty($aTmplVarsAttachmentsFiles),
+                'content' => $aTmplVarsAttachmentsFiles
+            ]
+        ];
+    }
+
+    protected function _getTmplVarsContentRepost(&$aEvent, $aBrowseParams = array())
+    {
+    	$aContent = &$aEvent['content'];
+        $sStylePrefix = $this->_oConfig->getPrefix('style');
+
+        $sOwnerLink = $this->parseLink($aContent['owner_url'], $aContent['owner_name']);
+
+        $sSample = _t($aContent['sample']);
+        $sSampleLink = empty($aContent['url']) ? $sSample : $this->parseLink($aContent['url'], $sSample);
+
+        $aTmplVarsData = [];
+        if(!empty($aContent['rdata']) && is_array($aContent['rdata'])) {
+            $aData = $aContent['rdata'];
+
+            $aTmplVarsData['style_prefix'] = $sStylePrefix;
+
+            if(isset($aData['text']))
+                $aTmplVarsData['text'] = $this->_prepareTextForOutput($aData['text'], $aEvent['id']);
+        }
+
+        $sContent = $this->_getContent($aContent['parse_type'], $aEvent, $aBrowseParams);
+
+        return [
+            'style_prefix' => $sStylePrefix,
+            'item_owner_action' => _t('_bx_timeline_txt_reposted', $sOwnerLink, $sSampleLink),
+            'bx_if:show_data' => [
+                'condition' => !empty($aTmplVarsData),
+                'content' => $aTmplVarsData
+            ],
+            'bx_if:show_content' => [
+                'condition' => !empty($sContent),
+                'content' => [
+                    'style_prefix' => $sStylePrefix,
+                    'content' => $sContent,
+                ]
+            ]
+        ];
+    }
+
+    protected function _getTmplVarsNote(&$aEvent)
+    {
+        $sStylePrefix = $this->_oConfig->getPrefix('style');
+
+        $iUser = bx_get_logged_profile_id();
+        $iOwner = $this->_oConfig->isSystem($aEvent['type'], $aEvent['action']) ? $aEvent['owner_id'] : $aEvent['object_id'];
+
+        $aTmplVars = array();
+        if(!empty($iOwner) && !is_array($iOwner) && !empty($aEvent['promoted'])) {
+            $sConnection = $this->_oConfig->getObject('conn_subscriptions');
+            $oConnection = BxDolConnection::getObjectInstance($sConnection);
+            if(!$oConnection->isConnected($iUser, $iOwner))
+                $aTmplVars[] = [
+                    'style_prefix' => $sStylePrefix,
+                    'class' => '',
+                    'bx_if:show_note_color' => [
+                        'condition' => false,
+                        'content' => []
+                    ],
+                    'item_note' => _t('_bx_timeline_txt_promoted')
+                ];
+        }
+
+        //--- Awaiting status related notes.
+        if($aEvent['status'] == BX_TIMELINE_STATUS_AWAITING) {
+            $sNote = '';
+            if((int)$aEvent['published'] > (int)$aEvent['date'])
+                $sNote = _t('_bx_timeline_txt_note_scheduled_awaiting', bx_time_js($aEvent['published'], BX_FORMAT_DATE, true));
+            else
+                $sNote = _t('_bx_timeline_txt_note_processing_awaiting');
+
+            $aTmplVars[] = [
+                'style_prefix' => $sStylePrefix,
+                'bx_if:show_note_color' => [
+                    'condition' => true,
+                    'content' => [
+                        'item_note_color' => 'red3'
+                    ]
+                ],
+                'item_note' => $sNote
+            ];
+        }
+
+        //--- Failed status related notes.
+        if($aEvent['status'] == BX_TIMELINE_STATUS_FAILED)
+            $aTmplVars[] = [
+                'style_prefix' => $sStylePrefix,
+                'bx_if:show_note_color' => [
+                    'condition' => true,
+                    'content' => [
+                        'item_note_color' => 'red2'
+                    ]
+                ],
+                'item_note' => _t('_bx_timeline_txt_note_processing_failed')
+            ];
+
+        //--- Pending status related notes.
+        if($aEvent['status_admin'] == BX_TIMELINE_STATUS_PENDING)
+            $aTmplVars[] = [
+                'style_prefix' => $sStylePrefix,
+                'bx_if:show_note_color' => [
+                    'condition' => true,
+                    'content' => [
+                        'item_note_color' => 'red3'
+                    ]
+                ],
+                'item_note' => _t('_bx_timeline_txt_note_approve_pending')
+            ];
+
+        return empty($aTmplVars) ? [] : [
+            'style_prefix' => $sStylePrefix,
+            'bx_repeat:notes' => $aTmplVars
+        ];
+    }
+
+    protected function _getTmplVarsOwnerActions(&$aEvent, $aBrowseParams = array())
+    {
+        $sStylePrefix = $this->_oConfig->getPrefix('style');
+
+        $iUser = bx_get_logged_profile_id();
+        $iOwner = $this->_oConfig->isSystem($aEvent['type'], $aEvent['action']) ? $aEvent['object_owner_id'] : $aEvent['object_id'];
+
+        $aTmplVarsActions = array();
+        if(!empty($iUser) && !empty($iOwner) && $iUser != $iOwner) {
+            $oOwner = BxDolProfile::getInstance($iOwner);
+            if($oOwner !== false && bx_srv($oOwner->getModule(), 'check_allowed_with_content', array('subscribe_add', $oOwner->getContentId())) === CHECK_ACTION_RESULT_ALLOWED) {
+                $sJsObject = $this->_oConfig->getJsObjectView($aBrowseParams);
+                $sConnection = $this->_oConfig->getObject('conn_subscriptions');
+
+                $sContent = _t('_sys_menu_item_title_sm_subscribe');
+                $aTmplVarsActions[] = array(
+                    'style_prefix' => $sStylePrefix,
+                    'href' => "javascript:void(0)",
+                    'onclick' => "bx_conn_action(this, '" . $sConnection . "', 'add', '" . $iOwner . "', false, function(oData, eElement) {" . $sJsObject . ".onConnect(eElement, oData);})",
+                    'title' => bx_html_attribute($sContent),
+                    'content' => $sContent,
+                    'icon' => 'check'
+                );
+            }
+        }
+
+        return array(
+            'style_prefix' => $sStylePrefix,
+            'bx_repeat:owner_actions' => $aTmplVarsActions
+        );
+    }
+
+    protected function _getTmplVarsImages($aImages, $mixedLayout, &$aEvent, &$aBrowseParams)
+    {
+        if(empty($aImages) || !is_array($aImages))
+            return array();
+
+        $iTotal = 0; //--- Total count of images related to the event.
+        if(isset($aImages['total']) && isset($aImages['items'])) {
+            $iTotal = (int)$aImages['total'];
+            $aImages = $aImages['items'];
+        }
+        else
+            $iTotal = count($aImages);
+
+        $sStylePrefix = $this->_oConfig->getPrefix('style');
+        $sJsObject = $this->_oConfig->getJsObjectView($aBrowseParams);
+
+        $bViewItem = isset($aBrowseParams['view']) && $aBrowseParams['view'] == BX_TIMELINE_VIEW_ITEM;
+
+        $sDisplay = '';
+        $aTmplVarsImages = array();
+
+        $sImageSrcKey = $sImageSrcKeyBig = '';
+        $sImageSrcKeyDefault = 'src';
+        if(count($aImages) == 1) {
+            $sDisplay = BX_TIMELINE_ML_SINGLE;
+            $sImageSrcKey = $bViewItem ? 'src_orig' : 'src_medium';
+        }
+        else if(is_array($mixedLayout) && !empty($mixedLayout['layout'])) {
+            $sDisplay = $mixedLayout['layout'];
+            $sImageSrcKey = 'src';
+            $sImageSrcKeyBig = 'src_medium';
+        }
+        else {
+            $sDisplay = BX_TIMELINE_ML_GALLERY;
+            $sImageSrcKey = 'src';
+            $sImageSrcKeyBig = 'src_medium';
+        }
+
+        $bAttachFirst = false;
+        if($sDisplay == BX_TIMELINE_ML_SHOWCASE)
+            $bAttachFirst = isset($mixedLayout['first']) && $mixedLayout['first'] === true;
+
+        $aImageFirst = reset($aImages);
+        $iImageFirst = isset($aImageFirst['id']) ? (int)$aImageFirst['id'] : 0;
+
+        foreach($aImages as $aImage) {
+            $sImageSrcKeyCur = $sImageSrcKey;
+            if(($bAttachFirst && isset($aImage['id']) && (int)$aImage['id'] == $iImageFirst) || $iTotal == 2)
+                $sImageSrcKeyCur = $sImageSrcKeyBig;
+
+            $sImageSrc = !empty($aImage[$sImageSrcKeyCur]) ? $aImage[$sImageSrcKeyCur] : $aImage[$sImageSrcKeyDefault];
+            if(empty($sImageSrc))
+                continue;
+
+            $sImage = $this->parseImage($sImageSrc, array(
+                'class' => $sStylePrefix . '-item-image'
+            ));
+
+            $aAttrs = array();
+            if(isset($aImage['onclick']))
+                $aAttrs['onclick'] = $aImage['onclick'];
+            else if(!empty($aImage['src_orig']))
+                $aAttrs['onclick'] = 'return ' . $sJsObject . '.showItem(this, \'' . $aEvent['id'] . '\', \'photo\', ' . json_encode(array('src' => base64_encode($aImage['src_orig']))) . ')'; 
+
+            $sImage = $this->parseLinkByName('image_link.html', isset($aImage['url']) ? $aImage['url'] : 'javascript:void(0)', $sImage, $aAttrs);
+
+            $aTmplVarsImages[] = array(
+                'style_prefix' => $sStylePrefix,
+                'class' => '',
+                'item' => $sImage
+            );
+        }
+        
+        return array(
+            'display' => $sDisplay,
+            'total' => $iTotal,
+            'items' => $aTmplVarsImages
+        );
+    }
+
+    protected function _getTmplVarsVideos($aVideos, $mixedLayout, &$aEvent, &$aBrowseParams)
+    {
+        if(empty($aVideos) || !is_array($aVideos))
+            return array();
+
+        $iTotal = 0; //--- Total count of videos related to the event.
+        if(isset($aVideos['total']) && isset($aVideos['items'])) {
+            $iTotal = (int)$aVideos['total'];
+            $aVideos = $aVideos['items'];
+        }
+        else
+            $iTotal = count($aVideos);
+
+        $sStylePrefix = $this->_oConfig->getPrefix('style');
+        $sJsObject = $this->_oConfig->getJsObjectView($aBrowseParams);
+        $aTmplVarsVideos = array();
+
+        /*
+         * For now Main Section may have only one video which can use 'autoplay' feature.
+         */
+        $bMain = $mixedLayout === true;
+        if($bMain) {
+            $sDisplay = BX_TIMELINE_ML_SINGLE;
+            if(count($aVideos) > 1)
+                $aVideos = array_slice($aVideos, 0, 1);
+        }
+        else
+            $sDisplay = is_array($mixedLayout) && !empty($mixedLayout['layout']) ? $mixedLayout['layout'] : BX_TIMELINE_AML_DEFAULT;
+
+        /*
+         * Main Section: Autoplay feature is only available here.
+         */
+        $sVap = $sVapId = $sVapSrc = $sVapTmpl = '';
+        if($bMain) {
+            $sVap = $this->_oConfig->getVideosAutoplay();
+            if($sVap != BX_TIMELINE_VAP_OFF) {
+                $sVapId = $this->_oConfig->getHtmlIds('view', 'video_iframe') . $aEvent['id'] . '-';
+                $sVapSrc = BX_DOL_URL_ROOT . $this->_oConfig->getBaseUri() . 'video/' . $aEvent['id'] . '/';
+                $sVapTmpl = $this->getHtml('video_iframe.html'); 
+            }
+        }
+
+        /*
+         * Attachments Section.
+         */
+        $sAttachTmpl = '';
+        $bAttachFirst = false;
+        if($sDisplay == BX_TIMELINE_ML_SHOWCASE) {
+            $sAttachTmpl = $this->getHtml('attach_video_preview.html');
+            $bAttachFirst = isset($mixedLayout['first']) && $mixedLayout['first'] === true;
+        }
+
+        $iVideoFirst = reset($aVideos)['id'];
+        foreach($aVideos as $aVideo) {
+            $iVideo = (int)$aVideo['id'];
+
+            if($bMain && $sVap != BX_TIMELINE_VAP_OFF)
+                $aTmplVarsVideos[] = array(
+                    'style_prefix' => $sStylePrefix,
+                    'class' => '',
+                    'item' => $this->parseHtmlByContent($sVapTmpl, array(
+                        'style_prefix' => $sStylePrefix,
+                        'html_id' => $sVapId . $iVideo,
+                        'src' => $sVapSrc . $iVideo . '/'
+                    )) 
+                );
+            else {
+                if($bMain || $sDisplay == BX_TIMELINE_ML_GALLERY || ($bAttachFirst && $iVideo == $iVideoFirst)) {
+                    $sItem = '';
+                    if(isset($aVideo['src'], $aVideo['src_orig'])) {
+                        $sItem = $this->parseImage($aVideo['src'], array(
+                            'class' => $sStylePrefix . '-item-image'
+                        ));
+
+                        $aAttrs = array();
+                        if(!empty($aVideo['src_orig']))
+                            $aAttrs['onclick'] = 'return ' . $sJsObject . '.showItem(this, \'' . $aEvent['id'] . '\', \'video\', ' . json_encode(array('src' => base64_encode($aVideo['src_orig']))) . ')'; 
+
+                        $sItem = $this->parseLinkByName('image_link.html', isset($aVideo['url']) ? $aVideo['url'] : 'javascript:void(0)', $sItem, $aAttrs);
+                    }
+                    else 
+                        $sItem = BxTemplFunctions::getInstance()->videoPlayer($aVideo['src_poster'], $aVideo['src_mp4'], $aVideo['src_mp4_hd'], array(
+                            'preload' => $this->_oConfig->getVideosPreload(),
+                        ), '', $aBrowseParams['dynamic_mode']);
+
+                    $aTmplVarsVideos[] = array(
+                        'style_prefix' => $sStylePrefix,
+                        'class' => '',
+                        'item' => $sItem
+                    );
+                }
+                else {
+                    $bUrl = !empty($aVideo['url']);
+                    $sUrl = $bUrl ? $aVideo['url'] : '';
+
+                    $sSrc = $aVideo[isset($aVideo['src'], $aVideo['src_orig']) ? 'src' : 'src_poster'];
+
+                    $bDuration = !empty($aVideo['duration']);
+                    $sDuration = _t_format_duration($bDuration ? $aVideo['duration'] : 0);
+
+                    $aTmplVarsVideos[] = array(
+                        'style_prefix' => $sStylePrefix,
+                        'class' => '',
+                        'item' => $this->parseHtmlByContent($sAttachTmpl, array(
+                            'style_prefix' => $sStylePrefix,
+                            'bx_if:show_link' => array(
+                                'condition' => $bUrl,
+                                'content' => array(
+                                    'style_prefix' => $sStylePrefix,
+                                    'url' => $sUrl,
+                                    'src' => $sSrc,
+                                )
+                            ),
+                            'bx_if:show_non_link' => array(
+                                'condition' => !$bUrl,
+                                'content' => array(
+                                    'style_prefix' => $sStylePrefix,
+                                    'src' => $sSrc,
+                                )
+                            ),
+                            'bx_if:show_duration' => array(
+                                'condition' => $bDuration,
+                                'content' => array(
+                                    'style_prefix' => $sStylePrefix,
+                                    'duration' => $sDuration,
+                                )
+                            )
+                        ))
+                    );
+                }
+            }
+        }
+ 
+        return array( 
+            'display' => $sDisplay,
+            'total' => $iTotal,
+            'items' => $aTmplVarsVideos
+        );
+    }
+
+    protected function _getTmplVarsFiles($aFiles, &$aEvent, &$aBrowseParams)
+    {
+        if(empty($aFiles) || !is_array($aFiles))
+            return array();
+
+        $iTotal = 0; //--- Total count of files related to the event.
+        if(isset($aFiles['total']) && isset($aFiles['items'])) {
+            $iTotal = (int)$aFiles['total'];
+            $aFiles = $aFiles['items'];
+        }
+        else
+            $iTotal = count($aFiles);
+
+        $sStylePrefix = $this->_oConfig->getPrefix('style');
+        $sJsObject = $this->_oConfig->getJsObjectView($aBrowseParams);
+
+        $bViewItem = isset($aBrowseParams['view']) && $aBrowseParams['view'] == BX_TIMELINE_VIEW_ITEM;
+
+        $sDisplay = '';
+        $aTmplVarsFiles = array();
+
+        $sFileSrcKey = '';
+        $sFileSrcKeyDefault = 'src';
+        if(count($aFiles) == 1) {
+            $sDisplay = 'single';
+            $sFileSrcKey = $bViewItem ? 'src_orig' : 'src_medium';
+        }
+        else {
+            $sDisplay = 'gallery';
+            $sFileSrcKey = 'src';
+        }
+
+        foreach($aFiles as $aFile) {
+            $sFileSrc = !empty($aFile[$sFileSrcKey]) ? $aFile[$sFileSrcKey] : $aFile[$sFileSrcKeyDefault];
+            if(empty($sFileSrc))
+                continue;
+
+            $aAttrs = ['target' => '_blank'];
+            if(isset($aFile['onclick']))
+                $aAttrs['onclick'] = $aFile['onclick'];
+            else if(!$bViewItem && !empty($aFile['src_orig']))
+                $aAttrs['onclick'] = 'return ' . $sJsObject . '.showItem(this, \'' . $aEvent['id'] . '\', \'file\', ' . json_encode(array('src' => base64_encode($aFile['src_orig']))) . ')'; 
+            if(isset($aFile['title']))
+                $aAttrs['title'] = $aFile['title'];
+
+            $sAttrs = '';
+            foreach($aAttrs as $sKey => $sValue)
+                $sAttrs .= ' ' . $sKey . '="' . bx_html_attribute($sValue) . '"';
+
+            $aTmplVarsFiles[] = [
+                'style_prefix' => $sStylePrefix,
+                'class' => '',
+                'item' => $this->parseHtmlByName('file_link.html', [
+                    'href' => isset($aFile['url']) ? $aFile['url'] : 'javascript:void(0)',
+                    'attrs' => $sAttrs,
+                    'icon_src' => $sFileSrc,
+                    'icon_class' => $sStylePrefix . '-item-file'
+                ])
+            ];
+        }
+
+        return array(
+            'display' => $sDisplay,
+            'total' => $iTotal,
+            'items' => $aTmplVarsFiles
+        );
+    }
+
+    protected function _getSystemData(&$aEvent, $aBrowseParams = array())
+    {
+        $mixedResult = $this->_oConfig->getSystemData($aEvent, $aBrowseParams);
+        if($mixedResult === false) {
+            $sMethod = 'display' . bx_gen_method_name($aEvent['type'] . '_' . $aEvent['action']);
+            if(method_exists($this, $sMethod))
+                $mixedResult = $this->$sMethod($aEvent);
+        }
+
+        if($mixedResult === false)
+            return '';
+
+        $this->_preparetDataActions($aEvent, $mixedResult);
+        return $mixedResult;
+    }
+
+    protected function _getCommonData(&$aEvent, $aBrowseParams = array())
+    {
+        $CNF = $this->_oConfig->CNF;
+
+        $oModule = $this->getModule();
+        $sJsObject = $this->_oConfig->getJsObjectView($aBrowseParams);
+        $sPrefix = $this->_oConfig->getPrefix('common_post');
+        $sType = str_replace($sPrefix, '', $aEvent['type']);
+
+        $oObjectOwner = BxDolProfile::getInstanceMagic($aEvent['object_id']);
+
+        $iOwnerId = $aEvent['owner_id'];
+        if(is_array($aEvent['owner_id']))
+            $iOwnerId = is_numeric($aEvent['object_privacy_view']) && (int)$aEvent['object_privacy_view'] < 0 ? abs((int)$aEvent['object_privacy_view']) : (int)array_shift($aEvent['owner_id']);
+
+        $aResult = array(
+            'owner_id' => $iOwnerId,
+            'object_owner_id' => $aEvent['object_id'],
+            'icon' => $CNF['ICON'],
+            'sample' => '_bx_timeline_txt_sample_with_article',
+            'sample_wo_article' => '_bx_timeline_txt_sample',
+            'sample_action' => '_bx_timeline_txt_added_sample',
+            'content_type' => $sType,
+            'content' => array(
+                'sample' => '_bx_timeline_txt_sample_with_article',
+                'sample_wo_article' => '_bx_timeline_txt_sample',
+                'sample_action' => '_bx_timeline_txt_added_sample',
+                'url' => $this->_oConfig->getItemViewUrl($aEvent)
+            ), //a string to display or array to parse default template before displaying.
+            'views' => '',
+            'votes' => '',
+            'reactions' => '',
+            'scores' => '',
+            'reports' => '',
+            'comments' => '',
+            'title' => $aEvent['title'], //may be empty.
+            'description' => bx_replace_markers($aEvent['description'], array(
+                'profile_name' => $oObjectOwner->getDisplayName()
+            )) //may be empty.
+        );
+
+        switch($sType) {
+            case BX_TIMELINE_PARSE_TYPE_POST:
+                if(!empty($aEvent['content']))
+                    $aResult['content'] = array_merge($aResult['content'], unserialize($aEvent['content']));
+
+                $aResult['content']['links'] = $oModule->getEventLinks($aEvent['id']);
+                $aResult['content']['images_attach'] = $oModule->getEventImages($aEvent['id']);
+                $aResult['content']['videos_attach'] = $oModule->getEventVideos($aEvent['id']);
+                $aResult['content']['files_attach'] = $oModule->getEventFiles($aEvent['id']);
+                break;
+
+            case BX_TIMELINE_PARSE_TYPE_REPOST:
+                if(empty($aEvent['content']))
+                    return array();
+
+                $aContent = unserialize($aEvent['content']);
+
+                if(!$this->_oConfig->isSystem($aContent['type'] , $aContent['action'])) {
+                    $aEventReposted = $this->_oDb->getEvents(array('browse' => 'id', 'value' => $aContent['object_id']));
+                    $aReposted = $this->_getCommonData($aEventReposted, $aBrowseParams);
+                } 
+                else {
+                    $aEventReposted = $this->_oDb->getEvents(array_merge(array('browse' => 'descriptor'), $aContent));
+                    $aReposted = $this->_getSystemData($aEventReposted, $aBrowseParams);
+                }
+
+                if(empty($aReposted) || !is_array($aReposted))
+                    return array();
+
+                $aEventReposted['content'] = $aReposted['content'];
+
+                $aResult['content'] = array_merge($aContent, $aReposted['content']);
+                $aResult['content']['parse_type'] = !empty($aReposted['content_type']) ? $aReposted['content_type'] : BX_TIMELINE_PARSE_TYPE_DEFAULT;
+
+                $sKey = 'allowed_view';
+                $aResult['content'][$sKey] = $this->_preparePrivacy($sKey, $aEventReposted, $aReposted);
+
+                $oObjectOwner = $oModule->getObjectUser($aReposted['object_owner_id']);
+                $aResult['content']['owner_id'] = $aReposted['object_owner_id'];
+                $aResult['content']['owner_name'] = $oObjectOwner->getDisplayName();
+                $aResult['content']['owner_url'] = $oObjectOwner->getUrl();
+
+                if(!empty($aReposted['sample']))
+                    $aResult['content']['sample'] = $aReposted['sample'];
+                if(!empty($aReposted['sample_wo_article']))
+                    $aResult['content']['sample'] = $aReposted['sample_wo_article'];
+
+                $sUserName = $oModule->getObjectUser($aEvent['object_id'])->getDisplayName();
+                $aResult['title'] = _t('_bx_timeline_txt_user_repost', $sUserName, _t($aResult['content']['sample']));
+                $aResult['description'] = _t('_bx_timeline_txt_user_reposted_user_sample', $sUserName, $aResult['content']['owner_name'], _t($aResult['content']['sample']));
+                $aResult['allowed_view'] = array(
+                    'module' => $this->_oConfig->getName(),
+                    'method' => 'get_timeline_repost_allowed_view',
+                );
+
+                if(!$this->_oConfig->isRepostOwnActions()) {
+                    $aResult['views'] = $aReposted['views'];
+                    $aResult['votes'] = $aReposted['votes'];
+                    $aResult['reactions'] = $aReposted['reactions'];
+                    $aResult['scores'] = $aReposted['scores'];
+                    $aResult['reports'] = $aReposted['reports'];
+                    $aResult['comments'] = $aReposted['comments'];
+                }
+                break;
+        }
+
+        $this->_preparetDataActions($aEvent, $aResult);
+        return $aResult;
+    }
+
+    protected function _getFirst($aEvents, $aParams = array())
+    {
+        $CNF = $this->_oConfig->CNF;
+
+        foreach($aEvents as $aEvent)
+            if((int)$aEvent[$CNF['FIELD_STICKED']] == 0)
+                return (int)$aEvent[$CNF['FIELD_ID']];
+
+        $aParams['start'] += $aParams['per_page'];
+        $aEvents = $this->_oDb->getEvents($aParams);
+        if(!empty($aEvents) && is_array($aEvents))
+            return $this->_getFirst($aEvents, $aParams);
+
+        return 0;
+    }
+
+    protected function _preparetDataActions(&$aEvent, &$aResult)
+    {
+        if(empty($aEvent) || !is_array($aEvent) || empty($aEvent['id']))
+            return;
+
+        $oModule = $this->getModule();
+
+        $sSystem = $this->_oConfig->getObject('view');
+        if(empty($aResult['views'])) {
+            $aResult['views'] = array();
+            if($oModule->getViewObject($sSystem, $aEvent['id']) !== false)
+                $aResult['views'] = array(
+                    'system' => $sSystem,
+                    'object_id' => $aEvent['id'],
+                    'count' => $aEvent['views']
+                );
+        }
+
+        $sSystem = $this->_oConfig->getObject('vote');
+        if(empty($aResult['votes'])) {
+            $aResult['votes'] = array();
+            if($oModule->getVoteObject($sSystem, $aEvent['id']) !== false)
+                $aResult['votes'] = array(
+                    'system' => $sSystem,
+                    'object_id' => $aEvent['id'],
+                    'count' => $aEvent['votes']
+                );
+        }
+        
+        $sSystem = $this->_oConfig->getObject('reaction');
+        if(empty($aResult['reactions'])) {
+            $aResult['reactions'] = array();
+            if($oModule->getReactionObject($sSystem, $aEvent['id']) !== false)
+                $aResult['reactions'] = array(
+                    'system' => $sSystem,
+                    'object_id' => $aEvent['id'],
+                    'count' => $aEvent['rvotes']
+                );
+        }
+
+        $sSystem = $this->_oConfig->getObject('score');
+        if(empty($aResult['scores'])) {
+            $aResult['scores'] = array();
+            if($oModule->getScoreObject($sSystem, $aEvent['id']) !== false)
+                $aResult['scores'] = array(
+                    'system' => $sSystem,
+                    'object_id' => $aEvent['id'],
+                    'score' => $aEvent['score']
+                );
+        }
+
+        $sSystem = $this->_oConfig->getObject('report');
+        if(empty($aResult['reports'])) {
+            $aResult['reports'] = array();
+            if($oModule->getReportObject($sSystem, $aEvent['id']) !== false)
+                $aResult['reports'] = array(
+                    'system' => $sSystem,
+                    'object_id' => $aEvent['id'],
+                    'count' => $aEvent['reports']
+                );
+        }
+
+        $sSystem = $this->_oConfig->getObject('comment');
+        if(empty($aResult['comments'])) {
+            $aResult['comments'] = array();
+            if($oModule->getCmtsObject($sSystem, $aEvent['id']) !== false)
+                $aResult['comments'] = array(
+                    'system' => $sSystem,
+                    'object_id' => $aEvent['id'],
+                    'count' => $aEvent['comments']
+                );
+        }
+    }
+
+    protected function _prepareTextForOutputBriefCard($s, $iEventId = 0)
+    {
+        $s = strip_tags($s, $this->_oConfig->getBriefCardsTags(true));
+        
+        return $this->_prepareTextForOutput($s, $iEventId = 0);
+    }
+
+    protected function _prepareTextForOutput($s, $iEventId = 0)
+    {
+    	$s = bx_process_output($s, BX_DATA_HTML);
+
+        $oMetatags = BxDolMetatags::getObjectInstance($this->_oConfig->getObject('metatags'));
+        $s = $oMetatags->metaParse($iEventId, $s);
+
+        return $s;
+    }
+    
+    protected function _preparePrivacy($sKey, $aEvent, $aEventData)
+    {
+        $iResult = CHECK_ACTION_RESULT_ALLOWED;
+        if(isset($aEventData[$sKey], $aEventData[$sKey]['module'], $aEventData[$sKey]['method']))
+            $iResult = BxDolService::call($aEventData[$sKey]['module'], $aEventData[$sKey]['method'], array($aEvent));
+        else if(($aHandler = $this->_oConfig->getHandler($aEvent)) !== false && BxDolRequest::serviceExists($aHandler['module_name'], 'get_timeline_post_allowed_view'))
+            $iResult = BxDolService::call($aHandler['module_name'], 'get_timeline_post_allowed_view', array($aEvent));
+
+        return $iResult;
+    }
+
+    protected function _getCounterIcon($aParams = array())
+    {
+        return $this->parseHtmlByName('repost_counter_icon.html', []);
+    }
+
+    protected function _getCounterLabel($iCount, $aParams = array())
+    {
+        return _t(isset($aParams['caption']) ? $aParams['caption'] : '_bx_timeline_txt_repost_counter', $iCount);
+    }
+}
+
+/** @} */

+ 143 - 0
modules/boonex/timeline/updates/13.0.4_13.0.5/source/install/config.php

@@ -0,0 +1,143 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Timeline Timeline
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_timeline',
+    'title' => 'Timeline',
+    'note' => 'Timeline module.',
+    'version' => '13.0.5',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '13.0.0-B4'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/timeline/',
+    'home_uri' => 'timeline',
+
+    'db_prefix' => 'bx_timeline_',
+    'class_prefix' => 'BxTimeline',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Timeline',
+
+    /**
+     * List of page triggers.
+     */
+    'page_triggers' => array (
+        'trigger_page_profile_view_entry',
+        'trigger_page_group_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_timeline_photos',
+    	'bx_timeline_videos',
+        'bx_timeline_files'
+    ),
+
+    /**
+     * Transcoders.
+     */
+    'transcoders' => array(
+    	'bx_timeline_photos_preview',
+    	'bx_timeline_photos_view',
+        'bx_timeline_photos_medium',
+        'bx_timeline_photos_big',
+
+        'bx_timeline_videos_photo_preview',
+        'bx_timeline_videos_photo_view',
+        'bx_timeline_videos_photo_big',
+        'bx_timeline_videos_poster_preview',
+    	'bx_timeline_videos_poster_view',
+        'bx_timeline_videos_poster_big',
+    	'bx_timeline_videos_mp4',
+    	'bx_timeline_videos_mp4_hd'
+    ),
+
+    /**
+     * 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,
+    	'update_relations' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'enable_success' => array(
+    	'process_page_triggers' => 1,
+        'process_menu_triggers' => 1,
+    	'register_transcoders' => 1,
+    	'clear_db_cache' => 1,
+    ),
+    'disable' => array (
+        'execute_sql' => 1,
+    	'update_relations_for_all' => 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
+     */
+    'relation_handlers' => array(
+    	'on_install' => '',
+    	'on_uninstall' => 'delete_module_events',
+	    'on_enable' => 'add_handlers',
+	    'on_disable' => 'delete_handlers',
+    ),
+    'relations' => array(
+    	'bx_notifications'
+    )
+);
+
+/** @} */

+ 411 - 0
modules/boonex/timeline/updates/13.0.4_13.0.5/source/install/langs/en.xml

@@ -0,0 +1,411 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources name="en" flag="gb" title="English">
+    <string name="_bx_timeline"><![CDATA[Timeline]]></string>
+    <string name="_bx_timeline_cmts"><![CDATA[Timeline's Comments]]></string>
+    <string name="_bx_timeline_reactions"><![CDATA[Timeline's Reactions]]></string>
+
+    <string name="_bx_timeline_options_category_general"><![CDATA[General]]></string>
+    <string name="_bx_timeline_options_category_browse"><![CDATA[Browse]]></string>
+    <string name="_bx_timeline_options_category_card"><![CDATA[Card]]></string>
+    <string name="_bx_timeline_options_category_cache"><![CDATA[Cache]]></string>
+    <string name="_bx_timeline_options_category_post"><![CDATA[Post]]></string>
+
+    <string name="_bx_timeline_option_enable_auto_approve"><![CDATA[Auto approve an update after creation]]></string>
+    <string name="_bx_timeline_option_enable_edit"><![CDATA[Allow user to edit his items]]></string>
+    <string name="_bx_timeline_option_enable_delete"><![CDATA[Allow Timeline owner to remove items]]></string>
+    <string name="_bx_timeline_option_enable_show_all"><![CDATA[Show all items in Public Feed including ones which were posted in personal Feeds]]></string>
+    <string name="_bx_timeline_option_enable_count_all_views"><![CDATA[Count views for all items in the Feed]]></string>
+    <string name="_bx_timeline_option_enable_repost_own_actions"><![CDATA[Repost uses its own actions (views, likes, etc)]]></string>
+    <string name="_bx_timeline_option_enable_hide_upon_delete"><![CDATA[Inactivate items upon hiding instead of deletion]]></string>
+    <string name="_bx_timeline_option_events_per_page_profile"><![CDATA[Number of items on profile page]]></string>
+    <string name="_bx_timeline_option_events_per_page_account"><![CDATA[Number of items on dashboard page]]></string>
+    <string name="_bx_timeline_option_events_per_page_home"><![CDATA[Number of items on site home page]]></string>
+    <string name="_bx_timeline_option_events_per_page"><![CDATA[Number of items per page]]></string>
+    <string name="_bx_timeline_option_enable_infinite_scroll"><![CDATA[Enable Infinite Scroll (experimental)]]></string>
+    <string name="_bx_timeline_option_events_per_preload"><![CDATA[Infinite Scroll: Number of items per preload]]></string>
+    <string name="_bx_timeline_option_auto_preloads"><![CDATA[Infinite Scroll: Number of auto preloads]]></string>
+    <string name="_bx_timeline_option_rss_length"><![CDATA[The length of RSS feed]]></string>
+    <string name="_bx_timeline_option_events_hide"><![CDATA[Show events]]></string>
+    <string name="_bx_timeline_option_enable_brief_cards"><![CDATA[Enable brief cards]]></string>
+    <string name="_bx_timeline_option_title_chars"><![CDATA[Number of characters in auto-generated update's title]]></string>
+    <string name="_bx_timeline_option_title_chars_short"><![CDATA[Number of characters in auto-generated update's short title]]></string>
+    <string name="_bx_timeline_option_videos_preload"><![CDATA[Videos preload]]></string>
+    <string name="_bx_timeline_option_videos_preload_auto"><![CDATA[Auto]]></string>
+    <string name="_bx_timeline_option_videos_preload_metadata"><![CDATA[Metadata]]></string>
+    <string name="_bx_timeline_option_videos_preload_none"><![CDATA[Disabled]]></string>
+    <string name="_bx_timeline_option_videos_autoplay"><![CDATA[Videos autoplay (for Timeline view only)]]></string>
+    <string name="_bx_timeline_option_videos_autoplay_off"><![CDATA[Disabled]]></string>
+    <string name="_bx_timeline_option_videos_autoplay_on_mute"><![CDATA[Enabled without sound]]></string>
+    <string name="_bx_timeline_option_videos_autoplay_on"><![CDATA[Enabled with sound]]></string>
+    <string name="_bx_timeline_option_preload_comments"><![CDATA[Number of preloaded comments (up to 7 items)]]></string>
+    <string name="_bx_timeline_option_enable_jump_to_switcher"><![CDATA[Show 'Jump to' switcher]]></string>
+    <string name="_bx_timeline_option_enable_sort_by_reaction"><![CDATA[Sort by the date of last comment (experimental, works for updates only)]]></string>
+    <string name="_bx_timeline_option_enable_sort_by_unread"><![CDATA[Sort by 'unread' state (show unread first).]]></string>
+    <string name="_bx_timeline_option_attachments_layout"><![CDATA[Show attachments as]]></string>
+    <string name="_bx_timeline_option_attachments_layout_gallery"><![CDATA[Gallery]]></string>
+    <string name="_bx_timeline_option_attachments_layout_showcase"><![CDATA[Showcase]]></string>
+    <string name="_bx_timeline_option_enable_hot"><![CDATA[Enable Hot feed aggregation]]></string>
+    <string name="_bx_timeline_option_hot_sources"><![CDATA[Use the following actions for content to appear in Hot feed]]></string>
+    <string name="_bx_timeline_option_hot_sources_content"><![CDATA[Add content]]></string>
+    <string name="_bx_timeline_option_hot_sources_comment"><![CDATA[Add comment]]></string>
+    <string name="_bx_timeline_option_hot_sources_vote"><![CDATA[Add vote]]></string>
+    <string name="_bx_timeline_option_hot_threshold_age"><![CDATA[Maximum age of commented/voted post that gets included in Hot feed (in days, 0 - no limit)]]></string>
+    <string name="_bx_timeline_option_hot_threshold_comment"><![CDATA[Minimum number of comments for content to appear in Hot feed]]></string>
+    <string name="_bx_timeline_option_hot_threshold_vote"><![CDATA[Minimum number of votes for content to appear in Hot feed]]></string>
+    <string name="_bx_timeline_option_hot_interval"><![CDATA[Interval of time (in hours) to get Hot events]]></string>
+    <string name="_bx_timeline_option_enable_cache_item"><![CDATA[Enable item cache]]></string>
+    <string name="_bx_timeline_option_cache_item_engine"><![CDATA[Item cache engine (other than File option may require custom server setup)]]></string>
+    <string name="_bx_timeline_option_cache_item_lifetime"><![CDATA[Item cache lifetime]]></string>
+    <string name="_bx_timeline_option_enable_editor_toolbar"><![CDATA[Enable post form editor toolbar]]></string>
+    <string name="_bx_timeline_option_editor_auto_attach_insertion"><![CDATA[Treat images inserted in the editor as attachments]]></string>
+    <string name="_bx_timeline_option_limit_attach_links"><![CDATA[Limit number of attached links (0 - no limit)]]></string>
+
+    <string name="_bx_timeline_form_post"><![CDATA[Post]]></string>
+    <string name="_bx_timeline_form_post_display_add"><![CDATA[Write Post]]></string>
+    <string name="_bx_timeline_form_post_display_add_public"><![CDATA[Write Public Post]]></string>
+    <string name="_bx_timeline_form_post_display_add_profile"><![CDATA[Write Profile Post]]></string>
+    <string name="_bx_timeline_form_post_display_edit"><![CDATA[Edit Post]]></string>
+    <string name="_bx_timeline_form_post_display_view"><![CDATA[View Post (for custom fields)]]></string>
+    <string name="_bx_timeline_form_post_input_sys_owner_id"><![CDATA[Owner ID]]></string>
+    <string name="_bx_timeline_form_post_input_owner_id_own"><![CDATA[Your profile]]></string>
+    <string name="_bx_timeline_form_post_input_owner_id_following_group"><![CDATA[{0}]]></string>
+    <string name="_bx_timeline_form_post_input_sys_action"><![CDATA[Action]]></string>
+    <string name="_bx_timeline_form_post_input_sys_type"><![CDATA[Type]]></string>
+    <string name="_bx_timeline_form_post_input_sys_text"><![CDATA[Content]]></string>
+    <string name="_bx_timeline_form_post_input_text"><![CDATA[]]></string>
+    <string name="_bx_timeline_form_post_input_sys_object_privacy_view"><![CDATA[Visibility]]></string>
+    <string name="_bx_timeline_form_post_input_object_privacy_view"><![CDATA[Visibility]]></string>
+    <string name="_bx_timeline_form_post_input_sys_date"><![CDATA[Created at]]></string>
+    <string name="_bx_timeline_form_post_input_date"><![CDATA[Created at]]></string>
+    <string name="_bx_timeline_form_post_input_sys_date_published"><![CDATA[Publishing time]]></string>
+    <string name="_bx_timeline_form_post_input_date_published"><![CDATA[Publishing time]]></string>
+    <string name="_bx_timeline_form_post_input_date_published_info"><![CDATA[Leave empty to publish immediately.]]></string>
+    <string name="_bx_timeline_form_post_input_sys_link"><![CDATA[Link]]></string>
+    <string name="_bx_timeline_form_post_input_link_alt"><![CDATA[Add Link]]></string>
+    <string name="_bx_timeline_form_post_input_link_err_delete"><![CDATA[Cannot remove the link. Please report.]]></string>
+    <string name="_bx_timeline_form_post_input_sys_photo"><![CDATA[Photo]]></string>
+    <string name="_bx_timeline_form_post_input_photo"><![CDATA[]]></string>
+    <string name="_bx_timeline_form_post_input_sys_files"><![CDATA[File]]></string>
+    <string name="_bx_timeline_form_post_input_files"><![CDATA[]]></string>
+    <string name="_bx_timeline_form_post_input_photo_alt"><![CDATA[Add Photo]]></string>
+    <string name="_bx_timeline_form_post_input_sys_video"><![CDATA[Video]]></string>
+    <string name="_bx_timeline_form_post_input_video"><![CDATA[]]></string>
+    <string name="_bx_timeline_form_post_input_video_alt"><![CDATA[Add Video]]></string>
+    <string name="_bx_timeline_form_post_input_sys_attachments"><![CDATA[Attachments]]></string>
+    <string name="_bx_timeline_form_post_input_sys_do_submit"><![CDATA[Post]]></string>
+    <string name="_bx_timeline_form_post_input_do_submit"><![CDATA[Post]]></string>
+    <string name="_bx_timeline_form_post_input_sys_do_cancel"><![CDATA[Cancel]]></string>
+    <string name="_bx_timeline_form_post_input_do_cancel"><![CDATA[Cancel]]></string>
+
+    <string name="_bx_timeline_form_attach_link"><![CDATA[Attach Link]]></string>
+    <string name="_bx_timeline_form_attach_link_display_add"><![CDATA[Attach Link]]></string>
+    <string name="_bx_timeline_form_attach_link_input_sys_event_id"><![CDATA[Event ID]]></string>
+    <string name="_bx_timeline_form_attach_link_input_sys_url"><![CDATA[Url]]></string>
+    <string name="_bx_timeline_form_attach_link_input_url"><![CDATA[Add Link]]></string>
+    <string name="_bx_timeline_form_attach_link_input_url_err"><![CDATA[Correct Link is essential. Please, fill in this field.]]></string>
+    <string name="_bx_timeline_form_attach_link_input_sys_do_submit"><![CDATA[Add]]></string>
+    <string name="_bx_timeline_form_attach_link_input_do_submit"><![CDATA[Add]]></string>
+    <string name="_bx_timeline_form_attach_link_input_do_cancel"><![CDATA[Close]]></string>
+
+    <string name="_bx_timeline_form_repost"><![CDATA[Repost]]></string>
+    <string name="_bx_timeline_form_repost_display_with"><![CDATA[Repost With Text]]></string>
+    <string name="_bx_timeline_form_repost_display_to"><![CDATA[Repost To]]></string>
+    <string name="_bx_timeline_form_repost_input_sys_reposter_id"><![CDATA[Reposter ID]]></string>
+    <string name="_bx_timeline_form_repost_input_sys_owner_id"><![CDATA[Owner ID]]></string>
+    <string name="_bx_timeline_form_repost_input_sys_type"><![CDATA[Type]]></string>
+    <string name="_bx_timeline_form_repost_input_sys_action"><![CDATA[Action]]></string>
+    <string name="_bx_timeline_form_repost_input_sys_object_id"><![CDATA[Object ID]]></string>
+    <string name="_bx_timeline_form_repost_input_sys_search"><![CDATA[Search]]></string>
+    <string name="_bx_timeline_form_repost_input_search"><![CDATA[Search]]></string>
+    <string name="_bx_timeline_form_repost_input_sys_list"><![CDATA[List]]></string>
+    <string name="_bx_timeline_form_repost_input_list"><![CDATA[or select]]></string>
+    <string name="_bx_timeline_form_repost_input_sys_text"><![CDATA[Text]]></string>
+    <string name="_bx_timeline_form_repost_input_text"><![CDATA[]]></string>
+    <string name="_bx_timeline_form_repost_input_sys_reposted"><![CDATA[Reposted]]></string>
+    <string name="_bx_timeline_form_repost_input_reposted"><![CDATA[]]></string>
+    <string name="_bx_timeline_form_repost_input_sys_do_submit"><![CDATA[Repost]]></string>
+    <string name="_bx_timeline_form_repost_input_do_submit"><![CDATA[Repost]]></string>
+    <string name="_bx_timeline_form_repost_input_sys_do_cancel"><![CDATA[Cancel]]></string>
+    <string name="_bx_timeline_form_repost_input_do_cancel"><![CDATA[Cancel]]></string>
+
+    <string name="_bx_timeline_form_filters_input_by_modules"><![CDATA[Content:]]></string>
+    <string name="_bx_timeline_form_filters_input_by_modules_all"><![CDATA[All]]></string>
+    <string name="_bx_timeline_form_filters_input_by_modules_selected"><![CDATA[Selected]]></string>
+    <string name="_bx_timeline_form_filters_input_do_apply"><![CDATA[Apply]]></string>
+
+    <string name="_bx_timeline_privacy_view"><![CDATA[View event]]></string>
+
+    <string name="_bx_timeline_acl_action_post"><![CDATA[Post]]></string>
+    <string name="_bx_timeline_acl_action_edit"><![CDATA[Edit Any Post]]></string>
+    <string name="_bx_timeline_acl_action_delete"><![CDATA[Delete Any Post]]></string>
+    <string name="_bx_timeline_acl_action_vote"><![CDATA[Vote]]></string>
+    <string name="_bx_timeline_acl_action_repost"><![CDATA[Repost]]></string>
+    <string name="_bx_timeline_acl_action_send"><![CDATA[Send]]></string>
+    <string name="_bx_timeline_acl_action_mute"><![CDATA[Mute Author]]></string>
+    <string name="_bx_timeline_acl_action_pin"><![CDATA['Pin here' Any Post]]></string>
+    <string name="_bx_timeline_acl_action_stick"><![CDATA['Pin for all' Any Post]]></string>
+    <string name="_bx_timeline_acl_action_promote"><![CDATA[Promote Any Post]]></string>
+
+
+    <!-- Pages -->
+    <string name="_bx_timeline_page_title_sys_view"><![CDATA[Profile Feed]]></string>
+    <string name="_bx_timeline_page_title_view"><![CDATA[Profile Feed]]></string>
+    <string name="_bx_timeline_page_title_sys_view_home"><![CDATA[Public Feed]]></string>
+    <string name="_bx_timeline_page_title_view_home"><![CDATA[Public Feed]]></string>
+    <string name="_bx_timeline_page_title_sys_view_hot"><![CDATA[Hot Feed]]></string>
+    <string name="_bx_timeline_page_title_view_hot"><![CDATA[Hot Feed]]></string>
+    <string name="_bx_timeline_page_title_sys_item"><![CDATA[Feed Item]]></string>
+    <string name="_bx_timeline_page_title_item"><![CDATA[Feed Item]]></string>
+    <string name="_bx_timeline_page_title_sys_item_brief"><![CDATA[Feed Item Preview]]></string>
+    <string name="_bx_timeline_page_title_item_brief"><![CDATA[Feed Item Preview]]></string>
+    <string name="_bx_timeline_page_title_sys_account"><![CDATA[Feed]]></string>
+    <string name="_bx_timeline_page_title_account"><![CDATA[Feed]]></string>
+    <string name="_bx_timeline_page_title_sys_manage_administration"><![CDATA[Manage All]]></string>
+    <string name="_bx_timeline_page_title_manage"><![CDATA[Manage]]></string>
+    <string name="_bx_timeline_page_block_title_system_post_profile"><![CDATA[Post to Сontext Feed]]></string>
+    <string name="_bx_timeline_page_block_title_post_profile"><![CDATA[Post to Feed]]></string>
+    <string name="_bx_timeline_page_block_title_system_view_profile"><![CDATA[Profile Feed (Timeline)]]></string>
+    <string name="_bx_timeline_page_block_title_view_profile"><![CDATA[Profile Feed]]></string>
+    <string name="_bx_timeline_page_block_title_system_view_profile_outline"><![CDATA[Profile Feed (Outline)]]></string>
+    <string name="_bx_timeline_page_block_title_view_profile_outline"><![CDATA[Profile Feed]]></string>
+    <string name="_bx_timeline_page_block_title_item"><![CDATA[Item]]></string>
+    <string name="_bx_timeline_page_block_title_item_content"><![CDATA[Content]]></string>
+    <string name="_bx_timeline_page_block_title_item_info"><![CDATA[Info]]></string>
+    <string name="_bx_timeline_page_block_title_entry_reports"><![CDATA[Reports]]></string>
+    <string name="_bx_timeline_page_block_title_item_comments"><![CDATA[Comments]]></string>
+    <string name="_bx_timeline_page_block_title_system_post_account"><![CDATA[Post to Feed]]></string>
+    <string name="_bx_timeline_page_block_title_post_account"><![CDATA[Post to Feed]]></string>
+    <string name="_bx_timeline_page_block_title_system_view_account"><![CDATA[Feed (Timeline)]]></string>
+    <string name="_bx_timeline_page_block_title_view_account"><![CDATA[Feed]]></string>
+    <string name="_bx_timeline_page_block_title_system_view_account_outline"><![CDATA[Feed (Outline)]]></string>
+    <string name="_bx_timeline_page_block_title_view_account_outline"><![CDATA[Feed]]></string>
+    <string name="_bx_timeline_page_block_title_system_views_timeline"><![CDATA[All Feeds (Timeline)]]></string>
+    <string name="_bx_timeline_page_block_title_views_timeline"><![CDATA[Feed]]></string>
+    <string name="_bx_timeline_page_block_title_system_views_outline"><![CDATA[All Feeds (Outline)]]></string>
+    <string name="_bx_timeline_page_block_title_views_outline"><![CDATA[Feed]]></string>        
+    <string name="_bx_timeline_page_block_title_system_post_home"><![CDATA[Post to Public Feed]]></string>
+    <string name="_bx_timeline_page_block_title_post_home"><![CDATA[Post to Feed]]></string>
+    <string name="_bx_timeline_page_block_title_system_view_home"><![CDATA[Public Feed (Timeline)]]></string>
+    <string name="_bx_timeline_page_block_title_view_home"><![CDATA[Public Feed]]></string>
+    <string name="_bx_timeline_page_block_title_system_view_home_outline"><![CDATA[Public Feed (Outline)]]></string>
+    <string name="_bx_timeline_page_block_title_view_home_outline"><![CDATA[Public Feed]]></string>
+    <string name="_bx_timeline_page_block_title_system_view_hot"><![CDATA[Hot Feed (Timeline)]]></string>
+    <string name="_bx_timeline_page_block_title_view_hot"><![CDATA[Hot Feed]]></string>
+    <string name="_bx_timeline_page_block_title_system_view_hot_outline"><![CDATA[Hot Feed (Outline)]]></string>
+    <string name="_bx_timeline_page_block_title_view_hot_outline"><![CDATA[Hot Feed]]></string>
+    <string name="_bx_timeline_page_block_title_system_menu_db"><![CDATA[Dynamic Browsing: Menu]]></string>
+    <string name="_bx_timeline_page_block_title_menu_db"><![CDATA[Feeds]]></string>
+    <string name="_bx_timeline_page_block_title_system_views_db"><![CDATA[Dynamic Browsing: Views]]></string>
+    <string name="_bx_timeline_page_block_title_views_db"><![CDATA[Feed]]></string>
+    <string name="_bx_timeline_page_block_title_browse_cmts"><![CDATA[Feeds' Comments]]></string>
+
+    <string name="_bx_timeline_page_title_sys_manage"><![CDATA[Manage]]></string>
+    <string name="_bx_timeline_page_title_manage"><![CDATA[Manage Timeline]]></string>
+    <string name="_bx_timeline_page_block_title_system_manage"><![CDATA[Manage]]></string>
+    <string name="_bx_timeline_page_block_title_system_manage_administration"><![CDATA[Manage All]]></string>
+    <string name="_bx_timeline_page_block_title_manage"><![CDATA[Manage]]></string>
+    <string name="_bx_timeline_page_block_title_manage_own"><![CDATA[Manage]]></string>
+    <string name="_bx_timeline_page_block_title_muted"><![CDATA[Muted]]></string>
+
+    <string name="_bx_timeline_page_content_ph_timeline"><![CDATA[Timeline: with timeline placeholder]]></string>
+    <string name="_bx_timeline_page_content_ph_outline"><![CDATA[Timeline: with outline placeholder]]></string>
+
+
+    <!-- Menus -->
+    <string name="_bx_timeline_menu_title_view"><![CDATA[View]]></string>
+    <string name="_bx_timeline_menu_set_title_view"><![CDATA[View]]></string>
+    <string name="_bx_timeline_menu_item_title_system_channels"><![CDATA[Channels]]></string>
+    <string name="_bx_timeline_menu_item_title_channels"><![CDATA[Channels]]></string>
+    <string name="_bx_timeline_menu_item_title_system_feed"><![CDATA[Feed]]></string>
+    <string name="_bx_timeline_menu_item_title_feed"><![CDATA[Feed]]></string>
+    <string name="_bx_timeline_menu_item_title_system_public"><![CDATA[Public]]></string>
+    <string name="_bx_timeline_menu_item_title_public"><![CDATA[Public]]></string>
+    <string name="_bx_timeline_menu_item_title_system_hot"><![CDATA[Hot]]></string>
+    <string name="_bx_timeline_menu_item_title_hot"><![CDATA[Hot]]></string>
+
+    <string name="_bx_timeline_menu_title_feeds"><![CDATA[Feeds]]></string>
+    <string name="_bx_timeline_menu_set_title_feeds"><![CDATA[Feeds]]></string>
+    <string name="_bx_timeline_menu_template_title_feeds"><![CDATA[Feeds]]></string>
+    <string name="_bx_timeline_menu_item_title_system_divider"><![CDATA[Divider]]></string>
+
+    <string name="_bx_timeline_menu_item_view_all"><![CDATA[All posts]]></string>
+    <string name="_bx_timeline_menu_item_view_owner"><![CDATA[Posts by {0}]]></string>
+    <string name="_bx_timeline_menu_item_view_other"><![CDATA[Posts by others]]></string>
+    <string name="_bx_timeline_menu_item_get_rss"><![CDATA[RSS]]></string>
+
+    <string name="_bx_timeline_menu_title_item_share"><![CDATA[Share Item]]></string>
+    <string name="_bx_timeline_menu_set_title_item_share"><![CDATA[Share Item]]></string>
+    <string name="_bx_timeline_menu_item_title_system_item_repost"><![CDATA[Repost]]></string>
+    <string name="_bx_timeline_menu_item_title_item_repost"><![CDATA[Repost]]></string>
+    <string name="_bx_timeline_menu_item_title_system_item_repost_with"><![CDATA[Repost with Text]]></string>
+    <string name="_bx_timeline_menu_item_title_item_repost_with"><![CDATA[Repost with Text]]></string>
+    <string name="_bx_timeline_menu_item_title_system_item_repost_to"><![CDATA[Repost to Context]]></string>
+    <string name="_bx_timeline_menu_item_title_item_repost_to"><![CDATA[Repost to Context]]></string>
+    <string name="_bx_timeline_menu_item_title_system_item_send"><![CDATA[Send]]></string>
+    <string name="_bx_timeline_menu_item_title_item_send"><![CDATA[Send to Friend]]></string>
+    <string name="_bx_timeline_menu_item_title_system_admt_timeline"><![CDATA[Timeline]]></string>
+    <string name="_bx_timeline_menu_item_title_admt_timeline"><![CDATA[Timeline]]></string>
+
+    <string name="_bx_timeline_menu_title_item_manage"><![CDATA[Manage Item]]></string>
+    <string name="_bx_timeline_menu_set_title_item_manage"><![CDATA[Manage Item]]></string>
+    <string name="_bx_timeline_menu_item_title_system_item_pin"><![CDATA[Pin here]]></string>
+    <string name="_bx_timeline_menu_item_title_item_pin"><![CDATA[Pin here]]></string>
+    <string name="_bx_timeline_menu_item_title_system_item_unpin"><![CDATA[Unpin here]]></string>
+    <string name="_bx_timeline_menu_item_title_item_unpin"><![CDATA[Unpin here]]></string>
+    <string name="_bx_timeline_menu_item_title_system_item_stick"><![CDATA[Pin for all]]></string>
+    <string name="_bx_timeline_menu_item_title_item_stick"><![CDATA[Pin for all]]></string>
+    <string name="_bx_timeline_menu_item_title_system_item_unstick"><![CDATA[Unpin for all]]></string>
+    <string name="_bx_timeline_menu_item_title_item_unstick"><![CDATA[Unpin for all]]></string>
+    <string name="_bx_timeline_menu_item_title_system_item_promote"><![CDATA[Promote]]></string>
+    <string name="_bx_timeline_menu_item_title_item_promote"><![CDATA[Promote]]></string>
+    <string name="_bx_timeline_menu_item_title_system_item_unpromote"><![CDATA[Unpromote]]></string>
+    <string name="_bx_timeline_menu_item_title_item_unpromote"><![CDATA[Unpromote]]></string>
+    <string name="_bx_timeline_menu_item_title_system_item_edit"><![CDATA[Edit]]></string>
+    <string name="_bx_timeline_menu_item_title_item_edit"><![CDATA[Edit]]></string>
+    <string name="_bx_timeline_menu_item_title_system_item_delete"><![CDATA[Delete]]></string>
+    <string name="_bx_timeline_menu_item_title_item_delete"><![CDATA[{delete_title}]]></string>
+    <string name="_bx_timeline_menu_item_title_item_delete_common"><![CDATA[Delete]]></string>
+    <string name="_bx_timeline_menu_item_title_item_delete_system"><![CDATA[Hide from feeds]]></string>
+    <string name="_bx_timeline_menu_item_title_system_item_mute"><![CDATA[Mute Author]]></string>
+    <string name="_bx_timeline_menu_item_title_item_mute"><![CDATA[Mute Author]]></string>
+
+    <string name="_bx_timeline_menu_title_item_actions"><![CDATA[Item Actions]]></string>
+    <string name="_bx_timeline_menu_set_title_item_actions"><![CDATA[Item Actions]]></string>
+    <string name="_bx_timeline_menu_title_item_actions_all"><![CDATA[Item Actions All]]></string>
+    <string name="_bx_timeline_menu_set_title_item_actions_all"><![CDATA[Item Actions All]]></string>
+    <string name="_bx_timeline_menu_title_item_counters"><![CDATA[Item Counters]]></string>
+    <string name="_bx_timeline_menu_set_title_item_counters"><![CDATA[Item Counters]]></string>
+    <string name="_bx_timeline_menu_item_title_system_item_comment"><![CDATA[Comment]]></string>
+    <string name="_bx_timeline_menu_item_title_item_comment"><![CDATA[Comment]]></string>
+    <string name="_bx_timeline_menu_item_title_system_item_view"><![CDATA[View]]></string>
+    <string name="_bx_timeline_menu_item_title_system_item_vote"><![CDATA[Vote (Like)]]></string>
+    <string name="_bx_timeline_menu_item_title_system_item_score"><![CDATA[Vote (Up/Down)]]></string>
+    <string name="_bx_timeline_menu_item_title_system_item_reaction"><![CDATA[Reaction]]></string>
+    <string name="_bx_timeline_menu_item_title_system_item_share"><![CDATA[Share]]></string>
+    <string name="_bx_timeline_menu_item_title_item_share"><![CDATA[Share]]></string>
+    <string name="_bx_timeline_menu_item_title_system_item_report"><![CDATA[Report]]></string>
+    <string name="_bx_timeline_menu_item_title_system_item_more"><![CDATA[More Actions]]></string>
+    <string name="_bx_timeline_menu_item_title_item_more"><![CDATA[]]></string>
+
+    <string name="_bx_timeline_menu_title_post_attachments"><![CDATA[Form Attachments]]></string>
+    <string name="_bx_timeline_menu_set_title_post_attachments"><![CDATA[Form Attachments]]></string>
+    <string name="_bx_timeline_menu_item_title_system_add_emoji"><![CDATA[Add Emoji]]></string>
+    <string name="_bx_timeline_menu_item_title_add_emoji"><![CDATA[Add Emoji]]></string>
+    <string name="_bx_timeline_menu_item_title_system_add_link"><![CDATA[Add Link]]></string>
+    <string name="_bx_timeline_menu_item_title_add_link"><![CDATA[Add Link]]></string>
+    <string name="_bx_timeline_menu_item_title_system_add_photo_simple"><![CDATA[Add Photo (Simple)]]></string>
+    <string name="_bx_timeline_menu_item_title_system_add_photo_html5"><![CDATA[Add Photo (HTML5)]]></string>
+    <string name="_bx_timeline_menu_item_title_add_photo"><![CDATA[Add Photo]]></string>
+    <string name="_bx_timeline_menu_item_title_system_add_video_simple"><![CDATA[Add Video (Simple)]]></string>
+    <string name="_bx_timeline_menu_item_title_system_add_video_html5"><![CDATA[Add Video (HTML5)]]></string>
+
+    <string name="_bx_timeline_menu_item_title_add_file"><![CDATA[Add File]]></string>
+    <string name="_bx_timeline_menu_item_title_system_add_file_simple"><![CDATA[Add File (Simple)]]></string>
+    <string name="_bx_timeline_menu_item_title_system_add_file_html5"><![CDATA[Add File (HTML5)]]></string>
+
+    <string name="_bx_timeline_menu_item_title_add_video"><![CDATA[Add Video]]></string>
+    <string name="_bx_timeline_menu_item_title_system_add_video_record"><![CDATA[Record Video]]></string>
+    <string name="_bx_timeline_menu_item_title_add_video_record"><![CDATA[Record Video]]></string>
+    <string name="_bx_timeline_menu_item_title_system_timeline"><![CDATA[Timeline]]></string>
+    <string name="_bx_timeline_menu_item_title_timeline"><![CDATA[Timeline]]></string>
+    <string name="_bx_timeline_menu_item_title_system_create_entry"><![CDATA[Update]]></string>
+    <string name="_bx_timeline_menu_item_title_create_entry"><![CDATA[Update]]></string>
+    <string name="_bx_timeline_menu_item_title_system_view_timeline_view"><![CDATA[Timeline]]></string>
+    <string name="_bx_timeline_menu_item_title_view_timeline_view"><![CDATA[Timeline]]></string>
+
+    <string name="_bx_timeline_menu_item_title_system_manage_my_timeline"><![CDATA[Timeline]]></string>
+    <string name="_bx_timeline_menu_item_title_manage_my_timeline"><![CDATA[Timeline]]></string>
+
+    <!-- Grids -->
+    <string name="_bx_timeline_grid_filter_item_title_adm_select_one_filter1"><![CDATA[All Statuses]]></string>
+    <string name="_bx_timeline_grid_filter_item_title_adm_active"><![CDATA[Active]]></string>
+    <string name="_bx_timeline_grid_filter_item_title_adm_hidden"><![CDATA[Hidden]]></string>
+    <string name="_bx_timeline_grid_filter_item_title_adm_pending"><![CDATA[Pending]]></string>
+    <string name="_bx_timeline_grid_column_title_adm_active"><![CDATA[Active]]></string>
+    <string name="_bx_timeline_grid_column_title_adm_description"><![CDATA[Event]]></string>
+    <string name="_bx_timeline_grid_column_title_adm_added"><![CDATA[Added]]></string>
+    <string name="_bx_timeline_grid_column_title_adm_author"><![CDATA[Author]]></string>
+    <string name="_bx_timeline_grid_action_title_adm_delete"><![CDATA[Delete]]></string>
+    <string name="_bx_timeline_grid_action_title_adm_audit_content"><![CDATA[Audit actions]]></string>
+    <string name="_bx_timeline_grid_txt_account_manager"><![CDATA[Redirect to manage account.]]></string>
+
+    <string name="_bx_timeline_alert_module_comment"><![CDATA[Comment]]></string>
+    <string name="_bx_timeline_alert_module_timeline_common_post"><![CDATA[Timeline (post)]]></string>
+    <string name="_bx_timeline_alert_module_timeline_common_repost"><![CDATA[Timeline (repost)]]></string>
+    <string name="_bx_timeline_alert_action_added"><![CDATA[add]]></string>
+    <string name="_bx_timeline_alert_action_post_common"><![CDATA[add post]]></string>
+    <string name="_bx_timeline_alert_action_repost"><![CDATA[repost]]></string>
+    <string name="_bx_timeline_alert_action_post_common_personal"><![CDATA[New content]]></string>
+    <string name="_bx_timeline_alert_action_post_common_follow_member"><![CDATA[New content]]></string>
+    <string name="_bx_timeline_alert_action_post_common_follow_context"><![CDATA[New content]]></string>
+    <string name="_bx_timeline_alert_action_repost_personal"><![CDATA[New content repost]]></string>
+    <string name="_bx_timeline_alert_action_repost_follow_member"><![CDATA[New content repost]]></string>
+    <string name="_bx_timeline_alert_action_repost_follow_context"><![CDATA[New content repost]]></string>
+
+    <string name="_bx_timeline_txt_msg_no_results"><![CDATA[Empty]]></string>
+    <string name="_bx_timeline_txt_msg_performed_action"><![CDATA[The action was successfully performed.]]></string>
+    <string name="_bx_timeline_txt_msg_posted"><![CDATA[Posted successfully.]]></string>
+    <string name="_bx_timeline_grid_action_err_delete"><![CDATA[Cannot delete the selected timeline events(s).]]></string>
+    <string name="_bx_timeline_txt_err_cannot_perform_insertion"><![CDATA[Cannot perform insertion.]]></string>
+    <string name="_bx_timeline_txt_err_cannot_perform_action"><![CDATA[Cannot perform action. Please report.]]></string>
+    <string name="_bx_timeline_txt_err_empty_post"><![CDATA[The post is empty.]]></string>
+    <string name="_bx_timeline_txt_err_attach_links"><![CDATA[The maximum allowed number of attached links has been reached.]]></string>
+
+    <string name="_bx_timeline_txt_to"><![CDATA[to]]></string>
+    <string name="_bx_timeline_txt_load_more"><![CDATA[Load More]]></string>
+    <string name="_bx_timeline_txt_loading"><![CDATA[Loading...]]></string>
+    <string name="_bx_timeline_txt_loading_complete"><![CDATA[Loading complete]]></string>
+    <string name="_bx_timeline_txt_or_jump_to"><![CDATA[... or jump to:]]></string>
+    <string name="_bx_timeline_txt_jump_to_n_year"><![CDATA[Jump to {0} year]]></string>
+    <string name="_bx_timeline_txt_jump_to_recent"><![CDATA[Jump to recent posts]]></string>
+    <string name="_bx_timeline_txt_status_deleted"><![CDATA[Deleted]]></string>
+    <string name="_bx_timeline_txt_hot"><![CDATA[Hot post]]></string>
+    <string name="_bx_timeline_txt_pinned"><![CDATA[Pinned post]]></string>
+    <string name="_bx_timeline_txt_sticked"><![CDATA[Pinned for all post]]></string>
+    <string name="_bx_timeline_txt_promoted"><![CDATA[Promoted]]></string>
+    <string name="_bx_timeline_txt_note_approve_pending"><![CDATA[Update will be published as soon as it's approved by moderator]]></string>
+    <string name="_bx_timeline_txt_note_scheduled_awaiting"><![CDATA[Update publishing date is {0}]]></string>
+    <string name="_bx_timeline_txt_note_processing_awaiting"><![CDATA[Update will be published as soon as video is converted]]></string>
+    <string name="_bx_timeline_txt_note_processing_failed"><![CDATA[Update isn't published because video conversion failed, edit video to fix the issue.]]></string>
+    <string name="_bx_timeline_txt_rss_caption"><![CDATA[{0}'s timeline]]></string>
+    <string name="_bx_timeline_txt_added_sample"><![CDATA[Added {0}]]></string>
+    <string name="_bx_timeline_txt_user_added_sample"><![CDATA[{0} added {1}]]></string>
+    <string name="_bx_timeline_txt_user_repost"><![CDATA[{0}'s repost]]></string>
+    <string name="_bx_timeline_txt_user_reposted_user_sample"><![CDATA[{0} reposted {1}'s {2}]]></string>
+    <string name="_bx_timeline_txt_sample"><![CDATA[post]]></string>
+    <string name="_bx_timeline_txt_sample_with_article"><![CDATA[a post]]></string>
+    <string name="_bx_timeline_txt_sample_ext"><![CDATA[timeline post]]></string>
+    <string name="_bx_timeline_txt_sample_comment_single"><![CDATA[comment to timeline post]]></string>
+    <string name="_bx_timeline_txt_sample_vote_single"><![CDATA[vote to timeline post]]></string>
+    <string name="_bx_timeline_txt_sample_reaction_single"><![CDATA['{0}' reaction to timeline post]]></string>
+    <string name="_bx_timeline_txt_sample_score_up_single"><![CDATA[score up vote to timeline post]]></string>
+    <string name="_bx_timeline_txt_sample_score_down_single"><![CDATA[score down vote to timeline post]]></string>
+    <string name="_bx_timeline_txt_sample_with_link"><![CDATA[with link]]></string>
+    <string name="_bx_timeline_txt_sample_with_image"><![CDATA[with image]]></string>
+    <string name="_bx_timeline_txt_sample_with_video"><![CDATA[with video]]></string>
+    <string name="_bx_timeline_txt_sample_with_media"><![CDATA[with media]]></string>
+    <string name="_bx_timeline_txt_sample_with_file"><![CDATA[with file]]></string>
+    <string name="_bx_timeline_txt_today"><![CDATA[Today]]></string>
+    <string name="_bx_timeline_txt_some_text_here"><![CDATA[Share your thoughts, location, photos or video]]></string>
+    <string name="_bx_timeline_txt_show"><![CDATA[Show]]></string>
+    <string name="_bx_timeline_txt_new_content"><![CDATA[New content]]></string>
+    <string name="_bx_timeline_txt_filters"><![CDATA[Filters]]></string>
+
+    <string name="_bx_timeline_txt_do_repost"><![CDATA[Repost]]></string>
+    <string name="_bx_timeline_txt_do_repost_with"><![CDATA[Repost with Text]]></string>
+    <string name="_bx_timeline_txt_do_repost_to"><![CDATA[Repost to Context]]></string>
+    <string name="_bx_timeline_txt_repost_counter"><![CDATA[{0}]]></string>
+    <string name="_bx_timeline_txt_reposted"><![CDATA[Reposted {0}'s {1}.]]></string>
+    <string name="_bx_timeline_txt_reposted_by"><![CDATA[Reposted by]]></string>
+    <string name="_bx_timeline_txt_err_cannot_repost"><![CDATA[Cannot repost. Please report.]]></string>
+    <string name="_bx_timeline_txt_err_already_reposted"><![CDATA[You already reposted the item.]]></string>
+    <string name="_bx_timeline_txt_msg_success_repost"><![CDATA[The item was successfully reposted.]]></string>
+    <string name="_bx_timeline_txt_object_reposted"><![CDATA[<b class="bx-ntfs-content-profile">{owner_name}</b> reposted a {entry_sample} <b class="bx-ntfs-content-entry">{entry_caption}</b>]]></string>
+
+    <!-- EMAIL TEMPLATES -->
+    <string name="_bx_timeline_et_txt_name_send"><![CDATA[Send to Friend.]]></string>
+    <string name="_bx_timeline_et_txt_subject_send"><![CDATA[It may be interesting for you.]]></string>
+    <string name="_bx_timeline_et_txt_body_send"><![CDATA[
+<p>Hello.</p>
+<p>Take a look at <a href="{ViewLink}">this post</a>, it may be interesting for you.</p>]]></string>
+</resources>

+ 570 - 0
modules/boonex/timeline/updates/13.0.4_13.0.5/source/install/sql/enable.sql

@@ -0,0 +1,570 @@
+
+-- CONTENT PLACEHOLDERS
+SET @iCPHOrder = (SELECT IFNULL(MAX(`order`), 0) FROM `sys_pages_content_placeholders` ORDER BY `order` DESC LIMIT 1);
+INSERT INTO `sys_pages_content_placeholders` (`module`, `title`, `template`, `order`) VALUES
+('bx_timeline', '_bx_timeline_page_content_ph_timeline', 'block_async_timeline.html', @iCPHOrder + 1),
+('bx_timeline', '_bx_timeline_page_content_ph_outline', 'block_async_outline.html', @iCPHOrder + 2);
+
+
+-- PAGES & BLOCKS
+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_timeline_view', '_bx_timeline_page_title_sys_view', '_bx_timeline_page_title_view', 'bx_timeline', 5, 2147483647, 1, 'timeline-view', 'page.php?i=timeline-view', '', '', '', 0, 1, 0, 'BxTimelinePageView', 'modules/boonex/timeline/classes/BxTimelinePageView.php'),
+('bx_timeline_view_home', '_bx_timeline_page_title_sys_view_home', '_bx_timeline_page_title_view_home', 'bx_timeline', 5, 2147483647, 1, 'timeline-view-home', 'page.php?i=timeline-view-home', '', '', '', 0, 1, 0, '', ''),
+('bx_timeline_view_hot', '_bx_timeline_page_title_sys_view_hot', '_bx_timeline_page_title_view_hot', 'bx_timeline', 5, 2147483647, 1, 'timeline-view-hot', 'page.php?i=timeline-view-hot', '', '', '', 0, 1, 0, '', ''),
+
+('bx_timeline_item', '_bx_timeline_page_title_sys_item', '_bx_timeline_page_title_item', 'bx_timeline', 2, 2147483647, 1, 'item', '', '', '', '', 0, 1, 0, 'BxTimelinePageViewItem', 'modules/boonex/timeline/classes/BxTimelinePageViewItem.php'),
+('bx_timeline_item_brief', '_bx_timeline_page_title_sys_item_brief', '_bx_timeline_page_title_item_brief', 'bx_timeline', 5, 2147483647, 1, 'item-quick', '', '', '', '', 0, 1, 0, 'BxTimelinePageViewItem', 'modules/boonex/timeline/classes/BxTimelinePageViewItem.php'),
+
+('bx_timeline_manage', '_bx_timeline_page_title_sys_manage', '_bx_timeline_page_title_manage', 'bx_timeline', 5, 2147483647, 1, 'timeline-manage', 'page.php?i=timeline-manage', '', '', '', 0, 1, 0, '', '');
+
+INSERT INTO `sys_pages_blocks` (`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES
+('bx_timeline_view', 1, 'bx_timeline', '_bx_timeline_page_block_title_system_post_profile', '_bx_timeline_page_block_title_post_profile', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:11:"bx_timeline";s:6:"method";s:14:"get_block_post";}', 0, 0, 1, 1),
+('bx_timeline_view', 1, 'bx_timeline', '_bx_timeline_page_block_title_system_view_profile', '_bx_timeline_page_block_title_view_profile', 0, 2147483647, 'service', 'a:2:{s:6:"module";s:11:"bx_timeline";s:6:"method";s:14:"get_block_view";}', 0, 0, 1, 2),
+('bx_timeline_view', 1, 'bx_timeline', '_bx_timeline_page_block_title_system_view_profile_outline', '_bx_timeline_page_block_title_view_profile_outline', 0, 2147483647, 'service', 'a:2:{s:6:"module";s:11:"bx_timeline";s:6:"method";s:22:"get_block_view_outline";}', 0, 0, 0, 3),
+
+('bx_timeline_view_home', 1, 'bx_timeline', '_bx_timeline_page_block_title_system_post_home', '_bx_timeline_page_block_title_post_home', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:11:"bx_timeline";s:6:"method";s:19:"get_block_post_home";}', 0, 0, 1, 1),
+('bx_timeline_view_home', 1, 'bx_timeline', '_bx_timeline_page_block_title_system_view_home', '_bx_timeline_page_block_title_view_home', 0, 2147483647, 'service', 'a:2:{s:6:"module";s:11:"bx_timeline";s:6:"method";s:19:"get_block_view_home";}', 0, 0, 0, 2),
+('bx_timeline_view_home', 1, 'bx_timeline', '_bx_timeline_page_block_title_system_view_home_outline', '_bx_timeline_page_block_title_view_home_outline', 0, 2147483647, 'service', 'a:2:{s:6:"module";s:11:"bx_timeline";s:6:"method";s:27:"get_block_view_home_outline";}', 0, 0, 1, 3),
+
+('bx_timeline_view_hot', 1, 'bx_timeline', '_bx_timeline_page_block_title_system_view_hot', '_bx_timeline_page_block_title_view_hot', 0, 2147483647, 'service', 'a:2:{s:6:"module";s:11:"bx_timeline";s:6:"method";s:18:"get_block_view_hot";}', 0, 1, 0, 1),
+('bx_timeline_view_hot', 1, 'bx_timeline', '_bx_timeline_page_block_title_system_view_hot_outline', '_bx_timeline_page_block_title_view_hot_outline', 0, 2147483647, 'service', 'a:2:{s:6:"module";s:11:"bx_timeline";s:6:"method";s:26:"get_block_view_hot_outline";}', 0, 1, 1, 2),
+
+('bx_timeline_item', 1, 'bx_timeline', '', '_bx_timeline_page_block_title_item', 0, 2147483647, 'service', 'a:2:{s:6:"module";s:11:"bx_timeline";s:6:"method";s:14:"get_block_item";}', 0, 0, 1, 1),
+('bx_timeline_item', 1, 'bx_timeline', '', '_bx_timeline_page_block_title_item_comments', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:11:"bx_timeline";s:6:"method";s:23:"get_block_item_comments";}', 0, 0, 1, 2),
+('bx_timeline_item', 2, 'bx_timeline', '', '_bx_timeline_page_block_title_item_info', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:11:"bx_timeline";s:6:"method";s:19:"get_block_item_info";}', 0, 0, 1, 1),
+('bx_timeline_item', 1, 'bx_timeline', '', '_bx_timeline_page_block_title_entry_reports', 11, 2147483647, 'service', 'a:2:{s:6:\"module\";s:11:\"bx_timeline\";s:6:\"method\";s:14:\"entity_reports\";}', 0, 0, 1, 6),
+
+('bx_timeline_item_brief', 1, 'bx_timeline', '', '_bx_timeline_page_block_title_item_content', 0, 2147483647, 'service', 'a:2:{s:6:"module";s:11:"bx_timeline";s:6:"method";s:22:"get_block_item_content";}', 0, 0, 1, 1),
+('bx_timeline_item_brief', 0, 'bx_timeline', '', '_bx_timeline_page_block_title_item_info', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:11:"bx_timeline";s:6:"method";s:19:"get_block_item_info";}', 0, 0, 1, 1),
+('bx_timeline_item_brief', 0, 'bx_timeline', '', '_bx_timeline_page_block_title_item_comments', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:11:"bx_timeline";s:6:"method";s:23:"get_block_item_comments";}', 0, 0, 1, 2),
+
+('bx_timeline_manage', 1, 'bx_timeline', '', '_bx_timeline_page_block_title_manage_own', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:11:"bx_timeline";s:6:"method";s:12:"manage_tools";}', 0, 0, 1, 1),
+('bx_timeline_manage', 1, 'bx_timeline', '', '_bx_timeline_page_block_title_muted', 11, 2147483647, 'service', 'a:2:{s:6:"module";s:11:"bx_timeline";s:6:"method";s:15:"get_block_muted";}', 0, 0, 1, 2);
+
+
+-- PAGES: add page block on dashboard
+SET @iPBCellDashboard = 2;
+SET @iPBOrderDashboard = 1; --(SELECT IFNULL(MAX(`order`), 0) FROM `sys_pages_blocks` WHERE `object` = 'sys_dashboard' AND `cell_id` = @iPBCellDashboard LIMIT 1);
+INSERT INTO `sys_pages_blocks` (`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `tabs`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES
+('sys_dashboard', @iPBCellDashboard, 'bx_timeline', '_bx_timeline_page_block_title_system_post_account', '_bx_timeline_page_block_title_post_account', 11, 0, 2147483644, 'service', 'a:2:{s:6:"module";s:11:"bx_timeline";s:6:"method";s:22:"get_block_post_account";}', 0, 1, 0, @iPBOrderDashboard),
+('sys_dashboard', @iPBCellDashboard, 'bx_timeline', '_bx_timeline_page_block_title_system_views_timeline', '_bx_timeline_page_block_title_views_timeline', 11, 1, 2147483644, 'service', 'a:3:{s:6:"module";s:11:"bx_timeline";s:6:"method";s:24:"get_block_views_timeline";s:6:"params";a:1:{i:0;s:4:"feed";}}', 0, 0, 0, @iPBOrderDashboard + 1),
+('sys_dashboard', @iPBCellDashboard, 'bx_timeline', '_bx_timeline_page_block_title_system_views_outline', '_bx_timeline_page_block_title_views_outline', 11, 1, 2147483644, 'service', 'a:3:{s:6:"module";s:11:"bx_timeline";s:6:"method";s:23:"get_block_views_outline";s:6:"params";a:1:{i:0;s:4:"feed";}}', 0, 0, 0, @iPBOrderDashboard + 1);
+
+-- PAGES: add page block on home
+SET @iPBCellHome = 3;
+SET @iPBOrderHome = (SELECT IFNULL(MAX(`order`), 0) FROM `sys_pages_blocks` WHERE `object` = 'sys_home' AND `cell_id` = @iPBCellHome ORDER BY `order` DESC LIMIT 1);
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `tabs`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('sys_home', @iPBCellHome, 'bx_timeline', '_bx_timeline_page_block_title_system_post_home', '_bx_timeline_page_block_title_post_home', 11, 0, 2147483644, 'service', 'a:2:{s:6:"module";s:11:"bx_timeline";s:6:"method";s:19:"get_block_post_home";}', 0, 1, 0, @iPBOrderHome + 1),
+('sys_home', @iPBCellHome, 'bx_timeline', '_bx_timeline_page_block_title_system_views_timeline', '_bx_timeline_page_block_title_views_timeline', 11, 1, 2147483644, 'service', 'a:3:{s:6:"module";s:11:"bx_timeline";s:6:"method";s:24:"get_block_views_timeline";s:6:"params";a:1:{i:0;s:4:"feed";}}', 0, 0, 1, @iPBOrderHome + 2);
+
+SET @iPBCellHome = 4;
+SET @iPBOrderHome = (SELECT IFNULL(MAX(`order`), 0) FROM `sys_pages_blocks` WHERE `object` = 'sys_home' AND `cell_id` = @iPBCellHome ORDER BY `order` DESC LIMIT 1);
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('sys_home', @iPBCellHome, 'bx_timeline', '_bx_timeline_page_block_title_system_view_home_outline', '_bx_timeline_page_block_title_view_home_outline', 0, 1, 'service', 'a:2:{s:6:"module";s:11:"bx_timeline";s:6:"method";s:27:"get_block_view_home_outline";}', 0, 0, 1, @iPBOrderHome + 1);
+
+-- PAGES: add page block to profiles modules (trigger* page objects are processed separately upon modules enable/disable)
+SET @iPBCellProfile = 2;
+INSERT INTO `sys_pages_blocks` (`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES
+('trigger_page_profile_view_entry', @iPBCellProfile, 'bx_timeline', '_bx_timeline_page_block_title_system_post_profile', '_bx_timeline_page_block_title_post_profile', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:11:"bx_timeline";s:6:"method";s:22:"get_block_post_profile";s:6:"params";a:1:{i:0;s:6:"{type}";}}', 0, 0, 1, 0),
+('trigger_page_profile_view_entry', @iPBCellProfile, 'bx_timeline', '_bx_timeline_page_block_title_system_view_profile', '_bx_timeline_page_block_title_view_profile', 0, 2147483647, 'service', 'a:3:{s:6:"module";s:11:"bx_timeline";s:6:"method";s:22:"get_block_view_profile";s:6:"params";a:1:{i:0;s:6:"{type}";}}', 0, 0, 1, 0),
+('trigger_page_profile_view_entry', @iPBCellProfile, 'bx_timeline', '_bx_timeline_page_block_title_system_view_profile_outline', '_bx_timeline_page_block_title_view_profile_outline', 0, 2147483647, 'service', 'a:3:{s:6:"module";s:11:"bx_timeline";s:6:"method";s:30:"get_block_view_profile_outline";s:6:"params";a:1:{i:0;s:6:"{type}";}}', 0, 0, 0, 0);
+
+SET @iPBCellGroup = 4;
+INSERT INTO `sys_pages_blocks` (`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `tabs`, `async`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES
+('trigger_page_group_view_entry', @iPBCellGroup, 'bx_timeline', '_bx_timeline_page_block_title_system_post_profile', '_bx_timeline_page_block_title_post_profile', 11, 0, 0, 2147483647, 'service', 'a:3:{s:6:"module";s:11:"bx_timeline";s:6:"method";s:22:"get_block_post_profile";s:6:"params";a:1:{i:0;s:6:"{type}";}}', 0, 0, 0, 0),
+('trigger_page_group_view_entry', @iPBCellGroup, 'system', '_sys_page_block_title_sys_create_post_context', '_sys_page_block_title_create_post_context', 11, 1, 4, 2147483647, 'service', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:20:"get_create_post_form";s:6:"params";a:1:{i:0;s:12:"{profile_id}";}s:5:"class";s:13:"TemplServices";}', 0, 0, 1, 0),
+('trigger_page_group_view_entry', @iPBCellGroup, 'bx_timeline', '_bx_timeline_page_block_title_system_view_profile', '_bx_timeline_page_block_title_view_profile', 0, 0, 0, 2147483647, 'service', 'a:3:{s:6:"module";s:11:"bx_timeline";s:6:"method";s:22:"get_block_view_profile";s:6:"params";a:1:{i:0;s:6:"{type}";}}', 0, 0, 1, 0),
+('trigger_page_group_view_entry', @iPBCellGroup, 'bx_timeline', '_bx_timeline_page_block_title_system_view_profile_outline', '_bx_timeline_page_block_title_view_profile_outline', 0, 0, 0, 2147483647, 'service', 'a:3:{s:6:"module";s:11:"bx_timeline";s:6:"method";s:30:"get_block_view_profile_outline";s:6:"params";a:1:{i:0;s:6:"{type}";}}', 0, 0, 0, 0);
+
+-- PAGE: module manage all
+INSERT INTO `sys_objects_page`(`object`, `title_system`, `title`, `module`, `layout_id`, `visible_for_levels`, `visible_for_levels_editable`, `uri`, `url`, `meta_description`, `meta_keywords`, `meta_robots`, `cache_lifetime`, `cache_editable`, `deletable`, `override_class_name`, `override_class_file`) VALUES 
+('bx_timeline_administration', '_bx_timeline_page_title_sys_manage_administration', '_bx_timeline_page_title_manage', 'bx_timeline', 5, 192, 1, 'timeline-administration', 'page.php?i=timeline-administration', '', '', '', 0, 1, 0, 'BxTimelinePageBrowse', 'modules/boonex/timeline/classes/BxTimelinePageBrowse.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_timeline_administration', 1, 'bx_timeline', '_bx_timeline_page_block_title_system_manage_administration', '_bx_timeline_page_block_title_manage', 11, 192, 'service', 'a:3:{s:6:\"module\";s:11:\"bx_timeline\";s:6:\"method\";s:12:\"manage_tools\";s:6:\"params\";a:1:{i:0;s:14:\"administration\";}}', 0, 1, 0);
+
+
+-- PAGE: service blocks
+SET @iBlockOrder = (SELECT `order` FROM `sys_pages_blocks` WHERE `object` = '' AND `cell_id` = 0 ORDER BY `order` DESC LIMIT 1);
+INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `title`, `designbox_id`, `tabs`, `visible_for_levels`, `type`, `content`, `deletable`, `copyable`, `active`, `order`) VALUES 
+('', 0, 'bx_timeline', '_bx_timeline_page_block_title_system_views_timeline', '_bx_timeline_page_block_title_views_timeline', 11, 1, 2147483647, 'service', 'a:2:{s:6:"module";s:11:"bx_timeline";s:6:"method";s:24:"get_block_views_timeline";}', 0, 1, 1, @iPBOrderHome + 1),
+('', 0, 'bx_timeline', '_bx_timeline_page_block_title_system_views_outline', '_bx_timeline_page_block_title_views_outline', 11, 1, 2147483647, 'service', 'a:2:{s:6:"module";s:11:"bx_timeline";s:6:"method";s:23:"get_block_views_outline";}', 0, 1, 1, @iPBOrderHome + 2),
+
+('', 0, 'bx_timeline', '_bx_timeline_page_block_title_system_view_home', '_bx_timeline_page_block_title_view_home', 0, 0, 2147483647, 'service', 'a:2:{s:6:"module";s:11:"bx_timeline";s:6:"method";s:19:"get_block_view_home";}', 0, 1, 1, @iBlockOrder + 3),
+('', 0, 'bx_timeline', '_bx_timeline_page_block_title_system_view_home_outline', '_bx_timeline_page_block_title_view_home_outline', 0, 0, 2147483647, 'service', 'a:2:{s:6:"module";s:11:"bx_timeline";s:6:"method";s:27:"get_block_view_home_outline";}', 0, 1, 1, @iBlockOrder + 4),
+
+('', 0, 'bx_timeline', '_bx_timeline_page_block_title_system_view_account', '_bx_timeline_page_block_title_view_account', 0, 0, 2147483644, 'service', 'a:2:{s:6:"module";s:11:"bx_timeline";s:6:"method";s:22:"get_block_view_account";}', 0, 1, 1, @iBlockOrder + 5),
+('', 0, 'bx_timeline', '_bx_timeline_page_block_title_system_view_account_outline', '_bx_timeline_page_block_title_view_account_outline', 0, 0, 2147483644, 'service', 'a:2:{s:6:"module";s:11:"bx_timeline";s:6:"method";s:30:"get_block_view_account_outline";}', 0, 1, 1, @iBlockOrder + 6),
+
+('', 0, 'bx_timeline', '_bx_timeline_page_block_title_system_menu_db', '_bx_timeline_page_block_title_menu_db', 11, 0, 2147483644, 'service', 'a:2:{s:6:"module";s:11:"bx_timeline";s:6:"method";s:17:"get_block_menu_db";}', 0, 1, 1, @iBlockOrder + 7),
+('', 0, 'bx_timeline', '_bx_timeline_page_block_title_system_views_db', '_bx_timeline_page_block_title_views_db', 11, 0, 2147483644, 'service', 'a:2:{s:6:"module";s:11:"bx_timeline";s:6:"method";s:18:"get_block_views_db";}', 0, 1, 1, @iBlockOrder + 8);
+
+
+-- MENU: View
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_timeline_menu_view', '_bx_timeline_menu_title_view', 'bx_timeline_menu_view', 'bx_timeline', 15, 0, 1, 'BxTimelineMenuView', 'modules/boonex/timeline/classes/BxTimelineMenuView.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_timeline_menu_view', 'bx_timeline', '_bx_timeline_menu_set_title_view', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES
+('bx_timeline_menu_view', 'bx_timeline', 'feed', '_bx_timeline_menu_item_title_system_feed', '_bx_timeline_menu_item_title_feed', 'javascript:void(0)', 'javascript:{js_object_view}.changeView(this, ''feed'')', '_self', '', '', 2147483647, 1, 0, 1),
+('bx_timeline_menu_view', 'bx_timeline', 'public', '_bx_timeline_menu_item_title_system_public', '_bx_timeline_menu_item_title_public', 'javascript:void(0)', 'javascript:{js_object_view}.changeView(this, ''public'')', '_self', '', '', 2147483647, 1, 0, 2),
+('bx_timeline_menu_view', 'bx_timeline', 'channels', '_bx_timeline_menu_item_title_system_channels', '_bx_timeline_menu_item_title_channels', 'javascript:void(0)', 'javascript:{js_object_view}.changeView(this, ''channels'')', '_self', '', '', 2147483647, 0, 0, 3),
+('bx_timeline_menu_view', 'bx_timeline', 'hot', '_bx_timeline_menu_item_title_system_hot', '_bx_timeline_menu_item_title_hot', 'javascript:void(0)', 'javascript:{js_object_view}.changeView(this, ''hot'')', '_self', '', '', 2147483647, 1, 0, 4);
+
+-- MENU: Feeds
+INSERT INTO `sys_menu_templates` (`id`, `template`, `title`, `visible`) VALUES
+(ROUND(RAND()*(9999 - 1000) + 1000), 'menu_feeds.html', '_bx_timeline_menu_template_title_feeds', 1);
+SET @iTemplId = (SELECT `id` FROM `sys_menu_templates` WHERE `template`='menu_feeds.html' AND `title`='_bx_timeline_menu_template_title_feeds' LIMIT 1);
+
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_timeline_menu_feeds', '_bx_timeline_menu_title_feeds', 'bx_timeline_menu_feeds', 'bx_timeline', @iTemplId, 0, 1, 'BxTimelineMenuFeeds', 'modules/boonex/timeline/classes/BxTimelineMenuFeeds.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_timeline_menu_feeds', 'bx_timeline', '_bx_timeline_menu_set_title_feeds', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES
+('bx_timeline_menu_feeds', 'bx_timeline', 'feed', '_bx_timeline_menu_item_title_system_feed', '_bx_timeline_menu_item_title_feed', 'javascript:void(0)', 'javascript:{js_object_view}.changeFeed(this, ''feed'')', '_self', '', '', 2147483647, 1, 0, 1),
+('bx_timeline_menu_feeds', 'bx_timeline', 'public', '_bx_timeline_menu_item_title_system_public', '_bx_timeline_menu_item_title_public', 'javascript:void(0)', 'javascript:{js_object_view}.changeFeed(this, ''public'')', '_self', '', '', 2147483647, 1, 0, 2),
+('bx_timeline_menu_feeds', 'bx_timeline', 'hot', '_bx_timeline_menu_item_title_system_hot', '_bx_timeline_menu_item_title_hot', 'javascript:void(0)', 'javascript:{js_object_view}.changeFeed(this, ''hot'')', '_self', '', '', 2147483647, 1, 0, 3),
+('bx_timeline_menu_feeds', 'bx_timeline', 'divider', '_bx_timeline_menu_item_title_system_divider', '', '', '', '', '', '', 2147483647, 1, 1, 4);
+
+-- MENU: Item Share (Repost, Send to Friend, etc)
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_timeline_menu_item_share', '_bx_timeline_menu_title_item_share', 'bx_timeline_menu_item_share', 'bx_timeline', 6, 0, 1, 'BxTimelineMenuItemShare', 'modules/boonex/timeline/classes/BxTimelineMenuItemShare.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_timeline_menu_item_share', 'bx_timeline', '_bx_timeline_menu_set_title_item_share', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES
+('bx_timeline_menu_item_share', 'bx_timeline', 'item-repost', '_bx_timeline_menu_item_title_system_item_repost', '_bx_timeline_menu_item_title_item_repost', 'javascript:void(0)', 'javascript:{repost_onclick}', '_self', 'redo', '', 2147483647, 1, 0, 1),
+('bx_timeline_menu_item_share', 'bx_timeline', 'item-repost-with', '_bx_timeline_menu_item_title_system_item_repost_with', '_bx_timeline_menu_item_title_item_repost_with', 'javascript:void(0)', 'javascript:{repost_with_onclick}', '_self', 'redo', '', 2147483647, 1, 0, 2),
+('bx_timeline_menu_item_share', 'bx_timeline', 'item-repost-to', '_bx_timeline_menu_item_title_system_item_repost_to', '_bx_timeline_menu_item_title_item_repost_to', 'javascript:void(0)', 'javascript:{repost_to_onclick}', '_self', 'redo', '', 2147483647, 1, 0, 3),
+('bx_timeline_menu_item_share', 'bx_timeline', 'item-send', '_bx_timeline_menu_item_title_system_item_send', '_bx_timeline_menu_item_title_item_send', 'page.php?i=start-convo&et={et_send}', '', '_self', 'envelope', '', 2147483647, 1, 0, 4);
+
+-- MENU: Item Manage (Pin, Delete, etc)
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_timeline_menu_item_manage', '_bx_timeline_menu_title_item_manage', 'bx_timeline_menu_item_manage', 'bx_timeline', 20, 0, 1, 'BxTimelineMenuItemManage', 'modules/boonex/timeline/classes/BxTimelineMenuItemManage.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_timeline_menu_item_manage', 'bx_timeline', '_bx_timeline_menu_set_title_item_manage', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('bx_timeline_menu_item_manage', 'bx_timeline', 'item-pin', '_bx_timeline_menu_item_title_system_item_pin', '_bx_timeline_menu_item_title_item_pin', 'javascript:void(0)', 'javascript:{js_object_view}.pinPost(this, {content_id}, 1)', '_self', 'thumbtack', '', 2147483647, 1, 0, 0),
+('bx_timeline_menu_item_manage', 'bx_timeline', 'item-unpin', '_bx_timeline_menu_item_title_system_item_unpin', '_bx_timeline_menu_item_title_item_unpin', 'javascript:void(0)', 'javascript:{js_object_view}.pinPost(this, {content_id}, 0)', '_self', 'thumbtack', '', 2147483647, 1, 0, 1),
+('bx_timeline_menu_item_manage', 'bx_timeline', 'item-stick', '_bx_timeline_menu_item_title_system_item_stick', '_bx_timeline_menu_item_title_item_stick', 'javascript:void(0)', 'javascript:{js_object_view}.stickPost(this, {content_id}, 1)', '_self', 'thumbtack', '', 2147483647, 1, 0, 2),
+('bx_timeline_menu_item_manage', 'bx_timeline', 'item-unstick', '_bx_timeline_menu_item_title_system_item_unstick', '_bx_timeline_menu_item_title_item_unstick', 'javascript:void(0)', 'javascript:{js_object_view}.stickPost(this, {content_id}, 0)', '_self', 'thumbtack', '', 2147483647, 1, 0, 3),
+('bx_timeline_menu_item_manage', 'bx_timeline', 'item-promote', '_bx_timeline_menu_item_title_system_item_promote', '_bx_timeline_menu_item_title_item_promote', 'javascript:void(0)', 'javascript:{js_object_view}.promotePost(this, {content_id}, 1)', '_self', 'certificate ', '', 2147483647, 1, 0, 4),
+('bx_timeline_menu_item_manage', 'bx_timeline', 'item-unpromote', '_bx_timeline_menu_item_title_system_item_unpromote', '_bx_timeline_menu_item_title_item_unpromote', 'javascript:void(0)', 'javascript:{js_object_view}.promotePost(this, {content_id}, 0)', '_self', 'certificate', '', 2147483647, 1, 0, 5),
+('bx_timeline_menu_item_manage', 'bx_timeline', 'item-report', '_bx_timeline_menu_item_title_system_item_report', '', 'javascript:void(0)', '', '', '', '', 2147483647, 1, 0, 6),
+('bx_timeline_menu_item_manage', 'bx_timeline', 'item-notes', '_sys_menu_item_title_system_va_notes', '_sys_menu_item_title_va_notes', 'javascript:void(0)', 'javascript:bx_get_notes(this,  ''{module_uri}'', {content_id});', '_self', 'exclamation-triangle', '', 2147483647, 1, 0, 7),
+('bx_timeline_menu_item_manage', 'bx_timeline', 'item-mute', '_bx_timeline_menu_item_title_system_item_mute', '_bx_timeline_menu_item_title_item_mute', 'javascript:void(0)', 'javascript:{js_object_view}.muteAuthor(this, {content_id})', '_self', 'user-slash', '', 2147483647, 1, 0, 8),
+('bx_timeline_menu_item_manage', 'bx_timeline', 'item-edit', '_bx_timeline_menu_item_title_system_item_edit', '_bx_timeline_menu_item_title_item_edit', 'javascript:void(0)', 'javascript:{js_object_view}.editPost(this, {content_id})', '_self', 'pencil-alt', '', 2147483647, 1, 0, 9),
+('bx_timeline_menu_item_manage', 'bx_timeline', 'item-delete', '_bx_timeline_menu_item_title_system_item_delete', '_bx_timeline_menu_item_title_item_delete', 'javascript:void(0)', 'javascript:{js_object_view}.deletePost(this, {content_id})', '_self', 'remove', '', 2147483647, 1, 0, 10);
+
+-- MENU: Item Actions (Comment, Vote, Share, Report, etc)
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_timeline_menu_item_actions', '_bx_timeline_menu_title_item_actions', 'bx_timeline_menu_item_actions', 'bx_timeline', 15, 0, 1, 'BxTimelineMenuItemActions', 'modules/boonex/timeline/classes/BxTimelineMenuItemActions.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_timeline_menu_item_actions', 'bx_timeline', '_bx_timeline_menu_set_title_item_actions', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `addon`, `submenu_object`, `submenu_popup`, `visible_for_levels`, `active`, `copyable`, `editable`, `order`) VALUES
+('bx_timeline_menu_item_actions', 'bx_timeline', 'item-view', '_bx_timeline_menu_item_title_system_item_view', '', 'javascript:void(0)', '', '', '', '', '', 0, 2147483647, 0, 0, 1, 0),
+('bx_timeline_menu_item_actions', 'bx_timeline', 'item-comment', '_bx_timeline_menu_item_title_system_item_comment', '_bx_timeline_menu_item_title_item_comment', 'javascript:void(0)', 'javascript:{comment_onclick}', '_self', 'comment', '', '', 0, 2147483647, 1, 0, 1, 10),
+('bx_timeline_menu_item_actions', 'bx_timeline', 'item-vote', '_bx_timeline_menu_item_title_system_item_vote', '', 'javascript:void(0)', '', '', '', '', '', 0, 2147483647, 0, 0, 1, 20),
+('bx_timeline_menu_item_actions', 'bx_timeline', 'item-reaction', '_bx_timeline_menu_item_title_system_item_reaction', '', 'javascript:void(0)', '', '', '', '', '', 0, 2147483647, 1, 0, 1, 30),
+('bx_timeline_menu_item_actions', 'bx_timeline', 'item-score', '_bx_timeline_menu_item_title_system_item_score', '', 'javascript:void(0)', '', '', '', '', '', 0, 2147483647, 0, 0, 1, 40),
+('bx_timeline_menu_item_actions', 'bx_timeline', 'item-share', '_bx_timeline_menu_item_title_system_item_share', '_bx_timeline_menu_item_title_item_share', 'javascript:void(0)', 'bx_menu_popup(''bx_timeline_menu_item_share'', this, {''id'':''bx_timeline_menu_item_share_{content_id}''}, {content_id:{content_id}, name:''{name}'', view:''{view}'', type:''{type}''});', '', 'share-alt', '', 'bx_timeline_menu_item_share', 1, 2147483647, 1, 0, 1, 50),
+('bx_timeline_menu_item_actions', 'bx_timeline', 'item-repost', '_bx_timeline_menu_item_title_system_item_repost', '_bx_timeline_menu_item_title_item_repost', 'javascript:void(0)', 'javascript:{repost_onclick}', '', 'redo', '', '', 0, 2147483647, 0, 0, 1, 55),
+('bx_timeline_menu_item_actions', 'bx_timeline', 'item-more', '_bx_timeline_menu_item_title_system_item_more', '_bx_timeline_menu_item_title_item_more', 'javascript:void(0)', 'bx_menu_popup(''bx_timeline_menu_item_manage'', this, {''id'':''bx_timeline_menu_item_manage_{content_id}''}, {content_id:{content_id}, name:''{name}'', view:''{view}'', type:''{type}''});', '', 'ellipsis-v', '', 'bx_timeline_menu_item_manage', 1, 2147483647, 0, 0, 1, 60);
+
+-- MENU: all actions menu for view entry 
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_timeline_menu_item_actions_all', '_bx_timeline_menu_title_item_actions_all', 'bx_timeline_menu_item_actions_all', 'bx_timeline', 15, 0, 0, 'BxTimelineMenuItemActionsAll', 'modules/boonex/timeline/classes/BxTimelineMenuItemActionsAll.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_timeline_menu_item_actions_all', 'bx_timeline', '_bx_timeline_menu_set_title_item_actions_all', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `addon`, `submenu_object`, `submenu_popup`, `visible_for_levels`, `active`, `copyable`, `editable`, `order`) VALUES 
+('bx_timeline_menu_item_actions_all', 'bx_timeline', 'item-view', '_bx_timeline_menu_item_title_system_item_view', '', '', '', '', '', '', '', 0, 2147483647, 0, 0, 1, 0),
+('bx_timeline_menu_item_actions_all', 'bx_timeline', 'item-comment', '_bx_timeline_menu_item_title_system_item_comment', '', '', '', '', '', '', '', 0, 2147483647, 1, 0, 1, 10),
+('bx_timeline_menu_item_actions_all', 'bx_timeline', 'item-vote', '_bx_timeline_menu_item_title_system_item_vote', '', '', '', '', '', '', '', 0, 2147483647, 0, 0, 1, 20),
+('bx_timeline_menu_item_actions_all', 'bx_timeline', 'item-reaction', '_bx_timeline_menu_item_title_system_item_reaction', '', '', '', '', '', '', '', 0, 2147483647, 1, 0, 1, 30),
+('bx_timeline_menu_item_actions_all', 'bx_timeline', 'item-score', '_bx_timeline_menu_item_title_system_item_score', '', '', '', '', '', '', '', 0, 2147483647, 0, 0, 1, 40),
+('bx_timeline_menu_item_actions_all', 'bx_timeline', 'item-share', '_bx_timeline_menu_item_title_system_item_share', '', '', '', '', '', '', '', 0, 2147483647, 1, 0, 1, 50),
+('bx_timeline_menu_item_actions_all', 'bx_timeline', 'item-repost', '_bx_timeline_menu_item_title_system_item_repost', '', '', '', '', '', '', '', 0, 2147483647, 0, 0, 1, 55),
+('bx_timeline_menu_item_actions_all', 'bx_timeline', 'item-pin', '_bx_timeline_menu_item_title_system_item_pin', '', '', '', '', '', '', '', 0, 2147483647, 1, 0, 1, 100),
+('bx_timeline_menu_item_actions_all', 'bx_timeline', 'item-unpin', '_bx_timeline_menu_item_title_system_item_unpin', '', '', '', '', '', '', '', 0, 2147483647, 1, 0, 1, 110),
+('bx_timeline_menu_item_actions_all', 'bx_timeline', 'item-stick', '_bx_timeline_menu_item_title_system_item_stick', '', '', '', '', '', '', '', 0, 2147483647, 1, 0, 1, 120),
+('bx_timeline_menu_item_actions_all', 'bx_timeline', 'item-unstick', '_bx_timeline_menu_item_title_system_item_unstick', '', '', '', '', '', '', '', 0, 2147483647, 1, 0, 1, 130),
+('bx_timeline_menu_item_actions_all', 'bx_timeline', 'item-promote', '_bx_timeline_menu_item_title_system_item_promote', '', '', '', '', '', '', '', 0, 2147483647, 1, 0, 1, 140),
+('bx_timeline_menu_item_actions_all', 'bx_timeline', 'item-unpromote', '_bx_timeline_menu_item_title_system_item_unpromote', '', '', '', '', '', '', '', 0, 2147483647, 1, 0, 1, 150),
+('bx_timeline_menu_item_actions_all', 'bx_timeline', 'item-report', '_bx_timeline_menu_item_title_system_item_report', '', '', '', '', '', '', '', 0, 2147483647, 1, 0, 1, 160),
+('bx_timeline_menu_item_actions_all', 'bx_timeline', 'item-mute', '_bx_timeline_menu_item_title_system_item_mute', '', '', '', '', '', '', '', 0, 2147483647, 1, 0, 1, 165),
+('bx_timeline_menu_item_actions_all', 'bx_timeline', 'item-edit', '_bx_timeline_menu_item_title_system_item_edit', '', '', '', '', '', '', '', 0, 2147483647, 1, 0, 1, 170),
+('bx_timeline_menu_item_actions_all', 'bx_timeline', 'item-delete', '_bx_timeline_menu_item_title_system_item_delete', '', '', '', '', '', '', '', 0, 2147483647, 1, 0, 1, 180),
+('bx_timeline_menu_item_actions_all', 'bx_timeline', 'more-auto', '_sys_menu_item_title_system_va_more_auto', '_sys_menu_item_title_va_more_auto', 'javascript:void(0)', '', '', 'ellipsis-v', '', '', 0, 2147483647, 1, 0, 1, 9999);
+
+-- MENU: Item Counters (Comments, Votes, Reactions, etc)
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_timeline_menu_item_counters', '_bx_timeline_menu_title_item_counters', 'bx_timeline_menu_item_counters', 'bx_timeline', 15, 0, 1, 'BxTimelineMenuItemCounters', 'modules/boonex/timeline/classes/BxTimelineMenuItemCounters.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_timeline_menu_item_counters', 'bx_timeline', '_bx_timeline_menu_set_title_item_counters', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `addon`, `submenu_object`, `submenu_popup`, `visible_for_levels`, `active`, `copyable`, `editable`, `order`) VALUES
+('bx_timeline_menu_item_counters', 'bx_timeline', 'item-view', '_bx_timeline_menu_item_title_system_item_view', '', 'javascript:void(0)', '', '', '', '', '', 0, 2147483647, 0, 0, 1, 0),
+('bx_timeline_menu_item_counters', 'bx_timeline', 'item-vote', '_bx_timeline_menu_item_title_system_item_vote', '', 'javascript:void(0)', '', '', '', '', '', 0, 2147483647, 0, 0, 1, 10),
+('bx_timeline_menu_item_counters', 'bx_timeline', 'item-reaction', '_bx_timeline_menu_item_title_system_item_reaction', '', 'javascript:void(0)', '', '', '', '', '', 0, 2147483647, 1, 0, 1, 20),
+('bx_timeline_menu_item_counters', 'bx_timeline', 'item-score', '_bx_timeline_menu_item_title_system_item_score', '', 'javascript:void(0)', '', '', '', '', '', 0, 2147483647, 0, 0, 1, 30),
+('bx_timeline_menu_item_counters', 'bx_timeline', 'item-comment', '_bx_timeline_menu_item_title_system_item_comment', '', 'javascript:void(0)', '', '', '', '', '', 0, 2147483647, 1, 0, 1, 40),
+('bx_timeline_menu_item_counters', 'bx_timeline', 'item-repost', '_bx_timeline_menu_item_title_system_item_repost', '', 'javascript:void(0)', '', '', '', '', '', 0, 2147483647, 0, 0, 1, 50);
+
+-- MENU: Item Meta Info
+INSERT INTO `sys_objects_menu` (`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES
+('bx_timeline_menu_item_meta', '_sys_menu_title_snippet_meta', 'bx_timeline_menu_item_meta', 'bx_timeline', 15, 0, 1, 'BxTimelineMenuSnippetMeta', 'modules/boonex/timeline/classes/BxTimelineMenuSnippetMeta.php');
+
+INSERT INTO `sys_menu_sets` (`set_name`, `module`, `title`, `deletable`) VALUES
+('bx_timeline_menu_item_meta', 'bx_timeline', '_sys_menu_set_title_snippet_meta', 0);
+
+-- comment meta info menu
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `addon`, `submenu_object`, `submenu_popup`, `visible_for_levels`, `active`, `copyable`, `editable`, `order`) VALUES 
+('bx_timeline_menu_item_meta', 'bx_timeline', 'date', '_sys_menu_item_title_system_sm_date', '_sys_menu_item_title_sm_date', '', '', '', '', '', '', 0, 2147483647, 1, 0, 1, 1),
+('bx_timeline_menu_item_meta', 'bx_timeline', 'membership', '_sys_menu_item_title_system_sm_membership', '_sys_menu_item_title_sm_membership', '', '', '', '', '', '', 0, 2147483647, 0, 0, 1, 2);
+
+-- MENU: Post form attachments (Link, Photo, Video)
+INSERT INTO `sys_objects_menu`(`object`, `title`, `set_name`, `module`, `template_id`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_timeline_menu_post_attachments', '_bx_timeline_menu_title_post_attachments', 'bx_timeline_menu_post_attachments', 'bx_timeline', 23, 0, 1, 'BxTimelineMenuPostAttachments', 'modules/boonex/timeline/classes/BxTimelineMenuPostAttachments.php');
+
+INSERT INTO `sys_menu_sets`(`set_name`, `module`, `title`, `deletable`) VALUES 
+('bx_timeline_menu_post_attachments', 'bx_timeline', '_bx_timeline_menu_set_title_post_attachments', 0);
+
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `addon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `editable`, `order`) VALUES 
+('bx_timeline_menu_post_attachments', 'bx_timeline', 'add-emoji', '_bx_timeline_menu_item_title_system_add_emoji', '_bx_timeline_menu_item_title_add_emoji', 'javascript:void(0)', '', '_self', 'far smile', '', '', 2147483647, 0, 0, 1, 0),
+('bx_timeline_menu_post_attachments', 'bx_timeline', 'add-link', '_bx_timeline_menu_item_title_system_add_link', '_bx_timeline_menu_item_title_add_link', 'javascript:void(0)', 'javascript:{js_object}.showAttachLink(this, {content_id});', '_self', 'link', '', '', 2147483647, 1, 0, 1, 1),
+('bx_timeline_menu_post_attachments', 'bx_timeline', 'add-photo-simple', '_bx_timeline_menu_item_title_system_add_photo_simple', '_bx_timeline_menu_item_title_add_photo', 'javascript:void(0)', 'javascript:{js_object_add_photo_simple}.showUploaderForm();', '_self', 'camera', '', '', 2147483647, 0, 0, 1, 2),
+('bx_timeline_menu_post_attachments', 'bx_timeline', 'add-photo-html5', '_bx_timeline_menu_item_title_system_add_photo_html5', '_bx_timeline_menu_item_title_add_photo', 'javascript:void(0)', 'javascript:{js_object_add_photo_html5}.showUploaderForm();', '_self', 'camera', '', '', 2147483647, 1, 0, 1, 3),
+('bx_timeline_menu_post_attachments', 'bx_timeline', 'add-video-simple', '_bx_timeline_menu_item_title_system_add_video_simple', '_bx_timeline_menu_item_title_add_video', 'javascript:void(0)', 'javascript:{js_object_add_video_simple}.showUploaderForm();', '_self', 'video', '', '', 2147483647, 0, 0, 1, 4),
+('bx_timeline_menu_post_attachments', 'bx_timeline', 'add-video-html5', '_bx_timeline_menu_item_title_system_add_video_html5', '_bx_timeline_menu_item_title_add_video', 'javascript:void(0)', 'javascript:{js_object_add_video_html5}.showUploaderForm();', '_self', 'video', '', '', 2147483647, 1, 0, 1, 5),
+('bx_timeline_menu_post_attachments', 'bx_timeline', 'add-video-record', '_bx_timeline_menu_item_title_system_add_video_record', '_bx_timeline_menu_item_title_add_video_record', 'javascript:void(0)', 'javascript:{js_object_add_video_record}.showUploaderForm();', '_self', 'fas circle', '', '', 2147483647, 1, 0, 1, 6),
+('bx_timeline_menu_post_attachments', 'bx_timeline', 'add-file-simple', '_bx_timeline_menu_item_title_system_add_file_simple', '_bx_timeline_menu_item_title_add_file', 'javascript:void(0)', 'javascript:{js_object_add_file_simple}.showUploaderForm();', '_self', 'file', '', '', 2147483647, 0, 0, 1, 7),
+('bx_timeline_menu_post_attachments', 'bx_timeline', 'add-file-html5', '_bx_timeline_menu_item_title_system_add_file_html5', '_bx_timeline_menu_item_title_add_file', 'javascript:void(0)', 'javascript:{js_object_add_file_html5}.showUploaderForm();', '_self', 'file', '', '', 2147483647, 1, 0, 1, 8);
+
+-- MENU: add to "add content" menu
+SET @iAddMenuOrder = (SELECT `order` FROM `sys_menu_items` WHERE `set_name` = 'sys_add_content_links' AND `active` = 1 ORDER BY `order` DESC LIMIT 1);
+INSERT INTO `sys_menu_items` (`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('sys_add_content_links', 'bx_timeline', 'create-item', '_bx_timeline_menu_item_title_system_create_entry', '_bx_timeline_menu_item_title_create_entry', 'page.php?i=timeline-view', '', '', 'far clock col-green1', '', 2147483647, 1, 1, IFNULL(@iAddMenuOrder, 0) + 1);
+
+-- MENU: add menu item to profiles modules (trigger* menu sets are processed separately upon modules enable/disable)
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('trigger_profile_view_submenu', 'bx_timeline', 'timeline-view', '_bx_timeline_menu_item_title_system_view_timeline_view', '_bx_timeline_menu_item_title_view_timeline_view', 'page.php?i=timeline-view&profile_id={profile_id}', '', '', 'far clock col-green1', '', 2147483647, 1, 0, 0),
+('trigger_group_view_submenu', 'bx_timeline', 'timeline-view', '_bx_timeline_menu_item_title_system_view_timeline_view', '_bx_timeline_menu_item_title_view_timeline_view', 'page.php?i=timeline-view&profile_id={profile_id}', '', '', 'far clock col-green1', '', 2147483647, 1, 0, 0);
+
+-- MENU: profile stats
+SET @iPStatsMenuOrder = (SELECT IFNULL(MAX(`order`), 0) FROM `sys_menu_items` WHERE `set_name` = 'sys_profile_stats' AND `active` = 1 LIMIT 1);
+INSERT INTO `sys_menu_items` (`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `addon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES
+('sys_profile_stats', 'bx_timeline', 'profile-stats-my-timeline', '_bx_timeline_menu_item_title_system_manage_my_timeline', '_bx_timeline_menu_item_title_manage_my_timeline', 'page.php?i=timeline-manage', '', '_self', 'far clock col-green1', 'a:2:{s:6:"module";s:11:"bx_timeline";s:6:"method";s:28:"get_menu_addon_profile_stats";}', '', 2147483646, 1, 0, @iPStatsMenuOrder + 2);
+
+-- MENU: dashboard manage tools
+SET @iManageMenuOrder = (SELECT IFNULL(MAX(`order`), 0) FROM `sys_menu_items` WHERE `set_name`='sys_account_dashboard_manage_tools' LIMIT 1);
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `addon`, `submenu_object`, `visible_for_levels`, `active`, `copyable`, `order`) VALUES 
+('sys_account_dashboard_manage_tools', 'bx_timeline', 'timeline-administration', '_bx_timeline_menu_item_title_system_admt_timeline', '_bx_timeline_menu_item_title_admt_timeline', 'page.php?i=timeline-administration', '', '_self', 'clock', 'a:2:{s:6:"module";s:11:"bx_timeline";s:6:"method";s:27:"get_menu_addon_manage_tools";}', '', 192, 1, 0, @iManageMenuOrder + 1);
+
+-- SETTINGS
+SET @iTypeOrder = (SELECT MAX(`order`) FROM `sys_options_types` WHERE `group` = 'modules');
+INSERT INTO `sys_options_types`(`group`, `name`, `caption`, `icon`, `order`) VALUES 
+('modules', 'bx_timeline', '_bx_timeline', 'bx_timeline@modules/boonex/timeline/|std-icon.svg', IF(ISNULL(@iTypeOrder), 1, @iTypeOrder + 1));
+SET @iTypeId = LAST_INSERT_ID();
+
+-- Category: General
+INSERT INTO `sys_options_categories` (`type_id`, `name`, `caption`, `order`)
+VALUES (@iTypeId, 'bx_timeline_general', '_bx_timeline_options_category_general', 1);
+SET @iCategId = LAST_INSERT_ID();
+
+-- Events hidden by default:
+SET @iHdrIdComment = (SELECT `id` FROM `bx_timeline_handlers` WHERE `group`='comment' AND `type`='insert' AND `alert_unit`='comment' AND `alert_action`='added' LIMIT 1);
+
+INSERT INTO `sys_options` (`name`, `value`, `category_id`, `caption`, `type`, `check`, `check_params`, `check_error`, `extra`, `order`) VALUES
+('bx_timeline_enable_auto_approve', 'on', @iCategId, '_bx_timeline_option_enable_auto_approve', 'checkbox', '', '', '', '', 0),
+('bx_timeline_enable_edit', 'on', @iCategId, '_bx_timeline_option_enable_edit', 'checkbox', '', '', '', '', 1),
+('bx_timeline_enable_delete', 'on', @iCategId, '_bx_timeline_option_enable_delete', 'checkbox', '', '', '', '', 2),
+('bx_timeline_enable_count_all_views', '', @iCategId, '_bx_timeline_option_enable_count_all_views', 'checkbox', '', '', '', '', 3),
+('bx_timeline_enable_repost_own_actions', 'on', @iCategId, '_bx_timeline_option_enable_repost_own_actions', 'checkbox', '', '', '', '', 4),
+('bx_timeline_enable_hide_upon_delete', '', @iCategId, '_bx_timeline_option_enable_hide_upon_delete', 'checkbox', '', '', '', '', 5),
+('bx_timeline_events_hide', CONCAT_WS(',', @iHdrIdComment), @iCategId, '_bx_timeline_option_events_hide', 'rlist', '', '', '', 'a:2:{s:6:"module";s:11:"bx_timeline";s:6:"method";s:21:"get_actions_checklist";}', 6);
+
+-- Category: Browse
+INSERT INTO `sys_options_categories` (`type_id`, `name`, `caption`, `order`)
+VALUES (@iTypeId, 'bx_timeline_browse', '_bx_timeline_options_category_browse', 2);
+SET @iCategId = LAST_INSERT_ID();
+
+INSERT INTO `sys_options` (`name`, `value`, `category_id`, `caption`, `type`, `check`, `check_params`, `check_error`, `extra`, `order`) VALUES
+('bx_timeline_enable_show_all', '', @iCategId, '_bx_timeline_option_enable_show_all', 'checkbox', '', '', '', '', 1),
+('bx_timeline_enable_jump_to_switcher', '', @iCategId, '_bx_timeline_option_enable_jump_to_switcher', 'checkbox', '', '', '', '', 2),
+('bx_timeline_enable_sort_by_reaction', '', @iCategId, '_bx_timeline_option_enable_sort_by_reaction', 'checkbox', '', '', '', '', 3),
+('bx_timeline_enable_sort_by_unread', '', @iCategId, '_bx_timeline_option_enable_sort_by_unread', 'checkbox', '', '', '', '', 4),
+
+('bx_timeline_events_per_page_profile', '12', @iCategId, '_bx_timeline_option_events_per_page_profile', 'digit', '', '', '', '', 10),
+('bx_timeline_events_per_page_account', '12', @iCategId, '_bx_timeline_option_events_per_page_account', 'digit', '', '', '', '', 11),
+('bx_timeline_events_per_page_home', '24', @iCategId, '_bx_timeline_option_events_per_page_home', 'digit', '', '', '', '', 12),
+('bx_timeline_events_per_page', '24', @iCategId, '_bx_timeline_option_events_per_page', 'digit', '', '', '', '', 13),
+('bx_timeline_rss_length', '5', @iCategId, '_bx_timeline_option_rss_length', 'digit', '', '', '', '', 14),
+
+('bx_timeline_enable_infinite_scroll', '', @iCategId, '_bx_timeline_option_enable_infinite_scroll', 'checkbox', '', '', '', '', 20),
+('bx_timeline_events_per_preload', '5', @iCategId, '_bx_timeline_option_events_per_preload', 'digit', '', '', '', '', 21),
+('bx_timeline_auto_preloads', '10', @iCategId, '_bx_timeline_option_auto_preloads', 'digit', '', '', '', '', 22),
+
+('bx_timeline_enable_hot', 'on', @iCategId, '_bx_timeline_option_enable_hot', 'checkbox', '', '', '', '', 30),
+('bx_timeline_hot_sources', 'content,comment,vote', @iCategId, '_bx_timeline_option_hot_sources', 'list', '', '', '', 'a:2:{s:6:"module";s:11:"bx_timeline";s:6:"method";s:25:"get_hot_sources_checklist";}', 31),
+('bx_timeline_hot_threshold_age', '0', @iCategId, '_bx_timeline_option_hot_threshold_age', 'digit', '', '', '', '', 32),
+('bx_timeline_hot_threshold_comment', '1', @iCategId, '_bx_timeline_option_hot_threshold_comment', 'digit', '', '', '', '', 33),
+('bx_timeline_hot_threshold_vote', '2', @iCategId, '_bx_timeline_option_hot_threshold_vote', 'digit', '', '', '', '', 34),
+('bx_timeline_hot_interval', '48', @iCategId, '_bx_timeline_option_hot_interval', 'digit', '', '', '', '', 35);
+
+-- Category: Card
+INSERT INTO `sys_options_categories` (`type_id`, `name`, `caption`, `order`)
+VALUES (@iTypeId, 'bx_timeline_card', '_bx_timeline_options_category_card', 3);
+SET @iCategId = LAST_INSERT_ID();
+
+INSERT INTO `sys_options` (`name`, `value`, `category_id`, `caption`, `type`, `check`, `check_params`, `check_error`, `extra`, `order`) VALUES
+('bx_timeline_enable_brief_cards', '', @iCategId, '_bx_timeline_option_enable_brief_cards', 'checkbox', '', '', '', '', 2),
+('bx_timeline_title_chars', '64', @iCategId, '_bx_timeline_option_title_chars', 'digit', '', '', '', '', 5),
+('bx_timeline_title_chars_short', '32', @iCategId, '_bx_timeline_option_title_chars_short', 'digit', '', '', '', '', 6),
+('bx_timeline_videos_preload', 'auto', @iCategId, '_bx_timeline_option_videos_preload', 'select', '', '', '', 'a:2:{s:6:"module";s:11:"bx_timeline";s:6:"method";s:26:"get_options_videos_preload";}', 10),
+('bx_timeline_videos_autoplay', 'off', @iCategId, '_bx_timeline_option_videos_autoplay', 'select', '', '', '', 'a:2:{s:6:"module";s:11:"bx_timeline";s:6:"method";s:27:"get_options_videos_autoplay";}', 11),
+('bx_timeline_preload_comments', '0', @iCategId, '_bx_timeline_option_preload_comments', 'digit', '', '', '', '', 20),
+('bx_timeline_attachments_layout', 'gallery', @iCategId, '_bx_timeline_option_attachments_layout', 'select', '', '', '', 'a:2:{s:6:"module";s:11:"bx_timeline";s:6:"method";s:30:"get_options_attachments_layout";}', 30);
+
+-- Category: Cache
+INSERT INTO `sys_options_categories` (`type_id`, `name`, `caption`, `order`)
+VALUES (@iTypeId, 'bx_timeline_cache', '_bx_timeline_options_category_cache', 4);
+SET @iCategId = LAST_INSERT_ID();
+
+INSERT INTO `sys_options` (`name`, `value`, `category_id`, `caption`, `type`, `check`, `check_params`, `check_error`, `extra`, `order`) VALUES
+('bx_timeline_enable_cache_item', 'on', @iCategId, '_bx_timeline_option_enable_cache_item', 'checkbox', '', '', '', '', 1),
+('bx_timeline_cache_item_engine', 'File', @iCategId, '_bx_timeline_option_cache_item_engine', 'select', '', '', '', 'File,Memcache,APC,XCache', 2),
+('bx_timeline_cache_item_lifetime', '604800', @iCategId, '_bx_timeline_option_cache_item_lifetime', 'digit', '', '', '', '', 3);
+
+-- Category: Post form
+INSERT INTO `sys_options_categories` (`type_id`, `name`, `caption`, `order`)
+VALUES (@iTypeId, 'bx_timeline_post', '_bx_timeline_options_category_post', 5);
+SET @iCategId = LAST_INSERT_ID();
+
+INSERT INTO `sys_options` (`name`, `value`, `category_id`, `caption`, `type`, `check`, `check_params`, `check_error`, `extra`, `order`) VALUES
+('bx_timeline_enable_editor_toolbar', '', @iCategId, '_bx_timeline_option_enable_editor_toolbar', 'checkbox', '', '', '', '', 1),
+('bx_timeline_editor_auto_attach_insertion', '', @iCategId, '_bx_timeline_option_editor_auto_attach_insertion', 'checkbox', '', '', '', '', 2),
+('bx_timeline_limit_attach_links', '0', @iCategId, '_bx_timeline_option_limit_attach_links', 'digit', '', '', '', '', 10);
+
+
+-- PRIVACY 
+INSERT INTO `sys_objects_privacy` (`object`, `module`, `action`, `title`, `default_group`, `table`, `table_field_id`, `table_field_author`, `override_class_name`, `override_class_file`) VALUES
+('bx_timeline_privacy_view', 'bx_timeline', 'view', '_bx_timeline_privacy_view', '3', 'bx_timeline_events', 'id', 'owner_id', 'BxTimelinePrivacy', 'modules/boonex/timeline/classes/BxTimelinePrivacy.php');
+
+
+-- ACL
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_timeline', 'post', NULL, '_bx_timeline_acl_action_post', '', 1, 3);
+SET @iIdActionPost = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_timeline', 'edit', NULL, '_bx_timeline_acl_action_edit', '', 1, 3);
+SET @iIdActionEdit = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_timeline', 'delete', NULL, '_bx_timeline_acl_action_delete', '', 1, 3);
+SET @iIdActionDelete = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_timeline', 'vote', NULL, '_bx_timeline_acl_action_vote', '', 1, 0);
+SET @iIdActionVote = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_timeline', 'repost', NULL, '_bx_timeline_acl_action_repost', '', 1, 3);
+SET @iIdActionRepost = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_timeline', 'send', NULL, '_bx_timeline_acl_action_send', '', 1, 3);
+SET @iIdActionSend = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_timeline', 'mute', NULL, '_bx_timeline_acl_action_mute', '', 1, 3);
+SET @iIdActionMute = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_timeline', 'pin', NULL, '_bx_timeline_acl_action_pin', '', 1, 3);
+SET @iIdActionPin = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_timeline', 'stick', NULL, '_bx_timeline_acl_action_stick', '', 1, 3);
+SET @iIdActionStick = LAST_INSERT_ID();
+
+INSERT INTO `sys_acl_actions` (`Module`, `Name`, `AdditionalParamName`, `Title`, `Desc`, `Countable`, `DisabledForLevels`) VALUES
+('bx_timeline', 'promote', NULL, '_bx_timeline_acl_action_promote', '', 1, 3);
+SET @iIdActionPromote = LAST_INSERT_ID();
+
+SET @iUnauthenticated = 1;
+SET @iAccount = 2;
+SET @iStandard = 3;
+SET @iUnconfirmed = 4;
+SET @iPending = 5;
+SET @iSuspended = 6;
+SET @iModerator = 7;
+SET @iAdministrator = 8;
+SET @iPremium = 9;
+
+INSERT INTO `sys_acl_matrix` (`IDLevel`, `IDAction`) VALUES
+
+-- post
+(@iStandard, @iIdActionPost),
+(@iModerator, @iIdActionPost),
+(@iAdministrator, @iIdActionPost),
+(@iPremium, @iIdActionPost),
+
+-- edit any post
+(@iModerator, @iIdActionEdit),
+(@iAdministrator, @iIdActionEdit),
+
+-- delete any post
+(@iModerator, @iIdActionDelete),
+(@iAdministrator, @iIdActionDelete),
+
+-- vote
+(@iStandard, @iIdActionVote),
+(@iModerator, @iIdActionVote),
+(@iAdministrator, @iIdActionVote),
+(@iPremium, @iIdActionVote),
+
+-- repost
+(@iStandard, @iIdActionRepost),
+(@iModerator, @iIdActionRepost),
+(@iAdministrator, @iIdActionRepost),
+(@iPremium, @iIdActionRepost),
+
+-- send
+(@iStandard, @iIdActionSend),
+(@iModerator, @iIdActionSend),
+(@iAdministrator, @iIdActionSend),
+(@iPremium, @iIdActionSend),
+
+-- mute
+(@iStandard, @iIdActionMute),
+(@iModerator, @iIdActionMute),
+(@iAdministrator, @iIdActionMute),
+(@iPremium, @iIdActionMute),
+
+-- pin any post
+(@iModerator, @iIdActionPin),
+(@iAdministrator, @iIdActionPin),
+
+-- stick any post
+(@iModerator, @iIdActionStick),
+(@iAdministrator, @iIdActionStick),
+
+-- promote any post
+(@iModerator, @iIdActionPromote),
+(@iAdministrator, @iIdActionPromote);
+
+
+-- ALERTS
+INSERT INTO `sys_alerts_handlers`(`name`, `class`, `file`, `service_call`) VALUES 
+('bx_timeline', 'BxTimelineResponse', 'modules/boonex/timeline/classes/BxTimelineResponse.php', '');
+SET @iHandler := LAST_INSERT_ID();
+
+INSERT INTO `sys_alerts` (`unit`, `action`, `handler_id`) VALUES
+('system', 'clear_cache', @iHandler),
+('system', 'enable', @iHandler),
+('system', 'disable', @iHandler),
+
+('account', 'confirm', @iHandler),
+('account', 'unconfirm', @iHandler),
+
+('profile', 'approve', @iHandler),
+('profile', 'disapprove', @iHandler),
+('profile', 'activate', @iHandler),
+('profile', 'suspend', @iHandler),
+('profile', 'delete', @iHandler),
+
+('comment', 'added', @iHandler),
+('comment', 'edited', @iHandler),
+('comment', 'deleted', @iHandler),
+
+('bx_timeline_videos_mp4', 'transcoded', @iHandler);
+
+
+-- SEARCH
+SET @iSearchOrder = (SELECT IFNULL(MAX(`Order`), 0) FROM `sys_objects_search`);
+INSERT INTO `sys_objects_search` (`ObjectName`, `Title`, `Order`, `ClassName`, `ClassPath`) VALUES
+('bx_timeline', '_bx_timeline', @iSearchOrder + 1, 'BxTimelineSearchResult', 'modules/boonex/timeline/classes/BxTimelineSearchResult.php'),
+('bx_timeline_cmts', '_bx_timeline_cmts', @iSearchOrder + 2, 'BxTimelineCmtsSearchResult', 'modules/boonex/timeline/classes/BxTimelineCmtsSearchResult.php');
+
+
+-- GRIDS: connection mute
+INSERT INTO `sys_objects_grid` (`object`, `source_type`, `source`, `table`, `field_id`, `field_order`, `field_active`, `paginate_url`, `paginate_per_page`, `paginate_simple`, `paginate_get_start`, `paginate_get_per_page`, `filter_fields`, `filter_fields_translatable`, `filter_mode`, `sorting_fields`, `sorting_fields_translatable`, `visible_for_levels`, `responsive`, `override_class_name`, `override_class_file`) VALUES
+('bx_timeline_mute', 'Sql', 'SELECT `p`.`id`, `c`.`added`, `c`.`mutual` FROM `sys_profiles` AS `p` INNER JOIN `sys_accounts` AS `a` ON (`a`.`id` = `p`.`account_id`) {join_connections}', 'sys_profiles', 'id', 'c`.`added', '', '', 10, NULL, 'start', '', 'name,email', '', 'auto', '', '', 2147483647, 0, 'BxTimelineGridMute', 'modules/boonex/timeline/classes/BxTimelineGridMute.php');
+
+INSERT INTO `sys_grid_fields` (`object`, `name`, `title`, `width`, `params`, `hidden_on`, `order`) VALUES
+('bx_timeline_mute', 'name', '_sys_name', '60%', '', '', 1),
+('bx_timeline_mute', 'info', '', '20%', '', '1', 2),
+('bx_timeline_mute', 'actions', '', '20%', '', '', 3);
+
+INSERT INTO `sys_grid_actions` (`object`, `type`, `name`, `title`, `icon`, `icon_only`, `confirm`, `order`) VALUES
+('bx_timeline_mute', 'single', 'delete', '', 'remove', 0, 1, 2);
+
+-- GRIDS: moderation tools
+INSERT INTO `sys_objects_grid` (`object`, `source_type`, `source`, `table`, `field_id`, `field_order`, `field_active`, `paginate_url`, `paginate_per_page`, `paginate_simple`, `paginate_get_start`, `paginate_get_per_page`, `filter_fields`, `filter_fields_translatable`, `filter_mode`, `sorting_fields`, `sorting_fields_translatable`, `visible_for_levels`, `override_class_name`, `override_class_file`) VALUES
+('bx_timeline_administration', 'Sql', 'SELECT * FROM `bx_timeline_events` WHERE 1 AND `active`=''1'' ', 'bx_timeline_events', 'id', 'date', 'status_admin', '', 20, NULL, 'start', '', 'title,description', '', 'like', 'reports', '', 192, 'BxTimelineGridAdministration', 'modules/boonex/timeline/classes/BxTimelineGridAdministration.php'),
+('bx_timeline_common', 'Sql', 'SELECT * FROM `bx_timeline_events` WHERE 1 AND `active`=''1'' ', 'bx_timeline_events', 'id', 'date', 'status', '', 20, NULL, 'start', '', 'title,description', '', 'like', '', '', 2147483647, 'BxTimelineGridCommon', 'modules/boonex/timeline/classes/BxTimelineGridCommon.php');
+
+INSERT INTO `sys_grid_fields` (`object`, `name`, `title`, `width`, `translatable`, `chars_limit`, `params`, `order`) VALUES
+('bx_timeline_administration', 'checkbox', '_sys_select', '2%', 0, '', '', 1),
+('bx_timeline_administration', 'switcher', '_bx_timeline_grid_column_title_adm_active', '8%', 0, '', '', 2),
+('bx_timeline_administration', 'reports', '_sys_txt_reports_title', '5%', 0, '', '', 3),
+('bx_timeline_administration', 'description', '_bx_timeline_grid_column_title_adm_description', '25%', 0, '25', '', 4),
+('bx_timeline_administration', 'date', '_bx_timeline_grid_column_title_adm_added', '20%', 1, '25', '', 5),
+('bx_timeline_administration', 'owner_id', '_bx_timeline_grid_column_title_adm_author', '20%', 0, '25', '', 6),
+('bx_timeline_administration', 'actions', '', '20%', 0, '', '', 7),
+
+('bx_timeline_common', 'checkbox', '_sys_select', '2%', 0, 0, '', 1),
+('bx_timeline_common', 'switcher', '_bx_timeline_grid_column_title_adm_active', '8%', 0, 0, '', 2),
+('bx_timeline_common', 'description', '_bx_timeline_grid_column_title_adm_description', '30%', 0, 25, '', 3),
+('bx_timeline_common', 'date', '_bx_timeline_grid_column_title_adm_added', '20%', 1, 25, '', 4),
+('bx_timeline_common', 'status_admin', '_bx_posts_grid_column_title_adm_status_admin', '20%', 0, 16, '', 5),
+('bx_timeline_common', 'actions', '', '20%', 0, 0, '', 6);
+
+INSERT INTO `sys_grid_actions` (`object`, `type`, `name`, `title`, `icon`, `icon_only`, `confirm`, `order`) VALUES
+('bx_timeline_administration', 'bulk', 'delete', '_bx_timeline_grid_action_title_adm_delete', '', 0, 1, 1),
+('bx_timeline_administration', 'single', 'delete', '_bx_timeline_grid_action_title_adm_delete', 'remove', 1, 1, 2),
+('bx_timeline_administration', 'single', 'audit_content', '_bx_timeline_grid_action_title_adm_audit_content', 'search', 1, 0, 4),
+
+('bx_timeline_common', 'bulk', 'delete', '_bx_timeline_grid_action_title_adm_delete', '', 0, 1, 1),
+('bx_timeline_common', 'single', 'delete', '_bx_timeline_grid_action_title_adm_delete', 'remove', 1, 1, 2);
+
+
+-- METATAGS
+INSERT INTO `sys_objects_metatags` (`object`, `module`, `table_keywords`, `table_locations`, `table_mentions`, `override_class_name`, `override_class_file`) VALUES
+('bx_timeline', 'bx_timeline', 'bx_timeline_meta_keywords', 'bx_timeline_meta_locations', 'bx_timeline_meta_mentions', '', '');
+
+
+-- CONNECTIONS
+INSERT INTO `sys_objects_connection` (`object`, `table`, `profile_initiator`, `profile_content`, `type`, `override_class_name`, `override_class_file`) VALUES
+('bx_timeline_mute', 'bx_timeline_mute', 1, 1, 'one-way', '', '');
+
+
+-- EMAIL TEMPLATES
+INSERT INTO `sys_email_templates` (`Module`, `NameSystem`, `Name`, `Subject`, `Body`) VALUES 
+('bx_timeline', '_bx_timeline_et_txt_name_send', 'bx_timeline_send', '_bx_timeline_et_txt_subject_send', '_bx_timeline_et_txt_body_send');
+
+
+-- CRON
+INSERT INTO `sys_cron_jobs` (`name`, `time`, `class`, `file`, `service_call`) VALUES
+('bx_timeline_hot', '0 * * * *', 'BxTimelineCronHot', 'modules/boonex/timeline/classes/BxTimelineCronHot.php', ''),
+('bx_timeline_publishing', '* * * * *', 'BxTimelineCronPublishing', 'modules/boonex/timeline/classes/BxTimelineCronPublishing.php', ''),
+('bx_timeline_clean', '0 0 * * *', 'BxTimelineCronClean', 'modules/boonex/timeline/classes/BxTimelineCronClean.php', '');
+
+
+-- PRELOADER
+SET @iOrderPreloader = (SELECT IFNULL(MAX(`order`), 9999) FROM `sys_preloader` WHERE `type`='js_system' AND `order` > 9999 LIMIT 1);
+INSERT INTO `sys_preloader`(`module`, `type`, `content`, `active`, `order`) VALUES
+('bx_timeline', 'js_system', 'modules/boonex/timeline/js/|modernizr.min.js', 1, @iOrderPreloader + 1);

+ 667 - 0
modules/boonex/timeline/updates/13.0.4_13.0.5/source/install/sql/install.sql

@@ -0,0 +1,667 @@
+SET @sName = 'bx_timeline';
+
+-- TABLES
+CREATE TABLE IF NOT EXISTS `bx_timeline_events` (
+  `id` int(11) NOT NULL auto_increment,
+  `owner_id` int(11) NOT NULL default '0',
+  `system` tinyint(4) NOT NULL default '1',
+  `type` varchar(255) NOT NULL,
+  `action` varchar(255) NOT NULL,
+  `object_id` int(11) NOT NULL default '0',
+  `object_owner_id` int(11) NOT NULL default '0',
+  `object_privacy_view` varchar(16) NOT NULL default '3',
+  `object_cf` int(11) NOT NULL default '1',
+  `content` text NOT NULL,
+  `title` varchar(255) NOT NULL,
+  `description` text NOT NULL,
+  `location` text NOT NULL,
+  `views` int(11) unsigned NOT NULL default '0',
+  `rate` float NOT NULL default '0',
+  `votes` int(11) unsigned 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',
+  `comments` int(11) unsigned NOT NULL default '0',
+  `reports` int(11) unsigned NOT NULL default '0',
+  `reposts` int(11) unsigned NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  `published` int(11) NOT NULL default '0',
+  `reacted` int(11) NOT NULL default '0',
+  `status` enum ('active', 'awaiting', 'failed', 'hidden', 'deleted') NOT NULL DEFAULT 'active',
+  `status_admin` enum('active','hidden','pending') NOT NULL DEFAULT 'active',
+  `active` tinyint(4) NOT NULL default '1',
+  `pinned` int(11) NOT NULL default '0',
+  `sticked` int(11) NOT NULL default '0',
+  `promoted` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `owner_id` (`owner_id`),
+  KEY `object_id` (`object_id`),
+  FULLTEXT KEY `search_fields` (`title`, `description`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_timeline_events2users` (
+  `id` int(11) NOT NULL auto_increment,
+  `user_id` int(11) NOT NULL DEFAULT '0',
+  `event_id` int(11) NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`),
+  UNIQUE `view` (`user_id`, `event_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_timeline_handlers` (
+  `id` int(11) NOT NULL auto_increment,
+  `group` varchar(64) NOT NULL default '',
+  `type` enum('insert','update','delete') NOT NULL DEFAULT 'insert',
+  `alert_unit` varchar(64) NOT NULL default '',
+  `alert_action` varchar(64) NOT NULL default '',
+  `content` text NOT NULL,
+  `privacy` varchar(64) NOT NULL default '',
+  PRIMARY KEY (`id`),
+  UNIQUE `handler` (`group`, `type`),
+  UNIQUE `alert` (`alert_unit`, `alert_action`)
+);
+
+INSERT INTO `bx_timeline_handlers`(`group`, `type`, `alert_unit`, `alert_action`, `content`) VALUES
+('common_post', 'insert', 'timeline_common_post', '', ''),
+('common_repost', 'insert', 'timeline_common_repost', '', ''),
+
+('profile', 'delete', 'profile', 'delete', ''),
+
+('comment', 'insert', 'comment', 'added', 'a:5:{s:11:"module_name";s:6:"system";s:13:"module_method";s:17:"get_timeline_post";s:12:"module_class";s:17:"TemplCmtsServices";s:9:"groupable";i:0;s:8:"group_by";s:0:"";}'),
+('comment', 'update', 'comment', 'edited', ''),
+('comment', 'delete', 'comment', 'deleted', '');
+
+-- TABLE: mute
+CREATE TABLE IF NOT EXISTS `bx_timeline_mute` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `initiator` int(11) NOT NULL,
+  `content` int(11) NOT NULL,
+  `mutual` tinyint(4) NOT NULL,
+  `added` int(10) unsigned NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `initiator` (`initiator`,`content`),
+  KEY `content` (`content`)
+);
+
+-- TABLES: STORAGES, TRANSCODERS, UPLOADERS
+CREATE TABLE IF NOT EXISTS `bx_timeline_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_timeline_photos_processed` (
+  `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_timeline_photos2events` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `event_id` int(11) NOT NULL DEFAULT '0',
+  `media_id` int(11) NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `media` (`event_id`, `media_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_timeline_videos` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `profile_id` int(10) unsigned NOT NULL,
+  `remote_id` varchar(128) NOT NULL,
+  `path` varchar(255) NOT NULL,
+  `file_name` varchar(255) NOT NULL,
+  `mime_type` varchar(128) NOT NULL,
+  `ext` varchar(32) NOT NULL,
+  `size` bigint(20) NOT NULL,
+  `dimensions` varchar(12) NOT NULL,
+  `added` int(11) NOT NULL,
+  `modified` int(11) NOT NULL,
+  `private` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `remote_id` (`remote_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_timeline_videos_processed` (
+  `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_timeline_videos2events` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `event_id` int(11) NOT NULL DEFAULT '0',
+  `media_id` int(11) NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `media` (`event_id`, `media_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_timeline_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_timeline_files2events` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `event_id` int(11) NOT NULL DEFAULT '0',
+  `media_id` int(11) NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `media` (`event_id`, `media_id`)
+);
+
+-- TABLES: LINKS
+CREATE TABLE IF NOT EXISTS `bx_timeline_links` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `profile_id` int(10) unsigned NOT NULL,
+  `media_id` int(11) NOT NULL DEFAULT '0',
+  `url` varchar(255) NOT NULL,
+  `title` varchar(255) NOT NULL,
+  `text` text NOT NULL,
+  `added` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  KEY `profile_id` (`profile_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_timeline_links2events` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `event_id` int(11) NOT NULL DEFAULT '0',
+  `link_id` int(11) NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `link` (`link_id`, `event_id`)
+);
+
+-- TABLES: REPOSTS
+CREATE TABLE IF NOT EXISTS `bx_timeline_reposts_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `event_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `author_nip` int(11) unsigned NOT NULL default '0',
+  `reposted_id` int(11) NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  `active` tinyint(4) NOT NULL default '1',
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `event_id` (`event_id`),
+  KEY `repost` (`reposted_id`, `author_nip`)
+);
+
+-- TABLES: COMMENTS
+CREATE TABLE IF NOT EXISTS `bx_timeline_comments` (
+  `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_time` int(11) unsigned NOT NULL DEFAULT '0',
+  `cmt_replies` int(11) NOT NULL DEFAULT '0',
+  `cmt_pinned` int(11) NOT NULL default '0',
+  `cmt_cf` int(11) NOT NULL default '1',
+  PRIMARY KEY (`cmt_id`),
+  KEY `cmt_object_id` (`cmt_object_id`,`cmt_parent_id`),
+  FULLTEXT KEY `search_fields` (`cmt_text`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_timeline_cmts_notes` (
+  `cmt_id` int(11) NOT NULL AUTO_INCREMENT,
+  `cmt_parent_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_vparent_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_object_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_author_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_level` int(11) NOT NULL DEFAULT '0',
+  `cmt_text` text NOT NULL,
+  `cmt_mood` tinyint(4) NOT NULL DEFAULT '0',
+  `cmt_rate` int(11) NOT NULL DEFAULT '0',
+  `cmt_rate_count` int(11) NOT NULL DEFAULT '0',
+  `cmt_time` int(11) unsigned NOT NULL DEFAULT '0',
+  `cmt_replies` int(11) NOT NULL DEFAULT '0',
+  `cmt_pinned` int(11) NOT NULL default '0',
+  PRIMARY KEY (`cmt_id`),
+  KEY `cmt_object_id` (`cmt_object_id`,`cmt_parent_id`),
+  FULLTEXT KEY `search_fields` (`cmt_text`)
+);
+
+-- TABLE: views
+CREATE TABLE IF NOT EXISTS `bx_timeline_views_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `viewer_id` int(11) NOT NULL default '0',
+  `viewer_nip` int(11) unsigned NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `id` (`object_id`,`viewer_id`,`viewer_nip`)
+);
+
+-- TABLES: VOTES
+CREATE TABLE IF NOT EXISTS `bx_timeline_votes` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `count` int(11) NOT NULL default '0',
+  `sum` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `object_id` (`object_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_timeline_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_timeline_reactions` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `reaction` varchar(32) NOT NULL default '',
+  `count` int(11) NOT NULL default '0',
+  `sum` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `reaction` (`object_id`, `reaction`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_timeline_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 IF NOT EXISTS `bx_timeline_meta_keywords` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(10) unsigned NOT NULL,
+  `keyword` varchar(255) NOT NULL,
+  PRIMARY KEY (`id`),
+  KEY `object_id` (`object_id`),
+  KEY `keyword` (`keyword`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_timeline_meta_locations` (
+  `object_id` int(10) unsigned NOT NULL,
+  `lat` double NOT NULL,
+  `lng` double NOT NULL,
+  `country` varchar(2) NOT NULL,
+  `state` varchar(255) NOT NULL,
+  `city` varchar(255) NOT NULL,
+  `zip` varchar(255) NOT NULL,
+  `street` varchar(255) NOT NULL,
+  `street_number` varchar(255) NOT NULL,
+  PRIMARY KEY (`object_id`),
+  KEY `country_state_city` (`country`,`state`(8),`city`(8))
+);
+
+CREATE TABLE IF NOT EXISTS `bx_timeline_meta_mentions` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(10) unsigned NOT NULL,
+  `profile_id` int(10) unsigned NOT NULL,
+  PRIMARY KEY (`id`),
+  KEY `object_id` (`object_id`),
+  KEY `profile_id` (`profile_id`)
+);
+
+-- TABLE: reports
+CREATE TABLE IF NOT EXISTS `bx_timeline_reports` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `count` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `object_id` (`object_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_timeline_reports_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `author_nip` int(11) unsigned NOT NULL default '0',
+  `type` varchar(32) NOT NULL default '',
+  `text` text NOT NULL default '',
+  `date` int(11) NOT NULL default '0',
+  `checked_by` int(11) NOT NULL default '0',
+  `status` tinyint(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `report` (`object_id`, `author_nip`)
+);
+
+-- TABLE: hot track
+CREATE TABLE IF NOT EXISTS `bx_timeline_hot_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `event_id` int(11) NOT NULL default '0',
+  `value` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `event_id` (`event_id`)
+);
+
+-- TABLE: scores
+CREATE TABLE IF NOT EXISTS `bx_timeline_scores` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `count_up` int(11) NOT NULL default '0',
+  `count_down` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `object_id` (`object_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_timeline_scores_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `author_nip` int(11) unsigned NOT NULL default '0',
+  `type` varchar(8) NOT NULL default '',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `vote` (`object_id`, `author_nip`)
+);
+
+
+-- STORAGES, TRANSCODERS, UPLOADERS
+SET @sStorageEngine = (SELECT `value` FROM `sys_options` WHERE `name` = 'sys_storage_default');
+
+INSERT INTO `sys_objects_uploader` (`object`, `active`, `override_class_name`, `override_class_file`) VALUES
+('bx_timeline_simple_photo', 1, 'BxTimelineUploaderSimpleAttach', 'modules/boonex/timeline/classes/BxTimelineUploaderSimpleAttach.php'),
+('bx_timeline_simple_video', 1, 'BxTimelineUploaderSimpleAttach', 'modules/boonex/timeline/classes/BxTimelineUploaderSimpleAttach.php'),
+('bx_timeline_html5_photo', 1, 'BxTimelineUploaderHTML5Attach', 'modules/boonex/timeline/classes/BxTimelineUploaderHTML5Attach.php'),
+('bx_timeline_html5_video', 1, 'BxTimelineUploaderHTML5Attach', 'modules/boonex/timeline/classes/BxTimelineUploaderHTML5Attach.php'),
+('bx_timeline_record_video', 1, 'BxTimelineUploaderRecordVideoAttach', 'modules/boonex/timeline/classes/BxTimelineUploaderRecordVideoAttach.php'),
+('bx_timeline_simple_file', 1, 'BxTimelineUploaderSimpleAttach', 'modules/boonex/timeline/classes/BxTimelineUploaderSimpleAttach.php'),
+('bx_timeline_html5_file', 1, 'BxTimelineUploaderHTML5Attach', 'modules/boonex/timeline/classes/BxTimelineUploaderHTML5Attach.php');
+
+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_timeline_photos', @sStorageEngine, '', 360, 2592000, 3, 'bx_timeline_photos', 'allow-deny', 'jpg,jpeg,jpe,gif,png', '', 0, 0, 0, 0, 0, 0),
+('bx_timeline_photos_processed', @sStorageEngine, '', 360, 2592000, 3, 'bx_timeline_photos_processed', 'allow-deny', 'jpg,jpeg,jpe,gif,png', '', 0, 0, 0, 0, 0, 0),
+
+('bx_timeline_videos', @sStorageEngine, 'a:1:{s:6:"fields";a:1:{s:10:"dimensions";s:17:"getFileDimensions";}}', 360, 2592000, 3, 'bx_timeline_videos', '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_timeline_videos_processed', @sStorageEngine, '', 360, 2592000, 3, 'bx_timeline_videos_processed', '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_timeline_files', @sStorageEngine, '', 360, 2592000, 3, 'bx_timeline_files', 'deny-allow', '', 'jpg,jpeg,jpe,gif,png,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_timeline_photos_preview', 'bx_timeline_photos_processed', 'Storage', 'a:1:{s:6:"object";s:18:"bx_timeline_photos";}', 'no', '1', '2592000', '0', '', ''),
+('bx_timeline_photos_view', 'bx_timeline_photos_processed', 'Storage', 'a:1:{s:6:"object";s:18:"bx_timeline_photos";}', 'no', '1', '2592000', '0', '', ''),
+('bx_timeline_photos_medium', 'bx_timeline_photos_processed', 'Storage', 'a:1:{s:6:"object";s:18:"bx_timeline_photos";}', 'no', '1', '2592000', '0', '', ''),
+('bx_timeline_photos_big', 'bx_timeline_photos_processed', 'Storage', 'a:1:{s:6:"object";s:18:"bx_timeline_photos";}', 'no', '1', '2592000', '0', '', ''),
+
+('bx_timeline_videos_photo_preview', 'bx_timeline_videos_processed', 'Storage', 'a:1:{s:6:"object";s:18:"bx_timeline_videos";}', 'no', '1', '2592000', '0', '', ''),
+('bx_timeline_videos_photo_view', 'bx_timeline_videos_processed', 'Storage', 'a:1:{s:6:"object";s:18:"bx_timeline_videos";}', 'no', '1', '2592000', '0', '', ''),
+('bx_timeline_videos_photo_big', 'bx_timeline_videos_processed', 'Storage', 'a:1:{s:6:"object";s:18:"bx_timeline_videos";}', 'no', '1', '2592000', '0', '', ''),
+('bx_timeline_videos_poster_preview', 'bx_timeline_videos_processed', 'Storage', 'a:1:{s:6:"object";s:18:"bx_timeline_videos";}', 'no', '0', '0', '0', 'BxDolTranscoderVideo', ''),
+('bx_timeline_videos_poster_view', 'bx_timeline_videos_processed', 'Storage', 'a:1:{s:6:"object";s:18:"bx_timeline_videos";}', 'no', '0', '0', '0', 'BxDolTranscoderVideo', ''),
+('bx_timeline_videos_poster_big', 'bx_timeline_videos_processed', 'Storage', 'a:1:{s:6:"object";s:18:"bx_timeline_videos";}', 'no', '0', '0', '0', 'BxDolTranscoderVideo', ''),
+('bx_timeline_videos_mp4', 'bx_timeline_videos_processed', 'Storage', 'a:1:{s:6:"object";s:18:"bx_timeline_videos";}', 'no', '0', '0', '0', 'BxDolTranscoderVideo', ''),
+('bx_timeline_videos_mp4_hd', 'bx_timeline_videos_processed', 'Storage', 'a:1:{s:6:"object";s:18:"bx_timeline_videos";}', 'no', '0', '0', '0', 'BxDolTranscoderVideo', ''),
+
+('bx_timeline_proxy_preview', 'bx_timeline_videos_processed', 'Proxy', 'a:4:{s:6:"object";s:18:"bx_timeline_videos";s:5:"image";s:32:"bx_timeline_videos_photo_preview";s:12:"video_poster";s:33:"bx_timeline_videos_poster_preview";s:5:"video";a:4:{i:0;s:22:"bx_timeline_videos_mp4";i:1;s:25:"bx_timeline_videos_mp4_hd";i:2;s:30:"bx_timeline_videos_poster_view";i:3;s:29:"bx_timeline_videos_poster_big";}}', 'no', 0, 0, 0, 'BxDolTranscoderProxy', ''),
+('bx_timeline_proxy_view', 'bx_timeline_videos_processed', 'Proxy', 'a:4:{s:6:"object";s:18:"bx_timeline_videos";s:5:"image";s:29:"bx_timeline_videos_photo_view";s:12:"video_poster";s:30:"bx_timeline_videos_poster_view";s:5:"video";a:2:{i:0;s:22:"bx_timeline_videos_mp4";i:1;s:25:"bx_timeline_videos_mp4_hd";}}', 'no', 0, 0, 0, 'BxDolTranscoderProxy', ''),
+('bx_timeline_proxy_big', 'bx_timeline_videos_processed', 'Proxy', 'a:4:{s:6:"object";s:18:"bx_timeline_videos";s:5:"image";s:28:"bx_timeline_videos_photo_big";s:12:"video_poster";s:29:"bx_timeline_videos_poster_big";s:5:"video";a:2:{i:0;s:22:"bx_timeline_videos_mp4";i:1;s:25:"bx_timeline_videos_mp4_hd";}}', 'no', 0, 0, 0, 'BxDolTranscoderProxy', '');
+
+INSERT INTO `sys_transcoder_filters` (`transcoder_object`, `filter`, `filter_params`, `order`) VALUES
+('bx_timeline_photos_preview', 'Resize', 'a:3:{s:1:"w";s:3:"100";s:1:"h";s:3:"100";s:13:"square_resize";s:1:"1";}', '0'),
+('bx_timeline_photos_view', 'Resize', 'a:1:{s:1:"w";s:3:"300";}', '0'),
+('bx_timeline_photos_medium', 'Resize', 'a:1:{s:1:"w";s:3:"600";}', '0'),
+('bx_timeline_photos_big', 'Resize', 'a:2:{s:1:"w";s:4:"1200";s:1:"h";s:4:"1200";}', '0'),
+
+('bx_timeline_videos_photo_preview', 'Resize', 'a:3:{s:1:"w";s:3:"300";s:1:"h";s:3:"300";s:13:"square_resize";s:1:"1";}', '0'),
+('bx_timeline_videos_photo_view', 'Resize', 'a:1:{s:1:"w";s:3:"480";}', '0'),
+('bx_timeline_videos_photo_big', 'Resize', 'a:2:{s:1:"w";s:4:"1200";s:1:"h";s:4:"1200";}', '0'),
+('bx_timeline_videos_poster_preview', 'Poster', 'a:2:{s:1:"h";s:3:"480";s:10:"force_type";s:3:"jpg";}', 0),
+('bx_timeline_videos_poster_preview', 'Resize', 'a:3:{s:1:"w";s:3:"300";s:1:"h";s:3:"300";s:13:"square_resize";s:1:"1";}', 10),
+('bx_timeline_videos_poster_view', 'Poster', 'a:2:{s:1:"h";s:3:"480";s:10:"force_type";s:3:"jpg";}', 0),
+('bx_timeline_videos_poster_big', 'Poster', 'a:2:{s:1:"h";s:3:"480";s:10:"force_type";s:3:"jpg";}', 0),
+('bx_timeline_videos_mp4', 'Mp4', 'a:2:{s:1:"h";s:3:"318";s:10:"force_type";s:3:"mp4";}', 0),
+('bx_timeline_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);
+
+
+-- Forms -> Post
+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_timeline_post', @sName, '_bx_timeline_form_post', '', 'a:1:{s:8:"onsubmit";s:46:"return {js_object_post}.onFormPostSubmit(this)";}', 'tlb_do_submit', 'bx_timeline_events', 'id', '', '', '', 0, 1, 'BxTimelineFormPost', 'modules/boonex/timeline/classes/BxTimelineFormPost.php');
+
+INSERT INTO `sys_form_displays` (`display_name`, `module`, `object`, `title`, `view_mode`) VALUES
+('bx_timeline_post_add', @sName, 'bx_timeline_post', '_bx_timeline_form_post_display_add', 0),
+('bx_timeline_post_add_public', @sName, 'bx_timeline_post', '_bx_timeline_form_post_display_add_public', 0),
+('bx_timeline_post_add_profile', @sName, 'bx_timeline_post', '_bx_timeline_form_post_display_add_profile', 0),
+
+('bx_timeline_post_edit', @sName, 'bx_timeline_post', '_bx_timeline_form_post_display_edit', 0),
+
+('bx_timeline_post_view', @sName, 'bx_timeline_post', '_bx_timeline_form_post_display_view', 1);
+
+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_timeline_post', @sName, 'type', 'post', '', 0, 'hidden', '_bx_timeline_form_post_input_sys_type', '', '', 0, 0, 0, '', '', '', '', '', '', 'Xss', '', 0, 0),
+('bx_timeline_post', @sName, 'action', '', '', 0, 'hidden', '_bx_timeline_form_post_input_sys_action', '', '', 0, 0, 0, '', '', '', '', '', '', 'Xss', '', 0, 0),
+('bx_timeline_post', @sName, 'owner_id', '0', '', 0, 'hidden', '_bx_timeline_form_post_input_sys_owner_id', '', '', 0, 0, 0, '', '', '', '', '', '', 'Int', '', 1, 0),
+('bx_timeline_post', @sName, 'text', '', '', 0, 'textarea', '_bx_timeline_form_post_input_sys_text', '_bx_timeline_form_post_input_text', '', 0, 0, 3, 'a:1:{s:12:"autocomplete";s:3:"off";}', '', '', '', '', '', 'XssHtml', '', 1, 0),
+('bx_timeline_post', @sName, 'anonymous', '', '', 0, 'switcher', '_sys_form_input_sys_anonymous', '_sys_form_input_anonymous', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_timeline_post', @sName, 'date', '', '', 0, 'datetime', '_bx_timeline_form_post_input_sys_date', '_bx_timeline_form_post_input_date', '', 0, 0, 0, '', '', '', '', '', '', 'DateTimeUtc', '', 1, 0),
+('bx_timeline_post', @sName, 'published', '', '', 0, 'datetime', '_bx_timeline_form_post_input_sys_date_published', '_bx_timeline_form_post_input_date_published', '_bx_timeline_form_post_input_date_published_info', 0, 0, 0, '', '', '', '', '', '', 'DateTimeUtc', '', 1, 0),
+('bx_timeline_post', @sName, 'object_cf', '1', '#!sys_content_filter', 0, 'select', '_sys_form_entry_input_sys_cf', '_sys_form_entry_input_cf', '', 0, 0, 0, '', '', '', '', '', '', 'Int', '', 1, 0),
+('bx_timeline_post', @sName, 'object_privacy_view', '', '', 0, 'custom', '_bx_timeline_form_post_input_sys_object_privacy_view', '_bx_timeline_form_post_input_object_privacy_view', '', 1, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
+('bx_timeline_post', @sName, 'location', '', '', 0, 'location', '_sys_form_input_sys_location', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_timeline_post', @sName, 'link', '', '', 0, 'custom', '_bx_timeline_form_post_input_sys_link', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_timeline_post', @sName, 'photo', 'a:1:{i:0;s:23:"bx_timeline_html5_photo";}', 'a:2:{s:24:"bx_timeline_simple_photo";s:26:"_sys_uploader_simple_title";s:23:"bx_timeline_html5_photo";s:25:"_sys_uploader_html5_title";}', 0, 'files', '_bx_timeline_form_post_input_sys_photo', '_bx_timeline_form_post_input_photo', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_timeline_post', @sName, 'video', 'a:2:{i:0;s:23:"bx_timeline_html5_video";i:1;s:24:"bx_timeline_record_video";}', 'a:3:{s:24:"bx_timeline_simple_video";s:26:"_sys_uploader_simple_title";s:23:"bx_timeline_html5_video";s:25:"_sys_uploader_html5_title";s:24:"bx_timeline_record_video";s:32:"_sys_uploader_record_video_title";}', 0, 'files', '_bx_timeline_form_post_input_sys_video', '_bx_timeline_form_post_input_video', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_timeline_post', @sName, 'file', 'a:1:{i:0;s:22:"bx_timeline_html5_file";}', 'a:2:{s:23:"bx_timeline_simple_file";s:26:"_sys_uploader_simple_title";s:22:"bx_timeline_html5_file";s:25:"_sys_uploader_html5_title";}', 0, 'files', '_bx_timeline_form_post_input_sys_files', '_bx_timeline_form_post_input_files', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_timeline_post', @sName, 'attachments', '', '', 0, 'custom', '_bx_timeline_form_post_input_sys_attachments', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_timeline_post', @sName, 'controls', '', 'tlb_do_submit,tlb_do_cancel', 0, 'input_set', '', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
+('bx_timeline_post', @sName, 'tlb_do_submit', '_bx_timeline_form_post_input_do_submit', '', 0, 'submit', '_bx_timeline_form_post_input_sys_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
+('bx_timeline_post', @sName, 'tlb_do_cancel', '_bx_timeline_form_post_input_do_cancel', '', 0, 'button', '_bx_timeline_form_post_input_sys_do_cancel', '', '', 0, 0, 0, 'a:2:{s:7:"onclick";s:51:"{js_object_view}.editPostCancel(this, {content_id})";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_timeline_post_add', 'type', 2147483647, 1, 0),
+('bx_timeline_post_add', 'action', 2147483647, 1, 1),
+('bx_timeline_post_add', 'text', 2147483647, 1, 2),
+('bx_timeline_post_add', 'attachments', 2147483647, 1, 3),
+('bx_timeline_post_add', 'owner_id', 2147483647, 1, 4),
+('bx_timeline_post_add', 'object_privacy_view', 2147483647, 1, 5),
+('bx_timeline_post_add', 'object_cf', 2147483647, 1, 6),
+('bx_timeline_post_add', 'published', 192, 0, 7),
+('bx_timeline_post_add', 'location', 2147483647, 1, 8),
+('bx_timeline_post_add', 'link', 2147483647, 1, 9),
+('bx_timeline_post_add', 'photo', 2147483647, 1, 10),
+('bx_timeline_post_add', 'video', 2147483647, 1, 11),
+('bx_timeline_post_add', 'file', 2147483647, 1, 12),
+('bx_timeline_post_add', 'tlb_do_submit', 2147483647, 1, 13),
+
+('bx_timeline_post_add_public', 'type', 2147483647, 1, 0),
+('bx_timeline_post_add_public', 'action', 2147483647, 1, 1),
+('bx_timeline_post_add_public', 'owner_id', 2147483647, 1, 2),
+('bx_timeline_post_add_public', 'text', 2147483647, 1, 3),
+('bx_timeline_post_add_public', 'attachments', 2147483647, 1, 4),
+('bx_timeline_post_add_public', 'object_privacy_view', 2147483647, 1, 5),
+('bx_timeline_post_add_public', 'object_cf', 2147483647, 1, 6),
+('bx_timeline_post_add_public', 'published', 192, 0, 7),
+('bx_timeline_post_add_public', 'location', 2147483647, 1, 8),
+('bx_timeline_post_add_public', 'link', 2147483647, 1, 9),
+('bx_timeline_post_add_public', 'photo', 2147483647, 1, 10),
+('bx_timeline_post_add_public', 'video', 2147483647, 1, 11),
+('bx_timeline_post_add_public', 'file', 2147483647, 1, 12),
+('bx_timeline_post_add_public', 'tlb_do_submit', 2147483647, 1, 13),
+
+('bx_timeline_post_add_profile', 'type', 2147483647, 1, 0),
+('bx_timeline_post_add_profile', 'action', 2147483647, 1, 1),
+('bx_timeline_post_add_profile', 'owner_id', 2147483647, 1, 2),
+('bx_timeline_post_add_profile', 'text', 2147483647, 1, 3),
+('bx_timeline_post_add_profile', 'attachments', 2147483647, 1, 4),
+('bx_timeline_post_add_profile', 'object_privacy_view', 2147483647, 1, 5),
+('bx_timeline_post_add_profile', 'object_cf', 2147483647, 1, 6),
+('bx_timeline_post_add_profile', 'published', 192, 0, 7),
+('bx_timeline_post_add_profile', 'location', 2147483647, 1, 8),
+('bx_timeline_post_add_profile', 'link', 2147483647, 1, 9),
+('bx_timeline_post_add_profile', 'photo', 2147483647, 1, 10),
+('bx_timeline_post_add_profile', 'video', 2147483647, 1, 11),
+('bx_timeline_post_add_profile', 'file', 2147483647, 1, 12),
+('bx_timeline_post_add_profile', 'tlb_do_submit', 2147483647, 1, 13),
+
+('bx_timeline_post_edit', 'type', 2147483647, 1, 1),
+('bx_timeline_post_edit', 'action', 2147483647, 1, 2),
+('bx_timeline_post_edit', 'owner_id', 2147483647, 1, 3),
+('bx_timeline_post_edit', 'text', 2147483647, 1, 4),
+('bx_timeline_post_edit', 'attachments', 2147483647, 1, 5),
+('bx_timeline_post_edit', 'published', 192, 0, 6),
+('bx_timeline_post_edit', 'location', 2147483647, 1, 7),
+('bx_timeline_post_edit', 'link', 2147483647, 1, 8),
+('bx_timeline_post_edit', 'photo', 2147483647, 1, 9),
+('bx_timeline_post_edit', 'video', 2147483647, 1, 10),
+('bx_timeline_post_edit', 'file', 2147483647, 1, 11),
+('bx_timeline_post_edit', 'object_cf', 2147483647, 1, 12),
+('bx_timeline_post_edit', 'controls', 2147483647, 1, 13),
+('bx_timeline_post_edit', 'tlb_do_submit', 2147483647, 1, 14),
+('bx_timeline_post_edit', 'tlb_do_cancel', 2147483647, 1, 15);
+
+-- Forms -> Attach link
+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_timeline_attach_link', @sName, '_bx_timeline_form_attach_link', '', '', 'do_submit', 'bx_timeline_links', 'id', '', '', '', 0, 1, '', '');
+
+INSERT INTO `sys_form_displays` (`display_name`, `module`, `object`, `title`, `view_mode`) VALUES
+('bx_timeline_attach_link_add', @sName, 'bx_timeline_attach_link', '_bx_timeline_form_attach_link_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_timeline_attach_link', @sName, 'event_id', '0', '', 0, 'hidden', '_bx_timeline_form_attach_link_input_sys_event_id', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
+('bx_timeline_attach_link', @sName, 'url', '', '', 0, 'text', '_bx_timeline_form_attach_link_input_sys_url', '_bx_timeline_form_attach_link_input_url', '', 0, 0, 0, '', '', '', 'Preg', 'a:1:{s:4:"preg";s:0:"";}', '_bx_timeline_form_attach_link_input_url_err', '', '', 0, 0),
+('bx_timeline_attach_link', @sName, 'controls', '', 'do_submit,do_cancel', 0, 'input_set', '', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
+('bx_timeline_attach_link', @sName, 'do_submit', '_bx_timeline_form_attach_link_input_do_submit', '', 0, 'submit', '_bx_timeline_form_attach_link_input_sys_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
+('bx_timeline_attach_link', @sName, 'do_cancel', '_bx_timeline_form_attach_link_input_do_cancel', '', 0, 'button', '_bx_timeline_form_attach_link_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_timeline_attach_link_add', 'event_id', 2147483647, 1, 1),
+('bx_timeline_attach_link_add', 'url', 2147483647, 1, 2),
+('bx_timeline_attach_link_add', 'controls', 2147483647, 1, 3),
+('bx_timeline_attach_link_add', 'do_submit', 2147483647, 1, 4),
+('bx_timeline_attach_link_add', 'do_cancel', 2147483647, 1, 5);
+
+-- Forms -> Repost To
+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_timeline_repost', @sName, '_bx_timeline_form_repost', '', '', 'do_submit', '', '', '', '', '', 0, 1, 'BxTimelineFormRepost', 'modules/boonex/timeline/classes/BxTimelineFormRepost.php');
+
+INSERT INTO `sys_form_displays` (`display_name`, `module`, `object`, `title`, `view_mode`) VALUES
+('bx_timeline_repost_with', @sName, 'bx_timeline_repost', '_bx_timeline_form_repost_display_with', 0),
+('bx_timeline_repost_to', @sName, 'bx_timeline_repost', '_bx_timeline_form_repost_display_to', 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_timeline_repost', @sName, 'reposter_id', '', '', 0, 'hidden', '_bx_timeline_form_repost_input_sys_reposter_id', '', '', 0, 0, 0, '', '', '', '', '', '', 'Int', '', 0, 0),
+('bx_timeline_repost', @sName, 'owner_id', '', '', 0, 'hidden', '_bx_timeline_form_repost_input_sys_owner_id', '', '', 0, 0, 0, '', '', '', '', '', '', 'Int', '', 0, 0),
+('bx_timeline_repost', @sName, 'type', '', '', 0, 'hidden', '_bx_timeline_form_repost_input_sys_type', '', '', 0, 0, 0, '', '', '', '', '', '', 'Xss', '', 0, 0),
+('bx_timeline_repost', @sName, 'action', '', '', 0, 'hidden', '_bx_timeline_form_repost_input_sys_action', '', '', 0, 0, 0, '', '', '', '', '', '', 'Xss', '', 0, 0),
+('bx_timeline_repost', @sName, 'object_id', '', '', 0, 'hidden', '_bx_timeline_form_repost_input_sys_object_id', '', '', 0, 0, 0, '', '', '', '', '', '', 'Int', '', 0, 0),
+('bx_timeline_repost', @sName, 'search', '', '', 0, 'custom', '_bx_timeline_form_repost_input_sys_search', '_bx_timeline_form_repost_input_search', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
+('bx_timeline_repost', @sName, 'list', '', '', 0, 'custom', '_bx_timeline_form_repost_input_sys_list', '_bx_timeline_form_repost_input_list', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
+('bx_timeline_repost', @sName, 'text', '', '', 0, 'textarea', '_bx_timeline_form_repost_input_sys_text', '_bx_timeline_form_repost_input_text', '', 0, 0, 0, 'a:1:{s:12:"autocomplete";s:3:"off";}', '', '', '', '', '', 'XssHtml', '', 1, 0),
+('bx_timeline_repost', @sName, 'reposted', '', '', 0, 'custom', '_bx_timeline_form_repost_input_sys_reposted', '_bx_timeline_form_repost_input_reposted', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
+('bx_timeline_repost', @sName, 'controls', '', 'do_submit,do_cancel', 0, 'input_set', '', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
+('bx_timeline_repost', @sName, 'do_submit', '_bx_timeline_form_repost_input_do_submit', '', 0, 'submit', '_bx_timeline_form_repost_input_sys_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
+('bx_timeline_repost', @sName, 'do_cancel', '_bx_timeline_form_repost_input_do_cancel', '', 0, 'button', '_bx_timeline_form_repost_input_sys_do_cancel', '', '', 0, 0, 0, 'a:2:{s:7:"onclick";s:45:"$(''.bx-popup-applied:visible'').dolPopupHide()";s:5:"class";s:22:"bx-def-margin-sec-left";}', '', '', '', '', '', '', '', 0, 0);
+
+INSERT INTO `sys_form_display_inputs` (`display_name`, `input_name`, `visible_for_levels`, `active`, `order`) VALUES
+('bx_timeline_repost_with', 'reposter_id', 2147483647, 1, 1),
+('bx_timeline_repost_with', 'owner_id', 2147483647, 1, 2),
+('bx_timeline_repost_with', 'type', 2147483647, 1, 3),
+('bx_timeline_repost_with', 'action', 2147483647, 1, 4),
+('bx_timeline_repost_with', 'object_id', 2147483647, 1, 5),
+('bx_timeline_repost_with', 'text', 2147483647, 1, 6),
+('bx_timeline_repost_with', 'reposted', 2147483647, 1, 7),
+('bx_timeline_repost_with', 'controls', 2147483647, 1, 8),
+('bx_timeline_repost_with', 'do_submit', 2147483647, 1, 9),
+('bx_timeline_repost_with', 'do_cancel', 2147483647, 1, 10),
+
+('bx_timeline_repost_to', 'reposter_id', 2147483647, 1, 1),
+('bx_timeline_repost_to', 'type', 2147483647, 1, 2),
+('bx_timeline_repost_to', 'action', 2147483647, 1, 3),
+('bx_timeline_repost_to', 'object_id', 2147483647, 1, 4),
+('bx_timeline_repost_to', 'search', 2147483647, 1, 5),
+('bx_timeline_repost_to', 'list', 2147483647, 1, 6),
+('bx_timeline_repost_to', 'controls', 2147483647, 1, 7),
+('bx_timeline_repost_to', 'do_submit', 2147483647, 1, 8),
+('bx_timeline_repost_to', 'do_cancel', 2147483647, 1, 9);
+
+
+-- COMMENTS
+INSERT INTO `sys_objects_cmts` (`Name`, `Module`, `Table`, `CharsPostMin`, `CharsPostMax`, `CharsDisplayMax`, `Html`, `PerView`, `PerViewReplies`, `BrowseType`, `IsBrowseSwitch`, `PostFormPosition`, `NumberOfLevels`, `IsDisplaySwitch`, `IsRatable`, `ViewingThreshold`, `IsOn`, `RootStylePrefix`, `BaseUrl`, `ObjectVote`, `TriggerTable`, `TriggerFieldId`, `TriggerFieldAuthor`, `TriggerFieldTitle`, `TriggerFieldComments`, `ClassName`, `ClassFile`) VALUES
+('bx_timeline', 'bx_timeline', 'bx_timeline_comments', 1, 5000, 1000, 3, 5, 3, 'tail', 1, 'bottom', 1, 1, 1, -3, 1, 'cmt', 'page.php?i=item&id={object_id}', '', 'bx_timeline_events', 'id', 'object_id', 'title', 'comments', 'BxTimelineCmts', 'modules/boonex/timeline/classes/BxTimelineCmts.php'),
+('bx_timeline_notes', 'bx_timeline', 'bx_timeline_cmts_notes', 1, 5000, 1000, 0, 5, 3, 'tail', 1, 'bottom', 1, 1, 1, -3, 1, 'cmt', 'page.php?i=view-post&id={object_id}', '', 'bx_timeline_events', 'id', 'object_owner_id', 'title', '', 'BxTemplCmtsNotes', '');
+
+
+-- VIEWS
+INSERT INTO `sys_objects_view` (`name`, `table_track`, `period`, `is_on`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_count`, `class_name`, `class_file`) VALUES 
+('bx_timeline', 'bx_timeline_views_track', '86400', '1', 'bx_timeline_events', 'id', 'object_id', 'views', '', '');
+
+
+-- VOTES
+INSERT INTO `sys_objects_vote`(`Name`, `TableMain`, `TableTrack`, `PostTimeout`, `MinValue`, `MaxValue`, `IsUndo`, `IsOn`, `TriggerTable`, `TriggerFieldId`, `TriggerFieldAuthor`, `TriggerFieldRate`, `TriggerFieldRateCount`, `ClassName`, `ClassFile`) VALUES 
+('bx_timeline', 'bx_timeline_votes', 'bx_timeline_votes_track', '604800', '1', '1', '0', '1', 'bx_timeline_events', 'id', 'object_id', 'rate', 'votes', 'BxTimelineVoteLikes', 'modules/boonex/timeline/classes/BxTimelineVoteLikes.php'),
+('bx_timeline_reactions', 'bx_timeline_reactions', 'bx_timeline_reactions_track', '604800', '1', '1', '1', '1', 'bx_timeline_events', 'id', 'object_id', 'rrate', 'rvotes', 'BxTemplVoteReactions', '');
+
+
+-- SCORES
+INSERT INTO `sys_objects_score` (`name`, `module`, `table_main`, `table_track`, `post_timeout`, `is_on`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_score`, `trigger_field_cup`, `trigger_field_cdown`, `class_name`, `class_file`) VALUES 
+('bx_timeline', 'bx_timeline', 'bx_timeline_scores', 'bx_timeline_scores_track', '604800', '0', 'bx_timeline_events', 'id', 'object_id', 'score', 'sc_up', 'sc_down', '', '');
+
+
+-- REPORTS
+INSERT INTO `sys_objects_report` (`name`, `module`, `table_main`, `table_track`, `is_on`, `base_url`, `object_comment`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_count`, `class_name`, `class_file`) VALUES 
+('bx_timeline', 'bx_timeline', 'bx_timeline_reports', 'bx_timeline_reports_track', '1', 'page.php?i=item&id={object_id}', 'bx_timeline_notes', 'bx_timeline_events', 'id', 'owner_id', 'reports',  'BxTimelineReport', 'modules/boonex/timeline/classes/BxTimelineReport.php');
+
+
+-- CONTENT INFO
+INSERT INTO `sys_objects_content_info` (`name`, `title`, `alert_unit`, `alert_action_add`, `alert_action_update`, `alert_action_delete`, `class_name`, `class_file`) VALUES
+('bx_timeline', '_bx_timeline', 'bx_timeline', 'post_common', '', 'delete', '', ''),
+('bx_timeline_cmts', '_bx_timeline_cmts', 'bx_timeline', 'commentPost', 'commentUpdated', 'commentRemoved', 'BxDolContentInfoCmts', '');
+
+
+-- STUDIO PAGE & WIDGET
+INSERT INTO `sys_std_pages`(`index`, `name`, `header`, `caption`, `icon`) VALUES
+(3, 'bx_timeline', '_bx_timeline', '_bx_timeline', 'bx_timeline@modules/boonex/timeline/|std-icon.svg');
+SET @iPageId = LAST_INSERT_ID();
+
+SET @iParentPageId = (SELECT `id` FROM `sys_std_pages` WHERE `name` = 'home');
+SET @iParentPageOrder = (SELECT MAX(`order`) FROM `sys_std_pages_widgets` WHERE `page_id` = @iParentPageId);
+INSERT INTO `sys_std_widgets` (`page_id`, `module`, `type`, `url`, `click`, `icon`, `caption`, `cnt_notices`, `cnt_actions`) VALUES
+(@iPageId, 'bx_timeline', 'extensions', '{url_studio}module.php?name=bx_timeline', '', 'bx_timeline@modules/boonex/timeline/|std-icon.svg', '_bx_timeline', '', '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));

+ 77 - 0
modules/boonex/timeline/updates/13.0.4_13.0.5/source/install/sql/uninstall.sql

@@ -0,0 +1,77 @@
+SET @sName = 'bx_timeline';
+
+DROP TABLE IF EXISTS `bx_timeline_events`, `bx_timeline_events2users`, `bx_timeline_handlers`;
+
+DROP TABLE IF EXISTS `bx_timeline_mute`;
+
+DROP TABLE IF EXISTS `bx_timeline_photos`, `bx_timeline_photos_processed`, `bx_timeline_photos2events`;
+
+DROP TABLE IF EXISTS `bx_timeline_videos`, `bx_timeline_videos_processed`, `bx_timeline_videos2events`;
+
+DROP TABLE IF EXISTS `bx_timeline_files`, `bx_timeline_files2events`;
+
+DROP TABLE IF EXISTS `bx_timeline_links`, `bx_timeline_links2events`;
+
+DROP TABLE IF EXISTS `bx_timeline_reposts_track`;
+
+DROP TABLE IF EXISTS `bx_timeline_comments`;
+
+DROP TABLE IF EXISTS `bx_timeline_views_track`;
+
+DROP TABLE IF EXISTS `bx_timeline_votes`, `bx_timeline_votes_track`, `bx_timeline_reactions`, `bx_timeline_reactions_track`;
+
+DROP TABLE IF EXISTS `bx_timeline_meta_keywords`, `bx_timeline_meta_locations`, `bx_timeline_meta_mentions`;
+
+DROP TABLE IF EXISTS `bx_timeline_reports`, `bx_timeline_reports_track`;
+
+DROP TABLE IF EXISTS `bx_timeline_hot_track`;
+
+DROP TABLE IF EXISTS `bx_timeline_scores`, `bx_timeline_scores_track`;
+
+DROP TABLE IF EXISTS `bx_timeline_cmts_notes`;
+
+
+-- STORAGES, TRANSCODERS, UPLOADERS
+DELETE FROM `sys_objects_uploader` WHERE `object` LIKE 'bx_timeline%';
+DELETE FROM `sys_objects_storage` WHERE `object`  LIKE 'bx_timeline%';
+DELETE FROM `sys_objects_transcoder` WHERE `object`  LIKE 'bx_timeline%';
+DELETE FROM `sys_transcoder_filters` WHERE `transcoder_object` LIKE 'bx_timeline%';
+DELETE FROM `sys_transcoder_images_files` WHERE `transcoder_object` LIKE 'bx_timeline%';
+DELETE FROM `sys_transcoder_videos_files` WHERE `transcoder_object` LIKE 'bx_timeline%';
+
+
+-- Forms All
+DELETE FROM `sys_form_display_inputs` WHERE `display_name` IN  (SELECT `display_name` FROM `sys_form_displays` WHERE `module` = @sName);
+DELETE FROM `sys_form_inputs` WHERE `module` = @sName;
+DELETE FROM `sys_form_displays` WHERE `module` = @sName;
+DELETE FROM `sys_objects_form` WHERE `module` = @sName;
+
+
+-- COMMENTS
+DELETE FROM `sys_objects_cmts` WHERE `Name` IN ('bx_timeline', 'bx_timeline_notes');
+
+
+-- VIEWS
+DELETE FROM `sys_objects_view` WHERE `name` = 'bx_timeline' LIMIT 1;
+
+
+-- VOTES
+DELETE FROM `sys_objects_vote` WHERE `Name` IN ('bx_timeline', 'bx_timeline_reactions');
+
+
+-- SCORES
+DELETE FROM `sys_objects_score` WHERE `name` = 'bx_timeline';
+
+
+-- REPORTS
+DELETE FROM `sys_objects_report` WHERE `Name` = 'bx_timeline' LIMIT 1;
+
+
+-- CONTENT INFO
+DELETE FROM `sys_objects_content_info` WHERE `name` IN ('bx_timeline', 'bx_timeline_cmts');
+
+
+-- STUDIO PAGE & WIDGET
+DELETE FROM `tp`, `tw`, `twb`, `tpw` 
+USING `sys_std_pages` AS `tp` LEFT JOIN `sys_std_widgets` AS `tw` ON `tp`.`id` = `tw`.`page_id` LEFT JOIN `sys_std_widgets_bookmarks` AS `twb` ON `tw`.`id` = `twb`.`widget_id` LEFT JOIN `sys_std_pages_widgets` AS `tpw` ON `tw`.`id` = `tpw`.`widget_id`
+WHERE  `tp`.`name` = @sName;

+ 565 - 0
modules/boonex/timeline/updates/13.0.4_13.0.5/source/js/main.js

@@ -0,0 +1,565 @@
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Timeline Timeline
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+function BxTimelineMain() {
+    this.sIdPost = '#bx-timeline-post';
+    this.sIdPostForm = 'form#bx_timeline_post';
+
+    this.sId = '#bx-timeline';
+
+    this.sSP = 'bx-tl';
+    this.sClassView = this.sSP + '-view';
+    this.sClassMasonry = this.sSP + '-masonry';
+    this.sClassItems = this.sSP + '-items';
+    this.sClassItem = this.sSP + '-item';
+    this.sClassItemCnt = this.sSP + '-item-cnt';
+    this.sClassDividerToday = this.sSP + '-divider-today';
+    this.sClassItemContent = this.sSP + '-item-content';
+    this.sClassItemComments = this.sSP + '-item-comments-holder';
+    this.sClassItemImages = this.sSP + '-item-images';
+    this.sClassItemImage = this.sSP + '-item-image';
+    this.sClassItemVideos = this.sSP + '-item-videos';
+    this.sClassItemVideo = this.sSP + '-item-video';
+    this.sClassItemAttachments = this.sSP + '-item-attachments';
+    this.sClassItemAttachment = this.sSP + '-item-attachment';
+    this.sClassSample = this.sSP + '-sample';
+    this.sClassBlink = this.sSP + '-blink';
+    this.sClassJumpTo = this.sSP + '-jump-to';
+
+    this.oView = null;
+    this.bViewTimeline = false;
+    this.bViewOutline = false;
+    this.bViewItem = false;
+
+    this._sPregTag = "(<([^>]+bx-tag[^>]+)>)";
+    this._sPregMention = "(<([^>]+bx-mention[^>]+)>)";
+    this._sPregUrl = "(([A-Za-z]{3,9}:(?:\\/\\/)?)(?:[\\-;:&=\\+\\$,\\w]+@)?[A-Za-z0-9\\.\\-]+|(?:www\\.|[\\-;:&=\\+\\$,\\w]+@)[A-Za-z0-9\\.\\-]+)((?:\\/[\\+~%#\\/\\.\\w\\-_!\\(\\)]*)?\\??(?:[\\-\\+=&;%@\\.\\w_]*)#?(?:[\\.\\!\\/\\w]*))?";
+
+    this._iLimitAttachLinks = 0;
+    this._sLimitAttachLinksErr = '';
+    this._oAttachedLinks = {};
+}
+
+BxTimelineMain.prototype.initView = function() 
+{
+    //Do some basic initialization here.
+};
+
+BxTimelineMain.prototype.initVideos = function(oParent) {
+    oParent.find('iframe').load(function() {
+        $(this).height(($(this).contents().find('video').height()) + 'px');
+    });
+};
+
+BxTimelineMain.prototype.isMasonry = function() {
+    return this.oView.find('.' + this.sClassItems).hasClass(this.sClassMasonry);
+};
+
+BxTimelineMain.prototype.isMasonryEmpty = function() {
+    return this.oView.find('.' + this.sClassItems + ' .' + this.sClassItem).length == 0;
+};
+
+BxTimelineMain.prototype.initMasonry = function(onComplete) {
+    var $this = this;
+    var oHolder = this.oView.find('.' + this.sClassItems);
+
+    var oItems = oHolder.find('.' + this.sClassItem);
+    if(oItems.length == 0) 
+        return;
+
+    oItems.resize(function(){
+            $this.reloadMasonry();
+    }).find('.bx-tl-item-text .bx-tl-content').checkOverflowHeight(this.sSP + '-overflow', function(oElement) {
+            $this.onFindOverflow(oElement);
+    });
+
+    oHolder.addClass(this.sClassMasonry).masonry({
+      itemSelector: '.' + this.sClassItem,
+      columnWidth: '.' + this.sSP + '-grid-sizer'
+    }).masonry('once', 'layoutComplete', function() {
+        if(typeof onComplete === 'function')
+            onComplete(oItems);
+    });
+};
+
+BxTimelineMain.prototype.destroyMasonry = function() {
+    this.oView.find('.' + this.sClassItems).removeClass(this.sClassMasonry).masonry('destroy');
+};
+
+BxTimelineMain.prototype.appendMasonry = function(oItems, onComplete) {
+    var $this = this;
+    var oItems = $(oItems);
+    oItems.resize(function(){
+            $this.reloadMasonry();
+    }).find('iframe').load(function() {
+            $this.reloadMasonry();
+    }).find('img.' + this.sSP + '-item-image').load(function() {
+            $this.reloadMasonry();
+    });
+
+    var oHolder = this.oView.find('.' + this.sClassItems).masonry('layout').append(oItems);
+    if(!this.isMasonry())
+        this.initMasonry(onComplete);
+    else
+        oHolder.masonry('appended', oItems).masonry('layout').masonry('once', 'layoutComplete', function() {
+            if(typeof onComplete === 'function')
+                onComplete(oItems);
+        });
+};
+
+BxTimelineMain.prototype.prependMasonry = function(oItems, onComplete) {
+    var $this = this;
+    var oItems = $(oItems);
+    oItems.resize(function(){
+        $this.reloadMasonry();
+    }).find('iframe').load(function() {
+        $this.reloadMasonry();
+    }).find('img.' + this.sSP + '-item-image').load(function() {
+        $this.reloadMasonry();
+    });
+
+    var oHolder = this.oView.find('.' + this.sClassItems).masonry('layout').prepend(oItems);
+    if(!this.isMasonry())
+        this.initMasonry(onComplete);
+    else
+        oHolder.masonry('prepended', oItems).masonry('layout').masonry('once', 'layoutComplete', function() {
+            if(typeof onComplete === 'function')
+                onComplete(oItems);
+        });
+};
+
+BxTimelineMain.prototype.removeMasonry = function(oItems, onRemove) {
+    var $this = this;
+    var oItems = $(oItems);
+
+    var oHolder = this.oView.find('.' + this.sClassItems);
+    if(typeof onRemove === 'function')
+        oHolder.masonry('once', 'removeComplete', onRemove);
+
+    oHolder.masonry('remove', oItems).masonry('layout');
+};
+
+BxTimelineMain.prototype.reloadMasonry = function() {
+    this.oView.find('.' + this.sClassItems).masonry('reloadItems').masonry('layout');
+};
+
+BxTimelineMain.prototype.initFlickityImages = function(oParent, sSelectorItemImage) {
+    var sItem = sSelectorItemImage ? sSelectorItemImage : 'div.' + this.sClassItemImage;
+    if(oParent.find(sItem).length <= 1)
+        return;
+
+    var oCarousel = oParent;
+
+    oCarousel.flickity({
+        cellSelector: sItem,
+        cellAlign: 'left',
+        imagesLoaded: true,
+        wrapAround: true,
+        pageDots: false
+    });
+
+    oCarousel.find(sItem + ' img').each(function() {
+        $(this).load(function() {
+            oCarousel.flickity('resize');
+        });
+    });
+};
+
+BxTimelineMain.prototype.initFlickityVideos = function(oParent) {
+    var sItem = 'div.' + this.sClassItemVideo;
+    if(oParent.find(sItem).length <= 1)
+        return;
+
+    var oCarousel = oParent;
+
+    oCarousel.flickity({
+        cellSelector: sItem,
+        cellAlign: 'left',
+        imagesLoaded: true,
+        wrapAround: true,
+        pageDots: false
+    });
+
+    oCarousel.find(sItem + ' video').each(function() {
+        this.addEventListener('loadedmetadata', function() {
+            oCarousel.flickity('resize');
+        }, true);
+    });
+};
+
+BxTimelineMain.prototype.initFlickityAttachments = function(oParent) {
+    var sItem = 'div.' + this.sClassItemAttachment;
+    if(oParent.find(sItem).length <= 1)
+        return;
+
+    var oCarousel = oParent;
+
+    oCarousel.flickity({
+        cellSelector: sItem,
+        cellAlign: 'left',
+        imagesLoaded: true,
+        wrapAround: true,
+        pageDots: false
+    });
+
+    oCarousel.find(sItem + ' img').each(function() {
+        $(this).load(function() {
+            oCarousel.flickity('resize');
+        });
+    });
+
+    oCarousel.find(sItem + ' video').each(function() {
+        this.addEventListener('loadedmetadata', function() {
+            oCarousel.flickity('resize');
+        }, true);
+    });
+};
+
+BxTimelineMain.prototype.initFlickity = function(oView) {
+    var $this = this;
+
+    //--- init Flickity for images (may be used in header section)
+    oView.find('.' + this.sClassItem + ' .' + this.sClassItemImages + '.' + this.sSP + '-ii-gallery').each(function() {
+        $this.initFlickityImages($(this));
+    });
+
+    //--- init Flickity for videos (may be used in header section)
+    oView.find('.' + this.sClassItem + ' .' + this.sClassItemVideos + '.' + this.sSP + '-iv-gallery').each(function() {
+        $this.initFlickityVideos($(this));
+    });
+
+    //--- init Flickity for attachments (images and video in attachments seation)
+    oView.find('.' + this.sClassItem + ' .' + this.sClassItemAttachments + '.' + this.sSP + '-ia-gallery').each(function() {
+        $this.initFlickityAttachments($(this));
+    });
+
+    //--- init Flickity for attachments (files in attachments seation) - DISABLED for now
+    if(this._bScrollForFiles) {
+        oView.find('.' + this.sClassItem + ' .' + this.sClassItemAttachments + '.' + this.sSP + '-iaf-gallery').each(function() {
+            $this.initFlickityAttachments($(this));
+        });
+    }
+};
+
+BxTimelineMain.prototype.initFlickityByItem = function(oItem) {
+    //--- init Flickity for images (may be used in header section)
+    var oGalleryImages = $(oItem).find('.' + this.sClassItemImages + '.' + this.sSP + '-ii-gallery');
+    if(oGalleryImages.length > 0)
+        this.initFlickityImages(oGalleryImages);
+
+    //--- init Flickity for videos (may be used in header section)
+    var oGalleryVideos = $(oItem).find('.' + this.sClassItemVideos + '.' + this.sSP + '-iv-gallery');
+    if(oGalleryVideos.length > 0)
+        this.initFlickityVideos(oGalleryVideos);
+
+    //--- init Flickity for attachments (images and video in attachments seation)
+    var oGalleryAttachments = $(oItem).find('.' + this.sClassItemAttachments + '.' + this.sSP + '-ia-gallery');
+    if(oGalleryAttachments.length > 0)
+        this.initFlickityAttachments(oGalleryAttachments);
+};
+
+BxTimelineMain.prototype.initTrackerInsertSpace = function(sFormId, iEventId)
+{
+    var $this = this;
+    var oForm = $('#' + sFormId);
+    var oTextarea = oForm.find('textarea');
+
+    this._oAttachedLinks = [];
+
+    if (typeof window.glOnSpaceEnterInEditor === 'undefined')
+        window.glOnSpaceEnterInEditor = [];    
+
+    window.glOnSpaceEnterInEditor.push(function(sData, sSelector) {
+        if(!oTextarea.is(sSelector))
+            return;
+
+        $this.parseContent(oForm, iEventId, sData, true);
+    });
+};
+
+BxTimelineMain.prototype.parseContent = function(oForm, iId, sData, bPerformAttach)
+{
+    var oExp, aMatch = null;
+
+    oExp = new RegExp(this._sPregTag , "ig");
+    sData = sData.replace(oExp, '');
+
+    oExp = new RegExp(this._sPregMention , "ig");
+    sData = sData.replace(oExp, '');
+
+    oExp = new RegExp(this._sPregUrl , "ig");
+    while(aMatch = oExp.exec(sData)) {
+        var sUrl = aMatch[0].replace(/^(\s|(&nbsp;))+|(\s|(&nbsp;))+$/gm,'');        
+        if(!sUrl.length || this._oAttachedLinks[sUrl] != undefined || (this._iLimitAttachLinks != 0 && Object.keys(this._oAttachedLinks).length >= this._iLimitAttachLinks))
+            continue;
+
+        //--- Mark that 'attach link' process was started.
+        this._oAttachedLinks[sUrl] = 0;
+
+        if(bPerformAttach) {
+            this.lockForm(oForm);
+
+            this.addAttachLink(oForm, iId, sUrl);
+        }
+    }
+};
+
+BxTimelineMain.prototype.lockForm = function(oForm)
+{
+    if(this.isLockedForm(oForm))
+        return;
+
+    oForm.attr('bx_form_locked', 1).find('input[type="submit"],button[type="submit"]').addClass('bx-btn-disabled');
+};
+
+BxTimelineMain.prototype.unlockForm = function(oForm)
+{
+    if(!this.isLockedForm(oForm))
+        return;
+
+    oForm.removeAttr('bx_form_locked').find('input[type="submit"],button[type="submit"]').removeClass('bx-btn-disabled');
+};
+
+BxTimelineMain.prototype.isLockedForm = function(oForm)
+{
+    return oForm.attr('bx_form_locked') == 1;
+};
+
+BxTimelineMain.prototype.addAttachLink = function(oElement, iId, sUrl)
+{
+    if(!sUrl || (this._iLimitAttachLinks != 0 && Object.keys(this._oAttachedLinks).length > this._iLimitAttachLinks))
+        return;
+
+    var $this = this;
+    var oData = this._getDefaultData();
+    oData['url'] = sUrl;
+    if(iId != undefined)
+        oData['event_id'] = iId;
+
+    jQuery.post (
+        this._sActionsUrl + 'add_attach_link/',
+        oData,
+        function(oData) {
+            var iEventId = 0;
+            if(oData && oData.event_id != undefined)
+                iEventId = parseInt(oData.event_id);
+            
+            if(!oData.id || !oData.item || !$.trim(oData.item).length){
+                $this.unlockForm($('#' + $this._aHtmlIds['attach_link_form_field'] + iEventId).parents('form:first'));
+                return;
+            }
+
+            //--- Mark that 'attach link' process was finished.
+            $this._oAttachedLinks[sUrl] = oData.id;
+
+            var oItem = $(oData.item).hide();
+            $('#' + $this._aHtmlIds['attach_link_form_field'] + iEventId).prepend(oItem).find('#' + oItem.attr('id')).bx_anim('show', $this._sAnimationEffect, $this._sAnimationSpeed, function() {
+                $(this).bxProcessHtml();
+            });
+
+            $this.unlockForm($('#' + $this._aHtmlIds['attach_link_form_field'] + iEventId).parents('form:first'));
+        },
+        'json'
+    );
+};
+
+BxTimelineMain.prototype.onFindOverflow = function(oElement) {
+    $(oElement).after($(oElement).parents('.' + this.sClassView + ':first').find('.' + this.sSP + '-content-show-more:hidden:first').clone().show());
+};
+
+BxTimelineMain.prototype.loadingInButton = function(e, bShow) {
+    if($(e).length)
+        bx_loading_btn($(e), bShow);
+    else
+        bx_loading($('body'), bShow);	
+};
+
+BxTimelineMain.prototype.loadingInItem = function(e, bShow) {
+    var oParent = $('body');
+    if($(e).length)
+        oParent = !$(e).hasClass(this.sClassItem) ? $(e).parents('.' + this.sClassItem + ':first') : $(e);
+
+    bx_loading(oParent.find('.' + this.sClassItemCnt), bShow);
+};
+
+BxTimelineMain.prototype.loadingInBlock = function(e, bShow) {
+    var oParent = $(e).length ? $(e).parents('.bx-db-container:first') : $('body'); 
+    bx_loading(oParent, bShow);
+};
+
+BxTimelineMain.prototype.loadingInBlockHeaderCustom = function(e, bShow) {
+    var oParent = $(e).length ? $(e).parents('.bx-tl-v-header:first') : $('body'); 
+    bx_loading(oParent, bShow);
+};
+
+BxTimelineMain.prototype.loadingInPopup = function(e, bShow) {
+    var oParent = $(e).length ? $(e).parents('.bx-popup-content:first') : $('body'); 
+    bx_loading(oParent, bShow);
+};
+
+BxTimelineMain.prototype.loadingIn = function(e, bShow) {
+    var oElement = $(e);
+    var bElement = oElement.length > 0;
+
+    if(bElement && oElement.hasClass('bx-btn'))
+        this.loadingInButton(e, bShow);
+    else if(bElement && (oElement.hasClass(this.sClassItem) || oElement.parents('.' + this.sClassItem + ':first').length > 0))
+        this.loadingInItem(e, bShow);
+    else if(bElement && oElement.parents('.bx-popup-content:first').length > 0)
+        this.loadingInPopup(e, bShow);
+    else if(bElement && oElement.parents('.bx-db-container:first').length > 0)
+        this.loadingInBlock(e, bShow);
+    else if(bElement && oElement.parents('.bx-tl-v-header:first').length > 0)
+        this.loadingInBlockHeaderCustom(e, bShow);
+    else 
+        bx_loading($('body'), bShow);
+};
+
+BxTimelineMain.prototype._loading = function(e, bShow) {
+    var oParent = $(e).length ? $(e) : $('body'); 
+    bx_loading(oParent, bShow);
+};
+
+BxTimelineMain.prototype._getViewObject = function(oElement) {
+    oElement = $(oElement);
+
+    var oView = oElement;
+    if(oView.hasClass(this.sClassView))
+        return oView;
+
+    oView = oElement.parents('.' + this.sClassView + ':first');
+    if(oView.hasClass(this.sClassView))
+        return oView;
+
+    oView = oElement.parents('.bx-page-block-container:first').find('.' + this.sClassView + ':first');
+    if(oView.hasClass(this.sClassView))
+        return oView;
+
+    return null;
+};
+
+BxTimelineMain.prototype._getView = function(oElement) {
+    var oView = this._getViewObject(oElement);
+    if(!oView || oView.length == 0)
+        return '';
+
+    if(oView.hasClass(this.sClassView + '-item'))
+        return 'item';
+
+    if(oView.hasClass(this.sClassView + '-timeline'))
+        return 'timeline';
+
+    if(oView.hasClass(this.sClassView + '-outline'))
+        return 'outline';
+
+    if(oView.hasClass(this.sClassView + '-search'))
+        return 'search';
+
+    return '';
+};
+
+BxTimelineMain.prototype._getName = function(oData, oRules)
+{
+    oRules = jQuery.extend({}, oRules);
+
+    var bWithView = oRules.with_view === undefined || oRules.with_view === true;
+    var bWithType = oRules.with_type === undefined || oRules.with_type === true;
+    var bWithOwner = oRules.with_owner !== undefined && oRules.with_owner === true;
+    var sGlue = oRules.glue !== undefined && oRules.glue ? oRules.glue : '_';
+
+    var aAddons = [];
+    if(oData['name'])
+        aAddons.push(oData['name']);
+    else {
+        if(bWithView && oData['view'])
+            aAddons.push(oData['view']);
+
+        if(bWithType && oData['type'])
+            aAddons.push(oData['type']);
+    }
+
+    if(bWithOwner)
+        aAddons.push(this._iOwnerId);
+
+    return aAddons.length > 0 ? aAddons.join(sGlue) : '';
+};
+
+BxTimelineMain.prototype._getHtmlId = function(sKey, oData, oRules)
+{
+    oRules = jQuery.extend({}, oRules);
+
+    var bWhole = oRules.whole === undefined || oRules.whole === true;
+    var bHash = oRules.hash === undefined || oRules.hash === true;
+    var sGlue = oRules.glue !== undefined && oRules.glue ? oRules.glue : '_';
+
+    var sHtmlId = this.sId  + sGlue + sKey + sGlue + this._getName(oData, oRules) + (!bWhole ? sGlue : '');
+    if(!bHash)
+        sHtmlId = sHtmlId.substr(1);
+
+    return sHtmlId.replace(new RegExp(sGlue, 'g'), '-');
+};
+
+BxTimelineMain.prototype._getDefaultData = function() {
+    var oDate = new Date();
+    return jQuery.extend({}, this._oRequestParams, {_t:oDate.getTime()});
+};
+
+
+BxTimelineMain.prototype._getPost = function(oView, iId, aParams) {
+    var $this = this;
+    var oData = this._getDefaultData();
+    oData = jQuery.extend({}, oData, {js_object: this._sObjName, id: iId}, aParams != undefined ? aParams : {});
+
+    this.loadingInBlock(oView, true);
+
+    jQuery.post (
+        this._sActionsUrl + 'get_post/',
+        oData,
+        function(oData) {
+            $this.loadingInBlock(oView, false);
+
+            processJsonData(oData);
+        },
+        'json'
+    );
+};
+
+(function($) {
+    $.fn.checkOverflowHeight = function(sClass, onFind) {
+    	if(!sClass)
+    		sClass = 'bx-overflow';
+
+        return this.each(function() {
+            var oElement = $(this);
+            if(oElement.hasClass(sClass) || oElement.css('overflow') != 'hidden')
+            	return;
+            
+            if (oElement.find('img').length > 0){
+                var oImg = oElement.find('img').first();
+                var iRelImgY = oImg.offset().top - oElement.offset().top;
+                
+                const img = new Image();
+                img.src = oImg.prop('src');
+                img.onload = function() {
+                    if (iRelImgY < oElement.height() && iRelImgY + this.height > oElement.height()){
+                        oElement.css('max-height', (iRelImgY + this.height) +  50 + 'px');
+                    }
+                }
+            }
+
+            if(oElement.prop('scrollHeight') <= Math.ceil(oElement.height()))
+            	return;
+
+            oElement.addClass(sClass);
+            if(typeof onFind === 'function')
+            	onFind(oElement);
+        });
+    };
+})(jQuery);

+ 372 - 0
modules/boonex/timeline/updates/13.0.4_13.0.5/source/js/post.js

@@ -0,0 +1,372 @@
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Timeline Timeline
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+function BxTimelinePost(oOptions) {
+    this._sActionsUri = oOptions.sActionUri;
+    this._sActionsUrl = oOptions.sActionUrl;
+    this._sObjName = oOptions.sObjName == undefined ? 'oTimelinePost' : oOptions.sObjName;
+    this._iOwnerId = oOptions.iOwnerId == undefined ? 0 : parseInt(oOptions.iOwnerId);
+    this._sAnimationEffect = oOptions.sAnimationEffect == undefined ? 'slide' : oOptions.sAnimationEffect;
+    this._iAnimationSpeed = oOptions.iAnimationSpeed == undefined ? 'slow' : oOptions.iAnimationSpeed;
+    this._bEmoji = oOptions.bEmoji == undefined ? false : oOptions.bEmoji;
+    this._bAutoAttach = oOptions.bAutoAttach == undefined ? false : oOptions.bAutoAttach;
+    this._sAutoUploader = oOptions.sAutoUploader == undefined ? '' : oOptions.sAutoUploader;
+    this._sAutoUploaderId = oOptions.sAutoUploaderId == undefined ? '' : oOptions.sAutoUploaderId;
+    this._iLimitAttachLinks = oOptions.iLimitAttachLinks == undefined ? 0 : oOptions.iLimitAttachLinks;
+    this._sLimitAttachLinksErr = oOptions.sLimitAttachLinksErr == undefined ? '' : oOptions.sLimitAttachLinksErr;
+    this._oAttachedLinks = oOptions.oAttachedLinks == undefined ? {} : oOptions.oAttachedLinks;
+    this._sVideosAutoplay = oOptions.sVideosAutoplay == undefined ? 'off' : oOptions.sVideosAutoplay;
+    this._aHtmlIds = oOptions.aHtmlIds == undefined ? {} : oOptions.aHtmlIds;
+    this._oRequestParams = oOptions.oRequestParams == undefined ? {} : oOptions.oRequestParams;
+
+    var $this = this;
+    if (typeof window.glOnInitEditor === 'undefined')
+        window.glOnInitEditor = [];
+
+    if(this._bEmoji)
+        window.glOnInitEditor.push(function (sEditorSelector) {
+            var sBaseUrl = sUrlRoot + 'plugins_public/emoji/js/';
+            if ('undefined' === typeof(EmojiPicker)) {
+                bx_get_scripts([
+                    sBaseUrl + 'util.js', 
+                    sBaseUrl + 'config.js',
+                    sBaseUrl + 'emoji-picker.js', 
+                    sBaseUrl + 'jquery.emojiarea.js'
+                ], function() {
+                    $this.initEmoji(sEditorSelector)
+                });
+            }
+            else
+                $this.initEmoji(sEditorSelector);
+        });
+
+    $(document).ready(function () {
+        var oPost = $($this.sIdPost + ' form');
+        if(!oPost || oPost.length == 0)
+            oPost = $($this.sIdPostForm);
+
+    	oPost.each(function() {
+            var sId = $(this).attr('id');
+            $this.initFormPost(sId);
+    	});
+    });
+}
+
+BxTimelinePost.prototype = new BxTimelineMain();
+
+BxTimelinePost.prototype.initEmoji = function(sEditorSelector)
+{
+    if(!this._bEmoji)
+        return;
+
+    var oLink = $(sEditorSelector).parents('form:first').find('a.add-emoji');
+
+    var oEmojiConf = {
+        emojiable_selector: bx_editor_get_htmleditable(sEditorSelector), 
+        menu_icon: oLink  /* emoji popup menu icon */
+    };
+    new EmojiPicker(oEmojiConf ).discover();  /* call init emoji function */
+};
+
+BxTimelinePost.prototype.initFormPost = function(sFormId)
+{
+    var $this = this;
+    var oForm = $('#' + sFormId);
+    var oTextarea = oForm.find('textarea');
+    autosize(oTextarea);
+
+    oForm.ajaxForm({
+        dataType: "json",
+        beforeSubmit: function (formData, jqForm, options) {
+            window[$this._sObjName].beforeFormPostSubmit(oForm);
+        },
+        success: function (oData) {
+            window[$this._sObjName].afterFormPostSubmit(oForm, oData);
+        }
+    });
+
+    this.initTrackerInsertSpace(sFormId);
+
+    if(this._bAutoAttach) {
+        if (typeof window.glOnInsertImageInEditor === 'undefined')
+            window.glOnInsertImageInEditor = [];
+
+        window.glOnInsertImageInEditor.push(function (oFile) {
+            const oFormData = new FormData();
+            oFormData.append('file', oFile);
+            oFormData.append('u', $this._sAutoUploader);
+            oFormData.append('uid', $this._sAutoUploaderId);
+
+            fetch($this._sActionsUrl + 'auto_attach_insertion/', {method: "POST", body: oFormData})
+            .then(response => response.json())
+            .then(result => {
+                processJsonData(result)
+            });
+        });
+   }
+};
+
+BxTimelinePost.prototype.onFormPostSubmit = function(oForm)
+{
+    if(this.isLockedForm($(oForm)))
+        return false;
+
+    return true;
+};
+
+BxTimelinePost.prototype.beforeFormPostSubmit = function(oForm)
+{
+    this.loadingInButton($(oForm).children().find(':submit'), true);
+};
+
+BxTimelinePost.prototype.afterFormPostSubmit = function (oForm, oData)
+{
+    var $this = this;
+    var fContinue = function() {
+        if(oData && oData.form != undefined && oData.form_id != undefined) {
+            $('#' + oData.form_id).replaceWith(oData.form);
+            $this.initFormPost(oData.form_id);
+
+            return;
+        }
+
+        if(oData && oData.id != undefined) {
+            var iId = parseInt(oData.id);
+            if(iId <= 0) 
+                return;
+
+            $('.' + $this.sClassView + ':visible').each(function() {
+                var oView = $(this);
+                $this._getPost(oView, iId, jQuery.extend({}, $this._oRequestParams, {view: $this._getView(oView), afps_loading: 1}));
+            });
+        }
+
+        $this._getForm(oForm);
+    };
+
+    this.loadingInButton($(oForm).children().find(':submit'), false);
+
+    if(oData && oData.message != undefined)
+        bx_alert(oData.message, fContinue);
+    else
+        fContinue();
+};
+    
+BxTimelinePost.prototype.initFormAttachLink = function(sFormId)
+{
+    var $this = this;
+    var oForm = $('#' + sFormId);
+
+    oForm.ajaxForm({
+        dataType: "json",
+        clearForm: true,
+        beforeSubmit: function (formData, jqForm, options) {
+            window[$this._sObjName].beforeFormAttachLinkSubmit(oForm);
+        },
+        success: function (oData) {
+            window[$this._sObjName].afterFormAttachLinkSubmit(oForm, oData);
+        }
+    });
+};
+
+BxTimelinePost.prototype.beforeFormAttachLinkSubmit = function(oForm)
+{
+    this.loadingInButton($(oForm).children().find(':submit'), true);
+};
+
+BxTimelinePost.prototype.afterFormAttachLinkSubmit = function (oForm, oData)
+{
+    var $this = this;
+    var fContinue = function() {
+        if(oData && oData.item != undefined) {
+            $('#' + $this._aHtmlIds['attach_link_popup']).dolPopupHide({});
+
+            if(!$.trim(oData.item).length)
+                return;
+
+            //--- Mark that 'attach link' process was finished.
+            $this._oAttachedLinks[oData.url] = oData.id;
+
+            var iEventId = 0;
+            if(oData && oData.event_id != undefined)
+                iEventId = parseInt(oData.event_id);
+
+            var oItem = $(oData.item).hide();
+            $('#' + $this._aHtmlIds['attach_link_form_field'] + iEventId).prepend(oItem).find('#' + oItem.attr('id')).bx_anim('show', $this._sAnimationEffect, $this._sAnimationSpeed, function() {
+                $(this).bxProcessHtml();
+            });
+
+            $this.unlockForm($('#' + $this._aHtmlIds['attach_link_form_field'] + iEventId).parents('form:first'));
+            return;
+        }
+
+        if(oData && oData.form != undefined && oData.form_id != undefined) {
+            $('#' + oData.form_id).replaceWith(oData.form);
+            $this.initFormAttachLink(oData.form_id);
+
+            return;
+        }
+    };
+
+    this.loadingInButton($(oForm).find(':submit'), false);
+
+    if(oData && oData.message != undefined)
+        bx_alert(oData.message, fContinue);
+    else
+        fContinue();
+};
+
+BxTimelinePost.prototype.deleteAttachLink = function(oLink, iId)
+{
+    var $this = this;
+    var oData = this._getDefaultData();
+    oData['id'] = iId;
+
+    var oAttachLink = $('#' + this._aHtmlIds['attach_link_item'] + iId);
+    bx_loading(oAttachLink, true);
+    
+    jQuery.post (
+        this._sActionsUrl + 'delete_attach_link/',
+        oData,
+        function(oData) {
+            var fContinue = function() {
+                if(oData && oData.code != undefined && oData.code == 0) {
+                    oAttachLink.bx_anim('hide', $this._sAnimationEffect, $this._sAnimationSpeed, function() {
+                        $(this).remove;
+                    });
+                }
+            };
+
+            bx_loading(oAttachLink, false);
+
+            if(oData && oData.message != undefined)
+                bx_alert(oData.message, fContinue);
+            else
+                    fContinue();
+        },
+        'json'
+    );
+
+    return false;
+};
+
+BxTimelinePost.prototype.showAttachLink = function(oLink, iEventId)
+{
+    if(this._iLimitAttachLinks != 0 && Object.keys(this._oAttachedLinks).length >= this._iLimitAttachLinks) {
+        bx_alert(this._sLimitAttachLinksErr);
+        return false;
+    }
+
+    var oData = this._getDefaultData();
+    oData['event_id'] = iEventId;
+
+    $(window).dolPopupAjax({
+        id: {value: this._aHtmlIds['attach_link_popup'], force: true},
+        url: bx_append_url_params(this._sActionsUri + 'get_attach_link_form/', oData),
+        closeOnOuterClick: false,
+        removeOnClose: true
+    });
+
+    return false;
+};
+
+BxTimelinePost.prototype._getForm = function(oElement)
+{
+    var $this = this;
+    var oData = this._getDefaultData();
+
+    jQuery.post (
+        this._sActionsUrl + 'get_post_form/',
+        oData,
+        function(oData) {
+            if(oData && oData.form != undefined && oData.form_id != undefined) {
+                $('#' + oData.form_id).replaceWith(oData.form);
+                $this.initFormPost(oData.form_id);
+            }
+        },
+        'json'
+    );
+};
+
+BxTimelinePost.prototype._onGetPost = function(oData)
+{
+    var $this = this;
+    var fContinue = function(oData) {
+        if(!$.trim(oData.item).length) 
+            return;
+
+        var aTypes = Array.isArray(oData.type) ? oData.type : new Array(oData.type);
+        aTypes.forEach(function(sType) {
+            oData['type'] = sType;
+            $this.oView = $($this._getHtmlId('main', oData));
+
+            /*
+             * For backward compatibility.
+             * Current UPF: 'Post to Feed' and Timeline: 'Post to Feed' forms 
+             * should work with an old Account Feed ('Owner and Connections') block.
+             */
+            if(!$this.oView.length && oData['type'] == 'feed') {
+                oData['type'] = 'owner_and_connections';
+                $this.oView = $($this._getHtmlId('main', oData));
+            }
+
+            var oLoadMore = $this.oView.find('.' + $this.sSP + '-load-more');
+            if(!oLoadMore.is(':visible'))
+                oLoadMore.show();
+
+            var oEmpty = $this.oView.find('.' + $this.sSP + '-empty');
+            if(oEmpty.is(':visible'))
+                oEmpty.hide();
+
+            var oContent = $(oData.item).bxProcessHtml();
+            switch(oData.view) {
+                case 'timeline':
+                    var oItems = $this.oView.find('.' + $this.sClassItems);
+                    var oDivider  = oItems.find('.' + $this.sClassDividerToday);
+                    var bDivider = oDivider.length > 0;
+
+                    if(bDivider && !oDivider.is(':visible'))
+                        oDivider.show();
+
+                    oContent.hide();
+
+                    var oItem = bDivider ? oDivider.after(oContent).next('.' + $this.sClassItem + ':hidden') : oContent.prependTo(oItems);
+                    oItem.bx_anim('show', $this._sAnimationEffect, $this._iAnimationSpeed, function() {
+                        $(this).find('.bx-tl-item-text .bx-tl-content').checkOverflowHeight($this.sSP + '-overflow', function(oElement) {
+                            $this.onFindOverflow(oElement);
+                        });
+
+                        $this.initFlickity($this.oView);
+                    });
+
+                    if($this._sVideosAutoplay != 'off')
+                        $this.initVideos($this.oView);
+                    break;
+
+                case 'outline':
+                    $this.prependMasonry(oContent, function(oItems) {
+                        $(oItems).find('.bx-tl-item-text .bx-tl-content').checkOverflowHeight($this.sSP + '-overflow', function(oElement) {
+                            $this.onFindOverflow(oElement);
+                        });
+
+                        $this.initFlickity($this.oView);
+                    });
+                    break;
+            }
+        });
+    };
+
+    if(oData && oData.message != undefined && oData.message.length != 0)
+        bx_alert(oData.message, function() {
+                fContinue(oData);
+        });
+    else
+        fContinue(oData);
+};

+ 1430 - 0
modules/boonex/timeline/updates/13.0.4_13.0.5/source/js/view.js

@@ -0,0 +1,1430 @@
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Timeline Timeline
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+function BxTimelineView(oOptions) {
+    BxTimelineMain.call(this, oOptions);
+
+    this._sActionsUri = oOptions.sActionUri;
+    this._sActionsUrl = oOptions.sActionUrl;
+    this._sObjName = oOptions.sObjName == undefined ? 'oTimelineView' : oOptions.sObjName;
+    this._sObjNameMenuFeeds = oOptions.sObjNameMenuFeeds == undefined ? 'bx_timeline_menu_feeds' : oOptions.sObjNameMenuFeeds;
+    this._sName = oOptions.sName == undefined ? '' : oOptions.sName;
+    this._sView = oOptions.sView == undefined ? 'timeline' : oOptions.sView;
+    this._sType = oOptions.sType == undefined ? 'public' : oOptions.sType;
+    this._iOwnerId = oOptions.iOwnerId == undefined ? 0 : oOptions.iOwnerId;
+    this._sReferrer = oOptions.sReferrer == undefined ? '' : oOptions.sReferrer;
+    this._sAnimationEffect = oOptions.sAnimationEffect == undefined ? 'slide' : oOptions.sAnimationEffect;
+    this._iAnimationSpeed = oOptions.iAnimationSpeed == undefined ? 'slow' : oOptions.iAnimationSpeed;
+    this._sVideosAutoplay = oOptions.sVideosAutoplay == undefined ? 'off' : oOptions.sVideosAutoplay;
+    this._bEventsToLoad = oOptions.bEventsToLoad == undefined ? false : oOptions.bEventsToLoad;
+    this._bAutoMarkAsViewed = oOptions.bAutoMarkAsViewed == undefined ? false : oOptions.bAutoMarkAsViewed;
+    this._aMarkedAsViewed = oOptions.aMarkedAsViewed == undefined ? [] : oOptions.aMarkedAsViewed;
+    this._iLimitAttachLinks = oOptions.iLimitAttachLinks == undefined ? 0 : oOptions.iLimitAttachLinks;
+    this._sLimitAttachLinksErr = oOptions.sLimitAttachLinksErr == undefined ? '' : oOptions.sLimitAttachLinksErr;
+    this._oAttachedLinks = oOptions.oAttachedLinks == undefined ? {} : oOptions.oAttachedLinks;
+    this._aHtmlIds = oOptions.aHtmlIds == undefined ? {} : oOptions.aHtmlIds;
+    this._oRequestParams = oOptions.oRequestParams == undefined ? {} : oOptions.oRequestParams;
+
+    this._bInfScroll = oOptions.bInfScroll == undefined ? false : oOptions.bInfScroll;
+    this._iInfScrollAutoPreloads = oOptions.iInfScrollAutoPreloads == undefined ? 10 : oOptions.iInfScrollAutoPreloads;
+    this._sInfScrollAfter = 'item';
+    this._iInfScrollAfterItem = 2; //--- Preload more info when scroll reached N item from the end of Timeline block.
+    this._fInfScrollAfterPercent = 0.25; //--- Preload more info when specified portion of Timeline block's content was already scrolled.
+    this._bInfScrollBusy = false;
+    this._iInfScrollPreloads = 1; //--- First portion is loaded with page loading or 'Load More' button click.
+
+    this._fOutsideOffset = 0.8;
+    this._oSaved = {};
+
+    this._fVapOffsetStart = 0.8;
+    this._fVapOffsetStop = 0.2;
+
+    this._bLiveUpdatePaused = false;
+
+    this._oFiltersPopupOptions = {};
+
+    if(typeof window.glBxTimelineVapPlayers === 'undefined')
+        window.glBxTimelineVapPlayers = [];
+
+    //--- Use Scroll for Attachments.
+    this._bScrollForFiles = true;
+
+    this._bAutoMarkBusy = false;
+    
+    //--- Get currently active 'view'.
+    this.initView();
+
+    //--- Initialize components on currently active 'view'.
+    this.init();
+}
+
+BxTimelineView.prototype = Object.create(BxTimelineMain.prototype);
+BxTimelineView.prototype.constructor = BxTimelineView;
+
+BxTimelineView.prototype.init = function(bForceInit)
+{
+    var $this = this;
+
+    if(!this.oView || bForceInit)
+        this.initView();
+
+    if(this.bViewTimeline) {
+        //-- Check content to show 'See More'
+        this.initSeeMore(this.oView, true);
+
+        //--- Init Video Autoplay
+        if(this._sVideosAutoplay != 'off') {
+            this.initVideosAutoplay(this.oView);
+
+            this.oView.on('hide')
+
+            $(window).on('scroll', function() {
+                if(!$this.oView.is(':visible'))
+                    return;
+
+                if(!window.requestAnimationFrame) 
+                    setTimeout(function() {
+                        $this.autoplayVideos($this.oView, $this._fVapOffsetStart, $this._fVapOffsetStop);
+                    }, 100);
+                else
+                    window.requestAnimationFrame(function() {
+                        $this.autoplayVideos($this.oView, $this._fVapOffsetStart, $this._fVapOffsetStop);
+                    });
+            });
+        }
+
+        //--- Blink (highlight) necessary items
+        this.blink(this.oView);
+
+        //--- Load 'Jump To'
+        this.initJumpTo(this.oView);
+
+        //--- Init 'Infinite Scroll'
+        this.initInfiniteScroll(this.oView);
+
+        //--- Init calendar
+        this.initCalendar();
+
+        //--- Init mark as viewed
+        if(this._bAutoMarkAsViewed) {
+            $(window).on('scroll', function() {
+                if(!$this.oView.is(':visible'))
+                    return;
+
+                if(!window.requestAnimationFrame) 
+                    setTimeout(function() {
+                        $this.markPostAsViewed($this.oView);
+                    }, 100);
+                else
+                    window.requestAnimationFrame(function() {
+                        $this.markPostAsViewed($this.oView);
+                    });
+            });
+        }
+    }
+
+    if(this.bViewOutline) {
+        this.initMasonry();
+
+        this.oView.find('.' + this.sClassItem).resize(function() {
+            $this.reloadMasonry();
+        });
+        this.oView.find('img.' + this.sClassItemImage).load(function() {
+            $this.reloadMasonry();
+        });
+
+        //--- Init Video Layout
+        if(this._sVideosAutoplay != 'off')
+            this.initVideos(this.oView);
+
+        //--- Blink (highlight) necessary items
+        this.blink(this.oView);
+
+        //--- Load 'Jump To'
+        this.initJumpTo(this.oView);
+
+        //--- Init 'Infinite Scroll'
+        this.initInfiniteScroll(this.oView);
+    }
+
+    if(this.bViewItem) {
+        //-- Check content to show 'See More'
+        this.initSeeMore(this.oView, false);
+
+        //--- Init Video Layout
+        if(this._sVideosAutoplay != 'off')
+            this.initVideos(this.oView);
+    }
+
+    //--- Init Flickity
+    this.initFlickity(this.oView);
+};
+
+BxTimelineView.prototype.initView = function() 
+{   
+    BxTimelineMain.prototype.initView.call(this);
+
+    this.oView = $(this._getHtmlId('main', this._oRequestParams));
+    if(!this.oView.length) 
+        return;
+
+    if(this.oView.hasClass(this.sClassView + '-timeline'))
+        this.bViewTimeline = true;
+    else if(this.oView.hasClass(this.sClassView + '-outline'))
+        this.bViewOutline = true;
+    else if(this.oView.hasClass(this.sClassView + '-item'))
+        this.bViewItem = true;
+};
+
+BxTimelineView.prototype.initSeeMore = function(oParent, bInItems)
+{
+    var $this = this;
+
+    var oSubParent = oParent;
+    if(bInItems)
+        oSubParent = oParent.find('.' + this.sClassItem);
+
+    oSubParent.find('.bx-tl-item-text .bx-tl-content').checkOverflowHeight(this.sSP + '-overflow', function(oElement) {
+        $this.onFindOverflow(oElement);
+    });
+
+    if(oSubParent.find('.bx-tl-item-text .bx-tl-content .bx-embed-link').length != 0)
+        setTimeout(function() {
+            oSubParent.find('.bx-tl-item-text .bx-tl-content:not(.' +  $this.sSP + '-overflow)').has('.bx-embed-link').checkOverflowHeight($this.sSP + '-overflow', function(oElement) {
+                $this.onFindOverflow(oElement);
+            });
+        }, 4000);
+};
+
+BxTimelineView.prototype.initJumpTo = function(oParent)
+{
+    var oJumpTo = $(oParent).find('.' + this.sClassJumpTo);
+    if(!oJumpTo || oJumpTo.length == 0 || oJumpTo.html() != '')
+        return;
+
+    bx_loading_btn(oJumpTo, true);
+
+    jQuery.post (
+        this._sActionsUrl + 'get_jump_to/',
+        this._getDefaultData(oParent),
+        function(oData) {
+            oData.holder = oJumpTo;
+
+            processJsonData(oData);
+        },
+        'json'
+    );
+};
+
+BxTimelineView.prototype.onGetJumpTo = function(oData)
+{
+    if(!oData.holder || oData.content == undefined)
+        return;
+
+    $(oData.holder).html(oData.content);
+};
+
+BxTimelineView.prototype.initInfiniteScroll = function(oParent)
+{
+    var $this = this;
+
+    if(!this._bInfScroll || !this._bEventsToLoad)
+        return;
+
+    $(window).bind('scroll', function(oEvent) {
+        if(!$this.oView.is(':visible'))
+            return;
+
+        if($this.oView.attr('id') != $this._getHtmlId('main', {name: $this._sName, view: $this._sView, type: $this._sType}, {hash: false}))
+            return;
+
+        if(!$this._bEventsToLoad || $this._bInfScrollBusy || $this._iInfScrollPreloads >= $this._iInfScrollAutoPreloads)
+            return;
+
+        var iScrollTop = parseInt($(window).scrollTop());
+        var iWindowHeight = $(window).height();
+
+        //--- Auto-scroll by reaching the N item from the end of parent block.
+        if($this._sInfScrollAfter == 'item') {
+            var oItems = oParent.find('.' + $this.sClassItem);
+            if((iScrollTop + iWindowHeight) <= ($(oItems.get(oItems.length - $this._iInfScrollAfterItem)).offset().top))
+                return;
+        }
+
+        //--- Auto-scroll by reaching the percent of parent block's height.
+        if($this._sInfScrollAfter == 'percent') {
+            var iParentTop = parseInt(oParent.offset().top);
+            var iParentHeight = parseInt(oParent.height());
+            if((iScrollTop + iWindowHeight) <= (iParentTop + iParentHeight * $this._fInfScrollAfterPercent))
+                return;
+        }
+
+        $this._bInfScrollBusy = true;
+        $this._getPage(undefined, $this._oRequestParams.start + $this._oRequestParams.per_page, $this._oRequestParams.per_page, function(oData) {
+            $this._bEventsToLoad = oData.events_to_load;
+            $this._iInfScrollPreloads += 1;
+            $this._bInfScrollBusy = false;
+        });
+    });
+};
+
+BxTimelineView.prototype.initVideosAutoplay = function(oParent)
+{
+    var $this = this;
+
+    if(this._sVideosAutoplay == 'off')
+        return;
+
+    this.initVideos(oParent);
+
+    var sPrefix = oParent.hasClass(this.sClassView) ? oParent.attr('id') : oParent.parents('.' + this.sClassView + ':first').attr('id');
+
+    oParent.find('iframe').each(function() {
+        var sPlayer = sPrefix + '_' + $(this).attr('id');
+        if(window.glBxTimelineVapPlayers[sPlayer])
+            return;
+
+        var oPlayer = new playerjs.Player(this);
+        if($this._sVideosAutoplay == 'on_mute')
+            oPlayer.mute();
+
+        var fFixHeight = function () {
+            $('#' + sPlayer).height(($('#' + sPlayer).contents().find('video').height()) + 'px');
+        };
+        oPlayer.on('ready', fFixHeight);
+        oPlayer.on('play', fFixHeight);
+
+        window.glBxTimelineVapPlayers[sPlayer] = oPlayer;
+    });
+};
+
+BxTimelineView.prototype.autoplayVideos = function(oView, fOffsetStart, fOffsetStop)
+{
+    var $this = this;
+
+    var oItems = oView.find('.' + this.sClassItem);
+    var sPrefix = oView.attr('id') + '_';
+
+    oItems.each(function() {
+        $(this).find('iframe').each(function() {
+            var oFrame = $(this);
+            var oPlayer = window.glBxTimelineVapPlayers[sPrefix + oFrame.attr('id')];
+            if(!oPlayer)
+                return;
+
+            var iFrameTop = oFrame.offset().top;
+            var iFrameBottom = iFrameTop + oFrame.height();
+            var iWindowTop = $(window).scrollTop();
+            var iWindowHeight = $(window).height();
+            if(iFrameTop <= iWindowTop + iWindowHeight * fOffsetStart && iFrameBottom >= iWindowTop + iWindowHeight * fOffsetStop)
+                oPlayer.play();
+            else
+                oPlayer.pause();
+        });
+    });
+};
+
+BxTimelineView.prototype.playVideos = function(oView)
+{
+    var $this = this;
+
+    var oItems = oView.find('.' + this.sClassItem);
+    var sPrefix = oView.attr('id') + '_';
+
+    oItems.each(function() {
+        $(this).find('iframe').each(function() {
+            var oFrame = $(this);
+            var oPlayer = window.glBxTimelineVapPlayers[sPrefix + oFrame.attr('id')];
+            if(!oPlayer)
+                return;
+
+            oPlayer.play();
+        });
+    });
+};
+
+BxTimelineView.prototype.pauseVideos = function(oView)
+{
+    var $this = this;
+
+    var oItems = oView.find('.' + this.sClassItem);
+    var sPrefix = oView.attr('id') + '_';
+
+    oItems.each(function() {
+        $(this).find('iframe').each(function() {
+            var oFrame = $(this);
+            var oPlayer = window.glBxTimelineVapPlayers[sPrefix + oFrame.attr('id')];
+            if(!oPlayer)
+                return;
+
+            oPlayer.pause();
+        });
+    });
+};
+
+BxTimelineView.prototype.reload = function(oSource, onLoad)
+{
+    var $this = this;
+
+    this.loadingInBlock(oSource, true);
+
+    this._oRequestParams.start = 0;
+    this._getPosts(oSource, function(oData) {
+        processJsonData(oData);
+
+        $this.init(true);
+
+        if(typeof onLoad == 'function')
+            onLoad();
+    });
+};
+
+BxTimelineView.prototype.changeFeed = function(oLink, sType, oRequestParams)
+{
+    var $this = this;
+    var oViews = $(this._getHtmlId('views_content', this._oRequestParams, {with_type: false})); 
+    var oViewActive = oViews.children(':visible');
+
+    if(this._sVideosAutoplay != 'off')
+        this.pauseVideos(oViewActive);
+
+    var sFilters = this._getHtmlId('filters_popup', jQuery.extend({}, this._oRequestParams, {name: ''}));
+    if($(sFilters).length)
+        $(sFilters).remove();
+
+    this._oRequestParams.type = sType;
+    oRequestParams = jQuery.extend({}, this._oRequestParams, {
+        name: '',
+        start: 0
+    }, oRequestParams);
+
+    var oData = this._getDefaultData(oLink);
+    oData = jQuery.extend({}, oData, oRequestParams);
+
+    var sView = $this._getHtmlId('main', oRequestParams);
+
+    var oTab = $(oLink);
+    var sTabActive = 'bx-menu-tab-active';
+    var sTabActiveBg = 'bx-def-color-bg-active';
+    oTab.parents('ul.' + this.sSP + '-menu-feeds').find('li.' + sTabActive).removeClass(sTabActive + ' ' + sTabActiveBg);
+    oTab.parents('li:first').addClass(sTabActive + ' ' + sTabActiveBg);
+
+    this.loadingIn(oLink, true);
+
+    jQuery.get (
+        this._sActionsUrl + 'get_view',
+        oData,
+        function(oResponse) {
+            if(oLink)
+                $this.loadingIn(oLink, false);
+
+            if(!oResponse.content)
+                return;
+
+            oViewActive.hide('fast', function() {
+                oViews.html('').append(oResponse.content).find(sView).bxProcessHtml();
+            });
+        },
+        'json'
+    );
+
+    return false;
+};
+
+BxTimelineView.prototype.changeFeedFilters = function(oLink, oRequestParams)
+{
+    var $this = this;
+
+    oRequestParams = jQuery.extend({}, this._oRequestParams, {
+        name: '',
+        start: 0
+    }, oRequestParams);
+
+    var sFilters = this._getHtmlId('filters_popup', oRequestParams);
+    if($(sFilters).length)
+        return $(sFilters).dolPopup(this._oFiltersPopupOptions);
+
+    var oData = this._getDefaultData(oLink);
+    if(oRequestParams != undefined)
+        oData = jQuery.extend({}, oData, oRequestParams);
+
+    this.loadingIn(oLink, true);
+
+    jQuery.get (
+        this._sActionsUrl + 'get_view_filters',
+        oData,
+        function(oResponse) {
+            if(oLink)
+                $this.loadingIn(oLink, false);
+
+            if(oResponse && oResponse.popup != undefined) {
+                $this._oFiltersPopupOptions = jQuery.extend({}, oResponse.popup.options, {
+                    pointer: { 
+                        el: $(oLink),
+                        align: 'right'
+                    }
+                });
+
+                oResponse.popup.options = $this._oFiltersPopupOptions;
+            }
+
+            processJsonData(oResponse);
+        },
+        'json'
+    );
+};
+
+BxTimelineView.prototype.toggleMenuItemFeeds = function(oSource)
+{
+    bx_menu_toggle(oSource, this._sObjNameMenuFeeds);
+};
+
+BxTimelineView.prototype.onFilterByModuleChange = function(oSource)
+{
+    var oModules = $(oSource).parents('.bx-form-element-wrapper:first').siblings('.modules');
+    oModules.find("input[name='modules[]']:checked").removeAttr('checked');
+    oModules.bx_anim($(oSource).val() == 'selected' ? 'show' : 'hide');
+};
+
+BxTimelineView.prototype.onFilterApply = function(oSource)
+{
+    var $this = this;
+    var sView = this._getHtmlId('main', this._oRequestParams); 
+    var oFilters = $(oSource).parents('.bx-tl-view-filters:first');
+
+    this._oRequestParams.start = 0;
+    this._oRequestParams.modules = [];
+    if(oFilters.find("input[name='by_module']:checked").val() == 'selected')
+        oFilters.find("input[name='modules[]']:checked").each(function() {
+            $this._oRequestParams.modules.push($(this).val());
+        });
+
+    var oData = this._getDefaultData(oSource);
+
+    this.loadingIn(oSource, true);
+
+    jQuery.get (
+        this._sActionsUrl + 'get_view',
+        oData,
+        function(oResponse) {
+            if(oSource)
+                $this.loadingIn(oSource, false);
+
+            if(!oResponse.content)
+                return;
+
+            $('.bx-popup-applied:visible').dolPopupHide();
+
+            $(sView).replaceWith(oResponse.content);
+            $(sView).bxProcessHtml();
+        },
+        'json'
+    );
+};
+
+BxTimelineView.prototype.changeView = function(oLink, sType, oRequestParams)
+{
+    var $this = this;
+    var oViews = $(this._getHtmlId('views_content', this._oRequestParams, {with_type: false})); 
+
+    var oViewBefore = $(this._getHtmlId('main', this._oRequestParams));
+    if(!oViewBefore.length)
+        oViewBefore = oViews.children(':visible');
+
+    var oViewPlaceholder = $(this._getHtmlId('main', jQuery.extend({}, this._oRequestParams, {type: 'placeholder'})));
+    var bViewPlaceholder = oViewPlaceholder && oViewPlaceholder.length != 0;
+
+    if(this._sVideosAutoplay != 'off')
+        this.pauseVideos(oViewBefore);
+
+    this._oRequestParams.start = 0;
+    this._oRequestParams.type = sType;
+
+    var oTab = $(oLink);
+    var sTabActive = 'bx-menu-tab-active';
+    oTab.parents('.bx-db-menu:first').find('li.' + sTabActive).removeClass(sTabActive);
+    oTab.parents('li:first').addClass(sTabActive);
+
+    var sView = this._getHtmlId('main', this._oRequestParams);
+    if(oViews.find(sView).length !== 0) {
+        oViewBefore.hide();
+        if(bViewPlaceholder) {
+            oViewPlaceholder.bx_anim('show', this._sAnimationEffect, this._iAnimationSpeed, function() {
+                oViewPlaceholder.hide();
+                oViews.find(sView).show();
+            });            
+        }
+        else
+            oViews.find(sView).show();
+
+        this.initView();
+        return;
+    }
+
+    var oData = this._getDefaultData(oLink);
+    if(oRequestParams != undefined)
+        oData = jQuery.extend({}, oData, oRequestParams);
+
+    if(bViewPlaceholder) {
+        oViewBefore.hide();
+        oViewPlaceholder.show();
+    }
+    else
+        this.loadingIn(oLink, true);
+
+    jQuery.get (
+        this._sActionsUrl + 'get_view',
+        oData,
+        function(oResponse) {
+            if(bViewPlaceholder)
+                oViewPlaceholder.hide();
+            else
+                $this.loadingIn(oLink, false);                
+
+            if(!oResponse.content) {
+                if(oViewBefore.is(':hidden'))
+                    oViewBefore.show();
+
+                return;
+            }
+
+            oViews.append(oResponse.content).find(sView).bxProcessHtml();
+        },
+        'json'
+    );
+};
+
+BxTimelineView.prototype.changePage = function(oLink, iStart, iPerPage, onLoad)
+{
+    if(this._bInfScroll)
+        this._iInfScrollPreloads = 1;
+
+    this._getPage(oLink, iStart, iPerPage, onLoad);
+};
+
+BxTimelineView.prototype.changeFilter = function(oLink)
+{
+    var sId = $(oLink).attr('id');
+    sId = sId.substr(sId.lastIndexOf('-') + 1, sId.length);
+
+    this.loadingInBlock(oLink, true);
+
+    this._oRequestParams.start = 0;
+    this._oRequestParams.filter = sId;
+    this._getPosts(oLink);
+};
+
+BxTimelineView.prototype.changeTimeline = function(oLink, sDate)
+{
+    var $this = this;
+
+    oLink = $(oLink);
+    var bLink = oLink.length > 0;
+    var bLoadingInButton = bLink && oLink.hasClass('bx-btn');
+
+    if(bLink) {
+        if(bLoadingInButton)
+            this.loadingInButton(oLink, true);
+        else
+            this.loadingInBlock(oLink, true);
+    }
+
+    this._oRequestParams.start = 0;
+    this._oRequestParams.timeline = sDate;
+    this._getPosts(oLink, function(oData) {
+        if(bLink) {
+            if(bLoadingInButton)
+                $this.loadingInButton(oLink, false);
+            else
+                $this.loadingInBlock(oLink, false);
+        }
+
+        window.scrollTo(0, $this.oView.offset().top - 150);
+
+        processJsonData(oData);
+    });
+};
+
+BxTimelineView.prototype.initCalendar = function()
+{
+    var $this = this;
+    var oInput = $('.' + $this.sSP + '-jump-to-calendar');
+    if(!oInput.length)
+        return;
+
+    var oInputPicker = oInput.parents('.flatpickr:first');
+    if(!oInputPicker.length)
+        return;
+
+    flatpickr(oInputPicker.get(0), {
+        wrap: true,
+        dateFormat: "Y-m-d",
+        minDate: 1900,
+        maxDate: "today",
+        onValueUpdate: function(aDates, sDate, oPicker){
+            $this.changeTimeline(oInputPicker.find('.bx-btn'), sDate);
+        }
+    });
+};
+
+/**
+ * Isn't needed for now, because 'flatpickr' picker is used.
+ * Saved for possible future usage.
+ */
+BxTimelineView.prototype.showCalendar = function(oLink)
+{
+};
+
+BxTimelineView.prototype.showMore = function(oLink)
+{
+    var sClassOverflow = this.sSP + '-overflow';
+
+    $(oLink).parents('.' + this.sClassItem + ':first').find('.' + sClassOverflow).css('max-height', 'none').removeClass(sClassOverflow);
+    $(oLink).parents('.' + this.sSP + '-content-show-more:first').remove();
+
+    if(this.bViewOutline)
+        this.reloadMasonry();
+};
+
+BxTimelineView.prototype.showItem = function(oLink, iId, sMode, oParams)
+{
+    var $this = this;
+    var oData = $.extend({}, this._getDefaultData(), {id: iId, mode: sMode}, (oParams != undefined ? oParams : {}));
+
+    $(".bx-popup-full-screen.bx-popup-applied:visible").dolPopupHide();
+
+    $(window).dolPopupAjax({
+        id: {
+            value: this._getHtmlId('item_popup', this._oRequestParams, {whole: false, hash: false}) + iId, 
+            force: true
+        },
+        url: bx_append_url_params(this._sActionsUrl + 'get_item_brief', oData),
+        closeOnOuterClick: false,
+        removeOnClose: true,
+        fullScreen: true,
+        displayMode: 'box',
+        onLoad: function(oPopup) {
+            var sClassImages = $this.sSP + '-bview-images';
+            var sClassImage = $this.sSP + '-bview-image';
+            var oParent = $(oPopup).find('.' + sClassImages);
+
+            if(oParent.length > 0 && oParent.find('.' + sClassImage).length > 1)
+                $this.initFlickityImages(oParent, '.' + sClassImage);
+        }
+    });
+
+    return false;
+};
+
+BxTimelineView.prototype.commentItem = function(oLink, sSystem, iId)
+{
+    var $this = this;
+    var oData = this._getDefaultData(oLink);
+    oData['system'] = sSystem;
+    oData['id'] = iId;
+
+    var oComments = $(oLink).parents('.' + this.sClassItem + ':first').find('.' + this.sClassItemComments);
+    if(oComments.children().length > 0) {
+        oComments.bx_anim('toggle', this._sAnimationEffect, this._iAnimationSpeed);
+        $(oLink).parents('.cmt-counter').toggleClass('cmt-counter-opened');
+    	return;
+    }
+
+    if(oLink)
+    	this.loadingInItem(oLink, true);
+
+    jQuery.get (
+        this._sActionsUrl + 'get_comments',
+        oData,
+        function(oData) {
+            if(oLink)
+                $this.loadingInItem(oLink, false);
+
+            if(!oData.content)
+                return;
+
+            oComments.html($(oData.content).hide()).children(':hidden').bxProcessHtml().bx_anim('show', $this._sAnimationEffect, $this._iAnimationSpeed);
+            $(oLink).parents('.cmt-counter').toggleClass('cmt-counter-opened');
+        },
+        'json'
+    );
+};
+
+BxTimelineView.prototype.pinPost = function(oLink, iId, iWay)
+{
+    this._markPost(oLink, iId, iWay, 'pin');
+};
+
+BxTimelineView.prototype.onPinPost = function(oData)
+{
+    this._onMarkPost(oData, 'pin');
+};
+
+BxTimelineView.prototype.stickPost = function(oLink, iId, iWay)
+{
+    this._markPost(oLink, iId, iWay, 'stick');
+};
+
+BxTimelineView.prototype.onStickPost = function(oData)
+{
+    this._onMarkPost(oData, 'stick');
+};
+
+BxTimelineView.prototype.promotePost = function(oLink, iId, iWay)
+{
+    var $this = this;
+    var oData = this._getDefaultData();
+    oData['id'] = iId;
+
+    $(oLink).parents('.bx-popup-applied:first:visible').dolPopupHide({
+        onHide: function(oPopup) {
+            $(oPopup).remove();
+        }
+    });
+
+    var oLoadingContainer = $(this._getHtmlId('item', this._oRequestParams, {whole: false}) + iId);
+
+    this.loadingInItem(oLoadingContainer, true);
+
+    $.post(
+        this._sActionsUrl + 'promote/',
+        oData,
+        function(oData) {
+            $this.loadingInItem(oLoadingContainer, false);
+
+            processJsonData(oData);
+        },
+        'json'
+    );
+};
+
+BxTimelineView.prototype.markPostAsViewed = function(oView)
+{
+    var $this = this;
+
+    var oItems = oView.find('.' + this.sClassItem);
+    var sPrefix = this._getHtmlId('item', this._oRequestParams, {whole: false}).replace('#', '');
+
+    oItems.each(function() {
+        if($this._bAutoMarkBusy)
+            return;
+
+        var oItem = $(this);
+        var iId = parseInt(oItem.attr('id').replace(sPrefix, ''));
+        if($this._aMarkedAsViewed.includes(iId))
+            return;
+
+        var iItemTop = oItem.offset().top;
+        var iItemBottom = iItemTop + oItem.height();
+        var iWindowTop = $(window).scrollTop();
+        var iWindowHeight = $(window).height();
+        if(iItemBottom < iWindowTop + iWindowHeight) {
+            $this._bAutoMarkBusy = true;
+
+            var oData = $this._getDefaultData();
+            oData['id'] = iId;
+
+            $.post(
+                $this._sActionsUrl + 'mark_as_read/',
+                oData,
+                function(oData) {
+                    if(oData && oData.id != undefined)
+                        $this._aMarkedAsViewed.push(oData.id);
+
+                    $this._bAutoMarkBusy = false;
+                },
+                'json'
+            );
+        }
+    });
+};
+
+BxTimelineView.prototype.muteAuthor = function(oLink, iId)
+{
+    var $this = this;
+    var oData = this._getDefaultData();
+    oData['id'] = iId;
+
+    $(oLink).parents('.bx-popup-applied:first:visible').dolPopupHide({
+        onHide: function(oPopup) {
+            $(oPopup).remove();
+        }
+    });
+
+    var oLoadingContainer = $(this._getHtmlId('item', this._oRequestParams, {whole: false}) + iId);
+
+    this.loadingInItem(oLoadingContainer, true);
+
+    $.post(
+        this._sActionsUrl + 'mute/',
+        oData,
+        function(oData) {
+            $this.loadingInItem(oLoadingContainer, false);
+
+            processJsonData(oData);
+        },
+        'json'
+    );
+};
+
+BxTimelineView.prototype.initFormEdit = function(sFormId, iEventId)
+{
+    var $this = this;
+    var oForm = $('#' + sFormId);
+    var oTextarea = oForm.find('textarea');
+
+    autosize(oTextarea);
+
+    oForm.ajaxForm({
+        dataType: "json",
+        beforeSubmit: function (formData, jqForm, options) {
+            window[$this._sObjName].beforeFormEditSubmit(oForm);
+        },
+        success: function (oData) {
+            window[$this._sObjName].afterFormEditSubmit(oForm, oData);
+        }
+    });
+
+    this.initTrackerInsertSpace(sFormId, iEventId);
+
+    var sContent = oTextarea.val();
+    if(sContent && sContent.length > 0)
+        this.parseContent(oForm, iEventId, sContent, false);
+};
+
+BxTimelineView.prototype.beforeFormEditSubmit = function(oForm)
+{
+    this.loadingInButton($(oForm).children().find(':submit'), true);
+};
+
+BxTimelineView.prototype.afterFormEditSubmit = function (oForm, oData)
+{
+    var $this = this;
+    var fContinue = function() {
+        var iId = 0;
+        if(oData && oData.id != undefined)
+            iId = parseInt(oData.id);
+
+        if(oData && oData.form != undefined && oData.form_id != undefined) {
+            $('#' + oData.form_id).replaceWith(oData.form);
+            $this.initFormEdit(oData.form_id, iId);
+
+            return;
+        }
+
+        if(iId > 0) 
+            $this._getPost($this.oView, iId, $this._oRequestParams);
+    };
+
+    this.loadingInButton($(oForm).children().find(':submit'), false);
+
+    if(oData && oData.message != undefined)
+        bx_alert(oData.message, fContinue);
+    else
+        fContinue();
+};
+
+BxTimelineView.prototype.editPost = function(oLink, iId)
+{
+    var $this = this;
+    var oData = this._getDefaultData(oLink);
+    oData['id'] = iId;
+
+    $(oLink).parents('.bx-popup-applied:first:visible').dolPopupHide();
+
+    var oItem = this.oView.find(this._getHtmlId('item', this._oRequestParams, {whole: false}) + iId);
+
+    var oContent = oItem.find('.' + this.sClassItemContent);
+    if(oContent.find('form').length) {
+        $(oContent).bx_anim('hide', this._sAnimationEffect, this._iAnimationSpeed, function() {
+            $(this).html($this._oSaved[iId]).bx_anim('show', $this._sAnimationEffect, $this._iAnimationSpeed);
+        });
+        return;
+    }
+    else
+        this._oSaved[iId] = oContent.html();
+
+    this.loadingInItem(oItem, true);
+
+    jQuery.post (
+        this._sActionsUrl + 'get_edit_form/' + iId + '/',
+        oData,
+        function (oData) {
+            processJsonData(oData);
+        },
+        'json'
+    );
+};
+
+BxTimelineView.prototype.onEditPost = function(oData)
+{
+    var $this = this;
+
+    if(!oData || !oData.id)
+        return;
+
+    var oItem = $(this._getHtmlId('item', this._oRequestParams, {whole: false}) + oData.id);
+
+    this.loadingInItem(oItem, false);
+
+    if(oData && oData.form != undefined && oData.form_id != undefined) {
+        oItem.find('.' + this.sClassItemContent).bx_anim('hide', this._sAnimationEffect, this._iAnimationSpeed, function() {
+            $(this).html(oData.form).bx_anim('show', $this._sAnimationEffect, $this._iAnimationSpeed, function() {
+                $this.initFormEdit(oData.form_id, oData.id);
+            });
+        });
+    }
+};
+
+BxTimelineView.prototype.editPostCancel = function(oButton, iId)
+{
+    this.editPost(oButton, iId);
+};
+
+BxTimelineView.prototype.deletePost = function(oLink, iId)
+{
+    var $this = this;
+
+    $(oLink).parents('.bx-popup-applied:first:visible').dolPopupHide();
+
+    bx_confirm('', function() {
+        var oData = $this._getDefaultData();
+        oData['id'] = iId;
+
+        $this.loadingInItem($($this._getHtmlId('item', $this._oRequestParams, {whole: false}) + iId), true);
+
+        $.post(
+            $this._sActionsUrl + 'delete/',
+            oData,
+            function(oData) {
+                processJsonData(oData);
+            },
+            'json'
+        );
+    });
+};
+
+BxTimelineView.prototype.onDeletePost = function(oData)
+{
+    var $this = this;
+    var oItem = $(this._getHtmlId('item', this._oRequestParams, {whole: false}) + oData.id);
+
+    //--- Delete from 'Timeline' (if available)
+    if(this.bViewTimeline) {
+        oItem.bx_anim('hide', this._sAnimationEffect, this._iAnimationSpeed, function() {
+            $(this).remove();
+
+            if($this.oView.find('.' + $this.sClassItem).length == 0) {
+                $this.oView.find('.' + $this.sClassDividerToday).hide();
+                $this.oView.find('.' + $this.sSP + '-load-more').hide();
+                $this.oView.find('.' + $this.sSP + '-empty').show();
+            }
+        });
+
+        return;
+    }
+
+    //--- Delete from 'Outline' (if available)
+    if(this.bViewOutline) {
+        oItem.bx_anim('hide', this._sAnimationEffect, this._iAnimationSpeed, function() {
+            $(this).remove();
+
+            if($this.oView.find('.' + $this.sClassItem).length == 0) {
+                $this.destroyMasonry();
+
+                $this.oView.find('.' + $this.sSP + '-load-more').hide();
+                $this.oView.find('.' + $this.sSP + '-empty').show();
+            } 
+            else
+                $this.reloadMasonry();
+        });
+
+        return;
+    }
+
+    //--- Delete from 'View Item' page.
+    if(this._sReferrer.length != 0)
+        document.location = this._sReferrer;
+};
+
+BxTimelineView.prototype.onConnect = function(eElement, oData)
+{
+    $(eElement).remove();
+};
+
+/*----------------------------*/
+/*--- Live Updates methods ---*/
+/*----------------------------*/
+BxTimelineView.prototype.goTo = function(oLink, sGoToId, sBlinkIds, onLoad)
+{
+    var $this = this;
+
+    this.loadingInPopup(oLink, true);
+
+    this._oRequestParams.start = 0;
+    this._oRequestParams.blink = sBlinkIds;
+    this._getPosts(this.oView, function(oData) {
+        $this.loadingInPopup(oLink, false);
+
+        $(oLink).parents('.bx-popup-applied:first:visible').dolPopupHide();
+
+        oData.go_to = sGoToId;
+        processJsonData(oData);
+    });
+};
+
+BxTimelineView.prototype.goToBtn = function(oLink, sGoToId, sBlinkIds, onLoad)
+{
+    var $this = this;
+
+    this.loadingInButton(oLink, true);
+
+    this._oRequestParams.start = 0;
+    this._oRequestParams.blink = sBlinkIds;
+    this._getPosts(this.oView, function(oData) {
+        oData.go_to = sGoToId;
+        processJsonData(oData);
+
+        $this.loadingInButton(oLink, false);
+        $(oLink).parents('.' + $this.sSP + '-live-update-button:first').remove();
+
+        $this.resumeLiveUpdates();
+    });
+};
+
+/*
+ * Show only one live update notification for all new events.
+ * 
+ * Note. oData.count_old and oData.count_new are also available and can be checked or used in notification popup.  
+ */
+BxTimelineView.prototype.showLiveUpdate = function(oData)
+{
+    if(!oData.code)
+        return;
+
+    var oButton = $(oData.code);
+    var sId = oButton.attr('id');
+    $('#' + sId).remove();
+
+    oButton.prependTo(this.oView);
+};
+
+/*
+ * Show separate live update notification for each new Event.
+ * 
+ * Note. This way to display live update notifications isn't used for now. 
+ * See BxTimelineView::showLiveUpdate method instead.
+ * 
+ * Note. oData.count_old and oData.count_new are also available and can be checked or used in notification popup.  
+ */
+BxTimelineView.prototype.showLiveUpdates = function(oData)
+{
+    if(!oData.code)
+        return;
+
+    var $this = this;
+
+    var oItems = $(oData.code);
+    var sId = oItems.attr('id');
+    $('#' + sId).remove();
+
+    oItems.prependTo('body').dolPopup({
+        position: 'fixed',
+        left: '1rem',
+        top: 'auto',
+        bottom: '1rem',
+        fog: false,
+        onBeforeShow: function() {
+        },
+        onBeforeHide: function() {
+        },
+        onShow: function() {
+            setTimeout(function() {
+                $('.bx-popup-chain.bx-popup-applied:visible:first').dolPopupHide();
+            }, 5000);
+        },
+        onHide: function() {
+            $this.resumeLiveUpdates();
+        }
+    });
+};
+
+BxTimelineView.prototype.previousLiveUpdate = function(oLink)
+{
+    var fPrevious = function() {
+        var sClass = 'bx-popup-chain-item';
+        $(oLink).parents('.' + sClass + ':first').hide().prev('.' + sClass).show();
+    };
+
+    if(!this.pauseLiveUpdates(fPrevious));
+        fPrevious();
+};
+
+BxTimelineView.prototype.hideLiveUpdate = function(oLink)
+{
+    $(oLink).parents('.bx-popup-applied:visible:first').dolPopupHide();
+};
+
+BxTimelineView.prototype.resumeLiveUpdates = function(onLoad)
+{
+    if(!this._bLiveUpdatePaused)
+        return false;
+
+    var $this = this;
+    this.changeLiveUpdates('resume_live_update', function() {
+        $this._bLiveUpdatePaused = false;
+
+        if(typeof onLoad == 'function')
+            onLoad();
+    });
+
+    return true;
+};
+
+BxTimelineView.prototype.pauseLiveUpdates = function(onLoad)
+{
+    if(this._bLiveUpdatePaused)
+        return false;
+
+    var $this = this;
+    this.changeLiveUpdates('pause_live_update', function() {
+        $this._bLiveUpdatePaused = true;
+
+        if(typeof onLoad == 'function')
+            onLoad();
+    });
+
+    return true;
+};
+
+BxTimelineView.prototype.changeLiveUpdates = function(sAction, onLoad)
+{
+    var $this = this;
+    var oParams = this._getDefaultActions();
+    oParams['action'] = sAction;
+
+    jQuery.get(
+        this._sActionsUrl + sAction + '/',
+        oParams,
+        function() {
+            if(typeof onLoad == 'function')
+                onLoad();
+        }
+    );
+};
+
+BxTimelineView.prototype.blink = function(oParent)
+{
+	oParent.find('.' + this.sClassBlink + '-plate:visible').animate({
+		opacity: 0
+	}, 
+	5000, 
+	function() {
+		oParent.find('.' + this.sClassBlink).removeClass(this.sClassBlink);
+	});
+};
+
+
+/*------------------------------------*/
+/*--- Internal (protected) methods ---*/
+/*------------------------------------*/
+BxTimelineView.prototype._getPage = function(oElement, iStart, iPerPage, onLoad)
+{
+    var $this = this;
+
+    if(oElement)
+        this.loadingIn(oElement, true);
+
+    this._oRequestParams.start = iStart;
+    this._oRequestParams.per_page = iPerPage;
+    this._getPosts(oElement, function(oData) {
+        if(oElement)
+            $this.loadingIn(oElement, false);
+
+    	var sItems = $.trim(oData.items);
+
+        if($this.bViewTimeline)
+            $this.oView.find('.' + $this.sClassItems).append($(sItems).hide()).find('.' + $this.sClassItem + ':hidden').bx_anim('show', $this._sAnimationEffect, $this._iAnimationSpeed, function() {
+                $(this).bxProcessHtml();
+
+                //-- Check content to show 'See More'
+                $this.initSeeMore($(this), false);
+
+                //-- Init Flickity
+                $this.initFlickity($this.oView);
+
+                //--- Init Video Autoplay
+                $this.initVideosAutoplay($this.oView);
+            });
+
+        if($this.bViewOutline)
+            $this.appendMasonry($(sItems).bxProcessHtml(), function(oItems) {
+                //-- Check content to show 'See More'
+                $this.initSeeMore(oItems, false);
+
+                //-- Init Flickity
+                $this.initFlickity($this.oView);
+
+                //--- Init Video Layout
+                if($this._sVideosAutoplay != 'off') 
+                    $this.initVideos($this.oView);
+            });
+
+    	if(oData && oData.load_more != undefined)
+            $this.oView.find('.' + $this.sSP + '-load-more-holder').html($.trim(oData.load_more));
+
+    	if(oData && oData.back != undefined)
+            $this.oView.find('.' + $this.sSP + '-back-holder').html($.trim(oData.back));
+
+    	if(oData && oData.empty != undefined && !$this.oView.find('.' + $this.sClassItem).length)
+            $this.oView.find('.' + $this.sSP + '-empty-holder').html($.trim(oData.empty));
+
+        if(typeof onLoad == 'function')
+            onLoad(oData);
+    });
+};
+
+BxTimelineView.prototype._getPosts = function(oElement, onComplete)
+{
+    var $this = this;
+    var oData = this._getDefaultData(oElement);
+
+    jQuery.get(
+        this._sActionsUrl + 'get_posts/',
+        oData,
+        function(oData) {
+            if(typeof onComplete === 'function')
+                return onComplete(oData);
+
+            if(oElement)
+                $this.loadingInBlock(oElement, false);
+
+            processJsonData(oData);
+        },
+        'json'
+    );
+};
+
+BxTimelineView.prototype._onGetPosts = function(oData)
+{
+    var $this = this;
+
+    var onComplete = function() {
+        if(oData && oData.go_to != undefined)
+            location.hash = oData.go_to;
+
+        if(oData && oData.load_more != undefined)
+            $this.oView.find('.' + $this.sSP + '-load-more-holder').html($.trim(oData.load_more));
+
+        if(oData && oData.back != undefined)
+            $this.oView.find('.' + $this.sSP + '-back-holder').html($.trim(oData.back));
+
+        if(oData && oData.empty != undefined)
+            $this.oView.find('.' + $this.sSP + '-empty-holder').html($.trim(oData.empty));
+
+        $this.initCalendar();
+    };
+
+    if(oData && oData.items != undefined) {
+        var sItems = $.trim(oData.items);
+
+        if(this.bViewTimeline) {
+            var oItems = this.oView.find('.' + this.sClassItems);
+            oItems.html(sItems).bxProcessHtml();
+
+            this.blink(oItems);
+            this.initFlickity(this.oView);            
+
+            onComplete();
+            return;
+        }
+
+        if(this.bViewOutline) {
+            oItems = this.oView.find('.' + this.sClassItems);
+            oItems.html(sItems).bxProcessHtml();
+
+            if(this.isMasonry())
+                this.destroyMasonry();
+
+            if(!this.isMasonryEmpty())
+                this.initMasonry();
+
+            this.blink(oItems);
+            this.initFlickity(this.oView);
+
+            onComplete();
+            return;
+        }
+    }
+};
+
+BxTimelineView.prototype._onGetPost = function(oData)
+{
+    if(!$.trim(oData.item).length) 
+        return;
+
+    var $this = this;
+    var sItem = this._getHtmlId('item', this._oRequestParams, {whole:false}) + oData.id;
+    this.oView.find(sItem).replaceWith($(oData.item).bxProcessHtml());
+    this.oView.find(sItem).find('.bx-tl-item-text .bx-tl-content').checkOverflowHeight(this.sSP + '-overflow', function(oElement) {
+        $this.onFindOverflow(oElement);
+    });
+
+    this.initFlickity(this.oView);
+};
+
+BxTimelineView.prototype._markPost = function(oLink, iId, iWay, sAction)
+{
+    var oData = this._getDefaultData();
+    oData['id'] = iId;
+
+    $(oLink).parents('.bx-popup-applied:first:visible').dolPopupHide({
+        onHide: function(oPopup) {
+            $(oPopup).remove();
+        }
+    });
+
+    this.loadingInItem($(this._getHtmlId('item', this._oRequestParams, {whole:false}) + iId), true);
+
+    $.post(
+        this._sActionsUrl + sAction + '/',
+        oData,
+        function(oData) {
+        	processJsonData(oData);
+        },
+        'json'
+    );
+};
+
+BxTimelineView.prototype._onMarkPost = function(oData, sAction)
+{
+    var $this = this;
+    var sItem = this._getHtmlId('item', this._oRequestParams, {whole:false}) + oData.id;
+
+    this._oRequestParams.start = 0;
+
+    //--- Mark on Timeline (if available)
+    if(this.bViewTimeline)
+        this._getPosts(this.oView, function(oData) {
+            $(sItem).bx_anim('hide', $this._sAnimationEffect, $this._iAnimationSpeed, function() {
+                $(this).remove();
+
+                processJsonData(oData);
+            });
+        });
+
+    //--- Mark on Outline (if available)
+    if(this.bViewOutline)
+        this._getPosts(this.oView, function(oData) {
+            $this.removeMasonry(sItem, function() {
+                processJsonData(oData);
+            });
+        });
+};

+ 1023 - 0
modules/boonex/timeline/updates/13.0.4_13.0.5/source/template/css/view.css

@@ -0,0 +1,1023 @@
+/*--- General section ---*/
+
+/*--- Dynamic Browsing: Menu ---*/
+.bx-tl-menu-feeds.bx-menu-ver li.bx-menu-tab-active {
+    background-color: rgba(235, 240, 245, 0.8);
+}
+.bx-tl-menu-feeds.bx-menu-ver li .bx-menu-item-link {
+    position: relative;
+    display: -webkit-flex;
+    display: flex;
+    -webkit-flex-flow: row nowrap;
+    flex-flow: row nowrap;
+    -webkit-align-items: center;
+    align-items: center;
+    -webkit-justify-content: space-between;
+    justify-content: space-between;
+}
+.bx-tl-menu-feeds.bx-menu-ver li a {
+    -webkit-flex-grow: 3;
+    flex-grow: 3;
+
+    position: relative;
+    display: -webkit-flex;
+    display: flex;
+    -webkit-flex-flow: row nowrap;
+    flex-flow: row nowrap;
+    -webkit-align-items: center;
+    align-items: center;
+    -webkit-justify-content: flex-start;
+    justify-content: flex-start;
+
+    line-height: 1.5rem;
+}
+.bx-tl-menu-feeds.bx-menu-ver li img, 
+.bx-tl-menu-feeds.bx-menu-ver li .sys-icon {
+    display: inline-block;
+    vertical-align: top;
+    width: 1.5rem;
+    height: 1.5rem;
+    line-height: 1.5rem;
+    font-size: 1.0rem;
+}
+.bx-tl-menu-feeds.bx-menu-ver li .bx-menu-item-title {
+    overflow: hidden;
+    text-overflow: ellipsis;
+}
+.bx-tl-menu-feeds.bx-menu-ver li .bx-menu-show {
+    display: none;
+}
+.bx-tl-menu-feeds.bx-menu-ver li .bx-menu-hide {
+    display: inline;
+}
+.bx-tl-menu-feeds.bx-menu-ver li.bx-mi-collapsed .bx-menu-show {
+    display: inline;
+}
+.bx-tl-menu-feeds.bx-menu-ver li.bx-mi-collapsed .bx-menu-hide {
+    display: none;
+}
+.bx-tl-menu-feeds.bx-menu-ver li.bx-mi-collapsed .bx-menu-item-subitems {
+    display: none;
+}
+.bx-tl-menu-feeds.bx-menu-ver li .bx-menu-subitem .bx-menu-item-cnt {
+    position: relative;
+    display: -webkit-flex;
+    display: flex;
+    -webkit-flex-flow: row nowrap;
+    flex-flow: row nowrap;
+    -webkit-align-items: center;
+    align-items: center;
+    -webkit-justify-content: space-between;
+    justify-content: space-between;
+}
+
+
+/*--- Views Block Style ---*/
+.bx-tl-views {
+    position: relative;
+}
+
+.bx-tl-views .bx-loading-ajax {
+    display: -webkit-flex;
+    display: flex;
+    -webkit-align-items: center;
+    align-items: center;
+    -webkit-justify-content: center;
+    justify-content: center;
+
+    top: 0;
+    width: 100%;
+    height: 100%;
+}
+.bx-tl-v-view {
+    position: relative;
+}
+.bx-tl-v-form .bx-tl-v-user {
+    position: absolute;
+    top: 0;
+    left: 0;
+}
+.bx-tl-v-form .bx-tl-v-content {
+    display: -webkit-flex;
+    display: flex;
+    -webkit-align-items: center;
+    align-items: center;
+}
+.bx-tl-v-form.bx-tl-v-default .bx-tl-v-content {
+    -webkit-align-items: stretch;
+    align-items: stretch;   
+}
+.bx-tl-v-form.bx-tl-v-default .bx-tl-v-content > div {
+    width: 100%;
+    cursor: text;
+}
+.bx-tl-v-form .bx-uploader-ghost .bx-base-general-icon-wrapper img {
+    max-width: 9.375rem;
+}
+
+
+/*--- View Block Style ---*/
+div.bx-tl-view {
+	position: relative;
+}
+
+.bx-tl-grid-sizer {
+	width: 100%;
+}
+.bx-tl-grid-item-sizer {
+    width: 100%;
+}
+
+.bx-tl-view-sizer {
+	width: 100%;
+}
+.bx-tl-view-sizer div.bx-tl-item-ind {
+	padding: 0px;
+}
+div.bx-tl-items-wrapper {
+	position: relative;
+}
+
+/*--- Filters Style ---*/
+div.bx-tl-view-filters {
+    min-width: 14rem;
+    max-width: 20rem;
+}
+div.bx-tl-view-filters div.bx-form-section-wrapper:first-child {
+    margin-top: 0;
+}
+div.bx-tl-view-filters div.bx-form-section-content {
+    padding-top: 0;
+    padding-bottom: 0;
+}
+
+/*--- Back Style ---*/
+
+
+/*--- Load More Style ---*/
+div.bx-tl-view-timeline div.bx-tl-load-more {
+    padding-top: 0px;
+}
+
+div.bx-tl-jump-to {
+    position: relative;
+    float: right;
+    line-height: 36px;
+    line-height: 2.25rem;
+}
+div.bx-tl-jump-to .bx-tl-jt-divider:last-child {
+    display: none;
+}
+div.bx-tl-jump-to .bx-btn {
+    display: inline-block;
+    float: none;
+}
+div.bx-tl-jump-to .bx-tl-jump-to-calendar {
+    width: 100%;
+}
+
+
+/*--- Divider Styles ---*/
+div.bx-tl-divider {
+    position: relative;
+}
+
+div.bx-tl-divider-cnt {
+    position: relative;
+    box-sizing: border-box;
+
+    width: 100%;
+
+    border: 2px solid rgba(0, 0, 0, 0.1);
+    border-radius: 20px;
+    -moz-border-radius: 20px;
+    -webkit-border-radius: 20px;
+    background-color: rgba(0, 0, 0, 0.1);
+    
+    text-align: center;
+    text-transform: uppercase;
+    font-weight: bold;
+    color: #ffffff;
+}
+
+/*--- Item Style ---*/
+div.bx-tl-item,
+div.bx-tl-item-cnt {
+    position: relative;
+}
+
+div.bx-tl-blink-plate {
+    position: absolute;
+    display: none;
+    top: -10px;
+    left: -10px;
+    width: 100%;
+    height: 100%;
+    padding: 10px;
+    background-color: rgb(255, 244, 213);
+    background-color: rgba(255, 234, 193, 0.5);
+}
+
+div.bx-tl-item.bx-tl-blink div.bx-tl-blink-plate {
+    display: block;
+}
+
+/*--- Item Sample Style ---*/
+div.bx-tl-item.bx-tl-sample div.bx-tl-is {
+    display: -webkit-flex;
+    display: flex;
+    -webkit-align-items: flex-start;
+    align-items: flex-start;
+}
+div.bx-tl-item.bx-tl-sample div.bx-tl-is.vcenter {
+    -webkit-align-items: center;
+    align-items: center;
+}
+div.bx-tl-item.bx-tl-sample div.bx-tl-is-avatar {
+    -webkit-flex-grow: 0;
+    flex-grow: 0;
+}
+div.bx-tl-item.bx-tl-sample div.bx-tl-is-content {
+    -webkit-flex-grow: 2;
+    flex-grow: 2;
+}
+
+div.bx-tl-item.bx-tl-sample .bx-tl-is-icon,
+div.bx-tl-item.bx-tl-sample .bx-tl-is-title,
+div.bx-tl-item.bx-tl-sample .bx-tl-is-aux > li,
+div.bx-tl-item.bx-tl-sample .bx-tl-is-paragraph > li {
+    background: -webkit-gradient(linear,left top,right top,color-stop(25%,#f2f2f2),color-stop(37%,#e6e6e6),color-stop(63%,#f2f2f2));
+    background: linear-gradient(90deg, #f2f2f2 25%, #e6e6e6 37%, #f2f2f2 63%);
+    background-size: auto;
+    background-size: 400% 100%;
+
+    -webkit-animation: bx-tl-sample-loading 1.4s ease infinite;
+    animation: bx-tl-sample-loading 1.4s ease infinite;
+}
+div.bx-tl-item.bx-tl-sample .bx-tl-is-icon {
+    display: block;
+}
+div.bx-tl-item.bx-tl-sample .bx-tl-is-title {
+    width: 100%;
+    height: 1rem;
+    margin: 0;
+    padding: 0;
+}
+div.bx-tl-item.bx-tl-sample .bx-tl-is-aux,
+div.bx-tl-item.bx-tl-sample .bx-tl-is-paragraph {
+    margin: 0;
+    padding: 0;
+
+    list-style: none;
+}
+div.bx-tl-item.bx-tl-sample .bx-tl-is-aux {
+    margin-top: 0.5rem;
+}
+div.bx-tl-item.bx-tl-sample .bx-tl-is-paragraph {
+    margin-top: 1.5rem;
+}
+div.bx-tl-item.bx-tl-sample .bx-tl-is-paragraph + .bx-tl-is-paragraph {
+    margin-top: 2.5rem;
+    text-align: right;
+}
+div.bx-tl-item.bx-tl-sample .bx-tl-is-aux > li {
+    width: 100%;
+    height: 0.75rem;
+
+    list-style: none;
+}
+div.bx-tl-item.bx-tl-sample .bx-tl-is-paragraph > li {
+    width: 100%;
+    height: 1rem;
+
+    list-style: none;
+}
+div.bx-tl-item.bx-tl-sample .bx-tl-is-paragraph + .bx-tl-is-paragraph > li {
+    display: inline-block;
+}
+div.bx-tl-item.bx-tl-sample .bx-tl-is-aux > li + li {
+    margin: 0.25rem 0 0 0;
+}
+div.bx-tl-item.bx-tl-sample .bx-tl-is-paragraph > li + li {
+    margin: 1.0rem 0 0 0;
+}
+
+@-webkit-keyframes bx-tl-sample-loading {
+    0% {
+        background-position:100% 50%
+    }
+    to {
+        background-position:0 50%
+    }
+}
+@keyframes bx-tl-sample-loading {
+    0% {
+        background-position:100% 50%
+    }
+    to {
+        background-position:0 50%
+    }
+}
+
+/*--- Item Owner Style ---*/
+div.bx-tl-item div.bx-tl-item-owner {
+    position: relative;
+    text-align: left;
+}
+
+div.bx-tl-item div.bx-tl-item-owner.bx-tl-io-with-actions div.bx-tl-owner-info {
+    margin-right: 2.5rem;
+}
+
+div.bx-tl-item div.bx-tl-owner-name {
+    position: relative;
+    display: -webkit-flex;
+    display: flex;
+    -webkit-align-items: center;
+    align-items: center;
+    -webkit-flex-wrap: wrap;
+    flex-wrap: wrap;
+
+    max-width: 100%;
+}
+
+div.bx-tl-item div.bx-tl-owner-name a.bx-tl-owner-name {
+    white-space: nowrap;
+    text-overflow: ellipsis;
+    overflow: hidden;
+}
+
+div.bx-tl-item div.bx-tl-owner-name .bx-badge-compact,
+div.bx-tl-item div.bx-tl-owner-name .bx-badges-list{
+    display:inline-block;
+}
+
+div.bx-tl-item div.bx-tl-owner-name > * {
+    vertical-align: middle;
+}
+
+div.bx-tl-item div.bx-tl-owner-name a.bx-tl-owner-name,
+div.bx-tl-item div.bx-tl-owner-name .bx-tl-timeline-owner-name a.bx-tl-ton-item {
+    font-weight: 700;
+}
+div.bx-tl-item div.bx-tl-owner-name .bx-tl-timeline-owner-name .bx-tl-ton-div:first-child {
+    display: none;
+}
+div.bx-tl-item div.bx-tl-owner-name .bx-tl-date,
+div.bx-tl-item div.bx-tl-owner-name .bx-tl-pinned .sys-icon,
+div.bx-tl-item div.bx-tl-owner-name .bx-tl-sticked .sys-icon,
+div.bx-tl-item div.bx-tl-owner-name .bx-tl-hot .sys-icon {
+    color: rgba(40, 60, 80, 0.5);
+}
+div.bx-tl-item div.bx-tl-owner-name .bx-tl-pinned .sys-icon,
+div.bx-tl-item div.bx-tl-owner-name .bx-tl-sticked .sys-icon,
+div.bx-tl-item div.bx-tl-owner-name .bx-tl-hot .sys-icon {
+    display: inline-block;
+    cursor: default;
+}
+
+/*+++ Item Owner Actions Style +++*/
+.bx-tl-owner-actions .bx-tl-oa-div,
+.bx-tl-owner-actions .bx-tl-owner-action {
+    padding: 0 0 0 0.5rem;
+}
+.bx-tl-view.bx-tl-view-outline .bx-tl-owner-actions .bx-tl-oa-div:first-of-type {
+    display: none;
+}
+
+/*--- Item Meta Info Style ---*/
+.bx-tl-item-meta {
+    white-space: nowrap;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    text-align: left;
+}
+.bx-tl-item-meta ul.bx-menu-custom.bx-menu-custom-hor {
+    position: relative;
+    display: inline-block;
+}
+.bx-tl-item-meta ul.bx-menu-custom.bx-menu-custom-hor > li {
+    vertical-align: top;
+}
+.bx-tl-item-meta ul.bx-menu-custom.bx-menu-custom-hor > li > span {
+    margin-right: 0;
+}
+.bx-tl-item-meta ul.bx-menu-custom li:first-child .bx-tl-item-meta-div {
+    display: none;
+}
+.bx-tl-item-meta ul.bx-menu-custom li .bx-tl-item-meta-item,
+.bx-tl-item-meta ul.bx-menu-custom li .bx-tl-item-meta-div,
+.bx-tl-item-meta ul.bx-menu-custom li .bx-btn {
+    position: relative;
+    float: none;
+    display: inline-block;
+    vertical-align: top;
+}
+.bx-tl-item-meta .bx-tl-date,
+.bx-tl-item-meta .bx-tl-pinned .sys-icon,
+.bx-tl-item-meta .bx-tl-sticked .sys-icon,
+.bx-tl-item-meta .bx-tl-hot .sys-icon {
+    color: rgba(40, 60, 80, 0.5);
+}
+.bx-tl-item-meta .bx-tl-pinned .sys-icon,
+.bx-tl-item-meta .bx-tl-sticked .sys-icon,
+.bx-tl-item-meta .bx-tl-hot .sys-icon {
+    display: inline-block;
+    cursor: default;
+}
+
+/*--- Item Manage Style ---*/
+.bx-tl-item-manage {
+    position: absolute;
+    top: 0;
+    right: 0;
+}
+.bx-tl-item-manage a {
+    position: relative;
+    width: 2rem;
+    height: 2rem;
+}
+
+/*--- Item Action Style ---*/
+div.bx-tl-item div.bx-tl-item-action .bx-tl-timeline-owner-name a.bx-tl-ton-item {
+    font-weight: 700;
+}
+div.bx-tl-item div.bx-tl-item-action .bx-tl-timeline-owner-name .bx-tl-ton-div:first-child {
+    display: none;
+}
+
+
+/*--- Item Content Style ---*/
+div.bx-tl-item-content {
+    position: relative;
+    text-align: left;
+}
+div.bx-tl-item-content form {
+    padding: 1rem 1rem 0 1rem;
+}
+div.bx-tl-item-content div.bx-tl-title {
+    text-overflow: ellipsis;
+    overflow: hidden;
+}
+div.bx-tl-item-content div.bx-tl-content iframe[src*='video'] {
+    width: 100%;
+    min-height: 240px !important;
+}
+div.bx-tl-item-text div.bx-tl-content {
+    position: relative;
+    max-height: 250px;
+
+    text-overflow: ellipsis;
+    overflow: hidden;
+}
+div.bx-tl-item-text div.bx-tl-content > p:first-child {
+    margin-top: 0;
+    padding-top: 0;
+}
+div.bx-tl-item-text div.bx-tl-content > p:last-child {
+    margin-bottom: 0;
+    padding-bottom: 0;
+}
+div.bx-tl-item-text div.bx-tl-content.bx-tl-overflow:before {
+    position: absolute;
+    bottom: 0;
+    width: 100%;
+    height: 20%;
+
+    background: -webkit-linear-gradient(top, rgba(255, 255, 255, 0), rgba(255, 255, 255, 1.0));
+    background: -moz-linear-gradient(top, rgba(255, 255, 255, 0), rgba(255, 255, 255, 1.0));
+    background: -o-linear-gradient(top, rgba(255, 255, 255, 0), rgba(255, 255, 255, 1.0));
+    background: linear-gradient(to bottom, rgba(255, 255, 255, 0), rgba(255, 255, 255, 1.0));
+
+    content: '';
+}
+div.bx-tl-item-text div.bx-tl-content-show-more {
+    position: relative;
+}
+div.bx-tl-item-text div.bx-tl-content p {
+    margin-top: 10px;
+    margin-top: 0.625rem;
+    margin-bottom: 10px;
+    margin-bottom: 0.625rem;
+}
+div.bx-tl-item-text div.bx-tl-content img {
+    max-width: 100%;
+    height: auto;
+}
+
+/*--- Item Images Style ---*/
+div.bx-tl-item div.bx-tl-item-images {
+    position: relative;
+    white-space: nowrap;
+    overflow: hidden;
+}
+div.bx-tl-item div.bx-tl-item-image {
+    display: inline-block;
+}
+
+/*--- Item Activity (Actions and Manage are different menus) ---*/
+div.bx-tl-item div.bx-tl-item-activity .bx-menu-custom.bx-menu-custom-hor {
+    position: relative;
+    display: -webkit-flex;
+    display: flex;
+    -webkit-justify-content: flex-start;
+    justify-content: flex-start;
+}
+div.bx-tl-item div.bx-tl-item-activity .bx-menu-custom.bx-menu-custom-hor.bx-mma-ready {
+    -webkit-justify-content: flex-start;
+    justify-content: flex-start;
+}
+div.bx-tl-item div.bx-tl-item-activity .bx-menu-custom.bx-menu-custom-hor::before,
+div.bx-tl-item div.bx-tl-item-activity .bx-menu-custom.bx-menu-custom-hor::after {
+    display: none;
+}
+div.bx-tl-item div.bx-tl-item-activity .bx-menu-custom li > a,
+div.bx-tl-item div.bx-tl-item-activity .bx-menu-custom li > span {
+    display: block;
+}
+div.bx-tl-item div.bx-tl-item-activity.bx-tl-ia-counters .bx-menu-custom.bx-menu-custom-hor {
+    -webkit-flex-wrap: wrap;
+    flex-wrap: wrap
+}
+div.bx-tl-item div.bx-tl-item-activity.bx-tl-ia-counters .bx-menu-custom.bx-menu-custom-hor li > a,
+div.bx-tl-item div.bx-tl-item-activity.bx-tl-ia-counters .bx-menu-custom.bx-menu-custom-hor li > div,
+div.bx-tl-item div.bx-tl-item-activity.bx-tl-ia-counters .bx-menu-custom.bx-menu-custom-hor li > span {
+    margin-top: 1.0rem;
+    margin-right: 1.25rem;
+}
+div.bx-tl-item div.bx-tl-item-activity .bx-menu-custom.bx-menu-custom-hor li > a,
+div.bx-tl-item div.bx-tl-item-activity .bx-menu-custom.bx-menu-custom-hor li > span {
+    margin-right: 1.25rem;
+}
+div.bx-tl-item div.bx-tl-item-activity .bx-menu-custom li > span {
+    margin-right: 0;
+}
+div.bx-tl-item div.bx-tl-item-activity .bx-menu-custom li > span.bx-def-margin-thd-topbottom {
+    margin-top: 0;
+    margin-bottom: 0;
+}
+div.bx-tl-item div.bx-tl-item-activity .bx-menu-custom li > span img {
+    background-size: contain;
+    background-repeat: no-repeat;
+    background-position: center center;
+}
+
+div.bx-tl-item div.bx-tl-item-manage .bx-menu-item-icon,
+div.bx-tl-item div.bx-tl-item-activity .bx-menu-custom li .sys-action-do-icon,
+div.bx-tl-item div.bx-tl-item-activity .bx-menu-custom li .bx-menu-item-icon {
+    box-sizing: border-box;
+
+    width: 2.0rem;
+    height: 2.0rem;
+
+    background-color: rgba(232, 232, 232, 1.0);
+    border: 1px solid #ffffff;
+    border-radius: 1rem;
+
+    font-size: 1.0rem;
+}
+
+div.bx-tl-item div.bx-tl-item-activity .bx-menu-custom li .sys-action-do-icon .sys-icon,
+div.bx-tl-item div.bx-tl-item-activity .bx-menu-custom li .bx-menu-item-icon .sys-icon {
+    vertical-align: top;
+}
+
+/*--- Item Activity (with Auto-More - all actions in one menu) and Item Manage (separate menu) ---*/
+div.bx-tl-item div.bx-tl-item-activity .bx-menu-custom.bx-menu-more-auto > li.bx-menu-item {
+    padding: 0;
+    white-space: nowrap;
+}
+div.bx-tl-item div.bx-tl-item-activity .bx-menu-custom.bx-menu-more-auto > li.bx-menu-item.bx-menu-item-more-auto a {
+    padding: 0;
+}
+.bx-popup .bx-menu-custom.bx-menu-custom-ver.bx-menu-object-bx_timeline_menu_item_manage > li.bx-menu-item  a > span,
+div.bx-tl-item div.bx-tl-item-activity .bx-menu-custom.bx-menu-more-auto .bx-popup .bx-menu-custom.bx-menu-submenu-more-auto > li.bx-menu-item  a > span {
+    margin-left: 0;
+}
+.bx-popup .bx-menu-custom.bx-menu-custom-ver.bx-menu-object-bx_timeline_menu_item_manage > li.bx-menu-item  a .sys-action-do-icon,
+.bx-popup .bx-menu-custom.bx-menu-custom-ver.bx-menu-object-bx_timeline_menu_item_manage > li.bx-menu-item  a .sys-action-do-icon > .sys-icon,
+.bx-popup .bx-menu-custom.bx-menu-custom-ver.bx-menu-object-bx_timeline_menu_item_manage > li.bx-menu-item  a .bx-menu-item-icon,
+.bx-popup .bx-menu-custom.bx-menu-custom-ver.bx-menu-object-bx_timeline_menu_item_manage > li.bx-menu-item  a .bx-menu-item-icon > .sys-icon,
+div.bx-tl-item div.bx-tl-item-activity .bx-menu-custom.bx-menu-more-auto .bx-popup .bx-menu-custom.bx-menu-submenu-more-auto > li.bx-menu-item  a .sys-action-do-icon,
+div.bx-tl-item div.bx-tl-item-activity .bx-menu-custom.bx-menu-more-auto .bx-popup .bx-menu-custom.bx-menu-submenu-more-auto > li.bx-menu-item  a .sys-action-do-icon > .sys-icon,
+div.bx-tl-item div.bx-tl-item-activity .bx-menu-custom.bx-menu-more-auto .bx-popup .bx-menu-custom.bx-menu-submenu-more-auto > li.bx-menu-item  a .bx-menu-item-icon,
+div.bx-tl-item div.bx-tl-item-activity .bx-menu-custom.bx-menu-more-auto .bx-popup .bx-menu-custom.bx-menu-submenu-more-auto > li.bx-menu-item  a .bx-menu-item-icon > .sys-icon {
+    width: 1.5rem;
+    height: 1.5rem;
+
+    background-color: transparent;
+    border-color: transparent;
+
+    line-height: 1.5rem;
+    font-size: 1.0rem;
+}
+.bx-popup .bx-menu-custom.bx-menu-custom-ver.bx-menu-object-bx_timeline_menu_item_manage > li.bx-menu-item  a .sys-action-do-text,
+.bx-popup .bx-menu-custom.bx-menu-custom-ver.bx-menu-object-bx_timeline_menu_item_manage > li.bx-menu-item  a .bx-menu-item-title,
+div.bx-tl-item div.bx-tl-item-activity .bx-menu-custom.bx-menu-more-auto .bx-popup .bx-menu-custom.bx-menu-submenu-more-auto > li.bx-menu-item  a .sys-action-do-text,
+div.bx-tl-item div.bx-tl-item-activity .bx-menu-custom.bx-menu-more-auto .bx-popup .bx-menu-custom.bx-menu-submenu-more-auto > li.bx-menu-item  a .bx-menu-item-title {
+    margin-left: 0.5rem;
+}
+
+/*--- Item Activity without Auto-More ---*/
+div.bx-tl-item div.bx-tl-item-activity:not(.bx-tl-ia-counters) .bx-menu-custom.bx-menu-custom-hor:not(.bx-menu-more-auto),
+div.bx-tl-item div.bx-tl-item-activity:not(.bx-tl-ia-counters) .bx-menu-custom.bx-menu-custom-hor:not(.bx-menu-more-auto) li {
+    overflow: hidden;
+}
+div.bx-tl-item div.bx-tl-item-activity:not(.bx-tl-ia-counters) .bx-menu-custom.bx-menu-custom-hor:not(.bx-menu-more-auto) a,
+div.bx-tl-item div.bx-tl-item-activity:not(.bx-tl-ia-counters) .bx-menu-custom.bx-menu-custom-hor:not(.bx-menu-more-auto) span {
+    display: block;
+    white-space: nowrap;
+}
+div.bx-tl-item div.bx-tl-item-activity:not(.bx-tl-ia-counters) .bx-menu-custom.bx-menu-custom-hor:not(.bx-menu-more-auto) span.bx-menu-item-icon,
+div.bx-tl-item div.bx-tl-item-activity:not(.bx-tl-ia-counters) .bx-menu-custom.bx-menu-custom-hor:not(.bx-menu-more-auto) span.sys-action-do-icon {
+    -webkit-flex-shrink: 0;
+    flex-shrink: 0;
+}
+div.bx-tl-item div.bx-tl-item-activity:not(.bx-tl-ia-counters) .bx-menu-custom.bx-menu-custom-hor:not(.bx-menu-more-auto) .sys-action-element-holder,
+div.bx-tl-item div.bx-tl-item-activity:not(.bx-tl-ia-counters) .bx-menu-custom.bx-menu-custom-hor:not(.bx-menu-more-auto) .bx-menu-item-title,
+div.bx-tl-item div.bx-tl-item-activity:not(.bx-tl-ia-counters) .bx-menu-custom.bx-menu-custom-hor:not(.bx-menu-more-auto) .sys-action-do-text {
+    max-width: 100%;
+
+    -webkit-flex-shrink: 1;
+    flex-shrink: 1;
+}
+div.bx-tl-item div.bx-tl-item-activity:not(.bx-tl-ia-counters) .bx-menu-custom.bx-menu-custom-hor:not(.bx-menu-more-auto) .bx-menu-item-title,
+div.bx-tl-item div.bx-tl-item-activity:not(.bx-tl-ia-counters) .bx-menu-custom.bx-menu-custom-hor:not(.bx-menu-more-auto) .sys-action-do-text {
+    overflow: hidden;
+    text-overflow: ellipsis;
+}
+
+.bx-media-phone div.bx-tl-item div.bx-tl-item-activity:not(.bx-tl-ia-counters) .bx-menu-custom.bx-menu-custom-hor:not(.bx-menu-more-auto) .bx-menu-item-title,
+.bx-media-phone div.bx-tl-item div.bx-tl-item-activity:not(.bx-tl-ia-counters) .bx-menu-custom.bx-menu-custom-hor:not(.bx-menu-more-auto) .sys-action-do-text {
+    display: none;
+}
+
+
+/*--- Item Style: Timeline ---*/
+div.bx-tl-view-timeline div.bx-tl-items,
+div.bx-tl-view-search div.bx-tl-items,
+div.bx-tl-view-item div.bx-tl-items {
+	margin-left: 0px;
+	margin-right: 0px;
+}
+div.bx-tl-view-timeline div.bx-tl-item,
+div.bx-tl-view-search div.bx-tl-item,
+div.bx-tl-view-item div.bx-tl-item {
+    position: relative;
+}
+div.bx-tl-view-timeline div.bx-tl-item-type {
+    position: absolute;
+    top: 0px;
+    left: 0px;
+}
+div.bx-tl-view-timeline div.bx-tl-item-circle {
+    position: relative;
+    display: -webkit-flex;
+    display: flex;
+    -webkit-align-items: center;
+    align-items: center;
+    -webkit-justify-content: center;
+    justify-content: center;
+
+    width: 2rem;
+    height: 2rem;
+
+    background-color: #dddddd;
+    background-clip: padding-box;
+    border-radius: 2rem;
+
+    text-align: center;
+    color: #999999;
+
+    overflow: hidden;
+}
+div.bx-tl-view-timeline div.bx-tl-item-circle .sys-icon {
+    font-size: 1.0rem;
+}
+
+
+/*--- Item Style: Outline ---*/
+div.bx-tl-view-outline div.bx-tl-item {
+	position: relative;
+}
+div.bx-tl-view-outline div.bx-tl-item div.bx-tl-item-owner.bx-tl-io-with-actions div.bx-tl-owner-info {
+    margin-right: 48px;
+    margin-right: 3.0rem;
+}
+div.bx-tl-view-outline div.bx-tl-item-ind {
+	position: relative;
+}
+
+/*+++ Item Text +++*/
+div.bx-tl-view-outline div.bx-tl-item-text div.bx-tl-title {
+	font-weight: bold;
+}
+div.bx-tl-view-outline div.bx-tl-content-show-more a {
+	font-weight: bold;
+}
+
+/*+++ Item Image +++*/
+div.bx-tl-view-search div.bx-tl-item-images {
+    margin-left: 0px;
+    margin-right: 0px;
+}
+div.bx-tl-view-search div.bx-tl-item-image {
+    margin-right: 2px;
+    margin-right: 0.125rem;
+}
+div.bx-tl-view-timeline div.bx-tl-item-image,
+div.bx-tl-view-outline div.bx-tl-item-image,
+div.bx-tl-view-item div.bx-tl-item-image {
+    width: 100%;
+    text-align: center;
+    overflow: hidden;
+}
+div.bx-tl-view-search div.bx-tl-item-image img {
+    height: 12.5rem;
+}
+div.bx-tl-view-timeline div.bx-tl-item-images.bx-tl-ii-gallery div.bx-tl-item-image img,
+div.bx-tl-view-item div.bx-tl-item-images.bx-tl-ii-gallery div.bx-tl-item-image img,
+div.bx-tl-view-timeline div.bx-tl-item-images.bx-tl-ii-single div.bx-tl-item-image img,
+div.bx-tl-view-item  div.bx-tl-item-images.bx-tl-ii-single div.bx-tl-item-image img {
+    position: relative;
+    display: block;
+    max-width: 100%;
+    margin-left: auto;
+    margin-right: auto;
+}
+div.bx-tl-view-outline div.bx-tl-item-image img {
+    max-width: 100%;
+    object-fit: cover;
+    object-position: center center;
+}
+
+/*+++ Item Video +++*/
+div.bx-tl-view-timeline div.bx-tl-item-video,
+div.bx-tl-view-outline div.bx-tl-item-video,
+div.bx-tl-view-item div.bx-tl-item-video {
+    width: 100%;
+}
+.bx-tl-video-iframe {
+    width: 100%;
+    border: none;
+}
+div.bx-tl-view div.bx-tl-item-videos.bx-tl-iv-gallery div.bx-tl-item-video video,
+div.bx-tl-view div.bx-tl-item-videos.bx-tl-iv-single div.bx-tl-item-video video {
+    display: block;
+    max-width: 100%;
+    margin-left: auto;
+    margin-right: auto;
+}
+
+/*+++ Item Attachment +++*/
+div.bx-tl-view div.bx-tl-item-attachments {
+    position: relative;
+    white-space: nowrap;
+    overflow-x: auto;
+}
+div.bx-tl-view div.bx-tl-item-attachments div.bx-tl-item-attachment {
+    position: relative;
+    display: -webkit-inline-flex;
+    display: inline-flex;
+    -webkit-justify-content: center;
+    justify-content: center;  
+
+    width: 100%;
+    vertical-align: middle;
+}
+div.bx-tl-view div.bx-tl-item-attachments div.bx-tl-item-attachment img {
+    position: relative;
+    display: block;
+    max-width: 100%;
+    margin-left: auto;
+    margin-right: auto;
+}
+div.bx-tl-view-outline div.bx-tl-item-attachment img {
+    max-width: 100%;
+    object-fit: cover;
+    object-position: center center;
+}
+
+/*+++ Video +++*/
+div.bx-tl-view-timeline div.bx-tl-item-attachment video,
+div.bx-tl-view-outline div.bx-tl-item-attachment video,
+div.bx-tl-view-item div.bx-tl-item-attachment video {
+    display: block;
+    max-width: 100%;
+    margin-left: auto;
+    margin-right: auto;
+}
+div.bx-tl-item-attachment .bx-tl-item-video {
+    position: relative;
+}
+div.bx-tl-item-attachment .bx-tl-iv-duration {
+    position: absolute;
+    right: 0.25rem;
+    bottom: 0.25rem;
+    background-color: rgba(255, 255, 255, 0.8);
+}
+
+
+/*+++ Showcase Layout +++*/
+div.bx-tl-view div.bx-tl-item-attachments.bx-tl-ia-showcase {
+    display: -webkit-flex;
+    display: flex;
+    -webkit-flex-wrap: wrap;
+    flex-wrap: wrap;
+    -webkit-justify-content: space-between;
+    justify-content: space-between;
+}
+div.bx-tl-view div.bx-tl-item-attachments.bx-tl-ia-showcase div.bx-tl-item-attachment {
+    box-sizing: border-box;
+    width: 33.2%;
+    height: 8.5rem;
+    border: 1px solid transparent;
+}
+div.bx-tl-view div.bx-tl-item-attachments.bx-tl-ia-showcase div.bx-tl-item-attachment.bx-tl-ia-first,
+div.bx-tl-view div.bx-tl-item-attachments.bx-tl-ia-showcase.bx-tl-ia-i2 div.bx-tl-item-attachment {
+    width: 100%;
+    height: auto;
+}
+div.bx-tl-view div.bx-tl-item-attachments.bx-tl-ia-showcase.bx-tl-ia-i3 div.bx-tl-item-attachment:not(.bx-tl-ia-first) {
+    width: 50%;
+}
+div.bx-tl-item-attachments.bx-tl-ia-showcase a,
+div.bx-tl-item-attachments.bx-tl-ia-showcase img {
+    position: relative;
+    display: block;
+    width: 100%;
+    height: 100%;
+}
+div.bx-tl-item-attachments.bx-tl-ia-showcase img {
+    object-fit: cover;
+}
+div.bx-tl-item-attachments.bx-tl-ia-showcase .bx-tl-item-more {
+    position: absolute;
+    display: -webkit-flex;
+    display: flex;
+    -webkit-align-items: center;
+    align-items: center;
+    -webkit-justify-content: center;
+    justify-content: center;
+
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 100%;
+    background-color: rgba(0, 0, 0, 0.7);
+
+    font-size: 2.5rem;
+}
+div.bx-tl-item-attachments.bx-tl-ia-showcase .bx-tl-item-more,
+div.bx-tl-item-attachments.bx-tl-ia-showcase .bx-tl-item-more a {
+    color: #ffffff;
+}
+
+
+/*+++ Slider Styles  +++*/
+div.bx-tl-item-images .flickity-slider,
+div.bx-tl-item-videos .flickity-slider,
+div.bx-tl-item-attachments .flickity-slider {
+    display: -webkit-flex;
+    display: flex;
+    -webkit-align-items: center;
+    align-items: center;
+}
+
+/*+++ Item Link +++*/
+div.bx-tl-view-outline div.bx-tl-item-link {
+	text-align: center;
+}
+div.bx-tl-view-outline div.bx-tl-il-thumbnail img {
+	width: 100%;
+	max-width: 100px;
+	height: 100%;
+	max-height: 100px;
+}
+div.bx-tl-view-outline div.bx-tl-il-embed iframe,
+div.bx-tl-view-timeline div.bx-tl-il-embed iframe {
+    width: 100%;
+}
+
+/*+++ Item Reposted +++*/
+div.bx-tl-view-outline div.bx-tl-reposted div.bx-tl-item-text {
+	padding-left: 5px;
+	padding-left: 0.3rem;
+
+	border-left: 1px solid #999999;
+	border-left: 0.07rem solid #999999;
+}
+div.bx-tl-view-outline div.bx-tl-reposted div.bx-tl-title {
+	font-size: 1.0rem;
+}
+div.bx-tl-view-outline div.bx-tl-reposted div.bx-tl-title a {
+	color: #999999;
+}
+div.bx-tl-view-outline div.bx-tl-reposted div.bx-tl-content {
+	font-size: 0.875rem;
+	color: #999999;
+}
+
+/*--- Item Style: View page ---*/
+div.bx-tl-view-item-comments .bx-tl-item-comments {
+    margin-top: 0;
+}
+div.bx-tl-view-item-comments .cmts .cmt:first-child  {
+    padding-top: 0;
+}
+
+div.bx-tl-view-info {
+    position: relative;
+}
+div.bx-tl-view-info .bx-base-pofile-unit {
+    float: none;
+}
+
+/*--- Item Brief Style ---*/
+div.bx-tl-bview-images {
+    position: relative;
+}
+div.bx-tl-bview-image.bx-tl-bvi-single,
+div.bx-tl-bview-images div.bx-tl-bview-image {
+    width: 100%;
+    height: calc(100vh - 7rem);
+    text-align: center;
+}
+div.bx-tl-bview-image.bx-tl-bvi-single img,
+div.bx-tl-bview-images div.bx-tl-bview-image img {
+    position: relative;
+    max-width: 100% !important;
+    max-height: 100% !important;
+    margin-left: auto;
+    margin-right: auto;
+}
+div.bx-tl-bview-image.bx-tl-bvi-single {
+    display: -webkit-flex;
+    display: flex;
+    -webkit-align-items: center;
+    align-items: center;
+    -webkit-justify-content: center;
+    justify-content: center;
+}
+
+
+/*--- Empty Style ---*/
+div.bx-tl-empty div.bx-msg-box-container {
+    margin-top: 0px;
+    margin-bottom: 0px;
+}
+
+
+/*--- Comments Styles ---*/
+div.bx-tl-item-comments-holder .cmt.bx-def-box {
+    border-width: 0px;
+}
+
+
+/*--- Live Update Alert Styles ---*/
+div.bx-tl-live-update-button {}
+@supports(position:sticky) {
+    div.bx-tl-live-update-button {
+        position: sticky;
+        top: 1rem;
+        z-index: 1;
+    }
+}
+@supports(position:-webkit-sticky) {
+    div.bx-tl-live-update-button {
+        position: -webkit-sticky;
+        top: 1rem;
+        z-index: 1;
+    }
+}
+div.bx-tl-live-update-button .bx-btn {
+    display: inline-block;
+    float: none;
+}
+
+/*--- Live Update Notifications Styles ---*/
+.bx-tl-live-update-item {
+    position: relative;
+    display: block;
+}
+div.bx-tl-lui-cnt {
+    position: relative;
+}
+div.bx-tl-lui-avatar {
+    position: absolute;
+    top: 0px;
+    left: 0px;
+    text-align: center;
+}
+div.bx-tl-lui-info {
+    position: realtive;
+    display: -webkit-flex;
+    display: flex;
+    -webkit-align-items: center;
+    align-items: center;
+}
+div.bx-tl-luii-username {
+    white-space: nowrap;
+    text-overflow: ellipsis;
+    overflow: hidden;
+}

+ 86 - 0
modules/boonex/timeline/updates/13.0.4_13.0.5/source/template/item_outline.html

@@ -0,0 +1,86 @@
+<div id="__html_id__" class="__style_prefix__-item __class__">
+    <a name="timeline-event-__id__"></a>
+    <div class="__style_prefix__-item-ind bx-def-padding-sec">
+        <div class="__style_prefix__-item-cnt bx-def-box bx-def-padding-topbottom bx-def-round-corners __class_content__">
+            <div class="__style_prefix__-blink-plate"></div>
+            <bx_if:show_note>
+                <div class="__style_prefix__-item-notes">
+                    <bx_repeat:notes>
+                        <div class="__style_prefix__-item-note bx-def-margin-sec-top-auto bx-def-margin-leftright bx-def-font-grayed">
+                            <div class="__style_prefix__-in-text<bx_if:show_note_color> col-__item_note_color__</bx_if:show_note_color>">__item_note__</div>
+                        </div>
+                    </bx_repeat:notes>
+                </div>
+                <div class="__style_prefix__-in-divider bx-def-hr bx-def-margin-sec-topbottom"></div>
+            </bx_if:show_note>
+            <div class="__style_prefix__-item-owner relative flex items-center mx-4 __class_owner__"> 
+                <div class="__style_prefix__-owner-avatar bx-def-thumb-size">__item_owner_unit__</div>
+                <div class="__style_prefix__-owner-info bx-def-thumb-size-min-height flex-auto flex flex-col items-start justify-center min-w-0 pl-2 lg:pl-4">
+                    <div class="__style_prefix__-owner-name bx-def-font-middle bx-def-font-grayed">
+                        <a href="__item_owner_url__" class="__style_prefix__-owner-name" title="__item_owner_title__">__item_owner_name__</a>
+                        <bx_if:show_owner_actions>
+                            <span class="__style_prefix__-owner-actions">
+                                <bx_repeat:owner_actions>
+                                    <span class="__style_prefix__-oa-div">&#183;</span><a class="__style_prefix__-owner-action" href="__href__" onclick="__onclick__" title="__title__"><i class="sys-icon __icon__"></i></a>
+                                </bx_repeat:owner_actions>
+                            </span>
+                        </bx_if:show_owner_actions>
+                    </div>
+                    <div class="__style_prefix__-item-meta bx-def-font-middle bx-def-font-grayed">
+                        <bx_if:show_menu_item_meta>
+                            <span class="__style_prefix__-meta">__meta__</span>
+                        </bx_if:show_menu_item_meta>
+                        <bx_if:show_pinned>
+                            <span class="__style_prefix__-pinned bx-def-margin-sec-left">
+                                <i class="sys-icon thumbtack" title="<bx_text_attribute:_bx_timeline_txt_pinned />"></i>
+                            </span>
+                        </bx_if:show_pinned>
+                        <bx_if:show_sticked>
+                            <span class="__style_prefix__-sticked bx-def-margin-sec-left">
+                                <i class="sys-icon thumbtack" title="<bx_text_attribute:_bx_timeline_txt_sticked />"></i>
+                            </span>
+                        </bx_if:show_sticked>
+                        <bx_if:show_hot>
+                            <span class="__style_prefix__-hot bx-def-margin-sec-left">
+                                <i class="sys-icon fire" title="<bx_text_attribute:_bx_timeline_txt_hot />"></i>
+                            </span>
+                        </bx_if:show_hot>
+                    </div>
+                    <bx_if:show_manage>
+                        <div class="__style_prefix__-item-manage">
+                            <a href="javascript:void(0)" onclick="__onclick__">
+                                <span class="bx-menu-item-icon bx-def-align-center"><i class="sys-icon ellipsis-v"></i></span>
+                            </a>
+                        </div>
+                    </bx_if:show_manage>
+                </div>
+            </div>
+            <bx_if:show_item_action>
+                <div class="__style_prefix__-item-action bx-def-margin-lefttopright bx-def-font-middle bx-def-font-grayed">
+                    <span>__item_owner_action__&nbsp;</span>
+                    <bx_if:show_timeline_owner>
+                        <span><bx_text:_bx_timeline_txt_to />&nbsp;</span> 
+                        <span class="__style_prefix__-timeline-owner-name">
+                            <bx_repeat:owners><span class="__style_prefix__-ton-div">, </span><a href="__owner_url__" class="__style_prefix__-ton-item">__owner_username__</a></bx_repeat:owners>
+                        </span> 
+                    </bx_if:show_timeline_owner>
+                </div>
+            </bx_if:show_item_action>
+            <div class="__style_prefix__-item-content __style_prefix__-ic-__content_type__ bx-clearfix">__content__</div>
+            <bx_if:show_location>
+                <div class="__style_prefix__-item-location bx-def-margin-lefttopright bx-def-font-grayed bx-clearfix">__location__</div>
+            </bx_if:show_location>
+            <bx_if:show_fields>
+                <div class="__style_prefix__-item-fields bx-def-margin-lefttopright bx-def-font-grayed bx-clearfix">__fields__</div>
+            </bx_if:show_fields>
+            <bx_if:show_menu_item_counters>
+                <div class="__style_prefix__-item-activity __style_prefix__-ia-counters bx-def-margin-leftright bx-clearfix">__menu_item_counters__</div>
+            </bx_if:show_menu_item_counters>
+            <bx_if:show_menu_item_actions>
+                <div class="__style_prefix__-item-activity-divider bx-def-hr bx-def-margin-top"></div>
+                <div class="__style_prefix__-item-activity bx-def-margin-leftright bx-def-margin-top bx-clearfix">__menu_item_actions__</div>
+            </bx_if:show_menu_item_actions>
+            <div class="__style_prefix__-item-comments-holder bx-def-margin-leftright">__comments__</div>
+        </div>
+    </div>
+</div>

+ 57 - 0
modules/boonex/timeline/updates/13.0.4_13.0.5/source/template/item_search.html

@@ -0,0 +1,57 @@
+<div id="__html_id__" class="__style_prefix__-item __class__ bx-def-thumb-size-min-height bx-def-padding-bottom bx-clearfix">
+    <div class="__style_prefix__-item-cnt bx-def-box bx-def-padding-topbottom bx-def-round-corners __class_content__">
+        <div class="__style_prefix__-item-owner flex items-start mx-4"> 
+            <div class="__style_prefix__-owner-avatar bx-def-thumb-size flex-none">__item_owner_unit__</div>
+            <div class="__style_prefix__-owner-info bx-def-thumb-size-min-height flex-auto flex flex-col items-start justify-center min-w-0 pl-2 lg:pl-4 overflow-hidden">
+                <bx_if:show_note>
+                    <div class="__style_prefix__-item-notes bx-def-margin-thd-bottom">
+                        <bx_repeat:notes>
+                            <div class="__style_prefix__-item-note bx-def-margin-sec-top-auto bx-def-font-small bx-def-font-grayed">
+                                <div class="__style_prefix__-in-text<bx_if:show_note_color> col-__item_note_color__</bx_if:show_note_color>">__item_note__</div>
+                            </div>
+                        </bx_repeat:notes>
+                    </div>
+                </bx_if:show_note>
+                <!-- NOTE: Spaces after and between elements in 'owner-name' DIV are needed for better line folding -->
+                <div class="__style_prefix__-owner-name bx-def-font-middle bx-def-font-light bx-def-font-grayed">
+                    <a href="__item_owner_url__" class="__style_prefix__-owner-name" title="__item_owner_title__">__item_owner_name__</a>
+                </div>
+                <div class="__style_prefix__-item-meta bx-def-font-middle bx-def-font-grayed">
+                    <bx_if:show_menu_item_meta>
+                        <span class="__style_prefix__-meta bx-def-font-small">__meta__</span>
+                    </bx_if:show_menu_item_meta>
+                    <bx_if:show_pinned>
+                        <span class="__style_prefix__-pinned bx-def-margin-thd-left">
+                            <i class="sys-icon thumbtack bx-def-margin-thd-left" title="<bx_text_attribute:_bx_timeline_txt_pinned />"></i>
+                        </span>
+                    </bx_if:show_pinned>
+                    <bx_if:show_sticked>
+                        <span class="__style_prefix__-sticked bx-def-margin-thd-left">
+                            <i class="sys-icon thumbtack bx-def-margin-thd-left" title="<bx_text_attribute:_bx_timeline_txt_sticked />"></i>
+                        </span>
+                    </bx_if:show_sticked>
+                    <bx_if:show_hot>
+                        <span class="__style_prefix__-hot bx-def-margin-thd-left">
+                            <i class="sys-icon fire bx-def-margin-thd-left" title="<bx_text_attribute:_bx_timeline_txt_hot />"></i>
+                        </span>
+                    </bx_if:show_hot>
+                </div>
+            </div>
+        </div>
+        <bx_if:show_item_action>
+            <div class="__style_prefix__-item-action bx-def-margin-lefttopright bx-def-font-middle bx-def-font-grayed">
+                <span class="bx-def-font-small">__item_owner_action__&nbsp;</span> 
+                <bx_if:show_timeline_owner>
+                    <i class="sys-icon caret-right"></i>
+                    <span class="__style_prefix__-timeline-owner-name">
+                        <bx_repeat:owners><span class="__style_prefix__-ton-div">, </span><a href="__owner_url__" class="__style_prefix__-ton-item">__owner_username__</a></bx_repeat:owners>
+                    </span>
+                </bx_if:show_timeline_owner>
+            </div>
+        </bx_if:show_item_action>
+        <div class="__style_prefix__-item-content __style_prefix__-ic-__content_type__ bx-clearfix">__content__</div>
+        <bx_if:show_location>
+            <div class="__style_prefix__-item-location bx-def-margin-leftright bx-def-margin-top bx-def-font-grayed bx-clearfix">__location__</div>
+        </bx_if:show_location>
+    </div>
+</div>

+ 84 - 0
modules/boonex/timeline/updates/13.0.4_13.0.5/source/template/item_timeline.html

@@ -0,0 +1,84 @@
+<div id="__html_id__" class="__style_prefix__-item __class__ bx-def-thumb-size-min-height bx-def-padding-bottom bx-clearfix">
+    <a name="timeline-event-__id__"></a>
+    <div class="__style_prefix__-item-cnt bx-def-box bx-def-padding-topbottom bx-def-round-corners __class_content__">
+        <div class="__style_prefix__-blink-plate"></div>
+        <bx_if:show_note>
+            <div class="__style_prefix__-item-notes">
+                <bx_repeat:notes>
+                    <div class="__style_prefix__-item-note bx-def-margin-sec-top-auto bx-def-margin-leftright bx-def-font-grayed">
+                        <div class="__style_prefix__-in-text<bx_if:show_note_color> col-__item_note_color__</bx_if:show_note_color>">__item_note__</div>
+                    </div>
+                </bx_repeat:notes>
+            </div>
+            <div class="__style_prefix__-in-divider bx-def-hr bx-def-margin-topbottom"></div>
+        </bx_if:show_note>
+        <div class="__style_prefix__-item-owner relative flex items-center mx-4 __class_owner__"> 
+            <div class="__style_prefix__-owner-avatar bx-def-thumb-size">__item_owner_unit__</div>
+            <div class="__style_prefix__-owner-info bx-def-thumb-size-min-height flex-auto flex flex-col items-start justify-center min-w-0 pl-2 lg:pl-4">
+                <div class="__style_prefix__-owner-name bx-def-font-middle bx-def-font-grayed">
+                    <a href="__item_owner_url__" class="__style_prefix__-owner-name" title="__item_owner_title__">__item_owner_name__</a> 
+                    <bx_if:show_owner_actions>
+                        <span class="__style_prefix__-owner-actions">
+                            <bx_repeat:owner_actions>
+                                <span class="__style_prefix__-oa-div">&#183;</span><a class="__style_prefix__-owner-action" href="__href__" onclick="__onclick__">__content__</a>
+                            </bx_repeat:owner_actions>
+                        </span>
+                    </bx_if:show_owner_actions>
+                </div>
+                <div class="__style_prefix__-item-meta bx-def-font-middle bx-def-font-grayed">
+                    <bx_if:show_menu_item_meta>
+                        <span class="__style_prefix__-meta">__meta__</span>
+                    </bx_if:show_menu_item_meta>
+                    <bx_if:show_pinned>
+                        <span class="__style_prefix__-pinned bx-def-margin-sec-left">
+                            <i class="sys-icon thumbtack" title="<bx_text_attribute:_bx_timeline_txt_pinned />"></i>
+                        </span>
+                    </bx_if:show_pinned>
+                    <bx_if:show_sticked>
+                        <span class="__style_prefix__-sticked bx-def-margin-sec-left">
+                            <i class="sys-icon thumbtack" title="<bx_text_attribute:_bx_timeline_txt_sticked />"></i>
+                        </span>
+                    </bx_if:show_sticked>
+                    <bx_if:show_hot>
+                        <span class="__style_prefix__-hot bx-def-margin-sec-left">
+                            <i class="sys-icon fire" title="<bx_text_attribute:_bx_timeline_txt_hot />"></i>
+                        </span>
+                    </bx_if:show_hot>
+                </div>
+                <bx_if:show_manage>
+                    <div class="__style_prefix__-item-manage">
+                        <a href="javascript:void(0)" onclick="__onclick__">
+                            <span class="bx-menu-item-icon bx-def-align-center"><i class="sys-icon ellipsis-v"></i></span>
+                        </a>
+                    </div>
+                </bx_if:show_manage>
+            </div>
+        </div>
+        <bx_if:show_item_action>
+            <div class="__style_prefix__-item-action bx-def-margin-lefttopright bx-def-font-middle bx-def-font-grayed">
+                <span>__item_owner_action__&nbsp;<i class="sys-icon __item_icon__"></i>&nbsp;</span>
+                <bx_if:show_timeline_owner>
+                    <span><bx_text:_bx_timeline_txt_to />&nbsp;</span> 
+                    <span class="__style_prefix__-timeline-owner-name">
+                        <bx_repeat:owners><span class="__style_prefix__-ton-div">, </span><a href="__owner_url__" class="__style_prefix__-ton-item">__owner_username__</a></bx_repeat:owners>
+                    </span> 
+                </bx_if:show_timeline_owner>
+            </div>
+        </bx_if:show_item_action>
+        <div class="__style_prefix__-item-content __style_prefix__-ic-__content_type__ bx-clearfix">__content__</div>
+        <bx_if:show_location>
+            <div class="__style_prefix__-item-location bx-def-margin-lefttopright bx-def-font-grayed bx-clearfix">__location__</div>
+        </bx_if:show_location>
+        <bx_if:show_fields>
+            <div class="__style_prefix__-item-fields bx-def-margin-lefttopright bx-def-font-grayed bx-clearfix">__fields__</div>
+        </bx_if:show_fields>
+        <bx_if:show_menu_item_counters>
+            <div class="__style_prefix__-item-activity __style_prefix__-ia-counters bx-def-margin-leftright bx-clearfix">__menu_item_counters__</div>
+        </bx_if:show_menu_item_counters>
+        <bx_if:show_menu_item_actions>
+            <div class="__style_prefix__-item-activity-divider bx-def-hr bx-def-margin-top"></div>
+            <div class="__style_prefix__-item-activity bx-def-margin-leftright bx-def-margin-top bx-clearfix">__menu_item_actions__</div>
+        </bx_if:show_menu_item_actions>
+        <div class="__style_prefix__-item-comments-holder bx-def-margin-leftright">__comments__</div>
+    </div>
+</div>

+ 14 - 0
modules/boonex/timeline/updates/13.0.4_13.0.5/source/template/jump_to.html

@@ -0,0 +1,14 @@
+<bx_if:show_list>
+    <div class="__style_prefix__-jump-to-cnt">
+        <bx_text:_bx_timeline_txt_or_jump_to />&nbsp;<bx_repeat:links><bx_if:show_link><a href="javascript:void(0)" onclick="__onclick__" title="__title__">__content__</a></bx_if:show_link><bx_if:show_text>__content__</bx_if:show_text><span class="__style_prefix__-jt-divider">, </span></bx_repeat:links>
+    </div>
+</bx_if:show_list>
+<bx_if:show_calendar>
+    <div class="__style_prefix__-jump-to-cnt flex items-center flatpickr">
+        <bx_text:_bx_timeline_txt_or_jump_to />
+        <div class="bx-form-input-wrapper bx-form-input-wrapper-datetime w-32 mx-2">
+            <input class="bx-def-font-inputs bx-form-input-datetime __style_prefix__-jump-to-calendar" type="text" data-input />
+        </div>
+        <a class="bx-btn __style_prefix__-jump-to-switch" href="javascript:void(0)" onclick="__onclick__" data-toggle><i class="sys-icon calendar-alt"></i></a>
+    </div>
+</bx_if:show_calendar>

+ 10 - 0
modules/boonex/timeline/updates/13.0.4_13.0.5/source/template/load_more.html

@@ -0,0 +1,10 @@
+<div class="__style_prefix__-load-more bx-def-padding-sec-top bx-clearfix" style="display:__visible__;">
+    <div class="__style_prefix__-load-more-cnt flex items-center justify-between">
+        <button class="bx-btn<bx_if:is_disabled> bx-btn-disabled</bx_if:is_disabled>" <bx_if:show_on_click>onclick="__on_click__"</bx_if:show_on_click>>
+            <bx_text:_bx_timeline_txt_load_more />
+        </button>
+        <bx_if:show_jump_to>
+            <div class="__style_prefix__-jump-to">__content__</div>
+        </bx_if:show_jump_to>
+    </div>
+</div>

+ 56 - 0
modules/boonex/timeline/updates/13.0.4_13.0.5/source/template/type_post.html

@@ -0,0 +1,56 @@
+<bx_if:show_top_raw>
+    <div class="__style_prefix__-item-top-raw mt-3 md:mt-4">__item_content_top_raw__</div>
+</bx_if:show_top_raw>
+<bx_if:show_images>
+    <div class="__style_prefix__-item-images __style_prefix__-ii-main __style_prefix__-ii-__display__ mt-3 md:mt-4 rounded">
+        <bx_repeat:items>
+            <div class="__style_prefix__-item-image flex-shrink-0 px-1 rounded overflow-hidden box-border">__item__</div>
+        </bx_repeat:items>
+    </div>
+</bx_if:show_images>
+<bx_if:show_videos>
+    <div class="__style_prefix__-item-videos __style_prefix__-iv-main __style_prefix__-iv-__display__ mx-1 mt-3 md:mt-4 rounded">
+        <bx_repeat:items>
+            <div class="__style_prefix__-item-video rounded">__item__</div>
+        </bx_repeat:items>
+    </div>
+</bx_if:show_videos>
+<bx_if:show_files>
+    <div class="__style_prefix__-item-files __style_prefix__-if-main __style_prefix__-if-__display__ mx-1 mt-3 md:mt-4 rounded">
+        <bx_repeat:items>
+            <div class="__style_prefix__-item-file rounded">__item__</div>
+        </bx_repeat:items>
+    </div>
+</bx_if:show_files>
+<div class="__style_prefix__-item-text mt-3 md:mt-4 mx-3 md:mx-4">
+    <bx_if:show_title>
+        <div class="__style_prefix__-title mb-1 md:mb-2 text-lg lg:text-xl font-semibold text-gray-700 dark:text-gray-300">__title__</div>
+    </bx_if:show_title>
+    <bx_if:show_content>
+        <div class="__style_prefix__-content bx-overflow-ready bx-def-vanilla-html relative mb-2 prose dark:prose-invert prose-sm max-w-none">__item_content__</div>
+    </bx_if:show_content>
+</div>
+<bx_if:show_attachments>
+    <div class="__style_prefix__-item-attachments __style_prefix__-ia-__display__ __style_prefix__-ia-i__count__ mx-1 mt-3 md:mt-4">
+        <bx_repeat:items>
+            <div class="__style_prefix__-item-attachment__class__">__item__</div>
+        </bx_repeat:items>
+    </div>
+</bx_if:show_attachments>
+<bx_if:show_links>
+    <div class="__style_prefix__-item-links px-3 md:px-4">
+        <bx_repeat:links>
+            <div class="__style_prefix__-item-link mt-3 md:mt-4">__link__</div>
+        </bx_repeat:links>
+    </div>
+</bx_if:show_links>
+<bx_if:show_attachments_files>
+    <div class="__style_prefix__-item-attachments __style_prefix__-iaf-__display__ __style_prefix__-iaf-i__count__ mx-1 mt-3 md:mt-4">
+        <bx_repeat:items>
+            <div class="__style_prefix__-item-attachment__class__">__item__</div>
+        </bx_repeat:items>
+    </div>
+</bx_if:show_attachments_files>
+<bx_if:show_raw>
+    <div class="__style_prefix__-item-raw px-3 md:px-4 mt-3 md:mt-4">__item_content_raw__</div>
+</bx_if:show_raw>