FileManipulator   A
last analyzed

Complexity

Total Complexity 22

Size/Duplication

Total Lines 119
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Importance

Changes 0
Metric Value
dl 0
loc 119
rs 10
c 0
b 0
f 0
wmc 22
lcom 1
cbo 4

5 Methods

Rating   Name   Duplication   Size   Complexity  
A removeLine() 0 11 2
A replaceFirst() 0 13 5
A insertAtLine() 0 10 2
B fixReference() 0 47 9
A applyToEachLine() 0 31 4
1
<?php
2
3
namespace Imanghafoori\LaravelMicroscope\Analyzers;
4
5
use Illuminate\Support\Str;
6
use Imanghafoori\LaravelMicroscope\Psr4Classes;
7
8
class FileManipulator
9
{
10
    public static function removeLine($file, $_line = null)
11
    {
12
        $lineChanger = function ($lineNum) use ($_line) {
13
            // Replace only the first occurrence in the file
14
            if ($lineNum == $_line) {
15
                return '';
16
            }
17
        };
18
19
        return self::applyToEachLine($file, $lineChanger);
20
    }
21
22
    public static function replaceFirst($absPath, $search, $replace = '', $_line = null)
23
    {
24
        $lineChanger = function ($lineNum, $line, $isReplaced) use ($search, $replace, $_line) {
25
            // Replace only the first occurrence in the file
26
            if (! $isReplaced && strstr($line, $search)) {
27
                if (! $_line || $lineNum == $_line) {
28
                    return Str::replaceFirst($search, $replace, $line);
29
                }
30
            }
31
        };
32
33
        return self::applyToEachLine($absPath, $lineChanger);
34
    }
35
36
    public static function insertAtLine($absPath, $newLine, $atLine)
37
    {
38
        $lineChanger = function ($lineNum, $currentLine) use ($newLine, $atLine) {
39
            if ($lineNum == $atLine) {
40
                return $newLine.PHP_EOL.$currentLine;
41
            }
42
        };
43
44
        return self::applyToEachLine($absPath, $lineChanger);
45
    }
46
47
    public static function fixReference($absPath, $class, $lineNum, $prefix = '', $isUsed = false)
48
    {
49
        if (config('microscope.no_fix')) {
50
            return [false, []];
51
        }
52
53
        $class_list = Psr4Classes::classList();
54
        $cls = \explode('\\', $class);
55
        $className = array_pop($cls);
56
        $correct = $class_list[$className] ?? [];
57
58
        $contextClassNamespace = NamespaceCorrector::getNamespaceFromRelativePath($absPath);
59
60
        if (\count($correct) !== 1) {
61
            return [false, $correct];
62
        }
63
64
        // We just remove the wrong import if import is not needed.
65
        if (NamespaceCorrector::haveSameNamespace($contextClassNamespace, $correct[0])) {
66
            if ($isUsed) {
67
                return [self::removeLine($absPath, $lineNum), [' Deleted!']];
68
            }
69
70
            $correct[0] = trim(class_basename($correct[0]), '\\');
71
            $prefix = '';
72
        }
73
74
        $uses = ParseUseStatement::parseUseStatements(token_get_all(file_get_contents($absPath)))[1];
75
76
        // if there is any use statement at the top of the file
77
        if (count($uses) && ! isset($uses[$className])) {
78
            foreach ($uses as $use) {
79
                self::replaceFirst($absPath, $class, $className, $lineNum);
80
                $lineNum = $use[1];
81
                $fullClassPath = trim($prefix, '\\').$correct[0];
82
83
                return [self::insertAtLine($absPath, "use $fullClassPath;", $lineNum), $correct];
84
            }
85
        }
86
        $uses = ParseUseStatement::parseUseStatements(token_get_all(file_get_contents($absPath)))[1];
87
88
        if (isset($uses[$className])) {
89
            return [self::replaceFirst($absPath, $class, $className, $lineNum), $correct];
90
        }
91
92
        return [self::replaceFirst($absPath, $class, $prefix.$correct[0], $lineNum), $correct];
93
    }
94
95
    private static function applyToEachLine($absPath, $lineChanger)
96
    {
97
        $reading = fopen($absPath, 'r');
98
        $tmpFile = fopen($absPath.'._tmp', 'w');
99
100
        $isReplaced = false;
101
102
        $lineNum = 0;
103
        while (! feof($reading)) {
104
            $lineNum++;
105
            $line = fgets($reading);
106
107
            $newLine = $lineChanger($lineNum, $line, $isReplaced);
108
            if (is_string($newLine)) {
109
                $line = $newLine;
110
                $isReplaced = true;
111
            }
112
            // Copy the entire file to the end
113
            fwrite($tmpFile, $line);
114
        }
115
        fclose($reading);
116
        fclose($tmpFile);
117
        // Might as well not overwrite the file if we didn't replace anything
118
        if ($isReplaced) {
119
            rename($absPath.'._tmp', $absPath);
120
        } else {
121
            unlink($absPath.'._tmp');
122
        }
123
124
        return $isReplaced;
125
    }
126
}
127