Builder   B
last analyzed

Complexity

Total Complexity 43

Size/Duplication

Total Lines 245
Duplicated Lines 0 %

Test Coverage

Coverage 91.18%

Importance

Changes 6
Bugs 2 Features 0
Metric Value
eloc 100
c 6
b 2
f 0
dl 0
loc 245
ccs 93
cts 102
cp 0.9118
rs 8.96
wmc 43

9 Methods

Rating   Name   Duplication   Size   Complexity  
B isIgnored() 0 17 8
A removeSortingInformations() 0 8 2
A getOrCreateDir() 0 12 2
A createContent() 0 37 5
A getName() 0 10 2
A sortTree() 0 6 3
A finalizeTree() 0 16 5
B build() 0 36 8
B getOrCreatePage() 0 34 8

How to fix   Complexity   

Complex Class

Complex classes like Builder often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Builder, and based on these observations, apply Extract Interface, too.

1
<?php namespace Todaymade\Daux\Tree;
2
3
use RuntimeException;
4
use SplFileInfo;
5
use Todaymade\Daux\DauxHelper;
6
7
class Builder
8
{
9
    protected static $IGNORED = [
10
        // Popular VCS Systems
11
        '.svn', '_svn', 'CVS', '_darcs', '.arch-params', '.monotone', '.bzr', '.git', '.hg',
12
13
        // Operating system files
14
        '.DS_Store', 'Thumbs.db',
15
    ];
16
17 21
    protected static function isIgnored(SplFileInfo $file, $ignore)
18
    {
19 21
        $filename = $file->getFilename();
20
21 21
        if (in_array($filename, static::$IGNORED)) {
22
            return true;
23
        }
24
25 21
        if (array_key_exists('folders', $ignore) && $file->isDir() && in_array($filename, $ignore['folders'])) {
26
            return true;
27
        }
28
29 21
        if (array_key_exists('files', $ignore) && !$file->isDir() && in_array($filename, $ignore['files'])) {
30
            return true;
31
        }
32
33 21
        return false;
34
    }
35
36
    /**
37
     * Get name for a file.
38
     *
39
     * @param string $path
40
     *
41
     * @return string
42 27
     */
43
    protected static function getName($path)
44
    {
45 27
        // ['dir' => 1, 'basename' => 2, 'filename' => 3, 'extension' => 5]
46
        preg_match('%^(.*?)[\\\\/]*(([^/\\\\]*?)(\.([^\.\\\\/]+?)|))[\\\\/\.]*$%im', $path, $m);
47 27
48
        if (!isset($m[3])) {
49
            throw new RuntimeException('Name not found');
50
        }
51 27
52
        return $m[3];
53
    }
54
55
    /**
56
     * Build the initial tree.
57
     *
58
     * @param Directory $node
59
     * @param array $ignore
60 21
     */
61
    public static function build($node, $ignore)
62
    {
63 21
        try {
64
            $it = new \FilesystemIterator($node->getPath());
65
        } catch (\UnexpectedValueException $e) {
66
            return;
67
        }
68 21
69
        if ($node instanceof Root) {
70 21
            // Ignore config.json in the root directory
71
            $ignore['files'][] = 'config.json';
72
        }
73
74 21
        /** @var \SplFileInfo $file */
75 21
        foreach ($it as $file) {
76
            if (static::isIgnored($file, $ignore)) {
77
                continue;
78
            }
79 21
80 19
            if ($file->isDir()) {
81 19
                $title = DauxHelper::slug(static::removeSortingInformations($file->getFilename()));
82 19
                $new = new Directory($node, $title, $file);
83 19
                $new->setName(static::getName($file->getPathName()));
84 19
                $new->setTitle(str_replace('_', ' ', static::removeSortingInformations($new->getName())));
85
                static::build($new, $ignore);
86 19
87 19
                $index = $new->getLocalIndexPage();
88 19
                if ($index && $index->getTitle() != $title) {
89
                    $new->setTitle($index->getTitle());
90
                }
91 21
            } else {
92
                static::createContent($node, $file);
93
            }
94
        }
95 21
96 21
        $node->sort();
97
    }
98
99
    /**
100
     * @return Content|Raw
101
     */
102
    public static function createContent(Directory $parent, SplFileInfo $file)
103 21
    {
104
        $name = static::getName($file->getPathname());
105 21
106
        $config = $parent->getConfig();
107 21
108
        if (!in_array($file->getExtension(), $config->getValidContentExtensions())) {
109 21
            $uri = $file->getFilename();
110 2
111
            $entry = new Raw($parent, $uri, $file);
112 2
            $entry->setTitle(str_replace('_', ' ', static::removeSortingInformations($name)));
113 2
            $entry->setName($name);
114 2
115
            return $entry;
116 2
        }
117
118
        $uri = static::removeSortingInformations($name);
119 21
        $uri = DauxHelper::slug($uri);
120 21
        if ($config->isStatic()) {
121 21
            $uri .= '.html';
122 20
        }
123
124
        $entry = new Content($parent, $uri, $file);
125 21
126
        if ($entry->getUri() == $config->getIndexKey()) {
127 21
            if ($parent instanceof Root) {
128 2
                $entry->setTitle($config->getTitle());
129 1
            } else {
130
                $entry->setTitle($parent->getTitle());
131 2
            }
132
        } else {
133
            $entry->setTitle(str_replace('_', ' ', static::removeSortingInformations($name)));
134 21
        }
135
136
        $entry->setName($name);
137 21
138
        return $entry;
139 21
    }
140
141
    /**
142
     * @param string $filename
143
     *
144
     * @return string
145
     */
146 45
    public static function removeSortingInformations($filename)
147
    {
148 45
        preg_match('/^[-+]?[0-9]*_?(.*)/', $filename, $matches);
149
150
        // Remove the numeric part
151
        // of the filename, only if
152
        // there is something after
153 45
        return empty($matches[1]) ? $matches[0] : $matches[1];
154
    }
155
156
    /**
157
     * @param string $title
158
     *
159
     * @return Directory
160
     */
161 2
    public static function getOrCreateDir(Directory $parent, $title)
162
    {
163 2
        $slug = DauxHelper::slug($title);
164
165 2
        if (array_key_exists($slug, $parent->getEntries())) {
166 1
            return $parent->getEntries()[$slug];
167
        }
168
169 1
        $dir = new Directory($parent, $slug);
170 1
        $dir->setTitle($title);
171
172 1
        return $dir;
173
    }
174
175
    /**
176
     * @param string $path
177
     *
178
     * @return ContentAbstract
179
     */
180 7
    public static function getOrCreatePage(Directory $parent, $path)
181
    {
182 7
        $extension = pathinfo($path, PATHINFO_EXTENSION);
183
        // If the file doesn't have an extension, set .md as a default
184 7
        if ($extension == '') {
185 1
            $extension = 'md';
186 1
            $path .= '.md';
187
        }
188
189 7
        $raw = !in_array($extension, $parent->getConfig()->getValidContentExtensions());
190
191 7
        $title = $uri = $path;
192 7
        if (!$raw) {
193 6
            $title = static::getName($path);
194 6
            $uri = DauxHelper::slug($title);
195 6
            if ($parent->getConfig()->isStatic()) {
196 6
                $uri .= '.html';
197
            }
198
        }
199
200 7
        if (array_key_exists($uri, $parent->getEntries())) {
201 1
            return $parent->getEntries()[$uri];
202
        }
203
204 6
        $page = $raw ? new ComputedRaw($parent, $uri) : new Content($parent, $uri);
205 6
        $page->setContent('-'); //set an almost empty content to avoid problems
206 6
        $page->setName($path);
207 6
        $page->setTitle($title);
208
209 6
        if ($title == 'index' || $title == '_index') {
210 1
            $page->setTitle($parent->getTitle());
211
        }
212
213 6
        return $page;
214
    }
215
216
    /**
217
     * Sort the tree recursively.
218
     */
219
    public static function sortTree(Directory $current)
220
    {
221 1
        $current->sort();
222 1
        foreach ($current->getEntries() as $entry) {
223 1
            if ($entry instanceof Directory) {
224 1
                Builder::sortTree($entry);
225
            }
226
        }
227
    }
228 1
229
    /**
230
     * Calculate next and previous for all pages.
231
     *
232
     * @param null|Content $prev
233
     *
234
     * @return null|Content
235
     */
236
    public static function finalizeTree(Directory $current, $prev = null)
237 1
    {
238
        foreach ($current->getEntries() as $entry) {
239 1
            if ($entry instanceof Directory) {
240 1
                $prev = Builder::finalizeTree($entry, $prev);
241
            } elseif ($entry instanceof Content) {
242 1
                if ($prev) {
243 1
                    $prev->setNext($entry);
244 1
                    $entry->setPrevious($prev);
245 1
                }
246
247
                $prev = $entry;
248 1
            }
249
        }
250
251
        return $prev;
252 1
    }
253
}
254