ViewAnalyzer::analyze()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 3
c 1
b 0
f 0
dl 0
loc 7
rs 10
cc 1
nc 1
nop 0
1
<?php
2
3
namespace TypeHints\Unused\Analyzer;
4
5
use Illuminate\Filesystem\Filesystem;
6
use Illuminate\Routing\Route;
7
use Illuminate\Routing\Router;
8
use Illuminate\Support\Collection;
9
use Illuminate\Support\Str;
10
use TypeHints\Unused\Parser\Action\ClosureParser;
11
use TypeHints\Unused\Parser\Action\ControllerParser;
12
use TypeHints\Unused\Parser\Action\ParserActionInterface;
13
use TypeHints\Unused\Parser\ParserInterface;
14
use TypeHints\Unused\Parser\ViewParser;
15
use TypeHints\Unused\Transformers\ViewTransformer;
16
17
class ViewAnalyzer
18
{
19
    protected $router;
20
21
    protected $unusedViews = [];
22
23
    protected $usedViews = [];
24
25
    public function __construct(Router $router)
26
    {
27
        $this->router = $router;
28
    }
29
30
    public function analyze()
31
    {
32
        $this->usedViews = $this->fetchUsedViews();
33
34
        $this->unusedViews = $this->fetchUnusedViews();
35
36
        return $this;
37
    }
38
39
    public function delete(string $view)
40
    {
41
        $filesystem = new Filesystem();
42
43
        $view = str_replace('.', '/', $view);
44
45
        foreach (config('view.paths') as $path) {
0 ignored issues
show
Bug introduced by
The function config was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

45
        foreach (/** @scrutinizer ignore-call */ config('view.paths') as $path) {
Loading history...
46
            $viewPath = $path.'/'.$view.'.blade.php';
47
48
            if ($filesystem->exists($viewPath)) {
49
                $filesystem->delete($viewPath);
50
            }
51
        }
52
    }
53
54
    protected function fetchUnusedViews()
55
    {
56
        $flattenUsedViews = collect($this->usedViews)->map(function ($viewTransformer) {
57
            return array_keys($viewTransformer->getViews());
58
        })
59
        ->flatten();
60
61
        $this->retrieveViewCounts($flattenUsedViews);
62
63
        return array_diff(
64
            $this->getAllViews(),
65
            $flattenUsedViews->unique()->toArray()
66
        );
67
    }
68
69
    protected function fetchUsedViews(): array
70
    {
71
        return array_map(function ($route) {
72
            return $this->generateViewTransformer($route);
73
        }, $this->router->getRoutes()->getRoutes());
74
    }
75
76
    /**
77
     * @param Route $route
78
     *
79
     * @return TypeHints\Unused\Transformers\ViewTransformer
0 ignored issues
show
Bug introduced by
The type TypeHints\Unused\Analyze...formers\ViewTransformer was not found. Did you mean TypeHints\Unused\Transformers\ViewTransformer? If so, make sure to prefix the type with \.
Loading history...
80
     */
81
    protected function generateViewTransformer(Route $route): ViewTransformer
82
    {
83
        return new ViewTransformer($this->parse($route));
0 ignored issues
show
Bug Best Practice introduced by
The expression return new TypeHints\Unu...r($this->parse($route)) returns the type TypeHints\Unused\Transformers\ViewTransformer which is incompatible with the documented return type TypeHints\Unused\Analyze...formers\ViewTransformer.
Loading history...
84
    }
85
86
    /**
87
     * @return array
88
     */
89
    protected function getAllViews(): array
90
    {
91
        $filesystem = new Filesystem();
92
93
        $views = [];
94
95
        foreach (config('view.paths') as $path) {
0 ignored issues
show
Bug introduced by
The function config was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

95
        foreach (/** @scrutinizer ignore-call */ config('view.paths') as $path) {
Loading history...
96
            foreach ($filesystem->allFiles($path, true) as $file) {
97
                if (Str::startsWith($file->getRelativePath(), 'vendor')) {
98
                    break;
99
                }
100
101
                $views[] = str_replace('.blade.php', '', str_replace('/', '.', $file->getRelativePathname()));
102
            }
103
        }
104
105
        return $views;
106
    }
107
108
    /**
109
     * @param Route $route
110
     *
111
     * @return TypeHints\Unused\Parser\ViewParser
0 ignored issues
show
Bug introduced by
The type TypeHints\Unused\Analyze...nused\Parser\ViewParser was not found. Did you mean TypeHints\Unused\Parser\ViewParser? If so, make sure to prefix the type with \.
Loading history...
112
     */
113
    protected function parse(Route $route): ViewParser
114
    {
115
        return $this->viewParser(
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->viewParser...arser($route))->parse() returns the type TypeHints\Unused\Parser\ViewParser which is incompatible with the documented return type TypeHints\Unused\Analyze...nused\Parser\ViewParser.
Loading history...
116
            $this->actionParser($route)
117
        )->parse();
118
    }
119
120
    /**
121
     * @param Route $route
122
     *
123
     * @return TypeHints\Unused\Parser\Action\ParserActionInterface
0 ignored issues
show
Bug introduced by
The type TypeHints\Unused\Analyze...n\ParserActionInterface was not found. Did you mean TypeHints\Unused\Parser\...n\ParserActionInterface? If so, make sure to prefix the type with \.
Loading history...
124
     */
125
    protected function actionParser(Route $route): ParserActionInterface
126
    {
127
        if (array_key_exists('controller', $route->getAction())) {
0 ignored issues
show
Bug introduced by
It seems like $route->getAction() can also be of type null; however, parameter $search of array_key_exists() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

127
        if (array_key_exists('controller', /** @scrutinizer ignore-type */ $route->getAction())) {
Loading history...
128
            return $this->controllerParser($route)->parse();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->controllerParser($route)->parse() returns the type TypeHints\Unused\Parser\Action\ControllerParser which is incompatible with the documented return type TypeHints\Unused\Analyze...n\ParserActionInterface.
Loading history...
129
        }
130
131
        return $this->closureParser($route)->parse();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->closureParser($route)->parse() returns the type TypeHints\Unused\Parser\Action\ClosureParser which is incompatible with the documented return type TypeHints\Unused\Analyze...n\ParserActionInterface.
Loading history...
132
    }
133
134
    /**
135
     * @param Route $route
136
     *
137
     * @return TypeHints\Unused\Parser\Action\ParserActionInterface
138
     */
139
    protected function controllerParser(Route $route): ParserActionInterface
140
    {
141
        return new ControllerParser($route);
0 ignored issues
show
Bug Best Practice introduced by
The expression return new TypeHints\Unu...ontrollerParser($route) returns the type TypeHints\Unused\Parser\Action\ControllerParser which is incompatible with the documented return type TypeHints\Unused\Analyze...n\ParserActionInterface.
Loading history...
142
    }
143
144
    /**
145
     * @param Route $route
146
     *
147
     * @return TypeHints\Unused\Parser\Action\ParserActionInterface
148
     */
149
    protected function closureParser(Route $route): ParserActionInterface
150
    {
151
        return new ClosureParser($route);
0 ignored issues
show
Bug Best Practice introduced by
The expression return new TypeHints\Unu...n\ClosureParser($route) returns the type TypeHints\Unused\Parser\Action\ClosureParser which is incompatible with the documented return type TypeHints\Unused\Analyze...n\ParserActionInterface.
Loading history...
152
    }
153
154
    /**
155
     * @param ParserActionInterface $content
156
     *
157
     * @return TypeHints\Unused\Parser\ParserInterface
0 ignored issues
show
Bug introduced by
The type TypeHints\Unused\Analyze...\Parser\ParserInterface was not found. Did you mean TypeHints\Unused\Parser\ParserInterface? If so, make sure to prefix the type with \.
Loading history...
158
     */
159
    protected function viewParser(ParserActionInterface $content): ParserInterface
160
    {
161
        return new ViewParser($content);
0 ignored issues
show
Bug Best Practice introduced by
The expression return new TypeHints\Unu...er\ViewParser($content) returns the type TypeHints\Unused\Parser\ViewParser which is incompatible with the documented return type TypeHints\Unused\Analyze...\Parser\ParserInterface.
Loading history...
162
    }
163
164
    /**
165
     * @return array
166
     */
167
    public function getUnusedViews(): array
168
    {
169
        return array_values($this->unusedViews);
170
    }
171
172
    /**
173
     * @return array
174
     */
175
    public function getUsedViews(): array
176
    {
177
        return array_map(function ($usedView) {
178
            return $usedView->transform();
179
        }, $this->usedViews);
180
    }
181
182
    /**
183
     * @param $usedViews
184
     */
185
    public function retrieveViewCounts(Collection $usedViews): void
186
    {
187
        $usedViewCountValues = array_count_values($usedViews->toArray());
188
189
        collect($this->usedViews)->map(function ($viewTransformer) use ($usedViewCountValues) {
190
            $views = array_keys($viewTransformer->getViews());
191
192
            if (!$views) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $views of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
193
                return;
194
            }
195
196
            foreach ($views as $view) {
197
                $viewTransformer->setViewCount($view, $usedViewCountValues[$view]);
198
            }
199
        });
200
    }
201
}
202