LineAligner   A
last analyzed

Complexity

Total Complexity 21

Size/Duplication

Total Lines 206
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 97.67%

Importance

Changes 5
Bugs 1 Features 1
Metric Value
wmc 21
c 5
b 1
f 1
lcom 1
cbo 2
dl 0
loc 206
ccs 84
cts 86
cp 0.9767
rs 10

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A align() 0 16 2
B findBlocks() 0 50 6
A createCleanedFile() 0 22 3
B buildVariableAssignmentLinePattern() 0 25 4
A buildAlignmentSpace() 0 9 2
A getValidBlocks() 0 12 3
1
<?php
2
3
namespace Matks\PHPMakeUp\LineAlignment;
4
5
use Exception;
6
use Matks\PHPMakeUp\File\FileManagerInterface;
7
use Matks\PHPMakeUp\LineAlignment\VariableAssignmentLine as Line;
8
use Matks\PHPMakeUp\LineAlignment\VariableAssignmentLineBlock as Block;
9
10
/**
11
 * Line Alignment manager
12
 */
13
class LineAligner implements LineAlignerInterface
14
{
15
    /**
16
     * Variable assignment code line regex
17
     */
18
    const VARIABLE_ASSIGNMENT_REGEX_BEGIN = '^([^=\(]*)\s';
19
    const VARIABLE_ASSIGNMENT_REGEX_END   = '\s(.*)$';
20
21
    private $allAssignmentCharacters = array(
22
        '=',
23
        '=>',
24
        '\.=',
25
        '<=',
26
    );
27
28
    /**
29
     * Constructor
30
     *
31
     * @param FileManagerInterface $fileManager
32
     */
33
    public function __construct(FileManagerInterface $fileManager)
34 1
    {
35 1
        $this->fileManager = $fileManager;
0 ignored issues
show
Bug introduced by
The property fileManager does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
36 1
    }
37
38
    /**
39
     * Search and align variable assignments code lines in a file
40
     *
41
     * @param string $filepath
42
     *
43
     * @throws Exception
44
     */
45
    public function align($filepath)
46
    {
47 1
        if (!file_exists($filepath)) {
48
            throw new Exception("File $filepath does not exist");
49
        }
50
51 1
        $blocks      = $this->findBlocks($filepath);
52 1
        $validBlocks = $this->getValidBlocks($blocks);
53
54 1
        $fileLines = $this->createCleanedFile($filepath, $validBlocks);
55
56 1
        $newFilepath = $filepath . '.copy';
57 1
        $this->fileManager->writeFile($newFilepath, $fileLines);
58
59 1
        $this->fileManager->replaceFile($filepath, $newFilepath);
60 1
    }
61
62
    /**
63
     * Find in given eligible VariableAssignmentLineBlocks
64
     *
65
     * @param string $filepath
66
     *
67
     * @return array
68
     */
69
    private function findBlocks($filepath)
70
    {
71 1
        $lines = file($filepath);
72
73 1
        $count        = 0;
74 1
        $currentBlock = null;
75 1
        $blocks       = array();
76
77 1
        foreach ($lines as $lineNumber => $line) {
78
79 1
            $matches = array();
80
81 1
            if (null !== $currentBlock) {
82 1
                $assignmentCharacters = array($currentBlock->getAssignmentCharacter());
83 1
                $pattern              = $this->buildVariableAssignmentLinePattern($assignmentCharacters);
84
85 1
                $result              = preg_match($pattern, $line, $matches);
86 1
                $patternDoesNotMatch = (0 === $result);
87 1
                if ($patternDoesNotMatch) {
88 1
                    $currentBlock = null;
89 1
                }
90 1
            }
91
92 1
            $pattern = $this->buildVariableAssignmentLinePattern($this->allAssignmentCharacters);
93
94 1
            $result              = preg_match($pattern, $line, $matches);
95 1
            $patternDoesNotMatch = (0 === $result);
96 1
            if ($patternDoesNotMatch) {
97 1
                $currentBlock = null;
98 1
                $count++;
99 1
                continue;
100
            }
101
102 1
            $partBefore          = $matches[1];
103 1
            $assignmentCharacter = $matches[2];
104 1
            $partAfter           = $matches[3];
105
106 1
            if (null == $currentBlock) {
107 1
                $currentBlock = new Block($assignmentCharacter);
108 1
                $blocks[]     = $currentBlock;
109 1
            }
110
111 1
            $eligibleLine = new Line($count, $partBefore, $partAfter);
112 1
            $currentBlock->addLine($eligibleLine);
113
114 1
            $count++;
115 1
        }
116
117 1
        return $blocks;
118
    }
119
120
    /**
121
     * Clean file lines according to found VariableAssignmentLineBlocks
122
     *
123
     * @param string $filepath
124
     * @param array  $blocks
125
     *
126
     * @return array
127
     */
128
    private function createCleanedFile($filepath, array $blocks)
129
    {
130 1
        $fileLines = file($filepath);
131
132 1
        foreach ($blocks as $block) {
133 1
            $alignmentLength = $block->getAlignment();
134
135 1
            foreach ($block->getLines() as $line) {
136 1
                $lineNumber = $line->getLineNumber();
137 1
                $partBefore = $line->getPartBefore();
138 1
                $partAfter  = $line->getPartAfter();
139
140 1
                $missingSpaceLength  = $alignmentLength - strlen($partBefore);
141 1
                $alignmentSpace      = $this->buildAlignmentSpace($missingSpaceLength);
142 1
                $assignmentCharacter = $block->getAssignmentCharacter();
143
144 1
                $fileLines[$lineNumber] = $partBefore . $alignmentSpace . ' ' . $assignmentCharacter . ' ' . $partAfter . PHP_EOL;
145 1
            }
146 1
        }
147
148 1
        return $fileLines;
149
    }
150
151
    /**
152
     * @param array $assignmentCharacters
153
     *
154
     * @return string
155
     */
156
    private function buildVariableAssignmentLinePattern(array $assignmentCharacters)
157
    {
158 1
        if (empty($assignmentCharacters)) {
159
            throw new \RuntimeException('No assignment characters provided');
160
        }
161
162 1
        $charactersRegex = '(';
163 1
        $length          = count($assignmentCharacters);
164
165 1
        for ($i = 0; $i < $length; $i++) {
166 1
            $character = $assignmentCharacters[$i];
167
168 1
            if (($length - 1) === $i) {
169 1
                $charactersRegex .= $character;
170 1
            } else {
171 1
                $charactersRegex .= $character . '|';
172
            }
173 1
        }
174
175 1
        $charactersRegex .= ')';
176
177 1
        $pattern = '#' . static::VARIABLE_ASSIGNMENT_REGEX_BEGIN . $charactersRegex . static::VARIABLE_ASSIGNMENT_REGEX_END . '#';
178
179 1
        return $pattern;
180
    }
181
182
    /**
183
     * Build alignment space
184
     *
185
     * @param integer $length
186
     *
187
     * @return string
188
     */
189
    private function buildAlignmentSpace($length)
190
    {
191 1
        $space = '';
192 1
        for ($i = 0; $i < $length; $i++) {
193 1
            $space .= ' ';
194 1
        }
195
196 1
        return $space;
197
    }
198
199
    /**
200
     * Filter valid blocks from given array of VariableAssignmentLineBlock
201
     *
202
     * @param array $blocks array of VariableAssignmentLineBlock
203
     *
204
     * @return array of valid VariableAssignmentLineBlock
205
     */
206
    private function getValidBlocks(array $blocks)
207
    {
208 1
        $result = array();
209
210 1
        foreach ($blocks as $block) {
211 1
            if ($block->isValid()) {
212 1
                $result[] = $block;
213 1
            }
214 1
        }
215
216 1
        return $result;
217
    }
218
}
219