# Code Coverage for /home/users/tracer/www/spookie.lab.24unix.net/Spookie/src/Command/CronRunCommand.php

| 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 |
3 | namespace App\Command;
4 |
5 | use App\Repository\UserRepository;
6 | use Symfony\Component\Console\Attribute\AsCommand;
7 | use Symfony\Component\Console\Command\Command;
8 | use Symfony\Component\Console\Input\InputInterface;
9 | use Symfony\Component\Console\Input\InputOption;
10 | use Symfony\Component\Console\Output\OutputInterface;
11 | use Symfony\Component\Console\Style\SymfonyStyle;
12 |
13 | #[AsCommand(
14 | name: 'cron:run',
15 | description: 'Cleanup stale avatars',
16 | )]
17 | class 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 | }