]> BookStack Code Mirror - bookstack/commitdiff
Merge pull request #4262 from BookStackApp/command_cleanup
authorDan Brown <redacted>
Wed, 24 May 2023 12:22:25 +0000 (13:22 +0100)
committerGitHub <redacted>
Wed, 24 May 2023 12:22:25 +0000 (13:22 +0100)
Command cleanup & alignment

22 files changed:
app/Activity/Models/View.php
app/Console/Commands/CleanupImagesCommand.php [moved from app/Console/Commands/CleanupImages.php with 61% similarity]
app/Console/Commands/ClearActivityCommand.php [moved from app/Console/Commands/ClearActivity.php with 57% similarity]
app/Console/Commands/ClearRevisionsCommand.php [moved from app/Console/Commands/ClearRevisions.php with 61% similarity]
app/Console/Commands/ClearViewsCommand.php [moved from app/Console/Commands/ClearViews.php with 68% similarity]
app/Console/Commands/CopyShelfPermissionsCommand.php [moved from app/Console/Commands/CopyShelfPermissions.php with 78% similarity]
app/Console/Commands/CreateAdminCommand.php [moved from app/Console/Commands/CreateAdmin.php with 81% similarity]
app/Console/Commands/DeleteUsers.php [deleted file]
app/Console/Commands/DeleteUsersCommand.php [new file with mode: 0644]
app/Console/Commands/RegenerateCommentContentCommand.php [moved from app/Console/Commands/RegenerateCommentContent.php with 63% similarity]
app/Console/Commands/RegeneratePermissionsCommand.php [moved from app/Console/Commands/RegeneratePermissions.php with 58% similarity]
app/Console/Commands/RegenerateReferencesCommand.php [moved from app/Console/Commands/RegenerateReferences.php with 59% similarity]
app/Console/Commands/RegenerateSearchCommand.php [moved from app/Console/Commands/RegenerateSearch.php with 61% similarity]
app/Console/Commands/ResetMfaCommand.php [moved from app/Console/Commands/ResetMfa.php with 80% similarity]
app/Console/Commands/UpdateUrlCommand.php [moved from app/Console/Commands/UpdateUrl.php with 97% similarity]
app/Console/Commands/UpgradeDatabaseEncodingCommand.php [moved from app/Console/Commands/UpgradeDatabaseEncoding.php with 69% similarity]
app/Uploads/ImageService.php
tests/Commands/CleanupImagesCommandTest.php [new file with mode: 0644]
tests/Commands/CopyShelfPermissionsCommandTest.php
tests/Commands/DeleteUsersCommandTest.php [new file with mode: 0644]
tests/Commands/RegenerateSearchCommandTest.php [new file with mode: 0644]
tests/Commands/UpgradeDatabaseEncodingCommandTest.php [new file with mode: 0644]

index a6bc2139ee5685053d66ed14b79abe4dfb7c74a8..512e0829596089434f0ad772d455fa04d2fdcfc4 100644 (file)
@@ -54,12 +54,4 @@ class View extends Model
 
         return $view->views;
     }
-
-    /**
-     * Clear all views from the system.
-     */
-    public static function clearAll()
-    {
-        static::query()->truncate();
-    }
 }
similarity index 61%
rename from app/Console/Commands/CleanupImages.php
rename to app/Console/Commands/CleanupImagesCommand.php
index 7221501979a529861e8e505ce66f9f79d7771160..fe924b0f46b79af8c694c37bf98087ae8a0e272b 100644 (file)
@@ -6,7 +6,7 @@ use BookStack\Uploads\ImageService;
 use Illuminate\Console\Command;
 use Symfony\Component\Console\Output\OutputInterface;
 
-class CleanupImages extends Command
+class CleanupImagesCommand extends Command
 {
     /**
      * The name and signature of the console command.
@@ -25,60 +25,49 @@ class CleanupImages extends Command
      */
     protected $description = 'Cleanup images and drawings';
 
-    protected $imageService;
-
-    /**
-     * Create a new command instance.
-     *
-     * @param \BookStack\Uploads\ImageService $imageService
-     */
-    public function __construct(ImageService $imageService)
-    {
-        $this->imageService = $imageService;
-        parent::__construct();
-    }
-
     /**
      * Execute the console command.
-     *
-     * @return mixed
      */
-    public function handle()
+    public function handle(ImageService $imageService): int
     {
-        $checkRevisions = $this->option('all') ? false : true;
-        $dryRun = $this->option('force') ? false : true;
+        $checkRevisions = !$this->option('all');
+        $dryRun = !$this->option('force');
 
         if (!$dryRun) {
-            $proceed = $this->confirm("This operation is destructive and is not guaranteed to be fully accurate.\nEnsure you have a backup of your images.\nAre you sure you want to proceed?");
+            $this->warn("This operation is destructive and is not guaranteed to be fully accurate.\nEnsure you have a backup of your images.\n");
+            $proceed = $this->confirm("Are you sure you want to proceed?");
             if (!$proceed) {
-                return;
+                return 0;
             }
         }
 
-        $deleted = $this->imageService->deleteUnusedImages($checkRevisions, $dryRun);
+        $deleted = $imageService->deleteUnusedImages($checkRevisions, $dryRun);
         $deleteCount = count($deleted);
 
         if ($dryRun) {
-            $this->comment('Dry run, No images have been deleted');
+            $this->comment('Dry run, no images have been deleted');
             $this->comment($deleteCount . ' images found that would have been deleted');
             $this->showDeletedImages($deleted);
             $this->comment('Run with -f or --force to perform deletions');
 
-            return;
+            return 0;
         }
 
         $this->showDeletedImages($deleted);
         $this->comment($deleteCount . ' images deleted');
+        return 0;
     }
 
-    protected function showDeletedImages($paths)
+    protected function showDeletedImages($paths): void
     {
         if ($this->getOutput()->getVerbosity() <= OutputInterface::VERBOSITY_NORMAL) {
             return;
         }
+
         if (count($paths) > 0) {
             $this->line('Images to delete:');
         }
+
         foreach ($paths as $path) {
             $this->line($path);
         }
similarity index 57%
rename from app/Console/Commands/ClearActivity.php
rename to app/Console/Commands/ClearActivityCommand.php
index 5ccf6e972b5752b52aa3534c03b797193e89dea1..54085c12be3c762c06a5e189996872bece641220 100644 (file)
@@ -5,7 +5,7 @@ namespace BookStack\Console\Commands;
 use BookStack\Activity\Models\Activity;
 use Illuminate\Console\Command;
 
-class ClearActivity extends Command
+class ClearActivityCommand extends Command
 {
     /**
      * The name and signature of the console command.
@@ -21,27 +21,13 @@ class ClearActivity extends Command
      */
     protected $description = 'Clear user activity from the system';
 
-    protected $activity;
-
-    /**
-     * Create a new command instance.
-     *
-     * @param Activity $activity
-     */
-    public function __construct(Activity $activity)
-    {
-        $this->activity = $activity;
-        parent::__construct();
-    }
-
     /**
      * Execute the console command.
-     *
-     * @return mixed
      */
-    public function handle()
+    public function handle(): int
     {
-        $this->activity->newQuery()->truncate();
+        Activity::query()->truncate();
         $this->comment('System activity cleared');
+        return 0;
     }
 }
similarity index 61%
rename from app/Console/Commands/ClearRevisions.php
rename to app/Console/Commands/ClearRevisionsCommand.php
index 681a7564b282e3e6d279c1ffa2b9ddfbce96488e..ad001fdb1e8954f3268c347f417e05bfa8f94aef 100644 (file)
@@ -5,7 +5,7 @@ namespace BookStack\Console\Commands;
 use BookStack\Entities\Models\PageRevision;
 use Illuminate\Console\Command;
 
-class ClearRevisions extends Command
+class ClearRevisionsCommand extends Command
 {
     /**
      * The name and signature of the console command.
@@ -23,28 +23,14 @@ class ClearRevisions extends Command
      */
     protected $description = 'Clear page revisions';
 
-    protected $pageRevision;
-
-    /**
-     * Create a new command instance.
-     *
-     * @param PageRevision $pageRevision
-     */
-    public function __construct(PageRevision $pageRevision)
-    {
-        $this->pageRevision = $pageRevision;
-        parent::__construct();
-    }
-
     /**
      * Execute the console command.
-     *
-     * @return mixed
      */
-    public function handle()
+    public function handle(): int
     {
         $deleteTypes = $this->option('all') ? ['version', 'update_draft'] : ['version'];
-        $this->pageRevision->newQuery()->whereIn('type', $deleteTypes)->delete();
+        PageRevision::query()->whereIn('type', $deleteTypes)->delete();
         $this->comment('Revisions deleted');
+        return 0;
     }
 }
similarity index 68%
rename from app/Console/Commands/ClearViews.php
rename to app/Console/Commands/ClearViewsCommand.php
index c76b78d231d1c2685bbdb0113281955e33b6c133..87ea503dc479f56f652a863f385b2b03c4ae07b0 100644 (file)
@@ -5,7 +5,7 @@ namespace BookStack\Console\Commands;
 use BookStack\Activity\Models\View;
 use Illuminate\Console\Command;
 
-class ClearViews extends Command
+class ClearViewsCommand extends Command
 {
     /**
      * The name and signature of the console command.
@@ -21,22 +21,13 @@ class ClearViews extends Command
      */
     protected $description = 'Clear all view-counts for all entities';
 
-    /**
-     * Create a new command instance.
-     */
-    public function __construct()
-    {
-        parent::__construct();
-    }
-
     /**
      * Execute the console command.
-     *
-     * @return mixed
      */
-    public function handle()
+    public function handle(): int
     {
-        View::clearAll();
+        View::query()->truncate();
         $this->comment('Views cleared');
+        return 0;
     }
 }
similarity index 78%
rename from app/Console/Commands/CopyShelfPermissions.php
rename to app/Console/Commands/CopyShelfPermissionsCommand.php
index ec4c875ffa97d3935d0101383559d7ff63508c54..fc11484bd4dfa3da89650e49a159664a05c372d8 100644 (file)
@@ -6,7 +6,7 @@ use BookStack\Entities\Models\Bookshelf;
 use BookStack\Entities\Tools\PermissionsUpdater;
 use Illuminate\Console\Command;
 
-class CopyShelfPermissions extends Command
+class CopyShelfPermissionsCommand extends Command
 {
     /**
      * The name and signature of the console command.
@@ -25,25 +25,10 @@ class CopyShelfPermissions extends Command
      */
     protected $description = 'Copy shelf permissions to all child books';
 
-    protected PermissionsUpdater $permissionsUpdater;
-
-    /**
-     * Create a new command instance.
-     *
-     * @return void
-     */
-    public function __construct(PermissionsUpdater $permissionsUpdater)
-    {
-        $this->permissionsUpdater = $permissionsUpdater;
-        parent::__construct();
-    }
-
     /**
      * Execute the console command.
-     *
-     * @return mixed
      */
-    public function handle()
+    public function handle(PermissionsUpdater $permissionsUpdater): int
     {
         $shelfSlug = $this->option('slug');
         $cascadeAll = $this->option('all');
@@ -52,7 +37,7 @@ class CopyShelfPermissions extends Command
         if (!$cascadeAll && !$shelfSlug) {
             $this->error('Either a --slug or --all option must be provided.');
 
-            return;
+            return 1;
         }
 
         if ($cascadeAll) {
@@ -63,7 +48,7 @@ class CopyShelfPermissions extends Command
             );
 
             if (!$continue && !$this->hasOption('no-interaction')) {
-                return;
+                return 0;
             }
 
             $shelves = Bookshelf::query()->get(['id']);
@@ -77,10 +62,11 @@ class CopyShelfPermissions extends Command
         }
 
         foreach ($shelves as $shelf) {
-            $this->permissionsUpdater->updateBookPermissionsFromShelf($shelf, false);
+            $permissionsUpdater->updateBookPermissionsFromShelf($shelf, false);
             $this->info('Copied permissions for shelf [' . $shelf->id . ']');
         }
 
         $this->info('Permissions copied for ' . $shelves->count() . ' shelves.');
+        return 0;
     }
 }
similarity index 81%
rename from app/Console/Commands/CreateAdmin.php
rename to app/Console/Commands/CreateAdminCommand.php
index 377207ed7816d53345b1f5e01fa0253ff38aa626..82b6e50aa522a372f208b070086e540f50d0d7d9 100644 (file)
@@ -2,7 +2,6 @@
 
 namespace BookStack\Console\Commands;
 
-use BookStack\Exceptions\NotFoundException;
 use BookStack\Users\Models\Role;
 use BookStack\Users\UserRepo;
 use Illuminate\Console\Command;
@@ -10,9 +9,8 @@ use Illuminate\Support\Facades\Validator;
 use Illuminate\Support\Str;
 use Illuminate\Validation\Rules\Password;
 use Illuminate\Validation\Rules\Unique;
-use Symfony\Component\Console\Command\Command as SymfonyCommand;
 
-class CreateAdmin extends Command
+class CreateAdminCommand extends Command
 {
     /**
      * The name and signature of the console command.
@@ -32,25 +30,10 @@ class CreateAdmin extends Command
      */
     protected $description = 'Add a new admin user to the system';
 
-    protected $userRepo;
-
-    /**
-     * Create a new command instance.
-     */
-    public function __construct(UserRepo $userRepo)
-    {
-        $this->userRepo = $userRepo;
-        parent::__construct();
-    }
-
     /**
      * Execute the console command.
-     *
-     * @throws NotFoundException
-     *
-     * @return mixed
      */
-    public function handle()
+    public function handle(UserRepo $userRepo): int
     {
         $details = $this->snakeCaseOptions();
 
@@ -82,17 +65,17 @@ class CreateAdmin extends Command
                 $this->error($error);
             }
 
-            return SymfonyCommand::FAILURE;
+            return 1;
         }
 
-        $user = $this->userRepo->createWithoutActivity($validator->validated());
+        $user = $userRepo->createWithoutActivity($validator->validated());
         $user->attachRole(Role::getSystemRole('admin'));
         $user->email_confirmed = true;
         $user->save();
 
         $this->info("Admin account with email \"{$user->email}\" successfully created!");
 
-        return SymfonyCommand::SUCCESS;
+        return 0;
     }
 
     protected function snakeCaseOptions(): array
diff --git a/app/Console/Commands/DeleteUsers.php b/app/Console/Commands/DeleteUsers.php
deleted file mode 100644 (file)
index c16a5d9..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-<?php
-
-namespace BookStack\Console\Commands;
-
-use BookStack\Users\Models\User;
-use BookStack\Users\UserRepo;
-use Illuminate\Console\Command;
-
-class DeleteUsers extends Command
-{
-    /**
-     * The name and signature of the console command.
-     *
-     * @var string
-     */
-    protected $signature = 'bookstack:delete-users';
-
-    protected $userRepo;
-
-    /**
-     * The console command description.
-     *
-     * @var string
-     */
-    protected $description = 'Delete users that are not "admin" or system users';
-
-    public function __construct(UserRepo $userRepo)
-    {
-        $this->userRepo = $userRepo;
-        parent::__construct();
-    }
-
-    public function handle()
-    {
-        $confirm = $this->ask('This will delete all users from the system that are not "admin" or system users. Are you sure you want to continue? (Type "yes" to continue)');
-        $numDeleted = 0;
-        if (strtolower(trim($confirm)) === 'yes') {
-            $totalUsers = User::query()->count();
-            $users = User::query()->whereNull('system_name')->with('roles')->get();
-            foreach ($users as $user) {
-                if ($user->hasSystemRole('admin')) {
-                    // don't delete users with "admin" role
-                    continue;
-                }
-                $this->userRepo->destroy($user);
-                $numDeleted++;
-            }
-            $this->info("Deleted $numDeleted of $totalUsers total users.");
-        } else {
-            $this->info('Exiting...');
-        }
-    }
-}
diff --git a/app/Console/Commands/DeleteUsersCommand.php b/app/Console/Commands/DeleteUsersCommand.php
new file mode 100644 (file)
index 0000000..d5c85dc
--- /dev/null
@@ -0,0 +1,53 @@
+<?php
+
+namespace BookStack\Console\Commands;
+
+use BookStack\Users\Models\User;
+use BookStack\Users\UserRepo;
+use Illuminate\Console\Command;
+
+class DeleteUsersCommand extends Command
+{
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $signature = 'bookstack:delete-users';
+
+    /**
+     * The console command description.
+     *
+     * @var string
+     */
+    protected $description = 'Delete users that are not "admin" or system users';
+
+    /**
+     * Execute the console command.
+     */
+    public function handle(UserRepo $userRepo): int
+    {
+        $this->warn('This will delete all users from the system that are not "admin" or system users.');
+        $confirm = $this->confirm('Are you sure you want to continue?');
+
+        if (!$confirm) {
+            return 0;
+        }
+
+        $totalUsers = User::query()->count();
+        $numDeleted = 0;
+        $users = User::query()->whereNull('system_name')->with('roles')->get();
+
+        foreach ($users as $user) {
+            if ($user->hasSystemRole('admin')) {
+                // don't delete users with "admin" role
+                continue;
+            }
+            $userRepo->destroy($user);
+            $numDeleted++;
+        }
+
+        $this->info("Deleted $numDeleted of $totalUsers total users.");
+        return 0;
+    }
+}
similarity index 63%
rename from app/Console/Commands/RegenerateCommentContent.php
rename to app/Console/Commands/RegenerateCommentContentCommand.php
index 3052559e305b1e9a96ae2f453bc0a43e5ac6c33b..f7ec426209f5eb29cf6aadf2eff69c9920cbcd2b 100644 (file)
@@ -7,14 +7,15 @@ use BookStack\Activity\Models\Comment;
 use Illuminate\Console\Command;
 use Illuminate\Support\Facades\DB;
 
-class RegenerateCommentContent extends Command
+class RegenerateCommentContentCommand extends Command
 {
     /**
      * The name and signature of the console command.
      *
      * @var string
      */
-    protected $signature = 'bookstack:regenerate-comment-content {--database= : The database connection to use.}';
+    protected $signature = 'bookstack:regenerate-comment-content
+                            {--database= : The database connection to use}';
 
     /**
      * The console command description.
@@ -23,35 +24,19 @@ class RegenerateCommentContent extends Command
      */
     protected $description = 'Regenerate the stored HTML of all comments';
 
-    /**
-     * @var CommentRepo
-     */
-    protected $commentRepo;
-
-    /**
-     * Create a new command instance.
-     */
-    public function __construct(CommentRepo $commentRepo)
-    {
-        $this->commentRepo = $commentRepo;
-        parent::__construct();
-    }
-
     /**
      * Execute the console command.
-     *
-     * @return mixed
      */
-    public function handle()
+    public function handle(CommentRepo $commentRepo): int
     {
         $connection = DB::getDefaultConnection();
         if ($this->option('database') !== null) {
             DB::setDefaultConnection($this->option('database'));
         }
 
-        Comment::query()->chunk(100, function ($comments) {
+        Comment::query()->chunk(100, function ($comments) use ($commentRepo) {
             foreach ($comments as $comment) {
-                $comment->html = $this->commentRepo->commentToHtml($comment->text);
+                $comment->html = $commentRepo->commentToHtml($comment->text);
                 $comment->save();
             }
         });
similarity index 58%
rename from app/Console/Commands/RegeneratePermissions.php
rename to app/Console/Commands/RegeneratePermissionsCommand.php
index 27dd8ea6530477f7d68ad0688f13413d3af230aa..856e943c52920d2d7759e6e223ef815c7c84c07e 100644 (file)
@@ -6,14 +6,15 @@ use BookStack\Permissions\JointPermissionBuilder;
 use Illuminate\Console\Command;
 use Illuminate\Support\Facades\DB;
 
-class RegeneratePermissions extends Command
+class RegeneratePermissionsCommand extends Command
 {
     /**
      * The name and signature of the console command.
      *
      * @var string
      */
-    protected $signature = 'bookstack:regenerate-permissions {--database= : The database connection to use.}';
+    protected $signature = 'bookstack:regenerate-permissions 
+                            {--database= : The database connection to use}';
 
     /**
      * The console command description.
@@ -22,23 +23,10 @@ class RegeneratePermissions extends Command
      */
     protected $description = 'Regenerate all system permissions';
 
-    protected JointPermissionBuilder $permissionBuilder;
-
-    /**
-     * Create a new command instance.
-     */
-    public function __construct(JointPermissionBuilder $permissionBuilder)
-    {
-        $this->permissionBuilder = $permissionBuilder;
-        parent::__construct();
-    }
-
     /**
      * Execute the console command.
-     *
-     * @return mixed
      */
-    public function handle()
+    public function handle(JointPermissionBuilder $permissionBuilder): int
     {
         $connection = DB::getDefaultConnection();
 
@@ -46,7 +34,7 @@ class RegeneratePermissions extends Command
             DB::setDefaultConnection($this->option('database'));
         }
 
-        $this->permissionBuilder->rebuildForAll();
+        $permissionBuilder->rebuildForAll();
 
         DB::setDefaultConnection($connection);
         $this->comment('Permissions regenerated');
similarity index 59%
rename from app/Console/Commands/RegenerateReferences.php
rename to app/Console/Commands/RegenerateReferencesCommand.php
index 805fd922d8e4e680b3c3b73e284669cb39b2f08f..ea8ff8e00e4b9fee837bf139d048fc22fe03b2bc 100644 (file)
@@ -6,14 +6,15 @@ use BookStack\References\ReferenceStore;
 use Illuminate\Console\Command;
 use Illuminate\Support\Facades\DB;
 
-class RegenerateReferences extends Command
+class RegenerateReferencesCommand extends Command
 {
     /**
      * The name and signature of the console command.
      *
      * @var string
      */
-    protected $signature = 'bookstack:regenerate-references {--database= : The database connection to use.}';
+    protected $signature = 'bookstack:regenerate-references
+                            {--database= : The database connection to use}';
 
     /**
      * The console command description.
@@ -22,25 +23,10 @@ class RegenerateReferences extends Command
      */
     protected $description = 'Regenerate all the cross-item model reference index';
 
-    protected ReferenceStore $references;
-
-    /**
-     * Create a new command instance.
-     *
-     * @return void
-     */
-    public function __construct(ReferenceStore $references)
-    {
-        $this->references = $references;
-        parent::__construct();
-    }
-
     /**
      * Execute the console command.
-     *
-     * @return int
      */
-    public function handle()
+    public function handle(ReferenceStore $references): int
     {
         $connection = DB::getDefaultConnection();
 
@@ -48,7 +34,7 @@ class RegenerateReferences extends Command
             DB::setDefaultConnection($this->option('database'));
         }
 
-        $this->references->updateForAllPages();
+        $references->updateForAllPages();
 
         DB::setDefaultConnection($connection);
 
similarity index 61%
rename from app/Console/Commands/RegenerateSearch.php
rename to app/Console/Commands/RegenerateSearchCommand.php
index ff584da56452561fab14ab1b63f0e72bb97a073b..f67a51e3d93776d37a581a171b33da56bbc76b05 100644 (file)
@@ -7,14 +7,15 @@ use BookStack\Search\SearchIndex;
 use Illuminate\Console\Command;
 use Illuminate\Support\Facades\DB;
 
-class RegenerateSearch extends Command
+class RegenerateSearchCommand extends Command
 {
     /**
      * The name and signature of the console command.
      *
      * @var string
      */
-    protected $signature = 'bookstack:regenerate-search {--database= : The database connection to use.}';
+    protected $signature = 'bookstack:regenerate-search 
+                            {--database= : The database connection to use}';
 
     /**
      * The console command description.
@@ -23,33 +24,17 @@ class RegenerateSearch extends Command
      */
     protected $description = 'Re-index all content for searching';
 
-    /**
-     * @var SearchIndex
-     */
-    protected $searchIndex;
-
-    /**
-     * Create a new command instance.
-     */
-    public function __construct(SearchIndex $searchIndex)
-    {
-        parent::__construct();
-        $this->searchIndex = $searchIndex;
-    }
-
     /**
      * Execute the console command.
-     *
-     * @return mixed
      */
-    public function handle()
+    public function handle(SearchIndex $searchIndex): int
     {
         $connection = DB::getDefaultConnection();
         if ($this->option('database') !== null) {
             DB::setDefaultConnection($this->option('database'));
         }
 
-        $this->searchIndex->indexAllEntities(function (Entity $model, int $processed, int $total): void {
+        $searchIndex->indexAllEntities(function (Entity $model, int $processed, int $total): void {
             $this->info('Indexed ' . class_basename($model) . ' entries (' . $processed . '/' . $total . ')');
         });
 
similarity index 80%
rename from app/Console/Commands/ResetMfa.php
rename to app/Console/Commands/ResetMfaCommand.php
index 4b1813099029485212b2c2f818f5ec476cbc9804..b8076d2d61f19d37854e497b70370e98d9ed5039 100644 (file)
@@ -5,7 +5,7 @@ namespace BookStack\Console\Commands;
 use BookStack\Users\Models\User;
 use Illuminate\Console\Command;
 
-class ResetMfa extends Command
+class ResetMfaCommand extends Command
 {
     /**
      * The name and signature of the console command.
@@ -24,22 +24,10 @@ class ResetMfa extends Command
      */
     protected $description = 'Reset & Clear any configured MFA methods for the given user';
 
-    /**
-     * Create a new command instance.
-     *
-     * @return void
-     */
-    public function __construct()
-    {
-        parent::__construct();
-    }
-
     /**
      * Execute the console command.
-     *
-     * @return mixed
      */
-    public function handle()
+    public function handle(): int
     {
         $id = $this->option('id');
         $email = $this->option('email');
@@ -66,13 +54,13 @@ class ResetMfa extends Command
         $this->info("This will delete any configure multi-factor authentication methods for user: \n- ID: {$user->id}\n- Name: {$user->name}\n- Email: {$user->email}\n");
         $this->info('If multi-factor authentication is required for this user they will be asked to reconfigure their methods on next login.');
         $confirm = $this->confirm('Are you sure you want to proceed?');
-        if ($confirm) {
-            $user->mfaValues()->delete();
-            $this->info('User MFA methods have been reset.');
-
-            return 0;
+        if (!$confirm) {
+            return 1;
         }
 
-        return 1;
+        $user->mfaValues()->delete();
+        $this->info('User MFA methods have been reset.');
+
+        return 0;
     }
 }
similarity index 97%
rename from app/Console/Commands/UpdateUrl.php
rename to app/Console/Commands/UpdateUrlCommand.php
index 0d218b380aebe3d8f39e71cc0e0cdef3efb6972b..27f84cc89f30689f40a87e80aaafa9181bcfb432 100644 (file)
@@ -5,7 +5,7 @@ namespace BookStack\Console\Commands;
 use Illuminate\Console\Command;
 use Illuminate\Database\Connection;
 
-class UpdateUrl extends Command
+class UpdateUrlCommand extends Command
 {
     /**
      * The name and signature of the console command.
@@ -26,10 +26,8 @@ class UpdateUrl extends Command
 
     /**
      * Execute the console command.
-     *
-     * @return mixed
      */
-    public function handle(Connection $db)
+    public function handle(Connection $db): int
     {
         $oldUrl = str_replace("'", '', $this->argument('oldUrl'));
         $newUrl = str_replace("'", '', $this->argument('newUrl'));
similarity index 69%
rename from app/Console/Commands/UpgradeDatabaseEncoding.php
rename to app/Console/Commands/UpgradeDatabaseEncodingCommand.php
index 32808729a545a47904457cb7af9bb67f557178e9..245ce57c6f064812f09d0b9a5696dae7e645660d 100644 (file)
@@ -5,14 +5,15 @@ namespace BookStack\Console\Commands;
 use Illuminate\Console\Command;
 use Illuminate\Support\Facades\DB;
 
-class UpgradeDatabaseEncoding extends Command
+class UpgradeDatabaseEncodingCommand extends Command
 {
     /**
      * The name and signature of the console command.
      *
      * @var string
      */
-    protected $signature = 'bookstack:db-utf8mb4 {--database= : The database connection to use.}';
+    protected $signature = 'bookstack:db-utf8mb4 
+                            {--database= : The database connection to use}';
 
     /**
      * The console command description.
@@ -21,20 +22,11 @@ class UpgradeDatabaseEncoding extends Command
      */
     protected $description = 'Generate SQL commands to upgrade the database to UTF8mb4';
 
-    /**
-     * Create a new command instance.
-     */
-    public function __construct()
-    {
-        parent::__construct();
-    }
 
     /**
      * Execute the console command.
-     *
-     * @return mixed
      */
-    public function handle()
+    public function handle(): int
     {
         $connection = DB::getDefaultConnection();
         if ($this->option('database') !== null) {
@@ -48,9 +40,11 @@ class UpgradeDatabaseEncoding extends Command
         $key = 'Tables_in_' . $database;
         foreach ($tables as $table) {
             $tableName = $table->$key;
-            $this->line('ALTER TABLE `' . $tableName . '` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;');
+            $this->line("ALTER TABLE `{$tableName}` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;");
         }
 
         DB::setDefaultConnection($connection);
+
+        return 0;
     }
 }
index 1d04582c094ef910cef05a33098ddda9819293a0..5458779e943906db62a58cce8f12587a248d5139 100644 (file)
@@ -462,6 +462,7 @@ class ImageService
 
         Image::query()->whereIn('type', $types)
             ->chunk(1000, function ($images) use ($checkRevisions, &$deletedPaths, $dryRun) {
+                /** @var Image $image */
                 foreach ($images as $image) {
                     $searchQuery = '%' . basename($image->path) . '%';
                     $inPage = DB::table('pages')
diff --git a/tests/Commands/CleanupImagesCommandTest.php b/tests/Commands/CleanupImagesCommandTest.php
new file mode 100644 (file)
index 0000000..a1a5ab9
--- /dev/null
@@ -0,0 +1,49 @@
+<?php
+
+namespace Tests\Commands;
+
+use BookStack\Uploads\Image;
+use Tests\TestCase;
+
+class CleanupImagesCommandTest extends TestCase
+{
+    public function test_command_defaults_to_dry_run()
+    {
+        $page = $this->entities->page();
+        $image = Image::factory()->create(['uploaded_to' => $page->id]);
+
+        $this->artisan('bookstack:cleanup-images -v')
+            ->expectsOutput('Dry run, no images have been deleted')
+            ->expectsOutput('1 images found that would have been deleted')
+            ->expectsOutputToContain($image->path)
+            ->assertExitCode(0);
+
+        $this->assertDatabaseHas('images', ['id' => $image->id]);
+    }
+
+    public function test_command_force_run()
+    {
+        $page = $this->entities->page();
+        $image = Image::factory()->create(['uploaded_to' => $page->id]);
+
+        $this->artisan('bookstack:cleanup-images --force')
+            ->expectsOutputToContain('This operation is destructive and is not guaranteed to be fully accurate')
+            ->expectsConfirmation('Are you sure you want to proceed?', 'yes')
+            ->expectsOutput('1 images deleted')
+            ->assertExitCode(0);
+
+        $this->assertDatabaseMissing('images', ['id' => $image->id]);
+    }
+
+    public function test_command_force_run_negative_confirmation()
+    {
+        $page = $this->entities->page();
+        $image = Image::factory()->create(['uploaded_to' => $page->id]);
+
+        $this->artisan('bookstack:cleanup-images --force')
+            ->expectsConfirmation('Are you sure you want to proceed?', 'no')
+            ->assertExitCode(0);
+
+        $this->assertDatabaseHas('images', ['id' => $image->id]);
+    }
+}
index c4b9fe6f305142cad1795f27b34b2145c67b0fb2..5c21a2e341cef66fa90011c0683bfa9007f722d6 100644 (file)
@@ -11,7 +11,7 @@ class CopyShelfPermissionsCommandTest extends TestCase
     {
         $this->artisan('bookstack:copy-shelf-permissions')
             ->expectsOutput('Either a --slug or --all option must be provided.')
-            ->assertExitCode(0);
+            ->assertExitCode(1);
     }
 
     public function test_copy_shelf_permissions_command_using_slug()
diff --git a/tests/Commands/DeleteUsersCommandTest.php b/tests/Commands/DeleteUsersCommandTest.php
new file mode 100644 (file)
index 0000000..a959df9
--- /dev/null
@@ -0,0 +1,44 @@
+<?php
+
+namespace Tests\Commands;
+
+use BookStack\Users\Models\User;
+use Illuminate\Database\Eloquent\Collection;
+use Tests\TestCase;
+
+class DeleteUsersCommandTest extends TestCase
+{
+    public function test_command_deletes_users()
+    {
+        $userCount = User::query()->count();
+        $normalUsers = $this->getNormalUsers();
+
+        $normalUserCount = $userCount - count($normalUsers);
+        $this->artisan('bookstack:delete-users')
+            ->expectsConfirmation('Are you sure you want to continue?', 'yes')
+            ->expectsOutputToContain("Deleted $normalUserCount of $userCount total users.")
+            ->assertExitCode(0);
+
+        $this->assertDatabaseMissing('users', ['id' => $normalUsers->first()->id]);
+    }
+
+    public function test_command_requires_confirmation()
+    {
+        $normalUsers = $this->getNormalUsers();
+
+        $this->artisan('bookstack:delete-users')
+            ->expectsConfirmation('Are you sure you want to continue?', 'no')
+            ->assertExitCode(0);
+
+        $this->assertDatabaseHas('users', ['id' => $normalUsers->first()->id]);
+    }
+
+    protected function getNormalUsers(): Collection
+    {
+        return User::query()->whereNull('system_name')
+            ->get()
+            ->filter(function (User $user) {
+                return !$user->hasSystemRole('admin');
+            });
+    }
+}
diff --git a/tests/Commands/RegenerateSearchCommandTest.php b/tests/Commands/RegenerateSearchCommandTest.php
new file mode 100644 (file)
index 0000000..418327e
--- /dev/null
@@ -0,0 +1,29 @@
+<?php
+
+namespace Tests\Commands;
+
+use BookStack\Search\SearchTerm;
+use Illuminate\Support\Facades\DB;
+use Tests\TestCase;
+
+class RegenerateSearchCommandTest extends TestCase
+{
+    public function test_command_regenerates_index()
+    {
+        DB::rollBack();
+        $page = $this->entities->page();
+        SearchTerm::truncate();
+
+        $this->assertDatabaseMissing('search_terms', ['entity_id' => $page->id]);
+
+        $this->artisan('bookstack:regenerate-search')
+            ->expectsOutput('Search index regenerated!')
+            ->assertExitCode(0);
+
+        $this->assertDatabaseHas('search_terms', [
+            'entity_type' => 'page',
+            'entity_id' => $page->id
+        ]);
+        DB::beginTransaction();
+    }
+}
diff --git a/tests/Commands/UpgradeDatabaseEncodingCommandTest.php b/tests/Commands/UpgradeDatabaseEncodingCommandTest.php
new file mode 100644 (file)
index 0000000..b7fe4eb
--- /dev/null
@@ -0,0 +1,15 @@
+<?php
+
+namespace Tests\Commands;
+
+use Tests\TestCase;
+
+class UpgradeDatabaseEncodingCommandTest extends TestCase
+{
+    public function test_command_outputs_sql()
+    {
+        $this->artisan('bookstack:db-utf8mb4')
+            ->expectsOutputToContain('ALTER DATABASE')
+            ->expectsOutputToContain('ALTER TABLE `users` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;');
+    }
+}