imanghafoori1 /
laravel-microscope
This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
| 1 | <?php |
||
| 2 | |||
| 3 | namespace Imanghafoori\LaravelMicroscope\Commands; |
||
| 4 | |||
| 5 | use Illuminate\Console\Command; |
||
| 6 | use Illuminate\Support\Composer; |
||
| 7 | use Illuminate\Support\Str; |
||
| 8 | use Imanghafoori\LaravelMicroscope\Analyzers\ComposerJson; |
||
| 9 | use Imanghafoori\LaravelMicroscope\CheckNamespaces; |
||
| 10 | use Imanghafoori\LaravelMicroscope\ErrorReporters\ErrorPrinter; |
||
| 11 | use Imanghafoori\LaravelMicroscope\FileReaders\Paths; |
||
| 12 | use Imanghafoori\LaravelMicroscope\LaravelPaths\FilePath; |
||
| 13 | use Imanghafoori\LaravelMicroscope\LaravelPaths\LaravelPaths; |
||
| 14 | use Imanghafoori\LaravelMicroscope\SpyClasses\RoutePaths; |
||
| 15 | |||
| 16 | class CheckPsr4 extends Command |
||
| 17 | { |
||
| 18 | protected $signature = 'check:psr4 {--d|detailed : Show files being checked} {--f|force} {--s|nofix}'; |
||
| 19 | |||
| 20 | protected $description = 'Checks the validity of namespaces'; |
||
| 21 | |||
| 22 | public function handle(ErrorPrinter $errorPrinter) |
||
| 23 | { |
||
| 24 | $this->line(''); |
||
| 25 | $this->info('Started checking PSR-4 namespaces...'); |
||
| 26 | $time = microtime(true); |
||
| 27 | |||
| 28 | $errorPrinter->printer = $this->output; |
||
| 29 | |||
| 30 | $autoload = ComposerJson::readAutoload(); |
||
| 31 | $this->checkNamespaces($autoload); |
||
| 32 | |||
| 33 | $this->option('nofix') && config(['microscope.no_fix' => true]); |
||
| 34 | |||
| 35 | if (CheckNamespaces::$changedNamespaces && ! config('microscope.no_fix')) { |
||
|
0 ignored issues
–
show
|
|||
| 36 | $olds = \array_keys(CheckNamespaces::$changedNamespaces); |
||
| 37 | $news = \array_values(CheckNamespaces::$changedNamespaces); |
||
| 38 | |||
| 39 | $this->fixReferences($autoload, $olds, $news); |
||
| 40 | } |
||
| 41 | |||
| 42 | if (Str::startsWith(request()->server('argv')[1] ?? '', 'check:psr4')) { |
||
| 43 | $this->reportResult($autoload); |
||
| 44 | $this->printErrorsCount($errorPrinter, $time); |
||
| 45 | } else { |
||
| 46 | $this->getOutput()->writeln(' - '.CheckNamespaces::$checkedNamespaces.' namespaces were checked.'); |
||
| 47 | } |
||
| 48 | |||
| 49 | $this->composerDumpIfNeeded($errorPrinter); |
||
| 50 | } |
||
| 51 | |||
| 52 | private function composerDumpIfNeeded(ErrorPrinter $errorPrinter) |
||
| 53 | { |
||
| 54 | if ($c = $errorPrinter->getCount('badNamespace')) { |
||
| 55 | $this->output->write('- '.$c.' Namespace'.($c > 1 ? 's' : '').' Fixed, Running: "composer dump"'); |
||
| 56 | app(Composer::class)->dumpAutoloads(); |
||
| 57 | $this->info("\n".'finished: "composer dump"'); |
||
| 58 | } |
||
| 59 | } |
||
| 60 | |||
| 61 | private function fixRefs($_path, $olds, $news) |
||
| 62 | { |
||
| 63 | $lines = file($_path); |
||
| 64 | $changed = []; |
||
| 65 | $olds = $this->deriveVariants($olds); |
||
| 66 | $news = $this->deriveVariants($news); |
||
| 67 | foreach ($lines as $i => $line) { |
||
| 68 | $count = 0; |
||
| 69 | $lines[$i] = \str_replace($olds, $news, $line, $count); |
||
| 70 | $count && $changed[] = ($i + 1); |
||
|
0 ignored issues
–
show
The expression
$count of type integer|null is loosely compared to true; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.
In PHP, under loose comparison (like For 0 == false // true
0 == null // true
123 == false // false
123 == null // false
// It is often better to use strict comparison
0 === false // false
0 === null // false
Loading history...
|
|||
| 71 | } |
||
| 72 | |||
| 73 | $changed && \file_put_contents($_path, \implode('', $lines)); |
||
|
0 ignored issues
–
show
The expression
$changed 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 Loading history...
|
|||
| 74 | |||
| 75 | return $changed; |
||
| 76 | } |
||
| 77 | |||
| 78 | private function deriveVariants($olds) |
||
| 79 | { |
||
| 80 | $newOld = []; |
||
| 81 | foreach ($olds as $old) { |
||
| 82 | $newOld[] = $old.'('; |
||
| 83 | $newOld[] = $old.'::'; |
||
| 84 | $newOld[] = $old.';'; |
||
| 85 | $newOld[] = $old."\n"; |
||
| 86 | $newOld[] = $old."\r"; |
||
| 87 | } |
||
| 88 | |||
| 89 | return $newOld; |
||
| 90 | } |
||
| 91 | |||
| 92 | private function collectNonPsr4Paths() |
||
| 93 | { |
||
| 94 | $paths = [ |
||
| 95 | RoutePaths::get(), |
||
| 96 | Paths::getAbsFilePaths(LaravelPaths::migrationDirs()), |
||
| 97 | Paths::getAbsFilePaths(config_path()), |
||
| 98 | Paths::getAbsFilePaths(LaravelPaths::factoryDirs()), |
||
| 99 | Paths::getAbsFilePaths(LaravelPaths::seeders()), |
||
| 100 | LaravelPaths::bladeFilePaths(), |
||
| 101 | ]; |
||
| 102 | |||
| 103 | return $this->mergePaths($paths); |
||
| 104 | } |
||
| 105 | |||
| 106 | private function mergePaths($paths) |
||
| 107 | { |
||
| 108 | $all = []; |
||
| 109 | foreach ($paths as $p) { |
||
| 110 | $all = array_merge($all, $p); |
||
| 111 | } |
||
| 112 | |||
| 113 | return $all; |
||
| 114 | } |
||
| 115 | |||
| 116 | private function fixReferences($autoload, $olds, $news) |
||
| 117 | { |
||
| 118 | foreach ($autoload as $psr4Path) { |
||
| 119 | $files = FilePath::getAllPhpFiles($psr4Path); |
||
| 120 | foreach ($files as $classFilePath) { |
||
| 121 | $_path = $classFilePath->getRealPath(); |
||
| 122 | $lineNumbers = $this->fixRefs($_path, $olds, $news); |
||
| 123 | foreach ($lineNumbers as $line) { |
||
| 124 | $this->report($_path, $line); |
||
| 125 | } |
||
| 126 | } |
||
| 127 | } |
||
| 128 | |||
| 129 | foreach ($this->collectNonPsr4Paths() as $_path) { |
||
| 130 | $lineNumbers = $this->fixRefs($_path, $olds, $news); |
||
| 131 | foreach ($lineNumbers as $line) { |
||
| 132 | $this->report($_path, $line); |
||
| 133 | } |
||
| 134 | } |
||
| 135 | } |
||
| 136 | |||
| 137 | private function checkNamespaces(array $autoload) |
||
| 138 | { |
||
| 139 | foreach ($autoload as $psr4Namespace => $psr4Path) { |
||
| 140 | $files = FilePath::getAllPhpFiles($psr4Path); |
||
| 141 | CheckNamespaces::within($files, $psr4Path, $psr4Namespace, $this); |
||
|
0 ignored issues
–
show
$files is of type object<Symfony\Component\Finder\Finder>, but the function expects a object<Imanghafoori\LaravelMicroscope\iterable>.
It seems like the type of the argument is not accepted by the function/method which you are calling. In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug. We suggest to add an explicit type cast like in the following example: function acceptsInteger($int) { }
$x = '123'; // string "123"
// Instead of
acceptsInteger($x);
// we recommend to use
acceptsInteger((integer) $x);
Loading history...
|
|||
| 142 | } |
||
| 143 | } |
||
| 144 | |||
| 145 | private function report($_path, $lineNumber) |
||
| 146 | { |
||
| 147 | app(ErrorPrinter::class)->simplePendError('', $_path, $lineNumber, 'ns_replacement', 'Namespace replacement:'); |
||
| 148 | } |
||
| 149 | |||
| 150 | private function printErrorsCount($errorPrinter, $time) |
||
| 151 | { |
||
| 152 | if ($errorCount = $errorPrinter->errorsList['total']) { |
||
| 153 | $this->warn(PHP_EOL.$errorCount.' error(s) found in namespaces'); |
||
| 154 | } else { |
||
| 155 | $this->noErrorFound($time); |
||
| 156 | } |
||
| 157 | } |
||
| 158 | |||
| 159 | private function reportResult($autoload) |
||
| 160 | { |
||
| 161 | $this->getOutput()->writeln(''); |
||
| 162 | $this->getOutput()->writeln('<fg=green>Finished!</fg=green>'); |
||
| 163 | $this->getOutput()->writeln('=============================='); |
||
| 164 | $this->getOutput()->writeln('<options=bold;fg=yellow>'.CheckNamespaces::$checkedNamespaces.' classes were checked under:</>'); |
||
| 165 | $this->getOutput()->writeln(' - '.implode("\n - ", array_keys($autoload)).''); |
||
| 166 | } |
||
| 167 | |||
| 168 | private function noErrorFound($time) |
||
| 169 | { |
||
| 170 | $time = microtime(true) - $time; |
||
| 171 | $this->line(PHP_EOL.'<fg=green>All namespaces are correct!</><fg=blue> You rock \(^_^)/ </>'); |
||
| 172 | $this->line('<fg=red;options=bold>'.round($time, 5).'(s)</>'); |
||
| 173 | $this->line(''); |
||
| 174 | } |
||
| 175 | } |
||
| 176 |
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.