Swidmann has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/148354

Change subject: Cache support
......................................................................

Cache support

Added CacheHelper class
Added LCStore_MC for memcached stuff
Added cache support for ArticleHelper
Added cache support for WidgetListHelper

Change-Id: I4b7f6830493a213e07440189656eb0a95f9f2c77
---
A BlueSpice.hooks.php
M BlueSpiceFoundation.php
M includes/AutoLoader.php
M includes/Config.class.php
A includes/cache/LCStore_MC.php
M includes/utility/ArticleHelper.class.php
A includes/utility/CacheHelper.class.php
M includes/utility/WidgetListHelper.class.php
M resources/bluespice.extjs/Ext.ux/form/ItemSelector.js
9 files changed, 283 insertions(+), 62 deletions(-)


  git pull 
ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/BlueSpiceFoundation 
refs/changes/54/148354/1

diff --git a/BlueSpice.hooks.php b/BlueSpice.hooks.php
new file mode 100644
index 0000000..9f2067e
--- /dev/null
+++ b/BlueSpice.hooks.php
@@ -0,0 +1,27 @@
+<?php
+$wgHooks['SetupAfterCache'][] = 'BsCoreHooks::onSetupAfterCache';
+$wgHooks['SoftwareInfo'][] = 'BsCoreHooks::onSoftwareInfo';
+$wgHooks['BeforePageDisplay'][] = 'BsCoreHooks::onBeforePageDisplay';
+$wgHooks['LinkEnd'][] = 'BsCoreHooks::LinkEnd';
+$wgHooks['MakeGlobalVariablesScript'][] = 
'BsCoreHooks::onMakeGlobalVariablesScript';
+$wgHooks['LoadExtensionSchemaUpdates'][] = 
'BsCoreHooks::onLoadExtensionSchemaUpdates';
+$wgHooks['ApiCheckCanExecute'][] = 'BsCoreHooks::onApiCheckCanExecute';
+$wgHooks['UserGetRights'][] = 'BsCoreHooks::onUserGetRights';
+$wgHooks['userCan'][] = 'BsCoreHooks::onUserCan';
+$wgHooks['UploadVerification'][] = 'BsCoreHooks::onUploadVerification';
+$wgHooks['SkinTemplateOutputPageBeforeExec'][] = 
'BsCoreHooks::onSkinTemplateOutputPageBeforeExec';
+
+$wgHooks['UserAddGroup'][] = 'BsGroupHelper::addTemporaryGroupToUserHelper';
+
+// START cache invalidation hooks
+$wgHooks['PageContentSaveComplete'][] = 
'BsCacheHelper::onPageContentSaveComplete';
+$wgHooks['BsSettingsAfterSaveSettings'][] = 
'BsCacheHelper::onBsSettingsAfterSaveSettings';
+// START cache invalidation hooks
+
+if ( !isset( $wgHooks['EditPage::showEditForm:initial'] ) ) {
+       $wgHooks['EditPage::showEditForm:initial'] = array();
+}
+
+if ( $wgDBtype == 'oracle' ) {
+       $wgHooks['ArticleDelete'][] = 'BSOracleHooks::onArticleDelete';
+}
diff --git a/BlueSpiceFoundation.php b/BlueSpiceFoundation.php
index 7e2760c..e4f77fd 100644
--- a/BlueSpiceFoundation.php
+++ b/BlueSpiceFoundation.php
@@ -90,29 +90,10 @@
 $wgSpecialPageGroups['SpecialCredits'] = 'bluespice';
 $wgSpecialPages['SpecialCredits'] = 'SpecialCredits';
 
-$wgHooks['SetupAfterCache'][] = 'BsCoreHooks::onSetupAfterCache';
-$wgHooks['SoftwareInfo'][] = 'BsCoreHooks::onSoftwareInfo';
-$wgHooks['BeforePageDisplay'][] = 'BsCoreHooks::onBeforePageDisplay';
-$wgHooks['LinkEnd'][] = 'BsCoreHooks::LinkEnd';
-$wgHooks['MakeGlobalVariablesScript'][] = 
'BsCoreHooks::onMakeGlobalVariablesScript';
-$wgHooks['LoadExtensionSchemaUpdates'][] = 
'BsCoreHooks::onLoadExtensionSchemaUpdates';
-$wgHooks['ApiCheckCanExecute'][] = 'BsCoreHooks::onApiCheckCanExecute';
-$wgHooks['UserGetRights'][] = 'BsCoreHooks::onUserGetRights';
-$wgHooks['userCan'][] = 'BsCoreHooks::onUserCan';
-$wgHooks['UploadVerification'][] = 'BsCoreHooks::onUploadVerification';
-$wgHooks['SkinTemplateOutputPageBeforeExec'][] = 
'BsCoreHooks::onSkinTemplateOutputPageBeforeExec';
-
-$wgHooks['UserAddGroup'][] = 'BsGroupHelper::addTemporaryGroupToUserHelper';
-
-if ( !isset( $wgHooks['EditPage::showEditForm:initial'] ) ) {
-       $wgHooks['EditPage::showEditForm:initial'] = array();
-}
-
-if ( $wgDBtype == 'oracle' ) {
-       $wgHooks['ArticleDelete'][] = 'BSOracleHooks::onArticleDelete';
-}
-
+// Register hooks
+require_once( 'BlueSpice.hooks.php' );
 //Setup
+
 $wgExtensionFunctions[] = 'BsCoreHooks::setup';
 
 // initalise BlueSpice as first extension in a fully initialised environment
diff --git a/includes/AutoLoader.php b/includes/AutoLoader.php
index 84196fb..fcc5622 100644
--- a/includes/AutoLoader.php
+++ b/includes/AutoLoader.php
@@ -15,6 +15,7 @@
 
 $GLOBALS['wgAutoloadClasses']['LCStore_BSDB'] = 
__DIR__."/cache/LCStore_BSDB.php";
 $GLOBALS['wgAutoloadClasses']['LCStore_SHM']  = 
__DIR__."/cache/LCStore_SHM.php";
+$GLOBALS['wgAutoloadClasses']['LCStore_MC']  = __DIR__."/cache/LCStore_MC.php";
 
 $GLOBALS['wgAutoloadClasses']['BsValidator'] = 
__DIR__."/validator/Validator.class.php";
 $GLOBALS['wgAutoloadClasses']['BsValidatorPlugin'] = 
__DIR__."/validator/Validator.class.php";
@@ -57,6 +58,7 @@
 
 //utility
 $GLOBALS['wgAutoloadClasses']['BsArticleHelper'] = 
__DIR__."/utility/ArticleHelper.class.php";
+$GLOBALS['wgAutoloadClasses']['BsCacheHelper'] = 
__DIR__."/utility/CacheHelper.class.php";
 $GLOBALS['wgAutoloadClasses']['BsConnectionHelper'] = 
__DIR__."/utility/ConnectionHelper.class.php";
 $GLOBALS['wgAutoloadClasses']['BsDOMHelper'] = 
__DIR__."/utility/DOMHelper.class.php";
 $GLOBALS['wgAutoloadClasses']['BsFormatConverter'] = 
__DIR__."/utility/FormatConverter.class.php";
diff --git a/includes/Config.class.php b/includes/Config.class.php
index 3813e82..1af870e 100644
--- a/includes/Config.class.php
+++ b/includes/Config.class.php
@@ -273,11 +273,29 @@
         * loads all settings from the database and saves the instances for 
every variable internal.
         */
        public static function loadSettings() {
-               $dbr = wfGetDB ( DB_READ );
-               # query the settings from bs_settings
-               $res = $dbr->select ( 'bs_settings', array ( 
$dbr->addIdentifierQuotes('key'), $dbr->addIdentifierQuotes('value') ) );
+               $oCache = wfGetCache( CACHE_ANYTHING );
+               $sKey = wfMemcKey( 'BlueSpice', 'BsConfig', 'loadSettings' );
+               $aData = $oCache->get( $sKey );
+
+               if( $aData !== false ) {
+                       wfDebugLog( 'BsMemcached' , __CLASS__.': Fetching 
settings from cache' );
+                       $aRows = $aData;
+               } else {
+                       wfDebugLog( 'BsMemcached' , __CLASS__.': Fetching 
settings from DB' );
+                       $dbr = wfGetDB ( DB_READ );
+                       # query the settings from bs_settings
+                       $res = $dbr->select ( 'bs_settings', array ( 
$dbr->addIdentifierQuotes('key'), $dbr->addIdentifierQuotes('value') ) );
+                       $aRows = array();
+
+                       while( $row = $res->fetchObject() ) {
+                               $aRows[] = $row;
+                       }
+
+                       // TODO SW: invalidate cache in BsCacheHelper
+                       $oCache->set( $sKey, $aRows, 60*5 );//invalidate cache 
after 5 minutes
+               }
                # unserialize and save every setting in the config class
-               while ( $row = $res->fetchObject () ) {
+               foreach( $aRows as $row ) {
                        self::set ( $row->key, unserialize ( $row->value ) );
                }
        }
@@ -321,7 +339,10 @@
                }
 
                # write the settings array to the database
-               return $dbw->insert('bs_settings', $aSettings);
+               wfRunHooks( 'BsSettingsBeforeSaveSettings', array( $this, 
&$aSettings ) );
+               $bReturn = $dbw->insert('bs_settings', $aSettings);
+               wfRunHooks( 'BsSettingsAfterSaveSettings', array( $this, 
$aSettings ) );
+               return $bReturn;
        }
 
        // TODO RBV (02.06.11 16:06): Core-Kontamination! Keine MediaWiki 
Funktionen im Core!
diff --git a/includes/cache/LCStore_MC.php b/includes/cache/LCStore_MC.php
new file mode 100644
index 0000000..cc8d35a
--- /dev/null
+++ b/includes/cache/LCStore_MC.php
@@ -0,0 +1,57 @@
+<?php
+
+/**
+ * This file is part of blue spice for MediaWiki.
+ *
+ * @copyright Copyright (c) 2014, HalloWelt! Medienwerkstatt GmbH, All rights 
reserved.
+ * @author Stefan Widmann <widm...@hallowelt.biz>
+ * @version 0.1.0 beta
+  */
+/**
+ * LCStore implementation which uses memcache to store data.
+ */
+class LCStore_MC implements LCStore {
+       private $currentLang;
+       private $keys;
+
+       public function __construct() {
+               $this->cache = wfGetCache( CACHE_MEMCACHED );
+       }
+
+       public $counter = 0;
+       public function get( $code, $key ) {
+               $k = wfMemcKey( 'l10n', $code, 'k', $key );
+               $r = $this->cache->get( $k );
+
+               return $r === false ? null : $r;
+       }
+
+       public function startWrite( $code ) {
+               $k = wfMemcKey( 'l10n', $code, 'l' );
+               $keys = $this->cache->get( $k );
+               if ( $keys ) {
+                       foreach ( $keys as $k ) {
+                               $this->cache->delete( $k );
+                       }
+               }
+               $this->currentLang = $code;
+               $this->keys = array();
+       }
+
+       public function finishWrite() {
+               if ( $this->currentLang ) {
+                       $k = wfMemcKey( 'l10n', $this->currentLang, 'l' );
+                       $this->cache->set( $k, array_keys( $this->keys ) );
+               }
+               $this->currentLang = null;
+               $this->keys = array();
+       }
+
+       public function set( $key, $value ) {
+               if ( $this->currentLang ) {
+                       $k = wfMemcKey( 'l10n', $this->currentLang, 'k', $key );
+                       $this->keys[$k] = true;
+                       $this->cache->set( $k, $value );
+               }
+       }
+}
\ No newline at end of file
diff --git a/includes/utility/ArticleHelper.class.php 
b/includes/utility/ArticleHelper.class.php
index d041ddc..c255689 100644
--- a/includes/utility/ArticleHelper.class.php
+++ b/includes/utility/ArticleHelper.class.php
@@ -13,7 +13,7 @@
        protected static $aInstances = array();
 
        /**
-        * Protected constructor. Instances can be obtained through the factory 
+        * Protected constructor. Instances can be obtained through the factory
         * method of this class
         * @param Title $oTitle
         */
@@ -43,20 +43,32 @@
                $oTalkPage   = $this->oTitle->getTalkPage();
                $iTalkPageId = $oTalkPage->getArticleID();
 
-               $dbr = wfGetDB( DB_SLAVE );
-               // a new revision (rev_id) is also created on page move. So use 
rev_text_id
-               $res = $dbr->select(
-                       'revision',
-                       'DISTINCT rev_text_id',
-                       array( 'rev_page' => $iTalkPageId ),
-                       __METHOD__
-               );
-               $iCount = $dbr->numRows( $res );
+               $sKey = BsCacheHelper::getCacheKey( 'BlueSpice', 
'ArticleHelper', 'getDiscussionAmount', $iTalkPageId );
+               $aData = BsCacheHelper::get( $sKey );
+
+               if( $aData !== false ) {
+                       wfDebugLog( 'BsMemcached', __CLASS__.': Fetching 
discussion amounts from cache' );
+                       $iCount = $aData;
+               } else {
+                       wfDebugLog( 'BsMemcached', __CLASS__.': Fetching 
discussion amounts from cache' );
+                       $dbr = wfGetDB( DB_SLAVE );
+                       // a new revision (rev_id) is also created on page 
move. So use rev_text_id
+                       $res = $dbr->select(
+                               'revision',
+                               'DISTINCT rev_text_id',
+                               array( 'rev_page' => $iTalkPageId ),
+                               __METHOD__
+                       );
+                       $iCount = $dbr->numRows( $res );
+
+                       BsCacheHelper::set( $sKey, $iCount );
+               }
+
                return $iCount;
        }
 
        /**
-        * 
+        *
         * @param string $sPropName
         * @param bool $bDoLoad
         * @return string|null
@@ -74,13 +86,13 @@
        }
 
        /**
-        * 
+        *
         * @param string $sPropName
         * @param bool $bDoLoad
         * @return sdtClass|true|false|null See PHP documentation for 
json_decode()
         */
        public function getJSONPageProp( $sPropName, $bDoLoad = false ) {
-               return json_decode( 
+               return json_decode(
                        $this->getPageProp( $sPropName, $bDoLoad )
                );
        }
@@ -117,18 +129,28 @@
         */
        public function loadPageProps() {
                $iArticleId = $this->oTitle->getArticleID();
-               $dbr = wfGetDB( DB_SLAVE );
-               $res = $dbr->select(
-                       'page_props',
-                       array('pp_propname', 'pp_value'),
-                       array('pp_page' => $iArticleId ),
-                       __METHOD__
-               );
 
-               foreach( $res as $row ) {
-                       $this->aPageProps[$row->pp_propname] = $row->pp_value;
+               $sKey = BsCacheHelper::getCacheKey( 'BlueSpice', 
'ArticleHelper', 'loadPageProps', $iArticleId );
+               $aData = BsCacheHelper::get( $sKey );
+
+               if( $aData !== false ) {
+                       wfDebugLog( 'BsMemcached', __CLASS__.': Fetching page 
props from cache' );
+                       $this->aPageProps = $aData;
+               } else {
+                       wfDebugLog( 'BsMemcached', __CLASS__.': Fetching page 
props from DB' );
+                       $dbr = wfGetDB( DB_SLAVE );
+                       $res = $dbr->select(
+                               'page_props',
+                               array('pp_propname', 'pp_value'),
+                               array('pp_page' => $iArticleId ),
+                               __METHOD__
+                       );
+
+                       foreach( $res as $row ) {
+                               $this->aPageProps[$row->pp_propname] = 
$row->pp_value;
+                       }
+                       BsCacheHelper::set( $sKey, $this->aPageProps, 60*15 
);// invalidates cache after 15 minutes
                }
-
                $this->bIsLoaded = true;
        }
 
diff --git a/includes/utility/CacheHelper.class.php 
b/includes/utility/CacheHelper.class.php
new file mode 100644
index 0000000..4ca8317
--- /dev/null
+++ b/includes/utility/CacheHelper.class.php
@@ -0,0 +1,101 @@
+<?php
+/**
+ * This class contains methods working with mediawiki's cache .
+ *
+ * @copyright Copyright (c) 2007-2014, HalloWelt! Medienwerkstatt GmbH, All 
rights reserved.
+ * @author Stefan Widmann <widm...@hallowelt.biz>
+ * @version 0.1.0 beta
+ */
+class BsCacheHelper {
+
+       protected static $aCacheKeys = array();
+       protected static $oCache = null;
+
+       public static function getCache() {
+               if( self::$oCache === null ) {
+                       self::$oCache = wfGetCache( CACHE_ANYTHING );
+               }
+
+               return self::$oCache;
+       }
+
+       public static function getCacheKey( /*...*/ ) {
+               $args = func_get_args();
+               $sKey = call_user_func_array( 'wfMemcKey', $args );
+               self::$aCacheKeys[] = $sKey;
+
+               return $sKey;
+       }
+
+       public static function get( $sKey ) {
+               return self::getCache()->get( $sKey );
+       }
+
+       public static function set( $sKey, $mData, $iExpiryTime = 0 ) {
+               return self::getCache()->set( $sKey, $mData, $iExpiryTime );
+       }
+
+       public static function invalidateCache( $sKey ) {
+               if( is_array( $sKey ) ) {
+                       foreach( $sKey as $key ) {
+                               self::getCache()->delete( $key );
+                       }
+                       return true;
+               }
+               return self::getCache()->delete( $sKey );
+       }
+
+       public static function clearAllCaches() {
+               foreach( self::$aCacheKeys as $sKey ) {
+                       self::getCache()->delete( $sKey );
+               }
+       }
+
+       /**
+        * cache invalidation
+        * @param Article $article
+        * @param User $user
+        * @param Content $content
+        * @param type $summary
+        * @param bool $isMinor
+        * @param bool $isWatch
+        * @param type $section
+        * @param type $flags
+        * @param Revision $revision
+        * @param Status $status
+        * @param type $baseRevId
+        * @return boolean
+        */
+       public static function onPageContentSaveComplete( $article, $user, 
$content, $summary, $isMinor, $isWatch, $section, $flags, $revision, $status, 
$baseRevId ) {
+               //invalidate cache ArticleHelper::getDiscussionAmount
+               if( $article->getTitle()->isTalkPage() ) {
+                       BsCacheHelper::invalidateCache( 
BsCacheHelper::getCacheKey( 'BlueSpice', 'ArticleHelper', 
'getDiscussionAmount', $article->getTitle()->getArticleID() ) );
+               } else {
+                       $aKeys = array(
+                               // invalidate cache ArticleHelper::loadPageProps
+                               BsCacheHelper::getCacheKey( 'BlueSpice', 
'ArticleHelper', 'loadPageProps', $article->getTitle()->getArticleID() ),
+                               // invalidate cache WidgetListHelper::getWidgets
+                               BsCacheHelper::getCacheKey( 'BlueSpice', 
'WidgetListHelper', $article->getTitle()->getPrefixedDBkey() )
+                       );
+
+                       BsCacheHelper::invalidateCache( $aKeys );
+               }
+               return true;
+       }
+
+       /**
+        *
+        * @param BsConfig $oBsConfig
+        * @param type $aSettings
+        */
+       public static function onBsSettingsAfterSaveSettings( $oBsConfig, 
$aSettings ) {
+               $aKeys = array(
+                       BsCacheHelper::getCacheKey( 'BlueSpice', 'BsConfig', 
'loadSettings' )
+               );
+
+               BsCacheHelper::invalidateCache( $aKeys );
+
+               return true;
+       }
+
+}
\ No newline at end of file
diff --git a/includes/utility/WidgetListHelper.class.php 
b/includes/utility/WidgetListHelper.class.php
index 4b7275a..5533d88 100644
--- a/includes/utility/WidgetListHelper.class.php
+++ b/includes/utility/WidgetListHelper.class.php
@@ -50,7 +50,7 @@
        /**
         * N-glton pattern implementation to prevent multiple parsing.
         * @param Title $oTitle
-        * @return BsWidgetListHelper 
+        * @return BsWidgetListHelper
         */
        public static function getInstanceForTitle( $oTitle ){
                $sTitleKey = $oTitle->getPrefixedDBkey();
@@ -76,11 +76,21 @@
                        return $this->aWidgetList;
                }
 
-               // TODO MRG (01.07.11 02:20): Maybe this could be stored in an 
object cache. Question is, however, when to invalidate.
-               $oArticle           = new Article( $this->oTitle, 0 ); //New: 
Fetch current revision
-               $sArticleContent    = $oArticle->fetchContent( 0 ); //Old 
(<1.18): Fetch current revision
-               // TODO MRG (01.07.11 02:16): Careful: this does not allow 
nested noincludes. However, these dont make sense anyways
-               $sArticleContent    = preg_replace( 
'#<noinclude>.*?<\/noinclude>#si', '', $sArticleContent );
+               $sKey = BsCacheHelper::getCacheKey( 'BlueSpice', 
'WidgetListHelper', $this->oTitle->getPrefixedDBkey() );
+               $aData = BsCacheHelper::get( $sKey );
+
+               if( $aData !== false ) {
+                       wfDebugLog( 'BsMemcached', __CLASS__.': Fetching 
WidgetList page content from cache' );
+                       $sArticleContent = $aData;
+               } else {
+                       wfDebugLog( 'BsMemcached', __CLASS__.': Fetching 
WidgetList page content from DB' );
+                       $oWikiPage = WikiPage::factory( $this->oTitle );
+                       $sArticleContent = 
$oWikiPage->getContent()->getNativeData();
+                       $sArticleContent    = preg_replace( 
'#<noinclude>.*?<\/noinclude>#si', '', $sArticleContent );
+
+                       BsCacheHelper::set( $sKey, $sArticleContent );
+               }
+
                if( empty ( $sArticleContent ) ) {
                        $this->aWidgetList = array();
                        return $this->aWidgetList;
diff --git a/resources/bluespice.extjs/Ext.ux/form/ItemSelector.js 
b/resources/bluespice.extjs/Ext.ux/form/ItemSelector.js
index a0efb0d..6a55109 100644
--- a/resources/bluespice.extjs/Ext.ux/form/ItemSelector.js
+++ b/resources/bluespice.extjs/Ext.ux/form/ItemSelector.js
@@ -70,7 +70,7 @@
                 return null;
             },
             getModelData: function(){
-                return null;    
+                return null;
             },
             flex: 1,
             dragGroup: me.ddGroup,
@@ -137,11 +137,11 @@
 
     /**
      * Get the selected records from the specified list.
-     * 
+     *
      * Records will be returned *in store order*, not in order of selection.
      * @param {Ext.view.BoundList} list The list to read selections from.
      * @return {Ext.data.Model[]} The selected records in store order.
-     * 
+     *
      */
     getSelections: function(list) {
         var store = list.getStore();
@@ -169,7 +169,7 @@
         store.insert(0, selected);
         store.resumeEvents();
         list.refresh();
-        this.syncValue(); 
+        this.syncValue();
         list.getSelectionModel().select(selected);
     },
 
@@ -270,7 +270,7 @@
 
     // Synchronizes the submit value with the current state of the toStore
     syncValue: function() {
-        var me = this; 
+        var me = this;
         me.mixins.field.setValue.call(me, 
me.setupValue(me.toField.store.getRange()));
     },
 
@@ -327,7 +327,7 @@
         Ext.suspendLayouts();
         fromField.boundList.refresh();
         toField.boundList.refresh();
-        Ext.resumeLayouts(true);        
+        Ext.resumeLayouts(true);
     },
 
     onBindStore: function(store, initial) {

-- 
To view, visit https://gerrit.wikimedia.org/r/148354
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I4b7f6830493a213e07440189656eb0a95f9f2c77
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/BlueSpiceFoundation
Gerrit-Branch: master
Gerrit-Owner: Swidmann <widm...@hallowelt.biz>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to