Passed
Push — master ( 669df3...c9ea6f )
by Christian
03:05
created

DirectoryRenderer::renderDirectory()   B

Complexity

Conditions 9
Paths 18

Size

Total Lines 35
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 90

Importance

Changes 0
Metric Value
cc 9
eloc 25
nc 18
nop 1
dl 0
loc 35
ccs 0
cts 25
cp 0
crap 90
rs 8.0555
c 0
b 0
f 0
1
<?php
2
3
namespace Scheb\Tombstone\Analyzer\Report\Html\Renderer;
4
5
use Scheb\Tombstone\Analyzer\AnalyzerFileResult;
6
use Scheb\Tombstone\Analyzer\AnalyzerResult;
7
use Scheb\Tombstone\Analyzer\Cli\Application;
8
use Scheb\Tombstone\Analyzer\Report\Html\TemplateFactory;
9
use Scheb\Tombstone\Analyzer\Report\PathTools;
10
use Scheb\Tombstone\Analyzer\Report\ReportGeneratorInterface;
11
use Scheb\Tombstone\Analyzer\ResultAggregateInterface;
12
use Scheb\Tombstone\Tracing\PathNormalizer;
13
14
class DirectoryRenderer implements ReportGeneratorInterface
15
{
16
    /**
17
     * @var string
18
     */
19
    private $reportDir;
20
21
    /**
22
     * @var string
23
     */
24
    private $sourceDir;
25
26
    /**
27
     * @var \Text_Template
28
     */
29
    private $directoryTemplate;
30
31
    /**
32
     * @var \Text_Template
33
     */
34
    private $directoryItemTemplate;
35
36
    /**
37
     * @var \Text_Template
38
     */
39
    private $barTemplate;
40
41
    public function __construct(string $reportDir, string $sourceDir)
42
    {
43
        $this->reportDir = $reportDir;
44
        $this->sourceDir = $sourceDir;
45
        $this->directoryTemplate = TemplateFactory::getTemplate('directory.html');
46
        $this->directoryItemTemplate = TemplateFactory::getTemplate('directory_item.html');
47
        $this->barTemplate = TemplateFactory::getTemplate('percentage_bar.html');
48
    }
49
50
    public function generate(AnalyzerResult $result): void
51
    {
52
        $tree = new ResultDirectory();
53
        $files = $result->getPerFile();
54
        foreach ($files as $fileResult) {
55
            $relativePath = PathNormalizer::makeRelativeTo($fileResult->getFile(), $this->sourceDir);
56
            $tree->addFileResult($relativePath, $fileResult);
57
        }
58
59
        $this->renderDirectoryRecursively($tree);
60
    }
61
62
    private function renderDirectoryRecursively(ResultDirectory $directory): void
63
    {
64
        $this->renderDirectory($directory);
65
        foreach ($directory->getDirectories() as $subDir) {
66
            $this->renderDirectoryRecursively($subDir);
67
        }
68
    }
69
70
    private function renderDirectory(ResultDirectory $directory): void
71
    {
72
        $directoryPath = $directory->getPath();
73
        $pathToRoot = './'.str_repeat('../', substr_count($directoryPath, '/') + ($directoryPath ? 1 : 0));
74
        $filesList = '';
75
        foreach ($directory->getDirectories() as $subDir) {
76
            $name = $subDir->getName();
77
            $link = './'.$subDir->getName().'/index.html';
78
            if ($subDir->getDeadCount() || $subDir->getUndeadCount()) {
79
                $filesList .= $this->renderDirectoryItem($name, $link, $subDir, $pathToRoot);
80
            }
81
        }
82
        foreach ($directory->getFiles() as $fileResult) {
83
            $name = basename($fileResult->getFile());
84
            $link = './'.$name.'.html';
85
            if ($fileResult->getDeadCount() || $fileResult->getUndeadCount()) {
86
                $filesList .= $this->renderDirectoryItem($name, $link, $fileResult, $pathToRoot);
87
            }
88
        }
89
90
        $this->directoryTemplate->setVar([
91
            'path_to_root' => $pathToRoot,
92
            'full_path' => PathTools::makePathAbsolute($directoryPath, $this->sourceDir),
93
            'breadcrumb' => $this->renderBreadcrumb($directoryPath),
94
            'files_list' => $filesList,
95
            'date' => date('r'),
96
            'version' => Application::VERSION,
97
        ]);
98
99
        $reportFile = $this->reportDir.DIRECTORY_SEPARATOR.$directoryPath.'/index.html';
100
        $reportDir = dirname($reportFile);
101
        if (!is_dir($reportDir)) {
102
            mkdir($reportDir, 0777, true);
103
        }
104
        $this->directoryTemplate->renderTo($reportFile);
105
    }
106
107
    /**
108
     * @param string                             $name
109
     * @param string                             $link
110
     * @param ResultAggregateInterface $result
111
     * @param string                             $pathToRoot
112
     *
113
     * @return string
114
     */
115
    private function renderDirectoryItem(string $name, string $link, ResultAggregateInterface $result, string $pathToRoot): string
116
    {
117
        $deadCount = $result->getDeadCount();
118
        $undeadCount = $result->getUndeadCount();
119
        $totalCount = $deadCount + $undeadCount;
120
121
        $class = 'success';
122
        if ($undeadCount) {
123
            if ($undeadCount < $totalCount) {
124
                $class = 'warning';
125
            } else {
126
                $class = 'danger';
127
            }
128
        }
129
130
        $bar = $this->renderBar($deadCount, $totalCount);
131
132
        $this->directoryItemTemplate->setVar([
133
            'name' => $name,
134
            'path_to_root' => $pathToRoot,
135
            'icon' => $result instanceof AnalyzerFileResult ? 'code' : 'directory',
136
            'link' => $link,
137
            'class' => $class,
138
            'bar' => $bar,
139
            'total' => $totalCount,
140
            'numDead' => $deadCount,
141
            'numUndead' => $undeadCount,
142
        ]);
143
144
        return $this->directoryItemTemplate->render();
145
    }
146
147
    private function renderBar(int $numDead, int $total): string
148
    {
149
        $this->barTemplate->setVar([
150
            'level' => 'success',
151
            'percent' => round($numDead / $total * 100, 2),
152
        ]);
153
154
        return $this->barTemplate->render();
155
    }
156
157
    private function renderBreadcrumb(string $directoryPath): string
158
    {
159
        if (!$directoryPath) {
160
            return '<li class="breadcrumb-item">'.$this->sourceDir.'</li> ';
161
        }
162
163
        $parts = explode('/', $directoryPath);
164
        $numParts = count($parts);
165
        $breadcrumbString = '<li class="breadcrumb-item"><a href="./'.str_repeat('../', $numParts).'index.html">'.$this->sourceDir.'</a></li> ';
166
167
        $folderUp = $numParts - 1;
168
        while ($label = array_shift($parts)) {
169
            if (!$parts) {
170
                $breadcrumbString .= '<li class="breadcrumb-item active">'.$label.'</li> ';
171
            } else {
172
                $link = './'.str_repeat('../', $folderUp).'index.html';
173
                $breadcrumbString .= sprintf('<li class="breadcrumb-item"><a href="%s">%s</a></li> ', $link, $label);
174
            }
175
            --$folderUp;
176
        }
177
178
        return $breadcrumbString;
179
    }
180
}
181