polarpress-pagebuilder/app/Console/Commands/MakeImageDB.php

167 lines
6.0 KiB
PHP

<?php
namespace App\Console\Commands;
use Illuminate\Support\Facades\File;
use Illuminate\Console\Command;
use App\Models\User;
use App\Models\ImageNode;
class MakeImageDB extends Command
{
/**
* Summary of processImage
* @param mixed $file
* @param mixed $parentId
* @param int $userId
* @param string $basePath
* @return void
*/
private function processImage($file, ?int $parentId, int $userId, string $basePath): void{
$ext = strtolower($file->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;
}
}