ViewAbstract::getTreeListHtml()   C
last analyzed

Complexity

Conditions 12
Paths 18

Size

Total Lines 102
Code Lines 62

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 12
eloc 62
nc 18
nop 2
dl 0
loc 102
rs 6.4024
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * View Abstract
5
 *
6
 * PHP Version 5.3.0
7
 *
8
 * Copyright (c) 2007-2010, Mayflower GmbH
9
 * All rights reserved.
10
 *
11
 * Redistribution and use in source and binary forms, with or without
12
 * modification, are permitted provided that the following conditions
13
 * are met:
14
 *
15
 *   * Redistributions of source code must retain the above copyright
16
 *     notice, this list of conditions and the following disclaimer.
17
 *
18
 *   * Redistributions in binary form must reproduce the above copyright
19
 *     notice, this list of conditions and the following disclaimer in
20
 *     the documentation and/or other materials provided with the
21
 *     distribution.
22
 *
23
 *   * Neither the name of Mayflower GmbH nor the names of his
24
 *     contributors may be used to endorse or promote products derived
25
 *     from this software without specific prior written permission.
26
 *
27
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
30
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
31
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
32
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
33
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
34
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
35
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
37
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38
 * POSSIBILITY OF SUCH DAMAGE.
39
 *
40
 * @category PHP_CodeBrowser
41
 *
42
 * @author Elger Thiele <[email protected]>
43
 * @author Jan Mergler <[email protected]>
44
 * @author Simon Kohlmeyer <[email protected]>
45
 *
46
 * @copyright 2007-2010 Mayflower GmbH
47
 *
48
 * @license http://www.opensource.org/licenses/bsd-license.php  BSD License
49
 *
50
 * @version SVN: $Id$
51
 *
52
 * @link http://www.phpunit.de/
53
 *
54
 * @since File available since  0.1.0
55
 */
56
57
namespace PHPCodeBrowser\View;
58
59
use Exception;
60
use PHPCodeBrowser\File;
61
use PHPCodeBrowser\Helper\IOHelper;
62
63
/**
64
 * ViewAbstract
65
 *
66
 * This class is generating the highlighted and formatted html view for file.
67
 *
68
 * @category PHP_CodeBrowser
69
 *
70
 * @author Elger Thiele <[email protected]>
71
 * @author Jan Mergler <[email protected]>
72
 * @author Simon Kohlmeyer <[email protected]>
73
 *
74
 * @copyright 2007-2010 Mayflower GmbH
75
 *
76
 * @license http://www.opensource.org/licenses/bsd-license.php  BSD License
77
 *
78
 * @version Release: @package_version@
79
 *
80
 * @link http://www.phpunit.de/
81
 *
82
 * @since Class available since  0.1.0
83
 */
84
class ViewAbstract
85
{
86
    /**
87
     * Template directory
88
     *
89
     * @var string
90
     */
91
    protected $templateDir;
92
93
    /**
94
     * Output directory
95
     *
96
     * @var string
97
     */
98
    protected $outputDir;
99
100
    /**
101
     * Available resource folders
102
     *
103
     * @var array
104
     */
105
    protected $resourceFolders = ['css', 'js', 'img'];
106
107
    /**
108
     * IOHelper for filesystem interaction.
109
     *
110
     * @var IOHelper
111
     */
112
    protected $ioHelper;
113
114
    /**
115
     * Default Constructor
116
     *
117
     * @param string   $templateDir The directory containing the templates.
118
     * @param string   $outputDir   The directory where the reviews should be.
119
     * @param IOHelper $ioHelper    The IOHelper object to use for I/O.
120
     *
121
     * @throws Exception
122
     */
123
    public function __construct(string $templateDir, string $outputDir, IOHelper $ioHelper)
124
    {
125
        $this->templateDir = $templateDir;
126
127
        if (!$this->templateDir) {
128
            throw new Exception(
129
                "Specified template directory '{$templateDir}' does not exist"
130
            );
131
        }
132
133
        $this->outputDir = $outputDir;
134
135
        if (!$this->outputDir) {
136
            throw new Exception(
137
                "Specified output directory '{$outputDir}' does not exist"
138
            );
139
        }
140
141
        $this->outputDir .= DIRECTORY_SEPARATOR;
142
143
        $this->ioHelper = $ioHelper;
144
    }
145
146
    /**
147
     * Copy needed resources to output directory
148
     *
149
     * @return void
150
     *
151
     * @throws Exception
152
     *
153
     * @see IOHelper->copyFile
154
     */
155
    public function copyResourceFolders(): void
156
    {
157
        foreach ($this->resourceFolders as $folder) {
158
            $this->ioHelper->copyDirectory(
159
                $this->templateDir.DIRECTORY_SEPARATOR.$folder,
160
                $this->outputDir.DIRECTORY_SEPARATOR.$folder
161
            );
162
        }
163
    }
164
165
    /**
166
     * Copy the noErrors file as index.html to indicate that no
167
     * source files were found
168
     *
169
     * @return void
170
     */
171
    public function copyNoErrorsIndex(): void
172
    {
173
        $this->ioHelper->createFile(
174
            $this->outputDir.'/index.html',
175
            $this->render('noErrors', [])
176
        );
177
    }
178
179
    /**
180
     * Creates a javascript-filled index.html
181
     *
182
     * @param array $fileList
183
     * @param bool  $excludeOK
184
     *
185
     * @return void
186
     */
187
    public function generateIndex(array $fileList, bool $excludeOK = false): void
188
    {
189
        //we want to exclude files without issues
190
        if ($excludeOK) {
191
            $fileList = \array_filter($fileList, [ViewAbstract::class, 'hasFileAnyIssues']);
192
        }
193
194
        $data = [];
195
196
        $data['treeList'] = $this->getTreeListHtml($fileList);
197
        $data['fileList'] = $fileList;
198
199
        $this->ioHelper->createFile(
200
            $this->outputDir.'/index.html',
201
            $this->render('index', $data)
202
        );
203
    }
204
205
    /**
206
     * Has the file any issues?
207
     *
208
     * @param File $file
209
     *
210
     * @return bool
211
     */
212
    public static function hasFileAnyIssues(File $file): bool
213
    {
214
        $issues = $file->getIssues();
215
216
        return !empty($issues);
217
    }
218
219
    /**
220
     * Convert a list of files to a html fragment for jstree.
221
     *
222
     * @param array<File> $fileList   The files, format: array('name' => File).
223
     * @param string      $hrefPrefix The prefix to put before all href= tags.
224
     *
225
     * @return string  The html fragment.
226
     */
227
    protected function getTreeListHtml(array $fileList, string $hrefPrefix = ''): string
228
    {
229
        /*
230
         * In this method, all directories have a trailing DIRECTORY_SEPARATOR.
231
         * This is important so that $curDir doesn't become empty if we go
232
         * up to the root directory ('/' on linux)
233
         */
234
        $curDir = IOHelper::getCommonPathPrefix(\array_keys($fileList));
235
        $preLen = \strlen($curDir);
236
237
        $indentStep = 4;
238
        $indent     = $indentStep;
239
        $ret        = '<ul>'.PHP_EOL;
240
241
        foreach ($fileList as $name => $file) {
242
            $dir = \dirname($name).DIRECTORY_SEPARATOR;
243
244
            // Go back until the file is somewhere below curDir
245
            while (!\str_starts_with($dir, $curDir)) {
246
                // chop off one subDir from $curDir
247
                $curDir  = \substr(
248
                    $curDir,
249
                    0,
250
                    \strrpos($curDir, DIRECTORY_SEPARATOR, -2) + 1
251
                );
252
                $ret    .= \str_pad(' ', $indent);
253
                $ret    .= '</ul>'.PHP_EOL;
254
                $indent -= $indentStep;
255
                $ret    .= \str_pad(' ', $indent);
256
                $ret    .= '</li>'.PHP_EOL;
257
            }
258
259
            if ($dir !== $curDir) {
260
                // File is in a subDir of current directory
261
                // relDir has no leading or trailing slash.
262
                $relDir  = \substr($dir, \strlen($curDir), -1);
263
                $relDirs = \explode(DIRECTORY_SEPARATOR, $relDir);
264
265
                foreach ($relDirs as $dirName) {
266
                    $curDir .= $dirName.DIRECTORY_SEPARATOR;
267
                    // Check how many errors/warnings are in this dir.
268
                    //TODO: Optimize this. Counts get recalculated for subDirs.
269
                    $errors   = 0;
270
                    $warnings = 0;
271
272
                    foreach (\array_keys($fileList) as $fName) {
273
                        if (\strncmp($fName, $curDir, \strlen($curDir)) !== 0) {
274
                            continue;
275
                        }
276
277
                        $errors   += $fileList[$fName]->getErrorCount();
278
                        $warnings += $fileList[$fName]->getWarningCount();
279
                    }
280
281
                    $count = '';
282
283
                    if (0 !== $errors || 0 !== $warnings) {
284
                        $count .= '(<span class="errorCount">';
285
                        $count .= $errors;
286
                        $count .= '</span>|<span class="warningCount">';
287
                        $count .= $warnings.'</span>)';
288
                    }
289
290
                    $ret    .= \str_pad(' ', $indent);
291
                    $ret    .= "<li><a class='treeDir'>{$dirName} {$count}</a>".PHP_EOL;
292
                    $indent += $indentStep;
293
                    $ret    .= \str_pad(' ', $indent);
294
                    $ret    .= '<ul>'.PHP_EOL;
295
                }
296
            }
297
298
            $name      = \str_replace('\\', '/', $name);
299
            $shortName = \substr($name, $preLen);
300
            $fileName  = \basename($name);
301
            $count     = '';
302
303
            if (0 !== $file->getErrorCount() || 0 !== $file->getWarningCount()) {
304
                $count .= '(<span class="errorCount">';
305
                $count .= $file->getErrorCount();
306
                $count .= '</span>|<span class="warningCount">';
307
                $count .= $file->getWarningCount();
308
                $count .= '</span>)';
309
            }
310
311
            $ret .= \str_pad(' ', $indent);
312
            $ret .= '<li class="php"><a class="fileLink" href="';
313
            $ret .= $hrefPrefix.$shortName.'.html">';
314
            $ret .= "{$fileName} {$count}</a></li>".PHP_EOL;
315
        }
316
317
        while ($indent > $indentStep) {
318
            $indent -= $indentStep;
319
            $ret    .= \str_pad(' ', $indent);
320
            $ret    .= '</ul>'.PHP_EOL;
321
            $indent -= $indentStep;
322
            $ret    .= \str_pad(' ', $indent);
323
            $ret    .= '</li>'.PHP_EOL;
324
        }
325
326
        $ret .= '</ul>'.PHP_EOL;
327
328
        return $ret;
329
    }
330
331
    /**
332
     * Render a template.
333
     *
334
     * Defined template is parsed and filled with data.
335
     * Rendered content is read from output buffer.
336
     *
337
     * @param string $templateName Template file to use for rendering
338
     * @param array  $data         Given data set to use for rendering
339
     *
340
     * @return string              HTML files as string from output buffer
341
     */
342
    protected function render(string $templateName, array $data): string
343
    {
344
        $filePath = $this->templateDir.DIRECTORY_SEPARATOR.$templateName.'.tpl';
345
346
        \extract($data, EXTR_SKIP);
347
348
        \ob_start();
349
        include $filePath;
350
        $contents = \ob_get_clean();
351
352
        return $contents;
353
    }
354
}
355