Task::getUnusedPublicAssets()   A
last analyzed

Complexity

Conditions 4
Paths 4

Size

Total Lines 40
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 27
c 2
b 0
f 0
dl 0
loc 40
rs 9.488
cc 4
nc 4
nop 6
1
<?php
2
3
namespace AppBundle\ShowUnusedPublicAssets;
4
5
use Helper\FileSystem;
6
use Helper\NullStyle;
7
use Symfony\Component\Console\Style\StyleInterface;
8
use Symfony\Component\Finder\Finder;
9
10
/**
11
 * Get all asset files in the public web directory and it's subdirecories that were not accessed according to webserver
12
 * logs.
13
 */
14
final class Task
15
{
16
    /**
17
     * @param string $pathToPublic
18
     * @param string $pathToLogfile
19
     * @param string $regExpToFindFile
20
     * @param string|null $pathToOutput
21
     * @param string|null $pathToBlacklist
22
     * @param StyleInterface|null $ioStyle
23
     */
24
    public function getUnusedPublicAssets($pathToPublic, $pathToLogfile, $regExpToFindFile, $pathToOutput, $pathToBlacklist, StyleInterface $ioStyle = null)
25
    {
26
        $ioStyle = $ioStyle ?: new NullStyle();
27
        $ioStyle->text('Started.');
28
29
        $accessedUrls = $this->getAccessedUrls($pathToPublic, $pathToLogfile, $regExpToFindFile);
30
        $ioStyle->text('Found ' . count($accessedUrls) . ' distinct accessed URLs.');
31
32
        $blacklistingRegExps = FileSystem::getBlacklistingRegExps($pathToBlacklist);
33
        $foundFilesInfos = iterator_to_array((new Finder())->in($pathToPublic)->files()->getIterator());
34
        $relevantPublicAssets = FileSystem::filterFilesIn($foundFilesInfos, $blacklistingRegExps);
35
36
        $message = 'Found ' . count($relevantPublicAssets) . ' used public assets';
37
        $numberOfBlacklistingRegExps = count($blacklistingRegExps);
38
        if ($numberOfBlacklistingRegExps > 0) {
39
            $message .= ' not matched by the ' . $numberOfBlacklistingRegExps . ' blacklisting regular expressions';
40
        }
41
        $ioStyle->text($message . ' in ' . $pathToPublic . '.');
42
43
        $unusedAssets = array_diff($relevantPublicAssets, $accessedUrls);
44
        sort($unusedAssets);
45
46
        $pathToOutput = FileSystem::getPathToOutput($pathToOutput, $pathToPublic, 'potentially-unused-public-assets.txt');
47
        FileSystem::writeArrayToFile($unusedAssets, $pathToOutput);
48
49
        $successMessages = false
50
            ? [
51
                'No potentially unused unused public assets found.'
52
            ]
53
            : [
54
                'Finished writing list of ' . count($unusedAssets) . ' potentially unused public assets. Please inspect the '
55
                    . 'output file ' . $pathToOutput,
56
                'For files you want to keep (even if they are not used according to the webserver access logs), you '
57
                    . 'can maintain a blacklist. With it, you can exclude these files from the output of further runs of '
58
                    . 'this command. See --help or the readme for details.',
59
                'Once you are sure you can restore the rest of the files (ideally from your version control system), try '
60
                    . 'deleting them, e.g. with "xargs -0 -d \'\n\' rm < ' . $pathToOutput . '", rerun your tests and check your logs '
61
                    . 'for 404s to see if that broke anything.',
62
            ];
63
        $ioStyle->success($successMessages);
64
    }
65
66
    /**
67
     * @param string $pathToPublic
68
     * @param string $pathToLogfile
69
     * @param string $regExpToFindFile
70
     * @return string[]
71
     */
72
    private function getAccessedUrls($pathToPublic, $pathToLogfile, $regExpToFindFile)
73
    {
74
        $logEntries = FileSystem::readFileIntoArray($pathToLogfile);
75
        $usedAssets = [];
76
        $regExpMatches = [];
77
78
        foreach ($logEntries as $logEntry) {
79
            if (preg_match($regExpToFindFile, $logEntry, $regExpMatches) === 1) {
80
                $usedAssets[] = realpath($pathToPublic . $regExpMatches[1]);
81
            }
82
        }
83
84
        $usedAssets = array_unique($usedAssets);
85
        sort($usedAssets);
86
87
        return $usedAssets;
88
    }
89
}
90