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;
$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');
}
}
'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',
<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') }}">
<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
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']);
<?php
-namespace Tests;
+namespace Tests\Settings;
use BookStack\Entities\Models\Book;
use BookStack\Entities\Models\Bookshelf;
use BookStack\Entities\Models\Page;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;
+use Tests\TestCase;
class RecycleBinTest extends TestCase
{
--- /dev/null
+<?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');
+ }
+}
<?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
{