Browse Source

#104 - Live updates engine.

AntonLV 12 years ago
parent
commit
e2af6048c4

+ 224 - 0
inc/classes/BxDolLiveUpdates.php

@@ -0,0 +1,224 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) BoonEx Pty Limited - http://www.boonex.com/
+ * CC-BY License - http://creativecommons.org/licenses/by/3.0/
+ *
+ * @defgroup    DolphinCore Dolphin Core
+ * @{
+ */
+
+bx_import('BxDol');
+bx_import('BxDolLiveUpdatesQuery');
+
+define('BX_DOL_LIVE_UPDATES_TYPE_TRANSIENT', 'transient');
+
+/**
+ * @page objects
+ * @section live updates Live Updates
+ * @ref BxDolLiveUpdates
+ */
+
+class BxDolLiveUpdates extends BxDol
+{
+	protected $_oQuery;
+    protected $_aSystems;
+
+    protected $_iInterval;
+
+    protected $_sSessionKey;
+
+	protected $_iCacheTTL; // Note. Non-zero value may lead to cache destroying in wrong time.  
+	protected $_sCacheKey;
+
+    protected $_sJsClass;
+    protected $_sJsObject;
+
+    public function __construct()
+    {
+        parent::__construct();
+
+        $this->_oQuery = new BxDolLiveUpdatesQuery();
+        $this->_aSystems = $this->_oQuery->getSystems();
+
+        $this->_iInterval = (int)$this->_oQuery->getParam('sys_live_updates_interval');
+
+        $this->_sSessionKey = 'bx_lu_index';
+        
+        $this->_iCacheTTL = 0;
+        $this->_sCacheKey = 'sys_live_updates_' . bx_get_logged_profile_id();
+
+        $this->_sJsClass = 'BxDolLiveUpdates';
+    	$this->_sJsObject = 'oLiveUpdates';
+    }
+
+    /**
+     * get live updates instanse
+     * @return ready to use class instance
+     */
+    public static function getInstance()
+    {
+		if(!isset($GLOBALS['bxDolClasses'][__CLASS__])) {
+			bx_import('BxTemplLiveUpdates');
+			$GLOBALS['bxDolClasses'][__CLASS__] = new BxTemplLiveUpdates();
+		}
+
+		return $GLOBALS['bxDolClasses'][__CLASS__];
+    }
+
+    /**
+     * 
+     * Is called via Ajax Requests only. 
+     */
+    public function perform()
+    {
+		$iIndex = $this->_getIndex();
+
+		$this->_aSystems = $this->_getCachedSystems();
+    	if(empty($this->_aSystems) || !is_array($this->_aSystems))
+    		return array();
+
+		$aCached = $this->_getCachedData();
+		$aRequested = $this->_getRequestedData($iIndex, true);
+
+		$aResult = array();
+		$bUpdateCache = false;
+		foreach($aRequested as $sName => $aData) {
+			if(isset($aCached[$sName]) && (int)$aCached[$sName] == (int)$aData['count'])
+				continue;
+
+			$aResultData = array('count_new' => $aData['count'], 'count_old' => $aCached[$sName]);
+			if(isset($aData['data']))
+				$aResultData = array_merge($aResultData, $aData['data']);
+
+			$aResult[] = array(
+				'data' => $aResultData,
+				'method' => $aData['method']
+			);
+
+			$aCached[$sName] = $aData['count'];
+			$bUpdateCache = true;
+		}
+
+		if($bUpdateCache)
+			$this->_updateCached('data', $aCached);
+
+    	return $aResult;
+    }
+
+    /**
+     * 
+     * Add transient live update for current user on this current page. 
+     * @param string $sName - unique name.
+     * @param integer $iFrequency - call frequency.
+     * @param string $sServiceCall - serialized service call.
+     * @param boolean $bActive - add active/not active live update.
+     */
+    public function add($sName, $iFrequency, $sServiceCall, $bActive = true)
+    {
+    	if(isset($this->_aSystems[$sName]))
+    		return false;
+
+    	$this->_aSystems[$sName] = array(
+    		'name' => $sName,
+    		'type' => BX_DOL_LIVE_UPDATES_TYPE_TRANSIENT,
+    		'frequency' => $iFrequency,
+    		'service_call' => $sServiceCall,
+    		'active' => $bActive ? 1 : 0
+    	);
+
+    	$this->_updateCached('systems', $this->_aSystems);
+
+    	return true;
+    }
+
+    protected function _getIndex()
+    {
+		bx_import('BxDolSession');
+    	$oSession = BxDolSession::getInstance();
+
+		$iIndex = (int)$oSession->getValue($this->_sSessionKey);
+		$oSession->setValue($this->_sSessionKey, ($iIndex + 1));
+
+		return $iIndex;
+    }
+
+    protected function _getCacheInfo()
+    {
+    	return array(
+    		$this->_oQuery->getDbCacheObject(),
+    		$this->_oQuery->genDbCacheKey($this->_sCacheKey),
+    		$this->_iCacheTTL
+    	);
+    }
+
+    protected function _getCached($sType)
+    {
+    	list($oCache, $sCacheKey, $iCacheTtl) = $this->_getCacheInfo();
+
+    	$aCached = $oCache->getData($sCacheKey, $iCacheTtl);
+    	if(empty($aCached[$sType])) {
+    		switch($sType) {
+    			case 'systems':
+    				$aCached[$sType] = $this->_oQuery->getSystems();
+    				break;
+
+    			case 'data':
+    				$aRequested = $this->_getRequestedData();
+    				foreach($aRequested as $sName => $aData)
+    					$aCached[$sType][$sName] = $aData['count'];
+    				break;
+    		}
+
+    		if(!empty($aCached[$sType]))
+    			$oCache->setData($sCacheKey, $aCached, $iCacheTtl);
+    	}
+
+    	return $aCached[$sType];
+    }
+
+	protected function _getCachedSystems()
+    {
+    	return $this->_getCached('systems');
+    }
+
+    protected function _getCachedData()
+    {
+    	return $this->_getCached('data');
+    }
+
+	protected function _updateCached($sKey, $aData)
+    {
+    	list($oCache, $sCacheKey, $iCacheTtl) = $this->_getCacheInfo();
+
+    	$aCached = $oCache->getData($sCacheKey, $iCacheTtl);
+    	$aCached[$sKey] = $aData;
+
+    	$oCache->setData($sCacheKey, $aCached, $iCacheTtl);
+    }
+
+    protected function _getRequestedData($iIndex = 0, $bIndexCheck = false)
+    {
+    	$aResult = array();
+
+    	foreach($this->_aSystems as $aSystem) {
+    		if(empty($aSystem) || !is_array($aSystem) || (int)$aSystem['active'] != 1)
+    			continue;
+
+			if($bIndexCheck && $iIndex % (int)$aSystem['frequency'] != 0)
+				continue;
+
+			if(!BxDolService::isSerializedService($aSystem['service_call']))
+				continue;
+
+			$aResponce = BxDolService::callSerialized($aSystem['service_call']);
+			if(empty($aResponce) || !is_array($aResponce) || !isset($aResponce['count'], $aResponce['method']))
+				continue;
+
+			$aResult[$aSystem['name']] = $aResponce;
+    	}
+
+    	return $aResult;
+    }
+}
+
+/** @} */

+ 38 - 0
inc/classes/BxDolLiveUpdatesQuery.php

@@ -0,0 +1,38 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) BoonEx Pty Limited - http://www.boonex.com/
+ * CC-BY License - http://creativecommons.org/licenses/by/3.0/
+ *
+ * @defgroup    DolphinCore Dolphin Core
+ * @{
+ */
+
+bx_import('BxDolDb');
+
+/**
+ * @see BxDolLiveUpdates
+ */
+class BxDolLiveUpdatesQuery extends BxDolDb
+{
+    public function __construct()
+    {
+        parent::__construct();
+    }
+
+	public function getSystems()
+    {
+        if(!isset($GLOBALS['bx_dol_live_updates_systems']))
+            $GLOBALS['bx_dol_live_updates_systems'] = BxDolDb::getInstance()->fromCache('sys_objects_live_updates', 'getAllWithKey', '
+                SELECT
+                    `id` as `id`,
+                    `name` AS `name`,
+                    `frequency` AS `frequency`,
+                    `service_call` AS `service_call`,
+                    `active` AS `active`
+                FROM `sys_objects_live_updates`', 'name');
+
+        return $GLOBALS['bx_dol_live_updates_systems'];
+    }
+}
+
+/** @} */

+ 61 - 0
inc/js/classes/BxDolLiveUpdates.js

@@ -0,0 +1,61 @@
+/**
+ * @package     Dolphin Core
+ * @copyright   Copyright (c) BoonEx Pty Limited - http://www.boonex.com/
+ * @license     CC-BY - http://creativecommons.org/licenses/by/3.0/
+ */
+
+function BxDolLiveUpdates(oOptions)
+{
+	this._sActionsUrl = oOptions.sActionsUrl == undefined ? sUrlRoot + 'live_updates.php' : oOptions.sActionsUrl;
+	this._sObjName = oOptions.sObjName == undefined ? 'oLiveUpdates' : oOptions.sObjName;
+	this._iInterval = oOptions.iInterval == undefined ? 3000 : oOptions.iInterval;
+	this._bServerRequesting = oOptions.bServerRequesting == undefined ? {} : oOptions.bServerRequesting;
+
+	this._iHandler = 0;
+
+	this.init();
+}
+
+BxDolLiveUpdates.prototype.init = function() {
+	var $this = this;
+
+	if(this._iHandler)
+		this.destroy();
+
+    $(document).ready(function() {
+    	$this._iHandler = setInterval(function() {
+    		$this.perform();
+    	}, $this._iInterval);
+    });
+};
+
+BxDolLiveUpdates.prototype.destroy = function() {
+	if(this._iHandler)
+		clearInterval(this._iHandler);
+};
+
+BxDolLiveUpdates.prototype.perform = function() {
+	if(!this._bServerRequesting)
+		return;
+
+	var $this = this;
+	var oDate = new Date();
+
+    $.get(
+    	this._sActionsUrl,
+        {
+    		_t: oDate.getTime()
+        },
+        function(aData) {
+        	$.each(aData, function(iIndex, oValue) {
+        		if(oValue.method) {
+        			var oFunc = function(oData) {
+        				eval(oValue.method);
+        			};
+        			oFunc(oValue.data);
+        		}
+        	});
+        },
+        'json'
+    );
+};

+ 22 - 3
install/sql/system.sql

@@ -5,7 +5,7 @@
 -- --------------------------------------------------------
 
 SET NAMES 'utf8';
-DROP TABLE IF EXISTS `sys_keys`, `sys_objects_editor`, `sys_objects_captcha`, `sys_objects_social_sharing`, `sys_objects_cmts`, `sys_cmts_images`, `sys_cmts_images_preview`, `sys_cmts_images2entries`, `sys_email_templates`, `sys_options`, sys_options_types, `sys_options_categories`, `sys_localization_categories`, `sys_localization_keys`, `sys_localization_languages`, `sys_localization_strings`, `sys_acl_actions`, `sys_acl_actions_track`, `sys_acl_matrix`, `sys_acl_levels`, `sys_sessions`, `sys_acl_levels_members`, `sys_objects_rss`, `sys_objects_search`, `sys_stat_site`, `sys_alerts`, `sys_alerts_handlers`, `sys_injections`, `sys_injections_admin`, `sys_modules`, `sys_modules_file_tracks`, `sys_modules_relations`, `sys_permalinks`, `sys_objects_privacy`, `sys_privacy_defaults`, `sys_privacy_groups`, `sys_objects_auths`, `sys_objects_vote`, `sys_objects_view`, `sys_cron_jobs`, `sys_objects_storage`, `sys_objects_uploader`, `sys_storage_user_quotas`, `sys_storage_tokens`, `sys_storage_ghosts`, `sys_storage_deletions`, `sys_storage_mime_types`, `sys_objects_transcoder_images`, `sys_transcoder_images_files`, `sys_transcoder_images_filters`, `sys_accounts`, `sys_profiles`, `sys_objects_form`, `sys_form_displays`, `sys_form_inputs`, `sys_form_display_inputs`, `sys_form_pre_lists`, `sys_form_pre_values`, `sys_menu_templates`, `sys_objects_menu`, `sys_menu_sets`, `sys_menu_items`, `sys_objects_grid`, `sys_grid_fields`, `sys_grid_actions`, `sys_objects_connection`, `sys_profiles_conn_subscriptions`, `sys_profiles_conn_friends`, `sys_objects_page`, `sys_pages_layouts`, `sys_pages_design_boxes`, `sys_pages_blocks`, `sys_objects_metatags`, `sys_images`, `sys_std_pages`, `sys_std_widgets`, `sys_std_pages_widgets`;
+DROP TABLE IF EXISTS `sys_keys`, `sys_objects_editor`, `sys_objects_captcha`, `sys_objects_social_sharing`, `sys_objects_cmts`, `sys_cmts_images`, `sys_cmts_images_preview`, `sys_cmts_images2entries`, `sys_email_templates`, `sys_options`, sys_options_types, `sys_options_categories`, `sys_localization_categories`, `sys_localization_keys`, `sys_localization_languages`, `sys_localization_strings`, `sys_acl_actions`, `sys_acl_actions_track`, `sys_acl_matrix`, `sys_acl_levels`, `sys_sessions`, `sys_acl_levels_members`, `sys_objects_rss`, `sys_objects_search`, `sys_stat_site`, `sys_alerts`, `sys_alerts_handlers`, `sys_injections`, `sys_injections_admin`, `sys_modules`, `sys_modules_file_tracks`, `sys_modules_relations`, `sys_permalinks`, `sys_objects_privacy`, `sys_privacy_defaults`, `sys_privacy_groups`, `sys_objects_auths`, `sys_objects_vote`, `sys_objects_view`, `sys_cron_jobs`, `sys_objects_storage`, `sys_objects_uploader`, `sys_storage_user_quotas`, `sys_storage_tokens`, `sys_storage_ghosts`, `sys_storage_deletions`, `sys_storage_mime_types`, `sys_objects_transcoder_images`, `sys_transcoder_images_files`, `sys_transcoder_images_filters`, `sys_accounts`, `sys_profiles`, `sys_objects_form`, `sys_form_displays`, `sys_form_inputs`, `sys_form_display_inputs`, `sys_form_pre_lists`, `sys_form_pre_values`, `sys_menu_templates`, `sys_objects_menu`, `sys_menu_sets`, `sys_menu_items`, `sys_objects_grid`, `sys_grid_fields`, `sys_grid_actions`, `sys_objects_connection`, `sys_profiles_conn_subscriptions`, `sys_profiles_conn_friends`, `sys_objects_page`, `sys_pages_layouts`, `sys_pages_design_boxes`, `sys_pages_blocks`, `sys_objects_metatags`, `sys_objects_live_updates`, `sys_images`, `sys_std_pages`, `sys_std_widgets`, `sys_std_pages_widgets`;
 ALTER DATABASE DEFAULT CHARACTER SET 'utf8' COLLATE 'utf8_unicode_ci';
 
 
@@ -235,7 +235,9 @@ INSERT INTO `sys_options`(`category_id`, `name`, `caption`, `value`, `type`, `ex
 (@iCategoryId, 'sys_redirect_after_account_added', '', 'page.php?i=create-persons-profile', 'digit', '', '', '', 50),
 
 (@iCategoryId, 'sys_editor_default', '', 'sys_tinymce', 'digit', '', '', '', 60),
-(@iCategoryId, 'sys_captcha_default', '', 'sys_recaptcha', 'digit', '', '', '', 61);
+(@iCategoryId, 'sys_captcha_default', '', 'sys_recaptcha', 'digit', '', '', '', 61),
+
+(@iCategoryId, 'sys_live_updates_interval', '', '3000', 'digit', '', '', '', 70);
 
 
 --
@@ -870,7 +872,8 @@ CREATE TABLE `sys_injections` (
 ) ENGINE=MyISAM  DEFAULT CHARSET=utf8;
 
 INSERT INTO `sys_injections`(`name`, `page_index`, `key`, `type`, `data`, `replace`, `active`) VALUES
-('update_cache', 150, 'injection_head', 'service', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:17:"get_cache_updater";s:6:"params";a:0:{}s:5:"class";s:19:"TemplStudioLauncher";}', 0, 1);
+('update_cache', 150, 'injection_head', 'service', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:17:"get_cache_updater";s:6:"params";a:0:{}s:5:"class";s:19:"TemplStudioLauncher";}', 0, 1),
+('live_updates', 0, 'injection_head', 'service', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:4:"init";s:6:"params";a:0:{}s:5:"class";s:24:"TemplLiveUpdatesServices";}', 0, 1);
 
 -- --------------------------------------------------------
 
@@ -3181,6 +3184,22 @@ CREATE TABLE `sys_objects_metatags` (
 
 -- --------------------------------------------------------
 
+--
+-- Table structure for table `sys_objects_live_updates`
+--
+
+CREATE TABLE `sys_objects_live_updates` (
+  `id` int(11) unsigned NOT NULL auto_increment,
+  `name` varchar(50) NOT NULL default '',
+  `frequency` tinyint(4) NOT NULL DEFAULT '1',
+  `service_call` text NOT NULL default '', 
+  `active` tinyint(4) NOT NULL DEFAULT '1',
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `name` (`name`)
+) ENGINE=MyISAM  DEFAULT CHARSET=utf8;
+
+-- --------------------------------------------------------
+
 --
 -- Table structure for table `sys_std_pages`
 --

+ 19 - 0
live_updates.php

@@ -0,0 +1,19 @@
+<?php
+/**
+ * @package     Dolphin Core
+ * @copyright   Copyright (c) BoonEx Pty Limited - http://www.boonex.com/
+ * @license     CC-BY - http://creativecommons.org/licenses/by/3.0/
+ */
+
+require_once('./inc/header.inc.php');
+require_once(BX_DIRECTORY_PATH_INC . "design.inc.php");
+
+bx_import('BxDolLiveUpdates');
+$oLiveUpdates = BxDolLiveUpdates::getInstance();
+
+if($oLiveUpdates) {
+    $aResult = $oLiveUpdates->perform();
+
+    header('Content-type: text/html; charset=utf-8');
+	echo json_encode($aResult);
+}

+ 23 - 0
modules/boonex/lagoon/data/template/system/scripts/BxTemplLiveUpdates.php

@@ -0,0 +1,23 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) BoonEx Pty Limited - http://www.boonex.com/
+ * CC-BY License - http://creativecommons.org/licenses/by/3.0/
+ *
+ * @defgroup    DolphinCore Dolphin Core
+ * @{
+ */
+
+bx_import('BxBaseLiveUpdates');
+
+/**
+ * @see BxDolView
+ */
+class BxTemplLiveUpdates extends BxBaseLiveUpdates
+{
+    function __construct()
+    {
+        parent::__construct();
+    }
+}
+
+/** @} */

+ 23 - 0
modules/boonex/lagoon/data/template/system/scripts/BxTemplLiveUpdatesServices.php

@@ -0,0 +1,23 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) BoonEx Pty Limited - http://www.boonex.com/
+ * CC-BY License - http://creativecommons.org/licenses/by/3.0/
+ *
+ * @defgroup    DolphinCore Dolphin Core
+ * @{
+ */
+
+bx_import('BxBaseLiveUpdatesServices');
+
+/**
+ * @see BxBaseLiveUpdatesServices
+ */
+class BxTemplLiveUpdatesServices extends BxBaseLiveUpdatesServices
+{
+    public function __construct()
+    {
+        parent::__construct();
+    }
+}
+
+/** @} */

+ 23 - 0
modules/boonex/ocean/data/template/system/scripts/BxTemplLiveUpdates.php

@@ -0,0 +1,23 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) BoonEx Pty Limited - http://www.boonex.com/
+ * CC-BY License - http://creativecommons.org/licenses/by/3.0/
+ *
+ * @defgroup    DolphinCore Dolphin Core
+ * @{
+ */
+
+bx_import('BxBaseLiveUpdates');
+
+/**
+ * @see BxDolView
+ */
+class BxTemplLiveUpdates extends BxBaseLiveUpdates
+{
+    function __construct()
+    {
+        parent::__construct();
+    }
+}
+
+/** @} */

+ 23 - 0
modules/boonex/ocean/data/template/system/scripts/BxTemplLiveUpdatesServices.php

@@ -0,0 +1,23 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) BoonEx Pty Limited - http://www.boonex.com/
+ * CC-BY License - http://creativecommons.org/licenses/by/3.0/
+ *
+ * @defgroup    DolphinCore Dolphin Core
+ * @{
+ */
+
+bx_import('BxBaseLiveUpdatesServices');
+
+/**
+ * @see BxBaseLiveUpdatesServices
+ */
+class BxTemplLiveUpdatesServices extends BxBaseLiveUpdatesServices
+{
+    public function __construct()
+    {
+        parent::__construct();
+    }
+}
+
+/** @} */

+ 41 - 0
template/scripts/BxBaseLiveUpdates.php

@@ -0,0 +1,41 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) BoonEx Pty Limited - http://www.boonex.com/
+ * CC-BY License - http://creativecommons.org/licenses/by/3.0/
+ *
+ * @defgroup    DolphinCore Dolphin Core
+ * @{
+ */
+
+bx_import('BxDolLiveUpdates');
+
+/**
+ * @see BxDolLiveUpdates
+ */
+class BxBaseLiveUpdates extends BxDolLiveUpdates
+{
+    public function __construct()
+    {
+        parent::__construct();
+    }
+
+	public function init($aParams = array())
+    {
+        $aParams = array_merge(array(
+        	'sActionsUrl' => BX_DOL_URL_ROOT . 'live_updates.php',
+        	'sObjName' => $this->_sJsObject,
+        	'iInterval' => $this->_iInterval,
+        	'bServerRequesting' => !empty($this->_aSystems)
+        ), $aParams);
+
+		$sContent = "var " . $this->_sJsObject . " = new " . $this->_sJsClass . "(" . json_encode($aParams) . ");";
+
+		bx_import('BxDolTemplate');
+		$oTemplate = BxDolTemplate::getInstance();
+
+		$oTemplate->addJs(array('BxDolLiveUpdates.js'));
+        return $oTemplate->_wrapInTagJsCode($sContent);
+    }
+}
+
+/** @} */

+ 27 - 0
template/scripts/BxBaseLiveUpdatesServices.php

@@ -0,0 +1,27 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) BoonEx Pty Limited - http://www.boonex.com/
+ * CC-BY License - http://creativecommons.org/licenses/by/3.0/
+ *
+ * @defgroup    DolphinCore Dolphin Core
+ * @{
+ */
+
+/**
+ * System services related to Live Updates.
+ */
+class BxBaseLiveUpdatesServices extends BxDol
+{
+    public function __construct()
+    {
+        parent::__construct();
+    }
+
+    public function serviceInit()
+    {
+        bx_import('BxDolLiveUpdates');
+        return BxDolLiveUpdates::getInstance()->init();
+    }
+}
+
+/** @} */