jenkins-bot has submitted this change and it was merged. Change subject: Add api action for listing collections of a user ......................................................................
Add api action for listing collections of a user Sandbox test url: http://localhost:8080/w/index.php?title=Special:ApiSandbox&mobileaction=toggle_view_desktop#action=gather&format=json&owner=User (Change User with the user you want to see.) If user is not specified, it defaults to the logged in user. If the owner specified does not match the logged in user the collections list will only show the public ones. Changes: * Introduces ArraySerializable Bug: T91440 Change-Id: I6092d444af229e1b34ef35686a07ffbb1d12d1c2 --- M Gather.php M extension.json M i18n/en.json M i18n/qqq.json A includes/api/CollectionsListApi.php A includes/models/ArraySerializable.php M includes/models/Collection.php M includes/models/CollectionBase.php M includes/models/CollectionInfo.php M includes/models/CollectionItem.php M includes/models/WithImage.php M includes/stores/JSONPage.php 12 files changed, 163 insertions(+), 38 deletions(-) Approvals: Robmoen: Looks good to me, but someone else must approve Jdlrobson: Looks good to me, approved jenkins-bot: Verified diff --git a/Gather.php b/Gather.php index 800540a..d154ac7 100644 --- a/Gather.php +++ b/Gather.php @@ -38,6 +38,7 @@ 'Gather\models\CollectionInfo' => 'models/CollectionInfo', 'Gather\models\Collection' => 'models/Collection', 'Gather\models\WithImage' => 'models/WithImage', + 'Gather\models\ArraySerializable' => 'models/ArraySerializable', 'Gather\stores\JSONPage' => 'stores/JSONPage', 'Gather\stores\Collection' => 'stores/Collection', @@ -59,6 +60,9 @@ 'Gather\views\helpers\CSS' => 'views/helpers/CSS', 'Gather\SpecialGather' => 'specials/SpecialGather', + + 'Gather\api\CollectionsListApi' => 'api/CollectionsListApi', + ); foreach ( $autoloadClasses as $className => $classFilename ) { @@ -76,6 +80,9 @@ $wgHooks['ContentHandlerDefaultModelFor'][] = 'Gather\Hooks::onContentHandlerDefaultModelFor'; $wgHooks['SkinMinervaDefaultModules'][] = 'Gather\Hooks::onSkinMinervaDefaultModules'; +// Api +$wgAPIModules['gather'] = 'Gather\api\CollectionsListApi'; + // ResourceLoader modules require_once __DIR__ . "/resources/Resources.php"; diff --git a/extension.json b/extension.json index dd6670a..306664e 100644 --- a/extension.json +++ b/extension.json @@ -27,6 +27,7 @@ "Gather\\models\\CollectionInfo": "includes/models/CollectionInfo.php", "Gather\\models\\Collection": "includes/models/Collection.php", "Gather\\models\\WithImage": "includes/models/WithImage.php", + "Gather\\models\\ArraySerializable": "includes/models/ArraySerializable.php", "Gather\\stores\\Collection": "includes/stores/Collection.php", "Gather\\stores\\JSONPage": "includes/stores/JSONPage.php", "Gather\\stores\\WatchlistCollection": "includes/stores/WatchlistCollection.php", @@ -43,7 +44,8 @@ "Gather\\views\\CollectionsList": "includes/views/CollectionsList.php", "Gather\\views\\CollectionsListItemCard": "includes/views/CollectionsListItemCard.php", "Gather\\views\\helpers\\CSS": "includes/views/helpers/CSS.php", - "Gather\\SpecialGather": "includes/specials/SpecialGather.php" + "Gather\\SpecialGather": "includes/specials/SpecialGather.php", + "Gather\\api\\CollectionsListApi": "includes/api/CollectionsListApi.php" }, "ResourceModules": { "ext.gather.icons": { diff --git a/i18n/en.json b/i18n/en.json index 2caa2bb..2f02d94 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -17,5 +17,9 @@ "gather-private": "Private", "gather-article-count": "$1 {{PLURAL:$1|article|articles}}", "gather-empty": "Nothing in this collection yet...", - "gather-empty-footer": "I don't know how you got here but this is a sad place." + "gather-empty-footer": "I don't know how you got here but this is a sad place.", + "apihelp-gather-description": "List and edit gather collections.", + "apihelp-gather-param-gather": "Action to perform on collections.", + "apihelp-gather-param-owner": "Owner of the collections to search for. If omitted, defaults to current user.", + "apihelp-gather-example-1": "List the collections for user <kbd>john</kbd>." } diff --git a/i18n/qqq.json b/i18n/qqq.json index ca70159..f0215e1 100644 --- a/i18n/qqq.json +++ b/i18n/qqq.json @@ -19,5 +19,9 @@ "gather-private": "Note: Experimental feature. Messages and UI may change radically at any time. Translate at your own risk.\n Label for a collection when it is not publicly visible\n{{Identical|Private}}", "gather-article-count": "Note: Experimental feature. Messages and UI may change radically at any time. Translate at your own risk.\n Expression of the number of articles in a collection. Parameter:\n* $1 - number of articles in the collection\n{{Identical|Article}}", "gather-empty": "Note: Experimental feature. Messages and UI may change radically at any time. Translate at your own risk.\n Message shown on an empty rendered collection on [[Special:Gather]].", - "gather-empty-footer": "Note: Experimental feature. Messages and UI may change radically at any time. Translate at your own risk.\n Footnote shown on an empty rendered collection on [[Special:Gather]]." + "gather-empty-footer": "Note: Experimental feature. Messages and UI may change radically at any time. Translate at your own risk.\n Footnote shown on an empty rendered collection on [[Special:Gather]].", + "apihelp-gather-description": "{{doc-apihelp-description|gather}}", + "apihelp-gather-param-gather": "{{doc-apihelp-param|gather|gather}}", + "apihelp-gather-param-owner": "{{doc-apihelp-param|gather|owner}}", + "apihelp-gather-example-1": "{{doc-apihelp-example|gather}}" } diff --git a/includes/api/CollectionsListApi.php b/includes/api/CollectionsListApi.php new file mode 100644 index 0000000..102a5ed --- /dev/null +++ b/includes/api/CollectionsListApi.php @@ -0,0 +1,103 @@ +<?php + +/** + * CollectionsListApi.php + */ + +namespace Gather\api; + +use Gather\stores; +use Gather\models; +use ApiBase; +use User; + +// FIXME: ApiQueryGeneratorBase should be used here in future. +class CollectionsListApi extends ApiBase { + /** + * Execute the requested api actions + */ + public function execute() { + $this->getMain()->setCacheMode( 'anon-public-user-private' ); + $params = $this->extractRequestParams(); + $action = $params['gather']; + + // Get the list of collections for a user + if ( $action === 'list' ) { + // If an owner wasn't specified, then get the collections of the current user + $owner = isset( $params['owner'] ) ? + User::newFromName( $params['owner'] ) : $this->getUser(); + // If the name is invalid – it contains illegal characters then this'll return false + if ( $owner !== false ) { + $collections = $this->getCollectionsList( $owner ); + $res = array(); + foreach ( $collections as $collection ) { + $res[] = $collection->toArray(); + } + $this->addResult( $res, 'collection' ); + } + } + } + + /** + * Add a result to the response + * @param string $result result in json to add to the response + * @param string $tagName xml tagName in case it needs to be set + */ + private function addResult( $result, $tagName = null ) { + $apiResult = $this->getResult(); + if ( $tagName !== null ) { + $apiResult->setIndexedTagName( $result, $tagName ); + $apiResult->setIndexedTagName_recursive( $result, $tagName ); + } + $apiResult->addValue( null, $this->getModuleName(), $result ); + } + + /** + * Get the list of collections for a user + * @param User $owner Owner of the collections + * @return models\Collection[] + */ + protected function getCollectionsList( $owner ) { + $ownsCollection = $this->getUser()->getName() === $owner->getName(); + $collectionsListStore = new stores\UserPageCollectionsList( $owner, $ownsCollection ); + return $collectionsListStore->getLists(); + } + + /** + * Returns usage examples for this module. + * @see ApiBase::getExamplesMessages() + * @todo Fill up examples + */ + protected function getExamplesMessages() { + return array( + 'action=gather&owner=john' => 'gather-apihelp-list-example-1', + ); + } + + /** + * Returns the help url for this API + * @return string + * @todo Add specific section for the api to Extension:Gather in mw.org + */ + public function getHelpUrls() { + return 'https://www.mediawiki.org/wiki/Extension:Gather'; + } + + /** + * Get allowed API parameters + * @return array + */ + public function getAllowedParams() { + return array( + 'gather' => array( + ApiBase::PARAM_DFLT => 'list', + ApiBase::PARAM_TYPE => array( + 'list' + ) + ), + 'owner' => array( + ApiBase::PARAM_TYPE => 'user' + ) + ); + } +} diff --git a/includes/models/ArraySerializable.php b/includes/models/ArraySerializable.php new file mode 100644 index 0000000..6dda022 --- /dev/null +++ b/includes/models/ArraySerializable.php @@ -0,0 +1,15 @@ +<?php + +/** + * ArraySerializable.php + */ + +namespace Gather\models; + +interface ArraySerializable { + /** + * Serialise to PHP array structure. + */ + public function toArray(); +} + diff --git a/includes/models/Collection.php b/includes/models/Collection.php index e9234d6..e4f2c0e 100644 --- a/includes/models/Collection.php +++ b/includes/models/Collection.php @@ -66,14 +66,12 @@ return count( $this->items ); } - /** - * Serialise to JSON - */ - public function toJSON() { - $data = parent::toJSON(); + /** @inheritdoc */ + public function toArray() { + $data = parent::toArray(); $data['items'] = array(); foreach ( $this as $item ) { - $data['items'][] = $item->toJSON(); + $data['items'][] = $item->toArray(); } return $data; } diff --git a/includes/models/CollectionBase.php b/includes/models/CollectionBase.php index bc62222..66aad8f 100644 --- a/includes/models/CollectionBase.php +++ b/includes/models/CollectionBase.php @@ -13,7 +13,7 @@ /** * Base model for a Collection. */ -abstract class CollectionBase implements WithImage { +abstract class CollectionBase implements WithImage, ArraySerializable { /** * The internal id of a collection @@ -128,17 +128,15 @@ ->getLocalURL(); } - /** - * Serialise to JSON - */ - public function toJSON() { + /** @inheritdoc */ + public function toArray() { $data = array( 'id' => $this->id, 'owner' => $this->owner->getName(), 'title' => $this->title, 'description' => $this->description, 'public' => $this->public, - 'image' => $this->image->getTitle() + 'image' => $this->image ? $this->image->getTitle()->getText() : null ); return $data; } @@ -147,7 +145,7 @@ * @inheritdoc */ public function hasImage() { - return $this->image ? true : false; + return (bool)$this->image; } /** diff --git a/includes/models/CollectionInfo.php b/includes/models/CollectionInfo.php index f469c8c..3492456 100644 --- a/includes/models/CollectionInfo.php +++ b/includes/models/CollectionInfo.php @@ -32,11 +32,9 @@ return $this->count; } - /** - * Serialise to JSON - */ - public function toJSON() { - $data = parent::toJSON(); + /** @inheritdoc */ + public function toArray() { + $data = parent::toArray(); $data['count'] = $this->count; return $data; } diff --git a/includes/models/CollectionItem.php b/includes/models/CollectionItem.php index 193005c..51df206 100644 --- a/includes/models/CollectionItem.php +++ b/includes/models/CollectionItem.php @@ -12,7 +12,7 @@ * An item of a Collection. Similar to a Page and MobilePage, but with some * extra information like the extract and image. */ -class CollectionItem implements WithImage { +class CollectionItem implements WithImage, ArraySerializable { /** * @var Title: Title for page @@ -20,21 +20,21 @@ private $title; /** - * @var File Associated page image file (see PageImages extension) + * @var File|null Associated page image file (see PageImages extension) */ private $file; /** - * @var string Page extract + * @var string|null Page extract */ private $extract; /** * @param Title $title - * @param File|bool $file - * @param string|bool $extract + * @param File $file + * @param string $extract */ - public function __construct( Title $title, $file = false, $extract = false ) { + public function __construct( Title $title, $file, $extract ) { $this->title = $title; $this->file = $file; $this->extract = $extract; @@ -44,7 +44,7 @@ * @inheritdoc */ public function hasImage() { - return $this->file ? true : false; + return (bool)$this->file; } /** @@ -53,7 +53,7 @@ * @return Boolean */ public function hasExtract() { - return $this->extract ? true : false; + return $this->extract !== null && $this->extract !== ''; } /** @@ -77,14 +77,9 @@ return $this->file; } - /** - * Serialise to JSON - */ - public function toJSON() { - return array( - 'title' => $this->title, - 'extract' => $this->extract, - ); + /** @inheritdoc */ + public function toArray() { + return $this->title->getText(); } } diff --git a/includes/models/WithImage.php b/includes/models/WithImage.php index 28a9960..884e3f3 100644 --- a/includes/models/WithImage.php +++ b/includes/models/WithImage.php @@ -20,7 +20,7 @@ public function hasImage(); /** - * @return File|bool Get the file from this item + * @return File Get the file from this item */ public function getFile(); } diff --git a/includes/stores/JSONPage.php b/includes/stores/JSONPage.php index f77ddc6..0bb168f 100644 --- a/includes/stores/JSONPage.php +++ b/includes/stores/JSONPage.php @@ -6,6 +6,7 @@ namespace Gather\stores; +use \Title; use \WikiPage; use \FormatJson; -- To view, visit https://gerrit.wikimedia.org/r/193349 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: I6092d444af229e1b34ef35686a07ffbb1d12d1c2 Gerrit-PatchSet: 21 Gerrit-Project: mediawiki/extensions/Gather Gerrit-Branch: master Gerrit-Owner: Jhernandez <[email protected]> Gerrit-Reviewer: Anomie <[email protected]> Gerrit-Reviewer: Florianschmidtwelzow <[email protected]> Gerrit-Reviewer: Jdlrobson <[email protected]> Gerrit-Reviewer: Jhernandez <[email protected]> Gerrit-Reviewer: Legoktm <[email protected]> Gerrit-Reviewer: MaxSem <[email protected]> Gerrit-Reviewer: Phuedx <[email protected]> Gerrit-Reviewer: Robmoen <[email protected]> Gerrit-Reviewer: Siebrand <[email protected]> Gerrit-Reviewer: Yurik <[email protected]> Gerrit-Reviewer: jenkins-bot <> _______________________________________________ MediaWiki-commits mailing list [email protected] https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
