From 458cea36449aeb037bc34b462ad135d426eed204 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jean-Ren=C3=A9=20ROUET?= <rouet@in2p3.fr>
Date: Mon, 12 Jun 2023 15:12:46 +0200
Subject: [PATCH 1/4] [API] add priority in book read [API] add priority in
 chapter create and update [API] add priority in page create and update

---
 app/Api/ApiEntityListFormatter.php                | 1 +
 app/Entities/Controllers/ChapterApiController.php | 2 ++
 app/Entities/Controllers/PageApiController.php    | 2 ++
 3 files changed, 5 insertions(+)

diff --git a/app/Api/ApiEntityListFormatter.php b/app/Api/ApiEntityListFormatter.php
index c170ecf0c..7d00834e5 100644
--- a/app/Api/ApiEntityListFormatter.php
+++ b/app/Api/ApiEntityListFormatter.php
@@ -22,6 +22,7 @@ class ApiEntityListFormatter
     protected $fields = [
         'id', 'name', 'slug', 'book_id', 'chapter_id',
         'draft', 'template', 'created_at', 'updated_at',
+        'priority'
     ];
 
     public function __construct(array $list)
diff --git a/app/Entities/Controllers/ChapterApiController.php b/app/Entities/Controllers/ChapterApiController.php
index 403c58de3..7f01e445a 100644
--- a/app/Entities/Controllers/ChapterApiController.php
+++ b/app/Entities/Controllers/ChapterApiController.php
@@ -19,12 +19,14 @@ class ChapterApiController extends ApiController
             'name'        => ['required', 'string', 'max:255'],
             'description' => ['string', 'max:1000'],
             'tags'        => ['array'],
+            'priority'    => ['integer'],
         ],
         'update' => [
             'book_id'     => ['integer'],
             'name'        => ['string', 'min:1', 'max:255'],
             'description' => ['string', 'max:1000'],
             'tags'        => ['array'],
+            'priority'    => ['integer'],
         ],
     ];
 
diff --git a/app/Entities/Controllers/PageApiController.php b/app/Entities/Controllers/PageApiController.php
index 28dd36f97..c83126df9 100644
--- a/app/Entities/Controllers/PageApiController.php
+++ b/app/Entities/Controllers/PageApiController.php
@@ -23,6 +23,7 @@ class PageApiController extends ApiController
             'html'       => ['required_without:markdown', 'string'],
             'markdown'   => ['required_without:html', 'string'],
             'tags'       => ['array'],
+            'priority'   => ['integer'],
         ],
         'update' => [
             'book_id'    => ['integer'],
@@ -31,6 +32,7 @@ class PageApiController extends ApiController
             'html'       => ['string'],
             'markdown'   => ['string'],
             'tags'       => ['array'],
+            'priority'   => ['integer'],
         ],
     ];
 

From 4d399f6ba77610635d4d1399b9ac3d5302c63b9c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jean-Ren=C3=A9=20ROUET?= <rouet@in2p3.fr>
Date: Tue, 11 Jul 2023 13:28:20 +0200
Subject: [PATCH 2/4] add priority on page and chapter create

---
 app/Entities/Repos/ChapterRepo.php | 2 +-
 app/Entities/Repos/PageRepo.php    | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/app/Entities/Repos/ChapterRepo.php b/app/Entities/Repos/ChapterRepo.php
index 588854c7e..dadeec7f8 100644
--- a/app/Entities/Repos/ChapterRepo.php
+++ b/app/Entities/Repos/ChapterRepo.php
@@ -49,7 +49,7 @@ class ChapterRepo
     {
         $chapter = new Chapter();
         $chapter->book_id = $parentBook->id;
-        $chapter->priority = (new BookContents($parentBook))->getLastPriority() + 1;
+        $chapter->priority = $chapter->priority ?: (new BookContents($parentBook))->getLastPriority() + 1;
         $this->baseRepo->create($chapter, $input);
         Activity::add(ActivityType::CHAPTER_CREATE, $chapter);
 
diff --git a/app/Entities/Repos/PageRepo.php b/app/Entities/Repos/PageRepo.php
index 521519dc0..637f4133a 100644
--- a/app/Entities/Repos/PageRepo.php
+++ b/app/Entities/Repos/PageRepo.php
@@ -164,7 +164,7 @@ class PageRepo
 
         $draft->draft = false;
         $draft->revision_count = 1;
-        $draft->priority = $this->getNewPriority($draft);
+        $draft->priority = $draft->priority ?: $this->getNewPriority($draft);
         $draft->save();
 
         $this->revisionRepo->storeNewForPage($draft, trans('entities.pages_initial_revision'));

From 3a36d3c847d235da3926f80303715e5349ee449f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jean-Ren=C3=A9=20ROUET?= <rouet@in2p3.fr>
Date: Tue, 11 Jul 2023 14:11:13 +0200
Subject: [PATCH 3/4] add tests for priority

---
 dev/api/requests/chapters-create.json |  6 +++--
 dev/api/requests/chapters-update.json |  5 ++--
 dev/api/requests/pages-create.json    |  5 ++--
 dev/api/requests/pages-update.json    |  5 ++--
 tests/Api/ChaptersApiTest.php         | 32 +++++++++++++++++++++++++
 tests/Api/PagesApiTest.php            | 34 +++++++++++++++++++++++++++
 6 files changed, 79 insertions(+), 8 deletions(-)

diff --git a/dev/api/requests/chapters-create.json b/dev/api/requests/chapters-create.json
index ca06fc298..afd3c71f1 100644
--- a/dev/api/requests/chapters-create.json
+++ b/dev/api/requests/chapters-create.json
@@ -5,5 +5,7 @@
   "tags": [
     {"name": "Category", "value": "Top Content"},
     {"name": "Rating", "value": "Highest"}
-  ]
-}
\ No newline at end of file
+  ],
+  "priority": 15
+}
+}
diff --git a/dev/api/requests/chapters-update.json b/dev/api/requests/chapters-update.json
index 6bd3a3e5c..f62d63d1e 100644
--- a/dev/api/requests/chapters-update.json
+++ b/dev/api/requests/chapters-update.json
@@ -5,5 +5,6 @@
   "tags": [
     {"name": "Category", "value": "Kinda Good Content"},
     {"name": "Rating", "value": "Medium"}
-  ]
-}
\ No newline at end of file
+  ],
+  "priority": 15
+}
diff --git a/dev/api/requests/pages-create.json b/dev/api/requests/pages-create.json
index 1f53b42d4..5a21a80c7 100644
--- a/dev/api/requests/pages-create.json
+++ b/dev/api/requests/pages-create.json
@@ -5,5 +5,6 @@
 	"tags": [
 		{"name": "Category", "value": "Not Bad Content"},
 		{"name": "Rating", "value": "Average"}
-	]
-}
\ No newline at end of file
+	],
+	"priority": 15
+}
diff --git a/dev/api/requests/pages-update.json b/dev/api/requests/pages-update.json
index b9bfeb630..fc8c73c0c 100644
--- a/dev/api/requests/pages-update.json
+++ b/dev/api/requests/pages-update.json
@@ -5,5 +5,6 @@
 	"tags": [
 		{"name": "Category", "value": "API Examples"},
 		{"name": "Rating", "value": "Alright"}
-	]
-}
\ No newline at end of file
+	],
+	"priority": 15
+}
diff --git a/tests/Api/ChaptersApiTest.php b/tests/Api/ChaptersApiTest.php
index 713d8bba4..a99a85af8 100644
--- a/tests/Api/ChaptersApiTest.php
+++ b/tests/Api/ChaptersApiTest.php
@@ -61,6 +61,37 @@ class ChaptersApiTest extends TestCase
         $this->assertActivityExists('chapter_create', $newItem);
     }
 
+    public function test_create_applies_correct_priority()
+    {
+        $this->actingAsApiEditor();
+        $book = $this->entities->book();
+        $details = [
+            'name'        => 'My API chapter',
+            'description' => 'A chapter created via the API',
+            'book_id'     => $book->id,
+            'tags'        => [
+                [
+                    'name'  => 'tagname',
+                    'value' => 'tagvalue',
+                ],
+            ],
+            'priority'     => 15,
+        ];
+
+        $resp = $this->postJson($this->baseEndpoint, $details);
+        $resp->assertStatus(200);
+        $newItem = Chapter::query()->orderByDesc('id')->where('name', '=', $details['name'])->first();
+        $resp->assertJson(array_merge($details, ['id' => $newItem->id, 'slug' => $newItem->slug]));
+        $this->assertDatabaseHas('tags', [
+            'entity_id'   => $newItem->id,
+            'entity_type' => $newItem->getMorphClass(),
+            'name'        => 'tagname',
+            'value'       => 'tagvalue',
+        ]);
+        $resp->assertJsonMissing(['pages' => []]);
+        $this->assertActivityExists('chapter_create', $newItem);
+    }
+
     public function test_chapter_name_needed_to_create()
     {
         $this->actingAsApiEditor();
@@ -137,6 +168,7 @@ class ChaptersApiTest extends TestCase
                     'value' => 'freshtagval',
                 ],
             ],
+            'priority'    => 15,
         ];
 
         $resp = $this->putJson($this->baseEndpoint . "/{$chapter->id}", $details);
diff --git a/tests/Api/PagesApiTest.php b/tests/Api/PagesApiTest.php
index 4a81f738b..a1f65692f 100644
--- a/tests/Api/PagesApiTest.php
+++ b/tests/Api/PagesApiTest.php
@@ -63,6 +63,39 @@ class PagesApiTest extends TestCase
         $this->assertActivityExists('page_create', $newItem);
     }
 
+    public function test_create_applies_correct_priority()
+    {
+        $this->actingAsApiEditor();
+        $book = $this->entities->book();
+        $details = [
+            'name'    => 'My API page',
+            'book_id' => $book->id,
+            'html'    => '<p>My new page content</p>',
+            'tags'    => [
+                [
+                    'name'  => 'tagname',
+                    'value' => 'tagvalue',
+                ],
+            ],
+            'priority' => 15,
+        ];
+
+        $resp = $this->postJson($this->baseEndpoint, $details);
+        unset($details['html']);
+        $resp->assertStatus(200);
+        $newItem = Page::query()->orderByDesc('id')->where('name', '=', $details['name'])->first();
+        $resp->assertJson(array_merge($details, ['id' => $newItem->id, 'slug' => $newItem->slug]));
+        $this->assertDatabaseHas('tags', [
+            'entity_id'   => $newItem->id,
+            'entity_type' => $newItem->getMorphClass(),
+            'name'        => 'tagname',
+            'value'       => 'tagvalue',
+        ]);
+        $resp->assertSeeText('My new page content');
+        $resp->assertJsonMissing(['book' => []]);
+        $this->assertActivityExists('page_create', $newItem);
+    }
+
     public function test_page_name_needed_to_create()
     {
         $this->actingAsApiEditor();
@@ -207,6 +240,7 @@ class PagesApiTest extends TestCase
                     'value' => 'freshtagval',
                 ],
             ],
+            'priority' => 15,
         ];
 
         $resp = $this->putJson($this->baseEndpoint . "/{$page->id}", $details);

From 9ca1139ab0d0f5dd8d8eda4e9cd96f6c33530344 Mon Sep 17 00:00:00 2001
From: Dan Brown <ssddanbrown@googlemail.com>
Date: Mon, 21 Aug 2023 15:40:53 +0100
Subject: [PATCH 4/4] API: Reviewed changes for API priority control

Review of #4313
- Made constructor changes while reviewing some classes.
- Updated API examples for consistency.
- Tweaked formatting for some array changes.
- Simplified added tests.
- Tweaked chapter/page repo priority handling to be simpler.

Performed manual API endpoint testing of page/chapter create/update.
---
 app/Api/ApiEntityListFormatter.php     |  9 ++++----
 app/Entities/Repos/ChapterRepo.php     | 13 ++++-------
 app/Entities/Repos/PageRepo.php        | 28 ++++++----------------
 dev/api/requests/chapters-create.json  |  5 ++--
 dev/api/requests/chapters-update.json  |  4 ++--
 dev/api/requests/pages-create.json     |  4 ++--
 dev/api/requests/pages-update.json     |  4 ++--
 dev/api/responses/chapters-create.json |  2 +-
 dev/api/responses/chapters-update.json |  2 +-
 dev/api/responses/pages-create.json    |  2 +-
 tests/Api/ChaptersApiTest.php          | 32 +-------------------------
 tests/Api/PagesApiTest.php             | 32 --------------------------
 12 files changed, 27 insertions(+), 110 deletions(-)

diff --git a/app/Api/ApiEntityListFormatter.php b/app/Api/ApiEntityListFormatter.php
index 7d00834e5..436d66d59 100644
--- a/app/Api/ApiEntityListFormatter.php
+++ b/app/Api/ApiEntityListFormatter.php
@@ -10,7 +10,7 @@ class ApiEntityListFormatter
      * The list to be formatted.
      * @var Entity[]
      */
-    protected $list = [];
+    protected array $list = [];
 
     /**
      * The fields to show in the formatted data.
@@ -19,10 +19,9 @@ class ApiEntityListFormatter
      * will be used for the resultant value. A null return value will omit the property.
      * @var array<string|int, string|callable>
      */
-    protected $fields = [
-        'id', 'name', 'slug', 'book_id', 'chapter_id',
-        'draft', 'template', 'created_at', 'updated_at',
-        'priority'
+    protected array $fields = [
+        'id', 'name', 'slug', 'book_id', 'chapter_id', 'draft',
+        'template', 'priority', 'created_at', 'updated_at',
     ];
 
     public function __construct(array $list)
diff --git a/app/Entities/Repos/ChapterRepo.php b/app/Entities/Repos/ChapterRepo.php
index dadeec7f8..977193d85 100644
--- a/app/Entities/Repos/ChapterRepo.php
+++ b/app/Entities/Repos/ChapterRepo.php
@@ -16,14 +16,9 @@ use Exception;
 
 class ChapterRepo
 {
-    protected $baseRepo;
-
-    /**
-     * ChapterRepo constructor.
-     */
-    public function __construct(BaseRepo $baseRepo)
-    {
-        $this->baseRepo = $baseRepo;
+    public function __construct(
+        protected BaseRepo $baseRepo
+    ) {
     }
 
     /**
@@ -49,7 +44,7 @@ class ChapterRepo
     {
         $chapter = new Chapter();
         $chapter->book_id = $parentBook->id;
-        $chapter->priority = $chapter->priority ?: (new BookContents($parentBook))->getLastPriority() + 1;
+        $chapter->priority = (new BookContents($parentBook))->getLastPriority() + 1;
         $this->baseRepo->create($chapter, $input);
         Activity::add(ActivityType::CHAPTER_CREATE, $chapter);
 
diff --git a/app/Entities/Repos/PageRepo.php b/app/Entities/Repos/PageRepo.php
index 637f4133a..61a1db63e 100644
--- a/app/Entities/Repos/PageRepo.php
+++ b/app/Entities/Repos/PageRepo.php
@@ -23,24 +23,12 @@ use Illuminate\Pagination\LengthAwarePaginator;
 
 class PageRepo
 {
-    protected BaseRepo $baseRepo;
-    protected RevisionRepo $revisionRepo;
-    protected ReferenceStore $referenceStore;
-    protected ReferenceUpdater $referenceUpdater;
-
-    /**
-     * PageRepo constructor.
-     */
     public function __construct(
-        BaseRepo $baseRepo,
-        RevisionRepo $revisionRepo,
-        ReferenceStore $referenceStore,
-        ReferenceUpdater $referenceUpdater
+        protected BaseRepo $baseRepo,
+        protected RevisionRepo $revisionRepo,
+        protected ReferenceStore $referenceStore,
+        protected ReferenceUpdater $referenceUpdater
     ) {
-        $this->baseRepo = $baseRepo;
-        $this->revisionRepo = $revisionRepo;
-        $this->referenceStore = $referenceStore;
-        $this->referenceUpdater = $referenceUpdater;
     }
 
     /**
@@ -159,13 +147,11 @@ class PageRepo
      */
     public function publishDraft(Page $draft, array $input): Page
     {
-        $this->updateTemplateStatusAndContentFromInput($draft, $input);
-        $this->baseRepo->update($draft, $input);
-
         $draft->draft = false;
         $draft->revision_count = 1;
-        $draft->priority = $draft->priority ?: $this->getNewPriority($draft);
-        $draft->save();
+        $draft->priority = $this->getNewPriority($draft);
+        $this->updateTemplateStatusAndContentFromInput($draft, $input);
+        $this->baseRepo->update($draft, $input);
 
         $this->revisionRepo->storeNewForPage($draft, trans('entities.pages_initial_revision'));
         $this->referenceStore->updateForPage($draft);
diff --git a/dev/api/requests/chapters-create.json b/dev/api/requests/chapters-create.json
index afd3c71f1..a7a0e072c 100644
--- a/dev/api/requests/chapters-create.json
+++ b/dev/api/requests/chapters-create.json
@@ -2,10 +2,9 @@
   "book_id": 1,
   "name": "My fantastic new chapter",
   "description": "This is a great new chapter that I've created via the API",
+  "priority": 15,
   "tags": [
     {"name": "Category", "value": "Top Content"},
     {"name": "Rating", "value": "Highest"}
-  ],
-  "priority": 15
-}
+  ]
 }
diff --git a/dev/api/requests/chapters-update.json b/dev/api/requests/chapters-update.json
index f62d63d1e..18c40301b 100644
--- a/dev/api/requests/chapters-update.json
+++ b/dev/api/requests/chapters-update.json
@@ -2,9 +2,9 @@
   "book_id": 1,
   "name": "My fantastic updated chapter",
   "description": "This is an updated chapter that I've altered via the API",
+  "priority": 16,
   "tags": [
     {"name": "Category", "value": "Kinda Good Content"},
     {"name": "Rating", "value": "Medium"}
-  ],
-  "priority": 15
+  ]
 }
diff --git a/dev/api/requests/pages-create.json b/dev/api/requests/pages-create.json
index 5a21a80c7..bb32943a2 100644
--- a/dev/api/requests/pages-create.json
+++ b/dev/api/requests/pages-create.json
@@ -2,9 +2,9 @@
 	"book_id": 1,
 	"name": "My API Page",
 	"html": "<p>my new API page</p>",
+	"priority": 15,
 	"tags": [
 		{"name": "Category", "value": "Not Bad Content"},
 		{"name": "Rating", "value": "Average"}
-	],
-	"priority": 15
+	]
 }
diff --git a/dev/api/requests/pages-update.json b/dev/api/requests/pages-update.json
index fc8c73c0c..e3ca9004e 100644
--- a/dev/api/requests/pages-update.json
+++ b/dev/api/requests/pages-update.json
@@ -2,9 +2,9 @@
 	"chapter_id": 1,
 	"name": "My updated API Page",
 	"html": "<p>my new API page - Updated</p>",
+	"priority": 16,
 	"tags": [
 		{"name": "Category", "value": "API Examples"},
 		{"name": "Rating", "value": "Alright"}
-	],
-	"priority": 15
+	]
 }
diff --git a/dev/api/responses/chapters-create.json b/dev/api/responses/chapters-create.json
index 4dbc764b1..cf47b123d 100644
--- a/dev/api/responses/chapters-create.json
+++ b/dev/api/responses/chapters-create.json
@@ -4,7 +4,7 @@
   "slug": "my-fantastic-new-chapter",
   "name": "My fantastic new chapter",
   "description": "This is a great new chapter that I've created via the API",
-  "priority": 6,
+  "priority": 15,
   "created_by": 1,
   "updated_by": 1,
   "owned_by": 1,
diff --git a/dev/api/responses/chapters-update.json b/dev/api/responses/chapters-update.json
index cc454d740..a4940af2d 100644
--- a/dev/api/responses/chapters-update.json
+++ b/dev/api/responses/chapters-update.json
@@ -4,7 +4,7 @@
   "slug": "my-fantastic-updated-chapter",
   "name": "My fantastic updated chapter",
   "description": "This is an updated chapter that I've altered via the API",
-  "priority": 7,
+  "priority": 16,
   "created_at": "2020-05-22T23:03:35.000000Z",
   "updated_at": "2020-05-22T23:07:20.000000Z",
   "created_by": 1,
diff --git a/dev/api/responses/pages-create.json b/dev/api/responses/pages-create.json
index 385d5384e..11f5ab8c8 100644
--- a/dev/api/responses/pages-create.json
+++ b/dev/api/responses/pages-create.json
@@ -6,7 +6,7 @@
 	"slug": "my-api-page",
 	"html": "<p id=\"bkmrk-my-new-api-page\">my new API page</p>",
 	"raw_html": "<p id=\"bkmrk-my-new-api-page\">my new API page</p>",
-	"priority": 14,
+	"priority": 15,
 	"created_at": "2020-11-28T15:01:39.000000Z",
 	"updated_at": "2020-11-28T15:01:39.000000Z",
 	"created_by": {
diff --git a/tests/Api/ChaptersApiTest.php b/tests/Api/ChaptersApiTest.php
index a99a85af8..0629f3aed 100644
--- a/tests/Api/ChaptersApiTest.php
+++ b/tests/Api/ChaptersApiTest.php
@@ -45,37 +45,7 @@ class ChaptersApiTest extends TestCase
                     'value' => 'tagvalue',
                 ],
             ],
-        ];
-
-        $resp = $this->postJson($this->baseEndpoint, $details);
-        $resp->assertStatus(200);
-        $newItem = Chapter::query()->orderByDesc('id')->where('name', '=', $details['name'])->first();
-        $resp->assertJson(array_merge($details, ['id' => $newItem->id, 'slug' => $newItem->slug]));
-        $this->assertDatabaseHas('tags', [
-            'entity_id'   => $newItem->id,
-            'entity_type' => $newItem->getMorphClass(),
-            'name'        => 'tagname',
-            'value'       => 'tagvalue',
-        ]);
-        $resp->assertJsonMissing(['pages' => []]);
-        $this->assertActivityExists('chapter_create', $newItem);
-    }
-
-    public function test_create_applies_correct_priority()
-    {
-        $this->actingAsApiEditor();
-        $book = $this->entities->book();
-        $details = [
-            'name'        => 'My API chapter',
-            'description' => 'A chapter created via the API',
-            'book_id'     => $book->id,
-            'tags'        => [
-                [
-                    'name'  => 'tagname',
-                    'value' => 'tagvalue',
-                ],
-            ],
-            'priority'     => 15,
+            'priority' => 15,
         ];
 
         $resp = $this->postJson($this->baseEndpoint, $details);
diff --git a/tests/Api/PagesApiTest.php b/tests/Api/PagesApiTest.php
index a1f65692f..0d084472d 100644
--- a/tests/Api/PagesApiTest.php
+++ b/tests/Api/PagesApiTest.php
@@ -32,38 +32,6 @@ class PagesApiTest extends TestCase
     }
 
     public function test_create_endpoint()
-    {
-        $this->actingAsApiEditor();
-        $book = $this->entities->book();
-        $details = [
-            'name'    => 'My API page',
-            'book_id' => $book->id,
-            'html'    => '<p>My new page content</p>',
-            'tags'    => [
-                [
-                    'name'  => 'tagname',
-                    'value' => 'tagvalue',
-                ],
-            ],
-        ];
-
-        $resp = $this->postJson($this->baseEndpoint, $details);
-        unset($details['html']);
-        $resp->assertStatus(200);
-        $newItem = Page::query()->orderByDesc('id')->where('name', '=', $details['name'])->first();
-        $resp->assertJson(array_merge($details, ['id' => $newItem->id, 'slug' => $newItem->slug]));
-        $this->assertDatabaseHas('tags', [
-            'entity_id'   => $newItem->id,
-            'entity_type' => $newItem->getMorphClass(),
-            'name'        => 'tagname',
-            'value'       => 'tagvalue',
-        ]);
-        $resp->assertSeeText('My new page content');
-        $resp->assertJsonMissing(['book' => []]);
-        $this->assertActivityExists('page_create', $newItem);
-    }
-
-    public function test_create_applies_correct_priority()
     {
         $this->actingAsApiEditor();
         $book = $this->entities->book();