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