jenkins-bot has submitted this change and it was merged.

Change subject: BSApiFileBackendStore
......................................................................


BSApiFileBackendStore

* Added BSApiExtJSStoreFileBackend
* Improvemnts to BSApiExtJSStoreBase

PatchSet 2:
* Renamed API module to 'bs-filebackend-store'
* Implemented new sort mechanism to BSApiExtJSStoreBase for better performance

PatchSet 3:
* Added processing af query param

PatchSet 4:
* Added default setting for $wgThumbnailScriptPath for later use
* Changed quering of categories to be less resource hungry
* Now using search index table to case insensitive 'query'

PatchSet 5:
* Improved performance by using file object factory from local repo
instead of wfFindFile (which needs to determin the filerepo first) This
should also word with other LocalFileRepos like NSFileRepo

Change-Id: Iaee62adc811e20f9ad7b8ebcc600119f103a070d
---
M BlueSpiceFoundation.php
M includes/AutoLoader.php
M includes/DefaultSettings.php
M includes/api/BSApiExtJSStoreBase.php
A includes/api/BSApiFileBackendStore.php
5 files changed, 167 insertions(+), 5 deletions(-)

Approvals:
  Robert Vogel: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/BlueSpiceFoundation.php b/BlueSpiceFoundation.php
index 68fe925..3b8e5e6 100644
--- a/BlueSpiceFoundation.php
+++ b/BlueSpiceFoundation.php
@@ -65,6 +65,8 @@
 $wgAjaxExportList[] = 'BsCommonAJAXInterface::getFileUrl';
 $wgAjaxExportList[] = 'BsCore::ajaxBSPing';
 
+$wgAPIModules['bs-filebackend-store'] = 'BSApiFileBackendStore';
+
 //I18N MW1.23+
 $wgMessagesDirs['BlueSpice'] = __DIR__ . '/i18n/core';
 $wgMessagesDirs['BlueSpiceCredits'] = __DIR__ . '/i18n/credits';
diff --git a/includes/AutoLoader.php b/includes/AutoLoader.php
index ffadfb5..99d11e9 100644
--- a/includes/AutoLoader.php
+++ b/includes/AutoLoader.php
@@ -55,6 +55,7 @@
 $GLOBALS['wgAutoloadClasses']['BSApiBase'] = __DIR__."/api/BSApiBase.php";
 $GLOBALS['wgAutoloadClasses']['BSApiTasksBase'] = 
__DIR__."/api/BSApiTasksBase.php";
 $GLOBALS['wgAutoloadClasses']['BSApiExtJSStoreBase'] = 
__DIR__."/api/BSApiExtJSStoreBase.php";
+$GLOBALS['wgAutoloadClasses']['BSApiFileBackendStore'] = 
__DIR__."/api/BSApiFileBackendStore.php";
 
 //adapter
 $GLOBALS['wgAutoloadClasses']['BsExtensionMW'] = 
__DIR__."/ExtensionMW.class.php";
diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php
index 13679c1..fd72d36 100644
--- a/includes/DefaultSettings.php
+++ b/includes/DefaultSettings.php
@@ -42,6 +42,7 @@
 $wgUrlProtocols[] = "file://";
 $wgVerifyMimeType = false;
 $wgAllowJavaUploads = true;
+$wgThumbnailScriptPath = "{$wgScriptPath}/thumb{$wgScriptExtension}"; //Enable 
on demand thumb rendering
 
 //wgScriptPath relative paths
 $sResourcesPath = '/extensions/BlueSpiceFoundation/resources';
diff --git a/includes/api/BSApiExtJSStoreBase.php 
b/includes/api/BSApiExtJSStoreBase.php
index 9e40541..0388378 100644
--- a/includes/api/BSApiExtJSStoreBase.php
+++ b/includes/api/BSApiExtJSStoreBase.php
@@ -176,7 +176,10 @@
         * @return array
         */
        public function postProcessData( $aData ) {
-               wfRunHooks( 'BSApiExtJSStoreBaseBeforePostProcessData', array( 
$this, &$aData ) );
+               if( !wfRunHooks( 'BSApiExtJSStoreBaseBeforePostProcessData', 
array( $this, &$aData ) ) ) {
+                       return $aData;
+               }
+
                $aProcessedData = array();
 
                //First, apply filter
@@ -184,7 +187,8 @@
                wfRunHooks( 'BSApiExtJSStoreBaseAfterFilterData', array( $this, 
&$aProcessedData ) );
 
                //Next, apply sort
-               usort($aProcessedData, array( $this, 'sortCallback') );
+               //usort($aProcessedData, array( $this, 'sortCallback') ); <-- 
had some performance issues
+               $aProcessedData = $this->sortData( $aProcessedData );
 
                //Before we trim, we save the count
                $this->iFinalDataSetCount = count( $aProcessedData );
@@ -197,6 +201,7 @@
 
        /**
         * Applies all sorters provided by the store
+        * --> has performance issues on large dataset; Code kept for 
documentation
         * @param object $oA
         * @param object $oB
         * @return int
@@ -210,16 +215,21 @@
 
                        if( $oA->$sProperty !== $oB->$sProperty ) {
                                if( $sDirection === 'ASC' ) {
-                                       return $oA->$sProperty > 
$oB->$sProperty ? -1 : 1;
+                                       return $oA->$sProperty < 
$oB->$sProperty ? -1 : 1;
                                }
                                else { //'DESC'
-                                       return $oA->$sProperty < 
$oB->$sProperty ? -1 : 1;
+                                       return $oA->$sProperty > 
$oB->$sProperty ? -1 : 1;
                                }
                        }
                }
                return 0;
        }
 
+       /**
+        *
+        * @param object $aDataSet
+        * @return boolean
+        */
        public function filterCallback( $aDataSet ) {
                $aFilter = $this->getParameter('filter');
                foreach( $aFilter as $oFilter ) {
@@ -239,6 +249,12 @@
                return true;
        }
 
+       /**
+        * Performs string filtering based on given filter of type string on a 
dataset
+        * @param object $oFilter
+        * @param oject $aDataSet
+        * @return boolean true if filter applies, false if not
+        */
        public function filterString($oFilter, $aDataSet) {
                $sFieldValue = $aDataSet->{$oFilter->field};
                $sFilterValue = $oFilter->value;
@@ -264,10 +280,16 @@
                }
        }
 
+       /**
+        * Applies pagination on the result
+        * @param array $aProcessedData The filtered result
+        * @return array a trimmed version of the result
+        */
        public function trimData($aProcessedData) {
                $iStart = $this->getParameter('start');
                $iEnd = $this->getParameter('limit') + $iStart;
-               if( $iEnd >= $this->iFinalDataSetCount ) {
+
+               if( $iEnd >= $this->iFinalDataSetCount || $iEnd === 0 ) {
                        $iEnd = $this->iFinalDataSetCount - 1;
                }
 
@@ -278,4 +300,36 @@
 
                return $aTrimmedData;
        }
+
+       /**
+        * Performs fast sorting on the results. Thanks at user "pigpen"
+        * @param array $aProcessedData
+        * @return array The sorted results
+        */
+       public function sortData($aProcessedData) {
+               $aSort = $this->getParameter('sort');
+               $iCount = count( $aSort );
+               for( $i = 0; $i < $iCount; $i++ ) {
+                       $sProperty = $aSort[$i]->property;
+                       $sDirection = strtoupper( $aSort[$i]->direction );
+                       $a{$sProperty} = array();
+                       foreach( $aProcessedData as $iKey => $aDataSet ) {
+                               $a{$sProperty}[$iKey] = $aDataSet->{$sProperty};
+                       }
+
+                       $aParams[] = $a{$sProperty};
+                       $aParams[] = SORT_NATURAL; //We might tweak this 
depending on the data type of the field. Mabye we should make some "getSort( 
$fieldName )" method
+                       if( $sDirection === 'ASC' ) {
+                               $aParams[] = SORT_ASC;
+                       }
+                       else {
+                               $aParams[] = SORT_DESC;
+                       }
+               }
+               $aParams[] = &$aProcessedData;
+
+               call_user_func_array( 'array_multisort', $aParams );
+               return $aProcessedData;
+       }
+
 }
diff --git a/includes/api/BSApiFileBackendStore.php 
b/includes/api/BSApiFileBackendStore.php
new file mode 100644
index 0000000..b187d88
--- /dev/null
+++ b/includes/api/BSApiFileBackendStore.php
@@ -0,0 +1,104 @@
+<?php
+
+class BSApiFileBackendStore extends BSApiExtJSStoreBase {
+
+       public function makeData() {
+               $oDbr = wfGetDB( DB_SLAVE );
+
+               $aContidions = array(
+                       'page_namespace' => NS_FILE,
+                       'page_title = img_name',
+                       'page_id = si_page' //Needed for case insensitive 
quering; Maybe implement 'query' as a implicit filter on 'img_name' field?
+               );
+
+               $sQuery = $this->getParameter( 'query' );
+               if( !empty($sQuery) ) {
+                       $aContidions[] = "si_title ".$oDbr->buildLike(
+                               $oDbr->anyString(),
+                               $sQuery,
+                               $oDbr->anyString()
+                       );
+               }
+
+               $oImgRes = $oDbr->select(
+                       array( 'image', 'page', 'searchindex' ),
+                       '*',
+                       $aContidions,
+                       __METHOD__
+               );
+
+               $bUseSecureFileStore = BsExtensionManager::isContextActive( 
'MW::SecureFileStore::Active' );
+
+               //First query: Get all files and their pages
+               $aReturn = array();
+               foreach( $oImgRes as $oRow ) {
+                       try {
+                               $oImg = 
RepoGroup::singleton()->getLocalRepo()->newFileFromRow( $oRow );
+                       } catch (Exception $ex) {
+                               continue;
+                       }
+
+                       //TODO: use 'thumb.php'?
+                       $sThumb = $oImg->createThumb( 48, 48 );
+                       if( $bUseSecureFileStore ) {
+                               $sThumb = SecureFileStore::secureStuff( 
$sThumb, true );
+                       }
+                       $oRow->img_metadata = unserialize( $oRow->img_metadata 
);
+                       $oRow->img_thumbnail = $sThumb;
+                       $oRow->categories = array();
+
+                       $aReturn[ $oRow->page_id ] = $oRow;
+               }
+
+               //Second query: Get all categories of each file page
+               $aPageIds = array_keys( $aReturn );
+               $oCatRes = $oDbr->select(
+                       'categorylinks',
+                       array( 'cl_from', 'cl_to' ),
+                       array( 'cl_from' => $aPageIds )
+               );
+               foreach( $oCatRes as $oCatRow ) {
+                       $aReturn[$oCatRow->cl_from]->categories[] = 
$oCatRow->cl_to;
+               }
+
+               return array_values( $aReturn );
+               //wfRunHooks( 'BSInsertFileGetFilesBeforeQuery', array( 
&$aConds, &$aNameFilters ) );
+       }
+
+       public function filterCallback( $aDataSet ) {
+               $aFilter = $this->getParameter('filter');
+               foreach( $aFilter as $oFilter ) {
+                       if( $oFilter->type != 'categories' ) {
+                               continue;
+                       }
+                       if( !$this->filterCategories($oFilter, $aDataSet) ) {
+                               return false;
+                       }
+               }
+               return parent::filterCallback($aDataSet);
+       }
+
+       public function filterCategories($oFilter, $aDataSet) {
+               $aFieldValue = $aDataSet->{$oFilter->field};
+               $aFilterValue = $oFilter->value;
+
+               switch( $oFilter->comparison ) {
+                       case 'ct':
+                               foreach($aFilterValue as $sValue) {
+                                       if( in_array($sValue, $aFieldValue) ) {
+                                               continue;
+                                       }
+                                       return false;
+                               }
+                               return true;
+                       case 'nct':
+                               foreach($aFilterValue as $sValue) {
+                                       if( !in_array($sValue, $aFieldValue) ) {
+                                               continue;
+                                       }
+                                       return false;
+                               }
+                               return true;
+               }
+       }
+}

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

Gerrit-MessageType: merged
Gerrit-Change-Id: Iaee62adc811e20f9ad7b8ebcc600119f103a070d
Gerrit-PatchSet: 6
Gerrit-Project: mediawiki/extensions/BlueSpiceFoundation
Gerrit-Branch: master
Gerrit-Owner: Pwirth <[email protected]>
Gerrit-Reviewer: Mglaser <[email protected]>
Gerrit-Reviewer: Robert Vogel <[email protected]>
Gerrit-Reviewer: Tweichart <[email protected]>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to