jenkins-bot has submitted this change and it was merged. ( 
https://gerrit.wikimedia.org/r/387186 )

Change subject: Fix handling of partial order parameters
......................................................................


Fix handling of partial order parameters

Throw an error when setListOrder() or setListEntryOrder() is called,
and the provided ids are valid, but not all valid ids are provided.

Bug: T177853
Change-Id: Id992ed0eefd67c9e0b67ce378a9654301880b52a
---
M i18n/en.json
M i18n/qqq.json
M src/ReadingListRepository.php
M tests/src/ReadingListRepositoryTest.php
4 files changed, 60 insertions(+), 22 deletions(-)

Approvals:
  jenkins-bot: Verified
  Mholloway: Looks good to me, approved



diff --git a/i18n/en.json b/i18n/en.json
index 5e88465..b7c4321 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -17,6 +17,8 @@
        "readinglists-db-error-duplicate-page": "The list already contains this 
page.",
        "readinglists-db-error-empty-list-ids": "List ids parameter must not be 
empty.",
        "readinglists-db-error-empty-order": "Order parameter must not be 
empty.",
+       "readinglists-db-error-missing-list": "All lists must be included in 
the order ($1 missing).",
+       "readinglists-db-error-missing-list-entry": "All list entries must be 
included in the order ($1 missing).",
        "readinglists-db-error-entry-not-in-list": "List entry $1 does not 
belong to this list.",
        "readinglists-db-error-user-required": "This method cannot be called 
without specifying the user.",
        "readinglists-apierror-project-title-param": "<var>$1project</var> and 
<var>$1title</var> must be used together.",
diff --git a/i18n/qqq.json b/i18n/qqq.json
index c7f8e33..b7b2f38 100644
--- a/i18n/qqq.json
+++ b/i18n/qqq.json
@@ -18,6 +18,8 @@
        "readinglists-db-error-duplicate-page": "Error message used when trying 
to add a page to a list that already contains it.",
        "readinglists-db-error-empty-list-ids": "Error message used when 
querying list entries without specifying any lists.",
        "readinglists-db-error-empty-order": "Error message used when trying to 
set the order of lists or list entries but passing an empty order array.",
+       "readinglists-db-error-missing-list": "Error message used when trying 
to set the order of lists but omitting some list IDs.",
+       "readinglists-db-error-missing-list-entry": "Error message used when 
trying to set the order of list entries but omitting some entry IDs.",
        "readinglists-db-error-entry-not-in-list": "Error message used when 
trying to set the order of list entries but some of them do not belong to the 
list.",
        "readinglists-db-error-user-required": "Error message used when calling 
a method that operates on a single user, but the user was not specified when 
the repository object was constructed.",
        "readinglists-apierror-project-title-param": "{{doc-apierror}}\n$1 is 
the module prefix.",
diff --git a/src/ReadingListRepository.php b/src/ReadingListRepository.php
index f22e298..5fdec56 100644
--- a/src/ReadingListRepository.php
+++ b/src/ReadingListRepository.php
@@ -534,28 +534,40 @@
                        throw new ReadingListRepositoryException( 
'readinglists-db-error-not-set-up' );
                }
 
-               // Make sure the lists exist and the user owns them.
-               $res = $this->dbw->select(
+               // Make sure the set of IDs match the actual lists.
+               $ids = $this->dbw->selectFieldValues(
                        'reading_list',
-                       [ 'rl_id', 'rl_user_id', 'rl_deleted' ],
-                       [ 'rl_id' => $order ]
-               );
-               $filtered = [];
-               foreach ( $res as $row ) {
+                       'rl_id',
+                       [
+                               'rl_user_id' => $this->userId,
+                               'rl_deleted' => 0,
+                       ]
+               ) ?: [];
+               $nonExistent = array_diff( $order, $ids );
+               if ( $nonExistent ) {
                        /** @var ReadingListRow $row */
-                       if ( $row->rl_user_id != $this->userId ) {
+                       $row = $this->dbw->selectRow(
+                               'reading_list',
+                               [ 'rl_id', 'rl_user_id', 'rl_deleted' ],
+                               [ 'rl_id' => reset( $nonExistent ) ]
+                       );
+                       if ( !$row ) {
+                               throw new ReadingListRepositoryException( 
'readinglists-db-error-no-such-list',
+                                       [ reset( $nonExistent ) ] );
+                       } elseif ( $row->rl_user_id != $this->userId ) {
                                throw new ReadingListRepositoryException(
                                        'readinglists-db-error-not-own-list', [ 
$row->rl_id ] );
                        } elseif ( $row->rl_deleted ) {
                                throw new ReadingListRepositoryException(
                                        'readinglists-db-error-list-deleted', [ 
$row->rl_id ] );
+                       } else {
+                               throw new LogicException( 'setListOrder failed 
for unknown reason' );
                        }
-                       $filtered[] = $row->rl_id;
                }
-               $missing = array_diff( $order, $filtered );
+               $missing = array_diff( $ids, $order );
                if ( $missing ) {
                        throw new ReadingListRepositoryException(
-                               'readinglists-db-error-no-such-list', [ reset( 
$missing ) ] );
+                               'readinglists-db-error-missing-list', [ reset( 
$missing ) ] );
                }
 
                $this->dbw->deleteJoin(
@@ -628,16 +640,27 @@
                        throw new ReadingListRepositoryException( 
'readinglists-db-error-empty-order' );
                }
 
-               // Make sure the list entries exist and the user owns them.
-               $res = $this->dbw->select(
+               // Make sure the set of IDs match the actual list entries.
+               $ids = $this->dbw->selectFieldValues(
                        'reading_list_entry',
-                       [ 'rle_id', 'rle_rl_id', 'rle_user_id', 'rle_deleted' ],
-                       [ 'rle_id' => $order ]
-               );
-               $filtered = [];
-               foreach ( $res as $row ) {
+                       'rle_id',
+                       [
+                               'rle_rl_id' => $id,
+                               'rle_deleted' => 0,
+                       ]
+               ) ?: [];
+               $nonExistent = array_diff( $order, $ids );
+               if ( $nonExistent ) {
                        /** @var ReadingListEntryRow $row */
-                       if ( $row->rle_user_id != $this->userId ) {
+                       $row = $this->dbw->selectRow(
+                               'reading_list_entry',
+                               [ 'rle_id', 'rle_rl_id', 'rle_user_id', 
'rle_deleted' ],
+                               [ 'rle_id' => reset( $nonExistent ) ]
+                       );
+                       if ( !$row ) {
+                               throw new ReadingListRepositoryException( 
'readinglists-db-error-no-such-list-entry',
+                                       [ reset( $nonExistent ) ] );
+                       } elseif ( $row->rle_user_id != $this->userId ) {
                                throw new ReadingListRepositoryException(
                                        
'readinglists-db-error-not-own-list-entry', [ $row->rle_id ] );
                        } elseif ( $row->rle_rl_id != $id ) {
@@ -646,13 +669,14 @@
                        } elseif ( $row->rle_deleted ) {
                                throw new ReadingListRepositoryException(
                                        
'readinglists-db-error-list-entry-deleted', [ $row->rle_id ] );
+                       } else {
+                               throw new LogicException( 'setListEntryOrder 
failed for unknown reason' );
                        }
-                       $filtered[] = $row->rle_id;
                }
-               $missing = array_diff( $order, $filtered );
+               $missing = array_diff( $ids, $order );
                if ( $missing ) {
                        throw new ReadingListRepositoryException(
-                               'readinglists-db-error-no-such-list-entry', [ 
reset( $missing ) ] );
+                               'readinglists-db-error-missing-list-entry', [ 
reset( $missing ) ] );
                }
 
                $this->dbw->deleteJoin(
diff --git a/tests/src/ReadingListRepositoryTest.php 
b/tests/src/ReadingListRepositoryTest.php
index 6747f63..c1d1f70 100644
--- a/tests/src/ReadingListRepositoryTest.php
+++ b/tests/src/ReadingListRepositoryTest.php
@@ -741,6 +741,11 @@
                                $repository->setListOrder( [] );
                        }
                );
+               $this->assertFailsWith( 'readinglists-db-error-missing-list',
+                       function () use ( $repository, $fooId, $foo2Id ) {
+                               $repository->setListOrder( [ $fooId, $foo2Id ] 
);
+                       }
+               );
                $this->assertFailsWith( 'readinglists-db-error-not-own-list',
                        function () use ( $repository, $fooId, $foo2Id, 
$foreignId ) {
                                $repository->setListOrder( [ $fooId, $foo2Id, 
$foreignId ] );
@@ -840,6 +845,11 @@
                                $repository->setListEntryOrder( $listId, [] );
                        }
                );
+               $this->assertFailsWith( 
'readinglists-db-error-missing-list-entry',
+                       function () use ( $repository, $listId, $entry1, 
$entry2 ) {
+                               $repository->setListEntryOrder( $listId, [ 
$entry1, $entry2 ] );
+                       }
+               );
                $this->assertFailsWith( 
'readinglists-db-error-not-own-list-entry',
                        function () use ( $repository, $listId, $foreignEntry ) 
{
                                $repository->setListEntryOrder( $listId, [ 
$foreignEntry ] );

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

Gerrit-MessageType: merged
Gerrit-Change-Id: Id992ed0eefd67c9e0b67ce378a9654301880b52a
Gerrit-PatchSet: 4
Gerrit-Project: mediawiki/extensions/ReadingLists
Gerrit-Branch: master
Gerrit-Owner: GergÅ‘ Tisza <[email protected]>
Gerrit-Reviewer: BearND <[email protected]>
Gerrit-Reviewer: Mholloway <[email protected]>
Gerrit-Reviewer: Siebrand <[email protected]>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to