Robert Vogel has uploaded a new change for review.

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

Change subject: [WIP] Setting up new extension
......................................................................

[WIP] Setting up new extension

This is the first change. The extension does not work yet

Change-Id: I204ad7bce1d7ee8c03d2cdfda87f0d9fec69225a
---
A .gitignore
A BSExtendedSearch.php
A composer.json
A includes/api/BSApiQueryExtendedSearch.php
4 files changed, 244 insertions(+), 0 deletions(-)


  git pull 
ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/BSExtendedSearch 
refs/changes/43/219143/1

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..22d0d82
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+vendor
diff --git a/BSExtendedSearch.php b/BSExtendedSearch.php
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/BSExtendedSearch.php
diff --git a/composer.json b/composer.json
new file mode 100644
index 0000000..0b6af31
--- /dev/null
+++ b/composer.json
@@ -0,0 +1,5 @@
+{
+    "require": {
+        "solarium/solarium": "dev-master"
+    }
+}
diff --git a/includes/api/BSApiQueryExtendedSearch.php 
b/includes/api/BSApiQueryExtendedSearch.php
new file mode 100644
index 0000000..0a94d33
--- /dev/null
+++ b/includes/api/BSApiQueryExtendedSearch.php
@@ -0,0 +1,238 @@
+<?php
+
+/**
+ * TODO: Implement as subclass of BSApiExtJSStoreBase and map ExtJS Store
+ * filters to Solr filterQuery-feature
+ */
+class BSApiQueryExtendedSearch extends ApiBase {
+       protected $root = 'results';
+       protected $totalProperty = 'total';
+
+       /**
+       * @var Solarium\QueryType\Select\Query\Query
+       */
+       protected $query = null;
+
+       /**
+       * @var \Solarium\QueryType\Select\Query\Component\EdisMax
+       */
+       protected $edismax = null;
+
+       /**
+       * @var 
Solarium\QueryType\Select\Query\Component\Highlighting\Highlighting
+       */
+       protected $hl = null;
+
+       public function execute() {
+               global $bsgExtendedSearchDefaultEDisMaxQueryFields;
+               $aSearchParams = $this->getParameter( 'searchParams' );
+               if( !isset( $aSearchParams['qf'] ) ) {
+                       $aSearchParams['qf'] = 
$bsgExtendedSearchDefaultEDisMaxQueryFields; //Array
+               }
+
+               wfRunHooks( 'BSApiQueryExtendedSearchBeforeExecute', array( 
$this, &$aSearchParams ) );
+
+               $client = $this->makeClient();
+               $this->query = $this->makeQuery( $client );
+               $this->edismax = $this->query->getEDisMax();
+               $this->edismax->setQueryFields( $this->makeQueryFields( 
$aSearchParams ) );
+               $this->makeFilterQueries( $this->query, $aSearchParams );
+
+               $this->query
+                       ->setQuery( $this->getParameter('query') ) // '*:*' is 
not supported by eDisMax
+                       ->setStart( $this->getParameter('start') )
+                       ->setRows( $this->getParameter('limit') );
+
+               $this->hl = $this->query->getHighlighting();
+               //TODO: use setOptions to allow more extensability
+               $this->hl->setFields('title, text');
+               $this->hl->setSnippets(3);
+               $this->hl->setSimplePrefix('<span 
class="bs-extendedsearch-highlight">');
+               $this->hl->setSimplePostfix('</span>');
+
+               $resultset = $client->execute($this->query);
+
+               $aData = array();
+               foreach( $resultset as $document ) {
+                       $aData[] = $this->makeResultRow( $document, $resultset 
);
+               }
+
+               $result = $this->getResult();
+               $result->setIndexedTagName( $aData, $this->root );
+               $result->addValue( null, $this->root, $aData );
+               $result->addValue( null, 'facetts', array() ); //TODO: 
Implement for facetted quieries!
+               $result->addValue( null, $this->totalProperty, 
$resultset->getNumFound() );
+       }
+
+       public function getAllowedParams() {
+               return array(
+                       'searchParams' => array(
+                               ApiBase::PARAM_TYPE => 'string',
+                               ApiBase::PARAM_REQUIRED => false,
+                               ApiBase::PARAM_DFLT => '{}'
+                       ),
+                       'query' => array(
+                               ApiBase::PARAM_TYPE => 'string',
+                               ApiBase::PARAM_REQUIRED => true
+                       ),
+                       'start' => array(
+                               ApiBase::PARAM_TYPE => 'integer',
+                               ApiBase::PARAM_REQUIRED => false,
+                               ApiBase::PARAM_DFLT => 0
+                       ),
+                       'limit' => array(
+                               ApiBase::PARAM_TYPE => 'integer',
+                               ApiBase::PARAM_REQUIRED => false,
+                               ApiBase::PARAM_DFLT => 5
+                       ),
+                       'format' => array(
+                               ApiBase::PARAM_DFLT => 'json',
+                               ApiBase::PARAM_REQUIRED => true,
+                               ApiBase::PARAM_TYPE => array( 'json', 'jsonfm' )
+                       )
+               );
+       }
+
+       public function getParamDescription() {
+               return array(
+                       'searchParams' => 'JSON string with parameters for 
SOLR. E.g filter querys "fq" in form "fieldname":value(s)',
+                       'query' => 'The query term for the search engine',
+                       'start' => 'The offset to start the result list from',
+                       'limit' => 'The number of items to return',
+                       'format' => 'The format of the output (only JSON or 
formatted JSON)'
+               );
+       }
+
+       protected function getParameterFromSettings($paramName, $paramSettings, 
$parseLimit) {
+               $value = parent::getParameterFromSettings($paramName, 
$paramSettings, $parseLimit);
+               //Unfortunately there is no way to register custom types for 
parameters
+               if( in_array( $paramName, array( 'searchParams' ) ) ) {
+                       $value = FormatJson::decode( $value, true );
+                       if( empty($value) ) {
+                               return array();
+                       }
+               }
+               return $value;
+       }
+
+       /**
+        *
+        * @param \Solarium\QueryType\Select\Result\Document $document
+        * @param \Solarium\Core\Query\Result\ResultInterface $resultset
+        * @return array
+        */
+       public function makeResultRow( $document, $resultset ) {
+               $oFormatter = $this->makeFormatter( $document->overall_type );
+               return $oFormatter->format( $document, $resultset, 
$this->getFinalParams() );
+       }
+
+       /**
+        *
+        * @param Solarium\Client $client
+        * @return Solarium\QueryType\Select\Query\Query
+        */
+       protected function makeQuery( $client ) {
+               return $client->createQuery( Solarium\Client::QUERY_SELECT );
+       }
+
+       protected function makeClient() {
+               $sUrl = BsConfig::get( 'MW::ExtendedSearch::SolrServiceUrl' );
+               $aUrl = wfParseUrl( $sUrl.'/bluespice' );
+
+               return new Solarium\Client( array(
+                       'endpoint' => array(
+                               'localhost' => $aUrl
+                       )
+               ) );
+       }
+
+       /**
+        *
+        * @param Solarium\QueryType\Select\Query\Query $query
+        */
+       protected function makeFilterQueries( $query, $aSearchParams ) {
+               //Implicit filter: wiki ID for shared indices!
+               $query->createFilterQuery('wiki')->setQuery( 
'wiki:'.BsConfig::get( 'MW::ExtendedSearch::CustomerID' ) );
+
+               //Implicit filter: readable namespaces!
+               $aReadableNamespaces = $this->getReadableNamespaces(); //TODO: 
Use BSF method when available!
+               $aFilterQueries = array();
+               if( isset($aSearchParams['fq']) ) {
+                       $aFilterQueries = $aSearchParams['fq'];
+               }
+               if( isset( $aFilterQueries['namespace'] ) ) {
+                       $aFilterQueries['namespace'] = array_intersect( 
$aReadableNamespaces, $aFilterQueries['namespace'] );
+               }
+               else {
+                       $aFilterQueries['namespace'] = $aReadableNamespaces;
+               }
+
+               foreach( $aFilterQueries as $sFieldname => $mValue ) {
+                       if( is_array( $mValue ) ) {
+                               $sFilterQuery = $sFieldname.':('.implode( ' ', 
$mValue ).')';
+                               $query->createFilterQuery( $sFieldname 
)->setQuery( $sFilterQuery );
+                       }
+                       else {
+                               $sFilterQuery = $sFieldname.':'.$mValue;
+                       }
+               }
+       }
+
+       protected function getReadableNamespaces() {
+               $aNamespaces = $this->getLanguage()->getNamespaceIds();
+               $aReadableNS = array();
+               foreach( $aNamespaces as $iNsId ) {
+                       $oTitle = Title::makeTitle( $iNsId, 'X' );
+                       if( $oTitle->userCan( 'read' ) ) {
+                               $aReadableNS[] = $iNsId;
+                       }
+               }
+               return $aReadableNS;
+       }
+
+       /**
+        *
+        * @global array $bsgExtendedSearchAPIFormatters
+        * @param string $sOverallType
+        * @return BSExtendedSearchApiFormatterBase
+        * @throws InvalidArgumentException
+        */
+       public function makeFormatter( $sOverallType ) {
+               global $bsgExtendedSearchAPIFormatters;
+               if( !isset( $bsgExtendedSearchAPIFormatters[$sOverallType] ) ) {
+                       //TODO: Or shall we fall back to 
'BSExtendedSearchApiFormatterBase'?
+                       throw new InvalidArgumentException( 'No formatter for 
overall_type "'.$sOverallType.'" found!' );
+               }
+
+               return new $bsgExtendedSearchAPIFormatters[$sOverallType]();
+       }
+
+       /**
+        *
+        * @param array $aSearchParams
+        * @return string
+        */
+       public function makeQueryFields( $aSearchParams ) {
+               $sQueryFields = '';
+               if( !isset( $aSearchParams['qf'] ) ) {
+                       return '';
+               }
+               if( is_string( $aSearchParams['qf'] ) ) {
+                       return $aSearchParams['qf'];
+               }
+
+               $aFieldBoosts = array();
+               foreach( $aSearchParams['qf'] as $sFieldName => $iBoost ) {
+                       $sFieldBoost = $sFieldName;
+                       if(is_numeric($iBoost)) {
+                               $sFieldBoost .= '^'.$iBoost;
+                       }
+
+                       $aFieldBoosts[] = $sFieldBoost;
+               }
+               $sQueryFields = implode( ' ', $aFieldBoosts );
+
+               return $sQueryFields;
+       }
+
+}
\ No newline at end of file

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: I204ad7bce1d7ee8c03d2cdfda87f0d9fec69225a
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/BSExtendedSearch
Gerrit-Branch: master
Gerrit-Owner: Robert Vogel <vo...@hallowelt.biz>

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

Reply via email to