Ladsgroup has uploaded a new change for review.

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

Change subject: [WIP] introduce list=wbgetsubscribers in repo
......................................................................

[WIP] introduce list=wbgetsubscribers in repo

What needs to be done:
 - i18n messages
 - get url working
 - CI tests

Bug: T145880
Change-Id: I95f7b00b010631f292c4ebcb5f2cfc9f21001d92
---
M repo/Wikibase.php
A repo/includes/Api/GetSubscribers.php
2 files changed, 244 insertions(+), 0 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Wikibase 
refs/changes/24/315324/1

diff --git a/repo/Wikibase.php b/repo/Wikibase.php
index 660eb98..e4a211a 100644
--- a/repo/Wikibase.php
+++ b/repo/Wikibase.php
@@ -177,6 +177,7 @@
        $wgAPIModules['wbavailablebadges'] = 
Wikibase\Repo\Api\AvailableBadges::class;
        $wgAPIModules['wbcreateredirect'] = 
Wikibase\Repo\Api\CreateRedirect::class;
        $wgAPIListModules['wbsearch'] = 
Wikibase\Repo\Api\QuerySearchEntities::class;
+       $wgAPIListModules['wbgetsubscribers'] = 
Wikibase\Repo\Api\GetSubscribers::class;
 
        // Special page registration
        $wgSpecialPages['NewItem'] = 
Wikibase\Repo\Specials\SpecialNewItem::class;
diff --git a/repo/includes/Api/GetSubscribers.php 
b/repo/includes/Api/GetSubscribers.php
new file mode 100644
index 0000000..51d2aef
--- /dev/null
+++ b/repo/includes/Api/GetSubscribers.php
@@ -0,0 +1,243 @@
+<?php
+
+namespace Wikibase\Repo\Api;
+
+use ApiBase;
+use ApiQueryBase;
+use ApiQuery;
+use ApiResult;
+use ResultWrapper;
+use Wikibase\DataModel\Entity\EntityId;
+use Wikibase\DataModel\Entity\EntityIdParser;
+use Wikibase\DataModel\Entity\EntityIdParsingException;
+use Wikibase\Repo\WikibaseRepo;
+
+/**
+ * API module for getting subscribers to given entities.
+ *
+ * @since 0.5
+ *
+ * @license GPL-2.0+
+ * @author Amir Sarabadani <ladsgr...@gmail.com>
+ */
+class GetSubscribers extends ApiQueryBase {
+
+       /**
+        * @var ApiErrorReporter
+        */
+       private $errorReporter;
+
+       /**
+        * @var EntityIdParser
+        */
+       private $idParser;
+
+       /**
+        * @param ApiQuery $queryModule
+        * @param string $moduleName
+        * @param string $modulePrefix
+        *
+        * @see ApiBase::__construct
+        */
+       public function __construct( ApiQuery $queryModule, $moduleName, 
$modulePrefix = 'wbgs' ) {
+               parent::__construct( $queryModule, $moduleName, $modulePrefix );
+
+               $wikibaseRepo = WikibaseRepo::getDefaultInstance();
+               $apiHelperFactory = $wikibaseRepo->getApiHelperFactory( 
$this->getContext() );
+               $this->errorReporter = $apiHelperFactory->getErrorReporter( 
$this );
+               $this->idParser = $wikibaseRepo->getEntityIdParser();
+       }
+
+       public function execute() {
+               $this->getMain()->setCacheMode( 'public' );
+
+               $params = $this->extractRequestParams();
+
+               $idStrings = $params['entities'];
+
+               foreach ( $idStrings as $idString ) {
+                       try {
+                               $this->idParser->parse( $idString );
+                       }
+                       catch ( EntityIdParsingException $e ) {
+                               $this->errorReporter->dieException( $e, 
'param-invalid' );
+                       }
+               }
+
+               $res = $this->doQuery( $idStrings, $params );
+               $props = isset( $params['props'] ) ? $params['props'] : [];
+               $this->formatResult( $res, $params['limit'], $props );
+       }
+
+       /**
+        * @param string[] $idStrings
+        * @param string[] $params
+        *
+        * @return ResultWrapper|null
+        */
+       public function doQuery( array $idStrings, array $params ) {
+
+               $this->addFields( [
+                       'cs_entity_id',
+                       'cs_subscriber_id',
+               ] );
+
+               $this->addTables( 'wb_changes_subscription' );
+
+               $this->addWhereFld( 'cs_entity_id', $idStrings );
+
+               if ( !is_null( $params['continue'] ) ) {
+                       $this->addContinue( $params['continue'] );
+               }
+
+               $orderBy = [ 'cs_entity_id', 'cs_subscriber_id' ];
+               $this->addOption( 'ORDER BY', $orderBy );
+
+               $this->addOption( 'LIMIT', $params['limit'] + 1 );
+               $res = $this->select( __METHOD__ );
+               return $res;
+       }
+
+       /**
+        * @param string $continueParam
+        *
+        */
+       private function addContinue( $continueParam ) {
+               $db = $this->getDB();
+               $continueParams = explode( '|', $continueParam );
+               $entityContinueSql = $db->addQuotes( $continueParams[0] );
+               $wikiContinueSql = $db->addQuotes( $continueParams[1] );
+               // Filtering out results that have been shown already and
+               // starting the query from where it ended.
+               $this->addWhere(
+                       "eu_page_id > $pageContinueSql OR " .
+                       "(eu_page_id = $pageContinueSql AND " .
+                       "(eu_entity_id > $entityContinueSql OR " .
+                       "(eu_entity_id = $entityContinueSql AND " .
+                       "eu_aspect >= $aspectContinueSql)))"
+               );
+       }
+
+       /**
+        * @param ResultWrapper $res
+        * @param int $limit
+        * @param array $props
+        */
+       private function formatResult( ResultWrapper $res, $limit, array $props 
) {
+               $currentEntity = null;
+               $entry = [];
+               $count = 0;
+               $result = $this->getResult();
+               $prRow = null;
+
+               foreach ( $res as $row ) {
+                       if ( ++$count > $limit ) {
+                               // We've reached the one extra which shows that
+                               // there are additional pages to be had. Stop 
here...
+                               $this->setContinueFromRow( $row );
+                               break;
+                       }
+
+                       if ( $currentEntity !== null && $row->cs_entity_id !== 
$currentEntity ) {
+                               // Let's add the data and check if it needs 
continuation
+                               $fit = $this->formatPageData( $prRow, 
$currentEntity, $entry, $result );
+                               if ( !$fit ) {
+                                       $this->setContinueFromRow( $row );
+                                       break;
+                               }
+                               $entry = [];
+                       }
+
+                       $currentEntity = $row->cs_entity_id;
+                       $prRow = $row;
+
+                       if ( array_key_exists( $row->cs_entity_id, $entry ) ) {
+                               $entry['subscribers'][] = 
$row->cs_subscriber_id;
+                       } else {
+                               $this->buildEntry( $entry, $row, isset( 
$props['url'] ) );
+                       }
+
+               }
+               if ( $entry ) {
+                       $this->formatPageData( $row, $currentEntity, $entry, 
$result );
+               }
+       }
+
+       /**
+        * @param array $entry
+        * @param object $row
+        * @param bool $url
+        */
+       private function buildEntry( &$entry, $row, $url ) {
+               $entry = [ 'subscribers' => [ $row->cs_subscriber_id ] ];
+               if ( $url ) {
+                       $entry['subscribers'][$row->cs_subscriber_id]['url'] = 
$this->repoLinker->getPageUrl(
+                               'Special:EntityData/' . $row->cs_entity_id );
+               }
+               ApiResult::setIndexedTagName(
+                       $entry['subscribers'], 'subscriber'
+               );
+               ApiResult::setArrayType( $entry, 'kvp', 'id' );
+       }
+
+       /**
+        * @param \stdClass $row
+        * @param string $entityId
+        * @param array $entry
+        * @param ApiResult $result
+        *
+        * @return bool
+        */
+       private function formatPageData( \stdClass $row, $entityId, array 
$entry, ApiResult $result ) {
+               $fit = $result->addValue( [ 'query', 'subscribers' ], 
$entityId, $entry );
+               return $fit;
+       }
+
+       /**
+        * @param object $row
+        */
+       private function setContinueFromRow( $row ) {
+               $this->setContinueEnumParameter(
+                       'continue',
+                       "{$row->cs_entity_id}|{$row->cs_subscriber_id}"
+               );
+       }
+
+       /**
+        * @see ApiBase::getAllowedParams
+        */
+       protected function getAllowedParams() {
+               return [
+                       'entities' => [
+                               self::PARAM_TYPE => 'string',
+                               self::PARAM_ISMULTI => true,
+                       ],
+                       'props' => [
+                               self::PARAM_TYPE => [
+                                       'url',
+                               ],
+                               self::PARAM_ISMULTI => true,
+                       ],
+                       'limit' => [
+                               ApiBase::PARAM_DFLT => 10,
+                               ApiBase::PARAM_TYPE => 'limit',
+                               ApiBase::PARAM_MIN => 1,
+                               ApiBase::PARAM_MAX => ApiBase::LIMIT_BIG1,
+                               ApiBase::PARAM_MAX2 => ApiBase::LIMIT_BIG2
+                       ]
+               ];
+       }
+
+       /**
+        * @see ApiBase::getExamplesMessages
+        */
+       protected function getExamplesMessages() {
+               return [
+                       "action=wbgetclaims&entity=Q42" =>
+                               "apihelp-wbgetclaims-example-1",
+                       "action=wbgetclaims&entity=Q42&property=P2" =>
+                               "apihelp-wbgetclaims-example-2",
+               ];
+       }
+
+}

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: I95f7b00b010631f292c4ebcb5f2cfc9f21001d92
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/Wikibase
Gerrit-Branch: master
Gerrit-Owner: Ladsgroup <ladsgr...@gmail.com>

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

Reply via email to