LibArea - добавление команды на удаление неиспользуемых изображений

27 Сентября 2022 (ред)

Как уже писал, этот сайт использует мультиблоговый движок LibArea. Из него попробовал сделать собственный блог с небольшими доработками, что собственно вы и видите здесь. Теперь вот понадобилось сделать консольную команду на удаление неиспользуемых изображений в текущем месяце. То есть тех, что оказались не вставлены ни в один существующий текст поста или ответа.

Планирую поставить команду выполняться по cron раз в день. Часто ставить не стоит, так как кто-то может в это время создавать пост с изображениями, а тут они удалятся. Можно выборочно удалить и те изображения, которые указаны в постах и ответах помеченных 'delete', то есть удалённых.

Если вы хотите наладить подобный процесс у себя, то перед первым пробным удалением неплохо бы сделать бэкап папки с картинками за текущий месяц, на всякий случай. А после проверки, что все удалилось корректно, удалить и сам бэкап.

Вот сама консольная команда:


<?php

/* Файл app/Commands/RemoveUnusedPostImages.php */

namespace App\Commands;

class RemoveUnusedPostImages extends \Hleb\Scheme\App\Commands\MainTask
{
    /** php console remove-unused-post-images [--all] **/

    const DESCRIPTION = "Remove unused images";

    protected function execute($arg = null)
    {

        $allPosts = \DB::run("SELECT * FROM posts")->fetchAll();

        $allAnswers = \DB::run("SELECT * FROM answers")->fetchAll();

        $data = array_merge($allPosts, $allAnswers);

        foreach ($data as $key => $value) {
            $data[$key]['content'] = $value['post_content'] ?? $value['answer_content'];
            $data[$key]['is_deleted'] = $value['post_is_deleted'] ?? $value['answer_is_deleted'];
        }

        if (!$data) {
            echo  PHP_EOL . "Posts and answers not found!" . PHP_EOL;

           return;
        }

        $countPosts = count($data);

        $images = [];

        $imagePath = "/uploads/posts/content/" . date("Y") . "/" . date("n") . "/";
        $dir = HLEB_PUBLIC_DIR . $imagePath;

        if (!file_exists($dir)) {
            echo  PHP_EOL . "Images directory not found!" . PHP_EOL;

            return;
        }

        if ($handle = opendir($dir)) {
            while (false !== ($file = readdir($handle))) {
                if ($file != "." && $file != "..") {
                    $images[] = $imagePath . $file;
                }
            }
        }

        $countImages = count($images);

        if (!$images) {
            echo  PHP_EOL . "Images not found!" . PHP_EOL;

            return;
        }

        foreach ($data as $post) {
           if ($post['content']) {
               foreach ($images as $key => $image) {
                   if ($post["is_deleted"] === 1 && $arg === "--all") {
                       continue;
                   }
                   if (strpos($post['content'], $image) !== false){
                       unset($images[$key]);
                   }
               }
           }
        }
        // Если удаляются все изображения, то явно что-то пошло не так.
        if (count($images) === $countImages) {
            echo  PHP_EOL . "Something went wrong!" . PHP_EOL;

            return;
        }

        foreach ($images as $key => $image) {
            unlink(HLEB_PUBLIC_DIR . $image);
            unset($images[$key]);
        }

        echo PHP_EOL . "POSTS: $countPosts | IMAGES: $countImages | DELETED: " . ($countImages - count($images)) . PHP_EOL;


        echo PHP_EOL . __CLASS__ . " done." . PHP_EOL;
    }
}

Вызвать её можно через php console remove-unused-post-images --all, где необязательный параметр --all устанавливает удаление неиспользуемых изображений и в удалённых постах и ответах.

fomiash fomiash + 221

2 Ответа

  1. fomiash fomiash 02 Октября 2022

    Еще вариант - картинки в "черновиках", они остаются на месте после удаления.

  1. Evg Evg 10 Октября 2022

    Очень полезно, спасибо!

    В Discourse так и делается, проходится по всему движку, и если фото нет в полях контента, то удаляется.

    Думаю вообще переписать эту систему добавление файлов, что-то она совсем не нравится, а именно, файл UploadImage.php. Слишком много варианто там внутри, да и код очень сумбурный такой. Когда начинал делать, непонятно зачем сделал разные варианты (даже путей). Ну да ладно, позже.



Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.