Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
28 / 28
100.00% covered (success)
100.00%
3 / 3
CRAP
100.00% covered (success)
100.00%
1 / 1
LogsCleanupCommand
100.00% covered (success)
100.00%
27 / 27
100.00% covered (success)
100.00%
3 / 3
7
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 configure
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
1
 execute
100.00% covered (success)
100.00%
18 / 18
100.00% covered (success)
100.00%
1 / 1
5
1<?php
2
3declare(strict_types=1);
4
5/** @license For full copyright and license information, please see the LICENSE.md file. */
6
7namespace App\Core\Console\Command;
8
9defined('AMMONLY_APP') || exit('Direct script access is forbidden.');
10
11use Symfony\Component\Console\Command\Command;
12use Symfony\Component\Console\Input\InputInterface;
13use Symfony\Component\Console\Input\InputOption;
14use Symfony\Component\Console\Output\OutputInterface;
15use Yiisoft\Files\FileHelper;
16
17/**
18 * Logs Cleanup Console Command.
19 *
20 * Rotates, archives, or purges old application and access logs based on retention days.
21 *
22 * @package App\Core\Console\Command
23 */
24final class LogsCleanupCommand extends Command
25{
26    /** @var string Command name identifier. */
27    private const string COMMAND_NAME = 'logs:cleanup';
28
29    /**
30     * LogsCleanupCommand constructor.
31     *
32     * @param string $basePath Base application directory.
33     */
34    public function __construct(private readonly string $basePath)
35    {
36        parent::__construct(self::COMMAND_NAME);
37    }
38
39    /** {@inheritdoc} */
40    protected function configure(): void
41    {
42        $this->setDescription('Purges or archives old log files according to retention policies.')
43            ->addOption(
44                'days',
45                'd',
46                InputOption::VALUE_OPTIONAL,
47                'Retention window in days (logs older than this will be deleted)',
48                '30'
49            );
50    }
51
52    /** {@inheritdoc} */
53    protected function execute(InputInterface $input, OutputInterface $output): int
54    {
55        $days = (int) $input->getOption('days');
56        $cutoff = time() - ($days * 86400);
57        $logsDir = $this->basePath . '/storage/logs';
58
59        if (!is_dir($logsDir)) {
60            $output->writeln('<comment>No logs directory found to clean.</comment>');
61            return Command::SUCCESS;
62        }
63
64        $files = FileHelper::findFiles($logsDir, ['only' => ['*.log', '*.json']]);
65        $deleted = 0;
66
67        foreach ($files as $file) {
68            if (filemtime($file) < $cutoff && basename($file) !== '.gitkeep') {
69                @unlink($file);
70                $deleted++;
71            }
72        }
73
74        $output->writeln(sprintf(
75            '<info>Logs cleanup complete: %d log file(s) older than %d days removed.</info>',
76            $deleted,
77            $days
78        ));
79
80        return Command::SUCCESS;
81    }
82}