Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
57.14% covered (warning)
57.14%
12 / 21
50.00% covered (danger)
50.00%
2 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
CronRunCommand
57.14% covered (warning)
57.14%
12 / 21
50.00% covered (danger)
50.00%
2 / 4
17.87
0.00% covered (danger)
0.00%
0 / 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%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 execute
62.50% covered (warning)
62.50%
5 / 8
0.00% covered (danger)
0.00%
0 / 1
3.47
 deleteStaleAvatars
45.45% covered (danger)
45.45%
5 / 11
0.00% covered (danger)
0.00%
0 / 1
9.06
1<?php
2
3namespace App\Command;
4
5use App\Repository\UserRepository;
6use Symfony\Component\Console\Attribute\AsCommand;
7use Symfony\Component\Console\Command\Command;
8use Symfony\Component\Console\Input\InputInterface;
9use Symfony\Component\Console\Input\InputOption;
10use Symfony\Component\Console\Output\OutputInterface;
11use Symfony\Component\Console\Style\SymfonyStyle;
12
13#[AsCommand(
14    name: 'cron:run',
15    description: 'Cleanup stale avatars',
16)]
17class CronRunCommand extends Command
18{
19    public function __construct(private readonly UserRepository $userRepository)
20    {
21        parent::__construct();
22    }
23
24    protected function configure(): void
25    {
26        //$this->addOption(name: 'verbose', shortcut: null, mode: InputOption::VALUE_NONE, description: 'Option description');
27        //            ->addArgument('arg1', InputArgument::OPTIONAL, 'Argument description')
28    }
29
30    public function execute(InputInterface $input, OutputInterface $output): int
31    {
32        $io = new SymfonyStyle(input: $input, output: $output);
33
34        $verbose = $input->getOption(name: 'verbose');
35
36        $staleCount = $this->deleteStaleAvatars();
37
38        if ($verbose) {
39            if ($staleCount > 0) {
40                $io->writeln(messages: "There were " . $staleCount . " stale avatars.");
41            } else {
42                $io->writeln(messages: "There were no stale avatars younger than 24 hours.");
43            }
44        }
45
46        return Command::SUCCESS;
47    }
48
49    private function deleteStaleAvatars(): int
50    {
51        $avatarDir = dirname(path: __DIR__, levels: 2) . '/public/uploads/avatars';
52        $keepTime = 86400; // 24 hours
53        $deletedFiles = 0;
54
55        foreach (glob(pattern: $avatarDir . '/*') as $entry) {
56            $filectime = filectime(filename: $entry);
57            if ($filectime && $filectime + $keepTime < time()) {
58                // check if it in use
59                if ($user = $this->userRepository->findOneBy(['avatar' => basename(path: $entry)])) {
60                    echo basename(path: $entry) . " is in use by: " . $user->getUserIdentifier() . PHP_EOL;
61                }
62                unlink(filename: $entry);
63                $deletedFiles++;
64            }
65
66        }
67        return $deletedFiles;
68    }
69}