AntonLV 3 лет назад
Родитель
Сommit
d1c2a9201a
100 измененных файлов с 28030 добавлено и 0 удалено
  1. 51 0
      modules/boonex/massmailer/updates/13.0.4_13.0.5/install/config.php
  2. 23 0
      modules/boonex/massmailer/updates/13.0.4_13.0.5/install/installer.php
  3. 4 0
      modules/boonex/massmailer/updates/13.0.4_13.0.5/install/langs/en.xml
  4. 12 0
      modules/boonex/massmailer/updates/13.0.4_13.0.5/install/sql/install.sql
  5. 684 0
      modules/boonex/massmailer/updates/13.0.4_13.0.5/source/classes/BxMassMailerModule.php
  6. 77 0
      modules/boonex/massmailer/updates/13.0.4_13.0.5/source/install/config.php
  7. 155 0
      modules/boonex/massmailer/updates/13.0.4_13.0.5/source/install/langs/en.xml
  8. 139 0
      modules/boonex/massmailer/updates/13.0.4_13.0.5/source/install/sql/install.sql
  9. 51 0
      modules/boonex/payment/updates/13.0.8_13.0.9/install/config.php
  10. 13 0
      modules/boonex/payment/updates/13.0.8_13.0.9/install/installer.php
  11. 246 0
      modules/boonex/payment/updates/13.0.8_13.0.9/source/classes/BxPaymentOrders.php
  12. 953 0
      modules/boonex/payment/updates/13.0.8_13.0.9/source/classes/BxPaymentProviderStripeV3.php
  13. 70 0
      modules/boonex/payment/updates/13.0.8_13.0.9/source/install/config.php
  14. 51 0
      modules/boonex/persons/updates/13.0.8_13.0.9/install/config.php
  15. 13 0
      modules/boonex/persons/updates/13.0.8_13.0.9/install/installer.php
  16. 12 0
      modules/boonex/persons/updates/13.0.8_13.0.9/install/sql/enable.sql
  17. 5 0
      modules/boonex/persons/updates/13.0.8_13.0.9/install/sql/install.sql
  18. 152 0
      modules/boonex/persons/updates/13.0.8_13.0.9/source/install/config.php
  19. 562 0
      modules/boonex/persons/updates/13.0.8_13.0.9/source/install/sql/enable.sql
  20. 418 0
      modules/boonex/persons/updates/13.0.8_13.0.9/source/install/sql/install.sql
  21. 51 0
      modules/boonex/photos/updates/13.0.6_13.0.7/install/config.php
  22. 13 0
      modules/boonex/photos/updates/13.0.6_13.0.7/install/installer.php
  23. 10 0
      modules/boonex/photos/updates/13.0.6_13.0.7/install/sql/install.sql
  24. 136 0
      modules/boonex/photos/updates/13.0.6_13.0.7/source/install/config.php
  25. 447 0
      modules/boonex/photos/updates/13.0.6_13.0.7/source/install/sql/install.sql
  26. 29 0
      modules/boonex/photos/updates/13.0.6_13.0.7/source/template/form_ghost_template.html
  27. 19 0
      modules/boonex/photos/updates/13.0.6_13.0.7/source/template/form_ghost_template_upload.html
  28. 51 0
      modules/boonex/polls/updates/13.0.5_13.0.6/install/config.php
  29. 13 0
      modules/boonex/polls/updates/13.0.5_13.0.6/install/installer.php
  30. 10 0
      modules/boonex/polls/updates/13.0.5_13.0.6/install/sql/install.sql
  31. 136 0
      modules/boonex/polls/updates/13.0.5_13.0.6/source/install/config.php
  32. 459 0
      modules/boonex/polls/updates/13.0.5_13.0.6/source/install/sql/install.sql
  33. 13 0
      modules/boonex/polls/updates/13.0.5_13.0.6/source/template/form_subentries.html
  34. 51 0
      modules/boonex/posts/updates/13.0.7_13.0.8/install/config.php
  35. 13 0
      modules/boonex/posts/updates/13.0.7_13.0.8/install/installer.php
  36. 11 0
      modules/boonex/posts/updates/13.0.7_13.0.8/install/sql/install.sql
  37. 155 0
      modules/boonex/posts/updates/13.0.7_13.0.8/source/install/config.php
  38. 708 0
      modules/boonex/posts/updates/13.0.7_13.0.8/source/install/sql/install.sql
  39. 51 0
      modules/boonex/profiler/updates/13.0.2_13.0.3/install/config.php
  40. 13 0
      modules/boonex/profiler/updates/13.0.2_13.0.3/install/installer.php
  41. 670 0
      modules/boonex/profiler/updates/13.0.2_13.0.3/source/classes/BxProfiler.php
  42. 26 0
      modules/boonex/profiler/updates/13.0.2_13.0.3/source/classes/BxProfilerAlertsResponse.php
  43. 153 0
      modules/boonex/profiler/updates/13.0.2_13.0.3/source/classes/BxProfilerTemplate.php
  44. 68 0
      modules/boonex/profiler/updates/13.0.2_13.0.3/source/install/config.php
  45. 51 0
      modules/boonex/shopify/updates/13.0.3_13.0.4/install/config.php
  46. 13 0
      modules/boonex/shopify/updates/13.0.3_13.0.4/install/installer.php
  47. 6 0
      modules/boonex/shopify/updates/13.0.3_13.0.4/install/sql/install.sql
  48. 116 0
      modules/boonex/shopify/updates/13.0.3_13.0.4/source/install/config.php
  49. 371 0
      modules/boonex/shopify/updates/13.0.3_13.0.4/source/install/sql/install.sql
  50. 51 0
      modules/boonex/snipcart/updates/13.0.3_13.0.4/install/config.php
  51. 13 0
      modules/boonex/snipcart/updates/13.0.3_13.0.4/install/installer.php
  52. 10 0
      modules/boonex/snipcart/updates/13.0.3_13.0.4/install/sql/install.sql
  53. 136 0
      modules/boonex/snipcart/updates/13.0.3_13.0.4/source/install/config.php
  54. 450 0
      modules/boonex/snipcart/updates/13.0.3_13.0.4/source/install/sql/install.sql
  55. 51 0
      modules/boonex/spaces/updates/13.0.7_13.0.8/install/config.php
  56. 13 0
      modules/boonex/spaces/updates/13.0.7_13.0.8/install/installer.php
  57. 10 0
      modules/boonex/spaces/updates/13.0.7_13.0.8/install/sql/install.sql
  58. 38 0
      modules/boonex/spaces/updates/13.0.7_13.0.8/source/classes/BxSpacesMenuSnippetMeta.php
  59. 152 0
      modules/boonex/spaces/updates/13.0.7_13.0.8/source/install/config.php
  60. 514 0
      modules/boonex/spaces/updates/13.0.7_13.0.8/source/install/sql/install.sql
  61. 51 0
      modules/boonex/stream/updates/13.0.6_13.0.7/install/config.php
  62. 13 0
      modules/boonex/stream/updates/13.0.6_13.0.7/install/installer.php
  63. 10 0
      modules/boonex/stream/updates/13.0.6_13.0.7/install/sql/install.sql
  64. 137 0
      modules/boonex/stream/updates/13.0.6_13.0.7/source/install/config.php
  65. 445 0
      modules/boonex/stream/updates/13.0.6_13.0.7/source/install/sql/install.sql
  66. 51 0
      modules/boonex/tasks/updates/13.0.5_13.0.6/install/config.php
  67. 13 0
      modules/boonex/tasks/updates/13.0.5_13.0.6/install/installer.php
  68. 11 0
      modules/boonex/tasks/updates/13.0.5_13.0.6/install/sql/install.sql
  69. 257 0
      modules/boonex/tasks/updates/13.0.5_13.0.6/source/classes/BxTasksFormEntry.php
  70. 727 0
      modules/boonex/tasks/updates/13.0.5_13.0.6/source/classes/BxTasksModule.php
  71. 149 0
      modules/boonex/tasks/updates/13.0.5_13.0.6/source/install/config.php
  72. 559 0
      modules/boonex/tasks/updates/13.0.5_13.0.6/source/install/sql/install.sql
  73. 53 0
      modules/boonex/timeline/updates/13.0.11_13.0.12/install/config.php
  74. 13 0
      modules/boonex/timeline/updates/13.0.11_13.0.12/install/installer.php
  75. 23 0
      modules/boonex/timeline/updates/13.0.11_13.0.12/install/langs/en.xml
  76. 39 0
      modules/boonex/timeline/updates/13.0.11_13.0.12/install/sql/enable.sql
  77. 78 0
      modules/boonex/timeline/updates/13.0.11_13.0.12/install/sql/install.sql
  78. 977 0
      modules/boonex/timeline/updates/13.0.11_13.0.12/source/classes/BxTimelineConfig.php
  79. 1394 0
      modules/boonex/timeline/updates/13.0.11_13.0.12/source/classes/BxTimelineDb.php
  80. 485 0
      modules/boonex/timeline/updates/13.0.11_13.0.12/source/classes/BxTimelineFormPost.php
  81. 237 0
      modules/boonex/timeline/updates/13.0.11_13.0.12/source/classes/BxTimelineMenuItemShare.php
  82. 91 0
      modules/boonex/timeline/updates/13.0.11_13.0.12/source/classes/BxTimelineMenuPostAttachments.php
  83. 5782 0
      modules/boonex/timeline/updates/13.0.11_13.0.12/source/classes/BxTimelineModule.php
  84. 78 0
      modules/boonex/timeline/updates/13.0.11_13.0.12/source/classes/BxTimelinePrivacy.php
  85. 383 0
      modules/boonex/timeline/updates/13.0.11_13.0.12/source/classes/BxTimelineResponse.php
  86. 3234 0
      modules/boonex/timeline/updates/13.0.11_13.0.12/source/classes/BxTimelineTemplate.php
  87. 41 0
      modules/boonex/timeline/updates/13.0.11_13.0.12/source/classes/BxTimelineUploaderHTML5Attach.php
  88. 143 0
      modules/boonex/timeline/updates/13.0.11_13.0.12/source/install/config.php
  89. 429 0
      modules/boonex/timeline/updates/13.0.11_13.0.12/source/install/langs/en.xml
  90. 577 0
      modules/boonex/timeline/updates/13.0.11_13.0.12/source/install/sql/enable.sql
  91. 722 0
      modules/boonex/timeline/updates/13.0.11_13.0.12/source/install/sql/install.sql
  92. 79 0
      modules/boonex/timeline/updates/13.0.11_13.0.12/source/install/sql/uninstall.sql
  93. 403 0
      modules/boonex/timeline/updates/13.0.11_13.0.12/source/js/post.js
  94. 1005 0
      modules/boonex/timeline/updates/13.0.11_13.0.12/source/template/css/view.css
  95. 86 0
      modules/boonex/timeline/updates/13.0.11_13.0.12/source/template/item_outline.html
  96. 56 0
      modules/boonex/timeline/updates/13.0.11_13.0.12/source/template/item_search.html
  97. 84 0
      modules/boonex/timeline/updates/13.0.11_13.0.12/source/template/item_timeline.html
  98. 59 0
      modules/boonex/timeline/updates/13.0.11_13.0.12/source/template/type_post.html
  99. 13 0
      modules/boonex/timeline/updates/13.0.11_13.0.12/source/template/uploader_nfw.html
  100. 51 0
      modules/boonex/videos/updates/13.0.5_13.0.6/install/config.php

+ 51 - 0
modules/boonex/massmailer/updates/13.0.4_13.0.5/install/config.php

@@ -0,0 +1,51 @@
+<?php
+/**
+ * Copyright (c) BoonEx Pty Limited - http://www.boonex.com/
+ * CC-BY License - http://creativecommons.org/licenses/by/3.0/
+ */
+
+$aConfig = array(
+    /**
+     * Main Section.
+     */
+    'title' => 'Mass mailer',
+    'version_from' => '13.0.4',
+    'version_to' => '13.0.5',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '13.1.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/massmailer/updates/update_13.0.4_13.0.5/',
+    'home_uri' => 'massmailer_update_1304_1305',
+
+    'module_dir' => 'boonex/massmailer/',
+    'module_uri' => 'massmailer',
+
+    'db_prefix' => 'bx_massmailer_',
+    'class_prefix' => 'BxMassMailer',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_files' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'MassMailer',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

+ 23 - 0
modules/boonex/massmailer/updates/13.0.4_13.0.5/install/installer.php

@@ -0,0 +1,23 @@
+<?php
+/**
+ * Copyright (c) BoonEx Pty Limited - http://www.boonex.com/
+ * CC-BY License - http://creativecommons.org/licenses/by/3.0/
+ */
+
+class BxMassMailerUpdater extends BxDolStudioUpdater
+{
+    function __construct($aConfig)
+    {
+        parent::__construct($aConfig);
+    }
+
+    public function actionExecuteSql($sOperation)
+    {
+        if($sOperation == 'install') {
+            if(!$this->oDb->isFieldExists('bx_massmailer_campaigns', 'is_track_links'))
+                $this->oDb->query("ALTER TABLE `bx_massmailer_campaigns` ADD `is_track_links` smallint(1) NOT NULL AFTER `is_one_per_account`");
+        }
+
+        return parent::actionExecuteSql($sOperation);
+    }
+}

+ 4 - 0
modules/boonex/massmailer/updates/13.0.4_13.0.5/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_massmailer_form_campaign_input_is_track_links"><![CDATA[Click tracking]]></string_add>
+</resources>

+ 12 - 0
modules/boonex/massmailer/updates/13.0.4_13.0.5/install/sql/install.sql

@@ -0,0 +1,12 @@
+SET @sName = 'bx_massmailer';
+
+
+-- FORMS
+DELETE FROM `sys_form_inputs` WHERE `object`=@sName AND `name`='is_track_links';
+INSERT INTO `sys_form_inputs` (`object`, `module`, `name`, `value`, `values`, `checked`, `type`, `caption_system`, `caption`, `info`, `required`, `unique`, `collapsed`, `html`, `attrs`, `attrs_tr`, `attrs_wrapper`, `checker_func`, `checker_params`, `checker_error`, `db_pass`, `db_params`, `editable`, `deletable`) VALUES
+(@sName, @sName, 'is_track_links', '1', '', 1, 'switcher', '_bx_massmailer_form_campaign_input_sys_is_track_links', '_bx_massmailer_form_campaign_input_is_track_links', '', 0, 0, 0, 0, '', '', '', '', '', '', 'Int', '', 1, 0);
+
+DELETE FROM `sys_form_display_inputs` WHERE `display_name` IN ('bx_massmailer_campaign_add', 'bx_massmailer_campaign_edit') AND `input_name`='is_track_links';
+INSERT INTO `sys_form_display_inputs` (`display_name`, `input_name`, `visible_for_levels`, `active`, `order`) VALUES
+('bx_massmailer_campaign_add', 'is_track_links', 2147483647, 1, 7),
+('bx_massmailer_campaign_edit', 'is_track_links', 2147483647, 1, 7);

+ 684 - 0
modules/boonex/massmailer/updates/13.0.4_13.0.5/source/classes/BxMassMailerModule.php

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

+ 77 - 0
modules/boonex/massmailer/updates/13.0.4_13.0.5/source/install/config.php

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

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

@@ -0,0 +1,155 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources name="en" flag="gb" title="English">
+  <string name="_bx_massmailer"><![CDATA[Mass Mailer]]></string>
+  <string name="_bx_massmailer_acl_action_use_massmailer"><![CDATA[Use Massmailer]]></string>
+  <string name="_bx_massmailer_adm_stg_cpt_type"><![CDATA[Mass Mailer]]></string>
+  <string name="_bx_massmailer_adm_stg_cpt_category_general"><![CDATA[General]]></string>
+  <string name="_bx_massmailer_delete_sent_email_in_days"><![CDATA[Delete sent email campaigns older than (days)]]></string>
+  <string name="_bx_massmailer_page_title_sys_manage_campaigns"><![CDATA[Campaigns]]></string>
+  <string name="_bx_massmailer_page_title_manage_campaigns"><![CDATA[Campaigns]]></string>
+  <string name="_bx_massmailer_page_title_sys_manage_campaigns"><![CDATA[Campaigns]]></string>
+  <string name="_bx_massmailer_page_block_title_manage_campaigns"><![CDATA[Campaigns]]></string>
+  <string name="_bx_massmailer_page_block_title_system_manage_campaigns"><![CDATA[Manage Campaigns]]></string>
+  <string name="_bx_massmailer_page_block_title_system_manage_segments"><![CDATA[Manage Segments]]></string>
+  <string name="_bx_massmailer_page_block_title_manage_segments"><![CDATA[Manage Segments]]></string>
+  <string name="_bx_massmailer_page_title_manage_segments"><![CDATA[Segments]]></string>
+  <string name="_bx_massmailer_page_title_sys_manage_segments"><![CDATA[Segments]]></string>
+  <string name="_bx_massmailer_page_title_manage_segments"><![CDATA[Segments]]></string>
+  <string name="_bx_massmailer_page_title_sys_create_campaign"><![CDATA[New Campaign]]></string>
+  <string name="_bx_massmailer_page_title_create_campaign"><![CDATA[New Campaign]]></string>
+  <string name="_bx_massmailer_page_block_title_create_campaign"><![CDATA[New Campaign]]></string>
+  <string name="_bx_massmailer_page_title_sys_edit_campaign"><![CDATA[Edit Campaign]]></string>
+  <string name="_bx_massmailer_page_title_edit_campaign"><![CDATA[Edit Campaign]]></string>
+  <string name="_bx_massmailer_page_block_title_edit_campaign"><![CDATA[Edit Campaign]]></string>
+  <string name="_bx_massmailer_page_title_sys_view_campaign"><![CDATA[Campaign report]]></string>
+  <string name="_bx_massmailer_page_title_view_campaign"><![CDATA[Campaign report]]></string>
+  <string name="_bx_massmailer_page_block_title_view_campaign_info"><![CDATA[Info]]></string>
+  <string name="_bx_massmailer_page_block_title_view_campaign_subscribers"><![CDATA[Subscribers]]></string>
+  <string name="_bx_massmailer_page_block_title_view_campaign_links"><![CDATA[Link activity]]></string>
+  <string name="_bx_massmailer_page_block_title_entry_breadcrumb"><![CDATA[Breadcrumb]]></string>
+  <string name="_bx_massmailer_page_title_sys_unsubscribe"><![CDATA[Unsubscribe From Site Newsletters]]></string>
+  <string name="_bx_massmailer_page_title_unsubscribe"><![CDATA[Unsubscribe From Site Newsletters]]></string>
+  <string name="_bx_massmailer_page_block_title_system_unsubscribe"><![CDATA[Unsubscribe From Site Newsletters]]></string>
+  <string name="_bx_massmailer_page_block_title_unsubscribe"><![CDATA[Unsubscribe From Site Newsletters]]></string>
+  <string name="_bx_massmailer_page_block_title_system_viewsubscribers"><![CDATA[Subscribers]]></string>
+  <string name="_bx_massmailer_page_block_title_viewsubscribers"><![CDATA[Subscribers]]></string>
+  <string name="_bx_massmailer_page_block_title_attributes"><![CDATA[Attributes]]></string>
+  <string name="_bx_massmailer_menu_item_title_system_admt_mailer"><![CDATA[Mass Mailer]]></string>
+  <string name="_bx_massmailer_menu_item_title_admt_mailer"><![CDATA[Mass Mailer]]></string>
+  <string name="_bx_massmailer_menu_item_title_manage_campaigns"><![CDATA[Campaigns]]></string>
+  <string name="_bx_massmailer_menu_title_submenu"><![CDATA[Mass Mailer  Submenu]]></string>
+  <string name="_bx_massmailer_menu_set_title_submenu"><![CDATA[Mass Mailer Submenu]]></string>
+  <string name="_bx_massmailer_menu_item_title_system_campaigns"><![CDATA[Campaigns]]></string>
+  <string name="_bx_massmailer_menu_item_title_campaigns"><![CDATA[Campaigns]]></string>
+  <string name="_bx_massmailer_menu_item_title_system_segments"><![CDATA[Segments]]></string>
+  <string name="_bx_massmailer_menu_item_title_segments"><![CDATA[Segments]]></string>
+  <string name="_bx_massmailer_menu_item_title_system_create_entry"><![CDATA[Campaign]]></string>
+  <string name="_bx_massmailer_menu_item_title_create_entry"><![CDATA[Campaign]]></string>
+
+  <string name="_bx_massmailer_grid_column_title_adm_title"><![CDATA[Title]]></string>
+  <string name="_bx_massmailer_grid_column_title_adm_author"><![CDATA[Author]]></string>
+  <string name="_bx_massmailer_grid_column_title_adm_date_created"><![CDATA[Created]]></string>
+  <string name="_bx_massmailer_grid_column_title_adm_date_sent"><![CDATA[Sent]]></string>
+  <string name="_bx_massmailer_grid_action_title_adm_delete"><![CDATA[Delete]]></string>
+  <string name="_bx_massmailer_grid_action_title_adm_edit"><![CDATA[Edit]]></string>
+  <string name="_bx_massmailer_grid_action_title_adm_copy"><![CDATA[Copy]]></string>
+  <string name="_bx_massmailer_grid_action_title_adm_delete"><![CDATA[Delete]]></string>
+  <string name="_bx_massmailer_grid_action_title_adm_view"><![CDATA[Report]]></string>
+  <string name="_bx_massmailer_grid_action_title_adm_send_test"><![CDATA[Send test]]></string>
+  <string name="_bx_massmailer_grid_action_title_adm_send_all"><![CDATA[Send All]]></string>
+  <string name="_bx_massmailer_grid_action_title_adm_add"><![CDATA[Add new campaign]]></string>
+  <string name="_bx_massmailer_grid_column_title_adm_segment"><![CDATA[Segment]]></string>
+  <string name="_bx_massmailer_grid_column_title_adm_is_one_per_account"><![CDATA[One per account]]></string>
+  <string name="_bx_massmailer_grid_column_title_adm_is_one_per_account_yes"><![CDATA[Yes]]></string>
+  <string name="_bx_massmailer_grid_column_title_adm_is_one_per_account_no"><![CDATA[No]]></string>
+  
+  <string name="_bx_massmailer_campaign_form_add_title"><![CDATA[New campaign]]></string>
+  <string name="_bx_massmailer_campaign_form_edit_title"><![CDATA[Edit campaign]]></string>
+  <string name="_bx_massmailer_campaign_form_send_test_title"><![CDATA[Send test letter]]></string>
+  <string name="_bx_massmailer_campaign_form_send_all_title"><![CDATA[Send campaign]]></string>
+  <string name="_bx_massmailer_form_campaign"><![CDATA[Campaign]]></string>
+  <string name="_bx_massmailer_form_campaign_add_display"><![CDATA[Add]]></string>
+  <string name="_bx_massmailer_form_campaign_edit_display"><![CDATA[Edit]]></string>
+  <string name="_bx_massmailer_form_entry_input_do_submit"><![CDATA[Save]]></string>
+  <string name="_bx_massmailer_form_entry_input_sys_do_submit"><![CDATA[Save]]></string>
+  <string name="_bx_massmailer_form_entry_input_do_send"><![CDATA[Send]]></string>
+  <string name="_bx_massmailer_form_entry_input_sys_do_send"><![CDATA[Send]]></string>
+  <string name="_bx_massmailer_form_campaign_input_sys_title"><![CDATA[Campaign name]]></string>
+  <string name="_bx_massmailer_form_campaign_input_title"><![CDATA[Campaign name]]></string>
+  <string name="_bx_massmailer_form_campaign_input_title_err"><![CDATA[Campaign name can't be empty]]></string>
+  <string name="_bx_massmailer_form_campaign_input_sys_body"><![CDATA[Body]]></string>
+  <string name="_bx_massmailer_form_campaign_input_body"><![CDATA[Body]]></string>
+  <string name="_bx_massmailer_form_campaign_input_body_err"><![CDATA[Body can't be empty and {unsubscribe_url} marker must be present]]></string>
+  <string name="_bx_massmailer_form_campaign_input_is_one_per_account"><![CDATA[One letter per one account]]></string>
+  <string name="_bx_massmailer_form_campaign_input_is_track_links"><![CDATA[Click tracking]]></string>
+  <string name="_bx_massmailer_form_campaign_input_sys_test_email"><![CDATA[Email]]></string>
+  <string name="_bx_massmailer_form_campaign_input_email"><![CDATA[Email]]></string>
+  <string name="_bx_massmailer_form_campaign_input_sys_segments"><![CDATA[Segments]]></string>
+  <string name="_bx_massmailer_form_campaign_input_segments"><![CDATA[Segments]]></string>
+  <string name="_bx_massmailer_form_campaign_input_segments_err"><![CDATA[Segments's can't be empty]]></string>
+  <string name="_bx_massmailer_form_campaign_input_sys_subject"><![CDATA[Subject]]></string>
+  <string name="_bx_massmailer_form_campaign_input_subject"><![CDATA[Subject]]></string>
+  <string name="_bx_massmailer_form_campaign_input_subject_err"><![CDATA[Subject can't be empty]]></string>
+  <string name="_bx_massmailer_form_campaign_input_sys_from_name"><![CDATA[From name]]></string>
+  <string name="_bx_massmailer_form_campaign_input_from_name"><![CDATA[From name]]></string>
+  <string name="_bx_massmailer_form_campaign_input_from_name_info"><![CDATA[If empty, Site Name is used]]></string>
+  <string name="_bx_massmailer_form_campaign_input_sys_reply_to"><![CDATA[Reply to Email]]></string>
+  <string name="_bx_massmailer_form_campaign_input_reply_to"><![CDATA[Reply to Email]]></string>
+  <string name="_bx_massmailer_form_campaign_input_reply_to_info"><![CDATA[If empty, Site Email is used]]></string>
+  <string name="_bx_massmailer_form_campaign_input_reply_to_err"><![CDATA[Email is not valid]]></string>
+  <string name="_bx_massmailer_form_campaign_input_from_name_info_value"><![CDATA[The message will be sent to {0} profiles.]]></string>
+  <string name="_bx_massmailer_form_campaign_input_sys_campaign_info"><![CDATA[Campaign info]]></string>
+  <string name="_bx_massmailer_form_campaign_input_sys_receive_news"><![CDATA[Receive Newsletterso]]></string>
+  <string name="_bx_massmailer_form_campaign_input_receive_news"><![CDATA[Receive Newsletters]]></string>
+  <string name="_bx_massmailer_form_campaign_input_sys_code"><![CDATA[Code]]></string>
+  <string name="_bx_massmailer_form_entry_input_cancel"><![CDATA[Cancel]]></string>
+
+  <string name="_bx_massmailer_txt_breadcrumb_title_new_campaign"><![CDATA[New campaign]]></string>
+  <string name="_bx_massmailer_txt_never_sent"><![CDATA[Never]]></string>
+  <string name="_bx_massmailer_txt_title_email"><![CDATA[Email]]></string>
+  <string name="_bx_massmailer_txt_title_title"><![CDATA[Title]]></string>
+  <string name="_bx_massmailer_txt_link_title"><![CDATA[Url]]></string>
+  <string name="_bx_massmailer_txt_click_count_title"><![CDATA[Total clicks]]></string>
+  <string name="_bx_massmailer_txt_last_click_title"><![CDATA[Last click]]></string>
+  <string name="_bx_massmailer_txt_subject_title"><![CDATA[Subject:]]></string>
+  <string name="_bx_massmailer_txt_body_title"><![CDATA[Body:]]></string>
+  <string name="_bx_massmailer_txt_sent_on_title"><![CDATA[Sent on:]]></string>
+  <string name="_bx_massmailer_txt_sent_to_title"><![CDATA[Segment:]]></string>
+  
+  <string name="_bx_massmailer_txt_sent_total_title"><![CDATA[Total sent - {0}]]></string>
+  <string name="_bx_massmailer_txt_opened_total_title"><![CDATA[Opened - {0}]]></string>
+  <string name="_bx_massmailer_txt_unopened_total_title"><![CDATA[Unopened - {0}]]></string>
+  <string name="_bx_massmailer_txt_clicked_total_title"><![CDATA[Clicked - {0}]]></string>
+  <string name="_bx_massmailer_txt_unsubscribed_total_title"><![CDATA[Unsubscribed - {0}]]></string>
+
+  <string name="_bx_massmailer_txt_attribute_global"><![CDATA[Account]]></string>
+  <string name="_bx_massmailer_txt_item"><![CDATA[Item]]></string>
+  <string name="_bx_massmailer_txt_value"><![CDATA[Value]]></string>
+  <string name="_bx_massmailer_txt_date"><![CDATA[Date]]></string>
+  <string name="_bx_massmailer_txt_attribute_email"><![CDATA[Email]]></string>
+  <string name="_bx_massmailer_txt_attribute_account_name"><![CDATA[Account name]]></string>
+  <string name="_bx_massmailer_txt_attribute_account_id"><![CDATA[Account ID]]></string>
+  <string name="_bx_massmailer_txt_attribute_reset_password_url"><![CDATA[Reset password URL]]></string>
+  <string name="_bx_massmailer_txt_attribute_unsubscribe_url"><![CDATA[Unsubscribe URL]]></string>
+  <string name="_bx_massmailer_txt_created_title"><![CDATA[Created:]]></string>
+  <string name="_bx_massmailer_txt_from_name_title"><![CDATA[From name:]]></string>
+  <string name="_bx_massmailer_txt_reply_title"><![CDATA[Reply:]]></string>
+  <string name="_bx_massmailer_txt_title_content_total"><![CDATA[Total numbers]]></string>
+  <string name="_bx_massmailer_txt_title_content_speed"><![CDATA[Growth speed]]></string>
+  <string name="_bx_massmailer_txt_title_date_sent"><![CDATA[Sent]]></string>
+  <string name="_bx_massmailer_txt_title_date_click"><![CDATA[Last click]]></string>
+  <string name="_bx_massmailer_txt_title_date_seen"><![CDATA[Seen]]></string>
+  <string name="_bx_massmailer_txt_copy_title"><![CDATA[ - Copy]]></string>
+  <string name="_bx_massmailer_txt_unsubscribe_error_occured"><![CDATA[Unsubscribe error]]></string>
+  <string name="_bx_massmailer_txt_subscribed"><![CDATA[Subscribed]]></string>
+  <string name="_bx_massmailer_txt_unsubscribed"><![CDATA[Unsubscribed]]></string>
+  <string name="_bx_massmailer_txt_send_test_error"><![CDATA[Error occurred]]></string>
+  <string name="_bx_massmailer_segments_all"><![CDATA[All subscribers]]></string>
+  <string name="_bx_massmailer_email_name"><![CDATA[Mass Mailer message]]></string>
+  <string name="_bx_massmailer_email_subject"><![CDATA[Mass Mailer message]]></string>
+  <string name="_bx_massmailer_email_body">
+    <![CDATA[
+  <br />{content} <br />
+  <img src="{seen_image_url}" width="1" height="1">
+  ]]></string>
+</resources>

+ 139 - 0
modules/boonex/massmailer/updates/13.0.4_13.0.5/source/install/sql/install.sql

@@ -0,0 +1,139 @@
+SET @sName = 'bx_massmailer';
+
+-- TABLES
+CREATE TABLE `bx_massmailer_campaigns` (
+  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
+  `title` varchar(255) DEFAULT NULL,
+  `subject` varchar(255) DEFAULT NULL,
+  `from_name` varchar(255) DEFAULT NULL,
+  `reply_to` varchar(255) DEFAULT NULL,
+  `body` text DEFAULT NULL,
+  `segments` varchar(255) DEFAULT NULL,
+  `author` int(11) NOT NULL,
+  `added` int(11) NOT NULL default '0',
+  `changed` int(11) NOT NULL default '0',
+  `date_sent` int(11) NOT NULL default '0',
+  `email_list` text DEFAULT NULL,
+  `is_one_per_account` smallint(1) NOT NULL,
+  `is_track_links` smallint(1) NOT NULL,  
+  PRIMARY KEY (`id`),
+  FULLTEXT KEY `title_text` (`title`, `subject`)
+);
+
+CREATE TABLE `bx_massmailer_segments` (
+  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
+  `title` varchar(255) DEFAULT NULL,
+  `info` text DEFAULT NULL,
+  `email_list` text DEFAULT NULL,
+  PRIMARY KEY (`id`)
+);
+
+CREATE TABLE `bx_massmailer_letters` (
+  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
+  `campaign_id` int(11) NOT NULL,
+  `email` varchar(255) NOT NULL,
+  `date_sent` int(11) NOT NULL default '0',
+  `date_seen` int(11) NOT NULL default '0',
+  `date_click` int(11) NOT NULL default '0',
+  `hash` varchar(35) NOT NULL,
+  PRIMARY KEY (`id`),
+  INDEX `campaign_id` (`campaign_id`),
+  INDEX `hash` (`hash`)
+);
+
+CREATE TABLE `bx_massmailer_links` (
+  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
+  `letter_hash` varchar(35) DEFAULT NULL,
+  `hash` varchar(35) DEFAULT NULL,
+  `link` varchar(255) DEFAULT NULL,
+  `title` varchar(255) DEFAULT NULL,
+  `campaign_id` int(11) DEFAULT NULL,
+  `date_click` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  INDEX `campaign_id` (`campaign_id`),
+  INDEX `hash` (`hash`),
+  INDEX `letter_hash` (`letter_hash`)
+);
+
+CREATE TABLE `bx_massmailer_unsubscribe` (
+  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
+  `account_id` int(11) DEFAULT NULL,
+  `campaign_id` int(11) DEFAULT NULL,
+  `unsubscribed` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  INDEX `campaign_id` (`campaign_id`)
+);
+
+-- STUDIO: page & widget
+INSERT INTO `sys_std_pages`(`index`, `name`, `header`, `caption`, `icon`) VALUES
+(3, @sName, '_bx_massmailer', '_bx_massmailer', 'bx_massmailer@modules/boonex/massmailer/|std-icon.svg');
+
+SET @iPageId = LAST_INSERT_ID();
+
+INSERT INTO `sys_std_widgets` (`page_id`, `module`, `type`, `url`, `click`, `icon`, `caption`, `cnt_notices`, `cnt_actions`, `featured`) 
+VALUES(@iPageId, @sName, 'extensions', '{url_studio}module.php?name=bx_massmailer', '', 'bx_massmailer@modules/boonex/massmailer/|std-icon.svg', '_bx_massmailer', '', '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";}', 0);
+
+SET @iParentPageId = (SELECT `id` FROM `sys_std_pages` WHERE `name` = 'home');
+SET @iParentPageOrder = (SELECT IFNULL(MAX(`order`), 0) + 1 FROM `sys_std_pages_widgets` WHERE `page_id` = @iParentPageId);
+
+INSERT INTO `sys_std_pages_widgets` (`page_id`, `widget_id`, `order`) VALUES
+(@iParentPageId, LAST_INSERT_ID(), @iParentPageOrder);
+
+-- FORMS
+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(@sName, @sName, '_bx_massmailer_form_campaign', '', 'a:1:{s:7:"enctype";s:19:"multipart/form-data";}', 'a:2:{i:0;s:9:"do_submit";i:1;s:7:"do_send";}', 'bx_massmailer_campaigns', 'id', '', '', 'a:1:{s:14:"checker_helper";s:29:"BxMassMailerFormCheckerHelper";}', 0, 1, 'BxMassMailerFormEntry', 'modules/boonex/massmailer/classes/BxMassMailerFormEntry.php');
+
+INSERT INTO `sys_form_displays` (`display_name`, `module`, `object`, `title`, `view_mode`) VALUES
+('bx_massmailer_campaign_add', @sName, @sName, '_bx_massmailer_form_campaign_add_display', 0),
+('bx_massmailer_campaign_edit', @sName, @sName, '_bx_massmailer_form_campaign_edit_display', 0),
+('bx_massmailer_campaign_send_test', @sName, @sName, '_bx_massmailer_form_campaign_send_test_display', 0),
+('bx_massmailer_campaign_send_all', @sName, @sName, '_bx_massmailer_form_campaign_send_all_display', 0);
+
+INSERT INTO `sys_form_inputs` (`object`, `module`, `name`, `value`, `values`, `checked`, `type`, `caption_system`, `caption`, `info`, `required`, `unique`, `collapsed`, `html`, `attrs`, `attrs_tr`, `attrs_wrapper`, `checker_func`, `checker_params`, `checker_error`, `db_pass`, `db_params`, `editable`, `deletable`) VALUES
+(@sName, @sName, 'do_submit', '_bx_massmailer_form_entry_input_do_submit', '', 0, 'submit', '_bx_massmailer_form_entry_input_sys_do_submit', '', '', 0, 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+(@sName, @sName, 'do_send', '_bx_massmailer_form_entry_input_do_send', '', 0, 'submit', '_bx_massmailer_form_entry_input_sys_do_send', '', '', 0, 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+(@sName, @sName, 'title', '', '', 0, 'text', '_bx_massmailer_form_campaign_input_sys_title', '_bx_massmailer_form_campaign_input_title', '', 1, 0, 0, 2, '', '', '', 'Avail', '', '_bx_massmailer_form_campaign_input_title_err', 'XssHtml', '', 1, 0),
+(@sName, @sName, 'segments', '', '', 0, 'select', '_bx_massmailer_form_campaign_input_sys_segments', '_bx_massmailer_form_campaign_input_segments', '', 1, 0, 0, 2, '', '', '', 'Avail', '', '_bx_massmailer_form_campaign_input_segments_err', 'XssHtml', '', 1, 0),
+(@sName, @sName, 'subject', '', '', 0, 'text', '_bx_massmailer_form_campaign_input_sys_subject', '_bx_massmailer_form_campaign_input_subject', '', 1, 0, 0, 2, '', '', '', 'Avail', '', '_bx_massmailer_form_campaign_input_subject_err', 'XssHtml', '', 1, 0),
+(@sName, @sName, 'from_name', '', '', 0, 'text', '_bx_massmailer_form_campaign_input_sys_from_name', '_bx_massmailer_form_campaign_input_from_name', '_bx_massmailer_form_campaign_input_from_name_info', 0, 0, 0, 2, '', '', '', '', '', '', 'XssHtml', '', 1, 0),
+(@sName, @sName, 'reply_to', '', '', 0, 'text', '_bx_massmailer_form_campaign_input_sys_reply_to', '_bx_massmailer_form_campaign_input_reply_to', '_bx_massmailer_form_campaign_input_reply_to_info', 0, 0, 0, 2, '', '', '', 'EmailOrEmpty', '', '_bx_massmailer_form_campaign_input_reply_to_err', 'XssHtml', '', 1, 0),
+(@sName, @sName, 'body', '', '', 0, 'textarea', '_bx_massmailer_form_campaign_input_sys_body', '_bx_massmailer_form_campaign_input_body', '', 1, 0, 0, 2, '', '', '', 'UnsubscribeUrl', '', '_bx_massmailer_form_campaign_input_body_err', 'XssHtml', '', 1, 0),
+(@sName, @sName, 'is_one_per_account', '1', '', 1, 'switcher', '_bx_massmailer_form_campaign_input_sys_is_one_per_account', '_bx_massmailer_form_campaign_input_is_one_per_account', '', 0, 0, 0, 0, '', '', '', '', '', '', 'Int', '', 1, 0),
+(@sName, @sName, 'is_track_links', '1', '', 1, 'switcher', '_bx_massmailer_form_campaign_input_sys_is_track_links', '_bx_massmailer_form_campaign_input_is_track_links', '', 0, 0, 0, 0, '', '', '', '', '', '', 'Int', '', 1, 0),
+(@sName, @sName, 'email', '', '', 0, 'text', '_bx_massmailer_form_campaign_input_sys_test_email', '_bx_massmailer_form_campaign_input_email', '', 1, 0, 0, 2, '', '', '', 'Email', '', '_sys_form_account_input_email_error', 'XssHtml', '', 1, 0),
+(@sName, @sName, 'campaign_info', '_bx_massmailer_form_campaign_input_from_name_info_value', '', 0, 'value', '_bx_massmailer_form_campaign_input_sys_campaign_info', '', '', 0, 0, 0, 2, '', '', '', '', '', '', 'XssHtml', '', 1, 0),
+(@sName, @sName, 'cancel', '_bx_massmailer_form_entry_input_cancel', '', 0, 'button', '_bx_dev_bp_btn_sys_block_cancel', '', '', 0, 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";}', '', '', 'Avail', '', '', '', '', 0, 0),
+(@sName, @sName, 'controls', '', 'do_submit,cancel', 0, 'input_set', '', '', '', 0, 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
+(@sName, @sName, 'controls2', '', 'do_send,cancel', 0, 'input_set', '', '', '', 0, 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0);
+
+INSERT INTO `sys_form_display_inputs` (`display_name`, `input_name`, `visible_for_levels`, `active`, `order`) VALUES
+('bx_massmailer_campaign_add', 'title', 2147483647, 1, 1),
+('bx_massmailer_campaign_add', 'segments', 2147483647, 1, 2),
+('bx_massmailer_campaign_add', 'subject', 2147483647, 1, 3),
+('bx_massmailer_campaign_add', 'from_name', 2147483647, 1, 4),
+('bx_massmailer_campaign_add', 'reply_to', 2147483647, 1, 5),
+('bx_massmailer_campaign_add', 'body', 2147483647, 1, 6),
+('bx_massmailer_campaign_add', 'is_one_per_account', 2147483647, 1, 7),
+('bx_massmailer_campaign_add', 'is_track_links', 2147483647, 1, 8),
+('bx_massmailer_campaign_add', 'controls', 2147483647, 1, 9),
+('bx_massmailer_campaign_add', 'do_submit', 2147483647, 1, 10),
+('bx_massmailer_campaign_add', 'cancel', 2147483647, 1, 10),
+('bx_massmailer_campaign_edit', 'title', 2147483647, 1, 1),
+('bx_massmailer_campaign_edit', 'segments', 2147483647, 1, 2),
+('bx_massmailer_campaign_edit', 'subject', 2147483647, 1, 3),
+('bx_massmailer_campaign_edit', 'from_name', 2147483647, 1, 4),
+('bx_massmailer_campaign_edit', 'reply_to', 2147483647, 1, 5),
+('bx_massmailer_campaign_edit', 'body', 2147483647, 1, 6),
+('bx_massmailer_campaign_edit', 'is_one_per_account', 2147483647, 1, 7),
+('bx_massmailer_campaign_edit', 'is_track_links', 2147483647, 1, 8),
+('bx_massmailer_campaign_edit', 'controls', 2147483647, 1, 9),
+('bx_massmailer_campaign_edit', 'do_submit', 2147483647, 1, 10),
+('bx_massmailer_campaign_edit', 'cancel', 2147483647, 1, 11),
+('bx_massmailer_campaign_send_test', 'email', 2147483647, 1, 1),
+('bx_massmailer_campaign_send_test', 'controls2', 2147483647, 1, 2),
+('bx_massmailer_campaign_send_test', 'do_send', 2147483647, 1, 3),
+('bx_massmailer_campaign_send_test', 'cancel', 2147483647, 1, 4),
+('bx_massmailer_campaign_send_all', 'campaign_info', 2147483647, 1, 1),
+('bx_massmailer_campaign_send_all', 'controls2', 2147483647, 1, 2),
+('bx_massmailer_campaign_send_all', 'do_send', 2147483647, 1, 3),
+('bx_massmailer_campaign_send_all', 'cancel', 2147483647, 1, 4);

+ 51 - 0
modules/boonex/payment/updates/13.0.8_13.0.9/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.8',
+    'version_to' => '13.0.9',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '13.1.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/payment/updates/update_13.0.8_13.0.9/',
+    'home_uri' => 'payment_update_1308_1309',
+
+    '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' => 0,
+        'clear_db_cache' => 0,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Payment',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

+ 13 - 0
modules/boonex/payment/updates/13.0.8_13.0.9/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);
+    }
+}

+ 246 - 0
modules/boonex/payment/updates/13.0.8_13.0.9/source/classes/BxPaymentOrders.php

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

+ 953 - 0
modules/boonex/payment/updates/13.0.8_13.0.9/source/classes/BxPaymentProviderStripeV3.php

@@ -0,0 +1,953 @@
+<?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
+ *
+ * @{
+ */
+
+require_once('BxPaymentProviderStripeBasic.php');
+
+class BxPaymentProviderStripeV3 extends BxPaymentProviderStripeBasic implements iBxBaseModPaymentProvider
+{
+    protected $_oStripe;
+
+    protected $_iAmountPrecision;
+
+    function __construct($aConfig)
+    {
+        parent::__construct($aConfig);
+
+        $this->_aIncludeJs = array(
+            'stripe_v3.js'
+        );
+
+        $this->_oStripe = null;
+
+        $this->_iAmountPrecision = 2;
+    }
+
+    public function actionGetSessionRecurring()
+    {
+        $aClient = $this->_oModule->getProfileInfo();
+
+        $aParams = array(
+            'seller_id' => (int)bx_get('seller_id'),
+            'seller_provider' => bx_process_input(bx_get('seller_provider')),
+            'module_id' => (int)bx_get('module_id'),
+            'item_id' => (int)bx_get('item_id'),
+            'item_count' => (int)bx_get('item_count'),
+            'item_addons' => '',
+            'redirect' => bx_process_input(bx_get('redirect')),
+            'custom' => bx_process_input(bx_get('custom')),
+        );
+        
+        if(($mixedItemAddons = bx_get('item_addons')) !== false) {
+            $mixedItemAddons = bx_process_input($mixedItemAddons);
+            if(!is_array($mixedItemAddons))
+                $mixedItemAddons = strpos($mixedItemAddons, ',') !== false ? explode(',', $mixedItemAddons) : [$mixedItemAddons];
+
+            $aParams['item_addons'] = $this->_oModule->_oConfig->a2s($mixedItemAddons);
+        }
+
+        $aItems = array($this->_oModule->_oConfig->descriptorA2S(array(
+            'seller_id' => $aParams['seller_id'],
+            'module_id' => $aParams['module_id'],
+            'item_id' => $aParams['item_id'],
+            'item_count' => $aParams['item_count'],
+            'item_addons' => $aParams['item_addons'],
+        )));
+
+        $oCart = $this->_oModule->getObjectCart();
+        $aCartInfo = $oCart->getInfo(BX_PAYMENT_TYPE_RECURRING, $aClient['id'], $aParams['seller_id'], $aItems);
+        if(empty($aCartInfo) || !is_array($aCartInfo))
+            return echoJson(array('msg' => _t('_bx_payment_err_nothing_selected')));
+
+        $aItem = reset($aCartInfo['items']);
+
+        $aSessionParams = array(
+            'cancel_url' => $aItem['url'],
+            'success_url' => bx_append_url_params($this->_oModule->_oConfig->getUrl('URL_SUBSCRIBE_JSON'), array_merge($aParams, array(
+                'session_id' => '{CHECKOUT_SESSION_ID}'
+            )), false)
+        );
+
+        $sSessionId = $this->_createSession(BX_PAYMENT_TYPE_RECURRING, $aSessionParams, $aClient, $aCartInfo);
+        if($sSessionId === false)
+            return echoJson(array('msg' => _t('_bx_payment_err_cannot_perform')));
+
+        $sJsObject = $this->getJsObject(array(
+            'iModuleId' => $aParams['module_id'],
+            'iSellerId' => $aParams['seller_id'],
+            'iItemId' => $aParams['item_id']
+        ));
+
+        return echoJson(array(
+            'code' => 0, 
+            'session_id' => $sSessionId,
+            'eval' => $sJsObject . '.onSubscribe(oData);'
+        ));
+    }
+
+    public function authorizeCheckout($iPendingId, $aCartInfo, $sRedirect = '')
+    {
+        $sSessionId = bx_process_input(bx_get('session_id'));
+
+    	if(empty($aCartInfo['items']) || !is_array($aCartInfo['items']))
+            return $this->_sLangsPrefix . 'err_empty_items';
+
+        $aClient = $this->_oModule->getProfileInfo();
+        $aVendor = $this->_oModule->getProfileInfo($aCartInfo['vendor_id']);
+
+        $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->_getSession(BX_PAYMENT_TYPE_SINGLE, $sSessionId);
+                if($mixedResult === false)
+                    return $this->_sLangsPrefix . 'err_cannot_perform';
+
+                return [
+                    'code' => BX_PAYMENT_RESULT_SUCCESS,
+                    'redirect' => $this->getReturnDataUrl($aVendor['id'], array(
+                        'mode' => $mixedResult['mode'],
+                        'order_id' => $mixedResult['order_id'],
+                        'customer_id' => $mixedResult['customer_id'], 
+                        'pending_id' => $aPending['id'],
+                        'redirect' => $sRedirect
+                    ))
+                ];
+
+            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'];
+
+        $bPaid = false;
+        $sOrder = '';
+        switch($aPending['type']) {
+            case BX_PAYMENT_TYPE_SINGLE:
+                $oPaymentIntent = $this->_createPaymentIntent($sOrderAuth, $aInfo['items_price'], $aInfo['vendor_currency_code']);
+                if($oPaymentIntent === false)
+                    return ['code' => 3, 'message' => $this->_sLangsPrefix . 'err_cannot_perform'];
+
+                $aPaymentIntent = $oPaymentIntent->jsonSerialize();
+                if(empty($aPaymentIntent) || !is_array($aPaymentIntent))
+                    return ['code' => 3, 'message' => $this->_sLangsPrefix . 'err_cannot_perform'];
+
+                $bPaid = $aPaymentIntent['status'] == 'succeeded';
+                $sOrder = $aPaymentIntent['id'];
+                break;
+
+            case BX_PAYMENT_TYPE_RECURRING:
+                return ['code' => 1, 'message' => $this->_sLangsPrefix . 'err_not_supported'];
+        }
+
+        $aResult = [
+            'code' => BX_PAYMENT_RESULT_SUCCESS,
+            'message' => $this->_sLangsPrefix . 'strp_msg_charged',
+            'pending_id' => $aPending['id'],
+            'paid' => $bPaid
+        ];
+
+        //--- Update pending transaction
+        $this->_oModule->_oDb->updateOrderPending($aResult['pending_id'], [
+            'order' => $sOrder,
+            'error_code' => $aResult['code'],
+            'error_msg' => _t($aResult['message']),
+        ]);
+
+        return $aResult;
+    }
+
+    public function initializeCheckout($iPendingId, $aCartInfo, $sRedirect = '')
+    {
+        $sSessionId = bx_process_input(bx_get('session_id'));
+
+    	if(empty($aCartInfo['items']) || !is_array($aCartInfo['items']))
+            return $this->_sLangsPrefix . 'err_empty_items';
+
+        $aClient = $this->_oModule->getProfileInfo();
+        $aVendor = $this->_oModule->getProfileInfo($aCartInfo['vendor_id']);
+
+        $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->_getSession(BX_PAYMENT_TYPE_SINGLE, $sSessionId);
+                if($mixedResult === false || $mixedResult['status'] != 'paid')
+                    return $this->_sLangsPrefix . 'err_cannot_perform';
+
+                header("Location: " . $this->getReturnDataUrl($aVendor['id'], array(
+                    'mode' => $mixedResult['mode'],
+                    'order_id' => $mixedResult['order_id'],
+                    'customer_id' => $mixedResult['customer_id'], 
+                    'pending_id' => $aPending['id'],
+                    'redirect' => $sRedirect
+                )));
+                exit;
+
+            case BX_PAYMENT_TYPE_RECURRING:
+                $mixedResult = $this->_getSession(BX_PAYMENT_TYPE_RECURRING, $sSessionId);
+                if($mixedResult === false)
+                    return $this->_sLangsPrefix . 'err_cannot_perform';
+
+                header("Location: " . $this->getReturnDataUrl($aVendor['id'], array(
+                    'mode' => $mixedResult['mode'],
+                    'order_id' => $mixedResult['order_id'],
+                    'customer_id' => $mixedResult['customer_id'],
+                    'pending_id' => $aPending['id'],
+                    'redirect' => $sRedirect
+                )));
+                exit;
+        }
+    }
+
+    public function finalizeCheckout(&$aData)
+    {
+        $sMode = bx_process_input($aData['mode']);
+    	$sOrderId = bx_process_input($aData['order_id']);
+    	$sCustomerId = bx_process_input($aData['customer_id']);
+        $iPendingId = bx_process_input($aData['pending_id'], BX_DATA_INT);
+        if(empty($iPendingId))
+            return array('code' => 1, 'message' => $this->_sLangsPrefix . 'err_wrong_data');
+
+        $sRedirect = bx_process_input($aData['redirect']);
+
+        $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 array('code' => 3, 'message' => $this->_sLangsPrefix . 'err_already_processed');
+
+        $aResult = array(
+            'code' => BX_PAYMENT_RESULT_SUCCESS,
+            'message' => '',
+            'pending_id' => $iPendingId,
+            'customer_id' => '',
+            'subscription_id' => '',
+            'client_name' => '',
+            'client_email' => '',
+            'authorized' => false,
+            'paid' => false,
+            'trial' => false,
+            'redirect' => $sRedirect
+        );
+
+        switch($aPending['type']) {
+            case BX_PAYMENT_TYPE_SINGLE:
+                $oCustomer = $this->_retrieveCustomer(BX_PAYMENT_TYPE_SINGLE, $sCustomerId);
+                if($oCustomer === false)
+                    return array('code' => 4, 'message' => $this->_sLangsPrefix . 'err_cannot_perform');
+
+                $aCustomer = $oCustomer->jsonSerialize();
+                if(empty($aCustomer) || !is_array($aCustomer))
+                    return array('code' => 4, 'message' => $this->_sLangsPrefix . 'err_cannot_perform');
+
+                $sMessage = '';
+                $bPaid = $bAuthorized = false;
+                switch($sMode) {
+                    case 'setup':
+                        $oSetupIntent = $this->_retrieveSetupIntent($sOrderId);
+                        if($oSetupIntent === false)
+                            return array('code' => 4, 'message' => $this->_sLangsPrefix . 'err_cannot_perform');
+                        
+                        $aSetupIntent = $oSetupIntent->jsonSerialize();
+                        if(empty($aSetupIntent) || !is_array($aSetupIntent))
+                            return array('code' => 4, 'message' => $this->_sLangsPrefix . 'err_cannot_perform');
+                                
+                        $sMessage = $this->_sLangsPrefix . 'strp_msg_authorized';
+                        $bAuthorized = $aSetupIntent['status'] == 'succeeded';
+                        break;
+
+                    case 'payment':
+                        $oPaymentIntent = $this->_retrievePaymentIntent($sOrderId);
+                        if($oPaymentIntent === false)
+                            return array('code' => 4, 'message' => $this->_sLangsPrefix . 'err_cannot_perform');
+
+                        $aPaymentIntent = $oPaymentIntent->jsonSerialize();
+                        if(empty($aPaymentIntent) || !is_array($aPaymentIntent))
+                            return array('code' => 4, 'message' => $this->_sLangsPrefix . 'err_cannot_perform');
+
+                        $sMessage = $this->_sLangsPrefix . 'strp_msg_charged';
+                        $bPaid = $aPaymentIntent['status'] == 'succeeded';
+                        break;
+                }
+
+                $aResult = array_merge($aResult, array(
+                    'message' => $sMessage,
+                    'client_email' => $aCustomer['email'],
+                    'authorized' => $bAuthorized,
+                    'paid' => $bPaid,
+                ));
+                break;
+
+            case BX_PAYMENT_TYPE_RECURRING:
+                $oCustomer = $this->_retrieveCustomer(BX_PAYMENT_TYPE_RECURRING, $sCustomerId);
+                $oSubscription = $this->_retrieveSubscription($sCustomerId, $sOrderId);
+                if($oCustomer === false || $oSubscription === false)
+                    return array('code' => 4, 'message' => $this->_sLangsPrefix . 'err_cannot_perform');
+
+                $aCustomer = $oCustomer->jsonSerialize();
+                $aSubscription = $oSubscription->jsonSerialize();
+                if(empty($aCustomer) || !is_array($aCustomer) || empty($aSubscription) || !is_array($aSubscription))
+                    return array('code' => 4, 'message' => $this->_sLangsPrefix . 'err_cannot_perform');
+
+                $aResult = array_merge($aResult, array(
+                    'message' => $this->_sLangsPrefix . 'strp_msg_subscribed',
+                    'customer_id' => $sCustomerId,
+                    'subscription_id' => $sOrderId,
+                    'client_email' => $aCustomer['email'],
+                    'trial' => $this->isSubscriptionStatus(BX_PAYMENT_SBS_STATUS_TRIAL, $aSubscription)
+                ));
+                break;
+        }
+
+        //--- Update pending transaction ---//
+        $this->_oModule->_oDb->updateOrderPending($iPendingId, array(
+            'order' => $sOrderId,
+            'error_code' => $aResult['code'],
+            'error_msg' => _t($aResult['message'])
+        ));
+
+        return $aResult;
+    }
+
+    public function getButtonSingle($iClientId, $iVendorId, $aParams = array())
+    {
+        if(!isset($aParams['sAction']))
+            return '';
+
+        return $aParams['sAction'] . parent::getButtonSingle($iClientId, $iVendorId, $aParams);
+    }
+
+    public function overwriteCheckoutParamsSingle($aParams, &$oGrid)
+    {
+        $aClient = $this->_oModule->getProfileInfo();
+
+        $oCart = $this->_oModule->getObjectCart();
+        $aCartInfo = $oCart->getInfo(BX_PAYMENT_TYPE_SINGLE, $aClient['id'], $aParams['seller_id'], $aParams['items']);
+        if(empty($aCartInfo) || !is_array($aCartInfo))
+            return array('msg' => _t('_bx_payment_err_nothing_selected'));
+
+        $aSessionParams = array(
+            'cancel_url' => $oCart->serviceGetCartUrl($aParams['seller_id']),
+            'success_url' => bx_append_url_params($this->_oModule->_oConfig->getUrl('URL_CART_CHECKOUT'), array_merge($aParams, array(
+                'session_id' => '{CHECKOUT_SESSION_ID}'
+            )), false)
+        );
+
+        $sSessionId = $this->_createSession(BX_PAYMENT_TYPE_SINGLE, $aSessionParams, $aClient, $aCartInfo);
+        if($sSessionId === false)
+            return array('msg' => _t('_bx_payment_err_cannot_perform'));
+
+        return array(
+            'eval' => $this->_oModule->_oConfig->getJsObject($this->_sName) . '.onCartCheckout(oData);', 
+            'session_id' => $sSessionId
+        );
+    }
+
+    public function createSessionAuthorize($sType, $iClientId, $iSellerId, $sItems, $aSessionParams = [])
+    {
+        $aClient = $this->_oModule->getProfileInfo($iClientId);
+
+        $oCart = $this->_oModule->getObjectCart();
+        $aCartInfo = $oCart->getInfo($sType, $aClient['id'], $iSellerId, $sItems);
+        if(empty($aCartInfo) || !is_array($aCartInfo))
+            return false;
+
+        $aSessionParams = array_merge([
+            'cancel_url' => $oCart->serviceGetCartUrl($iSellerId),
+            'success_url' => bx_append_url_params($this->_oModule->_oConfig->getUrl('URL_AUTHORIZE') . $sType . '/', [
+                'provider' => $this->_sName,
+                'seller_id' => $iSellerId,
+                'items' => $sItems,
+                'session_id' => '{CHECKOUT_SESSION_ID}'
+            ], false)
+        ], $aSessionParams);
+
+        return $this->_createSession('authorize', $aSessionParams, $aClient, $aCartInfo);
+    }
+
+    public function createTax($sName, $fPercentage, $bInclusive = false)
+    {
+        $oTax = null;
+        $aTax = [
+            'display_name' => $sName,
+            'percentage' => $fPercentage,
+            'inclusive' => $bInclusive,
+        ];
+
+        bx_alert($this->_oModule->_oConfig->getName(), $this->_sName . '_create_tax', 0, false, array(
+            'tax_object' => &$oTax, 
+            'tax_params' => &$aTax
+        ));
+
+        try {
+            if(empty($oTax))
+                $oTax = $this->_getStripe()->taxRates->create($aTax);
+        }
+        catch (Exception $oException) {
+            return $this->_processException('Create Tax Error: ', $oException);
+        }
+
+        $aResult = $oTax->jsonSerialize();
+        if(empty($aResult) || !is_array($aResult))
+            return false;
+
+        return $aResult['id'];
+    }
+
+    public function retrieveTax($sId)
+    {
+        $oTax = null;
+        bx_alert($this->_oModule->_oConfig->getName(), $this->_sName . '_retrieve_tax', 0, false, array(
+            'tax_id' => &$sId,
+            'tax_object' => &$oTax
+        ));
+
+        try {
+            if(empty($oTax))
+                $oTax = $this->_getStripe()->taxRates->retrieve($sId);
+        }
+        catch (Exception $oException) {
+            return $this->_processException('Retrieve Tax Error: ', $oException);
+        }
+
+        return $oTax;
+    }
+
+    public function getVerificationCodeSession($iVendorId, $iCustomerId, $fAmount, $sCurrency)
+    {
+        $sCode = $this->_getVerificationCodeSession($iVendorId, $iCustomerId, $fAmount, $sCurrency);
+
+        bx_alert($this->_oModule->_oConfig->getName(), $this->_sName . '_get_code_session', 0, false, array(
+            'provider' => $this,
+            'vendor_id' => $iVendorId, 
+            'customer_id' => $iCustomerId,
+            'amount' => $fAmount,
+            'currency' => $sCurrency,
+            'override_result' => &$sCode
+        ));
+
+        return $sCode;
+    }
+
+    public function checkVerificationCodeSession($iVendorId, $iCustomerId, $aResult)
+    {
+        $bCheckResult = $this->_checkVerificationCodeSession($iVendorId, $iCustomerId, $aResult);
+
+        bx_alert($this->_oModule->_oConfig->getName(), $this->_sName . '_verify_session', 0, false, array(
+            'provider' => $this,
+            'vendor_id' => $iVendorId, 
+            'customer_id' => $iCustomerId,
+            'result' => $aResult,
+            'override_result' => &$bCheckResult
+        ));
+
+        return $bCheckResult;
+    }
+
+    protected function _getStripe()
+    {
+        if(empty($this->_oStripe))
+            $this->_oStripe = new \Stripe\StripeClient($this->_getSecretKey());
+
+        return $this->_oStripe;
+    }
+
+    /*
+     * Related Docs: https://stripe.com/docs/api/customers/retrieve
+     */
+    protected function _retrieveCustomer($sType, $sId)
+    {
+        $oCustomer = null;
+        bx_alert($this->_oModule->_oConfig->getName(), $this->_sName . '_retrieve_customer', 0, false, array(
+            'type' => $sType,
+            'customer_id' => &$sId,
+            'customer_object' => &$oCustomer
+        ));
+
+        try {
+            if(empty($oCustomer))
+                $oCustomer = $this->_getStripe()->customers->retrieve($sId);
+        }
+        catch (Exception $oException) {
+            return $this->_processException('Retrieve Customer Error: ', $oException);
+        }
+
+        return $oCustomer;
+    }
+
+    /*
+     * Related Docs: https://stripe.com/docs/api/checkout/sessions/create
+     */
+    protected function _createSession($sType, $aParams, &$aClient, &$aCartInfo)
+    {
+        $sMode = '';
+        $aLineItems = $aMetaItems = [];
+        $bVerify = true;
+
+        switch($sType) {
+            case 'authorize':
+                $sMode = 'setup';
+                $bVerify = false;
+
+                foreach($aCartInfo['items'] as $aItem) {
+                    $aMetaItems[] = $this->_oModule->_oConfig->descriptorA2S([$aItem['module_id'], $aItem['id']]);
+                    if(!empty($aItem['addons']) && is_array($aItem['addons']))
+                        foreach($aItem['addons'] as $aAddon)
+                            $aMetaItems[] = $this->_oModule->_oConfig->descriptorA2S([$aAddon['module_id'], $aAddon['id']]);
+                }
+
+                $aParams['customer_creation'] = 'always';
+                break;
+
+            case BX_PAYMENT_TYPE_SINGLE:
+                $sMode = 'payment';
+
+                foreach($aCartInfo['items'] as $aItem) {
+                    $aProductData = [
+                        'name' => $aItem['title']
+                    ];
+                    if(!empty($aItem['description']))
+                        $aProductData['description'] = strmaxtextlen(strip_tags($aItem['description']), 60, '...');
+
+                    $aLineItems[] = [
+                        'price_data' => [
+                            'currency' => $aCartInfo['vendor_currency_code'],
+                            'product_data' => $aProductData,
+                            'unit_amount' => 100 * $this->_oModule->_oConfig->getPrice($sType, $aItem, $this->_iAmountPrecision),
+                        ],
+                        'quantity' => $aItem['quantity'],
+                    ];
+
+                    $aMetaItems[] = $this->_oModule->_oConfig->descriptorA2S([$aItem['module_id'], $aItem['id']]);
+
+                    if(!empty($aItem['addons']) && is_array($aItem['addons']))
+                        foreach($aItem['addons'] as $aAddon) {
+                            $aAddonData = [
+                                'name' => $aAddon['title']
+                            ];
+                            if(!empty($aAddon['description']))
+                                $aAddonData['description'] = strmaxtextlen(strip_tags($aAddon['description']), 60, '...');
+
+                            $aLineItems[] = [
+                                'price_data' => [
+                                    'currency' => $aCartInfo['vendor_currency_code'],
+                                    'product_data' => $aAddonData,
+                                    'unit_amount' => 100 * $this->_oModule->_oConfig->getPrice($sType, $aAddon, $this->_iAmountPrecision),
+                                ],
+                                'quantity' => $aAddon['quantity'],
+                            ];
+
+                            $aMetaItems[] = $this->_oModule->_oConfig->descriptorA2S([$aAddon['module_id'], $aAddon['id']]);
+                        }
+                }
+                break;
+
+            case BX_PAYMENT_TYPE_RECURRING:
+                $sMode = 'subscription';
+                $iTrial = 0;
+
+                foreach($aCartInfo['items'] as $aItem) {
+                    $aLineItems[] = [
+                        'price' => $aItem['name'],
+                        'quantity' => $aItem['quantity'],
+                    ];
+
+                    if((int)$aItem['trial_recurring'] > 0)
+                        $iTrial = (int)$aItem['trial_recurring'];
+
+                    $aMetaItems[] = $this->_oModule->_oConfig->descriptorA2S([$aItem['module_id'], $aItem['id']]);
+                    
+                    if(!empty($aItem['addons']) && is_array($aItem['addons']))
+                        foreach($aItem['addons'] as $aAddon) {
+                            $aLineItems[] = [
+                                'price' => $aAddon['name'],
+                                'quantity' => $aAddon['quantity'],
+                            ];
+
+                            $aMetaItems[] = $this->_oModule->_oConfig->descriptorA2S([$aAddon['module_id'], $aAddon['id']]);
+                        }
+                }
+
+                if($iTrial > 0) {
+                    $bVerify = false;
+
+                    $aParams['subscription_data'] = [
+                        'trial_period_days' => $iTrial
+                    ];
+                }
+
+                break;
+        }
+
+        $oSession = null;
+        $aSession = array_merge([
+            'payment_method_types' => ['card'],
+            'customer_email' => !empty($aClient['email']) ? $aClient['email'] : '',
+            'mode' => $sMode,
+            'success_url' => '',
+            'cancel_url' => '',
+        ], $aParams);
+
+        $bLineItems = !empty($aLineItems);
+        $aSession['line_items'] = $aLineItems;
+
+        $bMetaData = !empty($aMetaItems);
+        if($bMetaData) {
+            $aSession['metadata'] = [
+                'vendor' => $aCartInfo['vendor_id'],
+                'client' => $aClient['id'],
+                'type' => $sType, 
+                'items' => $this->_oModule->_oConfig->descriptorsA2S($aMetaItems)
+            ];
+
+            if($bVerify) {
+                $fAmount = 100 * round((float)$aCartInfo['items_price'], $this->_iAmountPrecision);
+                $aSession['metadata']['verification'] = $this->getVerificationCodeSession($aCartInfo['vendor_id'], $aClient['id'], $fAmount, $aCartInfo['vendor_currency_code']);
+            }
+        }
+
+        bx_alert($this->_oModule->_oConfig->getName(), $this->_sName . '_create_session', 0, false, array(
+            'session_object' => &$oSession, 
+            'session_params' => &$aSession
+        ));
+
+        try {
+            if(empty($oSession))
+                $oSession = $this->_getStripe()->checkout->sessions->create($aSession);
+        }
+        catch (Exception $oException) {
+            return $this->_processException('Create Session Error: ', $oException);
+        }
+
+        $aResult = $oSession->jsonSerialize();
+        if(empty($aResult) || !is_array($aResult))
+            return false;
+
+        if($bVerify && !$this->checkVerificationCodeSession($aCartInfo['vendor_id'], $aClient['id'], $aResult))
+            return false;
+
+        return $aResult['id'];
+    }
+
+    protected function _getSession($sType, $sId)
+    {
+        $oSession = $this->_retrieveSession($sId);
+        if($oSession === false)
+            return array();
+
+        $aSession = $oSession->jsonSerialize();
+        if(empty($aSession) || !is_array($aSession))
+            return array();
+
+        $sMode = 'payment';
+        if(!empty($aSession['mode']))
+            $sMode = $aSession['mode'];
+        
+        $aResult = array(
+            'id' => $aSession['id'],
+            'mode' => $sMode,
+            'order_id' => '',
+            'customer_id' => $aSession['customer'],
+            'status' => $aSession['payment_status']
+        );
+
+        switch($sType) {
+            case BX_PAYMENT_TYPE_SINGLE:
+                $aResult['order_id'] = $aSession[($sMode == 'setup' ? 'setup' : 'payment') . '_intent'];
+                break;
+
+            case BX_PAYMENT_TYPE_RECURRING:
+                $aResult['order_id'] = $aSession['subscription'];
+                break;
+        }
+
+        return $aResult;
+    }
+
+    /*
+     * Related Docs: https://stripe.com/docs/api/checkout/sessions/retrieve
+     */
+    protected function _retrieveSession($sId)
+    {
+        $oSession = null;
+        bx_alert($this->_oModule->_oConfig->getName(), $this->_sName . '_retrieve_session', 0, false, array(
+            'session_id' => &$sId,
+            'session_object' => &$oSession
+        ));
+
+        try {
+            if(empty($oSession))
+                $oSession = $this->_getStripe()->checkout->sessions->retrieve($sId);
+        }
+        catch (Exception $oException) {
+            return $this->_processException('Retrieve Session Error: ', $oException);
+        }
+
+        return $oSession;
+    }
+    
+    
+    /*
+     * Related Docs: https://stripe.com/docs/api/setup_intents/retrieve
+     */
+    protected function _retrieveSetupIntent($sId)
+    {
+        $oSetupIntent = null;
+        bx_alert($this->_oModule->_oConfig->getName(), $this->_sName . '_retrieve_setup_intent', 0, false, array(
+            'setup_intent_id' => &$sId,
+            'setup_intent_object' => &$oSetupIntent
+        ));
+
+        try {
+            if(empty($oSetupIntent))
+                $oSetupIntent = $this->_getStripe()->setupIntents->retrieve($sId);
+        }
+        catch (Exception $oException) {
+            return $this->_processException('Retrieve Setup Intent Error: ', $oException);
+        }
+
+        return $oSetupIntent;
+    }
+
+    /*
+     * Related Docs: https://stripe.com/docs/api/payment_intents/create
+     */
+    protected function _createPaymentIntent($sSetupIntentId, $fAmount, $sCurrency, $bConfirm = true)
+    {
+        $oPaymentIntent = null;
+        bx_alert($this->_oModule->_oConfig->getName(), $this->_sName . '_create_payment_intent', 0, false, array(
+            'setup_intent_id' => &$sSetupIntentId,
+            'payment_intent_object' => &$oPaymentIntent
+        ));
+
+        try {
+            if(empty($oPaymentIntent)) {
+                $oSetupIntent = $this->_retrieveSetupIntent($sSetupIntentId);
+                if($oSetupIntent === false)
+                    return false;
+
+                $aSetupIntent = $oSetupIntent->jsonSerialize();
+                if(empty($aSetupIntent) || !is_array($aSetupIntent))
+                    return false;
+
+                $oPaymentIntent = $this->_getStripe()->paymentIntents->create([
+                    'amount' => 100 * round($fAmount, $this->_iAmountPrecision),
+                    'currency' => strtolower($sCurrency),
+                    'customer' => $aSetupIntent['customer'],
+                    'payment_method' => $aSetupIntent['payment_method'],
+                    'confirm' => $bConfirm
+                ]);
+            }
+        }
+        catch (Exception $oException) {
+            return $this->_processException('Retrieve Payment Intent Error: ', $oException);
+        }
+
+        return $oPaymentIntent;
+    }
+
+    /*
+     * Related Docs: https://stripe.com/docs/api/payment_intents/retrieve
+     */
+    protected function _retrievePaymentIntent($sId)
+    {
+        $oPaymentIntent = null;
+        bx_alert($this->_oModule->_oConfig->getName(), $this->_sName . '_retrieve_payment_intent', 0, false, array(
+            'payment_intent_id' => &$sId,
+            'payment_intent_object' => &$oPaymentIntent
+        ));
+
+        try {
+            if(empty($oPaymentIntent))
+                $oPaymentIntent = $this->_getStripe()->paymentIntents->retrieve($sId);
+        }
+        catch (Exception $oException) {
+            return $this->_processException('Retrieve Payment Intent Error: ', $oException);
+        }
+
+        return $oPaymentIntent;
+    }
+    
+    /*
+     * Related Docs: https://stripe.com/docs/api/subscriptions/retrieve
+     */
+    protected function _retrieveSubscription($sCustomerId, $sSubscriptionId)
+    {
+        $oSubscription = null;
+        bx_alert($this->_oModule->_oConfig->getName(), $this->_sName . '_retrieve_subscription', 0, false, array(
+            'subscription_id' => &$sId,
+            'subscription_object' => &$oSubscription
+        ));
+
+        try {
+            if(empty($oSubscription))
+                $oSubscription = $this->_getStripe()->subscriptions->retrieve($sSubscriptionId);
+        }
+        catch (Exception $oException) {
+            return $this->_processException('Retrieve Subscription Error: ', $oException);
+        }
+
+        return $oSubscription;
+    }
+
+    /*
+     * Related Docs: https://stripe.com/docs/api/tokens/create_card
+     */
+    protected function _createToken($aCard)
+    {
+        try {
+            $oToken = $this->_getStripe()->tokens->create(['card' => $aCard]);
+        }
+        catch (Stripe\Error\Base $oException) {
+            return $this->_processException('Create Token Error: ', $oException);
+        }
+
+        return $oToken->jsonSerialize();
+    }
+
+    /*
+     * Related Docs: https://stripe.com/docs/api/cards/create
+     */
+    protected function _createCard($sType, $sCustomerId, $sToken)
+    {
+        try {
+            $oCard = $this->_getStripe()->customers->createSource($sCustomerId, [
+                'source' => $sToken
+            ]);
+        }
+        catch (Stripe\Error\Base $oException) {
+            return $this->_processException('Create Card Error: ', $oException);
+        }
+
+        return $oCard->jsonSerialize();
+    }
+
+    protected function _retrieveCard($sCustomerId, $sCardId = '')
+    {
+        try {
+            $oCustomer = $this->_getStripe()->customers->retrieve($sCustomerId);
+
+            if(empty($sCardId))
+                $sCardId = $oCustomer->default_source;
+            if(empty($sCardId))
+                return false;
+
+            $oCard = $this->_getStripe()->customers->retrieveSource($sCustomerId, $sCardId);
+        }
+        catch (Exception $oException) {
+            return $this->_processException('Retrieve Card Error: ', $oException);
+        }
+
+        return $oCard;
+    }
+
+    /*
+     * Related Docs: https://stripe.com/docs/api/payment_methods/retrieve
+     */
+    protected function _retrievePaymentMethod($sPaymentMethodId)
+    {
+        try {
+            $oPaymentMethod = $this->_getStripe()->paymentMethods->retrieve($sPaymentMethodId);
+        }
+        catch (Exception $oException) {
+            return $this->_processException('Retrieve Payment Method Error: ', $oException);
+        }
+
+        return $oPaymentMethod;
+    }
+
+    protected function _getButton($sType, $iClientId, $iVendorId, $aParams = array())
+    {
+        list($sJsCode, $sJsMethod) = $this->_getButtonJs($sType, $iClientId, $iVendorId, $aParams);
+
+    	if($sType == BX_PAYMENT_TYPE_SINGLE)
+            return $sJsCode;
+
+        return parent::_getButton($sType, $iClientId, $iVendorId);
+    }
+
+    protected function _getButtonJs($sType, $iClientId, $iVendorId, $aParams = array())
+    {
+        $sClientEmail = '';
+    	if(!empty($iClientId) && ($oClient = BxDolProfile::getInstance($iClientId)) !== false)
+            $sClientEmail = $oClient->getAccountObject()->getEmail();
+
+        $sPublicKey = '';
+    	bx_alert($this->_oModule->_oConfig->getName(), $this->_sName . '_get_button', 0, $iClientId, array(
+            'type' => &$sType, 
+            'public_key' => &$sPublicKey
+        ));
+
+        $sJsMethod = '';
+        $sJsObject = $this->getJsObject($aParams);
+        switch($sType) {
+            case BX_PAYMENT_TYPE_SINGLE:
+                $sJsMethod = 'void(0)';
+                break;
+
+            case BX_PAYMENT_TYPE_RECURRING:
+                $sJsMethod = $sJsObject . '.subscribe(this)';
+                break;
+        }
+
+        return array($this->_oModule->_oTemplate->getJsCode($this->_sName, array_merge(array(
+            'js_object' => $sJsObject,
+            'sProvider' => $this->_sName,
+            'sPublicKey' => !empty($sPublicKey) ? $sPublicKey : $this->_getPublicKey(),
+            'sVendorName' => '',
+            'sVendorCurrency' => '',
+            'sVendorIcon' => '',
+            'sClientEmail' => $sClientEmail,
+        ), $aParams)), $sJsMethod);
+    }
+
+    protected function _getVerificationCodeSession($iVendorId, $iCustomerId, $fAmount, $sCurrency)
+    {
+        return md5(implode('#-#', array(
+            (int)$iVendorId,
+            (int)$iCustomerId,
+            (float)$fAmount,
+            strtoupper($sCurrency)
+        )));
+    }
+
+    protected function _checkVerificationCodeSession($iVendorId, $iCustomerId, $aResult)
+    {
+        return !empty($aResult['metadata']['verification']) && $aResult['metadata']['verification'] == $this->getVerificationCodeSession($iVendorId, $iCustomerId, $aResult['amount_total'], $aResult['currency']);
+    }
+
+    protected function _processException($sMessage, &$oException)
+    {
+        if(method_exists($oException, 'getError')) {
+            $sError = $oException->getError()->message;
+            $aError = $oException->getError()->toArray();
+        }
+        else { 
+            $sError = $oException->getMessage();
+            $aError = array();
+        }
+
+        $this->log($sMessage . $sError);
+        if(!empty($aError))
+            $this->log($aError);
+
+        return false;
+    }
+}
+
+/** @} */

+ 70 - 0
modules/boonex/payment/updates/13.0.8_13.0.9/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.9',
+    'vendor' => 'Boonex',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '13.1.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/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(),
+);
+
+/** @} */

+ 51 - 0
modules/boonex/persons/updates/13.0.8_13.0.9/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.8',
+    'version_to' => '13.0.9',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '13.1.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/persons/updates/update_13.0.8_13.0.9/',
+    'home_uri' => 'persons_update_1308_1309',
+
+    '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' => 0,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Persons',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

+ 13 - 0
modules/boonex/persons/updates/13.0.8_13.0.9/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);
+    }
+}

+ 12 - 0
modules/boonex/persons/updates/13.0.8_13.0.9/install/sql/enable.sql

@@ -0,0 +1,12 @@
+-- MENUS
+DELETE FROM `sys_menu_items` WHERE `set_name`='bx_persons_snippet_meta' AND `name` IN ('ignore-befriend', 'ignore-subscribe');
+INSERT INTO `sys_menu_items`(`set_name`, `module`, `name`, `title_system`, `title`, `link`, `onclick`, `target`, `icon`, `submenu_object`, `visible_for_levels`, `hidden_on_cxt`, `active`, `copyable`, `editable`, `order`) VALUES
+('bx_persons_snippet_meta', 'bx_persons', 'ignore-befriend', '_sys_menu_item_title_system_sm_ignore_befriend', '_sys_menu_item_title_sm_ignore', '', '', '', '', '', 2147483647, 'all!recom_friends', 1, 0, 1, 13),
+('bx_persons_snippet_meta', 'bx_persons', 'ignore-subscribe', '_sys_menu_item_title_system_sm_ignore_subscribe', '_sys_menu_item_title_sm_ignore', '', '', '', '', '', 2147483647, 'all!recom_subscriptions', 1, 0, 1, 14);
+
+UPDATE `sys_menu_items` SET `hidden_on_cxt`='all!recom_friends' WHERE `set_name`='bx_persons_snippet_meta' AND `name` IN ('friends-mutual');
+UPDATE `sys_menu_items` SET `hidden_on_cxt`='recom_friends,recom_subscriptions' WHERE `set_name`='bx_persons_snippet_meta' AND `name` IN ('friends', 'unfriend', 'unsubscribe');
+UPDATE `sys_menu_items` SET `hidden_on_cxt`='recom_friends' WHERE `set_name`='bx_persons_snippet_meta' AND `name` IN ('subscribers', 'subscribe');
+UPDATE `sys_menu_items` SET `hidden_on_cxt`='recom_subscriptions' WHERE `set_name`='bx_persons_snippet_meta' AND `name` IN ('befriend');
+
+UPDATE `sys_menu_items` SET `active`='0' WHERE `set_name`='sys_profile_stats' AND `module`='bx_persons' AND `name` IN ('profile-stats-friend-requests', 'profile-stats-subscriptions', 'profile-stats-subscribed-me');

+ 5 - 0
modules/boonex/persons/updates/13.0.8_13.0.9/install/sql/install.sql

@@ -0,0 +1,5 @@
+SET @sName = 'bx_persons';
+
+
+-- VOTES
+UPDATE `sys_objects_vote` SET `Module`=@sName WHERE `Name`=@sName;

+ 152 - 0
modules/boonex/persons/updates/13.0.8_13.0.9/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.9',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '13.1.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/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',
+    ),
+);
+
+/** @} */

+ 562 - 0
modules/boonex/persons/updates/13.0.8_13.0.9/source/install/sql/enable.sql

@@ -0,0 +1,562 @@
+
+-- 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: 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-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-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', 'friends', '_sys_menu_item_title_system_sm_friends', '_sys_menu_item_title_sm_friends', '', '', '', '', '', 0, 2147483647, '', 1, 0, 23),
+('bx_persons_view_meta', 'bx_persons', 'subscribers', '_sys_menu_item_title_system_sm_subscribers', '_sys_menu_item_title_sm_subscribers', '', '', '', '', '', 0, 2147483647, '', 1, 0, 25),
+('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`, `hidden_on_cxt`, `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, 'all!recom_friends', 1, 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, 'recom_friends,recom_subscriptions', 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, 'recom_friends', 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, 'recom_subscriptions', 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, 'recom_friends,recom_subscriptions', 1, 0, 1, 10),
+('bx_persons_snippet_meta', 'bx_persons', 'subscribe', '_sys_menu_item_title_system_sm_subscribe', '_sys_menu_item_title_sm_subscribe', '', '', '', '', '', 2147483647, 'recom_friends', 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, 'recom_friends,recom_subscriptions', 1, 0, 1, 12),
+('bx_persons_snippet_meta', 'bx_persons', 'ignore-befriend', '_sys_menu_item_title_system_sm_ignore_befriend', '_sys_menu_item_title_sm_ignore', '', '', '', '', '', 2147483647, 'all!recom_friends', 1, 0, 1, 13),
+('bx_persons_snippet_meta', 'bx_persons', 'ignore-subscribe', '_sys_menu_item_title_system_sm_ignore_subscribe', '_sys_menu_item_title_sm_ignore', '', '', '', '', '', 2147483647, 'all!recom_subscriptions', 1, 0, 1, 14);
+
+-- 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, '', 0, 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, '', 0, 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, '', 0, 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');

+ 418 - 0
modules/boonex/persons/updates/13.0.8_13.0.9/source/install/sql/install.sql

@@ -0,0 +1,418 @@
+
+SET @sStorageEngine = (SELECT `value` FROM `sys_options` WHERE `name` = 'sys_storage_default');
+
+-- TABLE: PROFILES
+CREATE TABLE IF NOT EXISTS `bx_persons_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,
+  `cover_data` varchar(50) NOT NULL,
+  `fullname` varchar(255) NOT NULL,
+  `last_name` varchar(255) NOT NULL,
+  `description` text NOT NULL,
+  `gender` varchar(255) DEFAULT NULL,
+  `birthday` date DEFAULT 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',
+  `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',
+  PRIMARY KEY (`id`),
+  FULLTEXT KEY `search_fields` (`fullname`,`description`)
+);
+
+-- TABLE: STORAGES & TRANSCODERS
+CREATE TABLE IF NOT EXISTS `bx_persons_pictures` (
+  `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_persons_pictures_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_persons_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_persons_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_persons_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_persons_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_persons_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_persons_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',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `id` (`object_id`,`author_id`)
+);
+
+-- TABLE: reports
+CREATE TABLE IF NOT EXISTS `bx_persons_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_persons_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_persons_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_persons_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_persons_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: scores
+CREATE TABLE IF NOT EXISTS `bx_persons_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_persons_scores_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `author_nip` int(11) unsigned NOT NULL default '0',
+  `type` varchar(8) NOT NULL default '',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `vote` (`object_id`, `author_nip`)
+);
+
+CREATE TABLE `bx_persons_skills` (
+  `skill_id` int(11) NOT NULL AUTO_INCREMENT,
+  `skill_name` varchar(500) DEFAULT NULL,
+  `content_id` int(11) NOT NULL,
+  PRIMARY KEY (`skill_id`),
+  KEY `content_id` (`content_id`)
+);
+
+
+-- 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_persons_pictures', @sStorageEngine, '', 360, 2592000, 3, 'bx_persons_pictures', 'allow-deny', '{image}', '', 0, 0, 0, 0, 0, 0),
+('bx_persons_pictures_resized', @sStorageEngine, '', 360, 2592000, 3, 'bx_persons_pictures_resized', 'allow-deny', '{image}', '', 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_persons_icon', 'bx_persons_pictures_resized', 'Storage', 'a:1:{s:6:"object";s:19:"bx_persons_pictures";}', 'no', '1', '2592000', '0'),
+('bx_persons_thumb', 'bx_persons_pictures_resized', 'Storage', 'a:1:{s:6:"object";s:19:"bx_persons_pictures";}', 'no', '1', '2592000', '0'),
+('bx_persons_avatar', 'bx_persons_pictures_resized', 'Storage', 'a:1:{s:6:"object";s:19:"bx_persons_pictures";}', 'no', '1', '2592000', '0'),
+('bx_persons_avatar_big', 'bx_persons_pictures_resized', 'Storage', 'a:1:{s:6:"object";s:19:"bx_persons_pictures";}', 'no', '1', '2592000', '0'),
+('bx_persons_picture', 'bx_persons_pictures_resized', 'Storage', 'a:1:{s:6:"object";s:19:"bx_persons_pictures";}', 'no', '1', '2592000', '0'),
+('bx_persons_cover', 'bx_persons_pictures_resized', 'Storage', 'a:1:{s:6:"object";s:19:"bx_persons_pictures";}', 'no', '1', '2592000', '0'),
+('bx_persons_cover_thumb', 'bx_persons_pictures_resized', 'Storage', 'a:1:{s:6:"object";s:19:"bx_persons_pictures";}', 'no', '1', '2592000', '0'),
+('bx_persons_gallery', 'bx_persons_pictures_resized', 'Storage', 'a:1:{s:6:"object";s:19:"bx_persons_pictures";}', 'no', '1', '2592000', '0');
+
+INSERT INTO `sys_transcoder_filters` (`transcoder_object`, `filter`, `filter_params`, `order`) VALUES 
+('bx_persons_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_persons_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_persons_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_persons_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_persons_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_persons_cover', 'Resize', 'a:2:{s:1:"w";s:3:"960";s:1:"h";s:3:"480";}', '0'),
+('bx_persons_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_persons_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`, `parent_form`) VALUES 
+('bx_person', 'bx_persons', '_bx_persons_form_profile', '', 'a:1:{s:7:\"enctype\";s:19:\"multipart/form-data\";}', 'bx_persons_data', 'id', '', '', 'do_submit', '', 0, 1, 'BxPersonsFormEntry', 'modules/boonex/persons/classes/BxPersonsFormEntry.php', ''),
+('bx_person_skills', 'bx_persons', '_bx_persons_skills_form_profile', '', 'a:1:{s:7:\"enctype\";s:19:\"multipart/form-data\";}', 'bx_persons_skills', 'skill_id', '', '', 'do_submit', '', 0, 1, 'BxDolFormNested', 'inc/classes/BxDolFormNested.php', 'bx_person');
+
+INSERT INTO `sys_form_displays`(`object`, `display_name`, `module`, `view_mode`, `title`) VALUES 
+('bx_person', 'bx_person_add', 'bx_persons', 0, '_bx_persons_form_profile_display_add'),
+('bx_person', 'bx_person_delete', 'bx_persons', 0, '_bx_persons_form_profile_display_delete'),
+('bx_person', 'bx_person_edit', 'bx_persons', 0, '_bx_persons_form_profile_display_edit'),
+('bx_person', 'bx_person_edit_cover', 'bx_persons', 0, '_bx_persons_form_profile_display_edit_cover'),
+('bx_person', 'bx_person_view', 'bx_persons', 1, '_bx_persons_form_profile_display_view'),
+('bx_person', 'bx_person_view_full', 'bx_persons', 1, '_bx_persons_form_profile_display_view_full'),
+('bx_person_skills', 'bx_person_skills', 'bx_persons', 0, '_bx_persons_skills_form_profile_display_add'),
+('bx_person_skills', 'bx_person_skills_view', 'bx_persons', 1, '_bx_persons_skills_form_profile_display_view');
+
+INSERT INTO `sys_form_inputs`(`object`, `module`, `name`, `value`, `values`, `checked`, `type`, `caption_system`, `caption`, `info`, `required`, `collapsed`, `html`, `attrs`, `attrs_tr`, `attrs_wrapper`, `checker_func`, `checker_params`, `checker_error`, `db_pass`, `db_params`, `editable`, `deletable`, `rateable`) VALUES 
+('bx_person', 'bx_persons', 'allow_view_to', 3, '', 0, 'custom', '_bx_persons_form_profile_input_sys_allow_view_to', '_bx_persons_form_profile_input_allow_view_to', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0, ''),
+('bx_person', 'bx_persons', 'allow_post_to', 5, '', 0, 'custom', '_bx_persons_form_profile_input_sys_allow_post_to', '_bx_persons_form_profile_input_allow_post_to', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0, ''),
+('bx_person', 'bx_persons', 'allow_contact_to', 3, '', 0, 'custom', '_bx_persons_form_profile_input_sys_allow_contact_to', '_bx_persons_form_profile_input_allow_contact_to', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0, ''),
+('bx_person', 'bx_persons', 'delete_confirm', 1, '', 0, 'checkbox', '_bx_persons_form_profile_input_sys_delete_confirm', '_bx_persons_form_profile_input_delete_confirm', '_bx_persons_form_profile_input_delete_confirm_info', 1, 0, 0, '', '', '', 'Avail', '', '_bx_persons_form_profile_input_delete_confirm_error', '', '', 1, 0, ''),
+('bx_person', 'bx_persons', 'do_submit', '_bx_persons_form_profile_input_submit', '', 0, 'submit', '_bx_persons_form_profile_input_sys_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0, ''),
+('bx_person', 'bx_persons', 'description', '', '', 0, 'textarea', '_bx_persons_form_profile_input_sys_desc', '_bx_persons_form_profile_input_desc', '', 0, 0, 1, '', '', '', '', '', '', 'XssHtml', '', 1, 1, ''),
+('bx_person', 'bx_persons', 'fullname', '', '', 0, 'text', '_bx_persons_form_profile_input_sys_fullname', '_bx_persons_form_profile_input_fullname', '', 1, 0, 0, '', '', '', 'ProfileName', '', '_bx_persons_form_profile_input_fullname_err', 'Xss', '', 1, 0, ''),
+('bx_person', 'bx_persons', 'last_name', '', '', 0, 'text', '_bx_persons_form_profile_input_sys_last_name', '_bx_persons_form_profile_input_last_name', '', 1, 0, 0, '', '', '', '', '', '', 'Xss', '', 1, 0, ''),
+('bx_person', 'bx_persons', 'cover', 'a:1:{i:0;s:21:"bx_persons_cover_crop";}', 'a:1:{s:21:"bx_persons_cover_crop";s:24:"_sys_uploader_crop_title";}', 0, 'files', '_bx_persons_form_profile_input_sys_cover', '_bx_persons_form_profile_input_cover', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0, ''),
+('bx_person', 'bx_persons', 'picture', 'a:1:{i:0;s:23:"bx_persons_picture_crop";}', 'a:1:{s:23:"bx_persons_picture_crop";s:24:"_sys_uploader_crop_title";}', 0, 'files', '_bx_persons_form_profile_input_sys_picture', '_bx_persons_form_profile_input_picture', '', 0, 0, 0, '', '', '', '', '', '_bx_persons_form_profile_input_picture_err', '', '', 1, 0, ''),
+('bx_person', 'bx_persons', 'location', '', '', 0, 'location', '_sys_form_input_sys_location', '_sys_form_input_location', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0, ''),
+('bx_person', 'bx_persons', 'birthday', '0', '', 0, 'datepicker', '_bx_persons_form_profile_input_sys_birthday', '_bx_persons_form_profile_input_birthday', '', 1, 0, 0, '', '', '', 'date_range', 'a:3:{s:3:"min";i:18;s:3:"max";i:99;s:8:"required";b:0;}', '_bx_persons_form_profile_input_birthday_err', 'Date', '', 1, 0, ''),
+('bx_person', 'bx_persons', 'gender', '', '#!Sex', 0, 'select', '_bx_persons_form_profile_input_sys_gender', '_bx_persons_form_profile_input_gender', '', 0, 0, 0, '', '', '', '', '', '', 'Xss', '', 1, 0, ''),
+('bx_person', 'bx_persons', 'profile_email', '', '', 0, 'text', '_bx_persons_form_profile_input_sys_profile_email', '_bx_persons_form_profile_input_profile_email', '', 0, 0, 0, '', '', '', '', '', '', 'Xss', '', 0, 0, ''),
+('bx_person', 'bx_persons', 'profile_status', '', '', 0, 'text', '_bx_persons_form_profile_input_sys_profile_status', '_bx_persons_form_profile_input_profile_status', '', 0, 0, 0, '', '', '', '', '', '', 'Xss', '', 0, 0, ''),
+('bx_person', 'bx_persons', 'profile_ip', '', '', 0, 'text', '_bx_persons_form_profile_input_sys_profile_ip', '_bx_persons_form_profile_input_profile_ip', '', 0, 0, 0, '', '', '', '', '', '', 'Xss', '', 0, 0, ''),
+('bx_person', 'bx_persons', 'labels', '', '', 0, 'custom', '_sys_form_input_sys_labels', '_sys_form_input_labels', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0, ''),
+('bx_person', 'bx_persons', 'skills', 'bx_person_skills', '', 0, 'nested_form', '_bx_persons_form_profile_input_sys_skills', '_bx_persons_form_profile_input_skills', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0, 'sys_form_fields_votes'),
+('bx_person', 'bx_persons', 'added', '', '', 0, 'datetime', '_bx_persons_form_profile_input_sys_date_added', '_bx_persons_form_profile_input_date_added', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0, ''),
+('bx_person', 'bx_persons', 'changed', '', '', 0, 'datetime', '_bx_persons_form_profile_input_sys_date_changed', '_bx_persons_form_profile_input_date_changed', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0, ''),
+('bx_person', 'bx_persons', 'friends_count', '', '', 0, 'text', '_bx_persons_form_profile_input_sys_friends_count', '_bx_persons_form_profile_input_friends_count', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0, ''),
+('bx_person', 'bx_persons', 'followers_count', '', '', 0, 'text', '_bx_persons_form_profile_input_sys_followers_count', '_bx_persons_form_profile_input_followers_count', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0, ''),
+('bx_person_skills', 'bx_persons', 'skill_name', '', '', 0, 'text', '_bx_persons_skills_form_profile_input_sys_skill_name', '_bx_persons_skills_form_profile_input_skill_name', '', 1, 0, 0, '', '', '', 'Avail', '', '_bx_persons_skills_form_profile_input_skill_name_err', 'Xss', '', 1, 0, '');
+
+INSERT INTO `sys_form_display_inputs`(`display_name`, `input_name`, `visible_for_levels`, `active`, `order`) VALUES 
+('bx_person_add', 'picture', 2147483647, 1, 1),
+('bx_person_add', 'gender', 2147483647, 1, 2),
+('bx_person_add', 'birthday', 2147483647, 1, 3),
+('bx_person_add', 'fullname', 2147483647, 1, 4),
+('bx_person_add', 'last_name', 2147483647, 0, 5),
+('bx_person_add', 'description', 2147483647, 1, 6),
+('bx_person_add', 'location', 2147483647, 1, 7),
+('bx_person_add', 'allow_view_to', 2147483647, 1, 8),
+('bx_person_add', 'allow_post_to', 2147483647, 1, 9),
+('bx_person_add', 'allow_contact_to', 2147483647, 1, 10),
+('bx_person_add', 'do_submit', 2147483647, 1, 11),
+
+('bx_person_delete', 'cover', 2147483647, 0, 0),
+('bx_person_delete', 'picture', 2147483647, 0, 0),
+('bx_person_delete', 'delete_confirm', 2147483647, 1, 0),
+('bx_person_delete', 'do_submit', 2147483647, 1, 1),
+('bx_person_delete', 'fullname', 2147483647, 0, 2),
+
+('bx_person_edit', 'picture', 2147483647, 1, 1),
+('bx_person_edit', 'gender', 2147483647, 1, 2),
+('bx_person_edit', 'birthday', 2147483647, 1, 3),
+('bx_person_edit', 'fullname', 2147483647, 1, 4),
+('bx_person_edit', 'last_name', 2147483647, 0, 5),
+('bx_person_edit', 'description', 2147483647, 1, 6),
+('bx_person_edit', 'location', 2147483647, 1, 7),
+('bx_person_edit', 'allow_view_to', 2147483647, 1, 8),
+('bx_person_edit', 'allow_post_to', 2147483647, 1, 9),
+('bx_person_edit', 'allow_contact_to', 2147483647, 1, 10),
+('bx_person_edit', 'do_submit', 2147483647, 1, 11),
+
+('bx_person_edit_cover', 'delete_confirm', 2147483647, 0, 1),
+('bx_person_edit_cover', 'fullname', 2147483647, 0, 2),
+('bx_person_edit_cover', 'picture', 2147483647, 0, 3),
+('bx_person_edit_cover', 'cover', 2147483647, 1, 7),
+('bx_person_edit_cover', 'do_submit', 2147483647, 1, 8),
+
+('bx_person_view', 'gender', 2147483647, 1, 1),
+('bx_person_view', 'birthday', 2147483647, 1, 2),
+('bx_person_view', 'fullname', 2147483647, 1, 3),
+('bx_person_view', 'last_name', 2147483647, 0, 4),
+('bx_person_view', 'profile_email', 192, 1, 5),
+('bx_person_view', 'profile_status', 192, 1, 6),
+('bx_person_view', 'profile_ip', 192, 1, 7),
+('bx_person_view', 'added', 192, 1, 8),
+('bx_person_view', 'changed', 192, 1, 9),
+('bx_person_view', 'friends_count', 2147483647, 1, 10),
+('bx_person_view', 'followers_count', 2147483647, 1, 11),
+
+('bx_person_view_full', 'gender', 2147483647, 1, 1),
+('bx_person_view_full', 'birthday', 2147483647, 1, 2),
+('bx_person_view_full', 'fullname', 2147483647, 1, 3),
+('bx_person_view_full', 'last_name', 2147483647, 0, 4),
+('bx_person_view_full', 'description', 2147483647, 0, 5),
+('bx_person_view_full', 'profile_email', 192, 1, 6),
+('bx_person_view_full', 'profile_status', 192, 1, 7),
+
+('bx_person_skills', 'skill_name', 2147483647, 1, 1),
+('bx_person_skills_view', 'skill_name', 2147483647, 1, 1);
+
+-- COMMENTS
+INSERT INTO `sys_objects_cmts` (`Name`, `Module`, `Table`, `CharsPostMin`, `CharsPostMax`, `CharsDisplayMax`, `Html`, `PerView`, `PerViewReplies`, `BrowseType`, `IsBrowseSwitch`, `PostFormPosition`, `NumberOfLevels`, `IsDisplaySwitch`, `IsRatable`, `ViewingThreshold`, `IsOn`, `RootStylePrefix`, `BaseUrl`, `ObjectVote`, `TriggerTable`, `TriggerFieldId`, `TriggerFieldAuthor`, `TriggerFieldTitle`, `TriggerFieldComments`, `ClassName`, `ClassFile`) VALUES
+('bx_persons', 'bx_persons', 'bx_persons_cmts', 1, 5000, 1000, 3, 5, 3, 'tail', 1, 'bottom', 1, 1, 1, -3, 1, 'cmt', 'page.php?i=view-persons-profile&id={object_id}', '', 'bx_persons_data', 'id', 'author', 'fullname', 'comments', 'BxPersonsCmts', 'modules/boonex/persons/classes/BxPersonsCmts.php'),
+('bx_persons_notes', 'bx_persons', 'bx_persons_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_persons_data', 'id', 'author', 'fullname', '', '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_persons', 'bx_persons', 'bx_persons_views_track', '86400', '1', 'bx_persons_data', 'id', 'author', 'views', '', '');
+
+-- VOTES
+INSERT INTO `sys_objects_vote` (`Name`, `Module`, `TableMain`, `TableTrack`, `PostTimeout`, `MinValue`, `MaxValue`, `IsUndo`, `IsOn`, `TriggerTable`, `TriggerFieldId`, `TriggerFieldAuthor`, `TriggerFieldRate`, `TriggerFieldRateCount`, `ClassName`, `ClassFile`) VALUES 
+('bx_persons', 'bx_persons', 'bx_persons_votes', 'bx_persons_votes_track', '604800', '1', '1', '0', '1', 'bx_persons_data', 'id', '', 'rate', 'votes', 'BxPersonsVote', 'modules/boonex/persons/classes/BxPersonsVote.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_persons', 'bx_persons', 'bx_persons_scores', 'bx_persons_scores_track', '604800', '0', 'bx_persons_data', 'id', 'author', 'score', 'sc_up', 'sc_down', '', '');
+
+-- FAFORITES
+INSERT INTO `sys_objects_favorite` (`name`, `table_track`, `is_on`, `is_undo`, `is_public`, `base_url`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_count`, `class_name`, `class_file`) VALUES 
+('bx_persons', 'bx_persons_favorites_track', '1', '1', '0', 'page.php?i=view-persons-profile&id={object_id}', 'bx_persons_data', 'id', 'author', 'favorites', 'BxPersonsFavorite', 'modules/boonex/persons/classes/BxPersonsFavorite.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_persons', 'bx_persons', '1', '1', 'page.php?i=view-persons-profile&id={object_id}', 'bx_persons_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_persons', 'bx_persons', 'bx_persons_reports', 'bx_persons_reports_track', '1', 'page.php?i=view-persons-profile&id={object_id}', 'bx_persons_notes', 'bx_persons_data', 'id', 'author', 'reports', 'BxPersonsReport', 'modules/boonex/persons/classes/BxPersonsReport.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_persons', '_bx_persons', 'bx_persons', 'added', 'edited', 'deleted', '', ''),
+('bx_persons_cmts', '_bx_persons_cmts', 'bx_persons', 'commentPost', 'commentUpdated', 'commentRemoved', 'BxDolContentInfoCmts', '');
+
+INSERT INTO `sys_content_info_grids` (`object`, `grid_object`, `grid_field_id`, `condition`, `selection`) VALUES
+('bx_persons', 'bx_persons_administration', 'td`.`id', '', ''),
+('bx_persons', 'bx_persons_common', 'td`.`id', '', '');
+
+-- SEARCH EXTENDED
+INSERT INTO `sys_objects_search_extended` (`object`, `object_content_info`, `module`, `title`, `active`, `class_name`, `class_file`) VALUES
+('bx_persons', 'bx_persons', 'bx_persons', '_bx_persons_search_extended', 1, '', ''),
+('bx_persons_cmts', 'bx_persons_cmts', 'bx_persons', '_bx_persons_search_extended_cmts', 1, 'BxTemplSearchExtendedCmts', '');
+
+-- STUDIO PAGE & WIDGET
+INSERT INTO `sys_std_pages`(`index`, `name`, `header`, `caption`, `icon`) VALUES
+(3, 'bx_persons', '_bx_persons', '_bx_persons', 'bx_persons@modules/boonex/persons/|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_persons', 'users', '{url_studio}module.php?name=bx_persons', '', 'bx_persons@modules/boonex/persons/|std-icon.svg', '_bx_persons', '', '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/photos/updates/13.0.6_13.0.7/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' => 'Photos',
+    'version_from' => '13.0.6',
+    'version_to' => '13.0.7',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '13.0.1-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/photos/updates/update_13.0.6_13.0.7/',
+    'home_uri' => 'photos_update_1306_1307',
+
+    'module_dir' => 'boonex/photos/',
+    'module_uri' => 'photos',
+
+    'db_prefix' => 'bx_photos_',
+    'class_prefix' => 'BxPhotos',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_files' => 1,
+        'update_languages' => 0,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Photos',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

+ 13 - 0
modules/boonex/photos/updates/13.0.6_13.0.7/install/installer.php

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

+ 10 - 0
modules/boonex/photos/updates/13.0.6_13.0.7/install/sql/install.sql

@@ -0,0 +1,10 @@
+-- STORAGES & TRANSCODERS
+UPDATE `sys_transcoder_filters` SET `filter_params`='a:1:{s:1:"w";s:4:"1200";}' WHERE `transcoder_object`='bx_photos_cover';
+
+
+-- VOTES
+UPDATE `sys_objects_vote` SET `Module`='bx_photos' WHERE `Name` IN ('bx_photos', 'bx_photos_stars', 'bx_photos_reactions');
+
+
+-- VIEWS
+UPDATE `sys_objects_view` SET `module`='bx_photos' WHERE `name`='bx_photos';

+ 136 - 0
modules/boonex/photos/updates/13.0.6_13.0.7/source/install/config.php

@@ -0,0 +1,136 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Photos Photos
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_photos',
+    'title' => 'Photos',
+    'note' => 'Basic photo posting module.',
+    'version' => '13.0.7',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '13.1.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/photos/',
+    'home_uri' => 'photos',
+
+    'db_prefix' => 'bx_photos_',
+    'class_prefix' => 'BxPhotos',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Photos',
+
+    /**
+     * List of page triggers.
+     */
+    'page_triggers' => array (
+    	'trigger_page_profile_view_entry',
+    ),
+    
+    /**
+     * Menu triggers.
+     */
+    'menu_triggers' => array(
+    	'trigger_profile_view_submenu',
+        'trigger_group_view_submenu'
+    ),
+
+    /**
+     * Storage objects to automatically delete files from upon module uninstallation.
+     * Note. Don't add storage objects used in transcoder objects.
+     */
+    'storages' => array(
+    	'bx_photos_files'
+    ),
+
+    /**
+     * Transcoders.
+     */
+    'transcoders' => array(
+		'bx_photos_preview',
+        'bx_photos_gallery',
+        'bx_photos_cover'
+    ),
+
+    /**
+     * Extended Search Forms.
+     */
+    'esearches' => array(
+        'bx_photos',
+    	'bx_photos_cmts'
+    ),
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'uninstall' => array (
+    	'process_esearches' => 1,
+        'execute_sql' => 1,
+        'update_languages' => 1,
+        'update_relations' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'enable' => array(
+        'execute_sql' => 1,
+        'update_relations' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'enable_success' => array(
+        'process_menu_triggers' => 1,
+        'process_page_triggers' => 1,
+    	'process_esearches' => 1,
+        'register_transcoders' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable' => array (
+        'execute_sql' => 1,
+        'update_relations' => 1,
+        'unregister_transcoders' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable_failed' => array (
+        'register_transcoders' => 1,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Dependencies Section
+     */
+    'dependencies' => array(),
+
+    /**
+     * Relations Section
+     */
+    'relations' => array(
+    	'bx_timeline',
+    	'bx_notifications'
+    ),
+
+);
+
+/** @} */

+ 447 - 0
modules/boonex/photos/updates/13.0.6_13.0.7/source/install/sql/install.sql

@@ -0,0 +1,447 @@
+-- TABLE: entries
+CREATE TABLE IF NOT EXISTS `bx_photos_entries` (
+  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+  `author` int(10) unsigned NOT NULL default '0',
+  `added` int(11) NOT NULL default '0',
+  `changed` int(11) NOT NULL default '0',
+  `thumb` int(11) NOT NULL default '0',
+  `title` varchar(255) NOT NULL,
+  `cat` int(11) NOT NULL,
+  `text` text NOT NULL,
+  `labels` text NOT NULL,
+  `location` text NOT NULL,
+  `views` int(11) NOT NULL default '0',
+  `rate` float NOT NULL default '0',
+  `votes` int(11) NOT NULL default '0',
+  `srate` float NOT NULL default '0',
+  `svotes` int(11) NOT NULL default '0',
+  `rrate` float NOT NULL default '0',
+  `rvotes` int(11) NOT NULL default '0',
+  `score` int(11) NOT NULL default '0',
+  `sc_up` int(11) NOT NULL default '0',
+  `sc_down` int(11) NOT NULL default '0',
+  `favorites` int(11) NOT NULL default '0',
+  `comments` int(11) NOT NULL default '0',
+  `reports` int(11) NOT NULL default '0',
+  `featured` int(11) NOT NULL default '0',
+  `allow_view_to` varchar(16) NOT NULL DEFAULT '3',
+  `cf` int(11) NOT NULL default '1',
+  `status` enum('active','hidden') NOT NULL DEFAULT 'active',
+  `status_admin` enum('active','hidden','pending') NOT NULL DEFAULT 'active',
+  `exif` text NOT NULL,
+  PRIMARY KEY (`id`),
+  FULLTEXT KEY `title_text` (`title`,`text`)
+);
+
+-- TABLE: storages & transcoders
+CREATE TABLE IF NOT EXISTS `bx_photos_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_photos_media_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_photos_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_photos_cmts_notes` (
+  `cmt_id` int(11) NOT NULL AUTO_INCREMENT,
+  `cmt_parent_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_vparent_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_object_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_author_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_level` int(11) NOT NULL DEFAULT '0',
+  `cmt_text` text NOT NULL,
+  `cmt_mood` tinyint(4) NOT NULL DEFAULT '0',
+  `cmt_rate` int(11) NOT NULL DEFAULT '0',
+  `cmt_rate_count` int(11) NOT NULL DEFAULT '0',
+  `cmt_time` int(11) unsigned NOT NULL DEFAULT '0',
+  `cmt_replies` int(11) NOT NULL DEFAULT '0',
+  `cmt_pinned` int(11) NOT NULL default '0',
+  PRIMARY KEY (`cmt_id`),
+  KEY `cmt_object_id` (`cmt_object_id`,`cmt_parent_id`),
+  FULLTEXT KEY `search_fields` (`cmt_text`)
+);
+
+-- TABLE: votes
+CREATE TABLE IF NOT EXISTS `bx_photos_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_photos_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_photos_svotes` (
+  `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_photos_svotes_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_photos_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_photos_reactions_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `author_nip` int(11) unsigned NOT NULL default '0',
+  `reaction` varchar(32) NOT NULL default '',
+  `value` tinyint(4) NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `vote` (`object_id`, `author_nip`)
+);
+
+-- TABLE: views
+CREATE TABLE `bx_photos_views_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `viewer_id` int(11) NOT NULL default '0',
+  `viewer_nip` int(11) unsigned NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `id` (`object_id`,`viewer_id`,`viewer_nip`)
+);
+
+-- TABLE: metas
+CREATE TABLE `bx_photos_meta_keywords` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(10) unsigned NOT NULL,
+  `keyword` varchar(255) NOT NULL,
+  PRIMARY KEY (`id`),
+  KEY `object_id` (`object_id`),
+  KEY `keyword` (`keyword`)
+);
+
+CREATE TABLE `bx_photos_meta_keywords_camera` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(10) unsigned NOT NULL,
+  `keyword` varchar(255) NOT NULL,
+  PRIMARY KEY (`id`),
+  KEY `object_id` (`object_id`),
+  KEY `keyword` (`keyword`)
+);
+
+CREATE TABLE `bx_photos_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_photos_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_photos_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_photos_reports_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `author_nip` int(11) unsigned NOT NULL default '0',
+  `type` varchar(32) NOT NULL default '',
+  `text` text NOT NULL default '',
+  `date` int(11) NOT NULL default '0',
+  `checked_by` int(11) NOT NULL default '0',
+  `status` tinyint(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `report` (`object_id`, `author_nip`)
+);
+
+-- TABLE: favorites
+CREATE TABLE `bx_photos_favorites_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `list_id` int(11) NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `id` (`object_id`,`author_id`)
+);
+
+CREATE TABLE `bx_photos_favorites_lists` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `title` varchar(255) NOT NULL,
+  `author_id` int(11) NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  `allow_view_favorite_list_to` varchar(16) NOT NULL DEFAULT '3',
+  PRIMARY KEY (`id`)
+);
+
+
+-- TABLE: scores
+CREATE TABLE IF NOT EXISTS `bx_photos_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_photos_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
+SET @sStorageEngine = (SELECT `value` FROM `sys_options` WHERE `name` = 'sys_storage_default');
+
+INSERT INTO `sys_objects_storage` (`object`, `engine`, `params`, `token_life`, `cache_control`, `levels`, `table_files`, `ext_mode`, `ext_allow`, `ext_deny`, `quota_size`, `current_size`, `quota_number`, `current_number`, `max_file_size`, `ts`) VALUES
+('bx_photos_photos', @sStorageEngine, '', 360, 2592000, 3, 'bx_photos_photos', 'allow-deny', '{image}', '', 0, 0, 0, 0, 0, 0),
+('bx_photos_media_resized', @sStorageEngine, '', 360, 2592000, 3, 'bx_photos_media_resized', 'allow-deny', '{imagevideo}', '', 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_photos_preview', 'bx_photos_media_resized', 'Storage', 'a:1:{s:6:"object";s:16:"bx_photos_photos";}', 'no', 1, 2592000, 0, '', ''),
+('bx_photos_gallery', 'bx_photos_media_resized', 'Storage', 'a:1:{s:6:"object";s:16:"bx_photos_photos";}', 'no', 1, 2592000, 0, '', ''),
+('bx_photos_cover', 'bx_photos_media_resized', 'Storage', 'a:1:{s:6:"object";s:16:"bx_photos_photos";}', 'no', 1, 2592000, 0, '', '');
+
+INSERT INTO `sys_transcoder_filters` (`transcoder_object`, `filter`, `filter_params`, `order`) VALUES 
+('bx_photos_preview', 'Resize', 'a:3:{s:1:"w";s:3:"300";s:1:"h";s:3:"200";s:11:"crop_resize";s:1:"1";}', '0'),
+('bx_photos_gallery', 'Resize', 'a:1:{s:1:"w";s:3:"500";}', '0'),
+('bx_photos_cover', 'Resize', 'a:1:{s:1:"w";s:4:"1200";}', '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_photos', 'bx_photos', '_bx_photos_form_entry', '', 'a:1:{s:7:"enctype";s:19:"multipart/form-data";}', 'bx_photos_entries', 'id', '', '', 'a:2:{i:0;s:9:"do_submit";i:1;s:10:"do_publish";}', '', 0, 1, 'BxPhotosFormEntry', 'modules/boonex/photos/classes/BxPhotosFormEntry.php'),
+('bx_photos_upload', 'bx_photos', '_bx_photos_form_upload', '', 'a:1:{s:7:"enctype";s:19:"multipart/form-data";}', 'bx_photos_entries', 'id', '', '', 'do_submit', '', 0, 1, 'BxPhotosFormUpload', 'modules/boonex/photos/classes/BxPhotosFormUpload.php');
+
+INSERT INTO `sys_form_displays`(`object`, `display_name`, `module`, `view_mode`, `title`) VALUES 
+('bx_photos_upload', 'bx_photos_entry_upload', 'bx_photos', 0, '_bx_photos_form_upload_display_upload'),
+('bx_photos', 'bx_photos_entry_delete', 'bx_photos', 0, '_bx_photos_form_entry_display_delete'),
+('bx_photos', 'bx_photos_entry_edit', 'bx_photos', 0, '_bx_photos_form_entry_display_edit'),
+('bx_photos', 'bx_photos_entry_view', 'bx_photos', 1, '_bx_photos_form_entry_display_view');
+
+INSERT INTO `sys_form_inputs`(`object`, `module`, `name`, `value`, `values`, `checked`, `type`, `caption_system`, `caption`, `info`, `required`, `collapsed`, `html`, `attrs`, `attrs_tr`, `attrs_wrapper`, `checker_func`, `checker_params`, `checker_error`, `db_pass`, `db_params`, `editable`, `deletable`) VALUES 
+('bx_photos', 'bx_photos', '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_photos', 'bx_photos', 'allow_view_to', '', '', 0, 'custom', '_bx_photos_form_entry_input_sys_allow_view_to', '_bx_photos_form_entry_input_allow_view_to', '', 1, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_photos', 'bx_photos', 'delete_confirm', 1, '', 0, 'checkbox', '_bx_photos_form_entry_input_sys_delete_confirm', '_bx_photos_form_entry_input_delete_confirm', '_bx_photos_form_entry_input_delete_confirm_info', 1, 0, 0, '', '', '', 'Avail', '', '_bx_photos_form_entry_input_delete_confirm_error', '', '', 1, 0),
+('bx_photos', 'bx_photos', 'do_publish', '_bx_photos_form_entry_input_do_publish', '', 0, 'submit', '_bx_photos_form_entry_input_sys_do_publish', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_photos', 'bx_photos', 'do_submit', '_bx_photos_form_entry_input_do_submit', '', 0, 'submit', '_bx_photos_form_entry_input_sys_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_photos', 'bx_photos', 'location', '', '', 0, 'location', '_sys_form_input_sys_location', '_sys_form_input_location', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_photos', 'bx_photos', 'pictures', 'a:1:{i:0;s:15:"bx_photos_html5";}', 'a:1:{s:15:"bx_photos_html5";s:25:"_sys_uploader_html5_title";}', 0, 'files', '_bx_photos_form_entry_input_sys_picture', '_bx_photos_form_entry_input_picture', '', 1, 0, 0, '', '', '', 'avail', '', '_bx_photos_form_entry_input_picture_err', '', '', 1, 0),
+('bx_photos', 'bx_photos', 'text', '', '', 0, 'textarea', '_bx_photos_form_entry_input_sys_text', '_bx_photos_form_entry_input_text', '', 0, 0, 3, '', '', '', '', '', '', 'XssHtml', '', 1, 0),
+('bx_photos', 'bx_photos', 'title', '', '', 0, 'text', '_bx_photos_form_entry_input_sys_title', '_bx_photos_form_entry_input_title', '', 1, 0, 0, '', '', '', 'Avail', '', '_bx_photos_form_entry_input_title_err', 'Xss', '', 1, 0),
+('bx_photos', 'bx_photos', 'cat', '', '#!bx_photos_cats', 0, 'select', '_bx_photos_form_entry_input_sys_cat', '_bx_photos_form_entry_input_cat', '', 1, 0, 0, '', '', '', 'avail', '', '_bx_photos_form_entry_input_cat_err', 'Xss', '', 1, 0),
+('bx_photos', 'bx_photos', 'added', '', '', 0, 'datetime', '_bx_photos_form_entry_input_sys_date_added', '_bx_photos_form_entry_input_date_added', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_photos', 'bx_photos', 'changed', '', '', 0, 'datetime', '_bx_photos_form_entry_input_sys_date_changed', '_bx_photos_form_entry_input_date_changed', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_photos', 'bx_photos', 'labels', '', '', 0, 'custom', '_sys_form_input_sys_labels', '_sys_form_input_labels', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+
+('bx_photos_upload', 'bx_photos', 'pictures', 'a:1:{i:0;s:15:"bx_photos_html5";}', 'a:1:{s:15:"bx_photos_html5";s:25:"_sys_uploader_html5_title";}', 0, 'files', '_bx_photos_form_entry_input_sys_pictures', '_bx_photos_form_entry_input_pictures', '', 1, 0, 0, '', '', '', 'avail', '', '_bx_photos_form_entry_input_pictures_err', '', '', 1, 0),
+('bx_photos_upload', 'bx_photos', 'cat', '', '#!bx_photos_cats', 0, 'select', '_bx_photos_form_entry_input_sys_cat', '_bx_photos_form_entry_input_cat', '', 1, 0, 0, '', '', '', 'avail', '', '_bx_photos_form_entry_input_cat_err', 'Xss', '', 1, 0),
+('bx_photos_upload', 'bx_photos', 'cf', '', '#!sys_content_filter', 0, 'select', '_sys_form_entry_input_sys_cf', '_sys_form_entry_input_cf', '', 0, 0, 0, '', '', '', '', '', '', 'Int', '', 1, 0),
+('bx_photos_upload', 'bx_photos', 'allow_view_to', '', '', 0, 'custom', '_bx_photos_form_entry_input_sys_allow_view_to', '_bx_photos_form_entry_input_allow_view_to', '', 1, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_photos_upload', 'bx_photos', 'do_submit', '_bx_photos_form_entry_input_do_submit', '', 0, 'submit', '_bx_photos_form_entry_input_sys_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_photos_upload', 'bx_photos', 'profile_id', '0', '', 0, 'hidden', '_bx_photos_form_entry_input_sys_profile_id', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0);
+
+INSERT INTO `sys_form_display_inputs`(`display_name`, `input_name`, `visible_for_levels`, `active`, `order`) VALUES 
+('bx_photos_entry_upload', 'profile_id', 2147483647, 1, 1),
+('bx_photos_entry_upload', 'pictures', 2147483647, 1, 2),
+('bx_photos_entry_upload', 'cat', 2147483647, 1, 3),
+('bx_photos_entry_upload', 'allow_view_to', 2147483647, 1, 4),
+('bx_photos_entry_upload', 'cf', 2147483647, 1, 5),
+('bx_photos_entry_upload', 'do_submit', 2147483647, 1, 6),
+
+('bx_photos_entry_delete', 'delete_confirm', 2147483647, 1, 1),
+('bx_photos_entry_delete', 'do_submit', 2147483647, 1, 2),
+
+('bx_photos_entry_edit', 'title', 2147483647, 1, 1),
+('bx_photos_entry_edit', 'cat', 2147483647, 1, 2),
+('bx_photos_entry_edit', 'text', 2147483647, 1, 3),
+('bx_photos_entry_edit', 'pictures', 2147483647, 1, 4),
+('bx_photos_entry_edit', 'allow_view_to', 2147483647, 1, 5),
+('bx_photos_entry_edit', 'cf', 2147483647, 1, 6),
+('bx_photos_entry_edit', 'location', 2147483647, 1, 7),
+('bx_photos_entry_edit', 'do_submit', 2147483647, 1, 8),
+
+('bx_photos_entry_view', 'cat', 2147483647, 1, 2),
+('bx_photos_entry_view', 'added', 2147483647, 1, 3),
+('bx_photos_entry_view', 'changed', 2147483647, 1, 4);
+
+-- PRE-VALUES
+INSERT INTO `sys_form_pre_lists`(`key`, `title`, `module`, `use_for_sets`) VALUES
+('bx_photos_cats', '_bx_photos_pre_lists_cats', 'bx_photos', '0');
+
+INSERT INTO `sys_form_pre_values`(`Key`, `Value`, `Order`, `LKey`, `LKey2`) VALUES
+('bx_photos_cats', '', 0, '_sys_please_select', ''),
+('bx_photos_cats', '1', 1, '_bx_photos_cat_animals_and_pets', ''),
+('bx_photos_cats', '2', 2, '_bx_photos_cat_education', ''),
+('bx_photos_cats', '3', 3, '_bx_photos_cat_entertainment', ''),
+('bx_photos_cats', '4', 4, '_bx_photos_cat_film_and_animation', ''),
+('bx_photos_cats', '5', 5, '_bx_photos_cat_music', ''),
+('bx_photos_cats', '6', 6, '_bx_photos_cat_news', ''),
+('bx_photos_cats', '7', 7, '_bx_photos_cat_people_and_blogs', ''),
+('bx_photos_cats', '8', 8, '_bx_photos_cat_sports', ''),
+('bx_photos_cats', '9', 9, '_bx_photos_cat_travel', '');
+
+
+-- 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_photos', 'bx_photos', 'bx_photos_cmts', 1, 5000, 1000, 3, 5, 3, 'tail', 1, 'bottom', 1, 1, 1, -3, 1, 'cmt', 'page.php?i=view-photo&id={object_id}', '', 'bx_photos_entries', 'id', 'author', 'title', 'comments', '', ''),
+('bx_photos_notes', 'bx_photos', 'bx_photos_cmts_notes', 1, 5000, 1000, 0, 5, 3, 'tail', 1, 'bottom', 1, 1, 1, -3, 1, 'cmt', 'page.php?i=view-photo&id={object_id}', '', 'bx_photos_entries', 'id', 'author', 'title', '', 'BxTemplCmtsNotes', '');
+
+
+-- VOTES
+INSERT INTO `sys_objects_vote` (`Name`, `Module`, `TableMain`, `TableTrack`, `PostTimeout`, `MinValue`, `MaxValue`, `IsUndo`, `IsOn`, `TriggerTable`, `TriggerFieldId`, `TriggerFieldAuthor`, `TriggerFieldRate`, `TriggerFieldRateCount`, `ClassName`, `ClassFile`) VALUES 
+('bx_photos', 'bx_photos', 'bx_photos_votes', 'bx_photos_votes_track', '604800', '1', '1', '0', '1', 'bx_photos_entries', 'id', 'author', 'rate', 'votes', '', ''),
+('bx_photos_stars', 'bx_photos', 'bx_photos_svotes', 'bx_photos_svotes_track', '604800', '1', '5', '0', '1', 'bx_photos_entries', 'id', 'author', 'srate', 'svotes', 'BxPhotosVoteStars', 'modules/boonex/photos/classes/BxPhotosVoteStars.php'),
+('bx_photos_reactions', 'bx_photos', 'bx_photos_reactions', 'bx_photos_reactions_track', '604800', '1', '1', '1', '1', 'bx_photos_entries', 'id', 'author', 'rrate', 'rvotes', 'BxTemplVoteReactions', '');
+
+
+-- SCORES
+INSERT INTO `sys_objects_score` (`name`, `module`, `table_main`, `table_track`, `post_timeout`, `is_on`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_score`, `trigger_field_cup`, `trigger_field_cdown`, `class_name`, `class_file`) VALUES 
+('bx_photos', 'bx_photos', 'bx_photos_scores', 'bx_photos_scores_track', '604800', '0', 'bx_photos_entries', 'id', 'author', 'score', 'sc_up', 'sc_down', '', '');
+
+
+-- REPORTS
+INSERT INTO `sys_objects_report` (`name`, `module`, `table_main`, `table_track`, `is_on`, `base_url`, `object_comment`,  `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_count`, `class_name`, `class_file`) VALUES 
+('bx_photos', 'bx_photos', 'bx_photos_reports', 'bx_photos_reports_track', '1', 'page.php?i=view-photo&id={object_id}', 'bx_photos_notes', 'bx_photos_entries', 'id', 'author', 'reports', '', '');
+
+
+-- 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_photos', 'bx_photos', 'bx_photos_views_track', '86400', '1', 'bx_photos_entries', 'id', 'author', 'views', '', '');
+
+
+-- FAVORITES
+INSERT INTO `sys_objects_favorite` (`name`, `table_track`, `table_lists`, `is_on`, `is_undo`, `is_public`, `base_url`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_count`, `class_name`, `class_file`) VALUES 
+('bx_photos', 'bx_photos_favorites_track', 'bx_photos_favorites_lists', '1', '1', '1', 'page.php?i=view-photo&id={object_id}', 'bx_photos_entries', 'id', 'author', 'favorites', '', '');
+
+
+-- FEATURED
+INSERT INTO `sys_objects_feature` (`name`, `module`, `is_on`, `is_undo`, `base_url`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_flag`, `class_name`, `class_file`) VALUES 
+('bx_photos', 'bx_photos', '1', '1', 'page.php?i=view-photo&id={object_id}', 'bx_photos_entries', 'id', 'author', 'featured', '', '');
+
+
+-- CONTENT INFO
+INSERT INTO `sys_objects_content_info` (`name`, `title`, `alert_unit`, `alert_action_add`, `alert_action_update`, `alert_action_delete`, `class_name`, `class_file`) VALUES
+('bx_photos', '_bx_photos', 'bx_photos', 'added', 'edited', 'deleted', '', ''),
+('bx_photos_cmts', '_bx_photos_cmts', 'bx_photos', 'commentPost', 'commentUpdated', 'commentRemoved', 'BxDolContentInfoCmts', '');
+
+INSERT INTO `sys_content_info_grids` (`object`, `grid_object`, `grid_field_id`, `condition`, `selection`) VALUES
+('bx_photos', 'bx_photos_administration', 'id', '', ''),
+('bx_photos', 'bx_photos_common', 'id', '', '');
+
+
+-- SEARCH EXTENDED
+INSERT INTO `sys_objects_search_extended` (`object`, `object_content_info`, `module`, `title`, `active`, `class_name`, `class_file`) VALUES
+('bx_photos', 'bx_photos', 'bx_photos', '_bx_photos_search_extended', 1, '', ''),
+('bx_photos_cmts', 'bx_photos_cmts', 'bx_photos', '_bx_photos_search_extended_cmts', 1, 'BxTemplSearchExtendedCmts', '');
+
+
+-- STUDIO: page & widget
+INSERT INTO `sys_std_pages`(`index`, `name`, `header`, `caption`, `icon`) VALUES
+(3, 'bx_photos', '_bx_photos', '_bx_photos', 'bx_photos@modules/boonex/photos/|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_photos', 'content', '{url_studio}module.php?name=bx_photos', '', 'bx_photos@modules/boonex/photos/|std-icon.svg', '_bx_photos', '', '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));

+ 29 - 0
modules/boonex/photos/updates/13.0.6_13.0.7/source/template/form_ghost_template.html

@@ -0,0 +1,29 @@
+<div id="bx-uploader-file-{storage_object}-{file_id}" class="bx-uploader-ghost flex items-start mt-2">
+    <div class="bx-uploader-ghost-cnt">
+        <div class="bx-base-general-icon-wrapper">
+            <input type="hidden" name="__name__[]" value="{file_id}" />
+            <img src="{file_icon}" class="bx-def-round-corners bx-base-general-icon bx-base-general-icon-{file_id}" />
+        </div>
+        <span class="bx-base-general-uploader-ghost">
+            <a class="bx-btn bx-btn-small mr-2" href="javascript:void(0);" title="<bx_text:_sys_txt_form_entry_input_picture_delete />" onclick="bx_base_general_delete_ghost('{file_id}', '{file_url}', '{file_icon}', ['__editor_id__'], {js_instance_name});">
+                <bx_image_auto:times />
+            </a>
+            <a class="bx-btn bx-btn-small mr-2" href="javascript:void(0);" title="<bx_text:_sys_txt_form_entry_input_picture_copy />" onclick="bx_copy_to_clipboard('{file_url}');">
+                <bx_image_auto:copy />
+            </a>
+            <bx_if:set_thumb>
+                <input type="hidden" name="__name_thumb__[]" value="{file_id}" />
+            </bx_if:set_thumb>
+        </span>
+    </div>
+</div>
+<script>
+    $('#bx-base-general-intert-to-post-link-{file_id}').show();
+
+    $('#bx-uploader-file-{storage_object}-{file_id} .bx-base-general-use-as-thumb input[value="__thumb_id__"]').attr('checked', true);
+
+    // disable images drag&drop, because resized images address can be reset after some time
+    $(".bx-base-general-icon-{file_id}").bind('dragstart', function(){
+        return false; 
+    });
+</script>

+ 19 - 0
modules/boonex/photos/updates/13.0.6_13.0.7/source/template/form_ghost_template_upload.html

@@ -0,0 +1,19 @@
+<div id="bx-uploader-file-{storage_object}-{file_id}" class="bx-uploader-ghost flex items-start mt-2">
+    <div class="bx-uploader-ghost-cnt">
+        <div class="bx-base-general-icon-wrapper">
+            <input type="hidden" name="__name__[]" value="{file_id}" />
+            <img src="{file_icon}" class="bx-def-round-corners bx-base-general-icon bx-base-general-icon-{file_id}" />
+        </div>
+        <span class="bx-base-general-uploader-ghost">
+            <a class="bx-btn bx-btn-small bx-def-margin-sec-right" title="<bx_text:_sys_txt_form_entry_input_picture_delete />" href="javascript:void(0);" onclick="bx_base_general_delete_ghost('{file_id}', '{file_url}', '{file_icon}', ['__editor_id__'], {js_instance_name});">
+                <bx_image_auto:times />
+            </a>
+            <a class="bx-btn bx-btn-small mr-2" href="javascript:void(0);" title="<bx_text:_sys_txt_form_entry_input_picture_copy />" onclick="bx_copy_to_clipboard('{file_url}');">
+                <bx_image_auto:copy />
+            </a>
+        </span>
+    </div>
+    <div class="bx-form-input-wrapper bx-form-input-wrapper-text w-full">
+        <input placeholder="<bx_text:_bx_photos_form_entry_input_title />" class="bx-def-font-inputs bx-form-input-text block w-full py-2 px-3 border border-gray-300 dark:border-gray-700 rounded-md shadow-sm bg-white dark:bg-gray-900 placeholder-gray-500 focus:outline-none focus:placeholder-gray-400 focus:ring-2 focus:text-gray-900 dark:focus:text-gray-100 focus:ring-blue-500 focus:border-opacity-70 focus:ring-opacity-20 focus:border-blue-500 text-sm text-gray-700 dark:text-gray-300 appearance-none" type="text" value="" name="title-{file_id}" />
+    </div>
+</div>

+ 51 - 0
modules/boonex/polls/updates/13.0.5_13.0.6/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' => 'Polls',
+    'version_from' => '13.0.5',
+    'version_to' => '13.0.6',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '13.1.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/polls/updates/update_13.0.5_13.0.6/',
+    'home_uri' => 'polls_update_1305_1306',
+
+    'module_dir' => 'boonex/polls/',
+    'module_uri' => 'polls',
+
+    'db_prefix' => 'bx_polls_',
+    'class_prefix' => 'BxPolls',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_files' => 1,
+        'update_languages' => 0,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Polls',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

+ 13 - 0
modules/boonex/polls/updates/13.0.5_13.0.6/install/installer.php

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

+ 10 - 0
modules/boonex/polls/updates/13.0.5_13.0.6/install/sql/install.sql

@@ -0,0 +1,10 @@
+-- STORAGES & TRANSCODERS
+UPDATE `sys_transcoder_filters` SET `filter_params`='a:1:{s:1:"w";s:4:"1200";}' WHERE `transcoder_object`='bx_polls_cover';
+
+
+-- VOTES
+UPDATE `sys_objects_vote` SET `Module`='bx_polls' WHERE `Name` IN ('bx_polls', 'bx_polls_subentries', 'bx_polls_reactions');
+
+
+-- VIEWS
+UPDATE `sys_objects_view` SET `module`='bx_polls' WHERE `name`='bx_polls';

+ 136 - 0
modules/boonex/polls/updates/13.0.5_13.0.6/source/install/config.php

@@ -0,0 +1,136 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Polls Polls
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_polls',
+    'title' => 'Polls',
+    'note' => 'Basic poll module.',
+    'version' => '13.0.6',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '13.1.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/polls/',
+    'home_uri' => 'polls',
+
+    'db_prefix' => 'bx_polls_',
+    'class_prefix' => 'BxPolls',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Polls',
+
+    /**
+     * List of page triggers.
+     */
+    'page_triggers' => array (
+    	'trigger_page_profile_view_entry',
+    ),
+    
+    /**
+     * Menu triggers.
+     */
+    'menu_triggers' => array(
+    	'trigger_profile_view_submenu',
+        'trigger_group_view_submenu'
+    ),
+
+	/**
+     * Storage objects to automatically delete files from upon module uninstallation.
+     * Note. Don't add storage objects used in transcoder objects.
+     */
+    'storages' => array(
+    	'bx_polls_files'
+    ),
+
+    /**
+     * Transcoders.
+     */
+    'transcoders' => array(
+		'bx_polls_preview',
+        'bx_polls_gallery',
+        'bx_polls_cover'
+    ),
+
+	/**
+     * Extended Search Forms.
+     */
+    'esearches' => array(
+        'bx_polls',
+    	'bx_polls_cmts',
+    ),
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'uninstall' => array (
+    	'process_esearches' => 1,
+        'execute_sql' => 1,
+        'update_languages' => 1,
+    	'update_relations' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'enable' => array(
+        'execute_sql' => 1,
+    	'update_relations' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'enable_success' => array(
+        'process_menu_triggers' => 1,
+        'process_page_triggers' => 1,
+    	'process_esearches' => 1,
+    	'register_transcoders' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable' => array (
+        'execute_sql' => 1,
+    	'update_relations' => 1,
+    	'unregister_transcoders' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable_failed' => array (
+    	'register_transcoders' => 1,
+    	'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Dependencies Section
+     */
+    'dependencies' => array(),
+
+    /**
+     * Relations Section
+     */
+    'relations' => array(
+    	'bx_timeline',
+    	'bx_notifications'
+    ),
+
+);
+
+/** @} */

+ 459 - 0
modules/boonex/polls/updates/13.0.5_13.0.6/source/install/sql/install.sql

@@ -0,0 +1,459 @@
+-- TABLE: entries
+CREATE TABLE IF NOT EXISTS `bx_polls_entries` (
+  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+  `author` int(10) unsigned NOT NULL,
+  `added` int(11) NOT NULL,
+  `changed` int(11) NOT NULL,
+  `thumb` int(11) NOT NULL,
+  `text` text NOT NULL,
+  `cat` int(11) NOT NULL,
+  `labels` text NOT NULL,
+  `location` text NOT NULL,
+  `views` int(11) NOT NULL default '0',
+  `rate` float NOT NULL default '0',
+  `votes` int(11) NOT NULL default '0',
+  `rrate` float NOT NULL default '0',
+  `rvotes` int(11) NOT NULL default '0',
+  `score` int(11) NOT NULL default '0',
+  `sc_up` int(11) NOT NULL default '0',
+  `sc_down` int(11) NOT NULL default '0',
+  `favorites` int(11) NOT NULL default '0',
+  `comments` int(11) NOT NULL default '0',
+  `reports` int(11) NOT NULL default '0',
+  `featured` int(11) NOT NULL default '0',
+  `cf` int(11) NOT NULL default '1',
+  `allow_view_to` varchar(16) NOT NULL DEFAULT '3',
+  `anonymous` tinyint(4) NOT NULL DEFAULT '0',
+  `hidden_results` tinyint(4) NOT NULL DEFAULT '0',
+  `status` enum('active','hidden') NOT NULL DEFAULT 'active',
+  `status_admin` enum('active','hidden','pending') NOT NULL DEFAULT 'active',
+  PRIMARY KEY (`id`),
+  FULLTEXT KEY `search_fields` (`text`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_polls_subentries` (
+  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+  `entry_id` int(11) unsigned NOT NULL default '0',
+  `title` varchar(255) NOT NULL,
+  `rate` float NOT NULL default '0',
+  `votes` int(11) NOT NULL default '0',
+  `order` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  FULLTEXT KEY `title` (`title`)
+);
+
+-- TABLE: storages & transcoders
+CREATE TABLE IF NOT EXISTS `bx_polls_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_polls_photos_resized` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `profile_id` int(10) unsigned NOT NULL,
+  `remote_id` varchar(128) NOT NULL,
+  `path` varchar(255) NOT NULL,
+  `file_name` varchar(255) NOT NULL,
+  `mime_type` varchar(128) NOT NULL,
+  `ext` varchar(32) NOT NULL,
+  `size` bigint(20) NOT NULL,
+  `added` int(11) NOT NULL,
+  `modified` int(11) NOT NULL,
+  `private` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `remote_id` (`remote_id`)
+);
+
+-- TABLE: comments
+CREATE TABLE IF NOT EXISTS `bx_polls_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_polls_cmts_notes` (
+  `cmt_id` int(11) NOT NULL AUTO_INCREMENT,
+  `cmt_parent_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_vparent_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_object_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_author_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_level` int(11) NOT NULL DEFAULT '0',
+  `cmt_text` text NOT NULL,
+  `cmt_mood` tinyint(4) NOT NULL DEFAULT '0',
+  `cmt_rate` int(11) NOT NULL DEFAULT '0',
+  `cmt_rate_count` int(11) NOT NULL DEFAULT '0',
+  `cmt_time` int(11) unsigned NOT NULL DEFAULT '0',
+  `cmt_replies` int(11) NOT NULL DEFAULT '0',
+  `cmt_pinned` int(11) NOT NULL default '0',
+  PRIMARY KEY (`cmt_id`),
+  KEY `cmt_object_id` (`cmt_object_id`,`cmt_parent_id`),
+  FULLTEXT KEY `search_fields` (`cmt_text`)
+);
+
+-- TABLE: votes
+CREATE TABLE IF NOT EXISTS `bx_polls_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_polls_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_polls_votes_subentries` (
+  `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_polls_votes_subentries_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_polls_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_polls_reactions_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `author_nip` int(11) unsigned NOT NULL default '0',
+  `reaction` varchar(32) NOT NULL default '',
+  `value` tinyint(4) NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `vote` (`object_id`, `author_nip`)
+);
+
+-- TABLE: views
+CREATE TABLE `bx_polls_views_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `viewer_id` int(11) NOT NULL default '0',
+  `viewer_nip` int(11) unsigned NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `id` (`object_id`,`viewer_id`,`viewer_nip`)
+);
+
+-- TABLE: metas
+CREATE TABLE `bx_polls_meta_keywords` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(10) unsigned NOT NULL,
+  `keyword` varchar(255) NOT NULL,
+  PRIMARY KEY (`id`),
+  KEY `object_id` (`object_id`),
+  KEY `keyword` (`keyword`)
+);
+
+CREATE TABLE `bx_polls_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_polls_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_polls_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_polls_reports_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `author_nip` int(11) unsigned NOT NULL default '0',
+  `type` varchar(32) NOT NULL default '',
+  `text` text NOT NULL default '',
+  `date` int(11) NOT NULL default '0',
+  `checked_by` int(11) NOT NULL default '0',
+  `status` tinyint(11) NOT NULL default '0',	
+  PRIMARY KEY (`id`),
+  KEY `report` (`object_id`, `author_nip`)
+);
+
+-- TABLE: favorites
+CREATE TABLE `bx_polls_favorites_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `list_id` int(11) NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `id` (`object_id`,`author_id`)
+);
+
+CREATE TABLE `bx_polls_favorites_lists` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `title` varchar(255) NOT NULL,
+  `author_id` int(11) NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  `allow_view_favorite_list_to` varchar(16) NOT NULL DEFAULT '3',
+  PRIMARY KEY (`id`)
+);
+
+-- TABLE: scores
+CREATE TABLE IF NOT EXISTS `bx_polls_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_polls_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
+SET @sStorageEngine = (SELECT `value` FROM `sys_options` WHERE `name` = 'sys_storage_default');
+
+INSERT INTO `sys_objects_storage` (`object`, `engine`, `params`, `token_life`, `cache_control`, `levels`, `table_files`, `ext_mode`, `ext_allow`, `ext_deny`, `quota_size`, `current_size`, `quota_number`, `current_number`, `max_file_size`, `ts`) VALUES
+('bx_polls_files', @sStorageEngine, '', 360, 2592000, 3, 'bx_polls_files', 'allow-deny', '{image}', '', 0, 0, 0, 0, 0, 0),
+('bx_polls_photos_resized', @sStorageEngine, '', 360, 2592000, 3, 'bx_polls_photos_resized', 'allow-deny', '{image}', '', 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_polls_preview', 'bx_polls_photos_resized', 'Storage', 'a:1:{s:6:"object";s:14:"bx_polls_files";}', 'no', '1', '2592000', '0'),
+('bx_polls_gallery', 'bx_polls_photos_resized', 'Storage', 'a:1:{s:6:"object";s:14:"bx_polls_files";}', 'no', '1', '2592000', '0'),
+('bx_polls_cover', 'bx_polls_photos_resized', 'Storage', 'a:1:{s:6:"object";s:14:"bx_polls_files";}', 'no', '1', '2592000', '0');
+
+INSERT INTO `sys_transcoder_filters` (`transcoder_object`, `filter`, `filter_params`, `order`) VALUES 
+('bx_polls_preview', 'Resize', 'a:3:{s:1:"w";s:3:"300";s:1:"h";s:3:"200";s:11:"crop_resize";s:1:"1";}', '0'),
+('bx_polls_gallery', 'Resize', 'a:1:{s:1:"w";s:3:"500";}', '0'),
+('bx_polls_cover', 'Resize', 'a:1:{s:1:"w";s:4:"1200";}', '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_polls', 'bx_polls', '_bx_polls_form_entry', '', 'a:1:{s:7:"enctype";s:19:"multipart/form-data";}', 'bx_polls_entries', 'id', '', '', 'a:2:{i:0;s:9:"do_submit";i:1;s:10:"do_publish";}', 'a:1:{s:14:"checker_helper";s:29:"BxPollsFormEntryCheckerHelper";}', 0, 1, 'BxPollsFormEntry', 'modules/boonex/polls/classes/BxPollsFormEntry.php');
+
+INSERT INTO `sys_form_displays`(`object`, `display_name`, `module`, `view_mode`, `title`) VALUES 
+('bx_polls', 'bx_polls_entry_add', 'bx_polls', 0, '_bx_polls_form_entry_display_add'),
+('bx_polls', 'bx_polls_entry_delete', 'bx_polls', 0, '_bx_polls_form_entry_display_delete'),
+('bx_polls', 'bx_polls_entry_edit', 'bx_polls', 0, '_bx_polls_form_entry_display_edit'),
+('bx_polls', 'bx_polls_entry_view', 'bx_polls', 1, '_bx_polls_form_entry_display_view');
+
+INSERT INTO `sys_form_inputs`(`object`, `module`, `name`, `value`, `values`, `checked`, `type`, `caption_system`, `caption`, `info`, `required`, `collapsed`, `html`, `attrs`, `attrs_tr`, `attrs_wrapper`, `checker_func`, `checker_params`, `checker_error`, `db_pass`, `db_params`, `editable`, `deletable`) VALUES 
+('bx_polls', 'bx_polls', '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_polls', 'bx_polls', 'allow_view_to', '', '', 0, 'custom', '_bx_polls_form_entry_input_sys_allow_view_to', '_bx_polls_form_entry_input_allow_view_to', '', 1, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_polls', 'bx_polls', 'delete_confirm', 1, '', 0, 'checkbox', '_bx_polls_form_entry_input_sys_delete_confirm', '_bx_polls_form_entry_input_delete_confirm', '_bx_polls_form_entry_input_delete_confirm_info', 1, 0, 0, '', '', '', 'Avail', '', '_bx_polls_form_entry_input_delete_confirm_error', '', '', 1, 0),
+('bx_polls', 'bx_polls', 'do_publish', '_bx_polls_form_entry_input_do_publish', '', 0, 'submit', '_bx_polls_form_entry_input_sys_do_publish', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_polls', 'bx_polls', 'do_submit', '_bx_polls_form_entry_input_do_submit', '', 0, 'submit', '_bx_polls_form_entry_input_sys_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_polls', 'bx_polls', 'location', '', '', 0, 'location', '_sys_form_input_sys_location', '_sys_form_input_location', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_polls', 'bx_polls', 'pictures', 'a:1:{i:0;s:9:"sys_html5";}', 'a:1:{s:9:"sys_html5";s:25:"_sys_uploader_html5_title";}', 0, 'files', '_bx_polls_form_entry_input_sys_pictures', '_bx_polls_form_entry_input_pictures', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_polls', 'bx_polls', 'text', '', '', 0, 'textarea', '_bx_polls_form_entry_input_sys_text', '_bx_polls_form_entry_input_text', '', 1, 0, 2, '', '', '', 'Avail', '', '_bx_polls_form_entry_input_text_err', 'Xss', '', 1, 0),
+('bx_polls', 'bx_polls', 'subentries', '', '', 0, 'custom', '_bx_polls_form_entry_input_sys_subentries', '_bx_polls_form_entry_input_subentries', '', 1, 0, 0, '', '', '', 'AvailSubentries', '', '_bx_polls_form_entry_input_subentries_err', '', '', 1, 0),
+('bx_polls', 'bx_polls', 'cat', '', '#!bx_polls_cats', 0, 'select', '_bx_polls_form_entry_input_sys_cat', '_bx_polls_form_entry_input_cat', '', 1, 0, 0, '', '', '', 'avail', '', '_bx_polls_form_entry_input_cat_err', 'Xss', '', 1, 0),
+('bx_polls', 'bx_polls', 'anonymous', 1, '', 1, 'switcher', '_bx_polls_form_profile_input_sys_anonymous', '_bx_polls_form_profile_input_anonymous', '_bx_polls_form_profile_input_anonymous_info', 0, 0, 0, '', '', '', '', '', '', 'Xss', '', 1, 0),
+('bx_polls', 'bx_polls', 'hidden_results', 1, '', 0, 'switcher', '_bx_polls_form_profile_input_sys_hidden_results', '_bx_polls_form_profile_input_hidden_results', '', 0, 0, 0, '', '', '', '', '', '', 'Xss', '', 1, 0),
+('bx_polls', 'bx_polls', 'added', '', '', 0, 'datetime', '_bx_polls_form_entry_input_sys_date_added', '_bx_polls_form_entry_input_date_added', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_polls', 'bx_polls', 'changed', '', '', 0, 'datetime', '_bx_polls_form_entry_input_sys_date_changed', '_bx_polls_form_entry_input_date_changed', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_polls', 'bx_polls', 'labels', '', '', 0, 'custom', '_sys_form_input_sys_labels', '_sys_form_input_labels', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0);
+
+
+INSERT INTO `sys_form_display_inputs`(`display_name`, `input_name`, `visible_for_levels`, `active`, `order`) VALUES 
+('bx_polls_entry_add', 'cat', 2147483647, 1, 1),
+('bx_polls_entry_add', 'text', 2147483647, 1, 2),
+('bx_polls_entry_add', 'subentries', 2147483647, 1, 3),
+('bx_polls_entry_add', 'pictures', 2147483647, 1, 4),
+('bx_polls_entry_add', 'allow_view_to', 2147483647, 1, 5),
+('bx_polls_entry_add', 'cf', 2147483647, 1, 6),
+('bx_polls_entry_add', 'anonymous', 2147483647, 1, 7),
+('bx_polls_entry_add', 'hidden_results', 2147483647, 1, 8),
+('bx_polls_entry_add', 'location', 2147483647, 1, 9),
+('bx_polls_entry_add', 'do_publish', 2147483647, 1, 10),
+
+('bx_polls_entry_delete', 'delete_confirm', 2147483647, 1, 1),
+('bx_polls_entry_delete', 'do_submit', 2147483647, 1, 2),
+
+('bx_polls_entry_edit', 'cat', 2147483647, 1, 1),
+('bx_polls_entry_edit', 'text', 2147483647, 1, 2),
+('bx_polls_entry_edit', 'subentries', 2147483647, 1, 3),
+('bx_polls_entry_edit', 'pictures', 2147483647, 1, 4),
+('bx_polls_entry_edit', 'allow_view_to', 2147483647, 1, 5),
+('bx_polls_entry_edit', 'cf', 2147483647, 1, 6),
+('bx_polls_entry_edit', 'hidden_results', 2147483647, 1, 7),
+('bx_polls_entry_edit', 'location', 2147483647, 1, 8),
+('bx_polls_entry_edit', 'do_submit', 2147483647, 1, 9),
+
+('bx_polls_entry_view', 'cat', 2147483647, 1, 1),
+('bx_polls_entry_view', 'added', 2147483647, 1, 2),
+('bx_polls_entry_view', 'changed', 2147483647, 1, 3);
+
+
+-- PRE-VALUES
+INSERT INTO `sys_form_pre_lists`(`key`, `title`, `module`, `use_for_sets`) VALUES
+('bx_polls_cats', '_bx_polls_pre_lists_cats', 'bx_polls', '0');
+
+INSERT INTO `sys_form_pre_values`(`Key`, `Value`, `Order`, `LKey`, `LKey2`) VALUES
+('bx_polls_cats', '', 0, '_sys_please_select', ''),
+('bx_polls_cats', '1', 1, '_bx_polls_cat_beauty_and_style', ''),
+('bx_polls_cats', '2', 2, '_bx_polls_cat_business_and_money', ''),
+('bx_polls_cats', '3', 3, '_bx_polls_cat_cars_and_transportation', ''),
+('bx_polls_cats', '4', 4, '_bx_polls_cat_computers_and_internet', ''),
+('bx_polls_cats', '5', 5, '_bx_polls_cat_food_and_dining', ''),
+('bx_polls_cats', '6', 6, '_bx_polls_cat_education', ''),
+('bx_polls_cats', '7', 7, '_bx_polls_cat_electronics', ''),
+('bx_polls_cats', '8', 8, '_bx_polls_cat_entertainment', ''),
+('bx_polls_cats', '9', 9, '_bx_polls_cat_family_and_relationships', ''),
+('bx_polls_cats', '10', 10, '_bx_polls_cat_games', ''),
+('bx_polls_cats', '11', 11, '_bx_polls_cat_health_and_fitness', ''),
+('bx_polls_cats', '12', 12, '_bx_polls_cat_home_and_garden', ''),
+('bx_polls_cats', '13', 13, '_bx_polls_cat_news_and_events', ''),
+('bx_polls_cats', '14', 14, '_bx_polls_cat_pets', ''),
+('bx_polls_cats', '15', 15, '_bx_polls_cat_politics_and_government', ''),
+('bx_polls_cats', '16', 16, '_bx_polls_cat_pregnancy_and_parenting', ''),
+('bx_polls_cats', '17', 17, '_bx_polls_cat_sports', ''),
+('bx_polls_cats', '18', 18, '_bx_polls_cat_misc', ''),
+('bx_polls_cats', '19', 19, '_bx_polls_cat_would_you_rather', ''),
+('bx_polls_cats', '20', 20, '_bx_polls_cat_yes_or_no', '');
+
+
+-- 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_polls', 'bx_polls', 'bx_polls_cmts', 1, 5000, 1000, 3, 5, 3, 'tail', 1, 'bottom', 1, 1, 1, -3, 1, 'cmt', 'page.php?i=view-poll&id={object_id}', '', 'bx_polls_entries', 'id', 'author', 'text', 'comments', '', ''),
+('bx_polls_notes', 'bx_polls', 'bx_polls_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_polls_entries', 'id', 'author', 'text', '', 'BxTemplCmtsNotes', '');
+
+
+-- VOTES
+INSERT INTO `sys_objects_vote` (`Name`, `Module`, `TableMain`, `TableTrack`, `PostTimeout`, `MinValue`, `MaxValue`, `IsUndo`, `IsOn`, `TriggerTable`, `TriggerFieldId`, `TriggerFieldAuthor`, `TriggerFieldRate`, `TriggerFieldRateCount`, `ClassName`, `ClassFile`) VALUES 
+('bx_polls', 'bx_polls', 'bx_polls_votes', 'bx_polls_votes_track', '604800', '1', '1', '0', '1', 'bx_polls_entries', 'id', 'author', 'rate', 'votes', '', ''),
+('bx_polls_subentries', 'bx_polls', 'bx_polls_votes_subentries', 'bx_polls_votes_subentries_track', '604800', '1', '1', '0', '1', 'bx_polls_subentries', 'id', 'author', 'rate', 'votes', 'BxPollsVoteSubentries', 'modules/boonex/polls/classes/BxPollsVoteSubentries.php'),
+
+('bx_polls_reactions', 'bx_polls', 'bx_polls_reactions', 'bx_polls_reactions_track', '604800', '1', '1', '1', '1', 'bx_polls_entries', 'id', 'author', 'rrate', 'rvotes', 'BxTemplVoteReactions', '');
+
+
+-- SCORES
+INSERT INTO `sys_objects_score` (`name`, `module`, `table_main`, `table_track`, `post_timeout`, `is_on`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_score`, `trigger_field_cup`, `trigger_field_cdown`, `class_name`, `class_file`) VALUES 
+('bx_polls', 'bx_polls', 'bx_polls_scores', 'bx_polls_scores_track', '604800', '0', 'bx_polls_entries', 'id', 'author', 'score', 'sc_up', 'sc_down', '', '');
+
+
+-- REPORTS
+INSERT INTO `sys_objects_report` (`name`, `module`, `table_main`, `table_track`, `is_on`, `base_url`, `object_comment`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_count`, `class_name`, `class_file`) VALUES 
+('bx_polls', 'bx_polls', 'bx_polls_reports', 'bx_polls_reports_track', '1', 'page.php?i=view-poll&id={object_id}', 'bx_polls_notes', 'bx_polls_entries', 'id', 'author', 'reports', '', '');
+
+
+-- 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_polls', 'bx_polls', 'bx_polls_views_track', '86400', '1', 'bx_polls_entries', 'id', 'author', 'views', '', '');
+
+
+-- FAFORITES
+INSERT INTO `sys_objects_favorite` (`name`, `table_track`, `table_lists`, `is_on`, `is_undo`, `is_public`, `base_url`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_count`, `class_name`, `class_file`) VALUES 
+('bx_polls', 'bx_polls_favorites_track', 'bx_polls_favorites_lists', '1', '1', '1', 'page.php?i=view-poll&id={object_id}', 'bx_polls_entries', 'id', 'author', 'favorites', '', '');
+
+
+-- FEATURED
+INSERT INTO `sys_objects_feature` (`name`, `module`, `is_on`, `is_undo`, `base_url`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_flag`, `class_name`, `class_file`) VALUES 
+('bx_polls', 'bx_polls', '1', '1', 'page.php?i=view-poll&id={object_id}', 'bx_polls_entries', 'id', 'author', 'featured', '', '');
+
+
+-- CONTENT INFO
+INSERT INTO `sys_objects_content_info` (`name`, `title`, `alert_unit`, `alert_action_add`, `alert_action_update`, `alert_action_delete`, `class_name`, `class_file`) VALUES
+('bx_polls', '_bx_polls', 'bx_polls', 'added', 'edited', 'deleted', '', ''),
+('bx_polls_cmts', '_bx_polls_cmts', 'bx_polls', 'commentPost', 'commentUpdated', 'commentRemoved', 'BxDolContentInfoCmts', '');
+
+INSERT INTO `sys_content_info_grids` (`object`, `grid_object`, `grid_field_id`, `condition`, `selection`) VALUES
+('bx_polls', 'bx_polls_administration', 'id', '', ''),
+('bx_polls', 'bx_polls_common', 'id', '', '');
+
+
+-- SEARCH EXTENDED
+INSERT INTO `sys_objects_search_extended` (`object`, `object_content_info`, `module`, `title`, `active`, `class_name`, `class_file`) VALUES
+('bx_polls', 'bx_polls', 'bx_polls', '_bx_polls_search_extended', 1, '', ''),
+('bx_polls_cmts', 'bx_polls_cmts', 'bx_polls', '_bx_polls_search_extended_cmts', 1, 'BxTemplSearchExtendedCmts', '');
+
+
+-- STUDIO: page & widget
+INSERT INTO `sys_std_pages`(`index`, `name`, `header`, `caption`, `icon`) VALUES
+(3, 'bx_polls', '_bx_polls', '_bx_polls', 'bx_polls@modules/boonex/polls/|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_polls', 'content', '{url_studio}module.php?name=bx_polls', '', 'bx_polls@modules/boonex/polls/|std-icon.svg', '_bx_polls', '', '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));

+ 13 - 0
modules/boonex/polls/updates/13.0.5_13.0.6/source/template/form_subentries.html

@@ -0,0 +1,13 @@
+<div class="bx-form-input-subentries">
+    <bx_repeat:subentries>
+        <div class="bx-form-input-subentry bx-def-padding-thd-topbottom">
+            <div class="bx-form-input-subentry-cell bx-fi-sc-txt">__input_text__</div>
+            <div class="bx-form-input-subentry-cell bx-fi-sc-btn bx-def-padding-sec-left">
+                <a class="bx-btn" href="javascript:void(0)" onclick="javascript:__js_object__.subentryDelete(this)">
+                    <bx_image_auto:times />
+                </a>
+            </div>
+        </div>
+    </bx_repeat:subentries>
+    <div class="bx-form-input-subentry-add">__btn_add__</div>
+</div>

+ 51 - 0
modules/boonex/posts/updates/13.0.7_13.0.8/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' => 'Posts',
+    'version_from' => '13.0.7',
+    'version_to' => '13.0.8',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '13.1.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/posts/updates/update_13.0.7_13.0.8/',
+    'home_uri' => 'posts_update_1307_1308',
+
+    'module_dir' => 'boonex/posts/',
+    'module_uri' => 'posts',
+
+    'db_prefix' => 'bx_posts_',
+    'class_prefix' => 'BxPosts',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_files' => 1,
+        'update_languages' => 0,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Posts',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

+ 13 - 0
modules/boonex/posts/updates/13.0.7_13.0.8/install/installer.php

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

+ 11 - 0
modules/boonex/posts/updates/13.0.7_13.0.8/install/sql/install.sql

@@ -0,0 +1,11 @@
+-- STORAGES & TRANSCODERS
+UPDATE `sys_transcoder_filters` SET `filter_params`='a:1:{s:1:"w";s:4:"1200";}' WHERE `transcoder_object`='bx_posts_cover';
+UPDATE `sys_transcoder_filters` SET `filter_params`='a:2:{s:1:"w";s:4:"1200";s:1:"h";s:4:"1200";}' WHERE `transcoder_object`='bx_posts_view_photos';
+
+
+-- VOTES
+UPDATE `sys_objects_vote` SET `Module`='bx_posts' WHERE `Name` IN ('bx_posts', 'bx_posts_reactions', 'bx_posts_poll_answers');
+
+
+-- VIEWS
+UPDATE `sys_objects_view` SET `module`='bx_posts' WHERE `name`='bx_posts';

+ 155 - 0
modules/boonex/posts/updates/13.0.7_13.0.8/source/install/config.php

@@ -0,0 +1,155 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Posts Posts
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_posts',
+    'title' => 'Posts',
+    'note' => 'Basic blogging module.',
+    'version' => '13.0.8',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '13.1.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/posts/',
+    'home_uri' => 'posts',
+
+    'db_prefix' => 'bx_posts_',
+    'class_prefix' => 'BxPosts',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Posts',
+
+    /**
+     * List of page triggers.
+     */
+    'page_triggers' => array (
+    	'trigger_page_profile_view_entry',
+    ),
+    
+    /**
+     * Menu triggers.
+     */
+    'menu_triggers' => array(
+        'trigger_profile_view_submenu',
+        'trigger_group_view_submenu',
+    ),
+
+    /**
+     * Storage objects to automatically delete files from upon module uninstallation.
+     * Note. Don't add storage objects used in transcoder objects.
+     */
+    'storages' => array(
+        'bx_posts_covers',
+        'bx_posts_photos',
+        'bx_posts_videos',
+        'bx_posts_files'
+    ),
+
+    /**
+     * Transcoders.
+     */
+    'transcoders' => array(
+        'bx_posts_preview',
+        'bx_posts_miniature',
+        'bx_posts_gallery',
+        'bx_posts_cover',
+
+        'bx_posts_preview_photos',
+        'bx_posts_miniature_photos',
+        'bx_posts_gallery_photos',
+        'bx_posts_view_photos',
+
+        'bx_posts_videos_poster',
+        'bx_posts_videos_poster_preview',
+        'bx_posts_videos_mp4',
+        'bx_posts_videos_mp4_hd',
+        
+        'bx_posts_sounds_mp3',
+
+        'bx_posts_preview_files',
+        'bx_posts_gallery_files'
+    ),
+
+    /**
+     * Extended Search Forms.
+     */
+    'esearches' => array(
+        'bx_posts',
+    	'bx_posts_cmts'
+    ),
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'uninstall' => array (
+    	'process_esearches' => 1,
+        'execute_sql' => 1,
+        'update_languages' => 1,
+        'update_relations' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'enable' => array(
+        'execute_sql' => 1,
+        'update_relations' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'enable_success' => array(
+        'process_menu_triggers' => 1,
+        'process_page_triggers' => 1,
+    	'process_esearches' => 1,
+        'register_transcoders' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable' => array (
+        'execute_sql' => 1,
+        'update_relations' => 1,
+        'unregister_transcoders' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable_failed' => array (
+        'register_transcoders' => 1,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Dependencies Section
+     */
+    'dependencies' => array(),
+
+    /**
+     * Relations Section
+     */
+    'relations' => array(
+    	'bx_timeline',
+    	'bx_notifications'
+    ),
+
+);
+
+/** @} */

+ 708 - 0
modules/boonex/posts/updates/13.0.7_13.0.8/source/install/sql/install.sql

@@ -0,0 +1,708 @@
+-- TABLE: entries
+CREATE TABLE IF NOT EXISTS `bx_posts_posts` (
+  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+  `author` int(11) NOT NULL,
+  `added` int(11) NOT NULL,
+  `changed` int(11) NOT NULL,
+  `published` int(11) NOT NULL,
+  `thumb` int(11) NOT NULL,
+  `thumb_data` varchar(50) NOT NULL,
+  `title` varchar(255) NOT NULL,
+  `cat` int(11) NOT NULL,
+  `multicat` text NOT NULL,
+  `text` mediumtext NOT NULL,
+  `labels` text NOT NULL,
+  `location` text NOT NULL,
+  `views` int(11) NOT NULL default '0',
+  `rate` float NOT NULL default '0',
+  `votes` int(11) NOT NULL default '0',
+  `rrate` float NOT NULL default '0',
+  `rvotes` int(11) NOT NULL default '0',
+  `score` int(11) NOT NULL default '0',
+  `sc_up` int(11) NOT NULL default '0',
+  `sc_down` int(11) NOT NULL default '0',
+  `favorites` int(11) NOT NULL default '0',
+  `comments` int(11) NOT NULL default '0',
+  `reports` int(11) NOT NULL default '0',
+  `featured` int(11) NOT NULL default '0',
+  `cf` int(11) NOT NULL default '1',
+  `allow_view_to` varchar(16) NOT NULL DEFAULT '3',
+  `allow_comments` tinyint(4) NOT NULL DEFAULT '1',
+  `status` enum('active','awaiting','failed','hidden') NOT NULL DEFAULT 'active',
+  `status_admin` enum('active','hidden','pending') NOT NULL DEFAULT 'active',
+  PRIMARY KEY (`id`),
+  FULLTEXT KEY `title_text` (`title`,`text`)
+);
+
+-- TABLE: storages & transcoders
+CREATE TABLE IF NOT EXISTS `bx_posts_covers` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `profile_id` int(10) unsigned NOT NULL,
+  `remote_id` varchar(128) NOT NULL,
+  `path` varchar(255) NOT NULL,
+  `file_name` varchar(255) NOT NULL,
+  `mime_type` varchar(128) NOT NULL,
+  `ext` varchar(32) NOT NULL,
+  `size` bigint(20) NOT NULL,
+  `added` int(11) NOT NULL,
+  `modified` int(11) NOT NULL,
+  `private` int(11) NOT NULL,
+  `dimensions` varchar(12) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `remote_id` (`remote_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_posts_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_posts_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,
+  `dimensions` varchar(12) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `remote_id` (`remote_id`)
+);
+
+-- TABLES: LINKS
+CREATE TABLE IF NOT EXISTS `bx_posts_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_posts_links2content` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `content_id` int(11) NOT NULL DEFAULT '0',
+  `link_id` int(11) NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `link` (`link_id`, `content_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_posts_photos_resized` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `profile_id` int(10) unsigned NOT NULL,
+  `remote_id` varchar(128) NOT NULL,
+  `path` varchar(255) NOT NULL,
+  `file_name` varchar(255) NOT NULL,
+  `mime_type` varchar(128) NOT NULL,
+  `ext` varchar(32) NOT NULL,
+  `size` bigint(20) NOT NULL,
+  `added` int(11) NOT NULL,
+  `modified` int(11) NOT NULL,
+  `private` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `remote_id` (`remote_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_posts_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_posts_videos_resized` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `profile_id` int(10) unsigned NOT NULL,
+  `remote_id` varchar(128) NOT NULL,
+  `path` varchar(255) NOT NULL,
+  `file_name` varchar(255) NOT NULL,
+  `mime_type` varchar(128) NOT NULL,
+  `ext` varchar(32) NOT NULL,
+  `size` bigint(20) NOT NULL,
+  `added` int(11) NOT NULL,
+  `modified` int(11) NOT NULL,
+  `private` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `remote_id` (`remote_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_posts_sounds` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `profile_id` int(10) unsigned NOT NULL,
+  `remote_id` varchar(128) NOT NULL,
+  `path` varchar(255) NOT NULL,
+  `file_name` varchar(255) NOT NULL,
+  `mime_type` varchar(128) NOT NULL,
+  `ext` varchar(32) NOT NULL,
+  `size` bigint(20) NOT NULL,
+  `added` int(11) NOT NULL,
+  `modified` int(11) NOT NULL,
+  `private` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `remote_id` (`remote_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_posts_sounds_resized` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `profile_id` int(10) unsigned NOT NULL,
+  `remote_id` varchar(128) NOT NULL,
+  `path` varchar(255) NOT NULL,
+  `file_name` varchar(255) NOT NULL,
+  `mime_type` varchar(128) NOT NULL,
+  `ext` varchar(32) NOT NULL,
+  `size` bigint(20) NOT NULL,
+  `added` int(11) NOT NULL,
+  `modified` int(11) NOT NULL,
+  `private` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `remote_id` (`remote_id`)
+);
+
+-- TABLE: comments
+CREATE TABLE IF NOT EXISTS `bx_posts_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_posts_cmts_notes` (
+  `cmt_id` int(11) NOT NULL AUTO_INCREMENT,
+  `cmt_parent_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_vparent_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_object_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_author_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_level` int(11) NOT NULL DEFAULT '0',
+  `cmt_text` text NOT NULL,
+  `cmt_mood` tinyint(4) NOT NULL DEFAULT '0',
+  `cmt_rate` int(11) NOT NULL DEFAULT '0',
+  `cmt_rate_count` int(11) NOT NULL DEFAULT '0',
+  `cmt_time` int(11) unsigned NOT NULL DEFAULT '0',
+  `cmt_replies` int(11) NOT NULL DEFAULT '0',
+  `cmt_pinned` int(11) NOT NULL default '0',
+  PRIMARY KEY (`cmt_id`),
+  KEY `cmt_object_id` (`cmt_object_id`,`cmt_parent_id`),
+  FULLTEXT KEY `search_fields` (`cmt_text`)
+);
+
+-- TABLE: votes
+CREATE TABLE IF NOT EXISTS `bx_posts_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_posts_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_posts_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_posts_reactions_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `author_nip` int(11) unsigned NOT NULL default '0',
+  `reaction` varchar(32) NOT NULL default '',
+  `value` tinyint(4) NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `vote` (`object_id`, `author_nip`)
+);
+
+-- TABLE: views
+CREATE TABLE `bx_posts_views_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `viewer_id` int(11) NOT NULL default '0',
+  `viewer_nip` int(11) unsigned NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `id` (`object_id`,`viewer_id`,`viewer_nip`)
+);
+
+-- TABLE: metas
+CREATE TABLE `bx_posts_meta_keywords` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(10) unsigned NOT NULL,
+  `keyword` varchar(255) NOT NULL,
+  PRIMARY KEY (`id`),
+  KEY `object_id` (`object_id`),
+  KEY `keyword` (`keyword`)
+);
+
+CREATE TABLE `bx_posts_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`)
+);
+
+CREATE TABLE `bx_posts_meta_locations` (
+  `object_id` int(10) unsigned NOT NULL,
+  `lat` double NOT NULL,
+  `lng` double NOT NULL,
+  `country` varchar(2) NOT NULL,
+  `state` varchar(255) NOT NULL,
+  `city` varchar(255) NOT NULL,
+  `zip` varchar(255) NOT NULL,
+  `street` varchar(255) NOT NULL,
+  `street_number` varchar(255) NOT NULL,
+  PRIMARY KEY (`object_id`),
+  KEY `country_state_city` (`country`,`state`(8),`city`(8))
+);
+
+-- TABLE: reports
+CREATE TABLE IF NOT EXISTS `bx_posts_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_posts_reports_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `author_nip` int(11) unsigned NOT NULL default '0',
+  `type` varchar(32) NOT NULL default '',
+  `text` text NOT NULL default '',
+  `date` int(11) NOT NULL default '0',
+  `checked_by` int(11) NOT NULL default '0',
+  `status` tinyint(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `report` (`object_id`, `author_nip`)
+);
+
+-- TABLE: favorites
+CREATE TABLE `bx_posts_favorites_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `list_id` int(11) NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `id` (`object_id`,`author_id`)
+);
+
+CREATE TABLE `bx_posts_favorites_lists` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `title` varchar(255) NOT NULL,
+  `author_id` int(11) NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  `allow_view_favorite_list_to` varchar(16) NOT NULL DEFAULT '3',
+   PRIMARY KEY (`id`)
+);
+
+-- TABLE: scores
+CREATE TABLE IF NOT EXISTS `bx_posts_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_posts_scores_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `author_nip` int(11) unsigned NOT NULL default '0',
+  `type` varchar(8) NOT NULL default '',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `vote` (`object_id`, `author_nip`)
+);
+
+-- TABLE: polls
+CREATE TABLE IF NOT EXISTS `bx_posts_polls` (
+  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+  `author_id` int(11) NOT NULL default '0',
+  `content_id` int(11) NOT NULL default '0',
+  `text` text NOT NULL,
+  PRIMARY KEY (`id`),
+  KEY `content_id` (`content_id`),
+  FULLTEXT KEY `search_fields` (`text`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_posts_polls_answers` (
+  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+  `poll_id` int(11) unsigned NOT NULL default '0',
+  `title` varchar(255) NOT NULL,
+  `rate` float NOT NULL default '0',
+  `votes` int(11) NOT NULL default '0',
+  `order` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `poll_id` (`poll_id`),
+  FULLTEXT KEY `title` (`title`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_posts_polls_answers_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_posts_polls_answers_votes_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `author_nip` int(11) unsigned NOT NULL default '0',
+  `value` tinyint(4) NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `vote` (`object_id`, `author_nip`)
+);
+
+-- STORAGES & TRANSCODERS
+SET @sStorageEngine = (SELECT `value` FROM `sys_options` WHERE `name` = 'sys_storage_default');
+
+INSERT INTO `sys_objects_storage` (`object`, `engine`, `params`, `token_life`, `cache_control`, `levels`, `table_files`, `ext_mode`, `ext_allow`, `ext_deny`, `quota_size`, `current_size`, `quota_number`, `current_number`, `max_file_size`, `ts`) VALUES
+('bx_posts_covers', @sStorageEngine, '', 360, 2592000, 3, 'bx_posts_covers', 'allow-deny', '{image}', '', 0, 0, 0, 0, 0, 0),
+
+('bx_posts_photos', @sStorageEngine, '', 360, 2592000, 3, 'bx_posts_photos', 'allow-deny', '{image}', '', 0, 0, 0, 0, 0, 0),
+('bx_posts_photos_resized', @sStorageEngine, '', 360, 2592000, 3, 'bx_posts_photos_resized', 'allow-deny', '{image}', '', 0, 0, 0, 0, 0, 0),
+
+('bx_posts_videos', @sStorageEngine, '', 360, 2592000, 3, 'bx_posts_videos', 'allow-deny', '{video}', '', 0, 0, 0, 0, 0, 0),
+('bx_posts_videos_resized', @sStorageEngine, '', 360, 2592000, 3, 'bx_posts_videos_resized', 'allow-deny', '{imagevideo}', '', 0, 0, 0, 0, 0, 0),
+
+('bx_posts_sounds', @sStorageEngine, '', 360, 2592000, 3, 'bx_posts_sounds', 'allow-deny', '{audio}', '', 0, 0, 0, 0, 0, 0),
+('bx_posts_sounds_resized', @sStorageEngine, '', 360, 2592000, 3, 'bx_posts_sounds_resized', 'allow-deny', '{audio}', '', 0, 0, 0, 0, 0, 0),
+
+('bx_posts_files', @sStorageEngine, '', 360, 2592000, 3, 'bx_posts_files', 'deny-allow', '', '{dangerous}', 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_posts_preview', 'bx_posts_photos_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_posts_covers";}', 'no', '1', '2592000', '0', '', ''),
+('bx_posts_miniature', 'bx_posts_photos_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_posts_covers";}', 'no', '1', '2592000', '0', '', ''),
+('bx_posts_gallery', 'bx_posts_photos_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_posts_covers";}', 'no', '1', '2592000', '0', '', ''),
+('bx_posts_cover', 'bx_posts_photos_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_posts_covers";}', 'no', '1', '2592000', '0', '', ''),
+
+('bx_posts_preview_photos', 'bx_posts_photos_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_posts_photos";}', 'no', '1', '2592000', '0', '', ''),
+('bx_posts_miniature_photos', 'bx_posts_photos_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_posts_photos";}', 'no', '1', '2592000', '0', '', ''),
+('bx_posts_gallery_photos', 'bx_posts_photos_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_posts_photos";}', 'no', '1', '2592000', '0', '', ''),
+('bx_posts_view_photos', 'bx_posts_photos_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_posts_photos";}', 'no', '1', '2592000', '0', '', ''),
+
+('bx_posts_videos_poster', 'bx_posts_videos_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_posts_videos";}', 'no', '0', '0', '0', 'BxDolTranscoderVideo', ''),
+('bx_posts_videos_poster_preview', 'bx_posts_videos_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_posts_videos";}', 'no', '0', '0', '0', 'BxDolTranscoderVideo', ''),
+('bx_posts_videos_mp4', 'bx_posts_videos_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_posts_videos";}', 'no', '0', '0', '0', 'BxDolTranscoderVideo', ''),
+('bx_posts_videos_mp4_hd', 'bx_posts_videos_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_posts_videos";}', 'no', '0', '0', '0', 'BxDolTranscoderVideo', ''),
+
+('bx_posts_sounds_mp3', 'bx_posts_sounds_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_posts_sounds";}', 'no', '0', '0', '0', 'BxDolTranscoderAudio', ''),
+
+('bx_posts_preview_files', 'bx_posts_photos_resized', 'Storage', 'a:1:{s:6:"object";s:14:"bx_posts_files";}', 'no', '1', '2592000', '0', '', ''),
+('bx_posts_gallery_files', 'bx_posts_photos_resized', 'Storage', 'a:1:{s:6:"object";s:14:"bx_posts_files";}', 'no', '1', '2592000', '0', '', '');
+
+INSERT INTO `sys_transcoder_filters` (`transcoder_object`, `filter`, `filter_params`, `order`) VALUES 
+('bx_posts_preview', 'Resize', 'a:3:{s:1:"w";s:3:"300";s:1:"h";s:3:"200";s:11:"crop_resize";s:1:"1";}', '0'),
+('bx_posts_miniature', 'Resize', 'a:1:{s:1:"w";s:3:"300";}', '0'),
+('bx_posts_gallery', 'Resize', 'a:1:{s:1:"w";s:3:"500";}', '0'),
+('bx_posts_cover', 'Resize', 'a:1:{s:1:"w";s:4:"1200";}', '0'),
+
+('bx_posts_preview_photos', 'Resize', 'a:3:{s:1:"w";s:3:"300";s:1:"h";s:3:"200";s:11:"crop_resize";s:1:"1";}', '0'),
+('bx_posts_miniature_photos', 'Resize', 'a:4:{s:1:"w";s:3:"300";s:1:"h";s:3:"300";s:13:"square_resize";s:1:"1";s:10:"force_type";s:3:"jpg";}', '0'),
+('bx_posts_gallery_photos', 'Resize', 'a:4:{s:1:"w";s:3:"600";s:1:"h";s:3:"600";s:13:"square_resize";s:1:"1";s:10:"force_type";s:3:"jpg";}', '0'),
+('bx_posts_view_photos', 'Resize',  'a:2:{s:1:"w";s:4:"1200";s:1:"h";s:4:"1200";}', '0'),
+
+('bx_posts_videos_poster_preview', 'Resize', 'a:3:{s:1:"w";s:3:"300";s:1:"h";s:3:"200";s:13:"square_resize";s:1:"1";}', 10),
+('bx_posts_videos_poster_preview', 'Poster', 'a:2:{s:1:"h";s:3:"480";s:10:"force_type";s:3:"jpg";}', 0),
+('bx_posts_videos_poster', 'Poster', 'a:2:{s:1:"h";s:3:"318";s:10:"force_type";s:3:"jpg";}', 0),
+('bx_posts_videos_mp4', 'Mp4', 'a:2:{s:1:"h";s:3:"318";s:10:"force_type";s:3:"mp4";}', 0),
+('bx_posts_videos_mp4_hd', 'Mp4', 'a:3:{s:1:"h";s:3:"720";s:13:"video_bitrate";s:4:"1536";s:10:"force_type";s:3:"mp4";}', 0),
+
+('bx_posts_sounds_mp3', 'Mp3', 'a:0:{}', 0),
+
+('bx_posts_preview_files', 'Resize', 'a:3:{s:1:"w";s:3:"300";s:1:"h";s:3:"200";s:11:"crop_resize";s:1:"1";}', '0'),
+('bx_posts_gallery_files', 'Resize', 'a:4:{s:1:"w";s:3:"600";s:1:"h";s:3:"600";s:13:"square_resize";s:1:"1";s:10:"force_type";s:3:"jpg";}', '0');
+
+
+-- FORMS: entry (post)
+INSERT INTO `sys_objects_form`(`object`, `module`, `title`, `action`, `form_attrs`, `table`, `key`, `uri`, `uri_title`, `submit_name`, `params`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_posts', 'bx_posts', '_bx_posts_form_entry', '', 'a:1:{s:7:"enctype";s:19:"multipart/form-data";}', 'bx_posts_posts', 'id', '', '', 'a:2:{i:0;s:9:"do_submit";i:1;s:10:"do_publish";}', '', 0, 1, 'BxPostsFormEntry', 'modules/boonex/posts/classes/BxPostsFormEntry.php');
+
+INSERT INTO `sys_form_displays`(`object`, `display_name`, `module`, `view_mode`, `title`) VALUES 
+('bx_posts', 'bx_posts_entry_add', 'bx_posts', 0, '_bx_posts_form_entry_display_add'),
+('bx_posts', 'bx_posts_entry_delete', 'bx_posts', 0, '_bx_posts_form_entry_display_delete'),
+('bx_posts', 'bx_posts_entry_edit', 'bx_posts', 0, '_bx_posts_form_entry_display_edit'),
+('bx_posts', 'bx_posts_entry_view', 'bx_posts', 1, '_bx_posts_form_entry_display_view');
+
+INSERT INTO `sys_form_inputs`(`object`, `module`, `name`, `value`, `values`, `checked`, `type`, `caption_system`, `caption`, `info`, `required`, `collapsed`, `html`, `attrs`, `attrs_tr`, `attrs_wrapper`, `checker_func`, `checker_params`, `checker_error`, `db_pass`, `db_params`, `editable`, `deletable`) VALUES 
+('bx_posts', 'bx_posts', '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_posts', 'bx_posts', 'allow_view_to', '', '', 0, 'custom', '_bx_posts_form_entry_input_sys_allow_view_to', '_bx_posts_form_entry_input_allow_view_to', '', 1, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_posts', 'bx_posts', 'delete_confirm', 1, '', 0, 'checkbox', '_bx_posts_form_entry_input_sys_delete_confirm', '_bx_posts_form_entry_input_delete_confirm', '_bx_posts_form_entry_input_delete_confirm_info', 1, 0, 0, '', '', '', 'Avail', '', '_bx_posts_form_entry_input_delete_confirm_error', '', '', 1, 0),
+('bx_posts', 'bx_posts', 'do_publish', '_bx_posts_form_entry_input_do_publish', '', 0, 'submit', '_bx_posts_form_entry_input_sys_do_publish', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_posts', 'bx_posts', 'do_submit', '_bx_posts_form_entry_input_do_submit', '', 0, 'submit', '_bx_posts_form_entry_input_sys_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_posts', 'bx_posts', 'location', '', '', 0, 'location', '_sys_form_input_sys_location', '_sys_form_input_location', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_posts', 'bx_posts', 'covers', 'a:1:{i:0;s:14:"bx_posts_html5";}', 'a:1:{s:14:"bx_posts_html5";s:25:"_sys_uploader_html5_title";}', 0, 'files', '_bx_posts_form_entry_input_sys_covers', '_bx_posts_form_entry_input_covers', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_posts', 'bx_posts', 'pictures', 'a:1:{i:0;s:21:"bx_posts_photos_html5";}', 'a:1:{s:21:"bx_posts_photos_html5";s:25:"_sys_uploader_html5_title";}', 0, 'files', '_bx_posts_form_entry_input_sys_pictures', '_bx_posts_form_entry_input_pictures', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_posts', 'bx_posts', 'videos', 'a:2:{i:0;s:21:"bx_posts_videos_html5";i:1;s:28:"bx_posts_videos_record_video";}', 'a:2:{s:21:"bx_posts_videos_html5";s:25:"_sys_uploader_html5_title";s:28:"bx_posts_videos_record_video";s:32:"_sys_uploader_record_video_title";}', 0, 'files', '_bx_posts_form_entry_input_sys_videos', '_bx_posts_form_entry_input_videos', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_posts', 'bx_posts', 'link', '', '', 0, 'custom', '_bx_posts_form_post_input_sys_link', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_posts', 'bx_posts', 'sounds', 'a:1:{i:0;s:21:"bx_posts_sounds_html5";}', 'a:1:{s:21:"bx_posts_sounds_html5";s:25:"_sys_uploader_html5_title";}', 0, 'files', '_bx_posts_form_entry_input_sys_sounds', '_bx_posts_form_entry_input_sounds', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_posts', 'bx_posts', 'files', 'a:1:{i:0;s:20:"bx_posts_files_html5";}', 'a:1:{s:20:"bx_posts_files_html5";s:25:"_sys_uploader_html5_title";}', 0, 'files', '_bx_posts_form_entry_input_sys_files', '_bx_posts_form_entry_input_files', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_posts', 'bx_posts', 'polls', '', '', 0, 'custom', '_bx_posts_form_entry_input_sys_polls', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_posts', 'bx_posts', 'text', '', '', 0, 'textarea', '_bx_posts_form_entry_input_sys_text', '_bx_posts_form_entry_input_text', '', 1, 0, 2, '', '', '', 'Avail', '', '_bx_posts_form_entry_input_text_err', 'XssHtml', '', 1, 0),
+('bx_posts', 'bx_posts', 'title', '', '', 0, 'text', '_bx_posts_form_entry_input_sys_title', '_bx_posts_form_entry_input_title', '', 1, 0, 0, '', '', '', 'Avail', '', '_bx_posts_form_entry_input_title_err', 'Xss', '', 1, 0),
+('bx_posts', 'bx_posts', 'cat', '', '#!bx_posts_cats', 0, 'select', '_bx_posts_form_entry_input_sys_cat', '_bx_posts_form_entry_input_cat', '', 1, 0, 0, '', '', '', 'avail', '', '_bx_posts_form_entry_input_cat_err', 'Xss', '', 1, 0),
+('bx_posts', 'bx_posts', 'multicat', '', '', 0, 'custom', '_bx_posts_form_entry_input_sys_multicat', '_bx_posts_form_entry_input_multicat', '', 1, 0, 0, '', '', '', 'avail', '', '_bx_posts_form_entry_input_multicat_err', 'Xss', '', 1, 0),
+('bx_posts', 'bx_posts', 'added', '', '', 0, 'datetime', '_bx_posts_form_entry_input_sys_date_added', '_bx_posts_form_entry_input_date_added', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_posts', 'bx_posts', 'changed', '', '', 0, 'datetime', '_bx_posts_form_entry_input_sys_date_changed', '_bx_posts_form_entry_input_date_changed', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_posts', 'bx_posts', 'published', '', '', 0, 'datetime', '_bx_posts_form_entry_input_sys_date_published', '_bx_posts_form_entry_input_date_published', '_bx_posts_form_entry_input_date_published_info', 0, 0, 0, '', '', '', '', '', '', 'DateTimeTs', '', 1, 0),
+('bx_posts', 'bx_posts', 'attachments', '', '', 0, 'custom', '_bx_posts_form_entry_input_sys_attachments', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_posts', 'bx_posts', 'labels', '', '', 0, 'custom', '_sys_form_input_sys_labels', '_sys_form_input_labels', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_posts', 'bx_posts', 'anonymous', '', '', 0, 'switcher', '_sys_form_input_sys_anonymous', '_sys_form_input_anonymous', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_posts', 'bx_posts', 'allow_comments', '1', '', 1, 'switcher', '_bx_posts_form_entry_input_sys_allow_comments', '_bx_posts_form_entry_input_allow_comments', '', 0, 0, 0, '', '', '', '', '', '', 'Int', '', 1, 0);
+
+
+
+INSERT INTO `sys_form_display_inputs`(`display_name`, `input_name`, `visible_for_levels`, `active`, `order`) VALUES 
+('bx_posts_entry_add', 'delete_confirm', 2147483647, 0, 1),
+('bx_posts_entry_add', 'title', 2147483647, 1, 2),
+('bx_posts_entry_add', 'cat', 2147483647, 1, 3),
+('bx_posts_entry_add', 'text', 2147483647, 1, 4),
+('bx_posts_entry_add', 'attachments', 2147483647, 1, 5),
+('bx_posts_entry_add', 'link', 2147483647, 1, 6),
+('bx_posts_entry_add', 'pictures', 2147483647, 1, 7),
+('bx_posts_entry_add', 'videos', 2147483647, 1, 8),
+('bx_posts_entry_add', 'sounds', 2147483647, 1, 9),
+('bx_posts_entry_add', 'files', 2147483647, 1, 10),
+('bx_posts_entry_add', 'polls', 2147483647, 1, 11),
+('bx_posts_entry_add', 'covers', 2147483647, 1, 12),
+('bx_posts_entry_add', 'allow_view_to', 2147483647, 1, 13),
+('bx_posts_entry_add', 'cf', 2147483647, 1, 14),
+('bx_posts_entry_add', 'location', 2147483647, 1, 15),
+('bx_posts_entry_add', 'published', 192, 0, 16),
+('bx_posts_entry_add', 'allow_comments', 192, 1, 17),
+('bx_posts_entry_add', 'do_publish', 2147483647, 1, 18),
+
+('bx_posts_entry_delete', 'delete_confirm', 2147483647, 1, 1),
+('bx_posts_entry_delete', 'do_submit', 2147483647, 1, 2),
+
+('bx_posts_entry_edit', 'do_publish', 2147483647, 0, 1),
+('bx_posts_entry_edit', 'delete_confirm', 2147483647, 0, 2),
+('bx_posts_entry_edit', 'title', 2147483647, 1, 3),
+('bx_posts_entry_edit', 'cat', 2147483647, 1, 4),
+('bx_posts_entry_edit', 'text', 2147483647, 1, 5),
+('bx_posts_entry_edit', 'attachments', 2147483647, 1, 6),
+('bx_posts_entry_edit', 'link', 2147483647, 1, 7),
+('bx_posts_entry_edit', 'pictures', 2147483647, 1, 8),
+('bx_posts_entry_edit', 'videos', 2147483647, 1, 9),
+('bx_posts_entry_edit', 'sounds', 2147483647, 1, 10),
+('bx_posts_entry_edit', 'files', 2147483647, 1, 11),
+('bx_posts_entry_edit', 'polls', 2147483647, 1, 12),
+('bx_posts_entry_edit', 'covers', 2147483647, 1, 13),
+('bx_posts_entry_edit', 'allow_view_to', 2147483647, 1, 14),
+('bx_posts_entry_edit', 'cf', 2147483647, 1, 15),
+('bx_posts_entry_edit', 'location', 2147483647, 1, 16),
+('bx_posts_entry_edit', 'allow_comments', 192, 1, 17),
+('bx_posts_entry_edit', 'published', 192, 0, 18),
+('bx_posts_entry_edit', 'do_submit', 2147483647, 1, 19),
+
+('bx_posts_entry_view', 'cat', 2147483647, 1, 1),
+('bx_posts_entry_view', 'added', 2147483647, 1, 2),
+('bx_posts_entry_view', 'changed', 2147483647, 1, 3),
+('bx_posts_entry_view', 'published', 192, 1, 4);
+
+-- FORMS: poll
+INSERT INTO `sys_objects_form` (`object`, `module`, `title`, `action`, `form_attrs`, `submit_name`, `table`, `key`, `uri`, `uri_title`, `params`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES
+('bx_posts_poll', 'bx_posts', '_bx_posts_form_poll', '', '', 'do_submit', 'bx_posts_polls', 'id', '', '', 'a:1:{s:14:"checker_helper";s:28:"BxPostsFormPollCheckerHelper";}', 0, 1, 'BxPostsFormPoll', 'modules/boonex/posts/classes/BxPostsFormPoll.php');
+
+INSERT INTO `sys_form_displays` (`display_name`, `module`, `object`, `title`, `view_mode`) VALUES
+('bx_posts_poll_add', 'bx_posts', 'bx_posts_poll', '_bx_posts_form_poll_display_add', 0);
+
+INSERT INTO `sys_form_inputs` (`object`, `module`, `name`, `value`, `values`, `checked`, `type`, `caption_system`, `caption`, `info`, `required`, `collapsed`, `html`, `attrs`, `attrs_tr`, `attrs_wrapper`, `checker_func`, `checker_params`, `checker_error`, `db_pass`, `db_params`, `editable`, `deletable`) VALUES
+('bx_posts_poll', 'bx_posts', 'text', '', '', 0, 'text', '_bx_posts_form_poll_input_sys_text', '_bx_posts_form_poll_input_text', '', 1, 0, 0, '', '', '', 'Avail', '', '_bx_posts_form_poll_input_text_err', 'Xss', '', 1, 0),
+('bx_posts_poll', 'bx_posts', 'answers', '', '', 0, 'custom', '_bx_posts_form_poll_input_sys_answers', '_bx_posts_form_poll_input_answers', '', 1, 0, 0, '', '', '', 'AvailAnswers', '', '_bx_posts_form_poll_input_answers_err', '', '', 1, 0),
+('bx_posts_poll', 'bx_posts', 'controls', '', 'do_submit,do_cancel', 0, 'input_set', '', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
+('bx_posts_poll', 'bx_posts', 'do_submit', '_bx_posts_form_poll_input_do_submit', '', 0, 'submit', '_bx_posts_form_poll_input_sys_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
+('bx_posts_poll', 'bx_posts', 'do_cancel', '_bx_posts_form_poll_input_do_cancel', '', 0, 'button', '_bx_posts_form_poll_input_do_cancel', '', '', 0, 0, 0, 'a:2:{s:7:"onclick";s:45:"$(''.bx-popup-applied:visible'').dolPopupHide()";s:5:"class";s:22:"bx-def-margin-sec-left";}', '', '', '', '', '', '', '', 0, 0);
+
+INSERT INTO `sys_form_display_inputs` (`display_name`, `input_name`, `visible_for_levels`, `active`, `order`) VALUES
+('bx_posts_poll_add', 'text', 2147483647, 1, 1),
+('bx_posts_poll_add', 'answers', 2147483647, 1, 2),
+('bx_posts_poll_add', 'controls', 2147483647, 1, 3),
+('bx_posts_poll_add', 'do_submit', 2147483647, 1, 4),
+('bx_posts_poll_add', 'do_cancel', 2147483647, 1, 5);
+
+-- 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_posts_attach_link', 'bx_posts', '_bx_posts_form_attach_link', '', '', 'do_submit', 'bx_posts_links', 'id', '', '', '', 0, 1, '', '');
+
+INSERT INTO `sys_form_displays` (`display_name`, `module`, `object`, `title`, `view_mode`) VALUES
+('bx_posts_attach_link_add', 'bx_posts', 'bx_posts_attach_link', '_bx_posts_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_posts_attach_link', 'bx_posts', 'content_id', '0', '', 0, 'hidden', '_bx_posts_form_attach_link_input_sys_content_id', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
+('bx_posts_attach_link', 'bx_posts', 'url', '', '', 0, 'text', '_bx_posts_form_attach_link_input_sys_url', '_bx_posts_form_attach_link_input_url', '', 0, 0, 0, '', '', '', 'Preg', 'a:1:{s:4:"preg";s:0:"";}', '_bx_posts_form_attach_link_input_url_err', '', '', 0, 0),
+('bx_posts_attach_link', 'bx_posts', 'controls', '', 'do_submit,do_cancel', 0, 'input_set', '', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
+('bx_posts_attach_link', 'bx_posts', 'do_submit', '_bx_posts_form_attach_link_input_do_submit', '', 0, 'submit', '_bx_posts_form_attach_link_input_sys_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
+('bx_posts_attach_link', 'bx_posts', 'do_cancel', '_bx_posts_form_attach_link_input_do_cancel', '', 0, 'button', '_bx_posts_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_posts_attach_link_add', 'content_id', 2147483647, 1, 1),
+('bx_posts_attach_link_add', 'url', 2147483647, 1, 2),
+('bx_posts_attach_link_add', 'controls', 2147483647, 1, 3),
+('bx_posts_attach_link_add', 'do_submit', 2147483647, 1, 4),
+('bx_posts_attach_link_add', 'do_cancel', 2147483647, 1, 5);
+
+-- PRE-VALUES
+INSERT INTO `sys_form_pre_lists`(`key`, `title`, `module`, `use_for_sets`) VALUES
+('bx_posts_cats', '_bx_posts_pre_lists_cats', 'bx_posts', '0');
+
+INSERT INTO `sys_form_pre_values`(`Key`, `Value`, `Order`, `LKey`, `LKey2`) VALUES
+('bx_posts_cats', '', 0, '_sys_please_select', ''),
+('bx_posts_cats', '1', 1, '_bx_posts_cat_Animals_Pets', ''),
+('bx_posts_cats', '2', 2, '_bx_posts_cat_Architecture', ''),
+('bx_posts_cats', '3', 3, '_bx_posts_cat_Art', ''),
+('bx_posts_cats', '4', 4, '_bx_posts_cat_Cars_Motorcycles', ''),
+('bx_posts_cats', '5', 5, '_bx_posts_cat_Celebrities', ''),
+('bx_posts_cats', '6', 6, '_bx_posts_cat_Design', ''),
+('bx_posts_cats', '7', 7, '_bx_posts_cat_DIY_Crafts', ''),
+('bx_posts_cats', '8', 8, '_bx_posts_cat_Education', ''),
+('bx_posts_cats', '9', 9, '_bx_posts_cat_Film_Music_Books', ''),
+('bx_posts_cats', '10', 10, '_bx_posts_cat_Food_Drink', ''),
+('bx_posts_cats', '11', 11, '_bx_posts_cat_Gardening', ''),
+('bx_posts_cats', '12', 12, '_bx_posts_cat_Geek', ''),
+('bx_posts_cats', '13', 13, '_bx_posts_cat_Hair_Beauty', ''),
+('bx_posts_cats', '14', 14, '_bx_posts_cat_Health_Fitness', ''),
+('bx_posts_cats', '15', 15, '_bx_posts_cat_History', ''),
+('bx_posts_cats', '16', 16, '_bx_posts_cat_Holidays_Events', ''),
+('bx_posts_cats', '17', 17, '_bx_posts_cat_Home_Decor', ''),
+('bx_posts_cats', '18', 18, '_bx_posts_cat_Humor', ''),
+('bx_posts_cats', '19', 19, '_bx_posts_cat_Illustrations_Posters', ''),
+('bx_posts_cats', '20', 20, '_bx_posts_cat_Kids_Parenting', ''),
+('bx_posts_cats', '21', 21, '_bx_posts_cat_Mens_Fashion', ''),
+('bx_posts_cats', '22', 22, '_bx_posts_cat_Outdoors', ''),
+('bx_posts_cats', '23', 23, '_bx_posts_cat_Photography', ''),
+('bx_posts_cats', '24', 24, '_bx_posts_cat_Products', ''),
+('bx_posts_cats', '25', 25, '_bx_posts_cat_Quotes', ''),
+('bx_posts_cats', '26', 26, '_bx_posts_cat_Science_Nature', ''),
+('bx_posts_cats', '27', 27, '_bx_posts_cat_Sports', ''),
+('bx_posts_cats', '28', 28, '_bx_posts_cat_Tattoos', ''),
+('bx_posts_cats', '29', 29, '_bx_posts_cat_Technology', ''),
+('bx_posts_cats', '30', 30, '_bx_posts_cat_Travel', ''),
+('bx_posts_cats', '31', 31, '_bx_posts_cat_Weddings', ''),
+('bx_posts_cats', '32', 32, '_bx_posts_cat_Womens_Fashion', '');
+
+-- 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_posts', 'bx_posts', 'bx_posts_cmts', 1, 5000, 1000, 3, 5, 3, 'tail', 1, 'bottom', 1, 1, 1, -3, 1, 'cmt', 'page.php?i=view-post&id={object_id}', '', 'bx_posts_posts', 'id', 'author', 'title', 'comments', '', ''),
+('bx_posts_notes', 'bx_posts', 'bx_posts_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_posts_posts', 'id', 'author', 'title', '', 'BxTemplCmtsNotes', '');
+
+-- VOTES
+INSERT INTO `sys_objects_vote` (`Name`, `Module`, `TableMain`, `TableTrack`, `PostTimeout`, `MinValue`, `MaxValue`, `IsUndo`, `IsOn`, `TriggerTable`, `TriggerFieldId`, `TriggerFieldAuthor`, `TriggerFieldRate`, `TriggerFieldRateCount`, `ClassName`, `ClassFile`) VALUES 
+('bx_posts', 'bx_posts', 'bx_posts_votes', 'bx_posts_votes_track', '604800', '1', '1', '0', '1', 'bx_posts_posts', 'id', 'author', 'rate', 'votes', '', ''),
+('bx_posts_reactions', 'bx_posts', 'bx_posts_reactions', 'bx_posts_reactions_track', '604800', '1', '1', '1', '1', 'bx_posts_posts', 'id', 'author', 'rrate', 'rvotes', 'BxTemplVoteReactions', ''),
+('bx_posts_poll_answers', 'bx_posts', 'bx_posts_polls_answers_votes', 'bx_posts_polls_answers_votes_track', '604800', '1', '1', '0', '1', 'bx_posts_polls_answers', 'id', 'author_id', 'rate', 'votes', 'BxPostsVotePollAnswers', 'modules/boonex/posts/classes/BxPostsVotePollAnswers.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_posts', 'bx_posts', 'bx_posts_scores', 'bx_posts_scores_track', '604800', '0', 'bx_posts_posts', 'id', 'author', 'score', 'sc_up', 'sc_down', '', '');
+
+-- REPORTS
+INSERT INTO `sys_objects_report` (`name`, `module`, `table_main`, `table_track`, `is_on`, `base_url`, `object_comment`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_count`, `class_name`, `class_file`) VALUES 
+('bx_posts', 'bx_posts', 'bx_posts_reports', 'bx_posts_reports_track', '1', 'page.php?i=view-post&id={object_id}', 'bx_posts_notes', 'bx_posts_posts', 'id', 'author', 'reports', '', '');
+
+-- 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_posts', 'bx_posts', 'bx_posts_views_track', '86400', '1', 'bx_posts_posts', 'id', 'author', 'views', '', '');
+
+-- FAVORITES
+INSERT INTO `sys_objects_favorite` (`name`, `table_track`, `table_lists`, `is_on`, `is_undo`, `is_public`, `base_url`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_count`, `class_name`, `class_file`) VALUES 
+('bx_posts', 'bx_posts_favorites_track', 'bx_posts_favorites_lists', '1', '1', '1', 'page.php?i=view-post&id={object_id}', 'bx_posts_posts', 'id', 'author', 'favorites', '', '');
+
+-- FEATURED
+INSERT INTO `sys_objects_feature` (`name`, `module`, `is_on`, `is_undo`, `base_url`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_flag`, `class_name`, `class_file`) VALUES 
+('bx_posts', 'bx_posts', '1', '1', 'page.php?i=view-post&id={object_id}', 'bx_posts_posts', 'id', 'author', 'featured', '', '');
+
+-- CONTENT INFO
+INSERT INTO `sys_objects_content_info` (`name`, `title`, `alert_unit`, `alert_action_add`, `alert_action_update`, `alert_action_delete`, `class_name`, `class_file`) VALUES
+('bx_posts', '_bx_posts', 'bx_posts', 'added', 'edited', 'deleted', '', ''),
+('bx_posts_cmts', '_bx_posts_cmts', 'bx_posts', 'commentPost', 'commentUpdated', 'commentRemoved', 'BxDolContentInfoCmts', '');
+
+INSERT INTO `sys_content_info_grids` (`object`, `grid_object`, `grid_field_id`, `condition`, `selection`) VALUES
+('bx_posts', 'bx_posts_administration', 'id', '', ''),
+('bx_posts', 'bx_posts_common', 'id', '', '');
+
+-- SEARCH EXTENDED
+INSERT INTO `sys_objects_search_extended` (`object`, `object_content_info`, `module`, `title`, `active`, `class_name`, `class_file`) VALUES
+('bx_posts', 'bx_posts', 'bx_posts', '_bx_posts_search_extended', 1, '', ''),
+('bx_posts_cmts', 'bx_posts_cmts', 'bx_posts', '_bx_posts_search_extended_cmts', 1, 'BxTemplSearchExtendedCmts', '');
+
+-- STUDIO: page & widget
+INSERT INTO `sys_std_pages`(`index`, `name`, `header`, `caption`, `icon`) VALUES
+(3, 'bx_posts', '_bx_posts', '_bx_posts', 'bx_posts@modules/boonex/posts/|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_posts', 'content', '{url_studio}module.php?name=bx_posts', '', 'bx_posts@modules/boonex/posts/|std-icon.svg', '_bx_posts', '', '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/profiler/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' => 'Profiler',
+    'version_from' => '13.0.2',
+    'version_to' => '13.0.3',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '13.1.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/profiler/updates/update_13.0.2_13.0.3/',
+    'home_uri' => 'profiler_update_1302_1303',
+
+    'module_dir' => 'boonex/profiler/',
+    'module_uri' => 'profiler',
+
+    'db_prefix' => 'bx_profiler_',
+    'class_prefix' => 'BxProfiler',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 0,
+        'update_files' => 1,
+        'update_languages' => 0,
+        'clear_db_cache' => 0,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Boonex Profiler',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

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

+ 670 - 0
modules/boonex/profiler/updates/13.0.2_13.0.3/source/classes/BxProfiler.php

@@ -0,0 +1,670 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Profiler Profiler
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+define ('BX_PROFILER', true);
+define ('BX_PROFILER_DISPLAY', 1);
+
+require_once(BX_DIRECTORY_PATH_MODULES . 'boonex/profiler/install/config.php');
+$GLOBALS['bx_profiler_module'] = array (
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_profiler',
+    'title' => $aConfig['title'],
+    'vendor' => $aConfig['vendor'],
+    'path' => $aConfig['home_dir'],
+    'uri' => $aConfig['home_uri'],
+    'class_prefix' => $aConfig['class_prefix'],
+    'db_prefix' => $aConfig['db_prefix'],
+);
+
+bx_import('Template', $GLOBALS['bx_profiler_module']);
+bx_import('Config', $GLOBALS['bx_profiler_module']);
+
+class BxProfiler extends BxDol
+{
+    protected $oConfig, $oTemplate;
+
+    protected $aConf = array ();
+
+    protected $_iTimeStart = 0;
+
+    protected $_aQueries = array();
+    protected $_sQueryIndex = 0;
+
+    protected $_aModules = array();
+    protected $_aModulesNames = array();
+    protected $_aModulesLevel = 0;
+
+    protected $_aAlerts = array();
+    protected $_iAlertsLevel = 0;
+
+    protected $_aInjections = array();
+    protected $_sInjectionIndex = 0;
+
+    protected $_sLogDateFormat = "Y-m-d H:i:s";
+    protected $_sLogMaxArgLength = 64;
+    protected $_sLogFilename = 64;
+
+    function __construct($iTimeStart)
+    {
+        parent::__construct();
+
+        $this->oConfig = new BxProfilerConfig ($GLOBALS['bx_profiler_module']);
+        $this->oTemplate = new BxProfilerTemplate ($this->oConfig);
+        $this->oTemplateAdmin = BxDolStudioTemplate::getInstance();
+
+        if (getParam ('bx_profiler_long_sql_queries_log'))
+            $this->aConf['long_query'] = getParam ('bx_profiler_long_sql_queries_time');
+        if (getParam ('bx_profiler_long_module_query_log'))
+            $this->aConf['long_module'] = getParam ('bx_profiler_long_module_query_time');
+        if (getParam ('bx_profiler_long_page_log'))
+            $this->aConf['long_page'] = getParam ('bx_profiler_long_page_time');
+
+        $this->_iTimeStart = $iTimeStart;
+    }
+
+    // output profiler debug panel
+    function output ()
+    {
+        $iPageTime = $this->_getCurrentDelay ();
+        if (isset($this->aConf['long_page']) && $iPageTime > $this->aConf['long_page'])
+            $this->logPageOpen ($iPageTime);
+
+        switch (getParam('bx_profiler_show_debug_panel')) {
+        case 'all':
+            break;
+        case 'admins':
+            if (!isset($GLOBALS['logged']) || !$GLOBALS['logged']['admin'])
+                return;
+            break;
+        case 'none':
+        default:
+            return;
+        }
+
+        $aCss = array (
+			'profiler.css',
+            BX_DIRECTORY_PATH_PLUGINS_PUBLIC . 'jush/|jush.css',
+        );
+        $aJs = array (
+            'jquery.tablesorter.min.js',
+            'profiler.js',
+            'jush/jush.js',
+        );
+
+        $sJsCss = '';
+        foreach ($aCss as $sCssPath)
+            $sJsCss .= $this->oTemplate->addCss($sCssPath, 1);
+        foreach ($aJs as $sJsPath)
+            $sJsCss .= $this->oTemplate->addJs($sJsPath, 1);
+
+        $sPlanks  = $this->_plankMain ();
+        $sPlanks .= $this->_plankMenus ();
+        $sPlanks .= $this->_plankTemplates ();
+        $sPlanks .= $this->_plankInjections ();
+        $sPlanks .= $this->_plankPagesBlocks ();
+        $sPlanks .= $this->_plankSql ();
+        $sPlanks .= $this->_plankModules ();
+        $sPlanks .= $this->_plankAlerts ();
+
+        echo ob_get_clean();
+
+        $sContentType = $this->oTemplate->getHeaderContentType();
+        if ('text/html' == $sContentType) {            
+            echo $sJsCss . $sPlanks;
+        } 
+        else if ('application/json' == $sContentType) {
+            echo $sPlanks;
+        }
+    }
+
+    function _logBegin ($s)
+    {
+        $sDate = date ($this->_sLogDateFormat);
+        return "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" . $sDate . " " . $s . "\n" .
+        (getLoggedId() ? "User ID: " . getLoggedId()  . "\n" : '') .
+        "User role: " . ($GLOBALS['logged']['admin'] ? 'admin' : ($GLOBALS['logged']['member'] ? 'member' : 'guest')) . "\n";
+    }
+
+    function _logEnd ()
+    {
+        return "\n";
+    }
+
+    function _appendToLog ($s)
+    {
+		bx_log('bx_profiler', $s);
+    }
+
+    function logSqlQuery ($iTime, $aSqlQuery, &$oStmt)
+    {
+        $s  = $this->_logBegin ('LONG SQL QUERY: ' . $aSqlQuery['time']);
+        $s .= "Rows: " . $aSqlQuery['rows'] . "\n";
+        $s .= "Affected: " . $aSqlQuery['affected'] . "\n";
+        $s .= "Query: " . $aSqlQuery['sql'] . "\n";
+        if (getParam('bx_profiler_long_sql_queries_debug'))
+            $s .= "Backtrace: \n" . $this->_debugBackTrace (3);
+        $s .= $this->_logEnd();
+        $this->_appendToLog ($s);
+    }
+
+    function logModuleQuery ($iTime, $aModuleQuery)
+    {
+        $s  = $this->_logBegin ('LONG MODULE QUERY: ' . $aModuleQuery['time']);
+        $s .= "Module name: " . $aModuleQuery['name'] . "\n";
+        $s .= "Query type: " . $aModuleQuery['type'] . "\n";
+        $s .= "Class/file: " . $aModuleQuery['class/file'] . "\n";
+        $s .= "Method: " . $aModuleQuery['method'] . "\n";
+        if (getParam('bx_profiler_long_module_query_debug'))
+            $s .= "Backtrace: \n" . $this->_debugBackTrace (3);
+        $s .= $this->_logEnd();
+        $this->_appendToLog ($s);
+    }
+
+    function logPageOpen ($iTime)
+    {
+        $s  = $this->_logBegin ('LONG PAGE OPEN: ' . $this->_formatTime($iTime));
+        $s .= "Request method: " . $_SERVER['REQUEST_METHOD'] . "\n";
+        $s .= "Query string: " . $_SERVER['QUERY_STRING'] . "\n";
+        $s .= "Request URI: " . $_SERVER['REQUEST_URI'] . "\n";
+        $s .= "Script name: " . $_SERVER['SCRIPT_NAME'] . "\n";
+        $s .= "PHP self: " . $_SERVER['PHP_SELF'] . "\n";
+        if (getParam('bx_profiler_long_page_debug'))
+            $s .= "All server vars: \n" . print_r ($_SERVER, true);
+        $s .= $this->_logEnd();
+        $this->_appendToLog ($s);
+    }
+
+    function beginModule($sType, $sHash, &$aModule, $sClassFile, $sMethod = '' )
+    {
+        ++$this->_aModulesLevel;
+        $this->_aModulesNames[$aModule['title']] = isset($this->_aModulesNames[$aModule['title']]) ? $this->_aModulesNames[$aModule['title']] + 1 : 1;
+        $this->_aModules[$sHash] = array (
+            'name' => str_repeat("--", $this->_aModulesLevel-1) . $aModule['title'],
+            'type' => $sType,
+            'class/file' => $sClassFile,
+            'method' => $sMethod,
+            'begin' => microtime (),
+            'time' => -1,
+        );
+    }
+
+    function endModule($sType, $sHash)
+    {
+        --$this->_aModulesLevel;
+        $iTime = $this->_calcTime ($this->_aModules[$sHash]['begin']);
+        unset ($this->_aModules[$sHash]['begin']);
+        $this->_aModules[$sHash]['time'] = $this->_formatTime($iTime);
+        $this->_aModules[$sHash]['raw_time'] = $iTime;
+        if (isset($this->aConf['long_module']) && $iTime > $this->aConf['long_module'])
+            $this->logModuleQuery ($iTime, $this->_aModules[$sHash]);
+    }
+
+    function beginAlert($sUnit, $sAction, $sHandler)
+    {
+        $sHash = md5($sUnit . $sAction . $sHandler . $this->_iAlertsLevel);
+        ++$this->_iAlertsLevel;
+        $this->_aAlerts[$sHash] = array (
+            'name' => str_repeat("--", $this->_iAlertsLevel-1) . $sHandler,
+            'unit' => $sUnit,
+            'action' => $sAction,
+            'handler' => $sHandler,
+            'begin' => microtime (),
+            'time' => -1,
+        );
+    }
+
+    function endAlert($sUnit, $sAction, $sHandler)
+    {
+        --$this->_iAlertsLevel;
+        $sHash = md5($sUnit . $sAction . $sHandler . $this->_iAlertsLevel);
+        $iTime = $this->_calcTime ($this->_aAlerts[$sHash]['begin']);
+        unset ($this->_aAlerts[$sHash]['begin']);
+        $this->_aAlerts[$sHash]['time'] = $this->_formatTime($iTime);
+        $this->_aAlerts[$sHash]['raw_time'] = $iTime;
+    }
+
+    function beginInjection ($sId)
+    {
+        $this->_sInjectionIndex = $sId;
+        $this->_aInjections[$sId]['begin'] = microtime ();
+    }
+
+    function endInjection ($sId, $aInjection)
+    {
+        if (!isset($this->_aInjections[$sId]))
+            return;
+        $iTime = $this->_calcTime ($this->_aInjections[$sId]['begin']);
+        unset ($this->_aInjections[$sId]['begin']);
+        $this->_aInjections[$sId]['name'] = isset($aInjection['name']) ? $aInjection['name'] : 'no-name';
+        $this->_aInjections[$sId]['key'] = $aInjection['key'];
+        $this->_aInjections[$sId]['replace'] = $aInjection['replace'] ? 'yes' : 'no';
+        $this->_aInjections[$sId]['time'] = $this->_formatTime($iTime);
+        $this->_aInjections[$sId]['raw_time'] = $iTime;
+    }
+
+    function beginPageBlock ($sName, $iBlockId)
+    {
+        $this->_sPageBlockIndex = $iBlockId;
+        $this->_aPagesBlocks[$this->_sPageBlockIndex]['name'] = $sName;
+        $this->_aPagesBlocks[$this->_sPageBlockIndex]['begin'] = microtime ();
+    }
+
+    function endPageBlock ($iBlockId, $isEmpty, $isCached)
+    {
+        if (!$this->_sPageBlockIndex)
+            return;
+        $iTime = $this->_calcTime ($this->_aPagesBlocks[$this->_sPageBlockIndex]['begin']);
+        unset ($this->_aPagesBlocks[$this->_sPageBlockIndex]['begin']);
+        $this->_aPagesBlocks[$this->_sPageBlockIndex]['cached'] = $isCached ? 'yes' : 'no';
+        $this->_aPagesBlocks[$this->_sPageBlockIndex]['empty'] = $isEmpty ? 'yes' : 'no';
+        $this->_aPagesBlocks[$this->_sPageBlockIndex]['time'] = $this->_formatTime($iTime);
+        $this->_aPagesBlocks[$this->_sPageBlockIndex]['raw_time'] = $iTime;
+    }
+
+    function beginPage ($sName)
+    {
+        $this->_sPageIndex = md5 ($sName.time().rand());
+        $this->_aPages[$this->_sPageIndex]['name'] = $sName;
+        $this->_aPages[$this->_sPageIndex]['begin'] = microtime ();
+    }
+
+    function endPage (&$sContent)
+    {
+        if (!$this->_sPageIndex || !isset($this->_aPages[$this->_sPageIndex]['begin']))
+            return;
+        $iTime = $this->_calcTime ($this->_aPages[$this->_sPageIndex]['begin']);
+        unset ($this->_aPages[$this->_sPageIndex]['begin']);
+        $this->_aPages[$this->_sPageIndex]['time'] = $this->_formatTime($iTime);
+        $this->_aPages[$this->_sPageIndex]['raw_time'] = $iTime;
+    }
+
+    function beginTemplate ($sName, $sRand)
+    {
+        $this->_aTemplateIndexes[$sName.$sRand] = 1;
+        $this->_aTemplates[$sName.$sRand]['name'] = $sName;
+        $this->_aTemplates[$sName.$sRand]['begin'] = microtime ();
+    }
+
+    function endTemplate ($sName, $sRand, &$sContent, $isCached)
+    {
+        if (!isset($this->_aTemplateIndexes[$sName.$sRand]))
+            return;
+        $iTime = $this->_calcTime ($this->_aTemplates[$sName.$sRand]['begin']);
+        unset ($this->_aTemplates[$sName.$sRand]['begin']);
+        $this->_aTemplates[$sName.$sRand]['cached'] = $isCached ? 'yes' : 'no';
+        $this->_aTemplates[$sName.$sRand]['time'] = $this->_formatTime($iTime);
+        $this->_aTemplates[$sName.$sRand]['raw_time'] = $iTime;
+    }
+
+    function beginQuery ($sSql)
+    {
+        $this->_sQueryIndex = md5 ($sSql.time().rand());
+        $this->_aQueries[$this->_sQueryIndex]['sql'] = $sSql;
+        $this->_aQueries[$this->_sQueryIndex]['begin'] = microtime ();
+    }
+
+    function endQuery (&$oStmt)
+    {
+        if (!$this->_sQueryIndex)
+            return;
+        $iTime = $this->_calcTime ($this->_aQueries[$this->_sQueryIndex]['begin']);
+        unset ($this->_aQueries[$this->_sQueryIndex]['begin']);
+        $this->_aQueries[$this->_sQueryIndex]['time'] = $this->_formatTime($iTime);
+        $this->_aQueries[$this->_sQueryIndex]['raw_time'] = $iTime;
+        $this->_aQueries[$this->_sQueryIndex]['rows'] = $oStmt ? BxDolDb::getInstance()->getNumRows($oStmt) : '';
+        $this->_aQueries[$this->_sQueryIndex]['affected'] = $oStmt ? BxDolDb::getInstance()->getAffectedRows($oStmt) : '';
+        if (isset($this->aConf['long_query']) && $iTime > $this->aConf['long_query'])
+            $this->logSqlQuery ($iTime, $this->_aQueries[$this->_sQueryIndex], $oStmt);
+    }
+
+    function beginMenu ($sName)
+    {
+        $this->_aMenus[$sName]['name'] = $sName;
+        $this->_aMenus[$sName]['begin'] = microtime ();
+    }
+
+    function endMenu ($sName)
+    {
+        if (!isset($this->_aMenus[$sName]))
+            return;
+        $iTime = $this->_calcTime ($this->_aMenus[$sName]['begin']);
+        unset ($this->_aMenus[$sName]['begin']);
+        $this->_aMenus[$sName]['time'] = $this->_formatTime($iTime);
+        $this->_aMenus[$sName]['raw_time'] = $iTime;
+    }
+
+    function _getCurrentDelay ()
+    {
+        $i1 = explode(' ', microtime ());
+        $i2 = explode(' ', $this->_iTimeStart);
+        return ($i1[0]+$i1[1]) - ($i2[0]+$i2[1]);
+    }
+
+    function _plankMain ()
+    {
+        $sTime = $this->_formatTime($this->_getCurrentDelay (), 3);
+        if (function_exists('memory_get_usage'))
+            $sMemory = $this->_formatBytes(memory_get_usage(true)) . ' of ' . ini_get('memory_limit') . ' allowed';
+
+        return $this->oTemplate->plank(
+            $this->oTemplate->nameValue('Time:', $sTime) .
+            (function_exists('memory_get_usage') ? $this->oTemplate->nameValue('Memory:', $sMemory) : '') .
+            $this->oTemplate->nameValue('PHP:', phpversion()) .
+            $this->oTemplate->nameValue('SAPI:', php_sapi_name()) .
+            $this->oTemplate->nameValue('OS:', php_uname('s r m'))
+        );
+    }
+
+    function _plankTemplates ()
+    {
+        if (empty($GLOBALS['bx_profiler']->_aPages) && empty($GLOBALS['bx_profiler']->_aTemplates))
+            return;
+
+        $sPages = '';
+        if (!empty($GLOBALS['bx_profiler']->_aPages)) {
+            $iTimePages = 0;
+            foreach ($GLOBALS['bx_profiler']->_aPages as $k => $r) {
+                if (!isset($r['raw_time']))
+                    continue;
+                $iTimePages += $r['raw_time'];
+                unset ($GLOBALS['bx_profiler']->_aPages[$k]['raw_time']);
+            }
+            $sPages = count($GLOBALS['bx_profiler']->_aPages) . ' (' . $this->_formatTime($iTimePages, 3) . ')';
+        }
+
+        $sTemplatesCached = '';
+        $sTemplatesNotCached = '';
+        if ($GLOBALS['bx_profiler']->_aTemplates) {
+            $iTimeTemplatesCached = 0;
+            $iTimeTemplatesNotCached = 0;
+            $sTemplatesCached = 0;
+            $sTemplatesNotCached = 0;
+            foreach ($GLOBALS['bx_profiler']->_aTemplates as $k => $r) {
+                if (!isset($r['raw_time']))
+                    continue;
+                if ('yes' == $r['cached']) {
+                    $iTimeTemplatesCached += $r['raw_time'];
+                    ++$sTemplatesCached;
+                } else {
+                    $iTimeTemplatesNotCached += $r['raw_time'];
+                    ++$sTemplatesNotCached;
+                }
+                unset ($GLOBALS['bx_profiler']->_aTemplates[$k]['raw_time']);
+            }
+            if ($sTemplatesCached)
+                $sTemplatesCached .= ' (' . $this->_formatTime($iTimeTemplatesCached, 3) . ')';
+            if ($sTemplatesNotCached)
+                $sTemplatesNotCached .= ' (' . $this->_formatTime($iTimeTemplatesNotCached, 3) . ')';
+        }
+
+        return $this->oTemplate->plank(
+            ($sPages ? $this->oTemplate->nameValue('Pages:', $sPages) : '') .
+            ($sTemplatesCached ? $this->oTemplate->nameValue('Templates Cached:', $sTemplatesCached) : '') .
+            ($sTemplatesNotCached ? $this->oTemplate->nameValue('Templates Not Cached:', $sTemplatesNotCached) : ''),
+            $this->oTemplate->table($GLOBALS['bx_profiler']->_aTemplates)
+        );
+    }
+
+    function _plankInjections ()
+    {
+        if (!$GLOBALS['bx_profiler']->_aInjections)
+            return;
+
+        $iTimeInjections = 0;
+        foreach ($GLOBALS['bx_profiler']->_aInjections as $k => $r) {
+            if (!isset($r['raw_time']))
+                continue;
+            $iTimeInjections += $r['raw_time'];
+            unset ($GLOBALS['bx_profiler']->_aInjections[$k]['raw_time']);
+        }
+
+        $sInjections = count($GLOBALS['bx_profiler']->_aInjections) . ' injection (' . $this->_formatTime($iTimeInjections, 3) . ')';
+
+        return $this->oTemplate->plank(
+            $this->oTemplate->nameValue('Injections:', $sInjections),
+            $this->oTemplate->table($GLOBALS['bx_profiler']->_aInjections)
+        );
+    }
+
+    function _plankPagesBlocks ()
+    {
+        if (empty($GLOBALS['bx_profiler']->_aPagesBlocks))
+            return;
+
+        $iTimeBlocks = 0;
+        $iTimeBlocksCached = 0;
+        $iTimeBlocksNotCached = 0;
+        $iTimeBlocksEmpty = 0;
+        $iTimeBlocksNotEmpty = 0;
+
+        $iCountBlocksCached = 0;
+        $iCountBlocksNotCached = 0;
+        $iCountBlocksEmpty = 0;
+        $iCountBlocksNotEmpty = 0;
+
+        foreach ($GLOBALS['bx_profiler']->_aPagesBlocks as $k => $r) {
+            if (!isset($r['raw_time']))
+                continue;
+            $iTimeBlocks += $r['raw_time'];
+            if ($r['cached'] == 'yes') {
+                $iTimeBlocksCached += $r['raw_time'];
+                ++$iCountBlocksCached;
+            } else {
+                $iTimeBlocksNotCached += $r['raw_time'];
+                ++$iCountBlocksNotCached;
+            }
+            if ($r['empty'] == 'yes') {
+                $iTimeBlocksEmpty += $r['raw_time'];
+                ++$iCountBlocksEmpty;
+            } else {
+                $iTimeBlocksNotEmpty += $r['raw_time'];
+                ++$iCountBlocksNotEmpty;
+            }
+            unset ($GLOBALS['bx_profiler']->_aPagesBlocks[$k]['raw_time']);
+        }
+
+        $sBlocks = count($GLOBALS['bx_profiler']->_aPagesBlocks) . ' (' . $this->_formatTime($iTimeBlocks, 3) . ')';
+        if ($iCountBlocksCached)
+            $sBlocksCached = $iCountBlocksCached . ' (' . $this->_formatTime($iTimeBlocksCached, 3) . ')';
+        if ($iCountBlocksNotCached)
+            $sBlocksNotCached = $iCountBlocksNotCached . ' (' . $this->_formatTime($iTimeBlocksNotCached, 3) . ')';
+        if ($iCountBlocksEmpty)
+            $sBlocksEmpty = $iCountBlocksEmpty . ' (' . $this->_formatTime($iTimeBlocksEmpty, 3) . ')';
+        if ($iCountBlocksNotEmpty)
+            $sBlocksNotEmpty = $iCountBlocksNotEmpty . ' (' . $this->_formatTime($iTimeBlocksNotEmpty, 3) . ')';
+
+        return $this->oTemplate->plank(
+            $this->oTemplate->nameValue('Pages Blocks:', $sBlocks) .
+            ($iCountBlocksCached ? $this->oTemplate->nameValue('Cached:', $sBlocksCached) : '') .
+            ($iCountBlocksNotCached ? $this->oTemplate->nameValue('Not Cached:', $sBlocksNotCached) : '') .
+            ($iCountBlocksEmpty ? $this->oTemplate->nameValue('Empty:', $sBlocksEmpty) : '') .
+            ($iCountBlocksNotEmpty ? $this->oTemplate->nameValue('Not Empty:', $sBlocksNotEmpty) : ''),
+            $this->oTemplate->table($GLOBALS['bx_profiler']->_aPagesBlocks)
+        );
+    }
+
+    function _plankMenus ()
+    {
+        if (empty($GLOBALS['bx_profiler']->_aMenus))
+            return;
+
+        $iTimeMenus = 0;
+        foreach ($GLOBALS['bx_profiler']->_aMenus as $k => $r) {
+            if (!isset($r['raw_time']))
+                continue;
+            $iTimeMenus += $r['raw_time'];
+            unset ($GLOBALS['bx_profiler']->_aMenus[$k]['raw_time']);
+        }
+
+        $sMenus = count($GLOBALS['bx_profiler']->_aMenus) . ' menus (' . $this->_formatTime($iTimeMenus, 3) . ')';
+
+        return $this->oTemplate->plank(
+            $this->oTemplate->nameValue('Menus:', $sMenus),
+            $this->oTemplate->table($GLOBALS['bx_profiler']->_aMenus)
+        );
+    }
+
+    function _plankSql ()
+    {
+        if (empty($GLOBALS['bx_profiler']->_aQueries))
+            return;
+
+        $iTimeQueries = 0;
+        foreach ($GLOBALS['bx_profiler']->_aQueries as $k => $r) {
+            if (!isset($r['raw_time']))
+                continue;
+            $iTimeQueries += $r['raw_time'];
+            unset ($GLOBALS['bx_profiler']->_aQueries[$k]['raw_time']);
+        }
+
+        $sQueries = count($GLOBALS['bx_profiler']->_aQueries) . ' queries (' . $this->_formatTime($iTimeQueries, 3) . ')';
+
+        return $this->oTemplate->plank(
+            $this->oTemplate->nameValue('SQL:', $sQueries),
+            $this->oTemplate->table($GLOBALS['bx_profiler']->_aQueries, 'sql')
+        );
+    }
+
+    function _plankModules ()
+    {
+        if (empty($GLOBALS['bx_profiler']->_aModules))
+            return;
+
+        $iTimeModules = 0;
+        foreach ($GLOBALS['bx_profiler']->_aModules as $k => $r) {
+            if (!isset($r['raw_time']))
+                continue;
+            $iTimeModules += $r['raw_time'];
+            unset ($GLOBALS['bx_profiler']->_aModules[$k]['raw_time']);
+        }
+
+        $sModules = count($GLOBALS['bx_profiler']->_aModulesNames) . ' modules loaded';
+        $sModulesQueries = count($GLOBALS['bx_profiler']->_aModules) . ' modules queries (' . $this->_formatTime($iTimeModules, 3) . ')';
+
+        return $this->oTemplate->plank(
+            $this->oTemplate->nameValue('Modules:', $sModules) .
+            $this->oTemplate->nameValue('Modules Queries:', $sModulesQueries),
+            $this->oTemplate->table($GLOBALS['bx_profiler']->_aModules)
+        );
+    }
+
+    function _plankAlerts ()
+    {
+        if (empty($GLOBALS['bx_profiler']->_aAlerts))
+            return;
+
+        $iTimeAlerts = 0;
+        foreach ($GLOBALS['bx_profiler']->_aAlerts as $k => $r) {
+            if (!isset($r['raw_time']))
+                continue;
+            $iTimeAlerts += $r['raw_time'];
+            unset ($GLOBALS['bx_profiler']->_aAlerts[$k]['raw_time']);
+        }
+
+        $sAlerts = count($GLOBALS['bx_profiler']->_aAlerts) . ' alerts responses (' . $this->_formatTime($iTimeAlerts, 3) . ')';
+
+        return $this->oTemplate->plank(
+            $this->oTemplate->nameValue('Alerts:', $sAlerts),
+            $this->oTemplate->table($GLOBALS['bx_profiler']->_aAlerts)
+        );
+    }
+
+    function _formatTime ($i, $iPrecision = 4)
+    {
+        return round($i, $iPrecision) . ' sec';
+    }
+
+    function _formatBytes ($i)
+    {
+        if ($i > 1024*1024)
+            return round($i/1024/1024, 1) . 'M';
+        elseif ($i > 1024)
+            return round($i/1024, 1) . 'K';
+        else
+            return $i . 'B';
+    }
+
+    function _isProfilerDisabled()
+    {
+        if (isset($GLOBALS['bx_profiler_disable']) || isset($_GET['bx_profiler_disable']))
+            return true;
+
+        return false;
+    }
+
+    function _calcTime ($begin)
+    {
+        $i1 = explode(' ', microtime ());
+        $i2 = explode(' ', $begin);
+        return ($i1[0]+$i1[1]) - ($i2[0]+$i2[1]);
+    }
+
+    function _debugPrintArray ($mixed)
+    {
+        $sArgs .= 'Array(';
+        foreach ($mixed as $mixed2)
+            $sArgs .= (is_object($mixed2) ? $this->_debugPrintObject($mixed2) : $this->_debugPrintAny($mixed2)) . ',';
+        $sArgs = substr($sArgs, 0, -1);
+        $sArgs .= ')';
+        return $sArgs;
+    }
+
+    function _debugPrintObject ($mixed)
+    {
+        return get_class($mixed) . ' instance';
+    }
+
+    function _debugPrintAny ($mixed)
+    {
+        if (is_string)
+            return "'" . (strlen($mixed) > $this->_sLogMaxArgLength ? substr($mixed, 0, $this->_sLogMaxArgLength) . '...' : $mixed) . "'";
+        else
+            return $mixed;
+    }
+
+    function _debugBackTrace ($iShifts = 0)
+    {
+        $a = debug_backtrace();
+        while (--$iShifts > -1)
+            array_shift($a);
+
+        $s = '';
+        foreach ($a as $r) {
+
+            $sArgs = '';
+            foreach ($r['args'] as $mixed) {
+                switch (true) {
+                case is_array($mixed):
+                    $sArgs .= $this->_debugPrintArray($mixed);
+                    break;
+                case is_object($mixed):
+                    $sArgs .= $this->_debugPrintObject($mixed);
+                    break;
+                default:
+                    $sArgs .= $this->_debugPrintAny($mixed);
+                }
+                $sArgs .= ',';
+            }
+            $sArgs = substr($sArgs, 0, -1);
+
+            $s .= "--------------------------------------\n";
+            $s .= "{$r['line']} {$r['file']}\n";
+            $s .= "{$r['class']}{$r['type']}{$r['function']} ({$sArgs});\n";
+        }
+        return $s;
+    }
+}
+
+$GLOBALS['bx_profiler'] = new BxProfiler(BX_DOL_START);
+if (!$GLOBALS['bx_profiler']->_isProfilerDisabled())
+    register_shutdown_function (array ($GLOBALS['bx_profiler'], 'output'));
+
+/** @} */

+ 26 - 0
modules/boonex/profiler/updates/13.0.2_13.0.3/source/classes/BxProfilerAlertsResponse.php

@@ -0,0 +1,26 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Profiler Profiler
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+/**
+ * alerts handler
+ */
+class BxProfilerAlertsResponse extends BxDolAlertsResponse
+{
+    public function response($oAlert)
+    {
+        if ('system' == $oAlert->sUnit && 'begin' == $oAlert->sAction) {
+            ob_start();
+            require_once(BX_DIRECTORY_PATH_MODULES . 'boonex/profiler/classes/BxProfiler.php');
+        }
+    }
+}
+
+/** @} */

+ 153 - 0
modules/boonex/profiler/updates/13.0.2_13.0.3/source/classes/BxProfilerTemplate.php

@@ -0,0 +1,153 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Profiler Profiler
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+class BxProfilerTemplate extends BxDolModuleTemplate
+{
+    protected $_isAjaxOutput = false;
+
+    function __construct(&$oConfig)
+    {
+        $oDb = null;
+        parent::__construct($oConfig, $oDb);
+        $this->_isAjaxOutput = $this->_isAjaxRequest();
+    }
+
+    function plank($sTitle, $sContent = '')
+    {
+        static $i = 0;
+        $i++;
+        if ($this->_isAjaxOutput) {
+            if (!headers_sent() && function_exists('fb')) {
+                if ($sContent && is_array($sContent))
+                    fb($sContent, $sTitle, FirePHP::TABLE);
+                else
+                    fb($sTitle . $sContent);
+            }
+            elseif (!headers_sent()) {
+                if ($sContent && is_array($sContent)) {
+                    $sContentEnc = json_encode($sContent);
+                    header("X-Una-Profiler-$i: $sTitle" . ($sContent && $sContentEnc < 4000 ? '; ' . $sContentEnc : ''));
+                } else {
+                    header("X-Una-Profiler-$i: $sTitle" . ($sContent && $sContent < 4000 ? '; ' . $sContent : ''));
+                }
+            }
+            return '';
+        }
+        if ($sContent)
+            $sContent = '<div class="bx_profiler_switch" onclick="bx_profiler_switch(this)">+</div><div class="bx_profiler_content">'.$sContent.'</div>';
+        return '<div class="bx_profiler_plank"><span class="bx_profiler_plank_title">' . $sTitle . '</span>' . $sContent . '</div>';
+    }
+
+    function nameValue ($sName, $sVal)
+    {
+        return $this->_isAjaxOutput ? "{$sName}{$sVal} | " : "<u>$sName</u><b>$sVal</b>";
+    }
+
+    function table ($a, $sHighlight = '')
+    {
+        if ($this->_isAjaxOutput) {
+            $table = array();
+            foreach ($a as $r) {
+
+                if (!$table)
+                    $table[] = array_keys($r);
+
+                $rr = array_values($r);
+                if (false !== strpos($rr[0], '&#160;'))
+                    $rr[0] = str_replace('&#160;', '-', $rr[0]);
+                $table[] = $rr;
+            }
+            return $table;
+        }
+
+        $sId = md5(time() . rand());
+        $s = '<table id="'.$sId.'" class="bx_profiler_table">';
+        $th = '';
+        foreach ($a as $r) {
+            if (!$th) {
+                foreach ($r as $k => $v)
+                    $th .= "<th>$k</th>";
+                $s .= "<thead><tr>$th</tr></thead><tbody>";
+            }
+            $s .= '<tr>';
+            foreach ($r as $k => $v) {
+                $sClass = '';
+                if ($sHighlight && $k == $sHighlight)
+                    $sClass = ' class="highlight" ';
+
+                $s .= "<td $sClass>".htmlspecialchars_adv($v)."</td>";
+            }
+            $s .= '</tr>';
+        }
+        $s .= '</tbody></table>';
+        $s .= '<script language="javascript">$(document).ready(function(){ $(\'#'.$sId.'\').tablesorter(); });</script>';
+        return $s;
+    }
+
+    function _isAjaxRequest ()
+    {
+        if ('application/json' == $this->getHeaderContentType()) 
+            return true;
+
+        if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) and $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest')
+            return true;
+        if (isset($_GET['bx_profiler_ajax_request']))
+            return true;
+
+        if (preg_match('/vote\.php/', bx_html_attribute($_SERVER['PHP_SELF'])))
+            return true;
+        if (preg_match('/image_transcoder\.php/', bx_html_attribute($_SERVER['PHP_SELF'])))
+            return true;
+        if (preg_match('/storage\.php/', bx_html_attribute($_SERVER['PHP_SELF'])))
+            return true;
+        if (preg_match('/storage_uploader\.php/', bx_html_attribute($_SERVER['PHP_SELF'])))
+            return true;
+        if (preg_match('/searchKeywordContent\.php/', bx_html_attribute($_SERVER['PHP_SELF'])))
+            return true;        
+        if (preg_match('/menu\.php/', bx_html_attribute($_SERVER['PHP_SELF'])))
+            return true;
+        if (preg_match('/gzip_loader\.php/', $_SERVER['PHP_SELF']))
+            return true;
+        if (preg_match('/get_rss_feed\.php/', $_SERVER['PHP_SELF']))
+            return true;
+        return false;
+    }
+
+    function addCss($mixedFiles, $bDynamic = false)
+    {
+        if ($this->_isAjaxOutput)
+            return '';
+        return parent::addCss($mixedFiles, $bDynamic);
+    }
+
+    function addJs($mixedFiles, $bDynamic = false)
+    {
+        if ($this->_isAjaxOutput)
+            return '';
+        return parent::addJs($mixedFiles, $bDynamic);
+    }
+
+    function getHeaderContentType()
+    {
+        $aHeaders = headers_list();
+        foreach ($aHeaders as $s) {
+            $a = explode(':', $s);
+            if (isset($a[0]) && isset($a[1]) && 'content-type' == strtolower(trim($a[0]))) {
+                $aa = explode(';', $a[1]);
+                return strtolower(trim($aa[0]));
+            }
+        }
+
+        return false;
+    }
+}
+
+/** @} */

+ 68 - 0
modules/boonex/profiler/updates/13.0.2_13.0.3/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.3',
+    'vendor' => 'Boonex',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '13.1.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/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(),
+);
+
+/** @} */

+ 51 - 0
modules/boonex/shopify/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' => 'Shopify',
+    'version_from' => '13.0.3',
+    'version_to' => '13.0.4',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '13.1.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/shopify/updates/update_13.0.3_13.0.4/',
+    'home_uri' => 'shopify_update_1303_1304',
+
+    'module_dir' => 'boonex/shopify/',
+    'module_uri' => 'shopify',
+
+    'db_prefix' => 'bx_shopify_',
+    'class_prefix' => 'BxShopify',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_files' => 1,
+        'update_languages' => 0,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Shopify',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

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

+ 6 - 0
modules/boonex/shopify/updates/13.0.3_13.0.4/install/sql/install.sql

@@ -0,0 +1,6 @@
+-- VOTES
+UPDATE `sys_objects_vote` SET `Module`='bx_shopify' WHERE `Name` IN ('bx_shopify', 'bx_shopify_reactions');
+
+
+-- VIEWS
+UPDATE `sys_objects_view` SET `module`='bx_shopify' WHERE `name`='bx_shopify';

+ 116 - 0
modules/boonex/shopify/updates/13.0.3_13.0.4/source/install/config.php

@@ -0,0 +1,116 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Shopify Shopify
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_shopify',
+    'title' => 'Shopify',
+    'note' => 'Shopify shopping module.',
+    'version' => '13.0.4',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '13.1.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/shopify/',
+    'home_uri' => 'shopify',
+
+    'db_prefix' => 'bx_shopify_',
+    'class_prefix' => 'BxShopify',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Shopify',
+
+    /**
+     * List of page triggers.
+     */
+    'page_triggers' => array (
+    	'trigger_page_profile_view_entry',
+    ),
+    
+    /**
+     * Menu triggers.
+     */
+    'menu_triggers' => array(
+    	'trigger_profile_view_submenu',
+        'trigger_group_view_submenu'
+    ),
+
+	/**
+     * Extended Search Forms.
+     */
+    'esearches' => array(
+        'bx_shopify',
+    	'bx_shopify_cmts',
+    ),
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'uninstall' => array (
+    	'process_esearches' => 1,
+        'execute_sql' => 1,
+        'update_languages' => 1,
+    	'update_relations' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'enable' => array(
+        'execute_sql' => 1,
+    	'update_relations' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'enable_success' => array(
+        'process_menu_triggers' => 1,
+        'process_page_triggers' => 1,
+    	'process_esearches' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable' => array (
+        'execute_sql' => 1,
+    	'update_relations' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable_failed' => array (
+    	'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Dependencies Section
+     */
+    'dependencies' => array(),
+
+    /**
+     * Relations Section
+     */
+    'relations' => array(
+    	'bx_timeline',
+    	'bx_notifications'
+    ),
+
+);
+
+/** @} */

+ 371 - 0
modules/boonex/shopify/updates/13.0.3_13.0.4/source/install/sql/install.sql

@@ -0,0 +1,371 @@
+SET @sStorageEngine = (SELECT `value` FROM `sys_options` WHERE `name` = 'sys_storage_default');
+
+
+-- TABLE: entries
+CREATE TABLE IF NOT EXISTS `bx_shopify_entries` (
+  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+  `author` int(10) unsigned NOT NULL,
+  `added` int(11) NOT NULL,
+  `changed` int(11) NOT NULL,
+  `title` varchar(255) NOT NULL,
+  `code` varchar(255) NOT NULL default '',
+  `cat` int(11) NOT NULL,
+  `location` text NOT NULL,
+  `views` int(11) NOT NULL default '0',
+  `rate` float NOT NULL default '0',
+  `votes` int(11) NOT NULL default '0',
+  `rrate` float NOT NULL default '0',
+  `rvotes` int(11) NOT NULL default '0',
+  `score` int(11) NOT NULL default '0',
+  `sc_up` int(11) NOT NULL default '0',
+  `sc_down` int(11) NOT NULL default '0',
+  `favorites` int(11) NOT NULL default '0',
+  `comments` int(11) NOT NULL default '0',
+  `reports` int(11) NOT NULL default '0',
+  `featured` int(11) NOT NULL default '0',
+  `cf` int(11) NOT NULL default '1',
+  `allow_view_to` varchar(16) NOT NULL DEFAULT '3',
+  `status` enum('active','hidden') NOT NULL DEFAULT 'active',
+  `status_admin` enum('active','hidden','pending') NOT NULL DEFAULT 'active',
+  PRIMARY KEY (`id`),
+  FULLTEXT KEY `title_text` (`title`)
+);
+
+-- TABLE: settings
+CREATE TABLE IF NOT EXISTS `bx_shopify_settings` (
+  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+  `author` int(10) unsigned NOT NULL,
+  `domain` varchar(255) NOT NULL,
+  `access_token` varchar(255) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `author` (`author`)
+);
+
+-- TABLE: comments
+CREATE TABLE IF NOT EXISTS `bx_shopify_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_shopify_cmts_notes` (
+  `cmt_id` int(11) NOT NULL AUTO_INCREMENT,
+  `cmt_parent_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_vparent_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_object_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_author_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_level` int(11) NOT NULL DEFAULT '0',
+  `cmt_text` text NOT NULL,
+  `cmt_mood` tinyint(4) NOT NULL DEFAULT '0',
+  `cmt_rate` int(11) NOT NULL DEFAULT '0',
+  `cmt_rate_count` int(11) NOT NULL DEFAULT '0',
+  `cmt_time` int(11) unsigned NOT NULL DEFAULT '0',
+  `cmt_replies` int(11) NOT NULL DEFAULT '0',
+  `cmt_pinned` int(11) NOT NULL default '0',
+  PRIMARY KEY (`cmt_id`),
+  KEY `cmt_object_id` (`cmt_object_id`,`cmt_parent_id`),
+  FULLTEXT KEY `search_fields` (`cmt_text`)
+);
+
+-- TABLE: votes
+CREATE TABLE IF NOT EXISTS `bx_shopify_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_shopify_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_shopify_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_shopify_reactions_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `author_nip` int(11) unsigned NOT NULL default '0',
+  `reaction` varchar(32) NOT NULL default '',
+  `value` tinyint(4) NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `vote` (`object_id`, `author_nip`)
+);
+
+-- TABLE: views
+CREATE TABLE IF NOT EXISTS `bx_shopify_views_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `viewer_id` int(11) NOT NULL default '0',
+  `viewer_nip` int(11) unsigned NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `id` (`object_id`,`viewer_id`,`viewer_nip`)
+);
+
+-- TABLE: metas
+CREATE TABLE IF NOT EXISTS `bx_shopify_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_shopify_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_shopify_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_shopify_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_shopify_reports_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `author_nip` int(11) unsigned NOT NULL default '0',
+  `type` varchar(32) NOT NULL default '',
+  `text` text NOT NULL default '',
+  `date` int(11) NOT NULL default '0',
+  `checked_by` int(11) NOT NULL default '0',
+  `status` tinyint(11) NOT NULL default '0', 
+  PRIMARY KEY (`id`),
+  KEY `report` (`object_id`, `author_nip`)
+);
+
+-- TABLE: favorites
+CREATE TABLE IF NOT EXISTS `bx_shopify_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',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `id` (`object_id`,`author_id`)
+);
+
+-- TABLE: scores
+CREATE TABLE IF NOT EXISTS `bx_shopify_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_shopify_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`)
+);
+
+
+-- 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_shopify', 'bx_shopify', '_bx_shopify_form_entry', '', 'a:1:{s:7:"enctype";s:19:"multipart/form-data";}', 'bx_shopify_entries', 'id', '', '', 'a:2:{i:0;s:9:"do_submit";i:1;s:10:"do_publish";}', '', 0, 1, 'BxShopifyFormEntry', 'modules/boonex/shopify/classes/BxShopifyFormEntry.php'),
+('bx_shopify_settings', 'bx_shopify', '_bx_shopify_form_settings', '', 'a:1:{s:7:"enctype";s:19:"multipart/form-data";}', 'bx_shopify_settings', 'id', '', '', 'do_submit', '', 0, 1, 'BxShopifyFormSettings', 'modules/boonex/shopify/classes/BxShopifyFormSettings.php');
+
+INSERT INTO `sys_form_displays`(`object`, `display_name`, `module`, `view_mode`, `title`) VALUES 
+('bx_shopify', 'bx_shopify_entry_add', 'bx_shopify', 0, '_bx_shopify_form_entry_display_add'),
+('bx_shopify', 'bx_shopify_entry_delete', 'bx_shopify', 0, '_bx_shopify_form_entry_display_delete'),
+('bx_shopify', 'bx_shopify_entry_edit', 'bx_shopify', 0, '_bx_shopify_form_entry_display_edit'),
+('bx_shopify', 'bx_shopify_entry_view', 'bx_shopify', 1, '_bx_shopify_form_entry_display_view'),
+
+('bx_shopify_settings', 'bx_shopify_settings_edit', 'bx_shopify', 0, '_bx_shopify_form_settings_display_edit');
+
+INSERT INTO `sys_form_inputs`(`object`, `module`, `name`, `value`, `values`, `checked`, `type`, `caption_system`, `caption`, `info`, `required`, `collapsed`, `html`, `attrs`, `attrs_tr`, `attrs_wrapper`, `checker_func`, `checker_params`, `checker_error`, `db_pass`, `db_params`, `editable`, `deletable`) VALUES 
+('bx_shopify', 'bx_shopify', '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_shopify', 'bx_shopify', 'allow_view_to', '', '', 0, 'custom', '_bx_shopify_form_entry_input_sys_allow_view_to', '_bx_shopify_form_entry_input_allow_view_to', '', 1, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_shopify', 'bx_shopify', 'delete_confirm', 1, '', 0, 'checkbox', '_bx_shopify_form_entry_input_sys_delete_confirm', '_bx_shopify_form_entry_input_delete_confirm', '_bx_shopify_form_entry_input_delete_confirm_info', 1, 0, 0, '', '', '', 'Avail', '', '_bx_shopify_form_entry_input_delete_confirm_error', '', '', 1, 0),
+('bx_shopify', 'bx_shopify', 'do_publish', '_bx_shopify_form_entry_input_do_publish', '', 0, 'submit', '_bx_shopify_form_entry_input_sys_do_publish', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_shopify', 'bx_shopify', 'do_submit', '_bx_shopify_form_entry_input_do_submit', '', 0, 'submit', '_bx_shopify_form_entry_input_sys_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_shopify', 'bx_shopify', 'location', '', '', 0, 'location', '_sys_form_input_sys_location', '_sys_form_input_location', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_shopify', 'bx_shopify', 'title', '', '', 0, 'text', '_bx_shopify_form_entry_input_sys_title', '_bx_shopify_form_entry_input_title', '', 1, 0, 0, '', '', '', 'Avail', '', '_bx_shopify_form_entry_input_title_err', 'Xss', '', 1, 0),
+('bx_shopify', 'bx_shopify', 'code', '', '', 0, 'text', '_bx_shopify_form_entry_input_sys_code', '_bx_shopify_form_entry_input_code', '_bx_shopify_form_entry_input_code_inf', 1, 0, 0, '', '', '', 'Avail', '', '_bx_shopify_form_entry_input_code_err', 'Xss', '', 1, 0),
+('bx_shopify', 'bx_shopify', 'cat', '', '#!bx_shopify_cats', 0, 'select', '_bx_shopify_form_entry_input_sys_cat', '_bx_shopify_form_entry_input_cat', '', 1, 0, 0, '', '', '', 'Avail', '', '_bx_shopify_form_entry_input_cat_err', 'Xss', '', 1, 0),
+('bx_shopify', 'bx_shopify', 'added', '', '', 0, 'datetime', '_bx_shopify_form_entry_input_sys_date_added', '_bx_shopify_form_entry_input_date_added', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_shopify', 'bx_shopify', 'changed', '', '', 0, 'datetime', '_bx_shopify_form_entry_input_sys_date_changed', '_bx_shopify_form_entry_input_date_changed', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+
+('bx_shopify_settings', 'bx_shopify', 'domain', '', '', 0, 'text', '_bx_shopify_form_settings_input_sys_domain', '_bx_shopify_form_settings_input_domain', '', 1, 0, 0, '', '', '', 'Avail', '', '_bx_shopify_form_settings_input_domain_err', 'Xss', '', 1, 0),
+('bx_shopify_settings', 'bx_shopify', 'access_token', '', '', 0, 'text', '_bx_shopify_form_settings_input_sys_access_token', '_bx_shopify_form_settings_input_access_token', '', 1, 0, 0, '', '', '', 'Avail', '', '_bx_shopify_form_settings_input_access_token_err', 'Xss', '', 1, 0),
+('bx_shopify_settings', 'bx_shopify', 'do_submit', '_bx_shopify_form_settings_input_do_submit', '', 0, 'submit', '_bx_shopify_form_settings_input_sys_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0);
+
+INSERT INTO `sys_form_display_inputs`(`display_name`, `input_name`, `visible_for_levels`, `active`, `order`) VALUES 
+('bx_shopify_entry_add', 'code', 2147483647, 1, 1),
+('bx_shopify_entry_add', 'title', 2147483647, 1, 2),
+('bx_shopify_entry_add', 'cat', 2147483647, 1, 3),
+('bx_shopify_entry_add', 'allow_view_to', 2147483647, 1, 4),
+('bx_shopify_entry_add', 'cf', 2147483647, 1, 5),
+('bx_shopify_entry_add', 'location', 2147483647, 1, 6),
+('bx_shopify_entry_add', 'do_publish', 2147483647, 1, 7),
+
+('bx_shopify_entry_delete', 'delete_confirm', 2147483647, 1, 1),
+('bx_shopify_entry_delete', 'do_submit', 2147483647, 1, 2),
+
+('bx_shopify_entry_edit', 'code', 2147483647, 1, 1),
+('bx_shopify_entry_edit', 'title', 2147483647, 1, 2),
+('bx_shopify_entry_edit', 'cat', 2147483647, 1, 3),
+('bx_shopify_entry_edit', 'allow_view_to', 2147483647, 1, 4),
+('bx_shopify_entry_edit', 'cf', 2147483647, 1, 5),
+('bx_shopify_entry_edit', 'location', 2147483647, 1, 6),
+('bx_shopify_entry_edit', 'do_submit', 2147483647, 1, 7),
+
+('bx_shopify_entry_view', 'cat', 2147483647, 1, 1),
+('bx_shopify_entry_view', 'added', 2147483647, 1, 2),
+('bx_shopify_entry_view', 'changed', 2147483647, 1, 3),
+
+('bx_shopify_entry_view_full', 'cat', 2147483647, 1, 1),
+('bx_shopify_entry_view_full', 'added', 2147483647, 1, 2),
+('bx_shopify_entry_view_full', 'changed', 2147483647, 1, 3),
+
+('bx_shopify_settings_edit', 'mode', 2147483647, 1, 1),
+('bx_shopify_settings_edit', 'domain', 2147483647, 1, 2),
+('bx_shopify_settings_edit', 'access_token', 2147483647, 1, 3),
+('bx_shopify_settings_edit', 'do_submit', 2147483647, 1, 4);
+
+
+-- PRE-VALUES
+INSERT INTO `sys_form_pre_lists`(`key`, `title`, `module`, `use_for_sets`, `extendable`) VALUES
+('bx_shopify_cats', '_bx_shopify_pre_lists_cats', 'bx_shopify', '0', '1');
+
+INSERT INTO `sys_form_pre_values`(`Key`, `Value`, `Order`, `LKey`, `LKey2`) VALUES
+('bx_shopify_cats', '', 0, '_sys_please_select', ''),
+('bx_shopify_cats', '1', 1, '_bx_shopify_cat_automotive_and_industrial', ''),
+('bx_shopify_cats', '2', 2, '_bx_shopify_cat_beauty_health_food', ''),
+('bx_shopify_cats', '3', 3, '_bx_shopify_cat_books', ''),
+('bx_shopify_cats', '4', 4, '_bx_shopify_cat_clothing_shoes_jewelry', ''),
+('bx_shopify_cats', '5', 5, '_bx_shopify_cat_electronics_and_computers', ''),
+('bx_shopify_cats', '6', 6, '_bx_shopify_cat_handmade', ''),
+('bx_shopify_cats', '7', 7, '_bx_shopify_cat_home_garden_tools', ''),
+('bx_shopify_cats', '8', 8, '_bx_shopify_cat_movies_music_games', ''),
+('bx_shopify_cats', '9', 9, '_bx_shopify_cat_sports_and_outdoors', ''),
+('bx_shopify_cats', '10', 10, '_bx_shopify_cat_toys_kids_baby', '');
+
+
+-- 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_shopify', 'bx_shopify', 'bx_shopify_cmts', 1, 5000, 1000, 3, 5, 3, 'tail', 1, 'bottom', 1, 1, 1, -3, 1, 'cmt', 'page.php?i=view-shopify-entry&id={object_id}', '', 'bx_shopify_entries', 'id', 'author', 'title', 'comments', '', ''),
+('bx_shopify_notes', 'bx_shopify', 'bx_shopify_cmts_notes', 1, 5000, 1000, 0, 5, 3, 'tail', 1, 'bottom', 1, 1, 1, -3, 1, 'cmt', 'page.php?i=view-shopify-entry&id={object_id}', '', 'bx_shopify_entries', 'id', 'author', 'title', '', 'BxTemplCmtsNotes', '');
+
+
+-- VOTES
+INSERT INTO `sys_objects_vote` (`Name`, `Module`, `TableMain`, `TableTrack`, `PostTimeout`, `MinValue`, `MaxValue`, `IsUndo`, `IsOn`, `TriggerTable`, `TriggerFieldId`, `TriggerFieldAuthor`, `TriggerFieldRate`, `TriggerFieldRateCount`, `ClassName`, `ClassFile`) VALUES 
+('bx_shopify', 'bx_shopify', 'bx_shopify_votes', 'bx_shopify_votes_track', '604800', '1', '1', '0', '1', 'bx_shopify_entries', 'id', 'author', 'rate', 'votes', '', ''),
+('bx_shopify_reactions', 'bx_shopify', 'bx_shopify_reactions', 'bx_shopify_reactions_track', '604800', '1', '1', '1', '1', 'bx_shopify_entries', 'id', 'author', 'rrate', 'rvotes', 'BxTemplVoteReactions', '');
+
+
+-- SCORES
+INSERT INTO `sys_objects_score` (`name`, `module`, `table_main`, `table_track`, `post_timeout`, `is_on`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_score`, `trigger_field_cup`, `trigger_field_cdown`, `class_name`, `class_file`) VALUES 
+('bx_shopify', 'bx_shopify', 'bx_shopify_scores', 'bx_shopify_scores_track', '604800', '0', 'bx_shopify_entries', 'id', 'author', 'score', 'sc_up', 'sc_down', '', '');
+
+
+-- REPORTS
+INSERT INTO `sys_objects_report` (`name`, `module`, `table_main`, `table_track`, `is_on`, `base_url`, `object_comment`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_count`, `class_name`, `class_file`) VALUES 
+('bx_shopify', 'bx_shopify', 'bx_shopify_reports', 'bx_shopify_reports_track', '1', 'page.php?i=view-shopify-entry&id={object_id}', 'bx_shopify_notes', 'bx_shopify_entries', 'id', 'author', 'reports', '', '');
+
+
+-- 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_shopify', 'bx_shopify', 'bx_shopify_views_track', '86400', '1', 'bx_shopify_entries', 'id', 'author', 'views', '', '');
+
+
+-- FAFORITES
+INSERT INTO `sys_objects_favorite` (`name`, `table_track`, `is_on`, `is_undo`, `is_public`, `base_url`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_count`, `class_name`, `class_file`) VALUES 
+('bx_shopify', 'bx_shopify_favorites_track', '1', '1', '1', 'page.php?i=view-shopify-entry&id={object_id}', 'bx_shopify_entries', 'id', 'author', 'favorites', '', '');
+
+
+-- FEATURED
+INSERT INTO `sys_objects_feature` (`name`, `module`, `is_on`, `is_undo`, `base_url`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_flag`, `class_name`, `class_file`) VALUES 
+('bx_shopify', 'bx_shopify', '1', '1', 'page.php?i=view-shopify-entry&id={object_id}', 'bx_shopify_entries', 'id', 'author', 'featured', '', '');
+
+
+-- CONTENT INFO
+INSERT INTO `sys_objects_content_info` (`name`, `title`, `alert_unit`, `alert_action_add`, `alert_action_update`, `alert_action_delete`, `class_name`, `class_file`) VALUES
+('bx_shopify', '_bx_shopify', 'bx_shopify', 'added', 'edited', 'deleted', '', ''),
+('bx_shopify_cmts', '_bx_shopify_cmts', 'bx_shopify', 'commentPost', 'commentUpdated', 'commentRemoved', 'BxDolContentInfoCmts', '');
+
+INSERT INTO `sys_content_info_grids` (`object`, `grid_object`, `grid_field_id`, `condition`, `selection`) VALUES
+('bx_shopify', 'bx_shopify_administration', 'id', '', ''),
+('bx_shopify', 'bx_shopify_common', 'id', '', '');
+
+
+-- SEARCH EXTENDED
+INSERT INTO `sys_objects_search_extended` (`object`, `object_content_info`, `module`, `title`, `active`, `class_name`, `class_file`) VALUES
+('bx_shopify', 'bx_shopify', 'bx_shopify', '_bx_shopify_search_extended', 1, '', ''),
+('bx_shopify_cmts', 'bx_shopify_cmts', 'bx_shopify', '_bx_shopify_search_extended_cmts', 1, 'BxTemplSearchExtendedCmts', '');
+
+
+-- STUDIO: page & widget
+INSERT INTO `sys_std_pages`(`index`, `name`, `header`, `caption`, `icon`) VALUES
+(3, 'bx_shopify', '_bx_shopify', '_bx_shopify', 'bx_shopify@modules/boonex/shopify/|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_shopify', 'integrations', '{url_studio}module.php?name=bx_shopify', '', 'bx_shopify@modules/boonex/shopify/|std-icon.svg', '_bx_shopify', '', '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/snipcart/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' => 'Snipcart',
+    'version_from' => '13.0.3',
+    'version_to' => '13.0.4',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '13.1.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/snipcart/updates/update_13.0.3_13.0.4/',
+    'home_uri' => 'snipcart_update_1303_1304',
+
+    'module_dir' => 'boonex/snipcart/',
+    'module_uri' => 'snipcart',
+
+    'db_prefix' => 'bx_snipcart_',
+    'class_prefix' => 'BxSnipcart',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_files' => 1,
+        'update_languages' => 0,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Snipcart',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

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

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

@@ -0,0 +1,10 @@
+-- STORAGES & TRANSCODERS
+UPDATE `sys_transcoder_filters` SET `filter_params`='a:1:{s:1:"w";s:4:"1200";}' WHERE `transcoder_object`='bx_snipcart_cover';
+
+
+-- VOTES
+UPDATE `sys_objects_vote` SET `Module`='bx_snipcart' WHERE `Name` IN ('bx_snipcart', 'bx_snipcart_reactions');
+
+
+-- VIEWS
+UPDATE `sys_objects_view` SET `module`='bx_snipcart' WHERE `name`='bx_snipcart';

+ 136 - 0
modules/boonex/snipcart/updates/13.0.3_13.0.4/source/install/config.php

@@ -0,0 +1,136 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Snipcart Snipcart
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_snipcart',
+    'title' => 'Snipcart',
+    'note' => 'Snipcart shopping module.',
+    'version' => '13.0.4',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '13.1.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/snipcart/',
+    'home_uri' => 'snipcart',
+
+    'db_prefix' => 'bx_snipcart_',
+    'class_prefix' => 'BxSnipcart',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Snipcart',
+
+    /**
+     * List of page triggers.
+     */
+    'page_triggers' => array (
+    	'trigger_page_profile_view_entry',
+    ),
+    
+    /**
+     * Menu triggers.
+     */
+    'menu_triggers' => array(
+    	'trigger_profile_view_submenu',
+        'trigger_group_view_submenu'
+    ),
+
+	/**
+     * Storage objects to automatically delete files from upon module uninstallation.
+     * Note. Don't add storage objects used in transcoder objects.
+     */
+    'storages' => array(
+    	'bx_snipcart_files'
+    ),
+
+    /**
+     * Transcoders.
+     */
+    'transcoders' => array(
+		'bx_snipcart_preview',
+        'bx_snipcart_gallery',
+        'bx_snipcart_cover'
+    ),
+
+    /**
+     * Extended Search Forms.
+     */
+    'esearches' => array(
+        'bx_snipcart',
+    	'bx_snipcart_cmts',
+    ),
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'uninstall' => array (
+    	'process_esearches' => 1,
+        'execute_sql' => 1,
+        'update_languages' => 1,
+    	'update_relations' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'enable' => array(
+        'execute_sql' => 1,
+    	'update_relations' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'enable_success' => array(
+        'process_menu_triggers' => 1,
+        'process_page_triggers' => 1,
+    	'process_esearches' => 1,
+    	'register_transcoders' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable' => array (
+        'execute_sql' => 1,
+    	'update_relations' => 1,
+    	'unregister_transcoders' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable_failed' => array (
+    	'register_transcoders' => 1,
+    	'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Dependencies Section
+     */
+    'dependencies' => array(),
+
+    /**
+     * Relations Section
+     */
+    'relations' => array(
+    	'bx_timeline',
+    	'bx_notifications'
+    ),
+
+);
+
+/** @} */

+ 450 - 0
modules/boonex/snipcart/updates/13.0.3_13.0.4/source/install/sql/install.sql

@@ -0,0 +1,450 @@
+-- TABLE: entries
+CREATE TABLE IF NOT EXISTS `bx_snipcart_entries` (
+  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+  `author` int(10) unsigned NOT NULL,
+  `added` int(11) NOT NULL,
+  `changed` int(11) NOT NULL,
+  `thumb` int(11) NOT NULL,
+  `title` varchar(255) NOT NULL,
+  `cat` int(11) NOT NULL,
+  `text` text NOT NULL,
+  `price` float NOT NULL default '0',
+  `weight` float NOT NULL default '0',
+  `location` text NOT NULL,
+  `views` int(11) NOT NULL default '0',
+  `rate` float NOT NULL default '0',
+  `votes` int(11) NOT NULL default '0',
+  `rrate` float NOT NULL default '0',
+  `rvotes` int(11) NOT NULL default '0',
+  `score` int(11) NOT NULL default '0',
+  `sc_up` int(11) NOT NULL default '0',
+  `sc_down` int(11) NOT NULL default '0',
+  `favorites` int(11) NOT NULL default '0',
+  `comments` int(11) NOT NULL default '0',
+  `reports` int(11) NOT NULL default '0',
+  `featured` int(11) NOT NULL default '0',
+  `cf` int(11) NOT NULL default '1',
+  `allow_view_to` varchar(16) NOT NULL DEFAULT '3',
+  `status` enum('active','hidden') NOT NULL DEFAULT 'active',
+  `status_admin` enum('active','hidden','pending') NOT NULL DEFAULT 'active',
+  PRIMARY KEY (`id`),
+  FULLTEXT KEY `title_text` (`title`,`text`)
+);
+
+-- TABLE: settings
+CREATE TABLE IF NOT EXISTS `bx_snipcart_settings` (
+  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+  `author` int(10) unsigned NOT NULL,
+  `mode` varchar(8) NOT NULL DEFAULT '',
+  `api_key_test` varchar(255) NOT NULL DEFAULT '',
+  `api_key_live` varchar(255) NOT NULL DEFAULT '',
+  `currency` varchar(4) NOT NULL DEFAULT '',
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `author` (`author`)
+);
+
+-- TABLE: storages & transcoders
+CREATE TABLE IF NOT EXISTS `bx_snipcart_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_snipcart_photos_resized` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `profile_id` int(10) unsigned NOT NULL,
+  `remote_id` varchar(128) NOT NULL,
+  `path` varchar(255) NOT NULL,
+  `file_name` varchar(255) NOT NULL,
+  `mime_type` varchar(128) NOT NULL,
+  `ext` varchar(32) NOT NULL,
+  `size` bigint(20) NOT NULL,
+  `added` int(11) NOT NULL,
+  `modified` int(11) NOT NULL,
+  `private` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `remote_id` (`remote_id`)
+);
+
+-- TABLE: comments
+CREATE TABLE IF NOT EXISTS `bx_snipcart_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_snipcart_cmts_notes` (
+  `cmt_id` int(11) NOT NULL AUTO_INCREMENT,
+  `cmt_parent_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_vparent_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_object_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_author_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_level` int(11) NOT NULL DEFAULT '0',
+  `cmt_text` text NOT NULL,
+  `cmt_mood` tinyint(4) NOT NULL DEFAULT '0',
+  `cmt_rate` int(11) NOT NULL DEFAULT '0',
+  `cmt_rate_count` int(11) NOT NULL DEFAULT '0',
+  `cmt_time` int(11) unsigned NOT NULL DEFAULT '0',
+  `cmt_replies` int(11) NOT NULL DEFAULT '0',
+  `cmt_pinned` int(11) NOT NULL default '0',
+  PRIMARY KEY (`cmt_id`),
+  KEY `cmt_object_id` (`cmt_object_id`,`cmt_parent_id`),
+  FULLTEXT KEY `search_fields` (`cmt_text`)
+);
+
+-- TABLE: votes
+CREATE TABLE IF NOT EXISTS `bx_snipcart_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_snipcart_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_snipcart_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_snipcart_reactions_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `author_nip` int(11) unsigned NOT NULL default '0',
+  `reaction` varchar(32) NOT NULL default '',
+  `value` tinyint(4) NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `vote` (`object_id`, `author_nip`)
+);
+
+-- TABLE: views
+CREATE TABLE IF NOT EXISTS `bx_snipcart_views_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `viewer_id` int(11) NOT NULL default '0',
+  `viewer_nip` int(11) unsigned NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `id` (`object_id`,`viewer_id`,`viewer_nip`)
+);
+
+-- TABLE: metas
+CREATE TABLE IF NOT EXISTS `bx_snipcart_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_snipcart_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_snipcart_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_snipcart_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_snipcart_reports_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `author_nip` int(11) unsigned NOT NULL default '0',
+  `type` varchar(32) NOT NULL default '',
+  `text` text NOT NULL default '',
+  `date` int(11) NOT NULL default '0',
+  `checked_by` int(11) NOT NULL default '0',
+  `status` tinyint(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `report` (`object_id`, `author_nip`)
+);
+
+-- TABLE: favorites
+CREATE TABLE IF NOT EXISTS `bx_snipcart_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',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `id` (`object_id`,`author_id`)
+);
+
+-- TABLE: scores
+CREATE TABLE IF NOT EXISTS `bx_snipcart_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_snipcart_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
+SET @sStorageEngine = (SELECT `value` FROM `sys_options` WHERE `name` = 'sys_storage_default');
+
+INSERT INTO `sys_objects_storage` (`object`, `engine`, `params`, `token_life`, `cache_control`, `levels`, `table_files`, `ext_mode`, `ext_allow`, `ext_deny`, `quota_size`, `current_size`, `quota_number`, `current_number`, `max_file_size`, `ts`) VALUES
+('bx_snipcart_files', @sStorageEngine, '', 360, 2592000, 3, 'bx_snipcart_files', 'allow-deny', '{image}', '', 0, 0, 0, 0, 0, 0),
+('bx_snipcart_photos_resized', @sStorageEngine, '', 360, 2592000, 3, 'bx_snipcart_photos_resized', 'allow-deny', '{image}', '', 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_snipcart_preview', 'bx_snipcart_photos_resized', 'Storage', 'a:1:{s:6:"object";s:17:"bx_snipcart_files";}', 'no', '1', '2592000', '0'),
+('bx_snipcart_gallery', 'bx_snipcart_photos_resized', 'Storage', 'a:1:{s:6:"object";s:17:"bx_snipcart_files";}', 'no', '1', '2592000', '0'), 
+('bx_snipcart_cover', 'bx_snipcart_photos_resized', 'Storage', 'a:1:{s:6:"object";s:17:"bx_snipcart_files";}', 'no', '1', '2592000', '0');
+
+INSERT INTO `sys_transcoder_filters` (`transcoder_object`, `filter`, `filter_params`, `order`) VALUES 
+('bx_snipcart_preview', 'Resize', 'a:3:{s:1:"w";s:3:"300";s:1:"h";s:3:"200";s:11:"crop_resize";s:1:"1";}', '0'),
+('bx_snipcart_gallery', 'Resize', 'a:1:{s:1:"w";s:3:"500";}', '0'),
+('bx_snipcart_cover', 'Resize', 'a:1:{s:1:"w";s:4:"1200";}', '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_snipcart', 'bx_snipcart', '_bx_snipcart_form_entry', '', 'a:1:{s:7:"enctype";s:19:"multipart/form-data";}', 'bx_snipcart_entries', 'id', '', '', 'a:2:{i:0;s:9:"do_submit";i:1;s:10:"do_publish";}', '', 0, 1, 'BxSnipcartFormEntry', 'modules/boonex/snipcart/classes/BxSnipcartFormEntry.php'),
+('bx_snipcart_settings', 'bx_snipcart', '_bx_snipcart_form_settings', '', 'a:1:{s:7:"enctype";s:19:"multipart/form-data";}', 'bx_snipcart_settings', 'id', '', '', 'do_submit', '', 0, 1, 'BxSnipcartFormSettings', 'modules/boonex/snipcart/classes/BxSnipcartFormSettings.php');
+
+INSERT INTO `sys_form_displays`(`object`, `display_name`, `module`, `view_mode`, `title`) VALUES 
+('bx_snipcart', 'bx_snipcart_entry_add', 'bx_snipcart', 0, '_bx_snipcart_form_entry_display_add'),
+('bx_snipcart', 'bx_snipcart_entry_delete', 'bx_snipcart', 0, '_bx_snipcart_form_entry_display_delete'),
+('bx_snipcart', 'bx_snipcart_entry_edit', 'bx_snipcart', 0, '_bx_snipcart_form_entry_display_edit'),
+('bx_snipcart', 'bx_snipcart_entry_view', 'bx_snipcart', 1, '_bx_snipcart_form_entry_display_view'),
+
+('bx_snipcart_settings', 'bx_snipcart_settings_edit', 'bx_snipcart', 0, '_bx_snipcart_form_settings_display_edit');
+
+INSERT INTO `sys_form_inputs`(`object`, `module`, `name`, `value`, `values`, `checked`, `type`, `caption_system`, `caption`, `info`, `required`, `collapsed`, `html`, `attrs`, `attrs_tr`, `attrs_wrapper`, `checker_func`, `checker_params`, `checker_error`, `db_pass`, `db_params`, `editable`, `deletable`) VALUES 
+('bx_snipcart', 'bx_snipcart', '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_snipcart', 'bx_snipcart', 'allow_view_to', '', '', 0, 'custom', '_bx_snipcart_form_entry_input_sys_allow_view_to', '_bx_snipcart_form_entry_input_allow_view_to', '', 1, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_snipcart', 'bx_snipcart', 'delete_confirm', 1, '', 0, 'checkbox', '_bx_snipcart_form_entry_input_sys_delete_confirm', '_bx_snipcart_form_entry_input_delete_confirm', '_bx_snipcart_form_entry_input_delete_confirm_info', 1, 0, 0, '', '', '', 'Avail', '', '_bx_snipcart_form_entry_input_delete_confirm_error', '', '', 1, 0),
+('bx_snipcart', 'bx_snipcart', 'do_publish', '_bx_snipcart_form_entry_input_do_publish', '', 0, 'submit', '_bx_snipcart_form_entry_input_sys_do_publish', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_snipcart', 'bx_snipcart', 'do_submit', '_bx_snipcart_form_entry_input_do_submit', '', 0, 'submit', '_bx_snipcart_form_entry_input_sys_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_snipcart', 'bx_snipcart', 'location', '', '', 0, 'location', '_sys_form_input_sys_location', '_sys_form_input_location', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_snipcart', 'bx_snipcart', 'pictures', 'a:1:{i:0;s:9:"sys_html5";}', 'a:1:{s:9:"sys_html5";s:25:"_sys_uploader_html5_title";}', 0, 'files', '_bx_snipcart_form_entry_input_sys_pictures', '_bx_snipcart_form_entry_input_pictures', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_snipcart', 'bx_snipcart', 'text', '', '', 0, 'textarea', '_bx_snipcart_form_entry_input_sys_text', '_bx_snipcart_form_entry_input_text', '', 1, 0, 2, '', '', '', 'Avail', '', '_bx_snipcart_form_entry_input_text_err', 'XssHtml', '', 1, 0),
+('bx_snipcart', 'bx_snipcart', 'title', '', '', 0, 'text', '_bx_snipcart_form_entry_input_sys_title', '_bx_snipcart_form_entry_input_title', '', 1, 0, 0, '', '', '', 'Avail', '', '_bx_snipcart_form_entry_input_title_err', 'Xss', '', 1, 0),
+('bx_snipcart', 'bx_snipcart', 'cat', '', '#!bx_snipcart_cats', 0, 'select', '_bx_snipcart_form_entry_input_sys_cat', '_bx_snipcart_form_entry_input_cat', '', 1, 0, 0, '', '', '', 'Avail', '', '_bx_snipcart_form_entry_input_cat_err', 'Xss', '', 1, 0),
+('bx_snipcart', 'bx_snipcart', 'price', '', '', 0, 'price', '_bx_snipcart_form_entry_input_sys_price', '_bx_snipcart_form_entry_input_price', '_bx_snipcart_form_entry_input_price_inf', 1, 0, 0, '', '', '', 'Avail', '', '_bx_snipcart_form_entry_input_price_err', 'Float', '', 1, 0),
+('bx_snipcart', 'bx_snipcart', 'weight', '', '', 0, 'text', '_bx_snipcart_form_entry_input_sys_weight', '_bx_snipcart_form_entry_input_weight', '_bx_snipcart_form_entry_input_weight_inf', 1, 0, 0, '', '', '', 'Avail', '', '_bx_snipcart_form_entry_input_weight_err', 'Float', '', 1, 0),
+('bx_snipcart', 'bx_snipcart', 'added', '', '', 0, 'datetime', '_bx_snipcart_form_entry_input_sys_date_added', '_bx_snipcart_form_entry_input_date_added', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_snipcart', 'bx_snipcart', 'changed', '', '', 0, 'datetime', '_bx_snipcart_form_entry_input_sys_date_changed', '_bx_snipcart_form_entry_input_date_changed', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+
+('bx_snipcart_settings', 'bx_snipcart', 'mode', '', '#!bx_snipcart_modes', 0, 'select', '_bx_snipcart_form_settings_input_sys_mode', '_bx_snipcart_form_settings_input_mode', '', 1, 0, 0, '', '', '', 'Avail', '', '_bx_snipcart_form_settings_input_mode_err', 'Xss', '', 0, 0),
+('bx_snipcart_settings', 'bx_snipcart', 'api_key_test', '', '', 0, 'text', '_bx_snipcart_form_settings_input_sys_api_key_test', '_bx_snipcart_form_settings_input_api_key_test', '', 0, 0, 0, '', '', '', '', '', '', 'Xss', '', 1, 0),
+('bx_snipcart_settings', 'bx_snipcart', 'api_key_live', '', '', 0, 'text', '_bx_snipcart_form_settings_input_sys_api_key_live', '_bx_snipcart_form_settings_input_api_key_live', '', 0, 0, 0, '', '', '', '', '', '', 'Xss', '', 1, 0),
+('bx_snipcart_settings', 'bx_snipcart', 'currency', '', '#!bx_snipcart_currencies', 0, 'select', '_bx_snipcart_form_settings_input_sys_currency', '_bx_snipcart_form_settings_input_currency', '_bx_snipcart_form_settings_input_currency_inf', 1, 0, 0, '', '', '', 'Avail', '', '_bx_snipcart_form_settings_input_currency_err', 'Xss', '', 1, 0),
+('bx_snipcart_settings', 'bx_snipcart', 'do_submit', '_bx_snipcart_form_settings_input_do_submit', '', 0, 'submit', '_bx_snipcart_form_settings_input_sys_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0);
+
+INSERT INTO `sys_form_display_inputs`(`display_name`, `input_name`, `visible_for_levels`, `active`, `order`) VALUES 
+('bx_snipcart_entry_add', 'title', 2147483647, 1, 1),
+('bx_snipcart_entry_add', 'cat', 2147483647, 1, 2),
+('bx_snipcart_entry_add', 'text', 2147483647, 1, 3),
+('bx_snipcart_entry_add', 'price', 2147483647, 1, 4),
+('bx_snipcart_entry_add', 'weight', 2147483647, 1, 5),
+('bx_snipcart_entry_add', 'pictures', 2147483647, 1, 6),
+('bx_snipcart_entry_add', 'allow_view_to', 2147483647, 1, 7),
+('bx_snipcart_entry_add', 'cf', 2147483647, 1, 8),
+('bx_snipcart_entry_add', 'location', 2147483647, 1, 9),
+('bx_snipcart_entry_add', 'do_publish', 2147483647, 1, 10),
+
+('bx_snipcart_entry_delete', 'delete_confirm', 2147483647, 1, 1),
+('bx_snipcart_entry_delete', 'do_submit', 2147483647, 1, 2),
+
+('bx_snipcart_entry_edit', 'title', 2147483647, 1, 1),
+('bx_snipcart_entry_edit', 'cat', 2147483647, 1, 2),
+('bx_snipcart_entry_edit', 'text', 2147483647, 1, 3),
+('bx_snipcart_entry_edit', 'price', 2147483647, 1, 4),
+('bx_snipcart_entry_edit', 'weight', 2147483647, 1, 5),
+('bx_snipcart_entry_edit', 'pictures', 2147483647, 1, 6),
+('bx_snipcart_entry_edit', 'allow_view_to', 2147483647, 1, 7),
+('bx_snipcart_entry_edit', 'cf', 2147483647, 1, 8),
+('bx_snipcart_entry_edit', 'location', 2147483647, 1, 9),
+('bx_snipcart_entry_edit', 'do_submit', 2147483647, 1, 10),
+
+('bx_snipcart_entry_view', 'cat', 2147483647, 1, 1),
+('bx_snipcart_entry_view', 'weight', 2147483647, 1, 2),
+('bx_snipcart_entry_view', 'added', 2147483647, 1, 3),
+('bx_snipcart_entry_view', 'changed', 2147483647, 1, 4),
+
+('bx_snipcart_entry_view_full', 'cat', 2147483647, 1, 1),
+('bx_snipcart_entry_view_full', 'text', 2147483647, 1, 2),
+('bx_snipcart_entry_view_full', 'weight', 2147483647, 1, 3),
+('bx_snipcart_entry_view_full', 'added', 2147483647, 1, 4),
+('bx_snipcart_entry_view_full', 'changed', 2147483647, 1, 5),
+
+('bx_snipcart_settings_edit', 'mode', 2147483647, 1, 1),
+('bx_snipcart_settings_edit', 'api_key_test', 2147483647, 1, 2),
+('bx_snipcart_settings_edit', 'api_key_live', 2147483647, 1, 3),
+('bx_snipcart_settings_edit', 'currency', 2147483647, 1, 4),
+('bx_snipcart_settings_edit', 'do_submit', 2147483647, 1, 5);
+
+
+-- PRE-VALUES
+INSERT INTO `sys_form_pre_lists`(`key`, `title`, `module`, `use_for_sets`, `extendable`) VALUES
+('bx_snipcart_cats', '_bx_snipcart_pre_lists_cats', 'bx_snipcart', '0', '1'),
+('bx_snipcart_modes', '_bx_snipcart_pre_lists_modes', 'bx_snipcart', '0', '0'),
+('bx_snipcart_currencies', '_bx_snipcart_pre_lists_currencies', 'bx_snipcart', '0', '0');
+
+INSERT INTO `sys_form_pre_values`(`Key`, `Value`, `Order`, `LKey`, `LKey2`) VALUES
+('bx_snipcart_cats', '', 0, '_sys_please_select', ''),
+('bx_snipcart_cats', '1', 1, '_bx_snipcart_cat_automotive_and_industrial', ''),
+('bx_snipcart_cats', '2', 2, '_bx_snipcart_cat_beauty_health_food', ''),
+('bx_snipcart_cats', '3', 3, '_bx_snipcart_cat_books', ''),
+('bx_snipcart_cats', '4', 4, '_bx_snipcart_cat_clothing_shoes_jewelry', ''),
+('bx_snipcart_cats', '5', 5, '_bx_snipcart_cat_electronics_and_computers', ''),
+('bx_snipcart_cats', '6', 6, '_bx_snipcart_cat_handmade', ''),
+('bx_snipcart_cats', '7', 7, '_bx_snipcart_cat_home_garden_tools', ''),
+('bx_snipcart_cats', '8', 8, '_bx_snipcart_cat_movies_music_games', ''),
+('bx_snipcart_cats', '9', 9, '_bx_snipcart_cat_sports_and_outdoors', ''),
+('bx_snipcart_cats', '10', 10, '_bx_snipcart_cat_toys_kids_baby', ''),
+
+('bx_snipcart_modes', '', 0, '_sys_please_select', ''),
+('bx_snipcart_modes', 'test', 1, '_bx_snipcart_mode_test', ''),
+('bx_snipcart_modes', 'live', 2, '_bx_snipcart_mode_live', ''),
+
+('bx_snipcart_currencies', '', 0, '_sys_please_select', ''),
+('bx_snipcart_currencies', 'CAD', 1, 'CAD', 'C&#36;'),
+('bx_snipcart_currencies', 'EUR', 2, 'EUR', '&#128;'),
+('bx_snipcart_currencies', 'USD', 3, 'USD', '&#36;');
+
+
+-- 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_snipcart', 'bx_snipcart', 'bx_snipcart_cmts', 1, 5000, 1000, 3, 5, 3, 'tail', 1, 'bottom', 1, 1, 1, -3, 1, 'cmt', 'page.php?i=view-snipcart-entry&id={object_id}', '', 'bx_snipcart_entries', 'id', 'author', 'title', 'comments', '', ''),
+('bx_snipcart_notes', 'bx_snipcart', 'bx_snipcart_cmts_notes', 1, 5000, 1000, 0, 5, 3, 'tail', 1, 'bottom', 1, 1, 1, -3, 1, 'cmt', 'page.php?i=view-snipcart-entry&id={object_id}', '', 'bx_snipcart_entries', 'id', 'author', 'title', '', 'BxTemplCmtsNotes', '');
+
+
+-- VOTES
+INSERT INTO `sys_objects_vote` (`Name`, `Module`, `TableMain`, `TableTrack`, `PostTimeout`, `MinValue`, `MaxValue`, `IsUndo`, `IsOn`, `TriggerTable`, `TriggerFieldId`, `TriggerFieldAuthor`, `TriggerFieldRate`, `TriggerFieldRateCount`, `ClassName`, `ClassFile`) VALUES 
+('bx_snipcart', 'bx_snipcart', 'bx_snipcart_votes', 'bx_snipcart_votes_track', '604800', '1', '1', '0', '1', 'bx_snipcart_entries', 'id', 'author', 'rate', 'votes', '', ''),
+('bx_snipcart_reactions', 'bx_snipcart', 'bx_snipcart_reactions', 'bx_snipcart_reactions_track', '604800', '1', '1', '1', '1', 'bx_snipcart_entries', 'id', 'author', 'rrate', 'rvotes', 'BxTemplVoteReactions', '');
+
+
+-- SCORES
+INSERT INTO `sys_objects_score` (`name`, `module`, `table_main`, `table_track`, `post_timeout`, `is_on`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_score`, `trigger_field_cup`, `trigger_field_cdown`, `class_name`, `class_file`) VALUES 
+('bx_snipcart', 'bx_snipcart', 'bx_snipcart_scores', 'bx_snipcart_scores_track', '604800', '0', 'bx_snipcart_entries', 'id', 'author', 'score', 'sc_up', 'sc_down', '', '');
+
+
+-- REPORTS
+INSERT INTO `sys_objects_report` (`name`, `module`, `table_main`, `table_track`, `is_on`, `base_url`, `object_comment`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_count`, `class_name`, `class_file`) VALUES 
+('bx_snipcart', 'bx_snipcart', 'bx_snipcart_reports', 'bx_snipcart_reports_track', '1', 'page.php?i=view-snipcart-entry&id={object_id}', 'bx_snipcart_notes', 'bx_snipcart_entries', 'id', 'author', 'reports', '', '');
+
+
+-- 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_snipcart', 'bx_snipcart', 'bx_snipcart_views_track', '86400', '1', 'bx_snipcart_entries', 'id', 'author', 'views', '', '');
+
+
+-- FAFORITES
+INSERT INTO `sys_objects_favorite` (`name`, `table_track`, `is_on`, `is_undo`, `is_public`, `base_url`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_count`, `class_name`, `class_file`) VALUES 
+('bx_snipcart', 'bx_snipcart_favorites_track', '1', '1', '1', 'page.php?i=view-snipcart-entry&id={object_id}', 'bx_snipcart_entries', 'id', 'author', 'favorites', '', '');
+
+
+-- FEATURED
+INSERT INTO `sys_objects_feature` (`name`, `module`, `is_on`, `is_undo`, `base_url`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_flag`, `class_name`, `class_file`) VALUES 
+('bx_snipcart', 'bx_snipcart', '1', '1', 'page.php?i=view-snipcart-entry&id={object_id}', 'bx_snipcart_entries', 'id', 'author', 'featured', '', '');
+
+
+-- CONTENT INFO
+INSERT INTO `sys_objects_content_info` (`name`, `title`, `alert_unit`, `alert_action_add`, `alert_action_update`, `alert_action_delete`, `class_name`, `class_file`) VALUES
+('bx_snipcart', '_bx_snipcart', 'bx_snipcart', 'added', 'edited', 'deleted', '', ''),
+('bx_snipcart_cmts', '_bx_snipcart_cmts', 'bx_snipcart', 'commentPost', 'commentUpdated', 'commentRemoved', 'BxDolContentInfoCmts', '');
+
+INSERT INTO `sys_content_info_grids` (`object`, `grid_object`, `grid_field_id`, `condition`, `selection`) VALUES
+('bx_snipcart', 'bx_snipcart_administration', 'id', '', ''),
+('bx_snipcart', 'bx_snipcart_common', 'id', '', '');
+
+
+-- SEARCH EXTENDED
+INSERT INTO `sys_objects_search_extended` (`object`, `object_content_info`, `module`, `title`, `active`, `class_name`, `class_file`) VALUES
+('bx_snipcart', 'bx_snipcart', 'bx_snipcart', '_bx_snipcart_search_extended', 1, '', ''),
+('bx_snipcart_cmts', 'bx_snipcart_cmts', 'bx_snipcart', '_bx_snipcart_search_extended_cmts', 1, 'BxTemplSearchExtendedCmts', '');
+
+
+-- STUDIO: page & widget
+INSERT INTO `sys_std_pages`(`index`, `name`, `header`, `caption`, `icon`) VALUES
+(3, 'bx_snipcart', '_bx_snipcart', '_bx_snipcart', 'bx_snipcart@modules/boonex/snipcart/|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_snipcart', 'integrations', '{url_studio}module.php?name=bx_snipcart', '', 'bx_snipcart@modules/boonex/snipcart/|std-icon.svg', '_bx_snipcart', '', '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/spaces/updates/13.0.7_13.0.8/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.7',
+    'version_to' => '13.0.8',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '13.1.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/spaces/updates/update_13.0.7_13.0.8/',
+    'home_uri' => 'spaces_update_1307_1308',
+
+    '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.7_13.0.8/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);
+    }
+}

+ 10 - 0
modules/boonex/spaces/updates/13.0.7_13.0.8/install/sql/install.sql

@@ -0,0 +1,10 @@
+-- STORAGES & TRANSCODERS
+UPDATE `sys_transcoder_filters` SET `filter_params`='a:1:{s:1:"w";s:4:"1200";}' WHERE `transcoder_object`='bx_spaces_cover';
+
+
+-- VIEWS
+UPDATE `sys_objects_view` SET `module`='bx_spaces' WHERE `name`='bx_spaces';
+
+
+-- VOTES
+UPDATE `sys_objects_vote` SET `Module`='bx_spaces' WHERE `Name`='bx_spaces';

+ 38 - 0
modules/boonex/spaces/updates/13.0.7_13.0.8/source/classes/BxSpacesMenuSnippetMeta.php

@@ -0,0 +1,38 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defdroup    Spaces Spaces
+ * @indroup     UnaModules
+ *
+ * @{
+ */
+
+class BxSpacesMenuSnippetMeta extends BxBaseModGroupsMenuSnippetMeta
+{
+    public function __construct($aObject, $oTemplate = false)
+    {
+        $this->_sModule = 'bx_spaces';
+
+        parent::__construct($aObject, $oTemplate);
+
+        unset($this->_aConnectionToFunctionCheck['sys_profiles_friends']);
+    }
+
+    protected function _getMenuItemParent($aItem)
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        if(empty($CNF['FIELD_PARENT']) || empty($this->_aContentInfo[$CNF['FIELD_PARENT']]))
+            return false;
+
+        $oParent = BxDolProfile::getInstance((int)$this->_aContentInfo[$CNF['FIELD_PARENT']]);
+        if(!$oParent)
+            return false;
+
+        return $this->getUnitMetaItemCustom($oParent->getUnit(0, ['template' => ['name' => 'unit_wo_cover', 'size' => 'icon']]));
+    }
+}
+
+/** @} */

+ 152 - 0
modules/boonex/spaces/updates/13.0.7_13.0.8/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.8',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '13.1.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/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',
+    ),
+);
+
+/** @} */

+ 514 - 0
modules/boonex/spaces/updates/13.0.7_13.0.8/source/install/sql/install.sql

@@ -0,0 +1,514 @@
+SET @sStorageEngine = (SELECT `value` FROM `sys_options` WHERE `name` = 'sys_storage_default');
+
+-- TABLE: PROFILES
+CREATE TABLE IF NOT EXISTS `bx_spaces_data` (
+  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+  `author` int(10) unsigned NOT NULL,
+  `parent_space` int(10) unsigned NOT NULL  default '0',
+  `level` int(10) unsigned NOT NULL  default '0',
+  `added` int(11) NOT NULL,
+  `changed` int(11) NOT NULL,
+  `picture` int(11) NOT NULL,
+  `cover` int(11) NOT NULL,
+  `cover_data` varchar(50) NOT NULL,
+  `space_name` varchar(255) NOT NULL,
+  `space_cat` int(11) NOT NULL,
+  `space_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',
+  `cf` int(11) NOT NULL default '1',
+  `join_confirmation` tinyint(4) NOT NULL DEFAULT '0',
+  `allow_view_to` varchar(16) NOT NULL DEFAULT '3',
+  `allow_post_to` varchar(16) NOT NULL DEFAULT '3',
+  `status` enum('active','awaiting','hidden') NOT NULL DEFAULT 'active',
+  `status_admin` enum('active','hidden','pending') NOT NULL DEFAULT 'active',
+  PRIMARY KEY (`id`),
+  FULLTEXT KEY `search_fields` (`space_name`, `space_desc`)
+);
+
+-- TABLE: STORAGES & TRANSCODERS
+CREATE TABLE `bx_spaces_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,
+  `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 `bx_spaces_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_spaces_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_spaces_cmts_notes` (
+  `cmt_id` int(11) NOT NULL AUTO_INCREMENT,
+  `cmt_parent_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_vparent_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_object_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_author_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_level` int(11) NOT NULL DEFAULT '0',
+  `cmt_text` text NOT NULL,
+  `cmt_mood` tinyint(4) NOT NULL DEFAULT '0',
+  `cmt_rate` int(11) NOT NULL DEFAULT '0',
+  `cmt_rate_count` int(11) NOT NULL DEFAULT '0',
+  `cmt_time` int(11) unsigned NOT NULL DEFAULT '0',
+  `cmt_replies` int(11) NOT NULL DEFAULT '0',
+  `cmt_pinned` int(11) NOT NULL default '0',
+  PRIMARY KEY (`cmt_id`),
+  KEY `cmt_object_id` (`cmt_object_id`,`cmt_parent_id`),
+  FULLTEXT KEY `search_fields` (`cmt_text`)
+);
+
+-- TABLE: VIEWS
+CREATE TABLE `bx_spaces_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_spaces_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_spaces_votes_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `author_nip` int(11) unsigned NOT NULL default '0',
+  `value` tinyint(4) NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `vote` (`object_id`, `author_nip`)
+);
+
+-- TABLE: REPORTS
+CREATE TABLE IF NOT EXISTS `bx_spaces_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_spaces_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 `bx_spaces_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_spaces_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_spaces_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: fans
+CREATE TABLE IF NOT EXISTS `bx_spaces_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_spaces_admins` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `group_profile_id` int(10) unsigned NOT NULL,
+  `fan_id` int(10) unsigned NOT NULL,
+  `role` int(10) unsigned NOT NULL default '0',
+  `order` varchar(32) NOT NULL default '',
+  `added` int(11) unsigned NOT NULL default '0',
+  `expired` int(11) unsigned NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `admin` (`group_profile_id`,`fan_id`)
+);
+
+-- TABLE: favorites
+CREATE TABLE `bx_spaces_favorites_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `list_id` int(11) NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `id` (`object_id`,`author_id`)
+);
+
+CREATE TABLE `bx_spaces_favorites_lists` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `title` varchar(255) NOT NULL,
+  `author_id` int(11) NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  `allow_view_favorite_list_to` varchar(16) NOT NULL DEFAULT '3',
+   PRIMARY KEY (`id`)
+);
+
+
+-- TABLE: scores
+CREATE TABLE IF NOT EXISTS `bx_spaces_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_spaces_scores_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `author_nip` int(11) unsigned NOT NULL default '0',
+  `type` varchar(8) NOT NULL default '',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `vote` (`object_id`, `author_nip`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_spaces_invites` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `key` varchar(128) NOT NULL default '0',
+  `group_profile_id` int(11) NOT NULL default '0',
+  `author_profile_id` int(11) NOT NULL default '0',
+  `invited_profile_id` int(11) NOT NULL default '0',
+  `added` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`)
+);
+
+-- TABLE: Pricing
+CREATE TABLE IF NOT EXISTS `bx_spaces_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_spaces_pics', @sStorageEngine, '', 360, 2592000, 3, 'bx_spaces_pics', 'allow-deny', '{image}', '', 0, 0, 0, 0, 0, 0),
+('bx_spaces_pics_resized', @sStorageEngine, '', 360, 2592000, 3, 'bx_spaces_pics_resized', 'allow-deny', '{image}', '', 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_spaces_icon', 'bx_spaces_pics_resized', 'Storage', 'a:1:{s:6:"object";s:14:"bx_spaces_pics";}', 'no', '1', '2592000', '0'),
+('bx_spaces_thumb', 'bx_spaces_pics_resized', 'Storage', 'a:1:{s:6:"object";s:14:"bx_spaces_pics";}', 'no', '1', '2592000', '0'),
+('bx_spaces_avatar', 'bx_spaces_pics_resized', 'Storage', 'a:1:{s:6:"object";s:14:"bx_spaces_pics";}', 'no', '1', '2592000', '0'),
+('bx_spaces_avatar_big', 'bx_spaces_pics_resized', 'Storage', 'a:1:{s:6:"object";s:14:"bx_spaces_pics";}', 'no', '1', '2592000', '0'),
+('bx_spaces_picture', 'bx_spaces_pics_resized', 'Storage', 'a:1:{s:6:"object";s:14:"bx_spaces_pics";}', 'no', '1', '2592000', '0'),
+('bx_spaces_cover', 'bx_spaces_pics_resized', 'Storage', 'a:1:{s:6:"object";s:14:"bx_spaces_pics";}', 'no', '1', '2592000', '0'),
+('bx_spaces_cover_thumb', 'bx_spaces_pics_resized', 'Storage', 'a:1:{s:6:"object";s:14:"bx_spaces_pics";}', 'no', '1', '2592000', '0'),
+('bx_spaces_gallery', 'bx_spaces_pics_resized', 'Storage', 'a:1:{s:6:"object";s:14:"bx_spaces_pics";}', 'no', '1', '2592000', '0');
+
+INSERT INTO `sys_transcoder_filters` (`transcoder_object`, `filter`, `filter_params`, `order`) VALUES 
+('bx_spaces_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_spaces_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_spaces_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_spaces_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_spaces_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_spaces_cover', 'Resize', 'a:1:{s:1:"w";s:4:"1200";}', '0'),
+('bx_spaces_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_spaces_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_space', 'bx_spaces', '_bx_spaces_form_profile', '', 'a:1:{s:7:\"enctype\";s:19:\"multipart/form-data\";}', 'bx_spaces_data', 'id', '', '', 'do_submit', '', 0, 1, 'BxSpacesFormEntry', 'modules/boonex/spaces/classes/BxSpacesFormEntry.php');
+
+INSERT INTO `sys_form_displays`(`object`, `display_name`, `module`, `view_mode`, `title`) VALUES 
+('bx_space', 'bx_space_add', 'bx_spaces', 0, '_bx_spaces_form_profile_display_add'),
+('bx_space', 'bx_space_delete', 'bx_spaces', 0, '_bx_spaces_form_profile_display_delete'),
+('bx_space', 'bx_space_edit', 'bx_spaces', 0, '_bx_spaces_form_profile_display_edit'),
+('bx_space', 'bx_space_edit_cover', 'bx_spaces', 0, '_bx_spaces_form_profile_display_edit_cover'),
+('bx_space', 'bx_space_view', 'bx_spaces', 1, '_bx_spaces_form_profile_display_view'),
+('bx_space', 'bx_space_view_full', 'bx_spaces', 1, '_bx_spaces_form_profile_display_view_full'),
+('bx_space', 'bx_space_invite', 'bx_spaces', 0, '_bx_spaces_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_space', 'bx_spaces', '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_space', 'bx_spaces', 'allow_view_to', 3, '', 0, 'custom', '_bx_spaces_form_profile_input_sys_allow_view_to', '_bx_spaces_form_profile_input_allow_view_to', '_bx_spaces_form_profile_input_allow_view_to_desc', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_space', 'bx_spaces', 'allow_post_to', 3, '', 0, 'custom', '_bx_spaces_form_profile_input_sys_allow_post_to', '_bx_spaces_form_profile_input_allow_post_to', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_space', 'bx_spaces', 'delete_confirm', 1, '', 0, 'checkbox', '_bx_spaces_form_profile_input_sys_delete_confirm', '_bx_spaces_form_profile_input_delete_confirm', '_bx_spaces_form_profile_input_delete_confirm_info', 1, 0, 0, '', '', '', 'avail', '', '_bx_spaces_form_profile_input_delete_confirm_error', '', '', 1, 0),
+('bx_space', 'bx_spaces', 'do_submit', '_sys_form_account_input_submit', '', 0, 'submit', '_bx_spaces_form_profile_input_sys_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_space', 'bx_spaces', 'space_desc', '', '', 0, 'textarea', '_bx_spaces_form_profile_input_sys_space_desc', '_bx_spaces_form_profile_input_space_desc', '', 0, 0, 2, '', '', '', '', '', '', 'XssHtml', '', 1, 1),
+('bx_space', 'bx_spaces', 'space_cat', '', '#!bx_spaces_cats', 0, 'select', '_bx_spaces_form_profile_input_sys_space_cat', '_bx_spaces_form_profile_input_space_cat', '', 1, 0, 0, '', '', '', 'avail', '', '_bx_spaces_form_profile_input_space_cat_err', 'Xss', '', 1, 1),
+('bx_space', 'bx_spaces', 'space_name', '', '', 0, 'text', '_bx_spaces_form_profile_input_sys_space_name', '_bx_spaces_form_profile_input_space_name', '', 1, 0, 0, '', '', '', 'avail', '', '_bx_spaces_form_profile_input_space_name_err', 'Xss', '', 1, 0),
+('bx_space', 'bx_spaces', 'parent_space', '', '', 0, 'custom', '_bx_spaces_form_profile_input_sys_parent_space', '_bx_spaces_form_profile_input_parent_space', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 1),
+('bx_space', 'bx_spaces', 'initial_members', '', '', 0, 'custom', '_bx_spaces_form_profile_input_sys_initial_members', '_bx_spaces_form_profile_input_initial_members', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 1),
+('bx_space', 'bx_spaces', 'join_confirmation', 1, '', 0, 'switcher', '_bx_spaces_form_profile_input_sys_join_confirm', '_bx_spaces_form_profile_input_join_confirm', '', 0, 0, 0, '', '', '', '', '', '', 'Xss', '', 1, 0),
+('bx_space', 'bx_spaces', 'cover', 'a:1:{i:0;s:20:"bx_spaces_cover_crop";}', 'a:1:{s:20:"bx_spaces_cover_crop";s:24:"_sys_uploader_crop_title";}', 0, 'files', '_bx_spaces_form_profile_input_sys_cover', '_bx_spaces_form_profile_input_cover', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_space', 'bx_spaces', 'picture', 'a:1:{i:0;s:22:"bx_spaces_picture_crop";}', 'a:1:{s:22:"bx_spaces_picture_crop";s:24:"_sys_uploader_crop_title";}', 0, 'files', '_bx_spaces_form_profile_input_sys_picture', '_bx_spaces_form_profile_input_picture', '', 0, 0, 0, '', '', '', '', '', '_bx_spaces_form_profile_input_picture_err', '', '', 1, 0),
+('bx_space', 'bx_spaces', 'location', '', '', 0, 'location', '_sys_form_input_sys_location', '_sys_form_input_location', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_space', 'bx_spaces', 'labels', '', '', 0, 'custom', '_sys_form_input_sys_labels', '_sys_form_input_labels', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0);
+
+INSERT INTO `sys_form_display_inputs`(`display_name`, `input_name`, `visible_for_levels`, `active`, `order`) VALUES 
+('bx_space_add', 'initial_members', 2147483647, 1, 1),
+('bx_space_add', 'space_name', 2147483647, 1, 2),
+('bx_space_add', 'parent_space', 2147483647, 1, 3),
+('bx_space_add', 'space_cat', 2147483647, 1, 4),
+('bx_space_add', 'space_desc', 2147483647, 1, 5),
+('bx_space_add', 'location', 2147483647, 1, 6),
+('bx_space_add', 'join_confirmation', 2147483647, 1, 7),
+('bx_space_add', 'allow_view_to', 2147483647, 1, 8),
+('bx_space_add', 'allow_post_to', 2147483647, 1, 9),
+('bx_space_add', 'cf', 2147483647, 1, 10),
+('bx_space_add', 'do_submit', 2147483647, 1, 11),
+
+('bx_space_invite', 'initial_members', 2147483647, 1, 1),
+('bx_space_invite', 'do_submit', 2147483647, 1, 2),
+
+('bx_space_delete', 'delete_confirm', 2147483647, 1, 1),
+('bx_space_delete', 'do_submit', 2147483647, 1, 2),
+
+('bx_space_edit', 'space_name', 2147483647, 1, 1),
+('bx_space_edit', 'parent_space', 2147483647, 1, 2),
+('bx_space_edit', 'space_cat', 2147483647, 1, 3),
+('bx_space_edit', 'space_desc', 2147483647, 1, 4),
+('bx_space_edit', 'location', 2147483647, 1, 5),
+('bx_space_edit', 'join_confirmation', 2147483647, 1, 6),
+('bx_space_edit', 'allow_view_to', 2147483647, 1, 7),
+('bx_space_edit', 'allow_post_to', 2147483647, 1, 8),
+('bx_space_edit', 'cf', 2147483647, 1, 9),
+('bx_space_edit', 'do_submit', 2147483647, 1, 10),
+
+('bx_space_edit_cover', 'cover', 2147483647, 1, 1),
+('bx_space_edit_cover', 'do_submit', 2147483647, 1, 2),
+
+('bx_space_view', 'space_name', 2147483647, 1, 1),
+('bx_space_view', 'space_cat', 2147483647, 1, 2),
+
+('bx_space_view_full', 'space_name', 2147483647, 1, 1),
+('bx_space_view_full', 'space_cat', 2147483647, 1, 2),
+('bx_space_view_full', 'space_desc', 2147483647, 1, 3);
+
+-- FORMS: Price
+INSERT INTO `sys_objects_form` (`object`, `module`, `title`, `action`, `form_attrs`, `submit_name`, `table`, `key`, `uri`, `uri_title`, `params`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES
+('bx_spaces_price', 'bx_spaces', '_bx_spaces_form_price', '', '', 'do_submit', 'bx_spaces_prices', 'id', '', '', '', 0, 1, 'BxSpacesFormPrice', 'modules/boonex/spaces/classes/BxSpacesFormPrice.php');
+
+INSERT INTO `sys_form_displays` (`display_name`, `module`, `object`, `title`, `view_mode`) VALUES
+('bx_spaces_price_add', 'bx_spaces', 'bx_spaces_price', '_bx_spaces_form_price_display_add', 0),
+('bx_spaces_price_edit', 'bx_spaces', 'bx_spaces_price', '_bx_spaces_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_spaces_price', 'bx_spaces', 'id', '', '', 0, 'hidden', '_bx_spaces_form_price_input_sys_id', '', '', 1, 0, 0, '', '', '', '', '', '', 'Int', '', 1, 0),
+('bx_spaces_price', 'bx_spaces', 'role_id', '', '', 0, 'hidden', '_bx_spaces_form_price_input_sys_role_id', '', '', 1, 0, 0, '', '', '', '', '', '', 'Int', '', 1, 0),
+('bx_spaces_price', 'bx_spaces', 'name', '', '', 0, 'text', '_bx_spaces_form_price_input_sys_name', '_bx_spaces_form_price_input_name', '_bx_spaces_form_price_input_inf_name', 1, 0, 0, '', '', '', 'Avail', '', '_bx_spaces_form_price_input_err_name', 'Xss', '', 1, 0),
+('bx_spaces_price', 'bx_spaces', 'period', '', '', 0, 'text', '_bx_spaces_form_price_input_sys_period', '_bx_spaces_form_price_input_period', '_bx_spaces_form_price_input_inf_period', 1, 0, 0, '', '', '', '', '', '', 'Int', '', 1, 0),
+('bx_spaces_price', 'bx_spaces', 'period_unit', '', '#!bx_spaces_period_units', 0, 'select', '_bx_spaces_form_price_input_sys_period_unit', '_bx_spaces_form_price_input_period_unit', '_bx_spaces_form_price_input_inf_period_unit', 1, 0, 0, '', '', '', '', '', '', 'Xss', '', 1, 0),
+('bx_spaces_price', 'bx_spaces', 'price', '', '', 0, 'price', '_bx_spaces_form_price_input_sys_price', '_bx_spaces_form_price_input_price', '_bx_spaces_form_price_input_inf_price', 1, 0, 0, '', '', '', '', '', '', 'Float', '', 1, 0),
+('bx_spaces_price', 'bx_spaces', 'controls', '', 'do_submit,do_cancel', 0, 'input_set', '', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_spaces_price', 'bx_spaces', 'do_submit', '_bx_spaces_form_price_input_do_submit', '', 0, 'submit', '_bx_spaces_form_price_input_sys_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_spaces_price', 'bx_spaces', 'do_cancel', '_bx_spaces_form_price_input_do_cancel', '', 0, 'button', '_bx_spaces_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_spaces_price_add', 'id', 2147483647, 0, 1),
+('bx_spaces_price_add', 'role_id', 2147483647, 1, 2),
+('bx_spaces_price_add', 'name', 2147483647, 1, 3),
+('bx_spaces_price_add', 'price', 2147483647, 1, 4),
+('bx_spaces_price_add', 'period', 2147483647, 1, 5),
+('bx_spaces_price_add', 'period_unit', 2147483647, 1, 6),
+('bx_spaces_price_add', 'controls', 2147483647, 1, 7),
+('bx_spaces_price_add', 'do_submit', 2147483647, 1, 8),
+('bx_spaces_price_add', 'do_cancel', 2147483647, 1, 9),
+
+('bx_spaces_price_edit', 'id', 2147483647, 1, 1),
+('bx_spaces_price_edit', 'role_id', 2147483647, 1, 2),
+('bx_spaces_price_edit', 'name', 2147483647, 1, 3),
+('bx_spaces_price_edit', 'price', 2147483647, 1, 4),
+('bx_spaces_price_edit', 'period', 2147483647, 1, 5),
+('bx_spaces_price_edit', 'period_unit', 2147483647, 1, 6),
+('bx_spaces_price_edit', 'controls', 2147483647, 1, 7),
+('bx_spaces_price_edit', 'do_submit', 2147483647, 1, 8),
+('bx_spaces_price_edit', 'do_cancel', 2147483647, 1, 9);
+
+-- PRE-VALUES
+INSERT INTO `sys_form_pre_lists`(`key`, `title`, `module`, `use_for_sets`) VALUES
+('bx_spaces_cats', '_bx_spaces_pre_lists_cats', 'bx_spaces', '0');
+
+INSERT INTO `sys_form_pre_values`(`Key`, `Value`, `Order`, `LKey`, `LKey2`) VALUES
+('bx_spaces_cats', '', 0, '_sys_please_select', ''),
+('bx_spaces_cats', '1', 1, '_bx_spaces_cat_General', ''),
+('bx_spaces_cats', '2', 2, '_bx_spaces_cat_Business', ''),
+('bx_spaces_cats', '3', 3, '_bx_spaces_cat_Interests', ''),
+('bx_spaces_cats', '4', 4, '_bx_spaces_cat_Causes', ''),
+('bx_spaces_cats', '5', 5, '_bx_spaces_cat_Fun', ''),
+('bx_spaces_cats', '6', 6, '_bx_spaces_cat_Uncategorised', '');
+
+INSERT INTO `sys_form_pre_lists`(`key`, `title`, `module`, `use_for_sets`) VALUES
+('bx_spaces_roles', '_bx_spaces_pre_lists_roles', 'bx_spaces', '1');
+
+INSERT INTO `sys_form_pre_values`(`Key`, `Value`, `Order`, `LKey`, `LKey2`) VALUES
+('bx_spaces_roles', '0', 1, '_bx_spaces_role_regular', ''),
+('bx_spaces_roles', '1', 2, '_bx_spaces_role_administrator', ''),
+('bx_spaces_roles', '2', 3, '_bx_spaces_role_moderator', '');
+
+INSERT INTO `sys_form_pre_lists`(`key`, `title`, `module`, `use_for_sets`) VALUES
+('bx_spaces_period_units', '_bx_spaces_pre_lists_period_units', 'bx_spaces', '0');
+
+INSERT INTO `sys_form_pre_values`(`Key`, `Value`, `Order`, `LKey`, `LKey2`) VALUES
+('bx_spaces_period_units', '', 0, '_sys_please_select', ''),
+('bx_spaces_period_units', 'day', 1, '_bx_spaces_period_unit_day', ''),
+('bx_spaces_period_units', 'week', 2, '_bx_spaces_period_unit_week', ''),
+('bx_spaces_period_units', 'month', 3, '_bx_spaces_period_unit_month', ''),
+('bx_spaces_period_units', 'year', 4, '_bx_spaces_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_spaces', 'bx_spaces', 'bx_spaces_cmts', 1, 5000, 1000, 3, 5, 3, 'tail', 1, 'bottom', 1, 1, 1, -3, 1, 'cmt', 'page.php?i=view-space-profile&id={object_id}', '', 'bx_spaces_data', 'id', 'author', 'space_name', 'comments', 'BxSpacesCmts', 'modules/boonex/spaces/classes/BxSpacesCmts.php'),
+('bx_spaces_notes', 'bx_spaces', 'bx_spaces_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_spaces_data', 'id', 'author', 'space_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_spaces', 'bx_spaces', 'bx_spaces_views_track', '86400', '1', 'bx_spaces_data', 'id', 'author', 'views', '', '');
+
+-- VOTES
+INSERT INTO `sys_objects_vote` (`Name`, `Module`, `TableMain`, `TableTrack`, `PostTimeout`, `MinValue`, `MaxValue`, `IsUndo`, `IsOn`, `TriggerTable`, `TriggerFieldId`, `TriggerFieldAuthor`, `TriggerFieldRate`, `TriggerFieldRateCount`, `ClassName`, `ClassFile`) VALUES 
+('bx_spaces', 'bx_spaces', 'bx_spaces_votes', 'bx_spaces_votes_track', '604800', '1', '1', '0', '1', 'bx_spaces_data', 'id', 'author', 'rate', 'votes', '', '');
+
+-- SCORES
+INSERT INTO `sys_objects_score` (`name`, `module`, `table_main`, `table_track`, `post_timeout`, `is_on`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_score`, `trigger_field_cup`, `trigger_field_cdown`, `class_name`, `class_file`) VALUES 
+('bx_spaces', 'bx_spaces', 'bx_spaces_scores', 'bx_spaces_scores_track', '604800', '0', 'bx_spaces_data', 'id', 'author', 'score', 'sc_up', 'sc_down', '', '');
+
+-- REPORTS
+INSERT INTO `sys_objects_report` (`name`, `module`, `table_main`, `table_track`, `is_on`, `base_url`, `object_comment`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_count`, `class_name`, `class_file`) VALUES 
+('bx_spaces', 'bx_spaces', 'bx_spaces_reports', 'bx_spaces_reports_track', '1', 'page.php?i=view-space-profile&id={object_id}', 'bx_spaces_notes', 'bx_spaces_data', 'id', 'author', 'reports', '', '');
+
+-- FAFORITES
+INSERT INTO `sys_objects_favorite` (`name`, `table_track`, `table_lists`, `is_on`, `is_undo`, `is_public`, `base_url`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_count`, `class_name`, `class_file`) VALUES 
+('bx_spaces', 'bx_spaces_favorites_track', 'bx_spaces_favorites_lists', '1', '1', '1', 'page.php?i=view-space-profile&id={object_id}', 'bx_spaces_data', 'id', 'author', 'favorites', '', '');
+
+-- FEATURED
+INSERT INTO `sys_objects_feature` (`name`, `module`, `is_on`, `is_undo`, `base_url`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_flag`, `class_name`, `class_file`) VALUES 
+('bx_spaces', 'bx_spaces', '1', '1', 'page.php?i=view-space-profile&id={object_id}', 'bx_spaces_data', 'id', 'author', 'featured', '', '');
+
+-- CONTENT INFO
+INSERT INTO `sys_objects_content_info` (`name`, `title`, `alert_unit`, `alert_action_add`, `alert_action_update`, `alert_action_delete`, `class_name`, `class_file`) VALUES
+('bx_spaces', '_bx_spaces', 'bx_spaces', 'added', 'edited', 'deleted', '', ''),
+('bx_spaces_cmts', '_bx_spaces_cmts', 'bx_spaces', 'commentPost', 'commentUpdated', 'commentRemoved', 'BxDolContentInfoCmts', '');
+
+INSERT INTO `sys_content_info_grids` (`object`, `grid_object`, `grid_field_id`, `condition`, `selection`) VALUES
+('bx_spaces', 'bx_spaces_administration', 'td`.`id', '', ''),
+('bx_spaces', 'bx_spaces_common', 'td`.`id', '', '');
+
+-- SEARCH EXTENDED
+INSERT INTO `sys_objects_search_extended` (`object`, `object_content_info`, `module`, `title`, `active`, `class_name`, `class_file`) VALUES
+('bx_spaces', 'bx_spaces', 'bx_spaces', '_bx_spaces_search_extended', 1, '', ''),
+('bx_spaces_cmts', 'bx_spaces_cmts', 'bx_spaces', '_bx_spaces_search_extended_cmts', 1, 'BxTemplSearchExtendedCmts', '');
+
+-- STUDIO PAGE & WIDGET
+INSERT INTO `sys_std_pages`(`index`, `name`, `header`, `caption`, `icon`) VALUES
+(3, 'bx_spaces', '_bx_spaces', '_bx_spaces', 'bx_spaces@modules/boonex/spaces/|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_spaces', 'content', '{url_studio}module.php?name=bx_spaces', '', 'bx_spaces@modules/boonex/spaces/|std-icon.svg', '_bx_spaces', '', '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/stream/updates/13.0.6_13.0.7/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' => 'Stream',
+    'version_from' => '13.0.6',
+    'version_to' => '13.0.7',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '13.1.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/stream/updates/update_13.0.6_13.0.7/',
+    'home_uri' => 'stream_update_1306_1307',
+
+    'module_dir' => 'boonex/stream/',
+    'module_uri' => 'stream',
+
+    'db_prefix' => 'bx_stream_',
+    'class_prefix' => 'BxStrm',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_files' => 1,
+        'update_languages' => 0,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Stream',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

+ 13 - 0
modules/boonex/stream/updates/13.0.6_13.0.7/install/installer.php

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

+ 10 - 0
modules/boonex/stream/updates/13.0.6_13.0.7/install/sql/install.sql

@@ -0,0 +1,10 @@
+-- STORAGES & TRANSCODERS
+UPDATE `sys_transcoder_filters` SET `filter_params`='a:1:{s:1:"w";s:4:"1200";}' WHERE `transcoder_object`='bx_stream_cover';
+
+
+-- VOTES
+UPDATE `sys_objects_vote` SET `Module`='bx_stream' WHERE `Name` IN ('bx_stream', 'bx_stream_reactions');
+
+
+-- VIEWS
+UPDATE `sys_objects_view` SET `module`='bx_stream' WHERE `name`='bx_stream';

+ 137 - 0
modules/boonex/stream/updates/13.0.6_13.0.7/source/install/config.php

@@ -0,0 +1,137 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Stream Stream
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_stream',
+    'title' => 'Stream',
+    'note' => 'Live streaming module.',
+    'version' => '13.0.7',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '13.1.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/stream/',
+    'home_uri' => 'stream',
+
+    'db_prefix' => 'bx_stream_',
+    'class_prefix' => 'BxStrm',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Stream',
+
+    /**
+     * 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_stream_covers',
+    ),
+
+    /**
+     * Transcoders.
+     */
+    'transcoders' => array(
+        'bx_stream_preview',
+        'bx_stream_gallery',
+        'bx_stream_cover',
+    ),
+
+    /**
+     * Extended Search Forms.
+     */
+    'esearches' => array(
+        'bx_stream',
+    	'bx_stream_cmts'
+    ),
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'uninstall' => array (
+    	'process_esearches' => 1,
+        'execute_sql' => 1,
+        'update_languages' => 1,
+        'update_relations' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'enable' => array(
+        'execute_sql' => 1,
+        'update_relations' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'enable_success' => array(
+        'process_menu_triggers' => 1,
+        'process_page_triggers' => 1,
+    	'process_esearches' => 1,
+        'register_transcoders' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable' => array (
+        'execute_sql' => 1,
+        'update_relations' => 1,
+        'unregister_transcoders' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable_failed' => array (
+        'register_transcoders' => 1,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Dependencies Section
+     */
+    'dependencies' => array(),
+
+    /**
+     * Relations Section
+     */
+    'relations' => array(
+    	'bx_timeline',
+    	'bx_notifications'
+    ),
+
+);
+
+/** @} */

+ 445 - 0
modules/boonex/stream/updates/13.0.6_13.0.7/source/install/sql/install.sql

@@ -0,0 +1,445 @@
+-- TABLE: entries
+CREATE TABLE IF NOT EXISTS `bx_stream_streams` (
+  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+  `author` int(11) NOT NULL,
+  `added` int(11) NOT NULL,
+  `changed` int(11) NOT NULL,
+  `published` int(11) NOT NULL,
+  `thumb` int(11) NOT NULL,
+  `title` varchar(255) NOT NULL,
+  `cat` int(11) NOT NULL,
+  `multicat` text NOT NULL,
+  `text` mediumtext NOT NULL,
+  `key` varchar(12) NOT NULL,
+  `labels` text NOT NULL,
+  `location` text NOT NULL,
+  `views` int(11) NOT NULL default '0',
+  `rate` float NOT NULL default '0',
+  `votes` int(11) NOT NULL default '0',
+  `rrate` float NOT NULL default '0',
+  `rvotes` int(11) NOT NULL default '0',
+  `score` int(11) NOT NULL default '0',
+  `sc_up` int(11) NOT NULL default '0',
+  `sc_down` int(11) NOT NULL default '0',
+  `comments` int(11) NOT NULL default '0',
+  `reports` int(11) NOT NULL default '0',
+  `featured` int(11) NOT NULL default '0',
+  `cf` int(11) NOT NULL default '1',
+  `allow_view_to` varchar(16) NOT NULL DEFAULT '3',
+  `allow_comments` tinyint(4) NOT NULL DEFAULT '1',
+  `status` enum('active','awaiting','failed','hidden') NOT NULL DEFAULT 'active',
+  `status_admin` enum('active','hidden','pending') NOT NULL DEFAULT 'active',
+  PRIMARY KEY (`id`),
+  FULLTEXT KEY `title_text` (`title`,`text`)
+);
+
+-- TABLE: storages & transcoders
+CREATE TABLE IF NOT EXISTS `bx_stream_covers` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `profile_id` int(10) unsigned NOT NULL,
+  `remote_id` varchar(128) NOT NULL,
+  `path` varchar(255) NOT NULL,
+  `file_name` varchar(255) NOT NULL,
+  `mime_type` varchar(128) NOT NULL,
+  `ext` varchar(32) NOT NULL,
+  `size` bigint(20) NOT NULL,
+  `added` int(11) NOT NULL,
+  `modified` int(11) NOT NULL,
+  `private` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `remote_id` (`remote_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_stream_photos_resized` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `profile_id` int(10) unsigned NOT NULL,
+  `remote_id` varchar(128) NOT NULL,
+  `path` varchar(255) NOT NULL,
+  `file_name` varchar(255) NOT NULL,
+  `mime_type` varchar(128) NOT NULL,
+  `ext` varchar(32) NOT NULL,
+  `size` bigint(20) NOT NULL,
+  `added` int(11) NOT NULL,
+  `modified` int(11) NOT NULL,
+  `private` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `remote_id` (`remote_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_stream_recordings` (
+  `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_stream_recordings_seq` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `content_id` int(10) unsigned NOT NULL,
+  `tries` tinyint(4) NOT NULL DEFAULT 0,
+  `added` int(10) unsigned NOT NULL,
+  `status` enum('pending','processing') NOT NULL DEFAULT 'pending',
+  PRIMARY KEY (`id`),
+  KEY `content_id` (`content_id`)
+);
+
+-- TABLE: comments
+CREATE TABLE IF NOT EXISTS `bx_stream_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_stream_cmts_notes` (
+  `cmt_id` int(11) NOT NULL AUTO_INCREMENT,
+  `cmt_parent_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_vparent_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_object_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_author_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_level` int(11) NOT NULL DEFAULT '0',
+  `cmt_text` text NOT NULL,
+  `cmt_mood` tinyint(4) NOT NULL DEFAULT '0',
+  `cmt_rate` int(11) NOT NULL DEFAULT '0',
+  `cmt_rate_count` int(11) NOT NULL DEFAULT '0',
+  `cmt_time` int(11) unsigned NOT NULL DEFAULT '0',
+  `cmt_replies` int(11) NOT NULL DEFAULT '0',
+  `cmt_pinned` int(11) NOT NULL default '0',
+  PRIMARY KEY (`cmt_id`),
+  KEY `cmt_object_id` (`cmt_object_id`,`cmt_parent_id`),
+  FULLTEXT KEY `search_fields` (`cmt_text`)
+);
+
+-- TABLE: votes
+CREATE TABLE IF NOT EXISTS `bx_stream_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_stream_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_stream_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_stream_reactions_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `author_nip` int(11) unsigned NOT NULL default '0',
+  `reaction` varchar(32) NOT NULL default '',
+  `value` tinyint(4) NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `vote` (`object_id`, `author_nip`)
+);
+
+-- TABLE: views
+CREATE TABLE `bx_stream_views_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `viewer_id` int(11) NOT NULL default '0',
+  `viewer_nip` int(11) unsigned NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `id` (`object_id`,`viewer_id`,`viewer_nip`)
+);
+
+-- TABLE: metas
+CREATE TABLE `bx_stream_meta_keywords` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(10) unsigned NOT NULL,
+  `keyword` varchar(255) NOT NULL,
+  PRIMARY KEY (`id`),
+  KEY `object_id` (`object_id`),
+  KEY `keyword` (`keyword`)
+);
+
+CREATE TABLE `bx_stream_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`)
+);
+
+CREATE TABLE `bx_stream_meta_locations` (
+  `object_id` int(10) unsigned NOT NULL,
+  `lat` double NOT NULL,
+  `lng` double NOT NULL,
+  `country` varchar(2) NOT NULL,
+  `state` varchar(255) NOT NULL,
+  `city` varchar(255) NOT NULL,
+  `zip` varchar(255) NOT NULL,
+  `street` varchar(255) NOT NULL,
+  `street_number` varchar(255) NOT NULL,
+  PRIMARY KEY (`object_id`),
+  KEY `country_state_city` (`country`,`state`(8),`city`(8))
+);
+
+-- TABLE: reports
+CREATE TABLE IF NOT EXISTS `bx_stream_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_stream_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: scores
+CREATE TABLE IF NOT EXISTS `bx_stream_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_stream_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
+SET @sStorageEngine = (SELECT `value` FROM `sys_options` WHERE `name` = 'sys_storage_default');
+
+INSERT INTO `sys_objects_storage` (`object`, `engine`, `params`, `token_life`, `cache_control`, `levels`, `table_files`, `ext_mode`, `ext_allow`, `ext_deny`, `quota_size`, `current_size`, `quota_number`, `current_number`, `max_file_size`, `ts`) VALUES
+('bx_stream_covers', @sStorageEngine, '', 360, 2592000, 3, 'bx_stream_covers', 'allow-deny', '{image}', '', 0, 0, 0, 0, 0, 0),
+
+('bx_stream_photos_resized', @sStorageEngine, '', 360, 2592000, 3, 'bx_stream_photos_resized', 'allow-deny', '{image}', '', 0, 0, 0, 0, 0, 0),
+
+('bx_stream_recordings', @sStorageEngine, '', 360, 2592000, 3, 'bx_stream_recordings', 'allow-deny', '{video}', '', 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_stream_preview', 'bx_stream_photos_resized', 'Storage', 'a:1:{s:6:"object";s:16:"bx_stream_covers";}', 'no', '1', '2592000', '0', '', ''),
+('bx_stream_gallery', 'bx_stream_photos_resized', 'Storage', 'a:1:{s:6:"object";s:16:"bx_stream_covers";}', 'no', '1', '2592000', '0', '', ''),
+('bx_stream_cover', 'bx_stream_photos_resized', 'Storage', 'a:1:{s:6:"object";s:16:"bx_stream_covers";}', 'no', '1', '2592000', '0', '', '');
+
+INSERT INTO `sys_transcoder_filters` (`transcoder_object`, `filter`, `filter_params`, `order`) VALUES 
+('bx_stream_preview', 'Resize', 'a:3:{s:1:"w";s:3:"300";s:1:"h";s:3:"200";s:11:"crop_resize";s:1:"1";}', '0'),
+('bx_stream_gallery', 'Resize', 'a:1:{s:1:"w";s:3:"500";}', '0'),
+('bx_stream_cover', 'Resize', 'a:1:{s:1:"w";s:4:"1200";}', '0');
+
+
+-- FORMS: entry (post)
+INSERT INTO `sys_objects_form`(`object`, `module`, `title`, `action`, `form_attrs`, `table`, `key`, `uri`, `uri_title`, `submit_name`, `params`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_stream', 'bx_stream', '_bx_stream_form_entry', '', 'a:1:{s:7:"enctype";s:19:"multipart/form-data";}', 'bx_stream_streams', 'id', '', '', 'a:2:{i:0;s:9:"do_submit";i:1;s:10:"do_publish";}', '', 0, 1, 'BxStrmFormEntry', 'modules/boonex/stream/classes/BxStrmFormEntry.php');
+
+INSERT INTO `sys_form_displays`(`object`, `display_name`, `module`, `view_mode`, `title`) VALUES 
+('bx_stream', 'bx_stream_entry_add', 'bx_stream', 0, '_bx_stream_form_entry_display_add'),
+('bx_stream', 'bx_stream_entry_delete', 'bx_stream', 0, '_bx_stream_form_entry_display_delete'),
+('bx_stream', 'bx_stream_entry_edit', 'bx_stream', 0, '_bx_stream_form_entry_display_edit'),
+('bx_stream', 'bx_stream_entry_view', 'bx_stream', 1, '_bx_stream_form_entry_display_view');
+
+INSERT INTO `sys_form_inputs`(`object`, `module`, `name`, `value`, `values`, `checked`, `type`, `caption_system`, `caption`, `info`, `required`, `collapsed`, `html`, `attrs`, `attrs_tr`, `attrs_wrapper`, `checker_func`, `checker_params`, `checker_error`, `db_pass`, `db_params`, `editable`, `deletable`) VALUES 
+('bx_stream', 'bx_stream', '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_stream', 'bx_stream', 'allow_view_to', '', '', 0, 'custom', '_bx_stream_form_entry_input_sys_allow_view_to', '_bx_stream_form_entry_input_allow_view_to', '', 1, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_stream', 'bx_stream', 'delete_confirm', 1, '', 0, 'checkbox', '_bx_stream_form_entry_input_sys_delete_confirm', '_bx_stream_form_entry_input_delete_confirm', '_bx_stream_form_entry_input_delete_confirm_info', 1, 0, 0, '', '', '', 'Avail', '', '_bx_stream_form_entry_input_delete_confirm_error', '', '', 1, 0),
+('bx_stream', 'bx_stream', 'do_publish', '_bx_stream_form_entry_input_do_publish', '', 0, 'submit', '_bx_stream_form_entry_input_sys_do_publish', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_stream', 'bx_stream', 'do_submit', '_bx_stream_form_entry_input_do_submit', '', 0, 'submit', '_bx_stream_form_entry_input_sys_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_stream', 'bx_stream', 'location', '', '', 0, 'location', '_sys_form_input_sys_location', '_sys_form_input_location', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_stream', 'bx_stream', 'covers', 'a:1:{i:0;s:15:"bx_stream_html5";}', 'a:1:{s:15:"bx_stream_html5";s:25:"_sys_uploader_html5_title";}', 0, 'files', '_bx_stream_form_entry_input_sys_covers', '_bx_stream_form_entry_input_covers', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_stream', 'bx_stream', 'text', '', '', 0, 'textarea', '_bx_stream_form_entry_input_sys_text', '_bx_stream_form_entry_input_text', '', 1, 0, 2, '', '', '', 'Avail', '', '_bx_stream_form_entry_input_text_err', 'XssHtml', '', 1, 0),
+('bx_stream', 'bx_stream', 'title', '', '', 0, 'text', '_bx_stream_form_entry_input_sys_title', '_bx_stream_form_entry_input_title', '', 1, 0, 0, '', '', '', 'Avail', '', '_bx_stream_form_entry_input_title_err', 'Xss', '', 1, 0),
+('bx_stream', 'bx_stream', 'cat', '', '#!bx_stream_cats', 0, 'select', '_bx_stream_form_entry_input_sys_cat', '_bx_stream_form_entry_input_cat', '', 1, 0, 0, '', '', '', 'avail', '', '_bx_stream_form_entry_input_cat_err', 'Xss', '', 1, 0),
+('bx_stream', 'bx_stream', 'multicat', '', '', 0, 'custom', '_bx_stream_form_entry_input_sys_multicat', '_bx_stream_form_entry_input_multicat', '', 1, 0, 0, '', '', '', 'avail', '', '_bx_stream_form_entry_input_multicat_err', 'Xss', '', 1, 0),
+('bx_stream', 'bx_stream', 'added', '', '', 0, 'datetime', '_bx_stream_form_entry_input_sys_date_added', '_bx_stream_form_entry_input_date_added', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_stream', 'bx_stream', 'changed', '', '', 0, 'datetime', '_bx_stream_form_entry_input_sys_date_changed', '_bx_stream_form_entry_input_date_changed', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_stream', 'bx_stream', 'labels', '', '', 0, 'custom', '_sys_form_input_sys_labels', '_sys_form_input_labels', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_stream', 'bx_stream', 'anonymous', '', '', 0, 'switcher', '_sys_form_input_sys_anonymous', '_sys_form_input_anonymous', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_stream', 'bx_stream', 'allow_comments', '1', '', 1, 'switcher', '_bx_stream_form_entry_input_sys_allow_comments', '_bx_stream_form_entry_input_allow_comments', '', 0, 0, 0, '', '', '', '', '', '', 'Int', '', 1, 0);
+
+
+
+INSERT INTO `sys_form_display_inputs`(`display_name`, `input_name`, `visible_for_levels`, `active`, `order`) VALUES 
+('bx_stream_entry_add', 'delete_confirm', 2147483647, 0, 1),
+('bx_stream_entry_add', 'title', 2147483647, 1, 2),
+('bx_stream_entry_add', 'cat', 2147483647, 1, 3),
+('bx_stream_entry_add', 'text', 2147483647, 1, 4),
+('bx_stream_entry_add', 'covers', 2147483647, 1, 5),
+('bx_stream_entry_add', 'allow_view_to', 2147483647, 1, 6),
+('bx_stream_entry_add', 'cf', 2147483647, 1, 7),
+('bx_stream_entry_add', 'location', 2147483647, 1, 8),
+('bx_stream_entry_add', 'allow_comments', 192, 1, 9),
+('bx_stream_entry_add', 'do_publish', 2147483647, 1, 10),
+
+('bx_stream_entry_delete', 'delete_confirm', 2147483647, 1, 1),
+('bx_stream_entry_delete', 'do_submit', 2147483647, 1, 2),
+
+('bx_stream_entry_edit', 'do_publish', 2147483647, 0, 1),
+('bx_stream_entry_edit', 'delete_confirm', 2147483647, 0, 2),
+('bx_stream_entry_edit', 'title', 2147483647, 1, 3),
+('bx_stream_entry_edit', 'cat', 2147483647, 1, 4),
+('bx_stream_entry_edit', 'text', 2147483647, 1, 5),
+('bx_stream_entry_edit', 'covers', 2147483647, 1, 6),
+('bx_stream_entry_edit', 'allow_view_to', 2147483647, 1, 7),
+('bx_stream_entry_edit', 'cf', 2147483647, 1, 8),
+('bx_stream_entry_edit', 'location', 2147483647, 1, 9),
+('bx_stream_entry_edit', 'allow_comments', 192, 1, 10),
+('bx_stream_entry_edit', 'do_submit', 2147483647, 1, 11),
+
+('bx_stream_entry_view', 'cat', 2147483647, 1, 1),
+('bx_stream_entry_view', 'added', 2147483647, 1, 2),
+('bx_stream_entry_view', 'changed', 2147483647, 1, 3),
+('bx_stream_entry_view', 'published', 192, 1, 4);
+
+-- PRE-VALUES
+INSERT INTO `sys_form_pre_lists`(`key`, `title`, `module`, `use_for_sets`) VALUES
+('bx_stream_cats', '_bx_stream_pre_lists_cats', 'bx_stream', '0');
+
+INSERT INTO `sys_form_pre_values`(`Key`, `Value`, `Order`, `LKey`, `LKey2`) VALUES
+('bx_stream_cats', '', 0, '_sys_please_select', ''),
+('bx_stream_cats', '1', 1, '_bx_stream_cat_Animals_Pets', ''),
+('bx_stream_cats', '2', 2, '_bx_stream_cat_Architecture', ''),
+('bx_stream_cats', '3', 3, '_bx_stream_cat_Art', ''),
+('bx_stream_cats', '4', 4, '_bx_stream_cat_Cars_Motorcycles', ''),
+('bx_stream_cats', '5', 5, '_bx_stream_cat_Celebrities', ''),
+('bx_stream_cats', '6', 6, '_bx_stream_cat_Design', ''),
+('bx_stream_cats', '7', 7, '_bx_stream_cat_DIY_Crafts', ''),
+('bx_stream_cats', '8', 8, '_bx_stream_cat_Education', ''),
+('bx_stream_cats', '9', 9, '_bx_stream_cat_Film_Music_Books', ''),
+('bx_stream_cats', '10', 10, '_bx_stream_cat_Food_Drink', ''),
+('bx_stream_cats', '11', 11, '_bx_stream_cat_Gardening', ''),
+('bx_stream_cats', '12', 12, '_bx_stream_cat_Geek', ''),
+('bx_stream_cats', '13', 13, '_bx_stream_cat_Hair_Beauty', ''),
+('bx_stream_cats', '14', 14, '_bx_stream_cat_Health_Fitness', ''),
+('bx_stream_cats', '15', 15, '_bx_stream_cat_History', ''),
+('bx_stream_cats', '16', 16, '_bx_stream_cat_Holidays_Events', ''),
+('bx_stream_cats', '17', 17, '_bx_stream_cat_Home_Decor', ''),
+('bx_stream_cats', '18', 18, '_bx_stream_cat_Humor', ''),
+('bx_stream_cats', '19', 19, '_bx_stream_cat_Illustrations_Posters', ''),
+('bx_stream_cats', '20', 20, '_bx_stream_cat_Kids_Parenting', ''),
+('bx_stream_cats', '21', 21, '_bx_stream_cat_Mens_Fashion', ''),
+('bx_stream_cats', '22', 22, '_bx_stream_cat_Outdoors', ''),
+('bx_stream_cats', '23', 23, '_bx_stream_cat_Photography', ''),
+('bx_stream_cats', '24', 24, '_bx_stream_cat_Products', ''),
+('bx_stream_cats', '25', 25, '_bx_stream_cat_Quotes', ''),
+('bx_stream_cats', '26', 26, '_bx_stream_cat_Science_Nature', ''),
+('bx_stream_cats', '27', 27, '_bx_stream_cat_Sports', ''),
+('bx_stream_cats', '28', 28, '_bx_stream_cat_Tattoos', ''),
+('bx_stream_cats', '29', 29, '_bx_stream_cat_Technology', ''),
+('bx_stream_cats', '30', 30, '_bx_stream_cat_Travel', ''),
+('bx_stream_cats', '31', 31, '_bx_stream_cat_Weddings', ''),
+('bx_stream_cats', '32', 32, '_bx_stream_cat_Womens_Fashion', '');
+
+-- 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_stream', 'bx_stream', 'bx_stream_cmts', 1, 5000, 1000, 3, 5, 3, 'tail', 1, 'bottom', 1, 1, 1, -3, 1, 'cmt', 'page.php?i=view-stream&id={object_id}', '', 'bx_stream_streams', 'id', 'author', 'title', 'comments', '', ''),
+('bx_stream_notes', 'bx_stream', 'bx_stream_cmts_notes', 1, 5000, 1000, 0, 5, 3, 'tail', 1, 'bottom', 1, 1, 1, -3, 1, 'cmt', 'page.php?i=view-stream&id={object_id}', '', 'bx_stream_streams', 'id', 'author', 'title', '', 'BxTemplCmtsNotes', '');
+
+-- VOTES
+INSERT INTO `sys_objects_vote` (`Name`, `Module`, `TableMain`, `TableTrack`, `PostTimeout`, `MinValue`, `MaxValue`, `IsUndo`, `IsOn`, `TriggerTable`, `TriggerFieldId`, `TriggerFieldAuthor`, `TriggerFieldRate`, `TriggerFieldRateCount`, `ClassName`, `ClassFile`) VALUES 
+('bx_stream', 'bx_stream', 'bx_stream_votes', 'bx_stream_votes_track', '604800', '1', '1', '0', '1', 'bx_stream_streams', 'id', 'author', 'rate', 'votes', '', ''),
+('bx_stream_reactions', 'bx_stream', 'bx_stream_reactions', 'bx_stream_reactions_track', '604800', '1', '1', '1', '1', 'bx_stream_streams', 'id', 'author', 'rrate', 'rvotes', 'BxTemplVoteReactions', '');
+
+-- SCORES
+INSERT INTO `sys_objects_score` (`name`, `module`, `table_main`, `table_track`, `post_timeout`, `is_on`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_score`, `trigger_field_cup`, `trigger_field_cdown`, `class_name`, `class_file`) VALUES 
+('bx_stream', 'bx_stream', 'bx_stream_scores', 'bx_stream_scores_track', '604800', '0', 'bx_stream_streams', 'id', 'author', 'score', 'sc_up', 'sc_down', '', '');
+
+-- REPORTS
+INSERT INTO `sys_objects_report` (`name`, `module`, `table_main`, `table_track`, `is_on`, `base_url`, `object_comment`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_count`, `class_name`, `class_file`) VALUES 
+('bx_stream', 'bx_stream', 'bx_stream_reports', 'bx_stream_reports_track', '1', 'page.php?i=view-stream&id={object_id}', 'bx_stream_notes', 'bx_stream_streams', 'id', 'author', 'reports', '', '');
+
+-- 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_stream', 'bx_stream', 'bx_stream_views_track', '86400', '1', 'bx_stream_streams', 'id', 'author', 'views', '', '');
+
+-- 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_stream', 'bx_stream', '1', '1', 'page.php?i=view-stream&id={object_id}', 'bx_stream_streams', 'id', 'author', 'featured', '', '');
+
+-- CONTENT INFO
+INSERT INTO `sys_objects_content_info` (`name`, `title`, `alert_unit`, `alert_action_add`, `alert_action_update`, `alert_action_delete`, `class_name`, `class_file`) VALUES
+('bx_stream', '_bx_stream', 'bx_stream', 'added', 'edited', 'deleted', '', ''),
+('bx_stream_cmts', '_bx_stream_cmts', 'bx_stream', 'commentPost', 'commentUpdated', 'commentRemoved', 'BxDolContentInfoCmts', '');
+
+INSERT INTO `sys_content_info_grids` (`object`, `grid_object`, `grid_field_id`, `condition`, `selection`) VALUES
+('bx_stream', 'bx_stream_administration', 'id', '', ''),
+('bx_stream', 'bx_stream_common', 'id', '', '');
+
+-- SEARCH EXTENDED
+INSERT INTO `sys_objects_search_extended` (`object`, `object_content_info`, `module`, `title`, `active`, `class_name`, `class_file`) VALUES
+('bx_stream', 'bx_stream', 'bx_stream', '_bx_stream_search_extended', 1, '', ''),
+('bx_stream_cmts', 'bx_stream_cmts', 'bx_stream', '_bx_stream_search_extended_cmts', 1, 'BxTemplSearchExtendedCmts', '');
+
+-- LOGS
+
+INSERT INTO `sys_objects_logs` (`object`, `module`, `logs_storage`, `title`, `active`, `class_name`, `class_file`) VALUES
+('bx_stream_ome_api', 'bx_stream', 'Auto', '_bx_stream_logs_ome_api', 0, '', '');
+
+-- STUDIO: page & widget
+INSERT INTO `sys_std_pages`(`index`, `name`, `header`, `caption`, `icon`) VALUES
+(3, 'bx_stream', '_bx_stream', '_bx_stream', 'bx_stream@modules/boonex/stream/|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_stream', 'content', '{url_studio}module.php?name=bx_stream', '', 'bx_stream@modules/boonex/stream/|std-icon.svg', '_bx_stream', '', '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/tasks/updates/13.0.5_13.0.6/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' => 'Tasks',
+    'version_from' => '13.0.5',
+    'version_to' => '13.0.6',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '13.1.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/tasks/updates/update_13.0.5_13.0.6/',
+    'home_uri' => 'tasks_update_1305_1306',
+
+    'module_dir' => 'boonex/tasks/',
+    'module_uri' => 'tasks',
+
+    'db_prefix' => 'bx_tasks_',
+    'class_prefix' => 'BxTasks',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_files' => 1,
+        'update_languages' => 0,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Tasks',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

+ 13 - 0
modules/boonex/tasks/updates/13.0.5_13.0.6/install/installer.php

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

+ 11 - 0
modules/boonex/tasks/updates/13.0.5_13.0.6/install/sql/install.sql

@@ -0,0 +1,11 @@
+-- STORAGES & TRANSCODERS
+UPDATE `sys_transcoder_filters` SET `filter_params`='a:1:{s:1:"w";s:4:"1200";}' WHERE `transcoder_object`='bx_tasks_cover';
+UPDATE `sys_transcoder_filters` SET `filter_params`='a:1:{s:1:"w";s:4:"1200";}' WHERE `transcoder_object`='bx_tasks_gallery_photos';
+
+
+-- VOTES
+UPDATE `sys_objects_vote` SET `Module`='bx_tasks' WHERE `Name` IN ('bx_tasks', 'bx_tasks_reactions');
+
+
+-- VIEWS
+UPDATE `sys_objects_view` SET `module`='bx_tasks' WHERE `name`='bx_tasks';

+ 257 - 0
modules/boonex/tasks/updates/13.0.5_13.0.6/source/classes/BxTasksFormEntry.php

@@ -0,0 +1,257 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT 
+ * @defgroup    Tasks Tasks
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+/**
+ * Create/Edit entry form
+ */
+class BxTasksFormEntry extends BxBaseModTextFormEntry
+{
+    protected $_sGhostTemplateCover = 'form_ghost_template_cover.html';
+	
+    public function __construct($aInfo, $oTemplate = false)
+    {
+        $this->MODULE = 'bx_tasks';
+        parent::__construct($aInfo, $oTemplate);
+
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+    	if(isset($CNF['FIELD_COVER']) && isset($this->aInputs[$CNF['FIELD_COVER']])) {
+            if($this->_oModule->checkAllowedSetThumb() === CHECK_ACTION_RESULT_ALLOWED) {
+                $this->aInputs[$CNF['FIELD_COVER']]['storage_object'] = $CNF['OBJECT_STORAGE'];
+                $this->aInputs[$CNF['FIELD_COVER']]['uploaders'] = !empty($this->aInputs[$CNF['FIELD_COVER']]['value']) ? unserialize($this->aInputs[$CNF['FIELD_COVER']]['value']) : $CNF['OBJECT_UPLOADERS'];
+                $this->aInputs[$CNF['FIELD_COVER']]['upload_buttons_titles'] = array(
+                    'Simple' => _t('_bx_tasks_form_entry_input_covers_uploader_simple_title'), 
+                    'HTML5' => _t('_bx_tasks_form_entry_input_covers_uploader_html5_title')
+                );
+                $this->aInputs[$CNF['FIELD_COVER']]['images_transcoder'] = $CNF['OBJECT_IMAGES_TRANSCODER_PREVIEW'];
+                $this->aInputs[$CNF['FIELD_COVER']]['storage_private'] = 0;
+                $this->aInputs[$CNF['FIELD_COVER']]['multiple'] = false;
+                $this->aInputs[$CNF['FIELD_COVER']]['content_id'] = 0;
+                $this->aInputs[$CNF['FIELD_COVER']]['ghost_template'] = '';
+            }
+            else
+                unset($this->aInputs[$CNF['FIELD_COVER']]);
+        }
+
+        if(isset($CNF['FIELD_PHOTO']) && isset($this->aInputs[$CNF['FIELD_PHOTO']])) {
+            $this->aInputs[$CNF['FIELD_PHOTO']]['storage_object'] = $CNF['OBJECT_STORAGE_PHOTOS'];
+            $this->aInputs[$CNF['FIELD_PHOTO']]['uploaders'] = !empty($this->aInputs[$CNF['FIELD_PHOTO']]['value']) ? unserialize($this->aInputs[$CNF['FIELD_PHOTO']]['value']) : $CNF['OBJECT_UPLOADERS'];
+            $this->aInputs[$CNF['FIELD_PHOTO']]['images_transcoder'] = $CNF['OBJECT_IMAGES_TRANSCODER_PREVIEW_PHOTOS'];
+            $this->aInputs[$CNF['FIELD_PHOTO']]['storage_private'] = 0;
+            $this->aInputs[$CNF['FIELD_PHOTO']]['multiple'] = true;
+            $this->aInputs[$CNF['FIELD_PHOTO']]['content_id'] = 0;
+            $this->aInputs[$CNF['FIELD_PHOTO']]['ghost_template'] = '';
+            $this->aInputs[$CNF['FIELD_PHOTO']]['tr_attrs'] = array('class'=> 'bx-base-text-attachment-item');
+        }
+
+        if(isset($this->aInputs[$CNF['FIELD_VIDEO']])) {
+            $this->aInputs[$CNF['FIELD_VIDEO']]['storage_object'] = $CNF['OBJECT_STORAGE_VIDEOS'];
+            $this->aInputs[$CNF['FIELD_VIDEO']]['uploaders'] = !empty($this->aInputs[$CNF['FIELD_VIDEO']]['value']) ? unserialize($this->aInputs[$CNF['FIELD_VIDEO']]['value']) : $CNF['OBJECT_UPLOADERS'];
+            $this->aInputs[$CNF['FIELD_VIDEO']]['images_transcoder'] = $CNF['OBJECT_VIDEOS_TRANSCODERS']['poster_preview'];
+            $this->aInputs[$CNF['FIELD_VIDEO']]['storage_private'] = 0;
+            $this->aInputs[$CNF['FIELD_VIDEO']]['multiple'] = true;
+            $this->aInputs[$CNF['FIELD_VIDEO']]['content_id'] = 0;
+            $this->aInputs[$CNF['FIELD_VIDEO']]['ghost_template'] = '';
+            $this->aInputs[$CNF['FIELD_VIDEO']]['tr_attrs'] = array('class'=> 'bx-base-text-attachment-item');
+        }
+
+        if (isset($CNF['FIELD_FILE']) && isset($this->aInputs[$CNF['FIELD_FILE']])) {
+            $this->aInputs[$CNF['FIELD_FILE']]['storage_object'] = $CNF['OBJECT_STORAGE_FILES'];
+            $this->aInputs[$CNF['FIELD_FILE']]['uploaders'] = !empty($this->aInputs[$CNF['FIELD_FILE']]['value']) ? unserialize($this->aInputs[$CNF['FIELD_FILE']]['value']) : $CNF['OBJECT_UPLOADERS'];
+            $this->aInputs[$CNF['FIELD_FILE']]['images_transcoder'] = $CNF['OBJECT_IMAGES_TRANSCODER_PREVIEW_FILES'];
+            $this->aInputs[$CNF['FIELD_FILE']]['storage_private'] = 0;
+            $this->aInputs[$CNF['FIELD_FILE']]['multiple'] = true;
+            $this->aInputs[$CNF['FIELD_FILE']]['content_id'] = 0;
+            $this->aInputs[$CNF['FIELD_FILE']]['ghost_template'] = '';
+            $this->aInputs[$CNF['FIELD_FILE']]['tr_attrs'] = array('class'=> 'bx-base-text-attachment-item');
+        }
+		
+		if (isset($this->aInputs['initial_members']) && !isset($this->aInputs['initial_members']['value'])) {
+			if (bx_get('id')){
+				$oConn = BxDolConnection::getObjectInstance($CNF['OBJECT_CONNECTION']);
+				$this->aInputs['initial_members']['value'] = $oConn->getConnectedInitiators(bx_get('id'));
+			}
+			else{
+				$this->aInputs['initial_members']['value'] = array(bx_get_logged_profile_id());
+			}
+			
+        }
+    }
+
+	function getCode($bDynamicMode = false)
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        $sResult = parent::getCode($bDynamicMode);
+		$sInclude = $this->_oModule->_oTemplate->addJs(array('tasks.js'), $bDynamicMode);
+		$sResult .= ($bDynamicMode ? $sInclude : '') . $this->_oModule->_oTemplate->getJsCode('tasks');
+    	return $sResult;
+    }
+	
+    function initChecker ($aValues = array (), $aSpecificValues = array())
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        $bValues = $aValues && !empty($aValues['id']);
+        $aContentInfo = $bValues ? $this->_oModule->_oDb->getContentInfoById($aValues['id']) : false;
+
+        if($this->aParams['display'] == $CNF['OBJECT_FORM_ENTRY_DISPLAY_EDIT'] && isset($CNF['FIELD_PUBLISHED']) && isset($this->aInputs[$CNF['FIELD_PUBLISHED']]))
+            if($bValues && in_array($aValues[$CNF['FIELD_STATUS']], array('active', 'hidden')))
+                unset($this->aInputs[$CNF['FIELD_PUBLISHED']]);
+
+        if (isset($CNF['FIELD_COVER']) && isset($this->aInputs[$CNF['FIELD_COVER']])) {
+            if($bValues)
+                $this->aInputs[$CNF['FIELD_COVER']]['content_id'] = $aValues['id'];
+
+            $this->aInputs[$CNF['FIELD_COVER']]['ghost_template'] = $this->_oModule->_oTemplate->parseHtmlByName($this->_sGhostTemplateCover, $this->_getCoverGhostTmplVars($aContentInfo));
+        }
+
+        parent::initChecker ($aValues, $aSpecificValues);
+    }
+
+    public function insert ($aValsToAdd = array(), $isIgnore = false)
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        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(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']] ? 'awaiting' : 'active';
+
+        $iContentId = parent::insert ($aValsToAdd, $isIgnore);
+        if(!empty($iContentId)){
+            $this->processFiles($CNF['FIELD_COVER'], $iContentId, true);
+			
+			if(isset($this->aInputs['initial_members'])) {
+				$this->_setAssignments($iContentId, $this->aInputs['initial_members']['value']);
+			}
+        }
+        return $iContentId;
+    }
+
+    function update ($iContentId, $aValsToAdd = array(), &$aTrackTextFieldsChanges = null)
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        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;
+        }
+		
+		if(isset($this->aInputs['initial_members'])) {
+			$this->_setAssignments($iContentId, $this->aInputs['initial_members']['value']);
+		}
+		
+		$aContentInfo = $this->_oModule->_oDb->getContentInfoById($iContentId);
+		$aValsToAdd[$CNF['FIELD_ALLOW_VIEW_TO']] = $aContentInfo[$CNF['FIELD_ALLOW_VIEW_TO']];
+	
+        $iResult = parent::update ($iContentId, $aValsToAdd, $aTrackTextFieldsChanges);
+        $this->processFiles($CNF['FIELD_COVER'], $iContentId, false);   
+        return $iResult;
+    }
+
+    protected function _getCoverGhostTmplVars($aContentInfo = array())
+    {
+    	$CNF = &$this->_oModule->_oConfig->CNF;
+
+    	return array (
+            'name' => $this->aInputs[$CNF['FIELD_COVER']]['name'],
+            'content_id' => $this->aInputs[$CNF['FIELD_COVER']]['content_id'],
+            'editor_id' => isset($CNF['FIELD_TEXT_ID']) ? $CNF['FIELD_TEXT_ID'] : '',
+            'thumb_id' => isset($CNF['FIELD_THUMB']) && isset($aContentInfo[$CNF['FIELD_THUMB']]) ? $aContentInfo[$CNF['FIELD_THUMB']] : 0,
+            'name_thumb' => isset($CNF['FIELD_THUMB']) ? $CNF['FIELD_THUMB'] : ''
+        );
+    }
+
+    protected function _getPhotoGhostTmplVars($aContentInfo = array())
+    {
+    	$CNF = &$this->_oModule->_oConfig->CNF;
+
+    	return array (
+            'name' => $this->aInputs[$CNF['FIELD_PHOTO']]['name'],
+            'content_id' => (int)$this->aInputs[$CNF['FIELD_PHOTO']]['content_id'],
+            'editor_id' => isset($CNF['FIELD_TEXT_ID']) ? $CNF['FIELD_TEXT_ID'] : '',
+            'bx_if:set_thumb' => [
+				'condition' => false,
+				'content' => []
+			],
+    	);
+    }
+	
+    protected function _setAssignments($iContentId, $aMembers)
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+        $oConn = BxDolConnection::getObjectInstance($CNF['OBJECT_CONNECTION']);
+
+        $aMembers2 = $oConn->getConnectedInitiators($iContentId);
+
+        $aMembersToAdd = [];
+        $aMembersToRemove = $aMembers2;
+        if (is_array($aMembers)){
+            $aMembersToAdd = array_diff($aMembers, $aMembers2);
+            $aMembersToRemove = array_diff($aMembers2, $aMembers);
+        }    
+
+        $aContentInfo = $this->_oModule->_oDb->getContentInfoById($iContentId);
+
+        foreach($aMembersToAdd as $iProfileId){
+            $oConn->addConnection($iProfileId, $iContentId);
+
+            bx_alert($this->MODULE, 'assigned', $iContentId, false, array(
+                'object_author_id' => $iProfileId,
+                'privacy_view' => $aContentInfo[$CNF['FIELD_ALLOW_VIEW_TO']]
+            ));
+        }
+
+        foreach($aMembersToRemove as $iProfileId){
+            $oConn->removeConnection($iProfileId, $iContentId);
+
+            bx_alert($this->MODULE, 'unassigned', $iContentId, false, array(
+                'object_author_id' => $iProfileId,
+                'privacy_view' => $aContentInfo[$CNF['FIELD_ALLOW_VIEW_TO']]
+            ));
+        }
+    }
+	
+	protected function genCustomInputInitialMembers ($aInput)
+    {
+        $aInput['ajax_get_suggestions'] = BX_DOL_URL_ROOT . "modules/?r=" . $this->_oModule->_oConfig->getUri() . "/ajax_get_initial_members";
+        return $this->genCustomInputUsernamesSuggestions($aInput);
+    }
+	
+	protected function genCustomInputTasksList(&$aInput)
+    {
+        return $this->genInputStandard($aInput);
+    }
+}
+
+/** @} */

+ 727 - 0
modules/boonex/tasks/updates/13.0.5_13.0.6/source/classes/BxTasksModule.php

@@ -0,0 +1,727 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT 
+ * @defgroup    Tasks Tasks
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+/**
+ * Tasks module
+ */
+class BxTasksModule extends BxBaseModTextModule implements iBxDolCalendarService 
+{
+    function __construct(&$aModule)
+    {
+        parent::__construct($aModule);
+
+        $CNF = &$this->_oConfig->CNF;
+        $this->_aSearchableNamesExcept = array_merge($this->_aSearchableNamesExcept, array(
+            $CNF['FIELD_PUBLISHED'],
+            $CNF['FIELD_ALLOW_COMMENTS']
+        ));
+    }
+	
+    /**
+    * Action methods
+    */
+	
+    /**
+     * Get possible recipients for start conversation form
+     */
+    public function actionAjaxGetInitialMembers ()
+    {
+        $sTerm = bx_get('term');
+
+        $a = BxDolService::call('system', 'profiles_search', array($sTerm), 'TemplServiceProfiles');
+
+        header('Content-Type:text/javascript; charset=utf-8');
+        echo(json_encode($a));
+    }
+          
+    public function actionSetCompleted($iContentId, $iValue)
+    {
+        if (!$this->isAllowManage($iContentId))
+            return;
+        
+        $CNF = &$this->_oConfig->CNF;
+
+        $this->_oDb->updateEntriesBy(array($CNF['FIELD_COMPLETED'] => $iValue), array($CNF['FIELD_ID'] => (int)$iContentId));
+
+        $sActionName = 'completed';
+        if($iValue == '0')
+            $sActionName = 'reopened';
+
+        $aContentInfo = $this->_oDb->getContentInfoById($iContentId);
+
+        $iContentAuthor = (int)$aContentInfo[$CNF['FIELD_AUTHOR']];
+        bx_alert($this->getName(), $sActionName, $iContentId, false, array(
+            'object_author_id' => $iContentAuthor,
+            'privacy_view' => $aContentInfo[$CNF['FIELD_ALLOW_VIEW_TO']]
+        ));
+
+        $oConnection = BxDolConnection::getObjectInstance($CNF['OBJECT_CONNECTION']);
+        if($oConnection) {
+            $aProfileIds = $oConnection->getConnectedContent($iContentId);
+            if(!empty($aProfileIds) && is_array($aProfileIds))
+                foreach($aProfileIds as $iProfileId) {
+                    if($iProfileId == $iContentAuthor)
+                        continue;
+
+                    bx_alert($this->getName(), $sActionName, $iContentId, false, array(
+                        'object_author_id' => $iProfileId,
+                        'privacy_view' => $aContentInfo[$CNF['FIELD_ALLOW_VIEW_TO']]
+                    ));
+                }
+        }
+
+        echo 'ok';
+    }
+	
+	public function actionSetFilterValue($iListId, $sValue)
+	{
+		$CNF = &$this->_oConfig->CNF;
+		$aTmp = array();
+		if (isset($_COOKIE[$CNF['COOKIE_SETTING_KEY']]))
+			$aTmp =	json_decode($_COOKIE[$CNF['COOKIE_SETTING_KEY']], true);
+			
+		if ($sValue != '')
+			$aTmp[$iListId] = $sValue;
+		else
+			unset($aTmp[$iListId]);
+        bx_setcookie($CNF['COOKIE_SETTING_KEY'], json_encode($aTmp), time() + 60*60*24*365);
+	}
+	
+	public function actionProcessTaskListForm($iContextId, $iId)
+    {
+        if (!$this->isAllowAdd(-$iContextId))
+            return;
+        
+		$CNF = &$this->_oConfig->CNF;
+		$oForm = null;
+		$sPopupTitle = "";
+		$aContentInfo = array();
+		if ($iId == 0){
+			$oForm = BxDolForm::getObjectInstance($CNF['OBJECT_FORM_LIST_ENTRY'], $CNF['OBJECT_FORM_LIST_ENTRY_DISPLAY_ADD']);
+			$sPopupTitle = _t('_bx_tasks_form_list_entry_display_add');
+		}
+		else{
+			$oForm = BxDolForm::getObjectInstance($CNF['OBJECT_FORM_LIST_ENTRY'], $CNF['OBJECT_FORM_LIST_ENTRY_DISPLAY_EDIT']);
+			$aContentInfo = $this->_oDb->getList($iId);
+			$sPopupTitle = _t('_bx_tasks_form_list_entry_display_edit');
+		}
+		
+		$oForm->aFormAttrs['action'] = BX_DOL_URL_ROOT . $this->_oConfig->getBaseUri() . 'process_task_list_form/' . $iContextId . '/' . $iId . '/';
+		if (!$oForm)
+            return '';
+		
+		$oForm->initChecker($aContentInfo, array());
+		
+        if($oForm->isSubmittedAndValid()) {
+			if ($iId == 0){
+				$aValsToAdd['context_id'] = $iContextId;
+				$iId = $oForm->insert($aValsToAdd);
+			}
+			else{
+				$iId = $oForm->update($iId);
+			}
+
+			return echoJson(array(
+				 'eval' => $this->_oConfig->getJsObject('tasks') . '.reloadData(oData, ' . $iContextId . ')',
+			));
+        }
+        else {	
+			$sContent = $this->_oTemplate->parseHtmlByName('popup_form.html', array(
+				'form_id' => $oForm->getId(),
+				'form' => $oForm->getCode(true)
+			));
+																	 
+			if (!$oForm->isSubmitted()){
+				echo $sContent;
+				return;
+			}
+			
+            return echoJson(array('form' => $sContent, 'form_id' => $oForm->getId()));;
+        }
+	}
+    
+    public function actionDeleteTaskList($iId, $iContextId)
+    {
+        if (!$this->isAllowManageByContext($iContextId))
+            return;
+        
+        $this->_oDb->deleteList($iId);  
+        echoJson(array(
+            'context_id' => $iContextId,
+        ));
+    }
+	
+	public function actionProcessTaskForm($iContextId, $iListId)
+    {
+        if (!$this->isAllowAdd(-$iContextId))
+            return;
+        
+		$CNF = &$this->_oConfig->CNF;
+		$oForm = BxDolForm::getObjectInstance($CNF['OBJECT_FORM_ENTRY'], $CNF['OBJECT_FORM_ENTRY_DISPLAY_ADD']);
+		
+		$oForm->aFormAttrs['action'] = BX_DOL_URL_ROOT . $this->_oConfig->getBaseUri() . 'process_task_form/' . $iContextId . '/' . $iListId . '/';
+		if (!$oForm)
+            return '';
+		
+		$oForm->initChecker();
+		
+        if($oForm->isSubmittedAndValid()) {
+			$aValsToAdd[$CNF['FIELD_ALLOW_VIEW_TO']] = $iContextId;
+			$aValsToAdd[$CNF['FIELD_TASKLIST']] = $iListId;
+			$iContentId = $oForm->insert($aValsToAdd);
+			$this->onPublished($iContentId);
+			
+			return echoJson(array(
+				 'eval' => $this->_oConfig->getJsObject('tasks') . '.reloadData(oData, ' . $iContextId . ')',
+			));
+        }
+        else {	
+			$sContent = $this->_oTemplate->parseHtmlByName('popup_form.html', array(
+				'form_id' => $oForm->getId(),
+				'form' => $oForm->getCode(true)
+			));
+																	 
+			if (!$oForm->isSubmitted()){
+				echo $sContent;
+				return;
+			}
+            return echoJson(array('form' => $sContent, 'form_id' => $oForm->getId()));;
+        }
+	}
+	
+	public function actionCalendarData()
+    {
+        // check permissions
+        $aSQLPart = array();
+        $iContextId = (int)bx_get('context_id');
+        
+        if (!$this->isAllowView($iContextId))
+            return; 
+		
+		$oPrivacy = BxDolPrivacy::getObjectInstance($this->_oConfig->CNF['OBJECT_PRIVACY_VIEW']);
+		
+		if($iContextId){
+			$aSQLPart = $oPrivacy ? $oPrivacy->getContentByGroupAsSQLPart(- $iContextId) : array();
+		}
+        // get entries
+        $aEntries = $this->_oDb->getEntriesByDate(bx_get('start'), bx_get('end'), bx_get('event'), $aSQLPart);
+        
+        header('Content-Type: application/json; charset=utf-8');
+        echo json_encode($aEntries);
+    }
+	
+	/**
+     * Data for Timeline module
+     */
+    public function serviceGetTimelineData()
+    {
+    	$sModule = $this->_aModule['name'];
+        return array(
+            'handlers' => array(
+                array('group' => $sModule . '_object', 'type' => 'insert', 'alert_unit' => $sModule, 'alert_action' => 'added', 'module_name' => $sModule, 'module_method' => 'get_timeline_post', 'module_class' => 'Module', 'groupable' => 0, 'group_by' => ''),
+				array('group' => $sModule . '_completed', 'type' => 'insert', 'alert_unit' => $sModule, 'alert_action' => 'completed', 'module_name' => $sModule, 'module_method' => 'get_timeline_completed', 'module_class' => 'Module',  'groupable' => 0, 'group_by' => ''),
+				array('group' => $sModule . '_reopened', 'type' => 'insert', 'alert_unit' => $sModule, 'alert_action' => 'reopened', 'module_name' => $sModule, 'module_method' => 'get_timeline_reopened', 'module_class' => 'Module',  'groupable' => 0, 'group_by' => ''),
+                array('group' => $sModule . '_object', 'type' => 'update', 'alert_unit' => $sModule, 'alert_action' => 'edited'),
+                array('group' => $sModule . '_object', 'type' => 'delete', 'alert_unit' => $sModule, 'alert_action' => 'deleted'),
+            ),
+            'alerts' => array(
+                array('unit' => $sModule, 'action' => 'added'),
+				array('unit' => $sModule, 'action' => 'completed'),
+				array('unit' => $sModule, 'action' => 'reopened'),
+                array('unit' => $sModule, 'action' => 'edited'),
+                array('unit' => $sModule, 'action' => 'deleted'),
+            )
+        );
+    }
+	
+    /**
+     * Entry task for Timeline module
+     */
+    public function serviceGetTimelinePost($aEvent, $aBrowseParams = array())
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $aResult = parent::serviceGetTimelinePost($aEvent, $aBrowseParams);
+        if(empty($aResult) || !is_array($aResult) || empty($aResult['date']))
+            return $aResult;
+        $aContentInfo = $this->_oDb->getContentInfoById($aEvent['object_id']);
+        if($aContentInfo[$CNF['FIELD_PUBLISHED']] > $aResult['date'])
+            $aResult['date'] = $aContentInfo[$CNF['FIELD_PUBLISHED']];
+        return $aResult;
+    }
+	
+	public function serviceGetTimelineCompleted($aEvent, $aBrowseParams = array())
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $aResult = parent::serviceGetTimelinePost($aEvent, $aBrowseParams);
+		$aResult['sample_action'] = $aResult['content']['sample_action'] = _t('_bx_tasks_txt_action_completed');
+        if(empty($aResult) || !is_array($aResult) || empty($aResult['date']))
+            return $aResult;
+		
+        $aContentInfo = $this->_oDb->getContentInfoById($aEvent['object_id']);
+        if($aContentInfo[$CNF['FIELD_PUBLISHED']] > $aResult['date'])
+            $aResult['date'] = $aContentInfo[$CNF['FIELD_PUBLISHED']];
+        return $aResult;
+    }
+	
+	public function serviceGetTimelineReopened($aEvent, $aBrowseParams = array())
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $aResult = parent::serviceGetTimelinePost($aEvent, $aBrowseParams);
+		$aResult['sample_action'] = $aResult['content']['sample_action'] = _t('_bx_tasks_txt_action_reopened');
+        if(empty($aResult) || !is_array($aResult) || empty($aResult['date']))
+            return $aResult;
+		
+        $aContentInfo = $this->_oDb->getContentInfoById($aEvent['object_id']);
+        if($aContentInfo[$CNF['FIELD_PUBLISHED']] > $aResult['date'])
+            $aResult['date'] = $aContentInfo[$CNF['FIELD_PUBLISHED']];
+        return $aResult;
+    }
+
+    public function serviceGetNotificationsData()
+    {
+        $sModule = $this->_aModule['name'];
+
+        $sEventPrivacy = $sModule . '_allow_view_event_to';
+        if(BxDolPrivacy::getObjectInstance($sEventPrivacy) === false)
+                $sEventPrivacy = '';
+
+        $aResult = parent::serviceGetNotificationsData();
+        $aResult['handlers'] = array_merge($aResult['handlers'], array(
+            array('group' => $sModule . '_completed', 'type' => 'insert', 'alert_unit' => $sModule, 'alert_action' => 'completed', 'module_name' => $sModule, 'module_method' => 'get_notifications_completed', 'module_class' => 'Module', 'module_event_privacy' => $sEventPrivacy),
+            array('group' => $sModule . '_reopened', 'type' => 'insert', 'alert_unit' => $sModule, 'alert_action' => 'reopened', 'module_name' => $sModule, 'module_method' => 'get_notifications_reopened', 'module_class' => 'Module', 'module_event_privacy' => $sEventPrivacy),
+            array('group' => $sModule . '_expired', 'type' => 'insert', 'alert_unit' => $sModule, 'alert_action' => 'expired', 'module_name' => $sModule, 'module_method' => 'get_notifications_expired', 'module_class' => 'Module', 'module_event_privacy' => $sEventPrivacy),
+
+            array('group' => $sModule . '_assign', 'type' => 'insert', 'alert_unit' => $sModule, 'alert_action' => 'assigned', 'module_name' => $sModule, 'module_method' => 'get_notifications_assigned', 'module_class' => 'Module', 'module_event_privacy' => $sEventPrivacy),
+            array('group' => $sModule . '_assign', 'type' => 'delete', 'alert_unit' => $sModule, 'alert_action' => 'unassigned'),
+        ));
+
+        $aResult['settings'] = array_merge($aResult['settings'], array(
+            array('group' => 'content', 'unit' => $sModule, 'action' => 'completed', 'types' => array('personal', 'follow_member', 'follow_context')),
+            array('group' => 'content', 'unit' => $sModule, 'action' => 'reopened', 'types' => array('personal', 'follow_member', 'follow_context')),
+            array('group' => 'content', 'unit' => $sModule, 'action' => 'expired', 'types' => array('personal')),
+            array('group' => 'content', 'unit' => $sModule, 'action' => 'assigned', 'types' => array('personal')),
+        ));
+
+        $aResult['alerts'] = array_merge($aResult['alerts'], array(
+            array('unit' => $sModule, 'action' => 'completed'),
+            array('unit' => $sModule, 'action' => 'reopened'),
+            array('unit' => $sModule, 'action' => 'expired'),
+
+            array('unit' => $sModule, 'action' => 'assigned'),
+            array('unit' => $sModule, 'action' => 'unassigned'),
+        ));
+
+        return $aResult; 
+    }
+
+    public function serviceGetNotificationsCompleted($aEvent)
+    {
+        return $this->_serviceGetNotificationsByAction($aEvent, 'completed');
+    }
+
+    public function serviceGetNotificationsReopened($aEvent)
+    {
+        return $this->_serviceGetNotificationsByAction($aEvent, 'reopened');
+    }
+
+    public function serviceGetNotificationsExpired($aEvent)
+    {
+        return $this->_serviceGetNotificationsByAction($aEvent, 'expired');
+    }
+
+    public function serviceGetNotificationsAssigned($aEvent)
+    {
+        return $this->_serviceGetNotificationsByAction($aEvent, 'assigned');
+    }
+
+    protected function _serviceGetNotificationsByAction($aEvent, $sAction)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $aResult = parent::serviceGetNotificationsPost($aEvent);
+        if(empty($aResult) || !is_array($aResult))
+            return $aResult;
+
+        $aResult['entry_author'] = $aEvent['object_owner_id'];
+        $aResult['entry_author_name'] = '';
+        if(($oAuthor = BxDolProfile::getInstance($aResult['entry_author'])) !== false)
+            $aResult['entry_author_name'] = $oAuthor->getDisplayName();
+
+        $sLangKey = '_bx_tasks_txt_notification_' . $sAction;
+        if((int)$aEvent['object_privacy_view'] < 0)
+            $sLangKey .= '_in_context';
+
+        $aResult['lang_key'] = _t($sLangKey);
+        return $aResult;
+    }
+
+    public function serviceIsCompleted($iContentId)
+    {
+        if (!$this->serviceIsAllowManage($iContentId))
+            return false;
+        
+        $CNF = &$this->_oConfig->CNF;
+
+        $aContentInfo = $this->_oDb->getContentInfoById($iContentId);
+        return $aContentInfo[$CNF['FIELD_COMPLETED']] ? false: true;
+    }
+    
+    public function serviceIsUncompleted($iContentId)
+    {
+        if (!$this->serviceIsAllowManage($iContentId))
+            return false;
+        
+		$CNF = &$this->_oConfig->CNF;
+		$aContentInfo = $this->_oDb->getContentInfoById($iContentId);
+        return $aContentInfo[$CNF['FIELD_COMPLETED']] ? true : false;
+    }
+    
+    public function serviceIsAllowManage($iContentId)
+    {
+        if (!$this->isAllowManage($iContentId))
+            return false;
+        return true; 
+    }
+    
+    public function serviceIsAllowBadges($iContentId)
+    {
+        if (!$this->isAllowManage($iContentId))
+            return false;
+        
+        if (!$this->serviceIsBadgesAvaliable())
+            return false;
+        
+        return true; 
+    }
+	
+	public function serviceEntityAssignments($iContentId = 0, $bAsArray = false)
+	{
+		if (!$iContentId)
+            $iContentId = bx_process_input(bx_get('id'), BX_DATA_INT);
+        if (!$iContentId)
+            return false;
+
+		$mixedResult = BxDolConnection::getObjectInstance($this->_oConfig->CNF['OBJECT_CONNECTION'])->getConnectedInitiators($iContentId);
+        if(!$bAsArray) {
+			$s = '';
+            foreach ($mixedResult as $mixedProfile) {
+				$bProfile = is_array($mixedProfile);
+
+				$oProfile = BxDolProfile::getInstance($bProfile ? (int)$mixedProfile['id'] : (int)$mixedProfile);
+				if(!$oProfile)
+					continue;
+
+				$aUnitParams = array('template' => array('name' => 'unit', 'size' => 'thumb'));
+
+				if($bProfile && is_array($mixedProfile['info']))
+					$aUnitParams['template']['vars'] = $mixedProfile['info'];
+
+				$s .= $oProfile->getUnit(0, $aUnitParams);
+			}
+			$mixedResult = $s;
+			
+            if (!$mixedResult)
+                return MsgBox(_t('_sys_txt_empty'));
+        }
+
+        return $mixedResult;
+    }
+	
+    public function serviceCheckAllowedCommentsTask($iContentId, $sObjectComments) 
+    {
+        $CNF = &$this->_oConfig->CNF;
+        $aContentInfo = $this->_oDb->getContentInfoById($iContentId);
+        if ($aContentInfo[$CNF['FIELD_ALLOW_COMMENTS']] == 0)
+            return false;
+
+        return parent::serviceCheckAllowedCommentsTask($iContentId, $sObjectComments);
+    }
+	
+	public function serviceCheckAllowedCommentsView($iContentId, $sObjectComments) 
+    {
+        $CNF = &$this->_oConfig->CNF;
+        $aContentInfo = $this->_oDb->getContentInfoById($iContentId);
+        if ($aContentInfo[$CNF['FIELD_ALLOW_COMMENTS']] == 0)
+            return false;
+
+        return parent::serviceCheckAllowedCommentsView($iContentId, $sObjectComments);
+    }
+	
+	/**
+     * @page service Service Calls
+     * @section bx_tasks Tasks
+     * @subsection bx_tasks-page_blocks Page Blocks
+     * @subsubsection bx_tasks-calendar calendar
+     * 
+     * @code bx_srv('bx_tasks', 'calendar', [...]); @endcode
+     * 
+     * Shows tasks calendar baced on die date
+     * 
+     * @param $aData additional data to point which events to show, leave empty to show all events, specify event's ID in 'event' array key to show calendar for one event only, specify context's ID in 'context_id' array key to show calendar for one context events only. If only one event is specified then it will show calendar only if it's repeating event.
+     * @param $sTemplate template to use to show calendar, or leave empty for default template, possible options: calendar.html, calendar_compact.html
+     * @return HTML string with calendar to display on the site, all necessary CSS and JS files are automatically added to the HEAD section of the site HTML. On error empty string is returned.
+     *
+     * @see BxTasksModule::serviceCalendar
+     */
+    /** 
+     * @ref bx_tasks-calendar "calendar"
+     */
+    public function serviceCalendar($aData = array(), $sTemplate = 'calendar.html')
+    {
+        if (!$this->isAllowView($aData['context_id']))
+            return; 
+        
+        $o = new BxTemplCalendar(array(
+            'eventSources' => array (
+                bx_append_url_params(BX_DOL_URL_ROOT . $this->_oConfig->getBaseUri() . 'calendar_data', $aData),
+            ),
+        ), $this->_oTemplate);
+        return $o->display($sTemplate);
+    }
+	
+	public function serviceGetCalendarEntries($iProfileId)
+    {
+		$CNF = &$this->_oConfig->CNF;
+        $oConn = BxDolConnection::getObjectInstance($CNF['OBJECT_CONNECTION']);
+        $aData = $oConn->getConnectedInitiators($iProfileId);
+		$aData2 = array(0);
+        foreach($aData as $iProfileId2){
+            $oProfile = BxDolProfile::getInstance($iProfileId2);
+            array_push($aData2, $oProfile->getContentId());
+        }
+        $aSQLPart['where'] = " AND " . $CNF['TABLE_ENTRIES'] . ".`" . $CNF['FIELD_ID'] . "` IN(" . implode(',', $aData2) . ")";
+        return $this->_oDb->getEntriesByDate(bx_get('start'), bx_get('end'), null, $aSQLPart);
+	}
+	
+	public function serviceBrowseContext ($iProfileId = 0, $aParams = array())
+    {
+		if(!$iProfileId)
+            $iProfileId = bx_process_input(bx_get('profile_id'), BX_DATA_INT);
+        if(!$iProfileId)
+            return '';
+        return $this->serviceBrowseTasks (-$iProfileId, $aParams);
+    }
+	
+	public function serviceBrowseTasks ($iContextId = 0, $aParams = array())
+    {
+        if (!$this->isAllowView(-$iContextId))
+            return;  
+        
+        $oProfileContext = BxDolProfile::getInstance(-$iContextId);
+        $mixedResult = $oProfileContext->checkAllowedProfileView(-$iContextId);
+        if($mixedResult !== CHECK_ACTION_RESULT_ALLOWED)
+            return false;
+        
+		$CNF = &$this->_oConfig->CNF;
+		
+		$this->_oTemplate->addCssJs();
+		$aVars = array();
+		$aLists = $this->_oDb->getLists($iContextId);
+		$aListsVars = array();
+		$oConn = BxDolConnection::getObjectInstance($CNF['OBJECT_CONNECTION']);
+		
+		$aFilterValues = array();
+		if (isset($_COOKIE[$CNF['COOKIE_SETTING_KEY']]))
+			$aFilterValues = json_decode($_COOKIE[$CNF['COOKIE_SETTING_KEY']], true);
+
+        $bAllowAdd = $this->isAllowAdd(-$iContextId);
+        $bAllowManage = $this->isAllowManageByContext(-$iContextId);
+        
+        foreach($aLists as $aList) {
+			$aTasks = $this->_oDb->getTasks($iContextId, $aList['id']);
+			$aTasksVars = array();
+			foreach($aTasks as $aTask) {
+				$aMembers = $oConn->getConnectedContent($aTask[$CNF['FIELD_ID']]);
+				$aMembersVars = array();
+				foreach($aMembers as $iMember) {
+					$oProfile = BxDolProfile::getInstance($iMember);
+                    if($oProfile && !($oProfile instanceof BxDolProfileUndefined))
+					   $aMembersVars[] = array('info' => $oProfile->getUnit(0, array('template' => 'unit_wo_info')));
+				}
+				$aTasksVars[] = array(
+					'id' => $aTask[$CNF['FIELD_ID']],
+					'title' => bx_process_output($aTask[$CNF['FIELD_TITLE']]),
+					'created' => bx_time_js($aTask[$CNF['FIELD_ADDED']]),
+					'class' => $aTask[$CNF['FIELD_COMPLETED']] == 1 ? 'completed' : 'uncompleted',
+					'due' => $aTask[$CNF['FIELD_DUEDATE']] > 0 ? bx_time_js($aTask[$CNF['FIELD_DUEDATE']]) : '',
+					'bx_repeat:members' => $aMembersVars,
+					'badges' => $this->serviceGetBadges($aTask[$CNF['FIELD_ID']], true),
+					'url' => bx_absolute_url(BxDolPermalinks::getInstance()->permalink('page.php?i=' . $CNF['URI_VIEW_ENTRY'] . '&id=' . $aTask[$CNF['FIELD_ID']])),
+					'object' => $this->_oConfig->getJsObject('tasks'),
+                    'bx_if:allow_manage' => array(
+				        'condition' => $bAllowManage,
+				        'content' => array(
+                            'id' => $aTask[$CNF['FIELD_ID']],
+                            'object' => $this->_oConfig->getJsObject('tasks'),
+                            'checked' => $aTask[$CNF['FIELD_COMPLETED']] == 1 ? 'checked' : '',
+                        )
+			        ),
+                    'bx_if:deny_manage' => array(
+				        'condition' => !$bAllowManage,
+				        'content' => array(
+                            'id' => $aTask[$CNF['FIELD_ID']],
+                            'checked' => $aTask[$CNF['FIELD_COMPLETED']] == 1 ? 'checked' : '',
+                        )
+			        ),
+				);
+			}
+            
+			$sClass = $sCompleted = $sAll = "";
+			if (isset($aFilterValues[$aList[$CNF['FIELD_ID']]])){
+				$sClass = $aFilterValues[$aList[$CNF['FIELD_ID']]];
+				if ($sClass == 'completed')
+					$sCompleted= 'selected';
+				if ($sClass == 'all')
+					$sAll = 'selected';
+			}
+            
+			$aListsVars[] = array(
+               'bx_if:allow_edit_list' => array(
+				    'condition' => $bAllowAdd,
+				    'content' => array(
+                        'title' => $aList[$CNF['FIELD_TITLE']],
+                        'context_id' => $iContextId,
+                        'list_id' => $aList[$CNF['FIELD_ID']],
+                        'object' => $this->_oConfig->getJsObject('tasks'),
+                    )
+			    ),
+               'bx_if:allow_add' => array(
+				    'condition' => $bAllowAdd,
+				    'content' => array(
+                        'context_id' => $iContextId,
+                        'list_id' => $aList[$CNF['FIELD_ID']],
+                        'object' => $this->_oConfig->getJsObject('tasks'),
+                    )
+			    ),
+                'bx_if:allow_delete_list' => array(
+				    'condition' => $bAllowManage,
+				    'content' => array(
+                        'context_id' => $iContextId,
+                        'list_id' => $aList[$CNF['FIELD_ID']],
+                        'object' => $this->_oConfig->getJsObject('tasks'),
+                    )
+			    ),
+                'bx_if:deny_edit_list' => array(
+				    'condition' => !$bAllowAdd,
+				    'content' => array(
+                        'title' => $aList[$CNF['FIELD_TITLE']],
+                    )
+			    ),
+				'id' => $aList['id'],
+				'bx_repeat:tasks' =>  $aTasksVars,
+				'context_id' => $iContextId,
+				'list_id' => $aList[$CNF['FIELD_ID']],
+				'object' => $this->_oConfig->getJsObject('tasks'),
+				'class' => $sClass,
+				'completed' => $sCompleted,
+				'all' => $sAll,
+			);
+		}
+		
+		$aVars = array(
+			'bx_repeat:task_lists' => $aListsVars,
+			'bx_if:allow_add_list' => array(
+				'condition' => $bAllowAdd,
+				'content' => array(
+                    'context_id' => $iContextId,
+                    'object' => $this->_oConfig->getJsObject('tasks'),
+                )
+			),
+		);
+		
+		$this->_oTemplate->addJs(array(
+			'jquery-ui/jquery-ui.min.js',
+			'tasks.js',
+            'modules/base/general/js/|forms.js'
+    	));
+		
+		return $this->_oTemplate->getJsCode('tasks', array('t_confirm_block_deletion' => _t('_bx_tasks_confirm_tasklist_deletion'))) . $this->_oTemplate->parseHtmlByName('browse_tasks.html', $aVars);
+    }
+	
+    /**
+    * Common methods
+    */
+    public function onExpired($iContentId)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $aContentInfo = $this->_oDb->getContentInfoById($iContentId);
+        if(!$aContentInfo)
+            return;
+
+        $oConnection = BxDolConnection::getObjectInstance($CNF['OBJECT_CONNECTION']);
+        if($oConnection) {
+            $aProfileIds = $oConnection->getConnectedContent($iContentId);
+            if(!empty($aProfileIds) && is_array($aProfileIds))
+                foreach($aProfileIds as $iProfileId)
+                    bx_alert($this->getName(), 'expired', $iContentId, false, array(
+                        'object_author_id' => $iProfileId,
+                        'privacy_view' => $aContentInfo[$CNF['FIELD_ALLOW_VIEW_TO']]
+                    ));
+        }
+    }
+    
+    function isAllowView($iContextId)
+    {
+        $oProfileContext = BxDolProfile::getInstance($iContextId);
+        $mixedResult = $oProfileContext->checkAllowedProfileView($iContextId);
+        if($mixedResult !== CHECK_ACTION_RESULT_ALLOWED)
+            return false;
+        return true;
+    }
+    
+    function isAllowAdd($iContextId)
+    {
+        $oProfileContext = BxDolProfile::getInstance($iContextId);
+        $mixedResult = $oProfileContext->checkAllowedPostInProfile($iContextId);
+        if($mixedResult !== CHECK_ACTION_RESULT_ALLOWED)
+            return false;
+        return true;
+    }
+    
+    function isAllowManageByContext($iContextId)
+    {
+        if(isAdmin())
+            return true;
+      
+        $oProfileContext = BxDolProfile::getInstance($iContextId);
+        if(BxDolService::call($oProfileContext->getModule(), 'is_admin', array($iContextId)))
+            return true;
+    }
+    
+    function isAllowManage($iContentId)
+    {
+        $CNF = &$this->_oConfig->CNF;
+        
+        $aContentInfo = $this->_oDb->getContentInfoById($iContentId);
+        $bRv = $this->isAllowManageByContext(-$aContentInfo[$CNF['FIELD_ALLOW_VIEW_TO']]);
+        if ($bRv)
+            return $bRv;
+        
+        if ($aContentInfo[$CNF['FIELD_AUTHOR']] == bx_get_logged_profile_id())
+            return true;
+       
+        $oConnection = BxDolConnection::getObjectInstance($CNF['OBJECT_CONNECTION']);
+        if($oConnection) {
+            $aProfileIds = $oConnection->getConnectedContent($iContentId);
+            if(!empty($aProfileIds) && is_array($aProfileIds)){
+                if (in_array(bx_get_logged_profile_id(), $aProfileIds))
+                    return true;
+            }
+        }
+
+        return false;
+    }
+}
+
+/** @} */

+ 149 - 0
modules/boonex/tasks/updates/13.0.5_13.0.6/source/install/config.php

@@ -0,0 +1,149 @@
+<?php
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT 
+ * @defgroup    Tasks Tasks
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+$aConfig = array(
+
+    /**
+     * Main Section.
+     */
+    'type' => BX_DOL_MODULE_TYPE_MODULE,
+    'name' => 'bx_tasks',
+    'title' => 'Tasks',
+    'note' => 'Tasks module.',
+    'version' => '13.0.6',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '13.1.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/tasks/',
+    'home_uri' => 'tasks',
+
+    'db_prefix' => 'bx_tasks_',
+    'class_prefix' => 'BxTasks',
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Tasks',
+
+    /**
+     * List of page triggers.
+     */
+    'page_triggers' => array (
+    	'trigger_page_profile_view_entry',
+    ),
+    
+    /**
+     * Menu triggers.
+     */
+    'menu_triggers' => array(
+        'trigger_profile_view_submenu',
+        'trigger_group_view_submenu',
+    ),
+
+    /**
+     * Storage objects to automatically delete files from upon module uninstallation.
+     * Note. Don't add storage objects used in transcoder objects.
+     */
+    'storages' => array(
+        'bx_tasks_covers',
+    	'bx_tasks_photos',
+        'bx_tasks_videos',
+        'bx_tasks_files'
+    ),
+
+    /**
+     * Transcoders.
+     */
+    'transcoders' => array(
+        'bx_tasks_preview',
+        'bx_tasks_gallery',
+        'bx_tasks_cover',
+
+        'bx_tasks_preview_photos',
+        'bx_tasks_gallery_photos', 
+
+        'bx_tasks_videos_poster',
+        'bx_tasks_videos_poster_preview',
+        'bx_tasks_videos_mp4',
+        'bx_tasks_videos_mp4_hd',
+
+        'bx_tasks_preview_files',
+        'bx_tasks_gallery_files'
+    ),
+
+    /**
+     * Extended Search Forms.
+     */
+    'esearches' => array(
+        'bx_tasks',
+    	'bx_tasks_cmts'
+    ),
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_languages' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'uninstall' => array (
+    	'process_esearches' => 1,
+        'execute_sql' => 1,
+        'update_languages' => 1,
+        'update_relations' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'enable' => array(
+        'execute_sql' => 1,
+        'update_relations' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'enable_success' => array(
+        'process_menu_triggers' => 1,
+        'process_page_triggers' => 1,
+    	'process_esearches' => 1,
+        'register_transcoders' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable' => array (
+        'execute_sql' => 1,
+        'update_relations' => 1,
+        'unregister_transcoders' => 1,
+        'clear_db_cache' => 1,
+    ),
+    'disable_failed' => array (
+        'register_transcoders' => 1,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Dependencies Section
+     */
+    'dependencies' => array(),
+
+    /**
+     * Relations Section
+     */
+    'relations' => array(
+    	'bx_timeline',
+    	'bx_notifications'
+    ),
+
+);
+
+/** @} */

+ 559 - 0
modules/boonex/tasks/updates/13.0.5_13.0.6/source/install/sql/install.sql

@@ -0,0 +1,559 @@
+-- TABLE: entries
+CREATE TABLE IF NOT EXISTS `bx_tasks_tasks` (
+  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+  `author` int(11) NOT NULL,
+  `added` int(11) NOT NULL,
+  `changed` int(11) NOT NULL,
+  `published` int(11) NOT NULL,
+  `thumb` int(11) NOT NULL,
+  `title` varchar(255) NOT NULL,
+  `cat` int(11) NOT NULL,
+  `multicat` text NOT NULL,
+  `text` mediumtext NOT NULL,
+  `labels` text NOT NULL,
+  `views` int(11) NOT NULL default '0',
+  `rate` float NOT NULL default '0',
+  `votes` int(11) NOT NULL default '0',
+  `rrate` float NOT NULL default '0',
+  `rvotes` int(11) NOT NULL default '0',
+  `score` int(11) NOT NULL default '0',
+  `sc_up` int(11) NOT NULL default '0',
+  `sc_down` int(11) NOT NULL default '0',
+  `favorites` int(11) NOT NULL default '0',
+  `comments` int(11) NOT NULL default '0',
+  `reports` int(11) NOT NULL default '0',
+  `featured` int(11) NOT NULL default '0',
+  `due_date` int(11) NOT NULL,
+  `tasks_list` int(11) NOT NULL,	
+  `completed` tinyint(4) NOT NULL DEFAULT '0', 
+  `expired` tinyint(4) NOT NULL DEFAULT '0', 
+  `cf` int(11) NOT NULL default '1',
+  `allow_view_to` varchar(16) NOT NULL DEFAULT '3',
+  `allow_comments` tinyint(4) NOT NULL DEFAULT '1',
+  `status` enum('active','awaiting','failed','hidden') NOT NULL DEFAULT 'active',
+  `status_admin` enum('active','hidden','pending') NOT NULL DEFAULT 'active',
+  PRIMARY KEY (`id`),
+  FULLTEXT KEY `title_text` (`title`,`text`)
+);
+
+-- TABLE: task-lists
+CREATE TABLE IF NOT EXISTS `bx_tasks_lists` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `context_id` int(11) NOT NULL,
+  `title` varchar(255) NOT NULL,
+  PRIMARY KEY (`id`)
+);
+
+-- TABLE: assignment
+CREATE TABLE IF NOT EXISTS `bx_tasks_assignments` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `initiator` int(11) NOT NULL,
+  `content` int(11) NOT NULL,
+  `added` int(10) unsigned NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `initiator` (`initiator`,`content`),
+  KEY `content` (`content`)
+);
+
+-- TABLE: storages & transcoders
+CREATE TABLE IF NOT EXISTS `bx_tasks_covers` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `profile_id` int(10) unsigned NOT NULL,
+  `remote_id` varchar(128) NOT NULL,
+  `path` varchar(255) NOT NULL,
+  `file_name` varchar(255) NOT NULL,
+  `mime_type` varchar(128) NOT NULL,
+  `ext` varchar(32) NOT NULL,
+  `size` bigint(20) NOT NULL,
+  `added` int(11) NOT NULL,
+  `modified` int(11) NOT NULL,
+  `private` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `remote_id` (`remote_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_tasks_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_tasks_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_tasks_photos_resized` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `profile_id` int(10) unsigned NOT NULL,
+  `remote_id` varchar(128) NOT NULL,
+  `path` varchar(255) NOT NULL,
+  `file_name` varchar(255) NOT NULL,
+  `mime_type` varchar(128) NOT NULL,
+  `ext` varchar(32) NOT NULL,
+  `size` bigint(20) NOT NULL,
+  `added` int(11) NOT NULL,
+  `modified` int(11) NOT NULL,
+  `private` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `remote_id` (`remote_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_tasks_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_tasks_videos_resized` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `profile_id` int(10) unsigned NOT NULL,
+  `remote_id` varchar(128) NOT NULL,
+  `path` varchar(255) NOT NULL,
+  `file_name` varchar(255) NOT NULL,
+  `mime_type` varchar(128) NOT NULL,
+  `ext` varchar(32) NOT NULL,
+  `size` bigint(20) NOT NULL,
+  `added` int(11) NOT NULL,
+  `modified` int(11) NOT NULL,
+  `private` int(11) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `remote_id` (`remote_id`)
+);
+
+-- TABLE: comments
+CREATE TABLE IF NOT EXISTS `bx_tasks_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_tasks_cmts_notes` (
+  `cmt_id` int(11) NOT NULL AUTO_INCREMENT,
+  `cmt_parent_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_vparent_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_object_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_author_id` int(11) NOT NULL DEFAULT '0',
+  `cmt_level` int(11) NOT NULL DEFAULT '0',
+  `cmt_text` text NOT NULL,
+  `cmt_mood` tinyint(4) NOT NULL DEFAULT '0',
+  `cmt_rate` int(11) NOT NULL DEFAULT '0',
+  `cmt_rate_count` int(11) NOT NULL DEFAULT '0',
+  `cmt_time` int(11) unsigned NOT NULL DEFAULT '0',
+  `cmt_replies` int(11) NOT NULL DEFAULT '0',
+  `cmt_pinned` int(11) NOT NULL default '0',
+  PRIMARY KEY (`cmt_id`),
+  KEY `cmt_object_id` (`cmt_object_id`,`cmt_parent_id`),
+  FULLTEXT KEY `search_fields` (`cmt_text`)
+);
+
+-- TABLE: votes
+CREATE TABLE IF NOT EXISTS `bx_tasks_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_tasks_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_tasks_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_tasks_reactions_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `author_nip` int(11) unsigned NOT NULL default '0',
+  `reaction` varchar(32) NOT NULL default '',
+  `value` tinyint(4) NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `vote` (`object_id`, `author_nip`)
+);
+
+-- TABLE: views
+CREATE TABLE `bx_tasks_views_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `viewer_id` int(11) NOT NULL default '0',
+  `viewer_nip` int(11) unsigned NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `id` (`object_id`,`viewer_id`,`viewer_nip`)
+);
+
+-- TABLE: metas
+CREATE TABLE `bx_tasks_meta_keywords` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(10) unsigned NOT NULL,
+  `keyword` varchar(255) NOT NULL,
+  PRIMARY KEY (`id`),
+  KEY `object_id` (`object_id`),
+  KEY `keyword` (`keyword`)
+);
+
+CREATE TABLE `bx_tasks_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_tasks_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_tasks_reports_track` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `object_id` int(11) NOT NULL default '0',
+  `author_id` int(11) NOT NULL default '0',
+  `author_nip` int(11) unsigned NOT NULL default '0',
+  `type` varchar(32) NOT NULL default '',
+  `text` text NOT NULL default '',
+  `date` int(11) NOT NULL default '0',
+  `checked_by` int(11) NOT NULL default '0',
+  `status` tinyint(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `report` (`object_id`, `author_nip`)
+);
+
+-- TABLE: favorites
+CREATE TABLE `bx_tasks_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',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY (`id`),
+  KEY `id` (`object_id`,`author_id`)
+);
+
+-- TABLE: scores
+CREATE TABLE IF NOT EXISTS `bx_tasks_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_tasks_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
+SET @sStorageEngine = (SELECT `value` FROM `sys_options` WHERE `name` = 'sys_storage_default');
+
+INSERT INTO `sys_objects_storage` (`object`, `engine`, `params`, `token_life`, `cache_control`, `levels`, `table_files`, `ext_mode`, `ext_allow`, `ext_deny`, `quota_size`, `current_size`, `quota_number`, `current_number`, `max_file_size`, `ts`) VALUES
+('bx_tasks_covers', @sStorageEngine, '', 360, 2592000, 3, 'bx_tasks_covers', 'allow-deny', '{image}', '', 0, 0, 0, 0, 0, 0),
+
+('bx_tasks_photos', @sStorageEngine, '', 360, 2592000, 3, 'bx_tasks_photos', 'allow-deny', '{image}', '', 0, 0, 0, 0, 0, 0),
+('bx_tasks_photos_resized', @sStorageEngine, '', 360, 2592000, 3, 'bx_tasks_photos_resized', 'allow-deny', '{image}', '', 0, 0, 0, 0, 0, 0),
+
+('bx_tasks_videos', @sStorageEngine, '', 360, 2592000, 3, 'bx_tasks_videos', 'allow-deny', '{video}', '', 0, 0, 0, 0, 0, 0),
+('bx_tasks_videos_resized', @sStorageEngine, '', 360, 2592000, 3, 'bx_tasks_videos_resized', 'allow-deny', '{imagevideo}', '', 0, 0, 0, 0, 0, 0),
+
+('bx_tasks_files', @sStorageEngine, '', 360, 2592000, 3, 'bx_tasks_files', 'deny-allow', '', '{dangerous}', 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_tasks_preview', 'bx_tasks_photos_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_tasks_covers";}', 'no', '1', '2592000', '0', '', ''),
+('bx_tasks_gallery', 'bx_tasks_photos_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_tasks_covers";}', 'no', '1', '2592000', '0', '', ''),
+('bx_tasks_cover', 'bx_tasks_photos_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_tasks_covers";}', 'no', '1', '2592000', '0', '', ''),
+
+('bx_tasks_preview_photos', 'bx_tasks_photos_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_tasks_photos";}', 'no', '1', '2592000', '0', '', ''),
+('bx_tasks_gallery_photos', 'bx_tasks_photos_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_tasks_photos";}', 'no', '1', '2592000', '0', '', ''),
+
+('bx_tasks_videos_poster', 'bx_tasks_videos_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_tasks_videos";}', 'no', '0', '0', '0', 'BxDolTranscoderVideo', ''),
+('bx_tasks_videos_poster_preview', 'bx_tasks_videos_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_tasks_videos";}', 'no', '0', '0', '0', 'BxDolTranscoderVideo', ''),
+('bx_tasks_videos_mp4', 'bx_tasks_videos_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_tasks_videos";}', 'no', '0', '0', '0', 'BxDolTranscoderVideo', ''),
+('bx_tasks_videos_mp4_hd', 'bx_tasks_videos_resized', 'Storage', 'a:1:{s:6:"object";s:15:"bx_tasks_videos";}', 'no', '0', '0', '0', 'BxDolTranscoderVideo', ''),
+
+('bx_tasks_preview_files', 'bx_tasks_photos_resized', 'Storage', 'a:1:{s:6:"object";s:14:"bx_tasks_files";}', 'no', '1', '2592000', '0', '', ''),
+('bx_tasks_gallery_files', 'bx_tasks_photos_resized', 'Storage', 'a:1:{s:6:"object";s:14:"bx_tasks_files";}', 'no', '1', '2592000', '0', '', '');
+
+INSERT INTO `sys_transcoder_filters` (`transcoder_object`, `filter`, `filter_params`, `order`) VALUES 
+('bx_tasks_preview', 'Resize', 'a:3:{s:1:"w";s:3:"300";s:1:"h";s:3:"200";s:11:"crop_resize";s:1:"1";}', '0'),
+('bx_tasks_gallery', 'Resize', 'a:1:{s:1:"w";s:3:"500";}', '0'),
+('bx_tasks_cover', 'Resize', 'a:1:{s:1:"w";s:4:"1200";}', '0'),
+
+('bx_tasks_preview_photos', 'Resize', 'a:3:{s:1:"w";s:3:"300";s:1:"h";s:3:"200";s:11:"crop_resize";s:1:"1";}', '0'),
+('bx_tasks_gallery_photos', 'Resize', 'a:1:{s:1:"w";s:4:"1200";}', '0'),
+
+('bx_tasks_videos_poster_preview', 'Resize', 'a:3:{s:1:"w";s:3:"300";s:1:"h";s:3:"200";s:13:"square_resize";s:1:"1";}', 10),
+('bx_tasks_videos_poster_preview', 'Poster', 'a:2:{s:1:"h";s:3:"480";s:10:"force_type";s:3:"jpg";}', 0),
+('bx_tasks_videos_poster', 'Poster', 'a:2:{s:1:"h";s:3:"318";s:10:"force_type";s:3:"jpg";}', 0),
+('bx_tasks_videos_mp4', 'Mp4', 'a:2:{s:1:"h";s:3:"318";s:10:"force_type";s:3:"mp4";}', 0),
+('bx_tasks_videos_mp4_hd', 'Mp4', 'a:3:{s:1:"h";s:3:"720";s:13:"video_bitrate";s:4:"1536";s:10:"force_type";s:3:"mp4";}', 0),
+
+('bx_tasks_preview_files', 'Resize', 'a:3:{s:1:"w";s:3:"300";s:1:"h";s:3:"200";s:11:"crop_resize";s:1:"1";}', '0'),
+('bx_tasks_gallery_files', 'Resize', 'a:1:{s:1:"w";s:3:"500";}', '0');
+
+
+-- FORMS: entry (task)
+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_tasks', 'bx_tasks', '_bx_tasks_form_entry', '', 'a:1:{s:7:"enctype";s:19:"multipart/form-data";}', 'bx_tasks_tasks', 'id', '', '', 'a:2:{i:0;s:9:"do_submit";i:1;s:10:"do_publish";}', '', 0, 1, 'BxTasksFormEntry', 'modules/boonex/tasks/classes/BxTasksFormEntry.php');
+
+INSERT INTO `sys_form_displays`(`object`, `display_name`, `module`, `view_mode`, `title`) VALUES 
+('bx_tasks', 'bx_tasks_entry_add', 'bx_tasks', 0, '_bx_tasks_form_entry_display_add'),
+('bx_tasks', 'bx_tasks_entry_delete', 'bx_tasks', 0, '_bx_tasks_form_entry_display_delete'),
+('bx_tasks', 'bx_tasks_entry_edit', 'bx_tasks', 0, '_bx_tasks_form_entry_display_edit'),
+('bx_tasks', 'bx_tasks_entry_view', 'bx_tasks', 1, '_bx_tasks_form_entry_display_view');
+
+INSERT INTO `sys_form_inputs`(`object`, `module`, `name`, `value`, `values`, `checked`, `type`, `caption_system`, `caption`, `info`, `required`, `collapsed`, `html`, `attrs`, `attrs_tr`, `attrs_wrapper`, `checker_func`, `checker_params`, `checker_error`, `db_pass`, `db_params`, `editable`, `deletable`) VALUES 
+('bx_tasks', 'bx_tasks', '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_tasks', 'bx_tasks', 'allow_view_to', '', '', 0, 'custom', '_bx_tasks_form_entry_input_sys_allow_view_to', '_bx_tasks_form_entry_input_allow_view_to', '', 1, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_tasks', 'bx_tasks', 'delete_confirm', 1, '', 0, 'checkbox', '_bx_tasks_form_entry_input_sys_delete_confirm', '_bx_tasks_form_entry_input_delete_confirm', '_bx_tasks_form_entry_input_delete_confirm_info', 1, 0, 0, '', '', '', 'Avail', '', '_bx_tasks_form_entry_input_delete_confirm_error', '', '', 1, 0),
+('bx_tasks', 'bx_tasks', 'do_publish', '_bx_tasks_form_entry_input_do_publish', '', 0, 'submit', '_bx_tasks_form_entry_input_sys_do_publish', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_tasks', 'bx_tasks', 'do_submit', '_bx_tasks_form_entry_input_do_submit', '', 0, 'submit', '_bx_tasks_form_entry_input_sys_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_tasks', 'bx_tasks', 'do_cancel', '_bx_tasks_form_entry_input_do_cancel', '', 0, 'button', '_bx_tasks_form_entry_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),
+('bx_tasks', 'bx_tasks', 'controls', '', 'do_publish,do_cancel', 0, 'input_set', '', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_tasks', 'bx_tasks', 'covers', 'a:1:{i:0;s:14:"bx_tasks_html5";}', 'a:1:{s:14:"bx_tasks_html5";s:25:"_sys_uploader_html5_title";}', 0, 'files', '_bx_tasks_form_entry_input_sys_covers', '_bx_tasks_form_entry_input_covers', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_tasks', 'bx_tasks', 'pictures', 'a:1:{i:0;s:21:"bx_tasks_photos_html5";}', 'a:1:{s:21:"bx_tasks_photos_html5";s:25:"_sys_uploader_html5_title";}', 0, 'files', '_bx_tasks_form_entry_input_sys_pictures', '_bx_tasks_form_entry_input_pictures', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_tasks', 'bx_tasks', 'videos', 'a:2:{i:0;s:21:"bx_tasks_videos_html5";i:1;s:28:"bx_tasks_videos_record_video";}', 'a:2:{s:21:"bx_tasks_videos_html5";s:25:"_sys_uploader_html5_title";s:28:"bx_tasks_videos_record_video";s:32:"_sys_uploader_record_video_title";}', 0, 'files', '_bx_tasks_form_entry_input_sys_videos', '_bx_tasks_form_entry_input_videos', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_tasks', 'bx_tasks', 'files', 'a:1:{i:0;s:20:"bx_tasks_files_html5";}', 'a:1:{s:20:"bx_tasks_files_html5";s:25:"_sys_uploader_html5_title";}', 0, 'files', '_bx_tasks_form_entry_input_sys_files', '_bx_tasks_form_entry_input_files', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_tasks', 'bx_tasks', 'text', '', '', 0, 'textarea', '_bx_tasks_form_entry_input_sys_text', '_bx_tasks_form_entry_input_text', '', 0, 0, 2, '', '', '', '', '', '', 'XssHtml', '', 1, 0),
+('bx_tasks', 'bx_tasks', 'title', '', '', 0, 'text', '_bx_tasks_form_entry_input_sys_title', '_bx_tasks_form_entry_input_title', '', 1, 0, 0, '', '', '', 'Avail', '', '_bx_tasks_form_entry_input_title_err', 'Xss', '', 1, 0),
+('bx_tasks', 'bx_tasks', 'cat', '', '#!bx_tasks_cats', 0, 'select', '_bx_tasks_form_entry_input_sys_cat', '_bx_tasks_form_entry_input_cat', '', 1, 0, 0, '', '', '', 'avail', '', '_bx_tasks_form_entry_input_cat_err', 'Xss', '', 1, 0),
+('bx_tasks', 'bx_tasks', 'multicat', '', '', 0, 'custom', '_bx_tasks_form_entry_input_sys_multicat', '_bx_tasks_form_entry_input_multicat', '', 1, 0, 0, '', '', '', 'avail', '', '_bx_tasks_form_entry_input_multicat_err', 'Xss', '', 1, 0),
+('bx_tasks', 'bx_tasks', 'added', '', '', 0, 'datetime', '_bx_tasks_form_entry_input_sys_date_added', '_bx_tasks_form_entry_input_date_added', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_tasks', 'bx_tasks', 'changed', '', '', 0, 'datetime', '_bx_tasks_form_entry_input_sys_date_changed', '_bx_tasks_form_entry_input_date_changed', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_tasks', 'bx_tasks', 'published', '', '', 0, 'datetime', '_bx_tasks_form_entry_input_sys_date_published', '_bx_tasks_form_entry_input_date_published', '_bx_tasks_form_entry_input_date_published_info', 0, 0, 0, '', '', '', '', '', '', 'DateTimeTs', '', 1, 0),
+('bx_tasks', 'bx_tasks', 'initial_members', '', '', 0, 'custom', '_bx_tasks_form_profile_input_sys_initial_members', '_bx_tasks_form_profile_input_initial_members', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 1),
+('bx_tasks', 'bx_tasks', 'due_date', '', '', 0, 'datetime', '_bx_tasks_form_entry_input_sys_date_due_date', '_bx_tasks_form_entry_input_date_due_date', '', 0, 0, 0, '', '', '', '', '', '', 'DateTimeTs', '', 1, 0),
+('bx_tasks', 'bx_tasks', 'attachments', '', '', 0, 'custom', '_bx_tasks_form_entry_input_sys_attachments', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_tasks', 'bx_tasks', 'labels', '', '', 0, 'custom', '_sys_form_input_sys_labels', '_sys_form_input_labels', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_tasks', 'bx_tasks', 'anonymous', '', '', 0, 'switcher', '_sys_form_input_sys_anonymous', '_sys_form_input_anonymous', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_tasks', 'bx_tasks', 'allow_comments', '1', '', 1, 'switcher', '_bx_tasks_form_entry_input_sys_allow_comments', '_bx_tasks_form_entry_input_allow_comments', '', 0, 0, 0, '', '', '', '', '', '', 'Int', '', 1, 0);
+
+INSERT INTO `sys_form_display_inputs`(`display_name`, `input_name`, `visible_for_levels`, `active`, `order`) VALUES 
+('bx_tasks_entry_add', 'delete_confirm', 2147483647, 0, 1),
+('bx_tasks_entry_add', 'title', 2147483647, 1, 2),
+('bx_tasks_entry_add', 'text', 2147483647, 1, 3),
+('bx_tasks_entry_add', 'initial_members', 192, 1, 4),
+('bx_tasks_entry_add', 'due_date', 192, 1, 5),
+('bx_tasks_entry_add', 'controls', 2147483647, 1, 6),
+('bx_tasks_entry_add', 'do_publish', 2147483647, 1, 7),
+('bx_tasks_entry_add', 'do_cancel', 2147483647, 1, 8),
+
+('bx_tasks_entry_delete', 'delete_confirm', 2147483647, 1, 1),
+('bx_tasks_entry_delete', 'do_submit', 2147483647, 1, 2),
+
+('bx_tasks_entry_edit', 'do_publish', 2147483647, 0, 1),
+('bx_tasks_entry_edit', 'delete_confirm', 2147483647, 0, 2),
+('bx_tasks_entry_edit', 'title', 2147483647, 1, 3),
+('bx_tasks_entry_edit', 'text', 2147483647, 1, 4),
+('bx_tasks_entry_edit', 'attachments', 2147483647, 1, 5),
+('bx_tasks_entry_edit', 'pictures', 2147483647, 1, 6),
+('bx_tasks_entry_edit', 'videos', 2147483647, 1, 7),
+('bx_tasks_entry_edit', 'files', 2147483647, 1, 8),
+('bx_tasks_entry_edit', 'allow_view_to', 2147483647, 1, 9),
+('bx_tasks_entry_edit', 'cf', 2147483647, 1, 10),
+('bx_tasks_entry_edit', 'tasks_list', 192, 1, 11),
+('bx_tasks_entry_edit', 'initial_members', 192, 1, 12),
+('bx_tasks_entry_edit', 'due_date', 192, 1, 13),
+('bx_tasks_entry_edit', 'do_submit', 2147483647, 1, 14),
+
+('bx_tasks_entry_view', 'cat', 2147483647, 1, 1),
+('bx_tasks_entry_view', 'added', 2147483647, 1, 2),
+('bx_tasks_entry_view', 'changed', 2147483647, 1, 3),
+('bx_tasks_entry_view', 'due_date', 192, 1, 4);
+
+
+-- FORMS: entry (tasklist)
+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_tasks_list', 'bx_tasks', '_bx_tasks_form_list_entry', '', 'a:1:{s:7:"enctype";s:19:"multipart/form-data";}', 'bx_tasks_lists', 'id', '', '', 'do_submit', '', 0, 1, 'BxTasksFormListEntry', 'modules/boonex/tasks/classes/BxTasksFormListEntry.php');
+
+INSERT INTO `sys_form_displays`(`object`, `display_name`, `module`, `view_mode`, `title`) VALUES 
+('bx_tasks_list', 'bx_tasks_list_entry_add', 'bx_tasks', 0, '_bx_tasks_form_list_entry_display_add'),
+('bx_tasks_list', 'bx_tasks_list_entry_edit', 'bx_tasks', 0, '_bx_tasks_form_list_entry_display_edit');
+
+INSERT INTO `sys_form_inputs`(`object`, `module`, `name`, `value`, `values`, `checked`, `type`, `caption_system`, `caption`, `info`, `required`, `collapsed`, `html`, `attrs`, `attrs_tr`, `attrs_wrapper`, `checker_func`, `checker_params`, `checker_error`, `db_pass`, `db_params`, `editable`, `deletable`) VALUES 
+('bx_tasks_list', 'bx_tasks', 'do_submit', '_bx_tasks_form_list_entry_input_do_submit', '', 0, 'submit', '_bx_tasks_form_list_entry_input_sys_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_tasks_list', 'bx_tasks', 'title', '', '', 0, 'text', '_bx_tasks_form_list_entry_input_sys_title', '_bx_tasks_form_list_entry_input_title', '', 1, 0, 0, '', '', '', 'Avail', '', '_bx_tasks_form_list_entry_input_title_err', 'Xss', '', 1, 0),
+('bx_tasks_list', 'bx_tasks', 'do_cancel', '_bx_tasks_form_entry_input_do_cancel', '', 0, 'button', '_bx_tasks_form_entry_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),
+('bx_tasks_list', 'bx_tasks', 'controls', '', 'do_submit,do_cancel', 0, 'input_set', '', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0);
+
+
+INSERT INTO `sys_form_display_inputs`(`display_name`, `input_name`, `visible_for_levels`, `active`, `order`) VALUES 
+('bx_tasks_list_entry_add', 'title', 2147483647, 1, 1),
+('bx_tasks_list_entry_add', 'controls', 2147483647, 1, 2),
+('bx_tasks_list_entry_add', 'do_submit', 2147483647, 1, 3),
+('bx_tasks_list_entry_add', 'do_cancel', 2147483647, 1, 4),
+
+('bx_tasks_list_entry_edit', 'title', 2147483647, 1, 1),
+('bx_tasks_list_entry_edit', 'controls', 2147483647, 1, 2),
+('bx_tasks_list_entry_edit', 'do_submit', 2147483647, 1, 3),
+('bx_tasks_list_entry_edit', 'do_cancel', 2147483647, 1, 4);
+
+
+-- PRE-VALUES
+INSERT INTO `sys_form_pre_lists`(`key`, `title`, `module`, `use_for_sets`) VALUES
+('bx_tasks_cats', '_bx_tasks_pre_lists_cats', 'bx_tasks', '0');
+
+INSERT INTO `sys_form_pre_values`(`Key`, `Value`, `Order`, `LKey`, `LKey2`) VALUES
+('bx_tasks_cats', '', 0, '_sys_please_select', ''),
+('bx_tasks_cats', '1', 1, '_bx_tasks_cat_Animals_Pets', ''),
+('bx_tasks_cats', '2', 2, '_bx_tasks_cat_Architecture', ''),
+('bx_tasks_cats', '3', 3, '_bx_tasks_cat_Art', ''),
+('bx_tasks_cats', '4', 4, '_bx_tasks_cat_Cars_Motorcycles', ''),
+('bx_tasks_cats', '5', 5, '_bx_tasks_cat_Celebrities', ''),
+('bx_tasks_cats', '6', 6, '_bx_tasks_cat_Design', ''),
+('bx_tasks_cats', '7', 7, '_bx_tasks_cat_DIY_Crafts', ''),
+('bx_tasks_cats', '8', 8, '_bx_tasks_cat_Education', ''),
+('bx_tasks_cats', '9', 9, '_bx_tasks_cat_Film_Music_Books', ''),
+('bx_tasks_cats', '10', 10, '_bx_tasks_cat_Food_Drink', ''),
+('bx_tasks_cats', '11', 11, '_bx_tasks_cat_Gardening', ''),
+('bx_tasks_cats', '12', 12, '_bx_tasks_cat_Geek', ''),
+('bx_tasks_cats', '13', 13, '_bx_tasks_cat_Hair_Beauty', ''),
+('bx_tasks_cats', '14', 14, '_bx_tasks_cat_Health_Fitness', ''),
+('bx_tasks_cats', '15', 15, '_bx_tasks_cat_History', ''),
+('bx_tasks_cats', '16', 16, '_bx_tasks_cat_Holidays_Events', ''),
+('bx_tasks_cats', '17', 17, '_bx_tasks_cat_Home_Decor', ''),
+('bx_tasks_cats', '18', 18, '_bx_tasks_cat_Humor', ''),
+('bx_tasks_cats', '19', 19, '_bx_tasks_cat_Illustrations_Posters', ''),
+('bx_tasks_cats', '20', 20, '_bx_tasks_cat_Kids_Parenting', ''),
+('bx_tasks_cats', '21', 21, '_bx_tasks_cat_Mens_Fashion', ''),
+('bx_tasks_cats', '22', 22, '_bx_tasks_cat_Outdoors', ''),
+('bx_tasks_cats', '23', 23, '_bx_tasks_cat_Photography', ''),
+('bx_tasks_cats', '24', 24, '_bx_tasks_cat_Products', ''),
+('bx_tasks_cats', '25', 25, '_bx_tasks_cat_Quotes', ''),
+('bx_tasks_cats', '26', 26, '_bx_tasks_cat_Science_Nature', ''),
+('bx_tasks_cats', '27', 27, '_bx_tasks_cat_Sports', ''),
+('bx_tasks_cats', '28', 28, '_bx_tasks_cat_Tattoos', ''),
+('bx_tasks_cats', '29', 29, '_bx_tasks_cat_Technology', ''),
+('bx_tasks_cats', '30', 30, '_bx_tasks_cat_Travel', ''),
+('bx_tasks_cats', '31', 31, '_bx_tasks_cat_Weddings', ''),
+('bx_tasks_cats', '32', 32, '_bx_tasks_cat_Womens_Fashion', '');
+
+-- 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_tasks', 'bx_tasks', 'bx_tasks_cmts', 1, 5000, 1000, 3, 5, 3, 'tail', 1, 'bottom', 1, 1, 1, -3, 1, 'cmt', 'page.php?i=view-task&id={object_id}', '', 'bx_tasks_tasks', 'id', 'author', 'title', 'comments', '', ''),
+('bx_tasks_notes', 'bx_tasks', 'bx_tasks_cmts_notes', 1, 5000, 1000, 0, 5, 3, 'tail', 1, 'bottom', 1, 1, 1, -3, 1, 'cmt', 'page.php?i=view-task&id={object_id}', '', 'bx_tasks_tasks', 'id', 'author', 'title', '', 'BxTemplCmtsNotes', '');
+
+-- VOTES
+INSERT INTO `sys_objects_vote` (`Name`, `Module`, `TableMain`, `TableTrack`, `PostTimeout`, `MinValue`, `MaxValue`, `IsUndo`, `IsOn`, `TriggerTable`, `TriggerFieldId`, `TriggerFieldAuthor`, `TriggerFieldRate`, `TriggerFieldRateCount`, `ClassName`, `ClassFile`) VALUES 
+('bx_tasks', 'bx_tasks', 'bx_tasks_votes', 'bx_tasks_votes_track', '604800', '1', '1', '0', '1', 'bx_tasks_tasks', 'id', 'author', 'rate', 'votes', '', ''),
+('bx_tasks_reactions', 'bx_tasks', 'bx_tasks_reactions', 'bx_tasks_reactions_track', '604800', '1', '1', '1', '1', 'bx_tasks_tasks', 'id', 'author', 'rrate', 'rvotes', 'BxTemplVoteReactions', '');
+
+-- SCORES
+INSERT INTO `sys_objects_score` (`name`, `module`, `table_main`, `table_track`, `post_timeout`, `is_on`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_score`, `trigger_field_cup`, `trigger_field_cdown`, `class_name`, `class_file`) VALUES 
+('bx_tasks', 'bx_tasks', 'bx_tasks_scores', 'bx_tasks_scores_track', '604800', '0', 'bx_tasks_tasks', 'id', 'author', 'score', 'sc_up', 'sc_down', '', '');
+
+-- REPORTS
+INSERT INTO `sys_objects_report` (`name`, `module`, `table_main`, `table_track`, `is_on`, `base_url`, `object_comment`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_count`, `class_name`, `class_file`) VALUES 
+('bx_tasks', 'bx_tasks', 'bx_tasks_reports', 'bx_tasks_reports_track', '1', 'page.php?i=view-task&id={object_id}', 'bx_tasks_notes', 'bx_tasks_tasks', 'id', 'author', 'reports', '', '');
+
+-- 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_tasks', 'bx_tasks', 'bx_tasks_views_track', '86400', '1', 'bx_tasks_tasks', 'id', 'author', 'views', '', '');
+
+-- FAFORITES
+INSERT INTO `sys_objects_favorite` (`name`, `table_track`, `is_on`, `is_undo`, `is_public`, `base_url`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_count`, `class_name`, `class_file`) VALUES 
+('bx_tasks', 'bx_tasks_favorites_track', '1', '1', '1', 'page.php?i=view-task&id={object_id}', 'bx_tasks_tasks', 'id', 'author', 'favorites', '', '');
+
+-- FEATURED
+INSERT INTO `sys_objects_feature` (`name`, `module`, `is_on`, `is_undo`, `base_url`, `trigger_table`, `trigger_field_id`, `trigger_field_author`, `trigger_field_flag`, `class_name`, `class_file`) VALUES 
+('bx_tasks', 'bx_tasks', '1', '1', 'page.php?i=view-task&id={object_id}', 'bx_tasks_tasks', 'id', 'author', 'featured', '', '');
+
+-- CONTENT INFO
+INSERT INTO `sys_objects_content_info` (`name`, `title`, `alert_unit`, `alert_action_add`, `alert_action_update`, `alert_action_delete`, `class_name`, `class_file`) VALUES
+('bx_tasks', '_bx_tasks', 'bx_tasks', 'added', 'edited', 'deleted', '', ''),
+('bx_tasks_cmts', '_bx_tasks_cmts', 'bx_tasks', 'commentPost', 'commentUpdated', 'commentRemoved', 'BxDolContentInfoCmts', '');
+
+-- SEARCH EXTENDED
+INSERT INTO `sys_objects_search_extended` (`object`, `object_content_info`, `module`, `title`, `active`, `class_name`, `class_file`) VALUES
+('bx_tasks', 'bx_tasks', 'bx_tasks', '_bx_tasks_search_extended', 1, '', ''),
+('bx_tasks_cmts', 'bx_tasks_cmts', 'bx_tasks', '_bx_tasks_search_extended_cmts', 1, 'BxTemplSearchExtendedCmts', '');
+
+-- STUDIO: page & widget
+INSERT INTO `sys_std_pages`(`index`, `name`, `header`, `caption`, `icon`) VALUES
+(3, 'bx_tasks', '_bx_tasks', '_bx_tasks', 'bx_tasks@modules/boonex/tasks/|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_tasks', 'content', '{url_studio}module.php?name=bx_tasks', '', 'bx_tasks@modules/boonex/tasks/|std-icon.svg', '_bx_tasks', '', '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));
+

+ 53 - 0
modules/boonex/timeline/updates/13.0.11_13.0.12/install/config.php

@@ -0,0 +1,53 @@
+<?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.11',
+    'version_to' => '13.0.12',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '13.1.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/timeline/updates/update_13.0.11_13.0.12/',
+    'home_uri' => 'timeline_update_13011_13012',
+
+    '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(
+        'template/divider.html',
+    ),
+);

+ 13 - 0
modules/boonex/timeline/updates/13.0.11_13.0.12/install/installer.php

@@ -0,0 +1,13 @@
+<?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);
+    }
+}

+ 23 - 0
modules/boonex/timeline/updates/13.0.11_13.0.12/install/langs/en.xml

@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources name="en" flag="gb" title="English">
+	<string_add name="_bx_timeline_option_live_updates_length"><![CDATA[The length of Live Updates selection]]></string_add>
+	<string_add name="_bx_timeline_option_enable_cache_table"><![CDATA[Enable table cache (experimental)]]></string_add>
+    <string_add name="_bx_timeline_option_cache_table_interval"><![CDATA[Interval of time (in days) to get events for cache table]]></string_add>
+	<string_add name="_bx_timeline_option_enable_media_priority"><![CDATA[Enable priority of media content over links in attachments]]></string_add>
+	<string_add name="_bx_timeline_page_block_title_system_view_feed_and_hot"><![CDATA['For You' Feed (Timeline)]]></string_add>
+    <string_add name="_bx_timeline_page_block_title_view_feed_and_hot"><![CDATA[For You]]></string_add>
+    <string_add name="_bx_timeline_page_block_title_system_view_contexts_groups"><![CDATA[Followed groups (Timeline)]]></string_add>
+    <string_add name="_bx_timeline_page_block_title_view_contexts_groups"><![CDATA[Followed groups]]></string_add>
+    <string_add name="_bx_timeline_page_block_title_system_view_media_files"><![CDATA[Files Feed (Timeline)]]></string_add>
+    <string_add name="_bx_timeline_page_block_title_view_media_files"><![CDATA[Files]]></string_add>
+    <string_add name="_bx_timeline_page_block_title_system_view_media_images"><![CDATA[Photos Feed (Timeline)]]></string_add>
+    <string_add name="_bx_timeline_page_block_title_view_media_images"><![CDATA[Photos]]></string_add>
+    <string_add name="_bx_timeline_page_block_title_system_view_media_videos"><![CDATA[Videos Feed (Timeline)]]></string_add>
+    <string_add name="_bx_timeline_page_block_title_view_media_videos"><![CDATA[Videos]]></string_add>
+    <string_add name="_bx_timeline_page_block_title_system_view_media_any"><![CDATA[Any Media Feed (Timeline)]]></string_add>
+    <string_add name="_bx_timeline_page_block_title_view_media_any"><![CDATA[Media]]></string_add>
+	<string_add name="_bx_timeline_menu_item_title_system_feed_and_hot"><![CDATA[Feed and Hot]]></string_add>
+    <string_add name="_bx_timeline_menu_item_title_feed_and_hot"><![CDATA[For You]]></string_add>
+	<string_add name="_bx_timeline_menu_item_title_system_item_copy"><![CDATA[Copy to clipboard]]></string_add>
+    <string_add name="_bx_timeline_menu_item_title_item_copy"><![CDATA[Copy]]></string_add>
+</resources>

+ 39 - 0
modules/boonex/timeline/updates/13.0.11_13.0.12/install/sql/enable.sql

@@ -0,0 +1,39 @@
+SET @sName = 'bx_timeline';
+
+
+-- PAGES
+DELETE FROM `sys_pages_blocks` WHERE `object`='' AND `module`='bx_timeline' AND `title` IN ('_bx_timeline_page_block_title_view_feed_and_hot', '_bx_timeline_page_block_title_view_contexts_groups', '_bx_timeline_page_block_title_view_media_files', '_bx_timeline_page_block_title_view_media_images', '_bx_timeline_page_block_title_view_media_videos', '_bx_timeline_page_block_title_view_media_any');
+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_view_feed_and_hot', '_bx_timeline_page_block_title_view_feed_and_hot', 0, 0, 2147483644, 'service', 'a:3:{s:6:"module";s:11:"bx_timeline";s:6:"method";s:21:"get_block_view_custom";s:6:"params";a:1:{i:0;a:2:{s:4:"view";s:8:"timeline";s:4:"type";s:12:"feed_and_hot";}}}', 0, 1, 1, @iBlockOrder + 1),
+
+('', 0, 'bx_timeline', '_bx_timeline_page_block_title_system_view_contexts_groups', '_bx_timeline_page_block_title_view_contexts_groups', 0, 0, 2147483644, 'service', 'a:3:{s:6:"module";s:11:"bx_timeline";s:6:"method";s:21:"get_block_view_custom";s:6:"params";a:1:{i:0;a:3:{s:4:"view";s:8:"timeline";s:4:"type";s:18:"connected_contexts";s:7:"context";s:9:"bx_groups";}}}', 0, 1, 1, @iBlockOrder + 2),
+
+('', 0, 'bx_timeline', '_bx_timeline_page_block_title_system_view_media_files', '_bx_timeline_page_block_title_view_media_files', 0, 0, 2147483644, 'service', 'a:3:{s:6:"module";s:11:"bx_timeline";s:6:"method";s:21:"get_block_view_custom";s:6:"params";a:1:{i:0;a:3:{s:4:"view";s:8:"timeline";s:4:"type";s:4:"feed";s:5:"media";s:5:"files";}}}', 0, 1, 1, @iBlockOrder + 3),
+('', 0, 'bx_timeline', '_bx_timeline_page_block_title_system_view_media_images', '_bx_timeline_page_block_title_view_media_images', 0, 0, 2147483644, 'service', 'a:3:{s:6:"module";s:11:"bx_timeline";s:6:"method";s:21:"get_block_view_custom";s:6:"params";a:1:{i:0;a:3:{s:4:"view";s:8:"timeline";s:4:"type";s:4:"feed";s:5:"media";s:6:"images";}}}', 0, 1, 1, @iBlockOrder + 4),
+('', 0, 'bx_timeline', '_bx_timeline_page_block_title_system_view_media_videos', '_bx_timeline_page_block_title_view_media_videos', 0, 0, 2147483644, 'service', 'a:3:{s:6:"module";s:11:"bx_timeline";s:6:"method";s:21:"get_block_view_custom";s:6:"params";a:1:{i:0;a:3:{s:4:"view";s:8:"timeline";s:4:"type";s:4:"feed";s:5:"media";s:6:"videos";}}}', 0, 1, 1, @iBlockOrder + 5),
+('', 0, 'bx_timeline', '_bx_timeline_page_block_title_system_view_media_any', '_bx_timeline_page_block_title_view_media_any', 0, 0, 2147483644, 'service', 'a:3:{s:6:"module";s:11:"bx_timeline";s:6:"method";s:21:"get_block_view_custom";s:6:"params";a:1:{i:0;a:3:{s:4:"view";s:8:"timeline";s:4:"type";s:4:"feed";s:5:"media";a:3:{i:0;s:5:"files";i:1;s:6:"images";i:2;s:6:"videos";}}}}', 0, 1, 1, @iBlockOrder + 6);
+
+
+-- MENUS
+DELETE FROM `sys_menu_items` WHERE `set_name`='bx_timeline_menu_view' AND `name`='feed_and_hot';
+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_and_hot', '_bx_timeline_menu_item_title_system_feed_and_hot', '_bx_timeline_menu_item_title_feed_and_hot', 'javascript:void(0)', 'javascript:{js_object_view}.changeView(this, ''feed_and_hot'')', '_self', '', '', 2147483647, 0, 0, 5);
+
+
+-- SETTINGS
+SET @iCategId = (SELECT `id` FROM `sys_options_categories` WHERE `name`='bx_timeline_browse' LIMIT 1);
+DELETE FROM `sys_options`WHERE `name`='bx_timeline_live_updates_length';
+INSERT INTO `sys_options` (`name`, `value`, `category_id`, `caption`, `type`, `check`, `check_params`, `check_error`, `extra`, `order`) VALUES
+('bx_timeline_live_updates_length', '5', @iCategId, '_bx_timeline_option_live_updates_length', 'digit', '', '', '', '', 15);
+
+SET @iCategId = (SELECT `id` FROM `sys_options_categories` WHERE `name`='bx_timeline_cache' LIMIT 1);
+DELETE FROM `sys_options` WHERE `name` IN ('bx_timeline_enable_cache_table', 'bx_timeline_cache_table_interval');
+INSERT INTO `sys_options` (`name`, `value`, `category_id`, `caption`, `type`, `check`, `check_params`, `check_error`, `extra`, `order`) VALUES
+('bx_timeline_enable_cache_table', '', @iCategId, '_bx_timeline_option_enable_cache_table', 'checkbox', '', '', '', '', 10),
+('bx_timeline_cache_table_interval', '90', @iCategId, '_bx_timeline_option_cache_table_interval', 'digit', '', '', '', '', 11);
+
+SET @iCategId = (SELECT `id` FROM `sys_options_categories` WHERE `name`='bx_timeline_post' LIMIT 1);
+DELETE FROM `sys_options`WHERE `name`='bx_timeline_enable_media_priority';
+INSERT INTO `sys_options` (`name`, `value`, `category_id`, `caption`, `type`, `check`, `check_params`, `check_error`, `extra`, `order`) VALUES
+('bx_timeline_enable_media_priority', '', @iCategId, '_bx_timeline_option_enable_media_priority', 'checkbox', '', '', '', '', 3);

+ 78 - 0
modules/boonex/timeline/updates/13.0.11_13.0.12/install/sql/install.sql

@@ -0,0 +1,78 @@
+SET @sName = 'bx_timeline';
+
+
+-- TABLES
+CREATE TABLE IF NOT EXISTS `bx_timeline_events_slice` (
+  `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,
+  `source` varchar(32) NOT NULL default '',
+  `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_ef_photos` (
+  `event_id` int(11) NOT NULL DEFAULT '0',
+  PRIMARY KEY (`event_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_timeline_ef_videos` (
+  `event_id` int(11) NOT NULL DEFAULT '0',
+  PRIMARY KEY (`event_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_timeline_ef_files` (
+  `event_id` int(11) NOT NULL DEFAULT '0',
+  PRIMARY KEY (`event_id`)
+);
+
+
+-- STORAGES & TRANSCODERS
+UPDATE `sys_transcoder_filters` SET `filter_params`='a:2:{s:1:"w";s:4:"1000";s:1:"h";s:4:"1000";}' WHERE `transcoder_object`='bx_timeline_photos_big';
+UPDATE `sys_transcoder_filters` SET `filter_params`='a:2:{s:1:"w";s:4:"1000";s:1:"h";s:4:"1000";}' WHERE `transcoder_object`='bx_timeline_videos_photo_big';
+
+
+-- FORMS
+DELETE FROM `sys_form_display_inputs` WHERE `display_name`='bx_timeline_post_edit' AND `input_name`='object_privacy_view';
+INSERT INTO `sys_form_display_inputs` (`display_name`, `input_name`, `visible_for_levels`, `active`, `order`) VALUES
+('bx_timeline_post_edit', 'object_privacy_view', 2147483647, 1, 10);
+
+
+-- VIEWS
+UPDATE `sys_objects_view` SET `module`='bx_timeline' WHERE `name`='bx_timeline';
+
+
+-- VOTES
+UPDATE `sys_objects_vote` SET `Module`='bx_timeline' WHERE `Name` IN ('bx_timeline', 'bx_timeline_reactions');

+ 977 - 0
modules/boonex/timeline/updates/13.0.11_13.0.12/source/classes/BxTimelineConfig.php

@@ -0,0 +1,977 @@
+<?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 $_bCacheTable;
+    protected $_iCacheTableInterval;
+    protected $_aCacheTableCheckFields;
+
+    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 $_bEnableMediaPriority;
+    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_SOURCE' => 'source',
+            '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->_bCacheTable = getParam($sOptionPrefix . 'enable_cache_table') == 'on';
+        $this->_iCacheTableInterval = (int)getParam($sOptionPrefix . 'cache_table_interval');
+        $this->_aCacheTableCheckFields = [
+            'date' => 'date',
+            'reacted' => 'date',
+            'sticked' => 'flag'
+        ];
+
+        $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->_iLiveUpdateLength = (int)getParam($sOptionPrefix . 'live_updates_length');
+
+        $this->_bBriefCards = getParam($sOptionPrefix . 'enable_brief_cards') == 'on';
+
+        $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->_bEnableMediaPriority = getParam($sOptionPrefix . 'enable_media_priority') == '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 isEditorToolbar()
+    {
+    	return $this->_bEditorToolbar;
+    }
+
+    public function isEditorAutoAttach()
+    {
+    	return $this->_bEditorAutoAttach;
+    }
+
+    public function isMediaPriority()
+    {
+        return $this->_bEnableMediaPriority;
+    }
+
+    public function isUnhideRestored()
+    {
+        return $this->_bUnhideRestored;
+    }
+
+    public function isCacheItem()
+    {
+        return $this->_bCacheItem;
+    }
+
+    public function isCacheTable()
+    {
+        return $this->_bCacheTable;
+    }
+
+    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 : '') . '_' . bx_site_hash() . '.php';
+    }
+
+    public function getCacheItemKeys($iId, $sPostfix = '')
+    {
+        $aVariants = ['_r1', '_r2', '_m_r1', '_m_r2'];
+
+        return array_map(function($sValue) use ($iId, $sPostfix) {
+            return $this->getPrefix('cache_item') . $iId . $sValue . (!empty($sPostfix) ? '_' . $sPostfix : '') . '_' . bx_site_hash() . '.php';
+        }, $aVariants);
+    }
+
+    public function getCacheHotKey()
+    {
+        return $this->getPrefix('cache_list_hot');
+    }
+    
+    public function getCacheTableInterval()
+    {
+        return 86400 * $this->_iCacheTableInterval;
+    }
+
+    public function getCacheTableCheckFields()
+    {
+        $mixedResult = null;
+        bx_alert($this->getName(), 'cache_table_check_fields', 0, 0, ['check_fields' => $this->_aCacheTableCheckFields, 'override_result' => &$mixedResult]);
+        if($mixedResult !== null)
+            return $mixedResult;
+        
+        return $this->_aCacheTableCheckFields;
+    }
+
+    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)
+    {
+        $sUrl = BxDolPermalinks::getInstance()->permalink('page.php?i=' . $this->CNF['URI_VIEW_LIST'], ['id' => $iOwnerId]);
+        return $bAbsolute ? bx_absolute_url($sUrl) : $sUrl;
+    }
+
+    public function getHomeViewUrl($bAbsolute = true)
+    {
+        $sUrl = BxDolPermalinks::getInstance()->permalink($this->CNF['URL_HOME']);
+        return $bAbsolute ? bx_absolute_url($sUrl) : $sUrl;
+    }
+
+    public function getItemViewUrl($aEvent, $bAbsolute = true)
+    {
+        $sUrl = BxDolPermalinks::getInstance()->permalink('page.php?i=' . $this->CNF['URI_VIEW_ENTRY'], ['id' => $aEvent['id']]);
+        return $bAbsolute ? bx_absolute_url($sUrl) : $sUrl;
+    }
+
+    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_]+$/")
+    {
+        return bx_process_url_param($sValue, $sPattern);
+    }
+
+    public function processParamWithDefault($sValue, $sDefault, $sPattern = "/^[\d\w_]+$/")
+    {
+        return ($sValue = $this->processParam($sValue, $sPattern)) != '' ? $sValue : $sDefault;
+    }
+}
+
+/** @} */

+ 1394 - 0
modules/boonex/timeline/updates/13.0.11_13.0.12/source/classes/BxTimelineDb.php

@@ -0,0 +1,1394 @@
+<?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 $_sTableSlice;
+    protected $_sTableEvent2User;
+    protected $_aTablesEventFlags;
+
+    protected $_sTableRepostsTrack;
+    protected $_sTableHotTrack;
+
+    protected $_aTablesMedia;
+    protected $_aTablesMedia2Events;
+
+    /*
+     * Constructor.
+     */
+    function __construct(&$oConfig)
+    {
+        parent::__construct($oConfig);
+
+        $CNF = &$this->_oConfig->CNF;
+
+        $this->_sTableAlias = 'te';
+        $this->_sTableSlice = $this->_sPrefix . 'events_slice';
+        $this->_sTableEvent2User = $this->_sPrefix . 'events2users';
+        $this->_aTablesEventFlags = [
+            'images' => $this->_sPrefix . 'ef_photos',
+            'videos' => $this->_sPrefix . 'ef_videos',
+            'files' => $this->_sPrefix . 'ef_files'
+        ];
+
+        $this->_sTableRepostsTrack = $this->_sPrefix . 'reposts_track';
+        $this->_sTableHotTrack = $this->_sPrefix . 'hot_track';
+
+        $this->_aTablesMedia = [
+            $CNF['FIELD_PHOTO'] => $this->_sPrefix . 'photos',
+            $CNF['FIELD_VIDEO'] => $this->_sPrefix . 'videos',
+            $CNF['FIELD_FILE'] => $this->_sPrefix . 'files' 
+        ];
+        $this->_aTablesMedia2Events = [
+            $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 hasMedia($iEventId)
+    {
+        $bResult = false;
+
+        foreach($this->_aTablesMedia as $sType) {
+            $aMedia = $this->getMedia($sType, $iEventId);
+            if(!empty($aMedia) && is_array($aMedia)) {
+                $bResult = true;
+                break;
+            }
+        }
+
+        return $bResult;
+    }
+
+    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 rebuildSlice()
+    {
+        $this->query("TRUNCATE TABLE `" . $this->_sTableSlice . "`");
+
+        $aWhereConditions = [];
+
+        $iInterval = $this->_oConfig->getCacheTableInterval();
+        $aCheckFields = $this->_oConfig->getCacheTableCheckFields();
+        foreach($aCheckFields as $sField => $sType)
+            switch($sType) {
+                case 'flag':
+                    $aWhereConditions[] = "`" . $sField . "` <> 0";
+                    break;
+
+                case 'date':
+                    $aWhereConditions[] = "`" . $sField . "` > (UNIX_TIMESTAMP() - " . $iInterval . ")";
+                    break;
+            }
+
+        return $this->query("INSERT INTO `" . $this->_sTableSlice . "` SELECT * FROM `" . $this->_sTable . "` WHERE " . implode(" OR ", $aWhereConditions));
+    }
+
+    public function getEvents($aParams)
+    {
+        bx_alert($this->_oConfig->getName(), 'get_events_before', 0, 0, array(
+            'params' => &$aParams,
+        ));
+
+        $sTable = isset($aParams['from_cache']) && $aParams['from_cache'] === true ? $this->_sTableSlice : $this->_sTable;
+        $sTableAlias = $this->getTableAlias();
+
+        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' => $sTable,
+            'method' => &$sMethod,
+            'select_clause' => &$sSelectClause,
+            'join_clause' => &$mixedJoinClause,
+            'where_clause' => &$mixedWhereClause,
+            'order_clause' => &$sOrderClause,
+            'limit_clause' => &$sLimitClause
+        ));
+
+        $sSqlMask = "SELECT {select}
+            FROM `{$sTable}` AS `{$sTableAlias}`
+            LEFT JOIN `{$this->_sTableHandlers}` ON `{$sTableAlias}`.`type`=`{$this->_sTableHandlers}`.`alert_unit` AND `{$sTableAlias}`.`action`=`{$this->_sTableHandlers}`.`alert_action` {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);
+        }
+
+        if($bCount)
+            return array_sum($aSqlParts);
+
+        $sSql = bx_replace_markers('(' . implode(') UNION (', $aSqlParts) . ') {order} {limit}', [
+            'order' => str_replace("`{$sTableAlias}`.", '', $sOrderClause),
+            'limit' => str_replace("`{$sTableAlias}`.", '', $sLimitClause),
+        ]);
+
+        //echoDbg($sSql); exit;
+        return $this->$sMethod($sSql);
+    }
+
+    public function getEventFlagTypes()
+    {
+        return array_keys($this->_aTablesEventFlags);
+    }
+
+    public function updateEventFlagsByType($sType, $iEventId)
+    {
+        if(!isset($this->_aTablesEventFlags[$sType]))
+            return false;
+
+        return $this->query("INSERT IGNORE INTO `" . $this->_aTablesEventFlags[$sType] . "` (`event_id`) VALUES (:event_id)", [
+            'event_id' => $iEventId,
+        ]) !== false;
+    }
+
+    public function deleteEventFlagsByType($sType, $iEventId)
+    {
+        if(!isset($this->_aTablesEventFlags[$sType]))
+            return false;
+
+        return $this->query("DELETE FROM `" . $this->_aTablesEventFlags[$sType] . "` WHERE `event_id`=:event_id", [
+            'event_id' => $iEventId
+        ]) !== false;
+    }
+
+    public function deleteEventFlags($iEventId)
+    {
+        $aTypes = $this->getEventFlagTypes();
+        foreach($aTypes as $sType)
+            $this->deleteEventFlagsByType($sType, $iEventId);
+    }
+
+    protected function _getFilterAddon($iOwnerId, $sFilter)
+    {
+        $sTableAlias = $this->getTableAlias();
+
+        switch($sFilter) {
+            /**
+             * Direct posts in Timeline made by a timeline owner ($iOwnerId)
+             */
+            case BX_TIMELINE_FILTER_OWNER:
+                $sFilterAddon = $this->prepareAsString(" AND `{$sTableAlias}`.`action`='' AND `{$sTableAlias}`.`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 `{$sTableAlias}`.`action`='' AND `{$sTableAlias}`.`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 (`{$sTableAlias}`.`action`<>'' OR (`{$sTableAlias}`.`action`='' AND `{$sTableAlias}`.`object_id`<>?)) ", bx_get_logged_profile_id());
+                break;
+                
+
+            case BX_TIMELINE_FILTER_ALL:
+            default:
+                $sFilterAddon = "";
+        }
+        return $sFilterAddon;
+    }
+
+    protected function _getSqlPartsEvents($aParams)
+    {
+    	$sMethod = 'getAll';
+        $sTableAlias = $this->getTableAlias();
+    	$sSelectClause = "`{$sTableAlias}`.*";
+        $sJoinClause = $sWhereClause = $sOrderClause = $sLimitClause = "";
+
+        switch($aParams['browse']) {
+            case 'owner_id':
+                $sWhereClause = $this->prepareAsString("AND `{$sTableAlias}`.`owner_id`=? ", $aParams['value']);
+                break;
+
+            case 'source':
+                $sWhereClause = $this->prepareAsString("AND `{$sTableAlias}`.`source`=? ", $aParams['value']);
+                break;
+
+            case 'common_by_object':
+                $sCommonPostPrefix = $this->_oConfig->getPrefix('common_post');
+                $sWhereClause = $this->prepareAsString("AND `{$sTableAlias}`.`system`='0' AND `{$sTableAlias}`.`object_id`=? ", $aParams['value']);
+                break;
+
+            case 'descriptor':
+                $sMethod = 'getRow';
+                $sWhereClause = "";
+
+                if(isset($aParams['type']))
+                    $sWhereClause .= $this->prepareAsString("AND `{$sTableAlias}`.`type`=? ", $aParams['type']);
+                if(isset($aParams['action']))
+                    $sWhereClause .= $this->prepareAsString("AND `{$sTableAlias}`.`action`=? ", $aParams['action']);
+                if(isset($aParams['object_id']))
+                    $sWhereClause .= $this->prepareAsString("AND `{$sTableAlias}`.`object_id`=? ", $aParams['object_id']);
+
+                $sLimitClause = "LIMIT 1";
+                break;
+
+            case 'reposted_by_track':
+                $sJoinClause = $this->prepareAsString("INNER JOIN `" . $this->_sTableRepostsTrack . "` AS `trt` ON `{$sTableAlias}`.`id`=`trt`.`event_id` AND `trt`.`reposted_id`=?", $aParams['value']);
+                break;
+
+            case 'reposted_by_descriptor':
+            	$sWhereClause = "";
+
+            	if(isset($aParams['type']))
+                    $sWhereClause .= "AND `{$sTableAlias}`.`content` LIKE " . $this->escape('%' . $aParams['type'] . '%');
+
+                if(isset($aParams['action']))
+                    $sWhereClause .= "AND `{$sTableAlias}`.`content` LIKE " . $this->escape('%' . $aParams['action'] . '%');
+                break;
+
+            case 'last':
+                $sMethod = 'getRow';
+                $sSelectClause .= ", YEAR(FROM_UNIXTIME(`{$sTableAlias}`.`date`)) AS `year`";
+                list($sJoinClause, $sWhereClause) = $this->_getSqlPartsEventsList($aParams);
+                $sOrderClause = "ORDER BY `{$sTableAlias}`.`date` ASC, `{$sTableAlias}`.`id` ASC";
+                $sLimitClause = "LIMIT 1";
+                break;
+
+            case 'ids':
+                $sWhereClause = "AND `{$sTableAlias}`.`id` IN (" . $this->implode_escape($aParams['ids']) . ") ";
+                break;
+
+            default:
+            	list($sMethod, $sSelectClause, $sJoinClause, $sWhereClause, $sOrderClause, $sLimitClause) = parent::_getSqlPartsEvents($aParams);
+        }
+
+        if($this->_isList($aParams)) {
+            $sOrderClause = "";
+
+            switch($aParams['type']) {
+                case BX_TIMELINE_TYPE_HOT:
+                    $sOrderClause = "`{$sTableAlias}`.`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_CONNECTED_CONTEXTS:
+                    case BX_TIMELINE_TYPE_FEED:
+                    case BX_TIMELINE_TYPE_OWNER_AND_CONNECTIONS:
+                        $sOrderClause = "`{$sTableAlias}`.`sticked` DESC, ";
+                        break;
+
+                    case BX_BASE_MOD_NTFS_TYPE_OWNER:
+                        $sOrderClause = "`{$sTableAlias}`.`pinned` DESC, ";
+                        break;
+            }
+            
+            if($this->_oConfig->isSortByUnread()) {
+                $oProfileQuery = BxDolProfileQuery::getInstance();
+
+                $iDate = 0;
+                $iOwner = (int)$aParams['owner_id'];
+                $aOwner = $oProfileQuery->getInfoById($iOwner);
+                $iViewer = !empty($aParams['viewer_id']) ? (int)$aParams['viewer_id'] : bx_get_logged_profile_id();
+                if(!empty($aOwner) && is_array($aOwner) && BxDolRequest::serviceExists($aOwner['type'], 'is_fan') && bx_srv($aOwner['type'], 'is_fan', [$iOwner, $iViewer])) {
+                    $oModule = BxDolModule::getInstance($aOwner['type']);
+                    $aConnection = BxDolConnection::getObjectInstance($oModule->_oConfig->CNF['OBJECT_CONNECTIONS'])->getConnection($iViewer, $iOwner);
+                    $iDate = (int)$aConnection['added'];
+                }
+                else {
+                    $aViewer = $oProfileQuery->getInfoById($iViewer);
+                    if(!empty($aViewer) && is_array($aViewer))
+                        $iDate = bx_srv($aViewer['type'], 'get_date_added', [$aViewer['content_id']]);
+                }
+
+                $sSelectClause .= ", IF(NOT ISNULL(`teu`.`id`), 1, 0) AS `read`";
+                $sOrderClause .= $this->prepareAsString("IF(`{$sTableAlias}`.`date` > ?, `read`, 1) ASC, ", $iDate);
+            }
+
+            if($this->_oConfig->isSortByReaction())
+                $sOrderClause .= "`{$sTableAlias}`.`reacted` DESC, ";
+            else
+                $sOrderClause .= "`{$sTableAlias}`.`date` DESC, ";
+
+            $sOrderClause = "ORDER BY " . $sOrderClause . "`{$sTableAlias}`.`id` DESC";
+        }
+
+        return array($sMethod, $sSelectClause, $sJoinClause, $sWhereClause, $sOrderClause, $sLimitClause);
+    }
+
+    protected function _getSqlPartsEventsListStatusAdmin($aParams)
+    {
+        if(isset($aParams['moderator']) && $aParams['moderator'] === true)
+            return '';
+
+        $iViewerId = !empty($aParams['viewer_id']) ? $aParams['viewer_id'] : bx_get_logged_profile_id();       
+
+        $sTableAlias = $this->getTableAlias();
+
+        //--- Check viewer as event author.
+        $sWhereClause = $this->prepareAsString("`{$sTableAlias}`.`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 `{$sTableAlias}`.`object_owner_id` IN (" . $this->implode_escape($aGroups) . ")";
+
+        return $this->prepareAsString(" AND IF(`{$sTableAlias}`.`system`='0' AND (" . $sWhereClause . "), 1, `{$sTableAlias}`.`status_admin`=?) ", isset($aParams['status_admin']) ? $aParams['status_admin'] : BX_TIMELINE_STATUS_ACTIVE);
+    }
+
+    protected function _getSqlPartsEventsList($aParams)
+    {
+        $sCommonPostPrefix = $this->_oConfig->getPrefix('common_post');
+
+        $sTableAlias = $this->getTableAlias();
+    	$mixedJoinClause = $mixedWhereClause = "";
+
+        $mixedJoinClause = "INNER JOIN `sys_profiles` AS `tpoo` ON ABS(`{$sTableAlias}`.`object_owner_id`)=`tpoo`.`id` AND `tpoo`.`status`='active'";
+
+        if($this->_oConfig->isSortByUnread())
+            $mixedJoinClause .= $this->prepareAsString(" LEFT JOIN `{$this->_sTableEvent2User}` AS `teu` ON `{$sTableAlias}`.`id`=`teu`.`event_id` AND `teu`.`user_id`=? ", $aParams['viewer_id']);
+
+        $sWhereClauseStatus = "AND `{$sTableAlias}`.`active`='1' ";
+        $sWhereClauseStatus .= $this->prepareAsString("AND `{$sTableAlias}`.`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 `" . $sTableAlias . "`.`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 media filter
+        $sWhereClauseMedias = "";
+        if(!empty($aParams['media'])) {
+            if(is_array($aParams['media'])) {
+                $sWhereSubclauseMedias = "0";
+                $aMediaTypes = $aParams['media'];
+                foreach($aMediaTypes as $sMediaType) {
+                    if(!isset($this->_aTablesEventFlags[$sMediaType]))
+                        continue;
+
+                    $sTableAliasFlag = 't' . substr($sMediaType, 0, 2);
+                    $mixedJoinClause .= " LEFT JOIN `" . $this->_aTablesEventFlags[$sMediaType] . "` AS `{$sTableAliasFlag}` ON `{$sTableAlias}`.`id`=`{$sTableAliasFlag}`.`event_id`";
+                    $sWhereSubclauseMedias .= " OR NOT ISNULL(`{$sTableAliasFlag}`.`event_id`)";
+                }
+                $sWhereClauseMedias .= "AND ({$sWhereSubclauseMedias}) ";
+            }
+            else {
+                $sMediaType = $aParams['media'];
+                if(isset($this->_aTablesEventFlags[$sMediaType])) {
+                    $sTableAliasFlag = 't' . substr($sMediaType, 0, 2);
+                    $mixedJoinClause .= " INNER JOIN `" . $this->_aTablesEventFlags[$sMediaType] . "` AS `{$sTableAliasFlag}` ON `{$sTableAlias}`.`id`=`{$sTableAliasFlag}`.`event_id`";
+                }
+            }
+        }
+
+        //--- 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 `{$sTableAlias}`.`owner_id` $sMuted AND `{$sTableAlias}`.`object_owner_id` $sMuted ";
+            }
+        }
+
+        //--- Apply unpublished (date in future) filter
+        $sWhereClauseUnpublished = $this->prepareAsString("AND IF(`{$sTableAlias}`.`system`='0' AND `{$sTableAlias}`.`object_id` = ?, 1, `{$sTableAlias}`.`date` <= UNIX_TIMESTAMP()) ", bx_get_logged_profile_id());
+
+        //--- Apply content filter
+        $oCf = BxDolContentFilter::getInstance();
+        $sWhereClauseCf = $oCf->isEnabled() ? $oCf->getSQLParts($sTableAlias, 'object_cf') . ' ' : '';
+
+        //--- Check type
+        $mixedJoinSubclause = $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.
+                $mixedJoinSubclause = "LEFT JOIN `{$this->_sTableHotTrack}` ON `{$sTableAlias}`.`id`=`{$this->_sTableHotTrack}`.`event_id`";
+                $mixedWhereSubclause = "NOT ISNULL(`{$this->_sTableHotTrack}`.`value`)";
+
+                //--- Select Promoted posts.
+                $mixedWhereSubclause .= " OR `{$sTableAlias}`.`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 = "`{$sTableAlias}`.`system`='1'";
+
+                //--- Select Public (Direct) posts created on Home Page Timeline (Public Feed) 
+                $mixedWhereSubclause .= $this->prepareAsString(" OR `{$sTableAlias}`.`owner_id`=?", 0);
+
+                //--- Select Promoted posts.
+                $mixedWhereSubclause .= " OR `{$sTableAlias}`.`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("(`{$sTableAlias}`.`owner_id` = ?)", $aParams['owner_id']);
+
+                //--- Select Own Public (Direct) posts from Home Page Timeline (Public Feed).
+                $mixedWhereSubclause .= $this->prepareAsString(" OR (`{$sTableAlias}`.`owner_id` = '0' AND IF(`{$sTableAlias}`.`system`='0', `{$sTableAlias}`.`object_id` = ?, 1))", $aParams['owner_id']);
+                break;
+
+            //--- Feed: All Profile Connections 
+            case BX_BASE_MOD_NTFS_TYPE_CONNECTIONS:
+                if(empty($aParams['owner_id']))
+                    break;
+
+                $mixedJoinSubclause = [];
+                $mixedWhereSubclause = [];
+
+                $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($sTableAlias, 'owner_id', $aParams['owner_id']);
+                $aJoin1 = $aQueryParts['join'];
+
+                $mixedJoinSubclause['p1'] = "INNER JOIN `" . $aJoin1['table'] . "` AS `" . $aJoin1['table_alias'] . "` ON " . $aJoin1['condition'];
+                $mixedWhereSubclause['p1'] = "1";
+
+                //--- Exclude Own (Direct) posts on timelines of following members.
+                //--- Note. Disabled for now.
+                //$mixedWhereSubclause['p1'] .= $this->prepareAsString(" AND IF(`{$sTableAlias}`.`system`='0', `{$sTableAlias}`.`object_id` <> ?, 1)", $aParams['owner_id']);
+
+                $aQueryParts = $oConnection->getConnectedContentAsSQLPartsExt($sTableAlias, 'object_id', $aParams['owner_id']);
+                $aJoin2 = $aQueryParts['join'];
+
+                $aQueryParts = $oConnection->getConnectedContentAsSQLPartsExt($sTableAlias, 'object_id', $aParams['owner_id']);
+                $aJoin2 = $aQueryParts['join'];
+                $aJoin2['table_alias'] = 'cc';
+                $aJoin2['condition'] = str_replace('`c`', '`' . $aJoin2['table_alias'] . '`', $aJoin2['condition']);
+
+                $mixedJoinSubclause['p2'] = "INNER JOIN `" . $aJoin2['table'] . "` AS `" . $aJoin2['table_alias'] . "` ON `" . $sTableAlias . "`.`system`='0' AND " . $aJoin2['condition'];
+                $mixedWhereSubclause['p2'] = "1";
+
+                //--- Select Promoted posts.
+                $mixedJoinSubclause['p3'] = "";
+                $mixedWhereSubclause['p3'] = "`{$sTableAlias}`.`promoted` <> '0'";
+                break;
+
+            //--- Feed: Profile Connections to contexts by type (groups, events, spaces, etc) only.
+            case BX_TIMELINE_TYPE_CONNECTED_CONTEXTS:
+                if(empty($aParams['owner_id']) || empty($aParams['context']))
+                    break;
+
+                $mixedJoinSubclause = [];
+                $mixedWhereSubclause = [];
+
+                //--- Filter out unnecessary contexts.
+                $aContexts = is_array($aParams['context']) ? $aParams['context'] : [$aParams['context']];
+                $mixedJoinSubclause['p1'] = "INNER JOIN `sys_profiles` AS `tpo` ON ABS(`{$sTableAlias}`.`owner_id`)=`tpo`.`id` AND `tpo`.`type` IN (" . $this->implode_escape($aContexts) . ") AND `tpo`.`status`='active' ";
+
+                //--- Join System posts received by following contexts.
+                $oConnection = BxDolConnection::getObjectInstance($this->_oConfig->getObject('conn_subscriptions'));
+                $aQueryParts = $oConnection->getConnectedContentAsSQLPartsExt($sTableAlias, 'owner_id', $aParams['owner_id']);
+                $aJoin1 = $aQueryParts['join'];
+
+                $mixedJoinSubclause['p1'] .= "INNER JOIN `" . $aJoin1['table'] . "` AS `" . $aJoin1['table_alias'] . "` ON " . $aJoin1['condition'];
+                $mixedWhereSubclause['p1'] = "1";
+
+                //--- Select Promoted posts.
+                $mixedJoinSubclause['p2'] = "";
+                $mixedWhereSubclause['p2'] = "`{$sTableAlias}`.`promoted` <> '0'";
+                break;
+
+            //--- Feed: Profile Connections to Channel contexts only
+            case BX_TIMELINE_TYPE_CHANNELS:
+                if(empty($aParams['owner_id']))
+                    break;
+
+                $mixedJoinSubclause = [];
+                $mixedWhereSubclause = [];
+
+                $oConnection = BxDolConnection::getObjectInstance($this->_oConfig->getObject('conn_subscriptions'));
+
+                //--- Join System posts received by following channels.
+                $aQueryParts = $oConnection->getConnectedContentAsSQLPartsExt($sTableAlias, 'owner_id', $aParams['owner_id']);
+                $aJoin1 = $aQueryParts['join'];
+
+                $mixedJoinSubclause['p1'] = "INNER JOIN `" . $aJoin1['table'] . "` AS `" . $aJoin1['table_alias'] . "` ON " . $aJoin1['condition'];
+                $mixedWhereSubclause['p1'] = "`{$sTableAlias}`.`type`='bx_channels'";
+
+                //--- Exclude Own (Direct) posts on timelines of following members.
+                //--- Note. Disabled for now.
+                //$mixedWhereSubclause['p1'] = $this->prepareAsString(" AND IF(`{$sTableAlias}`.`system`='0', `{$sTableAlias}`.`object_id` <> ?, 1)", $aParams['owner_id']);
+
+                //--- Select Promoted posts.
+                $mixedJoinSubclause['p2'] = "";
+                $mixedWhereSubclause['p2'] = "`{$sTableAlias}`.`promoted` <> '0'";
+                break;
+
+            //--- Feed: Profile + Profile Connections to Non-Channel contexts
+            case BX_TIMELINE_TYPE_FEED:
+            case BX_TIMELINE_TYPE_FEED_AND_HOT:
+                if(empty($aParams['owner_id']))
+                    break;
+
+                $mixedJoinSubclause = [];
+                $mixedWhereSubclause = [];
+
+                $oConnection = BxDolConnection::getObjectInstance($this->_oConfig->getObject('conn_subscriptions'));
+
+                //--- Select Own (System and Direct) posts from Profile's Timeline.
+                $sWhereSubclauseOwnProfile = $this->prepareAsString("(`{$sTableAlias}`.`owner_id` = ?)", $aParams['owner_id']);
+
+                //--- Select Own Public (Direct) posts from Home Page Timeline (Public Feed).
+                $sWhereSubclauseOwnPublic = $this->prepareAsString("(`{$sTableAlias}`.`owner_id` = '0' AND IF(`{$sTableAlias}`.`system`='0', `{$sTableAlias}`.`object_id` = ?, 1))", $aParams['owner_id']);
+
+                $mixedJoinSubclause['p1'] = "";
+                $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($sTableAlias, 'owner_id', $aParams['owner_id']);
+                $aJoin1 = $aQueryParts['join'];
+
+                $mixedJoinSubclause['p2'] = "INNER JOIN `" . $aJoin1['table'] . "` AS `" . $aJoin1['table_alias'] . "` ON " . $aJoin1['condition'];
+                $mixedWhereSubclause['p2'] = "`{$sTableAlias}`.`type`<>'bx_channels'";
+                
+                //--- 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(`{$sTableAlias}`.`system`='0', `{$sTableAlias}`.`object_id` <> ?, 1))", $aParams['owner_id']);
+
+                $aQueryParts = $oConnection->getConnectedContentAsSQLPartsExt($sTableAlias, 'object_owner_id', $aParams['owner_id']);
+                $aJoin2 = $aQueryParts['join'];
+                $aJoin2['table_alias'] = 'cc';
+                $aJoin2['condition'] = str_replace('`c`', '`' . $aJoin2['table_alias'] . '`', $aJoin2['condition']);
+
+                $mixedJoinSubclause['p3'] = "INNER JOIN `" . $aJoin2['table'] . "` AS `" . $aJoin2['table_alias'] . "` ON `" . $sTableAlias . "`.`system` = 0 AND `" . $sTableAlias . "`.`object_privacy_view` > 0 AND " . $aJoin2['condition'];
+                $mixedWhereSubclause['p3'] = "1";
+
+                //--- Select Promoted posts.
+                $mixedJoinSubclause['p4'] = "";
+                $mixedWhereSubclause['p4'] = "`{$sTableAlias}`.`promoted` <> '0'";
+
+                //--- Select Hot posts.
+                if($aParams['type'] == BX_TIMELINE_TYPE_FEED_AND_HOT) {
+                    $mixedJoinSubclause['p5'] = "INNER JOIN `{$this->_sTableHotTrack}` ON `{$sTableAlias}`.`id`=`{$this->_sTableHotTrack}`.`event_id`";
+                    $mixedWhereSubclause['p5'] = "1";
+                }
+                break;
+
+            //--- Feed: Profile + All Profile Connections
+            case BX_TIMELINE_TYPE_OWNER_AND_CONNECTIONS:
+                if(empty($aParams['owner_id']))
+                    break;
+
+                $mixedJoinSubclause = [];
+                $mixedWhereSubclause = [];
+
+                $oConnection = BxDolConnection::getObjectInstance($this->_oConfig->getObject('conn_subscriptions'));
+
+                //--- Select Own (System and Direct) posts from Profile's Timeline.
+                $sWhereSubclauseOwnProfile = $this->prepareAsString("(`{$sTableAlias}`.`owner_id` = ?)", $aParams['owner_id']);
+
+                //--- Select Own Public (Direct) posts from Home Page Timeline (Public Feed).
+                $sWhereSubclauseOwnPublic = $this->prepareAsString("(`{$sTableAlias}`.`owner_id` = '0' AND IF(`{$sTableAlias}`.`system`='0', `{$sTableAlias}`.`object_id` = ?, 1))", $aParams['owner_id']);
+
+                $mixedJoinSubclause['p1'] = "";
+                $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($sTableAlias, 'owner_id', $aParams['owner_id']);
+                $aJoin1 = $aQueryParts['join'];
+
+                $mixedJoinSubclause['p2'] = "INNER JOIN `" . $aJoin1['table'] . "` AS `" . $aJoin1['table_alias'] . "` ON " . $aJoin1['condition'];
+                $mixedWhereSubclause['p2'] = "1";
+                
+                //--- 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(`{$sTableAlias}`.`system`='0', `{$sTableAlias}`.`object_id` <> ?, 1))", $aParams['owner_id']);
+
+                $aQueryParts = $oConnection->getConnectedContentAsSQLPartsExt($sTableAlias, 'object_id', $aParams['owner_id']);
+                $aJoin2 = $aQueryParts['join'];
+                $aJoin2['table_alias'] = 'cc';
+                $aJoin2['condition'] = str_replace('`c`', '`' . $aJoin2['table_alias'] . '`', $aJoin2['condition']);
+
+                $mixedJoinSubclause['p3'] = "INNER JOIN `" . $aJoin2['table'] . "` AS `" . $aJoin2['table_alias'] . "` ON `" . $sTableAlias . "`.`system`='0' AND " . $aJoin2['condition'];
+                $mixedWhereSubclause['p3'] = "1";
+
+                //--- Select Promoted posts.
+                $mixedJoinSubclause['p4'] = "";
+                $mixedWhereSubclause['p4'] = "`{$sTableAlias}`.`promoted` <> '0'";
+                break;
+
+            //--- Feed: Profile Connections to contexts from Selected module
+            default:
+                if(empty($aParams['owner_id']))
+                    break;
+
+                $mixedJoinSubclause = [];
+                $mixedWhereSubclause = [];
+
+                $oConnection = BxDolConnection::getObjectInstance($this->_oConfig->getObject('conn_subscriptions'));
+
+                //--- Join System posts received by following channels.
+                $aQueryParts = $oConnection->getConnectedContentAsSQLPartsExt($sTableAlias, 'owner_id', $aParams['owner_id']);
+                $aJoin1 = $aQueryParts['join'];
+
+                $mixedJoinSubclause['p1'] = "INNER JOIN `sys_profiles` AS `p` ON `" . $sTableAlias ."`.`owner_id`=`p`.`id` AND `p`.`type`='" . $aParams['type'] . "' ";
+                $mixedJoinSubclause['p1'] .= "INNER JOIN `" . $aJoin1['table'] . "` AS `" . $aJoin1['table_alias'] . "` ON " . $aJoin1['condition'];
+
+                $mixedWhereSubclause['p1'] = "1";
+                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(`{$sTableAlias}`.`system`='0', `{$sTableAlias}`.`object_id` <> ?, 1)", $aParams['owner_id']);
+
+                //--- Select Promoted posts.
+                $mixedJoinSubclause['p2'] = "";
+                $mixedWhereSubclause['p2'] = "`" . $sTableAlias . "`.`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' => isset($aParams['from_cache']) && $aParams['from_cache'] === true ? $this->_sTableSlice : $this->_sTable,
+            'join_clause' => &$mixedJoinClause,
+            'join_subclause' => &$mixedJoinSubclause,
+            '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_medias' => &$sWhereClauseMedias,
+            '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 .= $sWhereClauseMedias;
+        $mixedWhereClause .= $sWhereClauseMuted;
+        $mixedWhereClause .= $sWhereClauseUnpublished;
+        $mixedWhereClause .= $sWhereClauseCf;
+
+        //--- Combine general Join with SubJoins.
+        if(!empty($mixedJoinSubclause)) {
+            if(is_array($mixedJoinSubclause)) {
+                $aJoinClause = [];
+                foreach($mixedJoinSubclause as $sKey => $sValue)
+                    $aJoinClause[$sKey] = $mixedJoinClause . " " . $sValue . " ";
+                $mixedJoinClause = $aJoinClause;
+            }
+            else
+                $mixedJoinClause .= " " . $mixedJoinSubclause . " ";
+        }
+
+        //--- Combine general Where with SubWheres.
+        if(!empty($mixedWhereSubclause)) {
+            if(is_array($mixedWhereSubclause)) {
+                $aWhereClause = [];
+                foreach($mixedWhereSubclause as $sKey => $sValue)
+                    $aWhereClause[$sKey] = $mixedWhereClause . "AND " . $sValue . " ";
+                $mixedWhereClause = $aWhereClause;
+            }
+            else
+                $mixedWhereClause .= "AND (" . $mixedWhereSubclause . ") ";
+        }
+
+        return [$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
+        ]);
+    }
+}
+
+/** @} */

+ 485 - 0
modules/boonex/timeline/updates/13.0.11_13.0.12/source/classes/BxTimelineFormPost.php

@@ -0,0 +1,485 @@
+<?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 $_sType; //--- Is needed for Edit form. Determines which timeline the form was called from.
+    protected $_bVisibilityAutoselect;
+
+    protected $_aUploadersInfo;
+
+    public function __construct($aInfo, $oTemplate = false)
+    {
+        $this->MODULE = 'bx_timeline';
+
+        parent::__construct($aInfo, $oTemplate);
+
+        $this->_sGhostTemplate = 'uploader_nfw.html';
+
+        $this->_resetMode();
+        if(isset($this->aParams['display']))
+            switch($this->aParams['display']) {
+                case $this->_oModule->_oConfig->getObject('form_display_post_add'):
+                    $this->setModeAccount();
+                    break;
+
+                case $this->_oModule->_oConfig->getObject('form_display_post_add_public'):
+                    $this->setModePublic();
+                    break;
+
+                case $this->_oModule->_oConfig->getObject('form_display_post_add_profile'):
+                    $this->setModeProfile();
+                    break;
+            }
+
+        $this->_sType = '';
+        $this->_bVisibilityAutoselect = true;
+
+        $this->_aUploadersInfo = [];
+    }
+
+    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;
+
+        $bEdit = $this->aParams['display'] == $this->_oModule->_oConfig->getObject('form_display_post_edit');
+
+        $iUserId = $this->_oModule->getUserId();
+        $bValueId = $aValues && !empty($aValues['id']);
+        $iValueId = $bValueId ? (int)$aValues['id'] : 0;
+
+        if($bEdit && isset($aValues[$CNF['FIELD_OWNER_ID']]) && (int)$aValues[$CNF['FIELD_OWNER_ID']] === 0) 
+            $this->setType(BX_BASE_MOD_NTFS_TYPE_PUBLIC);
+
+        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() . $this->_oModule->_oTemplate->parseHtmlByName('uploader_progress.html', []);;
+        }
+
+        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($bEdit && 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();
+        }
+
+        $this->_initPrivacyFields();
+
+        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']]['storage_private'] = 0;
+            $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']]['storage_private'] = 0;
+            $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']]['storage_private'] = 0;
+            $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 setModePublic()
+    {
+        $this->_resetMode();
+
+        $this->_bPublicMode = true;
+    }
+
+    public function setModeProfile()
+    {
+        $this->_resetMode();
+
+        $this->_bProfileMode = true;
+    }
+
+    public function setModeAccount()
+    {
+        $this->_resetMode();
+
+        $this->_bAccountMode = true;
+    }
+
+    public function setType($sType)
+    {
+        $this->_sType = $sType;
+
+        switch($this->_sType) {
+            case BX_BASE_MOD_NTFS_TYPE_PUBLIC:
+                $this->setModePublic();
+                break;
+
+            case BX_BASE_MOD_NTFS_TYPE_OWNER:
+                $this->setModeProfile();
+                break;
+
+            case BX_TIMELINE_TYPE_OWNER_AND_CONNECTIONS:
+            case BX_TIMELINE_TYPE_CONNECTED_CONTEXTS:
+            case BX_TIMELINE_TYPE_FEED:
+            case BX_TIMELINE_TYPE_FEED_AND_HOT:
+                $this->setModeAccount();
+                break;
+        }
+
+        $this->_initPrivacyFields();
+    }
+
+    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);
+    }
+
+    protected function _initPrivacyFields()
+    {
+        $aPrivacyFields = $this->_getPrivacyFields();
+        foreach($aPrivacyFields as $sField => $sPrivacyObject)
+            $this->_initPrivacyField($sField, $sPrivacyObject);
+    }
+
+    /**
+     * 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 = [])
+    {
+    	return [
+            'js_object' => $this->_oModule->_oConfig->getJsObject('post'),
+            'name' => $this->aInputs[$sName]['name'],
+            'content_id' => (int)$this->aInputs[$sName]['content_id'],
+        ];
+    }
+    
+    protected function _getPhotoGhostTmplVars($aContentInfo = [])
+    {
+        return array_merge(parent::_getPhotoGhostTmplVars($aContentInfo), [
+            'js_object' => $this->_oModule->_oConfig->getJsObject('post'),
+        ]);
+    }
+
+    protected function _resetMode()
+    {
+        $this->_bPublicMode = false;
+        $this->_bProfileMode = false;
+        $this->_bAccountMode = false;
+    }
+}
+
+/** @} */

+ 237 - 0
modules/boonex/timeline/updates/13.0.11_13.0.12/source/classes/BxTimelineMenuItemShare.php

@@ -0,0 +1,237 @@
+<?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 BxTimelineMenuItemShare extends BxTemplMenu
+{
+    protected $_sModule;
+    protected $_oModule;
+
+    protected $_iEvent;
+    protected $_aEvent;
+
+    public function __construct($aObject, $oTemplate = false)
+    {
+        $this->_sModule = 'bx_timeline';
+        $this->_oModule = BxDolModule::getInstance($this->_sModule);
+
+        parent::__construct($aObject, $this->_oModule->_oTemplate);
+
+        $iContentId = 0;
+        if(bx_get('content_id') !== false)
+            $iContentId = bx_process_input(bx_get('content_id'), BX_DATA_INT);
+
+        if(!empty($iContentId)) {
+            $aBrowseParams = array('name' => '', 'view' => '', 'type' => '');
+            foreach($aBrowseParams as $sKey => $sValue)
+                if(bx_get($sKey) !== false)
+                    $aBrowseParams[$sKey] = $this->_oModule->_oConfig->prepareParam($sKey);
+
+            $this->setEventById($iContentId, $aBrowseParams);
+        }
+    }
+
+    public function setEventById($iEventId, $aBrowseParams = array())
+    {
+    	$this->_iEvent = $iEventId;
+    	$this->_aEvent = $this->_oModule->_oDb->getEvents(array('browse' => 'id', 'value' => $this->_iEvent));
+
+        $this->_setBrowseParams($aBrowseParams);
+
+        $sRepostOnclick = $sEtSend = '';
+        if(!empty($this->_aEvent) && is_array($this->_aEvent)) {
+            $sType = $this->_aEvent['type'];
+            $sAction = $this->_aEvent['action'];
+
+            $this->_aEvent['url'] = $this->_oModule->_oConfig->getItemViewUrl($this->_aEvent);
+            if($this->_oModule->_oConfig->isSystem($sType, $sAction)) {
+                $aResult = $this->_oModule->_oConfig->getSystemData($this->_aEvent);
+                if(!empty($aResult['url']))
+                    $this->_aEvent['url'] = $aResult['url'];
+            }
+
+            //--- Repost and 'Repost To' items
+            $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);
+            $sRepostWithOnclick = $this->_oModule->serviceGetRepostWithJsClick($iOwnerId, $sType, $sAction, $iObjectId);
+            $sRepostToOnclick = $this->_oModule->serviceGetRepostToJsClick($iOwnerId, $sType, $sAction, $iObjectId);
+
+            //--- Send item
+    	    $sAetSend = urlencode(base64_encode(serialize(array(
+    	        'name' => 'bx_timeline_send',
+    	        'params' => array(
+    	            'ViewLink' => $this->_aEvent['url']
+    	        )
+    	    )))); 
+        }
+
+    	$this->addMarkers(array(
+            'content_id' => $this->_iEvent,
+            'content_url' => $this->_aEvent['url'],
+
+            'repost_onclick' => $sRepostOnclick,
+            'repost_with_onclick' => $sRepostWithOnclick,
+            'repost_to_onclick' => $sRepostToOnclick,
+            'et_send' => $sAetSend
+    	));
+    }
+
+    public function getMenuItems ()
+    {
+        $aItems = parent::getMenuItems();
+
+        $aMarkers = array(
+            'id' => $this->_iEvent,
+            'module' => $this->_oModule->_oConfig->getName(),
+            'url' => $this->_aEvent['url'],
+            'title' => $this->_aEvent['title'],
+            'img_url' => '',
+            'img_url_encoded' => ''
+        );
+
+        $aEventData = $this->_oModule->_oTemplate->getDataCached($this->_aEvent);
+        if(!empty($aEventData['content']['images']) && is_array($aEventData['content']['images'])) {
+            $aImage = array_shift($aEventData['content']['images']);
+
+            $sImgUrl = isset($aImage['src_medium']) ? $aImage['src_medium'] : $aImage['src'];;
+            if(!empty($sImgUrl))
+                $aMarkers = array_merge($aMarkers, array(
+                    'img_url' => $sImgUrl,
+                    'img_url_encoded' => rawurlencode($sImgUrl),
+                ));
+        }
+
+        if(($oSocial = BxDolMenu::getObjectInstance('sys_social_sharing')) !== false) {
+            $oSocial->addMarkers($aMarkers);
+
+            $aItems = array_merge($aItems, $oSocial->getMenuItems());
+        }
+
+        if($this->_bIsApi) {
+            $aItemsApi = [];
+
+            foreach($aItems as $aItem)
+                switch($aItem['name']) {
+                    case 'item-repost':
+                        $iOwnerId = $this->_oModule->getUserId();
+                        $sType = $this->_aEvent['type'];
+                        $sAction = $this->_aEvent['action'];
+                        $iObjectId = 0;
+
+                        $sCommonPrefix = $this->_oModule->_oConfig->getPrefix('common_post');
+                        if(str_replace($sCommonPrefix, '', $sType) == BX_TIMELINE_PARSE_TYPE_REPOST) {
+                            $aRepostedData = unserialize($this->_aEvent['content']);
+
+                            $sType = $aRepostedData['type'];
+                            $sAction = $aRepostedData['action'];
+                            $iObjectId = $aRepostedData['object_id'];
+                        }
+                        else
+                            $iObjectId = $this->_oModule->_oConfig->isSystem($sType, $sAction) ? $this->_aEvent['object_id'] : $this->_aEvent['id'];
+
+                        $aItemsApi['item-repost'] = array_merge($aItem, [
+                            'data' => [
+                                'author_id' => $iOwnerId,
+                                'owner_id' => $iOwnerId,
+                                'type' => $sType,
+                                'action' => $sAction,
+                                'object_id' => $iObjectId
+                            ]
+                        ]);
+                        break;
+
+                    /**
+                     * TODO: Update when Copy function will be added in Timeline.
+                     */
+                    case 'item-send':
+                        $aItemsApi['item-copy'] = array_merge($aItem, [
+                            'name' => 'item-copy',
+                            'title' => _t('_bx_timeline_menu_item_title_item_copy'),
+                            'link' => $aMarkers['url'],
+                        ]);
+                        break;
+
+                    /**
+                     * TODO: Update when unified Share popup will be used here.
+                     */
+                    case 'social-sharing-facebook':
+                    case 'social-sharing-twitter':
+                    case 'social-sharing-pinterest':
+                    case 'social-sharing-linked_in':
+                    case 'social-sharing-whatsapp':
+                        if(isset($aItemsApi['item-share']))
+                            break;
+
+                        $aItemsApi['item-share'] = array_merge($aItem, [
+                            'name' => 'item-share',
+                            'title' => _t('_sys_menu_item_title_social_sharing'),
+                            'link' => $aMarkers['url'],
+                        ]);
+                        break;
+                }
+
+            return array_values($aItemsApi);
+        }
+
+        return $aItems;
+    }
+
+    protected function _setBrowseParams($aBrowseParams = array())
+    {
+        $aMarkers = array();
+        foreach($aBrowseParams as $sKey => $mixedValue)
+            if(!is_array($aMarkers))
+                $aMarkers[$sKey] = $mixedValue;
+
+        $this->addMarkers($aMarkers);
+        $this->addMarkers(array(
+            'js_object_view' => $this->_oModule->_oConfig->getJsObjectView($aBrowseParams)
+        ));
+    }
+
+    /**
+     * Check if menu items is visible.
+     * @param $a menu item array
+     * @return boolean
+     */
+    protected function _isVisible ($a)
+    {
+        if(!parent::_isVisible($a))
+            return false;
+
+        if(empty($this->_aEvent) || !is_array($this->_aEvent))
+            return false;
+
+        $sCheckFuncName = '';
+        $aCheckFuncParams = array();
+        switch ($a['name']) {
+            case 'item-repost':
+                $sCheckFuncName = 'isAllowedRepost';
+                $aCheckFuncParams = array($this->_aEvent);
+                break;
+
+            case 'item-send':
+                $sCheckFuncName = 'isAllowedSend';
+                $aCheckFuncParams = array($this->_aEvent);
+                break;
+        }
+
+        if(!$sCheckFuncName || !method_exists($this->_oModule, $sCheckFuncName))
+            return true;
+
+        return call_user_func_array(array($this->_oModule, $sCheckFuncName), $aCheckFuncParams) === true;
+    }
+}
+
+/** @} */

+ 91 - 0
modules/boonex/timeline/updates/13.0.11_13.0.12/source/classes/BxTimelineMenuPostAttachments.php

@@ -0,0 +1,91 @@
+<?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 BxTimelineMenuPostAttachments extends BxTemplMenu
+{
+    protected $_oModule;
+
+    protected $_iEvent;
+    
+    /**
+     * An array with uploaders, which are 
+     * available (active) in create form.
+     */
+    protected $_aUploadersInfo;
+
+    public function __construct($aObject, $oTemplate = false)
+    {
+        parent::__construct($aObject, $oTemplate);
+
+        $this->_oModule = BxDolModule::getInstance('bx_timeline');
+
+        $this->addMarkers(array(
+            'js_object' => $this->_oModule->_oConfig->getJsObject('post'),
+        ));
+    }
+
+    public function setEventById($iEventId, $aBrowseParams = array())
+    {
+        $this->_iEvent = $iEventId;
+
+        $this->addMarkers(array(
+            'content_id' => $this->_iEvent,
+        ));
+    }
+
+    public function setUploadersInfo($aUploadersInfo)
+    {
+        $this->_aUploadersInfo = $aUploadersInfo;
+    }
+
+    public function isMenuItem($sName)
+    {
+        if(empty($this->_aObject['menu_items'][$sName]) || !is_array($this->_aObject['menu_items'][$sName]))
+            return false;
+
+        $aMenuItem = $this->_aObject['menu_items'][$sName];
+        if(isset($aMenuItem['active']) && !$aMenuItem['active'])
+            return false;
+
+        return $this->_isVisible($aMenuItem);
+    }
+    
+    protected function _getMenuItem($a)
+    {
+        if(isset($a['active']) && !$a['active'])
+            return false;
+
+        if(isset($a['visible_for_levels']) && !$this->_isVisible($a))
+            return false;
+        
+        if(($sUploader = $this->_oModule->_oConfig->getUploaderByMenuItem($a['name'])) !== false) {
+            if(!isset($this->_aUploadersInfo[$sUploader]))
+                return false;
+
+            $this->addMarkers(array(
+                'js_object_' . str_replace('-', '_', $a['name']) => $this->_aUploadersInfo[$sUploader]['js_object']
+            ));
+        }
+
+        $aResult = parent::_getMenuItem($a);
+
+        switch($a['name']) {
+            case 'add-link': 
+                if($this->_oModule->_oConfig->isMediaPriority() && $this->_oModule->hasMedia($this->_iEvent))
+                    $aResult['class_link'] = 'bx-btn-disabled';
+                break;
+        }
+
+        return $aResult;
+    }
+}
+
+/** @} */

+ 5782 - 0
modules/boonex/timeline/updates/13.0.11_13.0.12/source/classes/BxTimelineModule.php

@@ -0,0 +1,5782 @@
+<?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_CONNECTED_CONTEXTS', 'connected_contexts'); //--- Followed contexts by type (groups, events, spaces, etc) only.
+define('BX_TIMELINE_TYPE_CHANNELS', 'channels'); //--- Followed channels only.
+define('BX_TIMELINE_TYPE_FEED', 'feed'); //--- Owner and followed contexts excluding channels.
+define('BX_TIMELINE_TYPE_HOT', 'hot'); //--- Aggrigated hot content.
+define('BX_TIMELINE_TYPE_FEED_AND_HOT', 'feed_and_hot'); 
+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)));
+
+        if (!bx_is_api())
+            echoJson($this->getFormPost());
+        else
+            $this->getFormPost();
+    }
+
+    public function actionEdit($iId)
+    {
+        $this->_iOwnerId = bx_process_input(bx_get('owner_id'), BX_DATA_INT);
+
+        $aParams = [
+            'type' => BX_TIMELINE_TYPE_DEFAULT,
+            'dynamic_mode' => true
+        ];
+
+        $aBrowseParams = [];
+        if(bx_get('bp') !== false) {
+            $aBrowseParams = $this->_oConfig->getBrowseParams(bx_process_input(bx_get('bp')));
+            $aBrowseParams = $this->_prepareParamsGet($aBrowseParams);
+
+            $aParams['type'] = $aBrowseParams['type'];
+        }
+
+        $mixedAllowed = $this->isAllowedPost(true);
+        if($mixedAllowed !== true)
+            return echoJson(array('message' => strip_tags($mixedAllowed)));
+
+        echoJson($this->getFormEdit($iId, $aParams, $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();
+
+        $this->_iOwnerId = $aParams['owner_id'];
+        $oProfileOwner = BxDolProfile::getInstance($this->_iOwnerId);
+        if(!$oProfileOwner)
+            return echoJson([]);
+
+        $mixedResult = $oProfileOwner->checkAllowedProfileView();
+        if($mixedResult !== CHECK_ACTION_RESULT_ALLOWED)
+            return echoJson(['code' => 1, 'msg' => $mixedResult]);
+
+        $sContent = $this->_oTemplate->getViewBlock($aParams);
+        if(empty($sContent))
+            return echoJson([]);
+
+        if(!empty($aParams['type']))
+            $this->_oConfig->setUserChoice(['type' => $aParams['type']]);
+
+        echoJson([
+            '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)"
+        ));
+    }
+    
+  
+    /**
+     * @page service Service Calls
+     * @section bx_timeline Timeline
+     * @subsection bx_timeline-other Other
+     * @subsubsection bx_timeline-get_posts get_posts
+     * 
+     * @code bx_srv('bx_timeline', 'get_posts', [...]); @endcode
+     * 
+     * Get a posts list for API.
+     *
+     * @return an array 
+     * 
+     * @see BxTimelineModule::serviceGetPosts
+     */
+     /** 
+     * @ref bx_timeline-get_posts "get_posts"
+     * @api @ref bx_timeline-get_posts "get_posts"
+     */
+    
+    function serviceGetPosts($aParams)
+    {
+        if(is_string($aParams)){
+            $aParams = json_decode($aParams, true);
+        }
+
+        return $this->_serviceGetBlockViewByType($aParams['params']);
+    }
+
+    public function actionGetPostForm()
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $this->_iOwnerId = bx_process_input(bx_get('owner_id'), BX_DATA_INT);
+        $sType = bx_process_input(bx_get('type'));
+
+        $aResult = $this->getFormPost([
+            'type' => $sType,
+            'form_display' => $this->_oConfig->getPostFormDisplay($sType)
+        ]);
+
+        if($this->_oConfig->isEditorAutoattach() && !empty($aResult['form_object'])) {
+            $aUploadersInfo = $aResult['form_object']->getUploadersInfo($CNF['FIELD_PHOTO']);
+            if(!empty($aUploadersInfo) && is_array($aUploadersInfo))
+                $aResult = array_merge($aResult, ['options' => [
+                    'sAutoUploader' => $aUploadersInfo['name'], 
+                    'sAutoUploaderId' => $aUploadersInfo['id']
+                ]]);
+
+            unset($aResult['form_object']);
+        }
+
+        echoJson($aResult);
+    }
+
+    public function actionGetEditForm($iId)
+    {
+        $aBrowseParams = $this->_prepareParamsGet();
+        $this->_iOwnerId = $aBrowseParams['owner_id'];
+
+        echoJson($this->getFormEdit($iId, [
+            'type' => $aBrowseParams['type'],
+            'dynamic_mode' => true
+        ], $aBrowseParams));
+    }
+    
+    public function serviceGetEditForm($iId)
+    {
+        $aFrm = $this->getFormEdit($iId)['form'];
+        $aFrm['inputs']['tlb_do_submit'] = $aFrm['inputs']['controls'][0];
+        unset($aForm['inputs']['controls']);
+        $aRv['form'] = ['id' => 'bx_timeline', 'type' => 'form', 'name' => 'feed_edit', 'data' => $aFrm, 'request' => ['immutable' => true]];
+        $aItemData = $this->getItemData($iId);
+        if(is_array($aItemData) && !empty($aItemData['event']))
+            $aRv['item'] = $this->_oTemplate->_getPostApi($aItemData['event']);
+        return $aRv;
+    }
+
+    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([]);
+
+        $aLink = $this->_oDb->getLinksBy(['type' => 'id', 'id' => $iLinkId, 'profile_id' => $iUserId]);
+    	if(empty($aLink) || !is_array($aLink))
+            return echoJson([]);
+
+        if(!empty($aLink['media_id']))
+            BxDolStorage::getObjectInstance($this->_oConfig->getObject('storage_photos'))->deleteFile($aLink['media_id']);
+
+        $aResult = [];
+        if($this->_oDb->deleteLink($iLinkId))
+            $aResult = ['code' => 0, 'url' => $aLink['url']];
+        else
+            $aResult = ['code' => 1, 'message' => _t('_bx_timeline_form_post_input_link_err_delete')];
+
+        echoJson($aResult);
+    }
+
+    public function actionDeleteAttachLinks()
+    {
+    	$iUserId = $this->getUserId();
+        $iEventId = bx_process_input(bx_get('event_id'), BX_DATA_INT);
+
+        $aParams = $iEventId > 0 ? ['type' => 'event_id', 'event_id' => $iEventId] : ['type' => 'unused', 'profile_id' => $iUserId];
+        $aLinks = $this->_oDb->getLinksBy($aParams);
+
+        $oStorage = BxDolStorage::getObjectInstance($this->_oConfig->getObject('storage_photos'));
+
+        $aUrls = [];
+        foreach($aLinks as $aLink) {
+            $aUrls[] = $aLink['url'];
+
+            if(!empty($aLink['media_id']))
+                $oStorage->deleteFile($aLink['media_id']);
+
+            $this->_oDb->deleteLink($aLink['id']);
+        }
+
+        echoJson(['code' => 0, 'urls' => $aUrls]);
+    }
+
+    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, true, 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 = $this->_oConfig->processParam(array_shift($aArgs));
+        switch($sType) {
+            case BX_BASE_MOD_NTFS_TYPE_OWNER:
+                $iOwnerId = (int)array_shift($aArgs);
+                $sOwnerName = $this->getObjectUser($iOwnerId)->getDisplayName();
+
+                $sRssCaption = _t('_bx_timeline_txt_rss_caption', $sOwnerName);
+                $sRssLink = $this->_oConfig->getViewUrl($iOwnerId);
+                break;
+
+            default:
+                $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' => '',
+            'GetPosts' => '',
+            'Repost' => '',
+            'Delete' => '',
+            'GetEditForm' => '',
+        ));
+    }
+
+    /**
+     * @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())
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+    	$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'];
+
+            if($this->_oConfig->isEditorAutoattach() && !empty($aResult['form_object'])) {
+                $aUploadersInfo = $aResult['form_object']->getUploadersInfo($CNF['FIELD_PHOTO']);
+                if(!empty($aUploadersInfo) && is_array($aUploadersInfo))
+                    $aParams = [
+                        'gparams' => ['sAutoUploader' => $aUploadersInfo['name'], 'sAutoUploaderId' => $aUploadersInfo['id']],
+                        'rparams' => $aParams
+                    ];
+            }
+
+            $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
+     * 
+     * @example Events from followed contexts by type (groups, events, spaces, etc). Groups in this example.
+     * array ('module' => 'bx_timeline', 'method' => 'get_block_view_custom', 'params' => array (0 => array ('view' => 'timeline', 'type' => 'connected_contexts', 'context' => 'bx_groups')))
+     * 
+     * @example Events from "For You" (Feed + Hot) feed.
+     * array ('module' => 'bx_timeline', 'method' => 'get_block_view_custom', 'params' => array (0 => array ('view' => 'timeline', 'type' => 'feed_and_hot')))
+     */
+    /** 
+     * @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([
+            'name' => BX_TIMELINE_NAME_VIEWS_DB,
+            'view' => BX_TIMELINE_VIEW_TIMELINE,
+            'type' => BX_TIMELINE_TYPE_FEED,
+            'owner_id' => $this->getProfileId()
+        ], $aParams));
+
+        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);
+        
+        if (bx_is_api()){
+            $aEventAdd = [
+                'author_data' => BxDolProfile::getData($aItemData['event']['object_owner_id'])
+            ];
+
+            $oMenuActions = BxDolMenu::getObjectInstance($this->_oConfig->getObject('menu_item_actions_all'));
+            if(!$oMenuActions)
+                $oMenuActions = BxDolMenu::getObjectInstance($this->_oConfig->getObject('menu_item_actions'));
+            if($oMenuActions !== false) {
+                $oMenuActions->setEvent($aItemData['event'], $aParams);
+
+                $aEventAdd['menu_actions'] = $oMenuActions->getCodeAPI();
+            }
+
+            $aItemData['event'] = array_merge($aItemData['event'], $aEventAdd);
+
+            return [bx_api_get_block('feed_item', $aItemData)];
+        }
+        
+        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_absolute_url($this->_oConfig->getItemViewUrl($aContent, false), '{bx_url_root}'),
+            '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_absolute_url($this->_oConfig->getItemViewUrl($aContent, false), '{bx_url_root}'),
+            'entry_caption' => $sEntryCaption,
+            'entry_author' => $aContent['owner_id'],
+            'subentry_sample' => $CNF['T']['txt_sample_comment_single'],
+            'subentry_url' => bx_absolute_url($oComment->getViewUrl((int)$aEvent['subobject_id'], false), '{bx_url_root}'),
+            '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_absolute_url($oComment->getViewUrl($iParentId, false), '{bx_url_root}'),
+            'entry_caption' => strmaxtextlen($aParentInfo['cmt_text'], 20, '...'),
+            'entry_author' => (int)$aParentInfo['cmt_author_id'],
+            'subentry_sample' => '_cmt_txt_sample_reply_to',
+            'subentry_url' => bx_absolute_url($oComment->getViewUrl((int)$aEvent['subobject_id'], false), '{bx_url_root}'),
+            '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_absolute_url($this->_oConfig->getItemViewUrl($aContent, false), '{bx_url_root}'),
+            '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_absolute_url($this->_oConfig->getItemViewUrl($aContent, false), '{bx_url_root}'),
+            '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_absolute_url($this->_oConfig->getItemViewUrl($aContent, false), '{bx_url_root}'),
+            '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_element_block_api get_repost_element_block_api
+     * 
+     * @code bx_srv('bx_timeline', 'get_repost_element_block_api', [...]); @endcode
+     * 
+     * Get repost element for content based modules. 
+     * Note. Response is formated to be used in API calls.
+     * 
+     * @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::serviceGetRepostElementBlockApi
+     */
+    /** 
+     * @ref bx_timeline-get_repost_element_block_api "get_repost_element_block_api"
+     * @api @ref bx_timeline-get_repost_element_block_api "get_repost_element_block_api"
+     */
+    public function serviceGetRepostElementBlockApi($iOwnerId, $sType, $sAction, $iObjectId, $aParams = [])
+    {
+        if(!bx_is_api())
+            return;
+
+        //TODO: Implement the functionality here.
+
+        $sClass = get_class($this);
+        return [
+            'display_type' => 'element',
+            'name' => md5($sClass),
+            'title' => get_class($this)
+        ];
+    }
+
+    /**
+     * @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"
+     * @api @ref bx_timeline-repost "repost"
+     */
+    public function serviceRepost($iAuthorId, $iOwnerId, $sType, $sAction, $iObjectId, $bForce = false)
+    {
+        $mixedResult = $this->repost($iAuthorId, $iOwnerId, $sType, $sAction, $iObjectId, false, $bForce);
+        if(bx_is_api() && !is_array($mixedResult))
+            $mixedResult = ['code' => 0, 'id' => $mixedResult];
+
+        return $mixedResult;
+    }
+    
+    /**
+     * @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, [
+            'per_page' => $this->_oConfig->getLiveUpdateLength(),
+            '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);
+
+                if(bx_is_api())
+                    return ['form_object' => $oForm];
+
+            	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']['db']);
+            $oForm->aInputs['text']['value'] = '';
+
+            $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);
+
+                $sSource = $this->getName() . '_' . $iUserId . '_' . $iId;
+                $aContent = array_merge($aContent, [
+                    'timeline_group' => [
+                        'by' => $sSource,
+                        'field' => 'owner_id'
+                    ]
+                ]);
+
+                $this->_oDb->updateEvent(['content' => serialize($aContent), 'source' => $sSource], ['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);
+
+                if(bx_is_api())
+                    return ['form_object' => $oForm, 'id' => $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);
+        }
+
+        if(bx_is_api())
+            return ['form_object' => $oForm];
+
+        $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 bx_is_api() ? bx_api_get_msg($mixedCheck !== false ? $mixedCheck : _t('_sys_txt_access_denied')) : ['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 bx_is_api ? ['form' => $oForm->getCodeAPI()] : $this->_prepareResponse([
+                    'form' => $sCodeAdd . $oForm->getCode($bDynamicMode), 
+                    'form_id' => $oForm->id
+                ], $bAjaxMode);
+            }
+
+            if($oForm->update($iId, $aValsToAdd) === false)
+                 return bx_is_api() ? bx_api_get_msg(_t('_bx_timeline_txt_err_cannot_perform_action')) : ['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 bx_is_api() ? [ 'id' => $iId ] : [ 'id' => $iId ];
+        }
+
+        return bx_is_api() ? ['form' => $oForm->getCodeAPI()] : [
+            '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')
+        ]);
+
+        $sParamsKey = 'type';
+        if(!empty($aParams[$sParamsKey]))
+            $oForm->setType($aParams[$sParamsKey]);
+
+        /**
+         * 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, $iCount) = $mixedComments;
+        $oCmts = $this->getCmtsObject($sSystem, $iObjectId);
+
+        if($oCmts->isViewAllowed() !== CHECK_ACTION_RESULT_ALLOWED || ($iCount == 0 && !$oCmts->isPostAllowed()))
+            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;
+    }
+
+    /**
+     * Checks if it's allowed to view a comment by checking the availability to view the content which was commented. 
+     * Note. Don't check the related comments object for view action accessibility because this method is called from there.
+     */
+    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);
+    }
+
+    /**
+     * Checks if it's allowed to post a comment by checking the availability to post anything in the context. 
+     * Note. Don't check the related comments object for post action accessibility because this method is called from there.
+     */
+    public function checkAllowedCommentsPost ($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');
+
+        /*
+         * Disabled in accordance with #4238 ticket.
+         * 
+        if(($mixedResult = $oOwner->checkAllowedPostInProfile()) !== CHECK_ACTION_RESULT_ALLOWED)
+            return $mixedResult;
+         */
+
+        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'];
+        }
+
+        $this->rebuildSlice();
+
+        //--- 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']);
+
+        $this->rebuildSlice();
+
+        //--- 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.
+        $this->deleteCacheItem($aEvent[$CNF['FIELD_ID']]);
+
+        //--- Rebuild cache table.
+        $this->rebuildSlice();
+
+        //--- 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']);
+        }
+
+        //--- Rebuild cache table.
+        $this->rebuildSlice();
+
+        //--- 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 related flags.
+        $this->_oDb->deleteEventFlags($aEvent[$CNF['FIELD_ID']]);
+
+    	//--- 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.
+        $this->deleteCacheItem($aEvent[$CNF['FIELD_ID']]);
+
+        //--- Rebuild cache table.
+        $this->rebuildSlice();
+
+        //--- 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)
+            return false;
+
+        return [$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 [];
+
+        $oTranscoderSm = BxDolTranscoderImage::getObjectInstance($this->_oConfig->getObject('transcoder_photos_view'));
+        $oTranscoderMd = BxDolTranscoderImage::getObjectInstance($this->_oConfig->getObject('transcoder_photos_medium'));
+        $oTranscoderLg = BxDolTranscoderImage::getObjectInstance($this->_oConfig->getObject('transcoder_photos_big'));
+
+        $aResult = [];
+        foreach($aPhotos as $iPhotoId) {
+            $sPhotoSrcMd = $oTranscoderMd->getFileUrl($iPhotoId);
+            if(empty($sPhotoSrcMd))
+                continue;
+
+            $sPhotoSrcSm = $oTranscoderSm->getFileUrl($iPhotoId);
+            if(empty($sPhotoSrcSm))
+                $sPhotoSrcSm = $sPhotoSrcMd;
+
+            $sPhotoSrcLg = $oTranscoderLg->getFileUrl($iPhotoId);
+            if(empty($sPhotoSrcLg))
+                $sPhotoSrcLg = $sPhotoSrcMd;
+
+            $aResult[] = [
+                'id' => $iPhotoId,
+                'src' => $sPhotoSrcMd,
+                'src_small' => $sPhotoSrcSm,
+                'src_medium' => $sPhotoSrcMd,
+                'src_orig' => $sPhotoSrcLg,
+            ];
+        }
+
+        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;
+    }
+
+    public function hasMedia($iEventId, $iProfileId = 0)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        if(!empty($iEventId))
+            return $this->_oDb->hasMedia($iEventId);
+
+        if(empty($iProfileId))
+            $iProfileId = $this->_iProfileId;
+
+        $aTypes = [
+            $CNF['FIELD_PHOTO'], 
+            $CNF['FIELD_VIDEO'], 
+            $CNF['FIELD_FILE']
+        ];
+
+        $bResult = false;
+        foreach($aTypes as $sType) {
+            $sStorage = $this->_oConfig->getObject('storage_' . strtolower($sType) . 's');
+            if(($oStorage = BxDolStorage::getObjectInstance($sStorage)) !== false) {
+                $aGhosts = $oStorage->getGhosts($iProfileId, 0);
+                if(!empty($aGhosts) && is_array($aGhosts)) {
+                    $bResult = true;
+                    break;
+                }
+            }
+        }
+
+        return $bResult;
+    }
+
+    public function deleteCacheItem($iEventId)
+    {
+        //--- Delete own item cache.
+        $oCacheItem = $this->getCacheItemObject();
+        $aCacheKeys = $this->_oConfig->getCacheItemKeys($iEventId);
+        foreach($aCacheKeys as $sCacheKey)
+            $oCacheItem->delData($sCacheKey);
+
+        //--- Delete item cache for reposts.
+        $aReposts = $this->_oDb->getReposts($iEventId);
+        foreach($aReposts as $aRepost)
+            $this->deleteCacheItem($aRepost['event_id']);
+    }
+
+    public function rebuildSlice()
+    {
+        if(!$this->_oConfig->isCacheTable())
+            return;
+
+        $this->_oDb->rebuildSlice();
+    }
+
+
+    /**
+     * 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 bx_is_api() ? [bx_api_get_block('browse', [
+            'unit' => 'feed',  
+            'request_url' => '/api.php?r=bx_timeline/get_posts/&params[]=',
+            'params' => $aParams,
+            'data' => $this->_oTemplate->getViewBlock($aParams)]),
+        ] : ['content' => $this->_oTemplate->getViewBlock($aParams)];
+    }
+
+    protected function _getBlockPost($iProfileId, $aParams = array())
+    {
+        $this->_iOwnerId = $iProfileId;
+
+        if($this->isAllowedPost() !== true)
+            return [];
+        
+        $mixedResult = $this->_oTemplate->getPostBlock($this->_iOwnerId, $aParams);
+
+        /*if (bx_is_api()){
+            $this->actionPost();
+        }
+        */
+        return bx_is_api() ? $mixedResult : [
+            'content' => $mixedResult
+        ];
+    }
+
+    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);
+        
+        if(bx_is_api())
+            return [bx_api_get_block('browse', [
+                'unit' => 'feed',  
+                'request_url' => '/api.php?r=bx_timeline/get_posts/&params[]=',
+                'params' => $aParams,
+                'data' => $sContent
+            ])];
+
+        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_absolute_url(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['media']))
+            $aParams['media'] = '';
+
+        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', 'media', '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['media'] = $aParams['media'] !== false ? bx_process_input($aParams['media'], 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
+        );
+    }
+}
+
+/** @} */

+ 78 - 0
modules/boonex/timeline/updates/13.0.11_13.0.12/source/classes/BxTimelinePrivacy.php

@@ -0,0 +1,78 @@
+<?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 BxTimelinePrivacy extends BxBaseModNotificationsPrivacy
+{
+    protected $_oModule;
+
+    public function __construct ($aOptions, $oTemplate = false)
+    {
+        parent::__construct ($aOptions, $oTemplate);
+
+        $this->_oModule = BxDolModule::getInstance('bx_timeline');
+    }
+
+    public function addSpaces($aValues, $iOwnerId, $aParams)
+    {
+        if(!$this->_aObject['spaces'])
+            return $aValues;
+
+        if(!empty($aParams['display']) && $aParams['display'] != $this->_oModule->_oConfig->getObject('form_display_post_add'))
+            return $aValues;
+
+        $sConnections = $this->_oModule->_oConfig->getObject('conn_subscriptions');
+        $aConnections = BxDolConnection::getObjectInstance($sConnections)->getConnectedContent($iOwnerId);
+
+        $aCnnGroups = array();
+        foreach($aConnections as $iId) {
+            $oCnnProfile = BxDolProfile::getInstance($iId);
+            if(!$oCnnProfile)
+                continue;
+
+            $sCnnProfileModule = $oCnnProfile->getModule();
+            $sCnnProfileMethod = 'check_allowed_post_in_profile';
+            if(!BxDolRequest::serviceExists($sCnnProfileModule, $sCnnProfileMethod))
+                continue;
+
+            $mixedCheckResult = bx_srv($sCnnProfileModule, $sCnnProfileMethod, array($oCnnProfile->getContentId(), $iOwnerId));
+            if($mixedCheckResult !== CHECK_ACTION_RESULT_ALLOWED)
+                continue;
+
+            $aCnnGroups[$sCnnProfileModule][] = array('key' => -$iId, 'value' => $oCnnProfile->getDisplayName());
+        }
+
+        ksort($aCnnGroups);
+        foreach($aCnnGroups as $sCnnGroup => $aCnnGroup) {
+            $aValues[] = array('type' => 'group_header', 'value' => mb_strtoupper(_t('_bx_timeline_form_post_input_owner_id_following_group', _t('_' . $sCnnGroup))));
+            if(!empty($aCnnGroup) && is_array($aCnnGroup))
+                $aValues = array_merge($aValues, $aCnnGroup);
+            $aValues[] = array('type' => 'group_end');
+        }
+
+        return $aValues;
+    }
+
+    public function getContentByGroupAsSQLPart($mixedGroupId)
+    {
+        $aResult = parent::getContentByGroupAsSQLPart($mixedGroupId);
+
+        if($this->_oModule->_oDb->isTableAlias()) {
+            $sTable = $this->_oModule->_oDb->getTable();
+            $sTableAlias = $this->_oModule->_oDb->getTableAlias();
+            foreach($aResult as $sKey => $sValue)
+                $aResult[$sKey] = str_replace($sTable, $sTableAlias, $sValue);
+        }
+
+        return $aResult;
+    }
+}
+
+/** @} */

+ 383 - 0
modules/boonex/timeline/updates/13.0.11_13.0.12/source/classes/BxTimelineResponse.php

@@ -0,0 +1,383 @@
+<?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)
+    {
+        bx_alert($this->_oModule->getName(), 'before_register_alert', 0, 0, array(
+            'unit' => $oAlert->sUnit,
+            'action' => $oAlert->sAction,
+            'alert' => &$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));
+
+                $sSource = '';
+                if(!empty($oAlert->aExtras['timeline_group']))
+                    $sSource = $oAlert->aExtras['timeline_group']['by'];
+                else
+                    $sSource = $oAlert->sUnit . '_' . $iObjectAuthorId . '_' . $oAlert->iObject;
+
+                $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,
+                    'source' => $sSource,
+                    '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;
+
+                $aContent = [];
+                if(!empty($aEvent['content']) && is_string($aEvent['content']))
+                    $aContent = unserialize($aEvent['content']);
+                if(!empty($oAlert->aExtras) && is_array($oAlert->aExtras))
+                    $aContent = array_merge($aContent, bx_process_input($oAlert->aExtras));
+
+                $aParamsSet = ['content' => serialize($aContent)];
+                $aParamsSetBySource = [];
+
+                foreach(['status', 'status_admin'] as $sStatusKey)
+                    if(!empty($aContent[$sStatusKey])) {
+                        $aParamsSet[$sStatusKey] = $aContent[$sStatusKey];
+                        $aParamsSetBySource[$sStatusKey] = $aContent[$sStatusKey];
+                    }
+
+                if($iObjectPrivacyView > 0)
+                    $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.
+                $this->_oModule->deleteCacheItem($aEvent[$CNF['FIELD_ID']]);              
+
+                //--- Update related events.
+                if(!empty($aParamsSetBySource)) {
+                    $aEventsBySource = $this->_oModule->_oDb->getEvents(['browse' => 'source', 'value' => $aEvent[$CNF['FIELD_SOURCE']]]);
+                    foreach($aEventsBySource as $aEventBySource) {
+                        if($aEventBySource[$CNF['FIELD_ID']] == $aEvent[$CNF['FIELD_ID']])
+                            continue;
+
+                        $this->_oModule->_oDb->updateEvent($aParamsSetBySource, ['id' => $aEventBySource[$CNF['FIELD_ID']]]);
+
+                        //--- Delete item cache.
+                        $this->_oModule->deleteCacheItem($aEventBySource[$CNF['FIELD_ID']]);
+                    }
+                }
+
+                $this->_oModule->rebuildSlice();
+                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
+            ));
+    }
+}
+
+/** @} */

+ 3234 - 0
modules/boonex/timeline/updates/13.0.11_13.0.12/source/classes/BxTimelineTemplate.php

@@ -0,0 +1,3234 @@
+<?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 $_aAclId2Name;
+
+    function __construct(&$oConfig, &$oDb)
+    {
+        parent::__construct($oConfig, $oDb);
+
+        $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':
+                $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(
+            'bAutoAttach' => $this->_oConfig->isEditorAutoAttach(),
+            'bMediaPriority' => $this->_oConfig->isMediaPriority(),
+            '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;
+        $oModule = $this->getModule();
+
+        $aResult = $oModule->getFormPost($aParams);
+
+        if($this->_oConfig->isEditorAutoattach() && !empty($aResult['form_object'])) {
+            $aUploadersInfo = $aResult['form_object']->getUploadersInfo($CNF['FIELD_PHOTO']);
+            if(!empty($aUploadersInfo) && is_array($aUploadersInfo))
+                $aParams = [
+                    'gparams' => ['sAutoUploader' => $aUploadersInfo['name'], 'sAutoUploaderId' => $aUploadersInfo['id']],
+                    'rparams' => $aParams
+                ];
+        }
+
+        if(bx_is_api()) {
+            $aType2Uri = [
+                '' => 'get_block_post_account',
+                'account' => 'get_block_post_account',
+                'feed' => 'get_block_post_account',
+                'owner' => 'get_block_post_profile',
+                'profile' => 'get_block_post_profile',
+                'public' => 'get_block_post_home'
+            ];
+ 
+            $sType = '';
+            if(isset($aParams['rparams']['type']))
+                $sType = $aParams['rparams']['type'];
+            else
+                $sType = trim(str_replace('bx_timeline_post_add', '', $aResult['form_object']->aParams['display']), '_');
+            
+
+            $oProfileOwner = BxDolProfile::getInstance($iOwnerId);
+            $aExt = ['request' => ['url' => $sUrl = '/api.php?r=' . $this->_oModule->getName() . '/' . $aType2Uri[$sType] . '&params[]=' . $oProfileOwner->getModule() . '&params[]=' . $oProfileOwner->getContentId(), 'immutable' => true]];
+            if(!empty($aResult['id'])) {
+                $aItemData = $oModule->getItemData($aResult['id']);
+                if(is_array($aItemData) && !empty($aItemData['event']))
+                    $aExt['response'] = $this->_getPostApi($aItemData['event'], $aParams);
+            }
+            $aExt['name'] = 'feed';
+            return [
+                bx_api_get_block('form', $aResult['form_object']->getCodeAPI(), ['ext' => $aExt])
+            ];
+        }
+
+        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' => $aResult['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']);
+
+        if (bx_is_api())
+            return [
+                'content' => [bx_api_get_block('browse', ['unit' => 'feed', 'data' => $this->getViewBlock($aParams)])],
+                'menu' => $oMenu->getCodeAPI()
+            ];
+
+        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();
+
+        if(bx_is_api()) {
+            if(defined('BX_API_PAGE'))
+                return [];
+
+            $oMenuActions = BxDolMenu::getObjectInstance($this->_oConfig->getObject('menu_item_actions_all'));
+            if(!$oMenuActions)
+                $oMenuActions = BxDolMenu::getObjectInstance($this->_oConfig->getObject('menu_item_actions'));
+
+            $oMenuManage = BxDolMenu::getObjectInstance($this->_oConfig->getObject('menu_item_manage'));
+
+            $aPosts = $this->getPosts(array_merge($aParams, ['return_data_type' => 'array']));
+            foreach($aPosts as &$aPost)
+                $aPost = $this->_getPostApi($aPost, $aParams, [
+                    'menu_actions' => $oMenuActions,
+                    'menu_manage' => $oMenuManage
+                ]);
+
+            return $aPosts;
+        }
+
+        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, [$aParams, $oModule->getUserId(), '{count}', '{init}']);
+
+        $aLiveUpdateParams = [$this->_oConfig->getLiveUpdateKey($aParams), 1, $sService, [true, false]];
+        if($sModuleMethod == 'get_live_update')
+            $aLiveUpdateParams[] = $iEvent;
+
+        $sLiveUpdateCode = null;
+        bx_alert($sModuleName, 'add_live_update', 0, 0, [
+            'browse_params' => $aParams,
+            'live_update_params' => &$aLiveUpdateParams,
+            'override_result' => &$sLiveUpdateCode,
+        ]);
+
+        if($sLiveUpdateCode === null && ($oLiveUpdates = BxDolLiveUpdates::getInstance()) !== false)
+            $sLiveUpdateCode = call_user_func_array([$oLiveUpdates, '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_absolute_url(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 '';
+
+        if(bx_is_api()) {
+            $oMenuManage = BxDolMenu::getObjectInstance($this->_oConfig->getObject('menu_item_manage'));
+            $oMenuManage->setEvent($aEvent);
+
+            return [bx_api_get_block('entity_author', [
+                'author_data' => BxDolProfile::getData($aResult[$CNF['FIELD_OBJECT_OWNER_ID']]),
+                'entry_date' => !empty($aEvent[$CNF['FIELD_ADDED']]) ? $aEvent[$CNF['FIELD_ADDED']] : '',
+                'menu_manage' => $oMenuManage->getCodeApi()
+            ])];
+        }
+
+        $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', [
+            'style_prefix' => $this->_oConfig->getPrefix('style'),
+            'author' => $this->getModule()->getObjectUser($aResult['object_owner_id'])->getUnit(),
+            'fields' => $oForm->getCode()
+        ]);
+    }
+
+    public function getItemBlockComments($iId)
+    {
+        $aEvent = $this->_oDb->getEvents(['browse' => 'id', 'value' => $iId]);
+        if(empty($aEvent))
+            return '';
+
+        $aEventData = $this->getDataCached($aEvent);
+        if($aEventData === false)
+            return '';
+
+        if(!$this->getModule()->isAllowedComment(array_merge($aEvent, $aEventData)))
+            return '';
+
+        if(bx_is_api()) {
+            $mixedComments = $this->getModule()->getCommentsData($aEventData['comments']);
+            if($mixedComments === false)
+                return '';
+
+            list($sSystem, $iObjectId) = $mixedComments;
+            return [bx_srv('system', 'get_data_api', [['module' => $sSystem, 'object_id' => $iObjectId]], 'TemplCmtsServices')];
+        }
+
+        return $this->parseHtmlByName('block_item_comments.html', [
+            'style_prefix' => $this->_oConfig->getPrefix('style'),
+            'content' => $this->_getComments($aEventData['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 Next
+        $aParamsDb['per_page'] += 1;
+        if($this->_oConfig->isCacheTable()) {
+            $aEvents = $this->_oDb->getEvents(array_merge($aParamsDb, ['from_cache' => true]));
+            if(count($aEvents) < $aParamsDb['per_page'])
+                $aEvents = $this->_oDb->getEvents(array_merge($aParamsDb, ['from_cache' => false]));
+        }
+        else
+            $aEvents = $this->_oDb->getEvents($aParamsDb);
+
+        //--- 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);
+
+        //--- 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']);
+
+        $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;
+            }
+
+            $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 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 '';
+
+        if (bx_is_api()){
+            $aParams = ['mode' => 'feed', 'order_way' => 'desc', 'start_from' => 0];
+            return [bx_srv('system', 'get_comments_api', [$oCmts, $aParams], 'TemplCmtsServices')];
+        }
+        
+        $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; 
+            if(typeof(window.BxTimelineRepost) === 'undefined')
+                $.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']));
+
+        //--- Update Flags ---//
+        $aContent = &$aResult['content'];
+        $aFlagTypes = $this->_oDb->getEventFlagTypes();
+        foreach($aFlagTypes as $sFt)
+            if((!empty($aContent[$sFt]) && is_array($aContent[$sFt])) || (!empty($aContent[$sFt . '_attach']) && is_array($aContent[$sFt .'_attach'])))
+                $this->_oDb->updateEventFlagsByType($sFt, $aEvent['id']);
+
+        return $aResult;
+    }
+
+    public function getDataCached($aEvent, $aBrowseParams = array())
+    {
+        if(!$this->_oConfig->isCacheItem() || bx_is_api()) 
+            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,
+            'item_owner_badges' => $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);
+    }
+
+    public function _getPostApi(&$aEvent, $aParams = [], $aEventAdd = [])
+    {
+        $oModule = $this->getModule();
+
+        $aEvent['author_data'] = BxDolProfile::getData($aEvent['object_owner_id']);
+        $aEvent['author_actions'] = [];
+
+        $iInitiatorProfile = (int)bx_get_logged_profile_id();
+        $iContentProfile = (int)$aEvent['object_owner_id'];
+
+        $sConnection = 'sys_profiles_subscriptions';      
+        if(($oConnection = BxDolConnection::getObjectInstance($sConnection)) !== false && $iInitiatorProfile != $iContentProfile && !$oConnection->isConnected($iInitiatorProfile, $iContentProfile)) {
+            $aEvent['author_actions'][] = [
+                'type' => 'connections',
+                'o' => $sConnection,
+                'a' => 'add',
+                'iid' => $iInitiatorProfile,
+                'cid' => $iContentProfile,
+                'title' => _t('_sys_menu_item_title_sm_subscribe'),
+            ];
+        }
+
+        $aEvent['url'] = bx_ltrim_str($aEvent['content']['url'], BX_DOL_URL_ROOT);
+
+        if(empty($aEventAdd['menu_actions'])) {
+            $oMenuActions = BxDolMenu::getObjectInstance($this->_oConfig->getObject('menu_item_actions_all'));
+            if(!$oMenuActions)
+                $oMenuActions = BxDolMenu::getObjectInstance($this->_oConfig->getObject('menu_item_actions'));
+        }
+        else
+            $oMenuActions = $aEventAdd['menu_actions'];
+
+        if($oMenuActions !== false) {
+            $oMenuActions->setEvent($aEvent, $aParams);
+
+            $aEvent['menu_actions'] = $oMenuActions->getCodeAPI();
+        }
+
+        if(empty($aEventAdd['menu_manage']))
+            $oMenuManage = BxDolMenu::getObjectInstance($this->_oConfig->getObject('menu_item_manage'));
+        else
+            $oMenuManage = $aEventAdd['menu_manage'];
+
+        if($oMenuManage !== false) {
+            $oMenuManage->setEvent($aEvent);
+
+            $aEvent['menu_manage'] = $oMenuManage->getCodeAPI();
+        }
+
+        $aCmts = [];
+        $oCmts = $oModule->getCmtsObject($aEvent['comments']['system'], $aEvent['comments']['object_id']);
+        if($oCmts !== false) {
+            $aCmtsParams = ['mode' => 'feed', 'order_way' => 'desc', 'start_from' => 0, 'per_view' => 1];
+            $aCmts = bx_srv('system', 'get_comments_api', [$oCmts, $aCmtsParams], 'TemplCmtsServices');
+
+            $aEvent['cmts'] = $aCmts;
+            $aEvent['cmts']['count'] = $aEvent['comments']['count'];
+        }
+
+        return $aEvent;
+    }
+
+    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 bx-lnk-src',
+                '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 [];
+
+        $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 = [];
+
+        $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;
+
+        $aImageSizes = [
+            'small' => '300w', 
+            'medium' => '500w', 
+            'orig' => '1200w'
+        ];
+        foreach($aImages as $aImage) {
+            $sImageSrcKeyCur = $sImageSrcKey;
+            if(($bAttachFirst && isset($aImage['id']) && (int)$aImage['id'] == $iImageFirst) || $iTotal == 2)
+                $sImageSrcKeyCur = $sImageSrcKeyBig;
+
+            if (is_array($aImage))
+                $sImageSrc = !empty($aImage[$sImageSrcKeyCur]) ? $aImage[$sImageSrcKeyCur] : $aImage[$sImageSrcKeyDefault];
+            if(empty($sImageSrc))
+                continue;
+
+            $sImageAttrSrcset = '';
+            foreach($aImageSizes as $sSize => $sWidth)
+                if(isset($aImage['src_' . $sSize]))
+                    $sImageAttrSrcset .= $aImage['src_' . $sSize] . ' ' . $sWidth . ', ';
+
+            $sImage = $this->parseImage($sImageSrc, array(
+                'class' => $sStylePrefix . '-item-image',
+                'srcset' => trim($sImageAttrSrcset, ", "),
+                'sizes' => '100%'
+            ));
+
+            $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);
+    }
+}
+
+/** @} */

+ 41 - 0
modules/boonex/timeline/updates/13.0.11_13.0.12/source/classes/BxTimelineUploaderHTML5Attach.php

@@ -0,0 +1,41 @@
+<?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 BxTimelineUploaderHTML5Attach extends BxTemplUploaderHTML5
+{
+    protected $_sModule;
+    protected $_oModule;
+
+    public function __construct ($aObject, $sStorageObject, $sUniqId, $oTemplate)
+    {
+        $this->_sModule = 'bx_timeline';
+        $this->_oModule = BxDolModule::getInstance($this->_sModule);
+
+        parent::__construct($aObject, $sStorageObject, $sUniqId, $oTemplate);
+
+        $this->_sButtonTemplate = 'uploader_button_html5_attach.html';
+    }
+
+    public function getUploaderJs($mixedGhostTemplate, $isMultiple = true, $aParams = [], $bDynamic = false)
+    {
+        $sJsObject = $this->_oModule->_oConfig->getJsObject('post');
+
+        $aParams = array_merge($aParams, [
+            'on_upload_before' => 'function(oUploader) {' . $sJsObject . '.onAttachMediaUploadBefore(oUploader);}',
+            'on_upload' => 'function(oUploader, iContentId) {' . $sJsObject . '.onAttachMediaUpload(oUploader, iContentId);}',
+            'on_restore_ghosts' => 'function(oUploader, aData) {' . $sJsObject . '.onAttachMediaRestoreGhosts(oUploader, aData);}',
+        ]);
+
+        return parent::getUploaderJs($mixedGhostTemplate, $isMultiple, $aParams, $bDynamic);
+    }
+}
+
+/** @} */

+ 143 - 0
modules/boonex/timeline/updates/13.0.11_13.0.12/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.12',
+    'vendor' => 'BoonEx',
+    'help_url' => 'http://feed.una.io/?section={module_name}',
+
+    'compatible_with' => array(
+        '13.1.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/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'
+    )
+);
+
+/** @} */

+ 429 - 0
modules/boonex/timeline/updates/13.0.11_13.0.12/source/install/langs/en.xml

@@ -0,0 +1,429 @@
+<?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_live_updates_length"><![CDATA[The length of Live Updates selection]]></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, experimental).]]></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_cache_table"><![CDATA[Enable table cache (experimental)]]></string>
+    <string name="_bx_timeline_option_cache_table_interval"><![CDATA[Interval of time (in days) to get events for cache table]]></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_enable_media_priority"><![CDATA[Enable priority of media content over links in 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_block_title_system_view_feed_and_hot"><![CDATA['For You' Feed (Timeline)]]></string>
+    <string name="_bx_timeline_page_block_title_view_feed_and_hot"><![CDATA[For You]]></string>
+    <string name="_bx_timeline_page_block_title_system_view_contexts_groups"><![CDATA[Followed groups (Timeline)]]></string>
+    <string name="_bx_timeline_page_block_title_view_contexts_groups"><![CDATA[Followed groups]]></string>
+    <string name="_bx_timeline_page_block_title_system_view_media_files"><![CDATA[Files Feed (Timeline)]]></string>
+    <string name="_bx_timeline_page_block_title_view_media_files"><![CDATA[Files]]></string>
+    <string name="_bx_timeline_page_block_title_system_view_media_images"><![CDATA[Photos Feed (Timeline)]]></string>
+    <string name="_bx_timeline_page_block_title_view_media_images"><![CDATA[Photos]]></string>
+    <string name="_bx_timeline_page_block_title_system_view_media_videos"><![CDATA[Videos Feed (Timeline)]]></string>
+    <string name="_bx_timeline_page_block_title_view_media_videos"><![CDATA[Videos]]></string>
+    <string name="_bx_timeline_page_block_title_system_view_media_any"><![CDATA[Any Media Feed (Timeline)]]></string>
+    <string name="_bx_timeline_page_block_title_view_media_any"><![CDATA[Media]]></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_feed_and_hot"><![CDATA[Feed and Hot]]></string>
+    <string name="_bx_timeline_menu_item_title_feed_and_hot"><![CDATA[For You]]></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_item_copy"><![CDATA[Copy to clipboard]]></string>
+    <string name="_bx_timeline_menu_item_title_item_copy"><![CDATA[Copy]]></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_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 media]]></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>

+ 577 - 0
modules/boonex/timeline/updates/13.0.11_13.0.12/source/install/sql/enable.sql

@@ -0,0 +1,577 @@
+
+-- 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),
+
+('', 0, 'bx_timeline', '_bx_timeline_page_block_title_system_view_feed_and_hot', '_bx_timeline_page_block_title_view_feed_and_hot', 0, 0, 2147483644, 'service', 'a:3:{s:6:"module";s:11:"bx_timeline";s:6:"method";s:21:"get_block_view_custom";s:6:"params";a:1:{i:0;a:2:{s:4:"view";s:8:"timeline";s:4:"type";s:12:"feed_and_hot";}}}', 0, 1, 1, @iBlockOrder + 9),
+
+('', 0, 'bx_timeline', '_bx_timeline_page_block_title_system_view_contexts_groups', '_bx_timeline_page_block_title_view_contexts_groups', 0, 0, 2147483644, 'service', 'a:3:{s:6:"module";s:11:"bx_timeline";s:6:"method";s:21:"get_block_view_custom";s:6:"params";a:1:{i:0;a:3:{s:4:"view";s:8:"timeline";s:4:"type";s:18:"connected_contexts";s:7:"context";s:9:"bx_groups";}}}', 0, 1, 1, @iBlockOrder + 10),
+
+('', 0, 'bx_timeline', '_bx_timeline_page_block_title_system_view_media_files', '_bx_timeline_page_block_title_view_media_files', 0, 0, 2147483644, 'service', 'a:3:{s:6:"module";s:11:"bx_timeline";s:6:"method";s:21:"get_block_view_custom";s:6:"params";a:1:{i:0;a:3:{s:4:"view";s:8:"timeline";s:4:"type";s:4:"feed";s:5:"media";s:5:"files";}}}', 0, 1, 1, @iBlockOrder + 11),
+('', 0, 'bx_timeline', '_bx_timeline_page_block_title_system_view_media_images', '_bx_timeline_page_block_title_view_media_images', 0, 0, 2147483644, 'service', 'a:3:{s:6:"module";s:11:"bx_timeline";s:6:"method";s:21:"get_block_view_custom";s:6:"params";a:1:{i:0;a:3:{s:4:"view";s:8:"timeline";s:4:"type";s:4:"feed";s:5:"media";s:6:"images";}}}', 0, 1, 1, @iBlockOrder + 12),
+('', 0, 'bx_timeline', '_bx_timeline_page_block_title_system_view_media_videos', '_bx_timeline_page_block_title_view_media_videos', 0, 0, 2147483644, 'service', 'a:3:{s:6:"module";s:11:"bx_timeline";s:6:"method";s:21:"get_block_view_custom";s:6:"params";a:1:{i:0;a:3:{s:4:"view";s:8:"timeline";s:4:"type";s:4:"feed";s:5:"media";s:6:"videos";}}}', 0, 1, 1, @iBlockOrder + 13),
+('', 0, 'bx_timeline', '_bx_timeline_page_block_title_system_view_media_any', '_bx_timeline_page_block_title_view_media_any', 0, 0, 2147483644, 'service', 'a:3:{s:6:"module";s:11:"bx_timeline";s:6:"method";s:21:"get_block_view_custom";s:6:"params";a:1:{i:0;a:3:{s:4:"view";s:8:"timeline";s:4:"type";s:4:"feed";s:5:"media";a:3:{i:0;s:5:"files";i:1;s:6:"images";i:2;s:6:"videos";}}}}', 0, 1, 1, @iBlockOrder + 14);
+
+
+-- 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),
+('bx_timeline_menu_view', 'bx_timeline', 'feed_and_hot', '_bx_timeline_menu_item_title_system_feed_and_hot', '_bx_timeline_menu_item_title_feed_and_hot', 'javascript:void(0)', 'javascript:{js_object_view}.changeView(this, ''feed_and_hot'')', '_self', '', '', 2147483647, 0, 0, 5);
+
+-- 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-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_live_updates_length', '5', @iCategId, '_bx_timeline_option_live_updates_length', 'digit', '', '', '', '', 15),
+
+('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),
+('bx_timeline_enable_cache_table', '', @iCategId, '_bx_timeline_option_enable_cache_table', 'checkbox', '', '', '', '', 10),
+('bx_timeline_cache_table_interval', '90', @iCategId, '_bx_timeline_option_cache_table_interval', 'digit', '', '', '', '', 11);
+
+-- 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_enable_media_priority', '', @iCategId, '_bx_timeline_option_enable_media_priority', 'checkbox', '', '', '', '', 3),
+('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', '');

+ 722 - 0
modules/boonex/timeline/updates/13.0.11_13.0.12/source/install/sql/install.sql

@@ -0,0 +1,722 @@
+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,
+  `source` varchar(32) NOT NULL default '',
+  `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_events_slice` (
+  `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,
+  `source` varchar(32) NOT NULL default '',
+  `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_ef_photos` (
+  `event_id` int(11) NOT NULL DEFAULT '0',
+  PRIMARY KEY (`event_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_timeline_ef_videos` (
+  `event_id` int(11) NOT NULL DEFAULT '0',
+  PRIMARY KEY (`event_id`)
+);
+
+CREATE TABLE IF NOT EXISTS `bx_timeline_ef_files` (
+  `event_id` int(11) NOT NULL DEFAULT '0',
+  PRIMARY KEY (`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_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_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', '{image}', '', 0, 0, 0, 0, 0, 0),
+('bx_timeline_photos_processed', @sStorageEngine, '', 360, 2592000, 3, 'bx_timeline_photos_processed', 'allow-deny', '{image}', '', 0, 0, 0, 0, 0, 0),
+
+('bx_timeline_videos', @sStorageEngine, '', 360, 2592000, 3, 'bx_timeline_videos', 'allow-deny', '{imagevideo}', '', 0, 0, 0, 0, 0, 0),
+('bx_timeline_videos_processed', @sStorageEngine, '', 360, 2592000, 3, 'bx_timeline_videos_processed', 'allow-deny', '{imagevideo}', '', 0, 0, 0, 0, 0, 0),
+
+('bx_timeline_files', @sStorageEngine, '', 360, 2592000, 3, 'bx_timeline_files', 'deny-allow', '', 'jpg,jpeg,jpe,gif,png,{dangerous}', 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:"1000";s:1:"h";s:4:"1000";}', '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:"1000";s:1:"h";s:4:"1000";}', '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, '', '', '', '', '', '', 'DateTimeTs', '', 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, '', '', '', '', '', '', 'DateTimeTs', '', 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:1:{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:2:{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:1:{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, 1),
+('bx_timeline_post_add', 'action', 2147483647, 1, 2),
+('bx_timeline_post_add', 'owner_id', 2147483647, 1, 3),
+('bx_timeline_post_add', 'text', 2147483647, 1, 4),
+('bx_timeline_post_add', 'attachments', 2147483647, 1, 5),
+('bx_timeline_post_add', 'link', 2147483647, 1, 6),
+('bx_timeline_post_add', 'photo', 2147483647, 1, 7),
+('bx_timeline_post_add', 'video', 2147483647, 1, 8),
+('bx_timeline_post_add', 'file', 2147483647, 1, 9),
+('bx_timeline_post_add', 'object_privacy_view', 2147483647, 1, 10),
+('bx_timeline_post_add', 'object_cf', 2147483647, 1, 11),
+('bx_timeline_post_add', 'published', 192, 0, 12),
+('bx_timeline_post_add', 'location', 2147483647, 1, 13),
+('bx_timeline_post_add', 'tlb_do_submit', 2147483647, 1, 14),
+
+('bx_timeline_post_add_public', 'type', 2147483647, 1, 1),
+('bx_timeline_post_add_public', 'action', 2147483647, 1, 2),
+('bx_timeline_post_add_public', 'owner_id', 2147483647, 1, 3),
+('bx_timeline_post_add_public', 'text', 2147483647, 1, 4),
+('bx_timeline_post_add_public', 'attachments', 2147483647, 1, 5),
+('bx_timeline_post_add_public', 'link', 2147483647, 1, 6),
+('bx_timeline_post_add_public', 'photo', 2147483647, 1, 7),
+('bx_timeline_post_add_public', 'video', 2147483647, 1, 8),
+('bx_timeline_post_add_public', 'file', 2147483647, 1, 9),
+('bx_timeline_post_add_public', 'object_privacy_view', 2147483647, 1, 10),
+('bx_timeline_post_add_public', 'object_cf', 2147483647, 1, 11),
+('bx_timeline_post_add_public', 'published', 192, 0, 12),
+('bx_timeline_post_add_public', 'location', 2147483647, 1, 13),
+('bx_timeline_post_add_public', 'tlb_do_submit', 2147483647, 1, 14),
+
+('bx_timeline_post_add_profile', 'type', 2147483647, 1, 1),
+('bx_timeline_post_add_profile', 'action', 2147483647, 1, 2),
+('bx_timeline_post_add_profile', 'owner_id', 2147483647, 1, 3),
+('bx_timeline_post_add_profile', 'text', 2147483647, 1, 4),
+('bx_timeline_post_add_profile', 'attachments', 2147483647, 1, 5),
+('bx_timeline_post_add_profile', 'link', 2147483647, 1, 6),
+('bx_timeline_post_add_profile', 'photo', 2147483647, 1, 7),
+('bx_timeline_post_add_profile', 'video', 2147483647, 1, 8),
+('bx_timeline_post_add_profile', 'file', 2147483647, 1, 9),
+('bx_timeline_post_add_profile', 'object_privacy_view', 2147483647, 1, 10),
+('bx_timeline_post_add_profile', 'object_cf', 2147483647, 1, 11),
+('bx_timeline_post_add_profile', 'published', 192, 0, 12),
+('bx_timeline_post_add_profile', 'location', 2147483647, 1, 13),
+('bx_timeline_post_add_profile', 'tlb_do_submit', 2147483647, 1, 14),
+
+('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', 'link', 2147483647, 1, 6),
+('bx_timeline_post_edit', 'photo', 2147483647, 1, 7),
+('bx_timeline_post_edit', 'video', 2147483647, 1, 8),
+('bx_timeline_post_edit', 'file', 2147483647, 1, 9),
+('bx_timeline_post_edit', 'object_privacy_view', 2147483647, 1, 10),
+('bx_timeline_post_edit', 'object_cf', 2147483647, 1, 11),
+('bx_timeline_post_edit', 'published', 192, 0, 12),
+('bx_timeline_post_edit', 'location', 2147483647, 1, 13),
+('bx_timeline_post_edit', 'controls', 2147483647, 1, 14),
+('bx_timeline_post_edit', 'tlb_do_submit', 2147483647, 1, 15),
+('bx_timeline_post_edit', 'tlb_do_cancel', 2147483647, 1, 16);
+
+-- 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`, `module`, `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', 'bx_timeline_views_track', '86400', '1', 'bx_timeline_events', 'id', 'object_id', 'views', '', '');
+
+
+-- VOTES
+INSERT INTO `sys_objects_vote`(`Name`, `Module`, `TableMain`, `TableTrack`, `PostTimeout`, `MinValue`, `MaxValue`, `IsUndo`, `IsOn`, `TriggerTable`, `TriggerFieldId`, `TriggerFieldAuthor`, `TriggerFieldRate`, `TriggerFieldRateCount`, `ClassName`, `ClassFile`) VALUES 
+('bx_timeline', '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', '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));

+ 79 - 0
modules/boonex/timeline/updates/13.0.11_13.0.12/source/install/sql/uninstall.sql

@@ -0,0 +1,79 @@
+SET @sName = 'bx_timeline';
+
+DROP TABLE IF EXISTS `bx_timeline_events`, `bx_timeline_events_slice`, `bx_timeline_events2users`, `bx_timeline_handlers`;
+
+DROP TABLE IF EXISTS `bx_timeline_ef_photos`, `bx_timeline_ef_videos`, `bx_timeline_ef_files`;
+
+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;

+ 403 - 0
modules/boonex/timeline/updates/13.0.11_13.0.12/source/js/post.js

@@ -0,0 +1,403 @@
+/**
+ * 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._bAutoAttach = oOptions.bAutoAttach == undefined ? false : oOptions.bAutoAttach;
+    this._sAutoUploader = oOptions.sAutoUploader == undefined ? '' : oOptions.sAutoUploader;
+    this._sAutoUploaderId = oOptions.sAutoUploaderId == undefined ? '' : oOptions.sAutoUploaderId;
+    this._bMediaPriority = oOptions.bMediaPriority == undefined ? false : oOptions.bMediaPriority;
+    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 = [];
+
+    $(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);
+
+            $this.initTrackerInsertSpace(sId);
+            if($this._bAutoAttach) 
+                $this.initTrackerInsertImage(sId);
+    	});
+    });
+}
+
+BxTimelinePost.prototype = new BxTimelineMain();
+
+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);
+        }
+    });
+};
+
+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;
+
+                        if(oData.url != undefined && oData.url.length != 0)
+                            delete $this._oAttachedLinks[oData.url];
+                    });
+                }
+            };
+
+            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($(oLink).hasClass('bx-btn-disabled'))
+        return false;
+
+    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.onAttachMediaUploadBefore = function(oUploader)
+{
+    $('#' + oUploader._sResultContainerId).parents('form:first').find(":submit").prop('disabled', true).addClass('bx-btn-disabled');
+};
+
+BxTimelinePost.prototype.onAttachMediaUpload = function(oUploader, iEventId)
+{
+    var $this = this;
+    var oData = this._getDefaultData();
+    oData['event_id'] = iEventId;
+
+    if(this._bMediaPriority) {
+        var oLinkFormField = $('#' + this._aHtmlIds['attach_link_form_field'] + iEventId);
+
+        oLinkFormField.parents('form:first').find('.bx-menu-item.add-link .bx-btn').addClass('bx-btn-disabled');
+
+        if(oLinkFormField.children().length > 0) {
+            oLinkFormField.hide();
+
+            jQuery.post (
+                this._sActionsUrl + 'delete_attach_links/',
+                oData,
+                function(oData) {
+                    if(!oData)
+                        return;
+
+                    var fContinue = function() {
+                        if(oData.code == undefined)
+                            return;
+
+                        if(oData.code == 0) {
+                            oLinkFormField.html('');
+
+                            if(oData.urls != undefined && oData.urls.length != 0)
+                                for(var i in oData.urls)
+                                    delete $this._oAttachedLinks[oData.urls[i]];
+                        }
+
+                        oLinkFormField.show();
+                    };
+
+                    if(oData.message != undefined)
+                        bx_alert(oData.message, fContinue);
+                    else
+                        fContinue();
+                },
+                'json'
+            );
+        }
+    }
+
+    $('#' + oUploader._sResultContainerId).parents('form:first').find(":submit").prop('disabled', false).removeClass('bx-btn-disabled');
+};
+
+BxTimelinePost.prototype.onAttachMediaRestoreGhosts = function(oUploader, aData)
+{
+    //perform some action after attached media's ghosts restoration.
+};
+
+BxTimelinePost.prototype.onAttachMediaDeleteGhost = function(iEventId, sMsg)
+{
+    if(sMsg != 'ok') 
+        return;
+
+    var oForm = $('#' + this._aHtmlIds['attach_link_form_field'] + iEventId).parents('form:first');
+    if(!oForm.find('.bx-tl-uploader-file').length)
+        oForm.find('.bx-menu-item.add-link .bx-btn').removeClass('bx-btn-disabled');
+};
+
+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.options != undefined)
+                $this.updateOptions(oData.options);
+
+            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);
+};

+ 1005 - 0
modules/boonex/timeline/updates/13.0.11_13.0.12/source/template/css/view.css

@@ -0,0 +1,1005 @@
+/*--- 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.0rem;
+}
+
+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 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 {
+    -webkit-flex-wrap: wrap;
+    flex-wrap: wrap;
+}
+.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-content-overflow {
+    display: none;
+}
+div.bx-tl-item-text div.bx-tl-content.bx-tl-overflow .bx-tl-content-overflow {
+    display: block;
+}
+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-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.11_13.0.12/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 flex-shrink-0">__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 flex items-center min-w-0" title="__item_owner_title__"><div class="truncate">__item_owner_name__</div>__item_owner_badges__</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>

+ 56 - 0
modules/boonex/timeline/updates/13.0.11_13.0.12/source/template/item_search.html

@@ -0,0 +1,56 @@
+<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>
+                <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 flex items-center min-w-0" title="__item_owner_title__"><div class="truncate">__item_owner_name__</div>__item_owner_badges__</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.11_13.0.12/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-lnk-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 flex-shrink-0">__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 flex items-center min-w-0" title="__item_owner_title__"><div class="truncate">__item_owner_name__</div>__item_owner_badges__</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>

+ 59 - 0
modules/boonex/timeline/updates/13.0.11_13.0.12/source/template/type_post.html

@@ -0,0 +1,59 @@
+<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-4 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-2 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__ mt-3 md:mt-4 rounded">
+        <bx_repeat:items>
+            <div class="__style_prefix__-item-file flex-shrink-0 px-4 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-2 md:mb-4 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 bx-def-vh-sm relative max-w-none">
+            __item_content__
+            <div class="__style_prefix__-content-overflow bx-def-color-bg-box-overflow absolute bottom-0 w-full h-1/5"></div>
+        </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>

+ 13 - 0
modules/boonex/timeline/updates/13.0.11_13.0.12/source/template/uploader_nfw.html

@@ -0,0 +1,13 @@
+<div id="bx-uploader-file-{storage_object}-{file_id}" class="bx-tl-uploader-file bx-def-margin-sec-top bx-def-margin-sec-left-auto">
+    <div class="bx-uploader-ghost-cnt">
+        <div class="bx-tl-uploader-file-preview bx-def-round-corners">
+            <input type="hidden" name="__name__[]" value="{file_id}" />
+            <img src="<bx_image_url:spacer.gif />" style="background-image:url({file_icon})" />
+        </div>
+        <span class="bx-base-general-uploader-ghost">
+            <a class="bx-btn bx-btn-small" href="javascript:void(0);" title="<bx_text:_Delete />" onclick="{js_instance_name}.deleteGhost('{file_id}', function(sMsg){__js_object__.onAttachMediaDeleteGhost(__content_id__, sMsg);})">
+                <bx_image_auto:times />
+            </a>
+        </span>
+    </div>
+</div>

+ 51 - 0
modules/boonex/videos/updates/13.0.5_13.0.6/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' => 'Videos',
+    'version_from' => '13.0.5',
+    'version_to' => '13.0.6',
+    'vendor' => 'BoonEx',
+
+    'compatible_with' => array(
+        '13.1.0-B1'
+    ),
+
+    /**
+     * 'home_dir' and 'home_uri' - should be unique. Don't use spaces in 'home_uri' and the other special chars.
+     */
+    'home_dir' => 'boonex/videos/updates/update_13.0.5_13.0.6/',
+    'home_uri' => 'videos_update_1305_1306',
+
+    'module_dir' => 'boonex/videos/',
+    'module_uri' => 'videos',
+
+    'db_prefix' => 'bx_videos_',
+    'class_prefix' => 'BxVideos',
+
+    /**
+     * Installation/Uninstallation Section.
+     */
+    'install' => array(
+        'execute_sql' => 1,
+        'update_files' => 1,
+        'update_languages' => 0,
+        'clear_db_cache' => 1,
+    ),
+
+    /**
+     * Category for language keys.
+     */
+    'language_category' => 'Videos',
+
+    /**
+     * Files Section
+     */
+    'delete_files' => array(),
+);

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