API: Allow generators to return data
It has long been requested that list=search and list=prefixsearch be able to indicate the search result ordering when used as generators. This change introduces a generic mechanism to allow for generators to specify additional page data. Bug: T16859 Bug: T75623 Change-Id: I115338d2bd890ccc109a79c65f92099c0d41fc2d
This commit is contained in:
parent
7efc2a1f61
commit
e2055fe0a5
5 changed files with 113 additions and 0 deletions
|
|
@ -101,6 +101,11 @@ production.
|
|||
* (bug 66776) format=json results will no longer be corrupted when
|
||||
$wgMangleFlashPolicy is in effect. format=php results will cleanly return an
|
||||
error instead of returning invalid serialized data.
|
||||
* Generators may now return data for the generated pages when used with
|
||||
action=query.
|
||||
* Query page data for generator=search and generator=prefixsearch will now
|
||||
include an "index" field, which may be used by the client for sorting the
|
||||
search results.
|
||||
|
||||
=== Action API internal changes in 1.25 ===
|
||||
* ApiHelp has been rewritten to support i18n and paginated HTML output.
|
||||
|
|
@ -130,6 +135,8 @@ production.
|
|||
revisions as "good" if the user has the 'deletedhistory' right. New methods
|
||||
ApiPageSet::getLiveRevisionIDs() and ApiPageSet::getDeletedRevisionIDs() are
|
||||
provided to access just the live or just the deleted revids.
|
||||
* Added ApiPageSet::setGeneratorData() and ApiPageSet::populateGeneratorData()
|
||||
to allow generators to include data in the action=query result.
|
||||
* The following methods have been deprecated and may be removed in a future
|
||||
release:
|
||||
* ApiBase::getDescription
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@ class ApiPageSet extends ApiBase {
|
|||
private $mLiveRevIDs = array();
|
||||
private $mDeletedRevIDs = array();
|
||||
private $mMissingRevIDs = array();
|
||||
private $mGeneratorData = array(); // [ns][dbkey] => data array
|
||||
private $mFakePageId = -1;
|
||||
private $mCacheMode = 'public';
|
||||
private $mRequestedPageFields = array();
|
||||
|
|
@ -1173,6 +1174,100 @@ class ApiPageSet extends ApiBase {
|
|||
return $linkBatch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set data for a title.
|
||||
*
|
||||
* This data may be extracted into an ApiResult using
|
||||
* self::populateGeneratorData. This should generally be limited to
|
||||
* data that is likely to be particularly useful to end users rather than
|
||||
* just being a dump of everything returned in non-generator mode.
|
||||
*
|
||||
* Redirects here will *not* be followed, even if 'redirects' was
|
||||
* specified, since in the case of multiple redirects we can't know which
|
||||
* source's data to use on the target.
|
||||
*
|
||||
* @param Title $title
|
||||
* @param array $data
|
||||
*/
|
||||
public function setGeneratorData( Title $title, array $data ) {
|
||||
$ns = $title->getNamespace();
|
||||
$dbkey = $title->getDBkey();
|
||||
$this->mGeneratorData[$ns][$dbkey] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate the generator data for all titles in the result
|
||||
*
|
||||
* The page data may be inserted into an ApiResult object or into an
|
||||
* associative array. The $path parameter specifies the path within the
|
||||
* ApiResult or array to find the "pages" node.
|
||||
*
|
||||
* The "pages" node itself must be an associative array mapping the page ID
|
||||
* or fake page ID values returned by this pageset (see
|
||||
* self::getAllTitlesByNamespace() and self::getSpecialTitles()) to
|
||||
* associative arrays of page data. Each of those subarrays will have the
|
||||
* data from self::setGeneratorData() merged in.
|
||||
*
|
||||
* Data that was set by self::setGeneratorData() for pages not in the
|
||||
* "pages" node will be ignored.
|
||||
*
|
||||
* @param ApiResult|array &$result
|
||||
* @param array $path
|
||||
* @return boolean Whether the data fit
|
||||
*/
|
||||
public function populateGeneratorData( &$result, array $path = array() ) {
|
||||
if ( $result instanceof ApiResult ) {
|
||||
$data = $result->getData();
|
||||
} else {
|
||||
$data = &$result;
|
||||
}
|
||||
foreach ( $path as $key ) {
|
||||
if ( !isset( $data[$key] ) ) {
|
||||
// Path isn't in $result, so nothing to add, so everything
|
||||
// "fits"
|
||||
return true;
|
||||
}
|
||||
$data = &$data[$key];
|
||||
}
|
||||
foreach ( $this->mGeneratorData as $ns => $dbkeys ) {
|
||||
if ( $ns === -1 ) {
|
||||
$pages = array();
|
||||
foreach ( $this->mSpecialTitles as $id => $title ) {
|
||||
$pages[$title->getDBkey()] = $id;
|
||||
}
|
||||
} else {
|
||||
if ( !isset( $this->mAllPages[$ns] ) ) {
|
||||
// No known titles in the whole namespace. Skip it.
|
||||
continue;
|
||||
}
|
||||
$pages = $this->mAllPages[$ns];
|
||||
}
|
||||
foreach ( $dbkeys as $dbkey => $genData ) {
|
||||
if ( !isset( $pages[$dbkey] ) ) {
|
||||
// Unknown title. Forget it.
|
||||
continue;
|
||||
}
|
||||
$pageId = $pages[$dbkey];
|
||||
if ( !isset( $data[$pageId] ) ) {
|
||||
// $pageId didn't make it into the result. Ignore it.
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( $result instanceof ApiResult ) {
|
||||
$path2 = array_merge( $path, array( $pageId ) );
|
||||
foreach ( $genData as $key => $value ) {
|
||||
if ( !$result->addValue( $path2, $key, $value ) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$data[$pageId] = array_merge( $data[$pageId], $genData );
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the database connection (read-only)
|
||||
* @return DatabaseBase
|
||||
|
|
|
|||
|
|
@ -437,6 +437,8 @@ class ApiQuery extends ApiBase {
|
|||
}
|
||||
|
||||
if ( count( $pages ) ) {
|
||||
$pageSet->populateGeneratorData( $pages );
|
||||
|
||||
if ( $this->mParams['indexpageids'] ) {
|
||||
$pageIDs = array_keys( $pages );
|
||||
// json treats all map keys as strings - converting to match
|
||||
|
|
|
|||
|
|
@ -48,6 +48,11 @@ class ApiQueryPrefixSearch extends ApiQueryGeneratorBase {
|
|||
$titles = $searcher->searchWithVariants( $search, $limit, $namespaces );
|
||||
if ( $resultPageSet ) {
|
||||
$resultPageSet->populateFromTitles( $titles );
|
||||
/** @todo If this module gets an 'offset' parameter, use it here */
|
||||
$offset = 1;
|
||||
foreach ( $titles as $index => $title ) {
|
||||
$resultPageSet->setGeneratorData( $title, array( 'index' => $index + $offset ) );
|
||||
}
|
||||
} else {
|
||||
$result = $this->getResult();
|
||||
foreach ( $titles as $title ) {
|
||||
|
|
|
|||
|
|
@ -259,6 +259,10 @@ class ApiQuerySearch extends ApiQueryGeneratorBase {
|
|||
}
|
||||
} else {
|
||||
$resultPageSet->populateFromTitles( $titles );
|
||||
$offset = $params['offset'] + 1;
|
||||
foreach ( $titles as $index => $title ) {
|
||||
$resultPageSet->setGeneratorData( $title, array( 'index' => $index + $offset ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue