Доработка команды ImagesCacheClearCommand для очистки кеша изображений

- Добавлена настройка paths.images_cache в configs/app.php для централизованного управления путем к кешу
- Обновлен ImageFactory для использования пути кеша из конфигурации вместо жестко закодированного пути
- Обновлен ImageToolServiceProvider для передачи пути кеша в ImageFactory
- Реализована полная функциональность очистки кеша в ImagesCacheClearCommand с подсчетом статистики
- Добавлен запрос подтверждения перед удалением файлов
- Команда зарегистрирована в cli.php
This commit is contained in:
2025-12-09 21:13:12 +03:00
parent c4b19286f3
commit 6aa258385e
6 changed files with 174 additions and 5 deletions

View File

@@ -6,7 +6,8 @@ use Console\Commands\PulseSendEventsCommand;
use Console\Commands\ScheduleListCommand; use Console\Commands\ScheduleListCommand;
use Console\Commands\ScheduleRunCommand; use Console\Commands\ScheduleRunCommand;
use Console\Commands\VersionCommand; use Console\Commands\VersionCommand;
use Console\Commands\WarmupImagesCacheCommand; use Console\Commands\ImagesWarmupCacheCommand;
use Console\Commands\ImagesCacheClearCommand;
use Monolog\Handler\RotatingFileHandler; use Monolog\Handler\RotatingFileHandler;
use Monolog\Logger; use Monolog\Logger;
use Openguru\OpenCartFramework\QueryBuilder\Connections\MySqlConnection; use Openguru\OpenCartFramework\QueryBuilder\Connections\MySqlConnection;
@@ -95,5 +96,6 @@ $console->add($app->get(VersionCommand::class));
$console->add($app->get(ScheduleRunCommand::class)); $console->add($app->get(ScheduleRunCommand::class));
$console->add($app->get(ScheduleListCommand::class)); $console->add($app->get(ScheduleListCommand::class));
$console->add($app->get(PulseSendEventsCommand::class)); $console->add($app->get(PulseSendEventsCommand::class));
$console->add($app->get(WarmupImagesCacheCommand::class)); $console->add($app->get(ImagesWarmupCacheCommand::class));
$console->add($app->get(ImagesCacheClearCommand::class));
$console->run(); $console->run();

View File

@@ -93,4 +93,8 @@ TEXT,
'db_table' => 'telecart_cache_items', 'db_table' => 'telecart_cache_items',
], ],
], ],
'paths' => [
'images_cache' => 'cache/telecart',
],
]; ];

View File

@@ -0,0 +1,156 @@
<?php
namespace Console\Commands;
use Openguru\OpenCartFramework\Container\Container;
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
class ImagesCacheClearCommand extends TeleCartCommand
{
protected static $defaultName = 'images:cache-clear';
protected static $defaultDescription = 'Очистка кеша изображений товаров';
private Container $container;
public function __construct(Container $container)
{
parent::__construct();
$this->container = $container;
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle($input, $output);
$io->title('Очистка кеша изображений товаров');
// Получаем пути из конфига
$imagesDir = $this->container->getConfigValue('paths.images');
$cachePath = $this->container->getConfigValue('paths.images_cache', 'cache/telecart');
$cachePath = ltrim($cachePath, '/');
$fullCachePath = rtrim($imagesDir, '/') . '/' . $cachePath;
if (!is_dir($fullCachePath)) {
$io->warning("Директория кеша не существует: {$fullCachePath}");
return Command::SUCCESS;
}
$io->section('Информация');
$io->listing([
"Директория изображений: {$imagesDir}",
"Путь кеша: {$cachePath}",
"Полный путь кеша: {$fullCachePath}",
]);
// Подсчитываем файлы перед удалением
$fileCount = 0;
$totalSize = 0;
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($fullCachePath, RecursiveDirectoryIterator::SKIP_DOTS),
RecursiveIteratorIterator::CHILD_FIRST
);
foreach ($iterator as $file) {
if ($file->isFile()) {
$fileCount++;
$totalSize += $file->getSize();
}
}
if ($fileCount === 0) {
$io->info('Кеш пуст, нечего очищать.');
return Command::SUCCESS;
}
$io->section('Статистика перед очисткой');
$io->listing([
"Файлов: {$fileCount}",
"Размер: " . $this->formatBytes($totalSize),
]);
// Запрашиваем подтверждение
if (!$io->confirm('Вы уверены, что хотите удалить все файлы из кеша?', false)) {
$io->info('Очистка кеша отменена.');
return Command::SUCCESS;
}
// Удаляем файлы и директории
$deletedFiles = 0;
$deletedDirs = 0;
$errors = 0;
$progressBar = $io->createProgressBar($fileCount);
$progressBar->setFormat(' %current%/%max% [%bar%] %percent:3s%% %message%');
$progressBar->setMessage('Удаление файлов...');
$progressBar->start();
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($fullCachePath, RecursiveDirectoryIterator::SKIP_DOTS),
RecursiveIteratorIterator::CHILD_FIRST
);
foreach ($iterator as $file) {
try {
if ($file->isFile()) {
if (@unlink($file->getPathname())) {
$deletedFiles++;
} else {
$errors++;
}
$progressBar->advance();
} elseif ($file->isDir()) {
if (@rmdir($file->getPathname())) {
$deletedDirs++;
}
}
} catch (\Exception $e) {
$errors++;
}
}
// Удаляем саму директорию кеша, если она пуста
if (is_dir($fullCachePath)) {
@rmdir($fullCachePath);
}
$progressBar->setMessage('Завершено');
$progressBar->finish();
$io->newLine(2);
// Выводим статистику
$io->section('Результаты');
$io->table(
['Метрика', 'Значение'],
[
['Удалено файлов', $deletedFiles],
['Удалено директорий', $deletedDirs],
['Ошибок', $errors],
]
);
if ($errors > 0) {
$io->warning("Обнаружено {$errors} ошибок при удалении файлов.");
} else {
$io->success('Кеш изображений успешно очищен!');
}
return Command::SUCCESS;
}
private function formatBytes(int $bytes, int $precision = 2): string
{
$units = ['B', 'KB', 'MB', 'GB', 'TB'];
for ($i = 0; $bytes > 1024 && $i < count($units) - 1; $i++) {
$bytes /= 1024;
}
return round($bytes, $precision) . ' ' . $units[$i];
}
}

View File

@@ -16,7 +16,7 @@ use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Console\Style\SymfonyStyle;
class WarmupImagesCacheCommand extends TeleCartCommand class ImagesWarmupCacheCommand extends TeleCartCommand
{ {
protected static $defaultName = 'images:warmup'; protected static $defaultName = 'images:warmup';
protected static $defaultDescription = 'Прогрев кеша изображений товаров'; protected static $defaultDescription = 'Прогрев кеша изображений товаров';

View File

@@ -31,6 +31,7 @@ class ImageFactory
'format' => 'webp', 'format' => 'webp',
'quality' => 90, 'quality' => 90,
'no_image_path' => 'no_image.png', 'no_image_path' => 'no_image.png',
'cache_path' => 'cache/telecart',
]; ];
public function __construct(string $imageDir, string $siteUrl, string $driver, array $options = []) public function __construct(string $imageDir, string $siteUrl, string $driver, array $options = [])
@@ -179,7 +180,10 @@ class ImageFactory
$filename .= '_' . substr(hash('SHA256', json_encode($this->modifications)), 0, 12); $filename .= '_' . substr(hash('SHA256', json_encode($this->modifications)), 0, 12);
} }
return $this->imageDir . '/cache/telecart/' . $imagePath . $filename . '.' . $format; $cachePath = $this->options['cache_path'] ?? 'cache/telecart';
$cachePath = ltrim($cachePath, '/');
return $this->imageDir . '/' . $cachePath . '/' . $imagePath . $filename . '.' . $format;
} }
private function applyModifications(): void private function applyModifications(): void

View File

@@ -15,7 +15,10 @@ class ImageToolServiceProvider extends ServiceProvider
return new ImageFactory( return new ImageFactory(
$container->getConfigValue('paths.images'), $container->getConfigValue('paths.images'),
$container->getConfigValue('app.shop_base_url'), $container->getConfigValue('app.shop_base_url'),
$driver $driver,
[
'cache_path' => $container->getConfigValue('paths.images_cache', 'cache/telecart'),
]
); );
}); });
} }