CheckStringy::isPossiblyClassyString()   A
last analyzed

Complexity

Conditions 5
Paths 5

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
nc 5
nop 2
dl 0
loc 10
rs 9.6111
c 0
b 0
f 0
1
<?php
2
3
namespace Imanghafoori\LaravelMicroscope\Checks;
4
5
use Illuminate\Support\Str;
6
use Imanghafoori\LaravelMicroscope\Analyzers\ComposerJson;
7
use Imanghafoori\LaravelMicroscope\Analyzers\FileManipulator;
8
use Imanghafoori\LaravelMicroscope\Analyzers\NamespaceCorrector;
9
use Imanghafoori\LaravelMicroscope\ErrorReporters\ErrorPrinter;
10
11
class CheckStringy
12
{
13
    public static function check($tokens, $absFilePath)
14
    {
15
        (new self())->checkStringy($tokens, $absFilePath);
16
    }
17
18
    public function checkStringy($tokens, $absFilePath)
19
    {
20
        $psr4 = ComposerJson::readAutoload();
21
        $namespaces = array_keys($psr4);
22
        $errorPrinter = resolve(ErrorPrinter::class);
23
        foreach ($tokens as $token) {
24
            if (! $this->isPossiblyClassyString($token, $namespaces)) {
25
                continue;
26
            }
27
28
            $classPath = \trim($token[1], '\'\"');
29
            if (! \class_exists($classPath)) {
30
                if (self::refersToDir($classPath)) {
31
                    continue;
32
                }
33
                $errorPrinter->wrongUsedClassError($absFilePath, $token[1], $token[2]);
34
                continue;
35
            }
36
37
            $errorPrinter->printLink($absFilePath, $token[2]);
38
            $command = app('current.command');
39
40
            if (! self::ask($command, $token, $absFilePath)) {
41
                continue;
42
            }
43
44
            $classPath = $this->getClassyPath($classPath);
45
            $command->info('Replacing: '.$token[1].'  with: '.$classPath);
46
47
            $contextClass = NamespaceCorrector::getNamespaceFromRelativePath($absFilePath);
48
49
            if (NamespaceCorrector::haveSameNamespace($contextClass, $classPath)) {
50
                $classPath = trim(class_basename($classPath), '\\');
51
            }
52
53
            FileManipulator::replaceFirst($absFilePath, $token[1], $classPath);
54
            $command->info('====================================');
55
        }
56
    }
57
58
    protected function getClassyPath($string)
59
    {
60
        ($string[0] !== '\\') && ($string = '\\'.$string);
61
        $string .= '::class';
62
63
        return str_replace('\\\\', '\\', $string);
64
    }
65
66
    private function isPossiblyClassyString($token, $namespaces)
67
    {
68
        $chars = ['@', ' ', ',', ':', '/', '.', '-'];
69
70
        return $token[0] == T_CONSTANT_ENCAPSED_STRING &&
71
            Str::contains($token[1], $namespaces) &&
72
            ! in_array($token[1], $namespaces) &&
73
            ! Str::contains($token[1], $chars) &&
74
            ! Str::endsWith($token[1], '\\');
75
    }
76
77
    private static function ask($command, $token, $absFilePath)
78
    {
79
        $command->getOutput()->text($token[2].' |'.file($absFilePath)[$token[2] - 1]);
80
        $text = 'Do you want to replace: '.$token[1].' with ::class version of it?';
81
82
        return $command->getOutput()->confirm($text, true);
83
    }
84
85
    private static function refersToDir(string $classPath)
86
    {
87
        return is_dir(base_path(NamespaceCorrector::getRelativePathFromNamespace($classPath)));
88
    }
89
}
90