From 728321e11325d983297c8ea413d97f970c04790b Mon Sep 17 00:00:00 2001 From: Amir Sarabadani Date: Thu, 22 Mar 2018 15:17:56 +0100 Subject: [PATCH] Make autopatrol third option in rc_patrolled and use it in API Bug: T184791 Change-Id: If64ba8b845b122a87f20646dddf72ef257b793cb --- includes/api/ApiQueryRecentChanges.php | 15 +++++++++++-- includes/api/ApiQueryUserContributions.php | 15 ++++++++++--- includes/api/ApiQueryWatchlist.php | 10 ++++++++- includes/api/i18n/en.json | 3 +++ includes/api/i18n/qqq.json | 3 +++ includes/changes/RecentChange.php | 4 ++++ includes/installer/MssqlUpdater.php | 1 + includes/logging/LogEntry.php | 2 +- includes/page/WikiPage.php | 5 +++-- .../watcheditem/WatchedItemQueryService.php | 9 ++++++++ .../archives/patch-rc_patrolled_type.sql | 22 +++++++++++++++++++ maintenance/mssql/tables.sql | 5 +++-- .../api/ApiQueryWatchlistIntegrationTest.php | 2 ++ 13 files changed, 85 insertions(+), 11 deletions(-) create mode 100644 maintenance/mssql/archives/patch-rc_patrolled_type.sql diff --git a/includes/api/ApiQueryRecentChanges.php b/includes/api/ApiQueryRecentChanges.php index e431202bc8..9ff41498a9 100644 --- a/includes/api/ApiQueryRecentChanges.php +++ b/includes/api/ApiQueryRecentChanges.php @@ -192,6 +192,9 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase { || ( isset( $show['patrolled'] ) && isset( $show['!patrolled'] ) ) || ( isset( $show['patrolled'] ) && isset( $show['unpatrolled'] ) ) || ( isset( $show['!patrolled'] ) && isset( $show['unpatrolled'] ) ) + || ( isset( $show['autopatrolled'] ) && isset( $show['!autopatrolled'] ) ) + || ( isset( $show['autopatrolled'] ) && isset( $show['unpatrolled'] ) ) + || ( isset( $show['autopatrolled'] ) && isset( $show['!patrolled'] ) ) ) { $this->dieWithError( 'apierror-show' ); } @@ -200,6 +203,8 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase { if ( isset( $show['patrolled'] ) || isset( $show['!patrolled'] ) || isset( $show['unpatrolled'] ) + || isset( $show['autopatrolled'] ) + || isset( $show['!autopatrolled'] ) ) { if ( !$user->useRCPatrol() && !$user->useNPPatrol() ) { $this->dieWithError( 'apierror-permissiondenied-patrolflag', 'permissiondenied' ); @@ -237,6 +242,9 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase { } } + $this->addWhereIf( 'rc_patrolled != 2', isset( $show['!autopatrolled'] ) ); + $this->addWhereIf( 'rc_patrolled = 2', isset( $show['autopatrolled'] ) ); + // Don't throw log entries out the window here $this->addWhereIf( 'page_is_redirect = 0 OR page_is_redirect IS NULL', @@ -544,8 +552,9 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase { /* Add the patrolled flag */ if ( $this->fld_patrolled ) { - $vals['patrolled'] = $row->rc_patrolled == 1; + $vals['patrolled'] = $row->rc_patrolled != 0; $vals['unpatrolled'] = ChangesList::isUnpatrolled( $row, $user ); + $vals['autopatrolled'] = $row->rc_patrolled == 2; } if ( $this->fld_loginfo && $row->rc_type == RC_LOG ) { @@ -694,7 +703,9 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase { '!redirect', 'patrolled', '!patrolled', - 'unpatrolled' + 'unpatrolled', + 'autopatrolled', + '!autopatrolled', ] ], 'limit' => [ diff --git a/includes/api/ApiQueryUserContributions.php b/includes/api/ApiQueryUserContributions.php index 816c56c160..f6bc8cb6b9 100644 --- a/includes/api/ApiQueryUserContributions.php +++ b/includes/api/ApiQueryUserContributions.php @@ -530,6 +530,8 @@ class ApiQueryContributions extends ApiQueryBase { if ( ( isset( $show['minor'] ) && isset( $show['!minor'] ) ) || ( isset( $show['patrolled'] ) && isset( $show['!patrolled'] ) ) + || ( isset( $show['autopatrolled'] ) && isset( $show['!autopatrolled'] ) ) + || ( isset( $show['autopatrolled'] ) && isset( $show['!patrolled'] ) ) || ( isset( $show['top'] ) && isset( $show['!top'] ) ) || ( isset( $show['new'] ) && isset( $show['!new'] ) ) ) { @@ -540,6 +542,8 @@ class ApiQueryContributions extends ApiQueryBase { $this->addWhereIf( 'rev_minor_edit != 0', isset( $show['minor'] ) ); $this->addWhereIf( 'rc_patrolled = 0', isset( $show['!patrolled'] ) ); $this->addWhereIf( 'rc_patrolled != 0', isset( $show['patrolled'] ) ); + $this->addWhereIf( 'rc_patrolled != 2', isset( $show['!autopatrolled'] ) ); + $this->addWhereIf( 'rc_patrolled = 2', isset( $show['autopatrolled'] ) ); $this->addWhereIf( $idField . ' != page_latest', isset( $show['!top'] ) ); $this->addWhereIf( $idField . ' = page_latest', isset( $show['top'] ) ); $this->addWhereIf( 'rev_parent_id != 0', isset( $show['!new'] ) ); @@ -548,15 +552,17 @@ class ApiQueryContributions extends ApiQueryBase { $this->addOption( 'LIMIT', $limit + 1 ); if ( isset( $show['patrolled'] ) || isset( $show['!patrolled'] ) || - $this->fld_patrolled + isset( $show['autopatrolled'] ) || isset( $show['!autopatrolled'] ) || $this->fld_patrolled ) { if ( !$user->useRCPatrol() && !$user->useNPPatrol() ) { $this->dieWithError( 'apierror-permissiondenied-patrolflag', 'permissiondenied' ); } + $isFilterset = isset( $show['patrolled'] ) || isset( $show['!patrolled'] ) || + isset( $show['autopatrolled'] ) || isset( $show['!autopatrolled'] ); $this->addTables( 'recentchanges' ); $this->addJoinConds( [ 'recentchanges' => [ - isset( $show['patrolled'] ) || isset( $show['!patrolled'] ) ? 'JOIN' : 'LEFT JOIN', + $isFilterset ? 'JOIN' : 'LEFT JOIN', [ // This is a crazy hack. recentchanges has no index on rc_this_oldid, so instead of adding // one T19237 did a join using rc_user_text and rc_timestamp instead. Now rc_user_text is @@ -660,7 +666,8 @@ class ApiQueryContributions extends ApiQueryBase { } if ( $this->fld_patrolled ) { - $vals['patrolled'] = (bool)$row->rc_patrolled; + $vals['patrolled'] = $row->rc_patrolled != RecentChange::PRC_UNPATROLLED; + $vals['autopatrolled'] = $row->rc_patrolled == RecentChange::PRC_AUTOPATROLLED; } if ( $this->fld_size && !is_null( $row->rev_len ) ) { @@ -778,6 +785,8 @@ class ApiQueryContributions extends ApiQueryBase { '!minor', 'patrolled', '!patrolled', + 'autopatrolled', + '!autopatrolled', 'top', '!top', 'new', diff --git a/includes/api/ApiQueryWatchlist.php b/includes/api/ApiQueryWatchlist.php index 69f1838786..52ad26cdcb 100644 --- a/includes/api/ApiQueryWatchlist.php +++ b/includes/api/ApiQueryWatchlist.php @@ -233,6 +233,7 @@ class ApiQueryWatchlist extends ApiQueryGeneratorBase { } if ( $this->fld_patrol ) { $includeFields[] = WatchedItemQueryService::INCLUDE_PATROL_INFO; + $includeFields[] = WatchedItemQueryService::INCLUDE_AUTOPATROL_INFO; } if ( $this->fld_sizes ) { $includeFields[] = WatchedItemQueryService::INCLUDE_SIZES; @@ -255,6 +256,10 @@ class ApiQueryWatchlist extends ApiQueryGeneratorBase { && isset( $show[WatchedItemQueryService::FILTER_NOT_ANON] ) ) || ( isset( $show[WatchedItemQueryService::FILTER_PATROLLED] ) && isset( $show[WatchedItemQueryService::FILTER_NOT_PATROLLED] ) ) + || ( isset( $show[WatchedItemQueryService::FILTER_AUTOPATROLLED] ) + && isset( $show[WatchedItemQueryService::FILTER_NOT_AUTOPATROLLED] ) ) + || ( isset( $show[WatchedItemQueryService::FILTER_AUTOPATROLLED] ) + && isset( $show[WatchedItemQueryService::FILTER_NOT_PATROLLED] ) ) || ( isset( $show[WatchedItemQueryService::FILTER_UNREAD] ) && isset( $show[WatchedItemQueryService::FILTER_NOT_UNREAD] ) ); } @@ -370,8 +375,9 @@ class ApiQueryWatchlist extends ApiQueryGeneratorBase { /* Add the patrolled flag */ if ( $this->fld_patrol ) { - $vals['patrolled'] = $recentChangeInfo['rc_patrolled'] == 1; + $vals['patrolled'] = $recentChangeInfo['rc_patrolled'] != 0; $vals['unpatrolled'] = ChangesList::isUnpatrolled( (object)$recentChangeInfo, $user ); + $vals['autopatrolled'] = $recentChangeInfo['rc_patrolled'] == 2; } if ( $this->fld_loginfo && $recentChangeInfo['rc_type'] == RC_LOG ) { @@ -477,6 +483,8 @@ class ApiQueryWatchlist extends ApiQueryGeneratorBase { WatchedItemQueryService::FILTER_NOT_ANON, WatchedItemQueryService::FILTER_PATROLLED, WatchedItemQueryService::FILTER_NOT_PATROLLED, + WatchedItemQueryService::FILTER_AUTOPATROLLED, + WatchedItemQueryService::FILTER_NOT_AUTOPATROLLED, WatchedItemQueryService::FILTER_UNREAD, WatchedItemQueryService::FILTER_NOT_UNREAD, ] diff --git a/includes/api/i18n/en.json b/includes/api/i18n/en.json index 756852650d..d158b2c678 100644 --- a/includes/api/i18n/en.json +++ b/includes/api/i18n/en.json @@ -1071,6 +1071,7 @@ "apihelp-query+recentchanges-paramvalue-prop-sizes": "Adds the new and old page length in bytes.", "apihelp-query+recentchanges-paramvalue-prop-redirect": "Tags edit if page is a redirect.", "apihelp-query+recentchanges-paramvalue-prop-patrolled": "Tags patrollable edits as being patrolled or unpatrolled.", + "apihelp-query+recentchanges-paramvalue-prop-autopatrolled": "Tags patrollable edits as being autopatrolled or not.", "apihelp-query+recentchanges-paramvalue-prop-loginfo": "Adds log information (log ID, log type, etc) to log entries.", "apihelp-query+recentchanges-paramvalue-prop-tags": "Lists tags for the entry.", "apihelp-query+recentchanges-paramvalue-prop-sha1": "Adds the content checksum for entries associated with a revision.", @@ -1260,6 +1261,7 @@ "apihelp-query+usercontribs-paramvalue-prop-sizediff": "Adds the size delta of the edit against its parent.", "apihelp-query+usercontribs-paramvalue-prop-flags": "Adds flags of the edit.", "apihelp-query+usercontribs-paramvalue-prop-patrolled": "Tags patrolled edits.", + "apihelp-query+usercontribs-paramvalue-prop-autopatrolled": "Tags autopatrolled edits.", "apihelp-query+usercontribs-paramvalue-prop-tags": "Lists tags for the edit.", "apihelp-query+usercontribs-param-show": "Show only items that meet these criteria, e.g. non minor edits only: $2show=!minor.\n\nIf $2show=patrolled or $2show=!patrolled is set, revisions older than [[mw:Special:MyLanguage/Manual:$wgRCMaxAge|$wgRCMaxAge]] ($1 {{PLURAL:$1|second|seconds}}) won't be shown.", "apihelp-query+usercontribs-param-tag": "Only list revisions tagged with this tag.", @@ -1327,6 +1329,7 @@ "apihelp-query+watchlist-paramvalue-prop-parsedcomment": "Adds parsed comment of the edit.", "apihelp-query+watchlist-paramvalue-prop-timestamp": "Adds timestamp of the edit.", "apihelp-query+watchlist-paramvalue-prop-patrol": "Tags edits that are patrolled.", + "apihelp-query+watchlist-paramvalue-prop-autopatrol": "Tags edits that are autopatrolled.", "apihelp-query+watchlist-paramvalue-prop-sizes": "Adds the old and new lengths of the page.", "apihelp-query+watchlist-paramvalue-prop-notificationtimestamp": "Adds timestamp of when the user was last notified about the edit.", "apihelp-query+watchlist-paramvalue-prop-loginfo": "Adds log information where appropriate.", diff --git a/includes/api/i18n/qqq.json b/includes/api/i18n/qqq.json index fc0de4e333..96ff10fda2 100644 --- a/includes/api/i18n/qqq.json +++ b/includes/api/i18n/qqq.json @@ -999,6 +999,7 @@ "apihelp-query+recentchanges-paramvalue-prop-sizes": "{{doc-apihelp-paramvalue|query+recentchanges|prop|sizes}}", "apihelp-query+recentchanges-paramvalue-prop-redirect": "{{doc-apihelp-paramvalue|query+recentchanges|prop|redirect}}", "apihelp-query+recentchanges-paramvalue-prop-patrolled": "{{doc-apihelp-paramvalue|query+recentchanges|prop|patrolled}}", + "apihelp-query+recentchanges-paramvalue-prop-autopatrolled": "{{doc-apihelp-paramvalue|query+recentchanges|prop|autopatrolled}}", "apihelp-query+recentchanges-paramvalue-prop-loginfo": "{{doc-apihelp-paramvalue|query+recentchanges|prop|loginfo}}", "apihelp-query+recentchanges-paramvalue-prop-tags": "{{doc-apihelp-paramvalue|query+recentchanges|prop|tags}}", "apihelp-query+recentchanges-paramvalue-prop-sha1": "{{doc-apihelp-paramvalue|query+recentchanges|prop|sha1}}", @@ -1177,6 +1178,7 @@ "apihelp-query+usercontribs-paramvalue-prop-sizediff": "{{doc-apihelp-paramvalue|query+usercontribs|prop|sizediff}}", "apihelp-query+usercontribs-paramvalue-prop-flags": "{{doc-apihelp-paramvalue|query+usercontribs|prop|flags}}", "apihelp-query+usercontribs-paramvalue-prop-patrolled": "{{doc-apihelp-paramvalue|query+usercontribs|prop|patrolled}}", + "apihelp-query+usercontribs-paramvalue-prop-autopatrolled": "{{doc-apihelp-paramvalue|query+usercontribs|prop|autopatrolled}}", "apihelp-query+usercontribs-paramvalue-prop-tags": "{{doc-apihelp-paramvalue|query+usercontribs|prop|tags}}", "apihelp-query+usercontribs-param-show": "{{doc-apihelp-param|query+usercontribs|show|params=* $1 - Value of [[mw:Manual:$RCMaxAge|$RCMaxAge]]|paramstart=2}}", "apihelp-query+usercontribs-param-tag": "{{doc-apihelp-param|query+usercontribs|tag}}", @@ -1241,6 +1243,7 @@ "apihelp-query+watchlist-paramvalue-prop-parsedcomment": "{{doc-apihelp-paramvalue|query+watchlist|prop|parsedcomment}}", "apihelp-query+watchlist-paramvalue-prop-timestamp": "{{doc-apihelp-paramvalue|query+watchlist|prop|timestamp}}", "apihelp-query+watchlist-paramvalue-prop-patrol": "{{doc-apihelp-paramvalue|query+watchlist|prop|patrol}}", + "apihelp-query+watchlist-paramvalue-prop-autopatrol": "{{doc-apihelp-paramvalue|query+watchlist|prop|autopatrol}}", "apihelp-query+watchlist-paramvalue-prop-sizes": "{{doc-apihelp-paramvalue|query+watchlist|prop|sizes}}", "apihelp-query+watchlist-paramvalue-prop-notificationtimestamp": "{{doc-apihelp-paramvalue|query+watchlist|prop|notificationtimestamp}}", "apihelp-query+watchlist-paramvalue-prop-loginfo": "{{doc-apihelp-paramvalue|query+watchlist|prop|loginfo}}", diff --git a/includes/changes/RecentChange.php b/includes/changes/RecentChange.php index 3dacf6af04..b0511209db 100644 --- a/includes/changes/RecentChange.php +++ b/includes/changes/RecentChange.php @@ -74,6 +74,10 @@ class RecentChange { const SRC_EXTERNAL = 'mw.external'; // obsolete const SRC_CATEGORIZE = 'mw.categorize'; + const PRC_UNPATROLLED = 0; + const PRC_PATROLLED = 1; + const PRC_AUTOPATROLLED = 2; + public $mAttribs = []; public $mExtra = []; diff --git a/includes/installer/MssqlUpdater.php b/includes/installer/MssqlUpdater.php index 5e0dbc0052..2d245a7281 100644 --- a/includes/installer/MssqlUpdater.php +++ b/includes/installer/MssqlUpdater.php @@ -125,6 +125,7 @@ class MssqlUpdater extends DatabaseUpdater { [ 'modifyField', 'revision', 'rev_text_id', 'patch-rev_text_id-default.sql' ], [ 'modifyTable', 'site_stats', 'patch-site_stats-modify.sql' ], [ 'populateArchiveRevId' ], + [ 'modifyField', 'recentchanges', 'rc_patrolled', 'patch-rc_patrolled_type.sql' ], ]; } diff --git a/includes/logging/LogEntry.php b/includes/logging/LogEntry.php index 80a138dca5..c672ef7fc9 100644 --- a/includes/logging/LogEntry.php +++ b/includes/logging/LogEntry.php @@ -785,7 +785,7 @@ class ManualLogEntry extends LogEntryBase { // Log the autopatrol if the log entry is patrollable if ( $this->getIsPatrollable() && - $rc->getAttribute( 'rc_patrolled' ) === 1 + $rc->getAttribute( 'rc_patrolled' ) === 2 ) { PatrolLog::record( $rc, true, $this->getPerformer() ); } diff --git a/includes/page/WikiPage.php b/includes/page/WikiPage.php index 039a329be4..f45036c1db 100644 --- a/includes/page/WikiPage.php +++ b/includes/page/WikiPage.php @@ -1781,7 +1781,7 @@ class WikiPage implements Page, IDBAccessObject { // Update recentchanges if ( !( $flags & EDIT_SUPPRESS_RC ) ) { // Mark as patrolled if the user can do so - $patrolled = $wgUseRCPatrol && !count( + $autopatrolled = $wgUseRCPatrol && !count( $this->mTitle->getUserPermissionsErrors( 'autopatrol', $user ) ); // Add RC row to the DB RecentChange::notifyEdit( @@ -1797,7 +1797,8 @@ class WikiPage implements Page, IDBAccessObject { $oldContent ? $oldContent->getSize() : 0, $newsize, $revisionId, - $patrolled, + $autopatrolled ? RecentChange::PRC_AUTOPATROLLED : + RecentChange::PRC_UNPATROLLED, $tags ); } diff --git a/includes/watcheditem/WatchedItemQueryService.php b/includes/watcheditem/WatchedItemQueryService.php index 412fdf54be..bf419a94a5 100644 --- a/includes/watcheditem/WatchedItemQueryService.php +++ b/includes/watcheditem/WatchedItemQueryService.php @@ -25,6 +25,7 @@ class WatchedItemQueryService { const INCLUDE_USER_ID = 'userid'; const INCLUDE_COMMENT = 'comment'; const INCLUDE_PATROL_INFO = 'patrol'; + const INCLUDE_AUTOPATROL_INFO = 'autopatrol'; const INCLUDE_SIZES = 'sizes'; const INCLUDE_LOG_INFO = 'loginfo'; const INCLUDE_TAGS = 'tags'; @@ -40,6 +41,8 @@ class WatchedItemQueryService { const FILTER_NOT_ANON = '!anon'; const FILTER_PATROLLED = 'patrolled'; const FILTER_NOT_PATROLLED = '!patrolled'; + const FILTER_AUTOPATROLLED = 'autopatrolled'; + const FILTER_NOT_AUTOPATROLLED = '!autopatrolled'; const FILTER_UNREAD = 'unread'; const FILTER_NOT_UNREAD = '!unread'; const FILTER_CHANGED = 'changed'; @@ -499,6 +502,12 @@ class WatchedItemQueryService { } elseif ( in_array( self::FILTER_NOT_PATROLLED, $options['filters'] ) ) { $conds[] = 'rc_patrolled = 0'; } + + if ( in_array( self::FILTER_AUTOPATROLLED, $options['filters'] ) ) { + $conds[] = 'rc_patrolled = 2'; + } elseif ( in_array( self::FILTER_NOT_AUTOPATROLLED, $options['filters'] ) ) { + $conds[] = 'rc_patrolled != 2'; + } } if ( in_array( self::FILTER_UNREAD, $options['filters'] ) ) { diff --git a/maintenance/mssql/archives/patch-rc_patrolled_type.sql b/maintenance/mssql/archives/patch-rc_patrolled_type.sql new file mode 100644 index 0000000000..c8c775590b --- /dev/null +++ b/maintenance/mssql/archives/patch-rc_patrolled_type.sql @@ -0,0 +1,22 @@ +DECLARE @cname sysname;-- + +SELECT @cname = dc.name +FROM sys.default_constraints dc +JOIN sys.columns c + ON c.object_id = dc.parent_object_id + AND c.column_id = dc.parent_column_id +WHERE + c.name = 'rc_patrolled' + AND c.object_id = OBJECT_ID('/*_*/recentchanges', 'U');-- + +IF @cname IS NOT NULL +BEGIN;-- + DECLARE @sql nvarchar(max);-- + SET @sql = N'ALTER TABLE /*_*/recentchanges DROP CONSTRAINT ' + @cname;-- + EXEC sp_executesql @sql;-- +END;-- + +DROP INDEX /*i*/rc_name_type_patrolled_timestamp ON /*_*/recentchanges;-- +ALTER TABLE /*_*/recentchanges ALTER COLUMN rc_patrolled tinyint NOT NULL;-- +ALTER TABLE /*_*/recentchanges ADD CONSTRAINT DF_rc_patrolled DEFAULT 0 FOR rc_patrolled;-- +CREATE INDEX /*i*/rc_name_type_patrolled_timestamp ON /*_*/recentchanges (rc_namespace, rc_type, rc_patrolled, rc_timestamp); \ No newline at end of file diff --git a/maintenance/mssql/tables.sql b/maintenance/mssql/tables.sql index 01ebb74136..a34b5b8a28 100644 --- a/maintenance/mssql/tables.sql +++ b/maintenance/mssql/tables.sql @@ -1001,8 +1001,9 @@ CREATE TABLE /*_*/recentchanges ( -- If the Recent Changes Patrol option is enabled, -- users may mark edits as having been reviewed to -- remove a warning flag on the RC list. - -- A value of 1 indicates the page has been reviewed. - rc_patrolled bit NOT NULL default 0, + -- A value of 1 indicates the page has been reviewed manually. + -- A value of 2 indicates the page has been automatically reviewed. + rc_patrolled tinyint NOT NULL CONSTRAINT DF_rc_patrolled DEFAULT 0 -- Recorded IP address the edit was made from, if the -- $wgPutIPinRC option is enabled. diff --git a/tests/phpunit/includes/api/ApiQueryWatchlistIntegrationTest.php b/tests/phpunit/includes/api/ApiQueryWatchlistIntegrationTest.php index a78a4c93a7..f973281c79 100644 --- a/tests/phpunit/includes/api/ApiQueryWatchlistIntegrationTest.php +++ b/tests/phpunit/includes/api/ApiQueryWatchlistIntegrationTest.php @@ -629,6 +629,7 @@ class ApiQueryWatchlistIntegrationTest extends ApiTestCase { 'type' => 'new', 'patrolled' => true, 'unpatrolled' => false, + 'autopatrolled' => false, ] ], $this->getItemsFromApiResponse( $result ) @@ -973,6 +974,7 @@ class ApiQueryWatchlistIntegrationTest extends ApiTestCase { 'type' => 'new', 'patrolled' => true, 'unpatrolled' => false, + 'autopatrolled' => false, ] ], $this->getItemsFromApiResponse( $resultPatrolled ) -- 2.20.1