Issues (15)

src/Command/CheckTranslations/CodeAnalyzer.php (1 issue)

Labels
Severity
1
<?php
2
3
namespace Efabrica\TranslationsAutomatization\Command\CheckTranslations;
4
5
6
use Efabrica\TranslationsAutomatization\Command\CheckFormKeys\ClassMethodArgVisitor;
7
use Exception;
8
use PhpParser\NodeTraverser;
9
use PhpParser\ParserFactory;
10
use RecursiveDirectoryIterator;
11
use RecursiveIteratorIterator;
12
use SplFileInfo;
13
14
class CodeAnalyzer
15
{
16
    private $directories;
17
18
    private $translationFindConfig;
19
20
    public function __construct(array $directories, array $translationFindConfig)
21
    {
22
        $this->directories = $directories;
23
        $this->translationFindConfig = $translationFindConfig;
24
    }
25
26
    public function analyzeDirectories(): array
27
    {
28
        $result = [];
29
        foreach ($this->directories as $directory) {
30
            if (is_dir($directory)) {
31
                $result[] = $this->analyzeDirectory($directory);
32
            }
33
        }
34
        return array_merge(...$result);
35
    }
36
37
    private function analyzeDirectory(string $directory): array
38
    {
39
        $translateCalls = [];
40
        $files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($directory));
41
        foreach ($files as $file) {
42
            if (!$file->isFile()) {
43
                continue;
44
            }
45
            $code = file_get_contents($file->getPathname());
46
            if ($file->getExtension() === 'php') {
47
                $translateCalls[] = $this->analyzeCode($code, $file->getPathname());
48
            }
49
            if ($file->getExtension() === 'latte') {
50
                $translateCalls[] = $this->findInLatte($file);
51
            }
52
        }
53
54
        return array_merge(...$translateCalls);
55
    }
56
57
    private function findInLatte(SplFileInfo $file): array
58
    {
59
        $translateCalls = [];
60
        $regex = "/\{_'[^']*'\}/";
61
        $content = file_get_contents($file->getPathname());
62
        if (preg_match_all($regex, $content, $matches)) {
63
            $lines = file($file->getPathname());
64
            foreach ($matches[0] as $match) {
65
                foreach ($lines as $lineNumber => $lineContent) {
66
                    if (strpos($lineContent, $match) !== false) {
67
                        $translateCalls[] = ['key' => substr($match, 3, -2), 'file' => $file->getPathname(), 'line' => $lineNumber + 1, 'method' => 'in_latte'];
68
                    }
69
                }
70
            }
71
        }
72
        return $translateCalls;
73
    }
74
75
    private function analyzeCode(string $code, string $filePath): array
76
    {
77
        $parser = (new ParserFactory())->createForNewestSupportedVersion();
78
        $traverser = new NodeTraverser();
79
        $result = [];
80
81
        $traverser->addVisitor(new ClassMethodArgVisitor($result, $filePath, $this->translationFindConfig));
82
83
        try {
84
            $ast = $parser->parse($code);
85
            $traverser->traverse($ast);
0 ignored issues
show
It seems like $ast can also be of type null; however, parameter $nodes of PhpParser\NodeTraverser::traverse() 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

85
            $traverser->traverse(/** @scrutinizer ignore-type */ $ast);
Loading history...
86
        } catch (Exception $e) {
87
            echo "Error analyzing file $filePath: " . $e->getMessage() . PHP_EOL;
88
        }
89
90
        return $result;
91
    }
92
}
93