]> BookStack Code Mirror - bookstack/commitdiff
Added maintenance action to regenerate references
authorDan Brown <redacted>
Mon, 29 Aug 2022 16:30:26 +0000 (17:30 +0100)
committerDan Brown <redacted>
Mon, 29 Aug 2022 16:30:26 +0000 (17:30 +0100)
app/Http/Controllers/MaintenanceController.php
resources/lang/en/settings.php
resources/views/settings/maintenance.blade.php
routes/web.php
tests/Settings/RecycleBinTest.php [moved from tests/RecycleBinTest.php with 99% similarity]
tests/Settings/RegenerateReferencesTest.php [new file with mode: 0644]
tests/Settings/TestEmailTest.php [moved from tests/TestEmailTest.php with 98% similarity]

index f13266d7c6150c77b255f49e7f9131ea8ceb98a1..8bfefb7acb95f1fe4c7d509f4e7084ba14e4da05 100644 (file)
@@ -5,6 +5,7 @@ namespace BookStack\Http\Controllers;
 use BookStack\Actions\ActivityType;
 use BookStack\Entities\Tools\TrashCan;
 use BookStack\Notifications\TestEmail;
+use BookStack\References\ReferenceStore;
 use BookStack\Uploads\ImageService;
 use Illuminate\Http\Request;
 
@@ -74,6 +75,24 @@ class MaintenanceController extends Controller
             $this->showErrorNotification($errorMessage);
         }
 
-        return redirect('/settings/maintenance#image-cleanup')->withInput();
+        return redirect('/settings/maintenance#image-cleanup');
+    }
+
+    /**
+     * Action to regenerate the reference index in the system.
+     */
+    public function regenerateReferences(ReferenceStore $referenceStore)
+    {
+        $this->checkPermission('settings-manage');
+        $this->logActivity(ActivityType::MAINTENANCE_ACTION_RUN, 'regenerate-references');
+
+        try {
+            $referenceStore->updateForAllPages();
+            $this->showSuccessNotification(trans('settings.maint_regen_references_success'));
+        } catch (\Exception $exception) {
+            $this->showErrorNotification($exception->getMessage());
+        }
+
+        return redirect('/settings/maintenance#regenerate-references');
     }
 }
index 3bfe70bc4cd556934240e8a78d2cc2d7ba41e542..9dbd96c5af30b95731d44a313ee79f3f31226307 100755 (executable)
@@ -89,6 +89,10 @@ return [
     'maint_send_test_email_mail_text' => 'Congratulations! As you received this email notification, your email settings seem to be configured properly.',
     'maint_recycle_bin_desc' => 'Deleted shelves, books, chapters & pages are sent to the recycle bin so they can be restored or permanently deleted. Older items in the recycle bin may be automatically removed after a while depending on system configuration.',
     'maint_recycle_bin_open' => 'Open Recycle Bin',
+    'maint_regen_references' => 'Regenerate References',
+    'maint_regen_references_desc' => 'This action will rebuild the cross-item reference index within the database. This is usually handled automatically but this action can be useful to index old content or content added via unofficial methods.',
+    'maint_regen_references_success' => 'Reference index has been regenerated!',
+    'maint_timeout_command_note' => 'Note: This action can take time to run, which can lead to timeout issues in some web environments. As an alternative, this action be performed using a terminal command.',
 
     // Recycle Bin
     'recycle_bin' => 'Recycle Bin',
index a2a9ebc8181fa89c767d48068f3242e2555380bd..7ee966e00594ac42ae3e11c1b98af06584026776 100644 (file)
 
     <div id="image-cleanup" class="card content-wrap auto-height">
         <h2 class="list-heading">{{ trans('settings.maint_image_cleanup') }}</h2>
-        <div class="grid half gap-xl">
+        <div class="grid left-focus gap-xl">
             <div>
                 <p class="small text-muted">{{ trans('settings.maint_image_cleanup_desc') }}</p>
+                <p class="small text-muted italic">{{ trans('settings.maint_timeout_command_note') }}</p>
             </div>
             <div>
                 <form method="POST" action="{{ url('/settings/maintenance/cleanup-images') }}">
@@ -55,7 +56,7 @@
 
     <div id="send-test-email" class="card content-wrap auto-height">
         <h2 class="list-heading">{{ trans('settings.maint_send_test_email') }}</h2>
-        <div class="grid half gap-xl">
+        <div class="grid left-focus gap-xl">
             <div>
                 <p class="small text-muted">{{ trans('settings.maint_send_test_email_desc') }}</p>
             </div>
         </div>
     </div>
 
+    <div id="regenerate-references" class="card content-wrap auto-height">
+        <h2 class="list-heading">{{ trans('settings.maint_regen_references') }}</h2>
+        <div class="grid left-focus gap-xl">
+            <div>
+                <p class="small text-muted">{{ trans('settings.maint_regen_references_desc') }}</p>
+                <p class="small text-muted italic">{{ trans('settings.maint_timeout_command_note') }}</p>
+            </div>
+            <div>
+                <form method="POST" action="{{ url('/settings/maintenance/regenerate-references') }}">
+                    {!! csrf_field()  !!}
+                    <button class="button outline">{{ trans('settings.maint_regen_references') }}</button>
+                </form>
+            </div>
+        </div>
+    </div>
+
 </div>
 @stop
index dc46821cb86eb63ff98f588035c020643b11c4ac..26d4b6f133b39618f6836d42e6235770633f9141 100644 (file)
@@ -218,6 +218,7 @@ Route::middleware('auth')->group(function () {
     Route::get('/settings/maintenance', [MaintenanceController::class, 'index']);
     Route::delete('/settings/maintenance/cleanup-images', [MaintenanceController::class, 'cleanupImages']);
     Route::post('/settings/maintenance/send-test-email', [MaintenanceController::class, 'sendTestEmail']);
+    Route::post('/settings/maintenance/regenerate-references', [MaintenanceController::class, 'regenerateReferences']);
 
     // Recycle Bin
     Route::get('/settings/recycle-bin', [RecycleBinController::class, 'index']);
similarity index 99%
rename from tests/RecycleBinTest.php
rename to tests/Settings/RecycleBinTest.php
index 0e05243380f52cd2838d15b8889aa5a420f06b32..465c1aaade5e8859d6e7c1b8da0fb18c541dd221 100644 (file)
@@ -1,6 +1,6 @@
 <?php
 
-namespace Tests;
+namespace Tests\Settings;
 
 use BookStack\Entities\Models\Book;
 use BookStack\Entities\Models\Bookshelf;
@@ -10,6 +10,7 @@ use BookStack\Entities\Models\Entity;
 use BookStack\Entities\Models\Page;
 use Illuminate\Support\Carbon;
 use Illuminate\Support\Facades\DB;
+use Tests\TestCase;
 
 class RecycleBinTest extends TestCase
 {
diff --git a/tests/Settings/RegenerateReferencesTest.php b/tests/Settings/RegenerateReferencesTest.php
new file mode 100644 (file)
index 0000000..0f31220
--- /dev/null
@@ -0,0 +1,55 @@
+<?php
+
+namespace Tests\Settings;
+
+use BookStack\Actions\ActivityType;
+use BookStack\References\ReferenceStore;
+use Tests\TestCase;
+
+class RegenerateReferencesTest extends TestCase
+{
+    public function test_option_visible_on_maintenance_page()
+    {
+        $pageView = $this->asAdmin()->get('/settings/maintenance');
+        $formCssSelector = 'form[action$="/settings/maintenance/regenerate-references"]';
+        $html = $this->withHtml($pageView);
+        $html->assertElementExists('#regenerate-references');
+        $html->assertElementExists($formCssSelector);
+        $html->assertElementContains($formCssSelector . ' button', 'Regenerate References');
+    }
+
+    public function test_action_runs_reference_regen()
+    {
+        $this->mock(ReferenceStore::class)
+            ->shouldReceive('updateForAllPages')
+            ->once();
+
+        $resp = $this->asAdmin()->post('/settings/maintenance/regenerate-references');
+        $resp->assertRedirect('/settings/maintenance#regenerate-references');
+        $this->assertSessionHas('success', 'Reference index has been regenerated!');
+        $this->assertActivityExists(ActivityType::MAINTENANCE_ACTION_RUN, null, 'regenerate-references');
+    }
+
+    public function test_settings_manage_permission_required()
+    {
+        $editor = $this->getEditor();
+        $resp = $this->actingAs($editor)->post('/settings/maintenance/regenerate-references');
+        $this->assertPermissionError($resp);
+
+        $this->giveUserPermissions($editor, ['settings-manage']);
+
+        $resp = $this->actingAs($editor)->post('/settings/maintenance/regenerate-references');
+        $this->assertNotPermissionError($resp);
+    }
+
+    public function test_action_failed_shown_as_error_notification()
+    {
+        $this->mock(ReferenceStore::class)
+            ->shouldReceive('updateForAllPages')
+            ->andThrow(\Exception::class, 'A badger stopped the task');
+
+        $resp = $this->asAdmin()->post('/settings/maintenance/regenerate-references');
+        $resp->assertRedirect('/settings/maintenance#regenerate-references');
+        $this->assertSessionError('A badger stopped the task');
+    }
+}
similarity index 98%
rename from tests/TestEmailTest.php
rename to tests/Settings/TestEmailTest.php
index 97f98225d4fe8b82920a2eb4b5d1cfc14f17c9fe..31c51158f8b87645f8be30c2e6328f65048b5cce 100644 (file)
@@ -1,10 +1,11 @@
 <?php
 
-namespace Tests;
+namespace Tests\Settings;
 
 use BookStack\Notifications\TestEmail;
 use Illuminate\Contracts\Notifications\Dispatcher;
 use Illuminate\Support\Facades\Notification;
+use Tests\TestCase;
 
 class TestEmailTest extends TestCase
 {