getExtension()); if (!in_array($ext, ['jpg', 'jpeg', 'png'])) return; $imageFileName = $file->getFilename(); $relativePath = str_replace(public_path(), '', $file->getPathname()); $relativePath = str_replace(DIRECTORY_SEPARATOR, '/', $relativePath); $relativePath = '/' . ltrim($relativePath, '/'); ImageNode::create([ 'user_id' => $userId, 'parent_id' => $parentId, 'name' => $imageFileName, 'fs_type' => 'file', 'fs_meta' => json_encode([ 'real_name' => $file->getPathname(), 'symbolic_name' => $relativePath, 'title' => pathinfo($imageFileName, PATHINFO_FILENAME), 'description' => '', 'copyright' => '', 'mime_type' => File::mimeType($file->getPathname()), 'size' => $file->getSize(), ]), ]); } /** * Summary of scanFolder * @param string $fullPath * @param mixed $parentId * @param int $userId * @param string $basePath * @return void */ private function scanFolder(string $fullPath, ?int $parentId, int $userId, string $basePath): void { $folderName = basename($fullPath); $folderNode = ImageNode::create([ 'user_id' => $userId, 'name' => $folderName, 'fs_type' => 'folder', 'parent_id' => $parentId, ]); foreach (File::directories($fullPath) as $subdir) { $this->scanFolder($subdir, $folderNode->id, $userId, $basePath); } foreach (File::files($fullPath) as $file) { $this->processImage($file, $folderNode->id, $userId, $basePath); } } /** * The name and signature of the console command. * * @var string */ protected $signature = 'pagebuilder:make-imagedb {--testmode : Use test-imagedb folder instead of imagedb for testing}'; /** * The console command description. * * @var string */ protected $description = 'This command is a substitute for PolarPress image handling/uploading and administration, in order to provide the page builder with images to work with in the various page components for the pagebuilder. It will scan the public/imagedb directory, and replicate its file/folder structure in the database.'; /** * Execute the console command. */ public function handle() { // The public path to the imagedb directory. If you change this, please also make sure you update // the .gitignore file so you don't accidentally push garbage to the repository. // We set up a test directory just for unit testing, so we don't polute the local database, or file // system with test data $imageDbPath = $this->option('testmode') ? public_path('test-imagedb') : public_path('imagedb'); if (!File::exists($imageDbPath) || !File::isDirectory($imageDbPath)) { if ($this->option('testmode')) { $this->error("The 'public/test-imagedb' directory does not exist."); } else { $this->error("The 'public/imagedb' directory does not exist."); } return Command::FAILURE; } // At this point, the directory exist, but we also need to make sure the directory is not empty $contents = File::allFiles($imageDbPath); $subdirs = File::directories($imageDbPath); if (empty($contents) && empty($subdirs)) { if ($this->option('testmode')) { $this->error("The 'public/test-imagedb' directory is empty. Nothing to index."); } else { $this->error("The 'public/imagedb' directory is empty. Nothing to index."); } return Command::FAILURE; } // To avoid dublications (and to make this simple), we're now going to reset the table and // truncate the data so we start on a clean slate $this->info("Clearing existing image nodes..."); ImageNode::truncate(); // The image node model requires a user relationship, so we need to make the command operator // select which user to act as in order to populate the database correctly $users = User::orderBy('name')->get(); if ($users->isEmpty()) { // Make sure there is at least one user in the database before continuing $this->error("No users found in the database. Cannot continue!"); $this->line('(Use artisan serve and npm run dev to spool up a local instance, and register a user from the web interface)'); return Command::FAILURE; } $options = []; foreach ($users as $user) { $label = "{$user->name} ({$user->email})"; $options[$label] = $user->id; } $selectedLabel = $this->choice( 'Select a user to act as:', array_keys($options), array_key_first($options) ); $userId = $options[$selectedLabel]; $this->info("Selected user ID: $userId: $selectedLabel"); $this->info("Scanning and indexing image directory..."); foreach (File::directories($imageDbPath) as $dir) { $this->scanFolder($dir, null, $userId, $imageDbPath); } foreach (File::files($imageDbPath) as $file) { $this->processImage($file, null, $userId, $imageDbPath); } $this->info("Image DB creation complete."); return Command::SUCCESS; } }