AntonLV 7 سال پیش
والد
کامیت
90ea8d58d6

+ 14 - 11
modules/boonex/russian/data/langs/bx_timeline/ru.xml

@@ -1,19 +1,19 @@
 <?xml version="1.0" encoding="utf-8"?>
 <resources name="ru" flag="ru" title="Russian">
 
-	<string name="_bx_timeline"><![CDATA[Лента]]></string>
-	<string name="_bx_timeline_cmts"><![CDATA[Лента - Комментарии]]></string>
+    <string name="_bx_timeline"><![CDATA[Лента]]></string>
+    <string name="_bx_timeline_cmts"><![CDATA[Лента - Комментарии]]></string>
 
     <string name="_bx_timeline_option_enable_edit"><![CDATA[Разрешить пользователю изменять собственные сообщения]]></string>
-	<string name="_bx_timeline_option_enable_delete"><![CDATA[Разрешить владельцу ленты удалять сообщения]]></string>
-	<string name="_bx_timeline_option_enable_show_all"><![CDATA[Показывать все сообщения в 'Общей хронике', включая те, что были написаны в персональных Хрониках]]></string>
-        <string name="_bx_timeline_option_enable_count_all_views"><![CDATA[Считать просмотры для всех событий в хронике]]></string>
-	<string name="_bx_timeline_option_events_per_page_profile"><![CDATA[Количество элементов на странице профайла]]></string>
-	<string name="_bx_timeline_option_events_per_page_account"><![CDATA[Количество элементов на странице "панель аккаунта"]]></string>
-	<string name="_bx_timeline_option_events_per_page_home"><![CDATA[Количество элементов на главной странице сайта]]></string>
-	<string name="_bx_timeline_option_events_per_page"><![CDATA[Количество элементов на странице]]></string>
-	<string name="_bx_timeline_option_rss_length"><![CDATA[Количество элементов в RSS-ленте]]></string>
-	<string name="_bx_timeline_option_events_hide"><![CDATA[Показывать события]]></string>
+    <string name="_bx_timeline_option_enable_delete"><![CDATA[Разрешить владельцу ленты удалять сообщения]]></string>
+    <string name="_bx_timeline_option_enable_show_all"><![CDATA[Показывать все сообщения в 'Общей хронике', включая те, что были написаны в персональных Хрониках]]></string>
+    <string name="_bx_timeline_option_enable_count_all_views"><![CDATA[Считать просмотры для всех событий в хронике]]></string>
+    <string name="_bx_timeline_option_events_per_page_profile"><![CDATA[Количество элементов на странице профайла]]></string>
+    <string name="_bx_timeline_option_events_per_page_account"><![CDATA[Количество элементов на странице "панель аккаунта"]]></string>
+    <string name="_bx_timeline_option_events_per_page_home"><![CDATA[Количество элементов на главной странице сайта]]></string>
+    <string name="_bx_timeline_option_events_per_page"><![CDATA[Количество элементов на странице]]></string>
+    <string name="_bx_timeline_option_rss_length"><![CDATA[Количество элементов в RSS-ленте]]></string>
+    <string name="_bx_timeline_option_events_hide"><![CDATA[Показывать события]]></string>
     <string name="_bx_timeline_option_videos_autoplay"><![CDATA[Автоматически проигрывать видео ролики (доступно только для Ленты)]]></string>
     <string name="_bx_timeline_option_videos_autoplay_off"><![CDATA[Отключено]]></string>
     <string name="_bx_timeline_option_videos_autoplay_on_mute"><![CDATA[Включено (без звука)]]></string>
@@ -21,6 +21,9 @@
     <string name="_bx_timeline_option_preload_comments"><![CDATA[Количество предварительно загруженных комментариев (до 7 штук)]]></string>
     <string name="_bx_timeline_option_enable_hot"><![CDATA[Включить сбор данных для листа 'горячих' сообщений]]></string>
     <string name="_bx_timeline_option_hot_interval"><![CDATA[Интервал времени (в часах) для получения 'горячих' сообщений]]></string>
+    <string name="_bx_timeline_option_enable_cache_item"><![CDATA[Включить кэш элемента]]></string>
+    <string name="_bx_timeline_option_cache_item_lifetime"><![CDATA[Время жизни кэша элемента]]></string>
+    <string name="_bx_timeline_option_enable_cache_list"><![CDATA[Включить кэш хроники]]></string>
     <string name="_bx_timeline_option_enable_editor_toolbar"><![CDATA[Включить панель инструментов в форме создания сообщения]]></string>
 
 	<string name="_bx_timeline_form_post"><![CDATA[Сообщение]]></string>

+ 30 - 1
modules/boonex/timeline/classes/BxTimelineConfig.php

@@ -20,6 +20,10 @@ class BxTimelineConfig extends BxBaseModNotificationsConfig
     protected $_bShowAll;
     protected $_bCountAllViews;
 
+    protected $_bCacheItem;
+    protected $_iCacheItemLifetime;
+    protected $_bCacheList;
+
     protected $_iRssLength;
     protected $_iLiveUpdateLength;
     protected $_iCharsDisplayMaxTitle;
@@ -116,7 +120,8 @@ class BxTimelineConfig extends BxBaseModNotificationsConfig
             'style' => 'bx-tl',
             'language' => '_bx_timeline',
             'option' => 'bx_timeline_',
-            'common_post' => 'timeline_common_'
+            'common_post' => 'timeline_common_',
+            'cache_item' => 'bx_timeline_item_'
         );
 
         $this->_aObjects = array_merge($this->_aObjects, array(
@@ -249,6 +254,10 @@ class BxTimelineConfig extends BxBaseModNotificationsConfig
         $this->_bShowAll = getParam($sOptionPrefix . 'enable_show_all') == 'on';
         $this->_bCountAllViews = getParam($sOptionPrefix . 'enable_count_all_views') == 'on';
 
+        $this->_bCacheItem = getParam($sOptionPrefix . 'enable_cache_item') == 'on';
+        $this->_iCacheItemLifetime = (int)getParam($sOptionPrefix . 'cache_item_lifetime');
+        $this->_bCacheList = getParam($sOptionPrefix . 'enable_cache_list') == 'on';
+
         $this->_aPerPage = array(
             'default' => (int)getParam($sOptionPrefix . 'events_per_page'),
             'profile' => (int)getParam($sOptionPrefix . 'events_per_page_profile'),
@@ -347,6 +356,26 @@ class BxTimelineConfig extends BxBaseModNotificationsConfig
         return $this->_bUnhideRestored;
     }
 
+    public function isCacheItem()
+    {
+        return $this->_bCacheItem;
+    }
+
+    public function isCacheList()
+    {
+        return $this->_bCacheList;
+    }
+
+    public function getCacheItemLifetime()
+    {
+        return $this->_iCacheItemLifetime;
+    }
+
+    public function getCacheItemKey($iId, $sPostfix = '')
+    {
+        return $this->_aPrefixes['cache_item'] . $iId . (!empty($sPostfix) ? '_' . $sPostfix : '') . '.php';
+    }
+
     public function getPostFormDisplay($sType)
     {
         if(empty($sType) || !array_key_exists($sType, $this->_aTypeToFormDisplay))

+ 93 - 23
modules/boonex/timeline/classes/BxTimelineDb.php

@@ -11,6 +11,8 @@
 
 class BxTimelineDb extends BxBaseModNotificationsDb
 {
+    protected $_sTableCache;
+
     protected $_sTableEvent2User;
     protected $_sTablesRepostTrack;
     protected $_sTableHotTrack;
@@ -24,6 +26,8 @@ class BxTimelineDb extends BxBaseModNotificationsDb
     function __construct(&$oConfig)
     {
         parent::__construct($oConfig);
+        $this->_sTableCache = $this->_sPrefix . 'cache';
+
         $this->_sTableEvent2User = $this->_sPrefix . 'events2users';
         $this->_sTableRepostsTrack = $this->_sPrefix . 'reposts_track';
         $this->_sTableHotTrack = $this->_sPrefix . 'hot_track';
@@ -54,7 +58,7 @@ class BxTimelineDb extends BxBaseModNotificationsDb
     	}
     }
 
-	public function activateModuleEvents($aData, $bActivate = true)
+    public function activateModuleEvents($aData, $bActivate = true)
     {
     	$iActivate = $bActivate ? 1 : 0;
 
@@ -387,6 +391,68 @@ class BxTimelineDb extends BxBaseModNotificationsDb
         return (int)$this->query("REPLACE INTO `" . $this->_sTableHotTrack . "` SET " . $this->arrayToSQL($aTrack)) > 0;
     }
 
+    public function insertCache($aParamsSet)
+    {
+        if(empty($aParamsSet))
+            return false;
+
+        return (int)$this->query("REPLACE INTO `{$this->_sTableCache}` SET " . $this->arrayToSQL($aParamsSet)) > 0;
+    }
+
+    public function deleteCache($aParamsWhere)
+    {
+        if(empty($aParamsWhere))
+            return false;
+
+        return (int)$this->query("DELETE FROM `{$this->_sTableCache}` WHERE " . $this->arrayToSQL($aParamsWhere, ' AND ')) > 0;
+    }
+
+    public function getCache($aParams)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+    	$aMethod = array('name' => 'getAll', 'params' => array(0 => 'query'));
+        
+        $sFieldsClause = '*';
+        $sWhereClause = $sLimitClause = '';
+
+        if(isset($aParams['start']) && !empty($aParams['per_page']))
+            $sLimitClause = $aParams['start'] . ", " . $aParams['per_page'];
+
+        switch($aParams['browse']) {
+            case 'list': // by type + owner profile (context) + viewer profile
+                $aMethod['name'] = 'getAllWithKey';
+                $aMethod['params'][1] = 'event_id';
+                $aMethod['params'][2] = array(
+                    'type' => $aParams['type'],
+                    'context_id' => $aParams['context_id'],
+                    'profile_id' => $aParams['profile_id']
+                );
+
+                //--- Apply custom check depending on Type
+                switch($aParams['type']) {
+                    case BX_BASE_MOD_NTFS_TYPE_PUBLIC:
+                        $aMethod['params'][2]['context_id'] = 0;
+                        break;
+
+                    case BX_TIMELINE_TYPE_OWNER_AND_CONNECTIONS:
+                        $aMethod['params'][2]['context_id'] = $aParams['profile_id'];
+                        break;
+                }
+
+                $sWhereClause .= " AND `type`=:type AND `context_id`=:context_id  AND `profile_id`=:profile_id";
+                break;
+        }
+
+        $sLimitClause = $sLimitClause ? "LIMIT " . $sLimitClause : "";
+
+        $aMethod['params'][0] = "SELECT " . $sFieldsClause . " 
+        FROM `{$this->_sTableCache}` 
+        WHERE 1" . $sWhereClause . " ORDER BY `date` DESC " . $sLimitClause;
+
+        return call_user_func_array(array($this, $aMethod['name']), $aMethod['params']);
+    }
+
     protected function _getFilterAddon($iOwnerId, $sFilter)
     {
         switch($sFilter) {
@@ -426,14 +492,14 @@ class BxTimelineDb extends BxBaseModNotificationsDb
         $sJoinClause = $sWhereClause = $sOrderClause = $sLimitClause = "";
 
         switch($aParams['browse']) {
-        	case 'owner_id':
-        		$sWhereClause = $this->prepareAsString("AND `{$this->_sTable}`.`owner_id`=? ", $aParams['value']);
-        		break;
+            case 'owner_id':
+                $sWhereClause = $this->prepareAsString("AND `{$this->_sTable}`.`owner_id`=? ", $aParams['value']);
+                break;
 
-        	case 'common_by_object':
-        		$sCommonPostPrefix = $this->_oConfig->getPrefix('common_post');
-        		$sWhereClause = $this->prepareAsString("AND SUBSTRING(`{$this->_sTable}`.`type`, 1, " . strlen($sCommonPostPrefix) . ")='" . $sCommonPostPrefix . "' AND `{$this->_sTable}`.`object_id`=? ", $aParams['value']);
-        		break;
+            case 'common_by_object':
+                $sCommonPostPrefix = $this->_oConfig->getPrefix('common_post');
+                $sWhereClause = $this->prepareAsString("AND SUBSTRING(`{$this->_sTable}`.`type`, 1, " . strlen($sCommonPostPrefix) . ")='" . $sCommonPostPrefix . "' AND `{$this->_sTable}`.`object_id`=? ", $aParams['value']);
+                break;
 
             case 'descriptor':
                 $sMethod = 'getRow';
@@ -465,32 +531,36 @@ class BxTimelineDb extends BxBaseModNotificationsDb
                     $sSelectClause  = "DISTINCT " . $sSelectClause;
                 break;
 
+            case 'ids':
+                $sWhereClause = "AND `{$this->_sTable}`.`id` IN (" . $this->implode_escape($aParams['ids']) . ") ";
+                break;
+
             default:
             	list($sMethod, $sSelectClause, $sJoinClause, $sWhereClause, $sOrderClause, $sLimitClause) = parent::_getSqlPartsEvents($aParams);
         }
 
-		$sSelectClause .= ", DAYOFYEAR(FROM_UNIXTIME(`{$this->_sTable}`.`date`)) AS `days`, DAYOFYEAR(NOW()) AS `today`, ROUND((UNIX_TIMESTAMP() - `{$this->_sTable}`.`date`)/86400) AS `ago_days`, YEAR(FROM_UNIXTIME(`{$this->_sTable}`.`date`)) AS `year`";
-		if($aParams['browse'] == 'list') {
-			$sOrderClause = "";
+        $sSelectClause .= ", DAYOFYEAR(FROM_UNIXTIME(`{$this->_sTable}`.`date`)) AS `days`, DAYOFYEAR(NOW()) AS `today`, ROUND((UNIX_TIMESTAMP() - `{$this->_sTable}`.`date`)/86400) AS `ago_days`, YEAR(FROM_UNIXTIME(`{$this->_sTable}`.`date`)) AS `year`";
+        if(in_array($aParams['browse'], array('list', 'ids'))) {
+            $sOrderClause = "";
 
-			switch($aParams['type']) {
-				case BX_TIMELINE_TYPE_HOT:
+            switch($aParams['type']) {
+                case BX_TIMELINE_TYPE_HOT:
                     $sOrderClause = "`{$this->_sTableHotTrack}`.`value` DESC, ";
                     break;
 
-				case BX_BASE_MOD_NTFS_TYPE_PUBLIC:
-				case BX_BASE_MOD_NTFS_TYPE_CONNECTIONS:
-				case BX_TIMELINE_TYPE_OWNER_AND_CONNECTIONS:
-					$sOrderClause = "`{$this->_sTable}`.`sticked` DESC, ";
-					break;
+                    case BX_BASE_MOD_NTFS_TYPE_PUBLIC:
+                    case BX_BASE_MOD_NTFS_TYPE_CONNECTIONS:
+                    case BX_TIMELINE_TYPE_OWNER_AND_CONNECTIONS:
+                        $sOrderClause = "`{$this->_sTable}`.`sticked` DESC, ";
+                        break;
 
-				case BX_BASE_MOD_NTFS_TYPE_OWNER:
-					$sOrderClause = "`{$this->_sTable}`.`pinned` DESC, ";
-					break;
-			}
+                    case BX_BASE_MOD_NTFS_TYPE_OWNER:
+                        $sOrderClause = "`{$this->_sTable}`.`pinned` DESC, ";
+                        break;
+            }
 
             $sOrderClause = "ORDER BY " . $sOrderClause . "`{$this->_sTable}`.`date` DESC";
-		}
+        }
 
         if(isset($aParams['count']) && $aParams['count'] === true) {
             $sMethod = 'getOne';

+ 34 - 17
modules/boonex/timeline/classes/BxTimelineResponse.php

@@ -25,6 +25,8 @@ class BxTimelineResponse extends BxBaseModNotificationsResponse
      */
     public function response($oAlert)
     {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
         $iObjectAuthorId = $this->_getObjectOwnerId($oAlert->aExtras);
     	$iObjectPrivacyView = $this->_getObjectPrivacyView($oAlert->aExtras);
         if($iObjectPrivacyView == BX_DOL_PG_HIDDEN)
@@ -58,8 +60,12 @@ class BxTimelineResponse extends BxBaseModNotificationsResponse
                 break;
 
             case BX_BASE_MOD_NTFS_HANDLER_TYPE_UPDATE:
+                $aEvent = $this->_oModule->_oDb->getEvents(array('browse' => 'descriptor', 'type' => $oAlert->sUnit, 'object_id' => $oAlert->iObject));
+                if(empty($aEvent) || !is_array($aEvent))
+                    break;
+
                 $aParamsSet = array(
-                	'content' => !empty($oAlert->aExtras) && is_array($oAlert->aExtras) ? serialize(bx_process_input($oAlert->aExtras)) : ''
+                    'content' => !empty($oAlert->aExtras) && is_array($oAlert->aExtras) ? serialize(bx_process_input($oAlert->aExtras)) : ''
                 );
 
                 if($iObjectPrivacyView > 0 && !empty($iObjectAuthorId) && $iObjectAuthorId == $oAlert->iSender)
@@ -74,31 +80,42 @@ class BxTimelineResponse extends BxBaseModNotificationsResponse
                     ));
 
                 $this->_oModule->_oDb->updateEvent($aParamsSet, array('type' => $oAlert->sUnit, 'object_id' => $oAlert->iObject));
+
+                //--- Delete cached
+                $this->_oModule->_oDb->deleteCache(array('owner_id' => 0)); //--- Delete cache for Public feed
+                $this->_oModule->_oDb->deleteCache(array('owner_id' => $aEvent[$CNF['FIELD_OWNER_ID']])); //--- Delete cache for old context
+                $this->_oModule->_oDb->deleteCache(array('owner_id' => $aParamsSet['owner_id'])); //--- Delete cache for new context
                 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']) {
-						$aEvents = $this->_oModule->_oDb->getEvents(array('browse' => 'common_by_object', 'value' => $oAlert->iObject));
-						foreach($aEvents as $aEvent)
-	            			$this->_oModule->deleteEvent($aEvent);
-            		}
-            		break;
-            	}
+                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']) {
+                        $aEvents = $this->_oModule->_oDb->getEvents(array('browse' => 'common_by_object', 'value' => $oAlert->iObject));
+                        foreach($aEvents as $aEvent)
+                            $this->_oModule->deleteEvent($aEvent);
+                    }
+
+                    //--- Delete cached
+                    $this->_oModule->_oDb->deleteCache(array('owner_id' => $oAlert->iObject));
+                    $this->_oModule->_oDb->deleteCache(array('profile_id' => $oAlert->iObject));
+                    break;
+                }
 
             	$aHandlers = $this->_oModule->_oDb->getHandlers(array('type' => 'by_group_key_type', 'group' => $aHandler['group']));
 
             	$aEvent = $this->_oModule->_oDb->getEvents(array(
-            		'browse' => 'descriptor', 
-            		'type' => $oAlert->sUnit,
-            		'action' => $aHandlers[BX_BASE_MOD_NTFS_HANDLER_TYPE_INSERT]['alert_action'], 
-            		'object_id' => $oAlert->iObject
+                    'browse' => 'descriptor', 
+                    'type' => $oAlert->sUnit,
+                    'action' => $aHandlers[BX_BASE_MOD_NTFS_HANDLER_TYPE_INSERT]['alert_action'], 
+                    'object_id' => $oAlert->iObject
             	));
             	$this->_oModule->deleteEvent($aEvent);
+
+                $this->_oModule->_oDb->deleteCache(array('event_id' => $aEvent[$CNF['FIELD_ID']]));
                 break;
         }
     }

+ 135 - 8
modules/boonex/timeline/classes/BxTimelineTemplate.php

@@ -264,7 +264,7 @@ class BxTimelineTemplate extends BxBaseModNotificationsTemplate
     }
 
     public function getItemBlockComments($iId) {
-        $CNF = $this->_oConfig->CNF;
+        $CNF = &$this->_oConfig->CNF;
 
         $aEvent = $this->_oDb->getEvents(array('browse' => 'id', 'value' => $iId));
         if(empty($aEvent))
@@ -289,14 +289,46 @@ class BxTimelineTemplate extends BxBaseModNotificationsTemplate
 
     public function getPost(&$aEvent, $aBrowseParams = array())
     {
+        $CNF = &$this->_oConfig->CNF;
+
         $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($aEvent['id']))
+            if(!$oPrivacy->check($aEvent[$CNF['FIELD_ID']])) {
+                if($this->_oConfig->isCacheList())
+                    $this->_oDb->deleteCache(array(
+                        'type' => $aBrowseParams['type'], 
+                        'profile_id' => bx_get_logged_profile_id(),
+                        'event_id' => $aEvent[$CNF['FIELD_ID']]
+                    ));
+
                 return '';
+            }
         }
 
-        $aResult = $this->getData($aEvent, $aBrowseParams);
+        $aResult = false;
+        if($this->_oConfig->isCacheItem()) {
+            $oCache = $this->getTemplatesCacheObject();
+
+            /**
+             * 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();
+
+            $aResult = $oCache->getData($sCacheKey, $iCacheLifetime);
+            if(empty($aResult)) {
+                $aResult = $this->getData($aEvent, $aBrowseParams);
+
+                $oCache->setData($sCacheKey, serialize($aResult), $iCacheLifetime);
+            }
+            else
+                $aResult = unserialize($aResult);
+        }
+        else
+            $aResult = $this->getData($aEvent, $aBrowseParams);
+
         if($aResult === false)
             return '';
 
@@ -330,7 +362,7 @@ class BxTimelineTemplate extends BxBaseModNotificationsTemplate
 
         $aParamsDb = $aParams;
 
-        //--- Check for Previous
+        //--- Before: Check for Previous
         $iDays = -1;
         $bPrevious = false;
         if($iStart - 1 >= 0) {
@@ -339,17 +371,18 @@ class BxTimelineTemplate extends BxBaseModNotificationsTemplate
             $bPrevious = true;
         }
 
-        //--- Check for Next
+        //--- Before: Check for Next
         $aParamsDb['per_page'] += 1;
-        $aEvents = $this->_oDb->getEvents($aParamsDb);
 
-        //--- Check for Previous
+        $aEvents = $this->_getPosts($aParamsDb);
+
+        //--- After: Check for Previous
         if($bPrevious) {
             $aEvent = array_shift($aEvents);
             $iDays = (int)$aEvent['days'];
         }
 
-        //--- Check for Next
+        //--- After: Check for Next
         $bNext = false;
         if(count($aEvents) > $iPerPage) {
             $aEvent = array_pop($aEvents);
@@ -996,6 +1029,100 @@ class BxTimelineTemplate extends BxBaseModNotificationsTemplate
         ));
     }
 
+    protected function _cacheEvent($iProfileId, &$aParams, &$aEvent)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $aParamsSet = array(
+            'type' => $aParams['type'],
+            'context_id' => $aEvent[$CNF['FIELD_OWNER_ID']], 
+            'profile_id' => $iProfileId, 
+            'event_id' => $aEvent[$CNF['FIELD_ID']], 
+            'date' => $aEvent[$CNF['FIELD_ADDED']]
+        );
+
+        switch ($aParams['type']) {
+            case BX_BASE_MOD_NTFS_TYPE_PUBLIC:
+                $aParamsSet['context_id'] = 0;
+                break;
+
+            case BX_TIMELINE_TYPE_OWNER_AND_CONNECTIONS:
+                $aParamsSet['context_id'] = $iProfileId;
+                break;
+        }
+
+        return $this->_oDb->insertCache($aParamsSet);
+    }
+
+    protected function _getCachedEvents($iProfileId, &$aParams)
+    {
+        return $this->_oDb->getCache(array(
+            'browse' => $aParams['browse'], 
+            'type' => $aParams['type'], 
+            'context_id' => $aParams['owner_id'], 
+            'profile_id' => $iProfileId, 
+            'start' => $aParams['start'], 
+            'per_page' => $aParams['per_page']
+        ));
+    }
+
+    protected function _getPosts($aParams)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        if(!$this->_oConfig->isCacheList())
+            return $this->_oDb->getEvents($aParams);
+
+        $iPerPage = (int)$aParams['per_page'];
+
+        $iProfileId = (int)bx_get_logged_profile_id(); 
+        $aCache = $this->_getCachedEvents($iProfileId, $aParams);
+        if(is_array($aCache) && count($aCache) == $iPerPage) {
+            /*
+             * Check if cache is valid
+             */
+            $bValid = false;
+            $bUpdated = false;
+            $aCachedItem = current($aCache);
+
+            while(!$bValid) {
+                $aEvents = $this->_oDb->getEvents($aParams);
+                foreach($aEvents as $aEvent) {
+                    if($aEvent[$CNF['FIELD_ID']] == $aCachedItem['event_id']) {
+                        $bValid = true;
+                        break;
+                    }
+
+                    if(!$this->_cacheEvent($iProfileId, $aParams, $aEvent))
+                        continue;
+
+                    $bUpdated = true;
+                }
+            }
+
+            if($bUpdated)
+                $aCache = $this->_getCachedEvents($iProfileId, $aParams);
+
+            return $this->_oDb->getEvents(array('browse' => 'ids', 'type' => $aParams['type'], 'ids' => array_keys($aCache)));
+        }
+
+        $aEvents = array();
+        while(count($aEvents) < $aParams['per_page']) {
+            $aEvents += $this->_oDb->getEvents($aParams);
+            $aParams['start'] += $aParams['per_page'];
+        }
+
+        $aIds = array();
+        foreach($aEvents as $aEvent) {
+            if(!$this->_cacheEvent($iProfileId, $aParams, $aEvent))
+                continue;
+
+            $aIds[] = $aEvent[$CNF['FIELD_ID']];
+        }
+
+        return $this->_oDb->getEvents(array('browse' => 'ids', 'type' => $aParams['type'], 'ids' => $aIds));
+    }
+
     protected function _getPost($sType, $aEvent, $aBrowseParams = array())
     {
         $CNF = &$this->_oConfig->CNF;

+ 3 - 0
modules/boonex/timeline/install/langs/en.xml

@@ -21,6 +21,9 @@
         <string name="_bx_timeline_option_preload_comments"><![CDATA[Number of preloaded comments (up to 7 items)]]></string>
 	<string name="_bx_timeline_option_enable_hot"><![CDATA[Enable Hot list aggregation]]></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_lifetime"><![CDATA[Item cache lifetime]]></string>
+        <string name="_bx_timeline_option_enable_cache_list"><![CDATA[Enable feed cache]]></string>
 	<string name="_bx_timeline_option_enable_editor_toolbar"><![CDATA[Enable post form editor toolbar]]></string>
 
 	<string name="_bx_timeline_form_post"><![CDATA[Post]]></string>

+ 3 - 0
modules/boonex/timeline/install/sql/enable.sql

@@ -175,6 +175,9 @@ INSERT INTO `sys_options` (`name`, `value`, `category_id`, `caption`, `type`, `c
 ('bx_timeline_preload_comments', '0', @iCategId, '_bx_timeline_option_preload_comments', 'digit', '', '', '', '', 51),
 ('bx_timeline_enable_hot', '', @iCategId, '_bx_timeline_option_enable_hot', 'checkbox', '', '', '', '', 60),
 ('bx_timeline_hot_interval', '48', @iCategId, '_bx_timeline_option_hot_interval', 'digit', '', '', '', '', 61),
+('bx_timeline_enable_cache_item', 'on', @iCategId, '_bx_timeline_option_enable_cache_item', 'checkbox', '', '', '', '', 70),
+('bx_timeline_cache_item_lifetime', '300', @iCategId, '_bx_timeline_option_cache_item_lifetime', 'digit', '', '', '', '', 71),
+('bx_timeline_enable_cache_list', 'on', @iCategId, '_bx_timeline_option_enable_cache_list', 'checkbox', '', '', '', '', 72),
 
 -- Post related settings
 ('bx_timeline_enable_editor_toolbar', '', @iCategId, '_bx_timeline_option_enable_editor_toolbar', 'checkbox', '', '', '', '', 100);

+ 9 - 0
modules/boonex/timeline/install/sql/install.sql

@@ -49,6 +49,15 @@ INSERT INTO `bx_timeline_handlers`(`group`, `type`, `alert_unit`, `alert_action`
 ('common_repost', 'insert', 'timeline_common_repost', '', ''),
 ('profile', 'delete', 'profile', 'delete', '');
 
+CREATE TABLE IF NOT EXISTS `bx_timeline_cache` (
+  `type` varchar(32) NOT NULL default '',
+  `context_id` int(11) NOT NULL default '0',
+  `profile_id` int(11) NOT NULL default '0',
+  `event_id` int(11) NOT NULL default '0',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY `item` (`type`, `context_id`, `profile_id`, `event_id`)
+);
+
 -- TABLES: STORAGES, TRANSCODERS, UPLOADERS
 CREATE TABLE IF NOT EXISTS `bx_timeline_photos` (
   `id` int(11) NOT NULL AUTO_INCREMENT,

+ 8 - 20
modules/boonex/timeline/install/sql/uninstall.sql

@@ -1,19 +1,12 @@
 SET @sName = 'bx_timeline';
 
-DROP TABLE IF EXISTS `bx_timeline_events`;
+DROP TABLE IF EXISTS `bx_timeline_events`, `bx_timeline_handlers`, `bx_timeline_cache`;
 
-DROP TABLE IF EXISTS `bx_timeline_handlers`;
+DROP TABLE IF EXISTS `bx_timeline_photos`, `bx_timeline_photos_processed`, `bx_timeline_photos2events`;
 
-DROP TABLE IF EXISTS `bx_timeline_photos`;
-DROP TABLE IF EXISTS `bx_timeline_photos_processed`;
-DROP TABLE IF EXISTS `bx_timeline_photos2events`;
+DROP TABLE IF EXISTS `bx_timeline_videos`, `bx_timeline_videos_processed`, `bx_timeline_videos2events`;
 
-DROP TABLE IF EXISTS `bx_timeline_videos`;
-DROP TABLE IF EXISTS `bx_timeline_videos_processed`;
-DROP TABLE IF EXISTS `bx_timeline_videos2events`;
-
-DROP TABLE IF EXISTS `bx_timeline_links`;
-DROP TABLE IF EXISTS `bx_timeline_links2events`;
+DROP TABLE IF EXISTS `bx_timeline_links`, `bx_timeline_links2events`;
 
 DROP TABLE IF EXISTS `bx_timeline_reposts_track`;
 
@@ -21,20 +14,15 @@ DROP TABLE IF EXISTS `bx_timeline_comments`;
 
 DROP TABLE IF EXISTS `bx_timeline_views_track`;
 
-DROP TABLE IF EXISTS `bx_timeline_votes`;
-DROP TABLE IF EXISTS `bx_timeline_votes_track`;
+DROP TABLE IF EXISTS `bx_timeline_votes`, `bx_timeline_votes_track`;
 
-DROP TABLE IF EXISTS `bx_timeline_meta_keywords`;
-DROP TABLE IF EXISTS `bx_timeline_meta_locations`;
-DROP TABLE IF EXISTS `bx_timeline_meta_mentions`;
+DROP TABLE IF EXISTS `bx_timeline_meta_keywords`, `bx_timeline_meta_locations`, `bx_timeline_meta_mentions`;
 
-DROP TABLE IF EXISTS `bx_timeline_reports`;
-DROP TABLE IF EXISTS `bx_timeline_reports_track`;
+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`;
-DROP TABLE IF EXISTS `bx_timeline_scores_track`;
+DROP TABLE IF EXISTS `bx_timeline_scores`, `bx_timeline_scores_track`;
 
 
 -- STORAGES, TRANSCODERS, UPLOADERS