Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
130 / 130
100.00% covered (success)
100.00%
8 / 8
CRAP
100.00% covered (success)
100.00%
1 / 1
LanguageCollector
100.00% covered (success)
100.00%
130 / 130
100.00% covered (success)
100.00%
8 / 8
34
100.00% covered (success)
100.00%
1 / 1
 setLanguage
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getActivities
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
2
 getContents
100.00% covered (success)
100.00%
21 / 21
100.00% covered (success)
100.00%
1 / 1
2
 renderRenderedMessages
100.00% covered (success)
100.00%
17 / 17
100.00% covered (success)
100.00%
1 / 1
4
 renderDirectories
100.00% covered (success)
100.00%
14 / 14
100.00% covered (success)
100.00%
1 / 1
4
 renderLines
100.00% covered (success)
100.00%
19 / 19
100.00% covered (success)
100.00%
1 / 1
4
 getLines
100.00% covered (success)
100.00%
38 / 38
100.00% covered (success)
100.00%
1 / 1
13
 getFallbackName
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
4
1<?php declare(strict_types=1);
2/*
3 * This file is part of Aplus Framework Language Library.
4 *
5 * (c) Natan Felles <natanfelles@gmail.com>
6 *
7 * For the full copyright and license information, please view the LICENSE
8 * file that was distributed with this source code.
9 */
10namespace Framework\Language\Debug;
11
12use Framework\Debug\Collector;
13use Framework\Language\Language;
14
15/**
16 * Class LanguageCollector.
17 *
18 * @package language
19 */
20class LanguageCollector extends Collector
21{
22    protected Language $language;
23
24    public function setLanguage(Language $language) : static
25    {
26        $this->language = $language;
27        return $this;
28    }
29
30    public function getActivities() : array
31    {
32        $activities = [];
33        foreach ($this->getData() as $index => $data) {
34            $activities[] = [
35                'collector' => $this->getName(),
36                'class' => static::class,
37                'description' => 'Render message ' . ($index + 1),
38                'start' => $data['start'],
39                'end' => $data['end'],
40            ];
41        }
42        return $activities;
43    }
44
45    public function getContents() : string
46    {
47        if ( ! isset($this->language)) {
48            return '<p>A Language instance has not been set on this collector.</p>';
49        }
50        \ob_start(); ?>
51        <p><strong>Default Locale:</strong> <?=
52            \htmlentities($this->language->getDefaultLocale())
53        ?></p>
54        <p><strong>Current Locale:</strong> <?=
55        \htmlentities($this->language->getCurrentLocale())
56        ?></p>
57        <p><strong>Supported Locales:</strong> <?=
58        \htmlentities(\implode(', ', $this->language->getSupportedLocales()))
59        ?></p>
60        <p><strong>Fallback Level:</strong> <?php
61        $level = $this->language->getFallbackLevel();
62        echo "{$level->value} ({$level->name})"; ?></p>
63        <h1>Rendered Messages</h1>
64        <?= $this->renderRenderedMessages() ?>
65        <h1>Directories</h1>
66        <?= $this->renderDirectories() ?>
67        <h1>Available Messages</h1>
68        <?php
69        echo $this->renderLines();
70        return \ob_get_clean(); // @phpstan-ignore-line
71    }
72
73    protected function renderRenderedMessages() : string
74    {
75        if ( ! $this->hasData()) {
76            return '<p>No message has been rendered.</p>';
77        }
78        $count = \count($this->getData());
79        \ob_start(); ?>
80        <p><?= $count ?> message<?= $count === 1 ? '' : 's' ?> has been rendered.</p>
81        <table>
82            <thead>
83            <tr>
84                <th>#</th>
85                <th>File</th>
86                <th>Line</th>
87                <th>Message</th>
88                <th>Locale</th>
89                <th title="Seconds">Time</th>
90            </tr>
91            </thead>
92            <tbody>
93            <?php foreach ($this->getData() as $index => $data): ?>
94                <tr>
95                    <td><?= $index + 1 ?></td>
96                    <td><?= \htmlentities($data['file']) ?></td>
97                    <td><?= \htmlentities($data['line']) ?></td>
98                    <td>
99                        <pre><code class="language-html"><?= \htmlentities($data['message']) ?></code></pre>
100                    </td>
101                    <td><?= \htmlentities($data['locale']) ?></td>
102                    <td><?= \round($data['end'] - $data['start'], 6) ?></td>
103                </tr>
104            <?php endforeach ?>
105            </tbody>
106        </table>
107        <?php
108        return \ob_get_clean(); // @phpstan-ignore-line
109    }
110
111    protected function renderDirectories() : string
112    {
113        $directories = $this->language->getDirectories();
114        if (empty($directories)) {
115            return '<p>No directory set for this Language instance.</p>';
116        }
117        $count = \count($directories);
118        \ob_start(); ?>
119        <p>There <?= $count === 1 ? 'is 1 directory' : "are {$count} directories" ?> set.</p>
120        <table>
121            <thead>
122            <tr>
123                <th>#</th>
124                <th>Directory</th>
125            </tr>
126            </thead>
127            <tbody>
128            <?php foreach ($this->language->getDirectories() as $index => $directory): ?>
129                <tr>
130                    <td><?= $index + 1 ?></td>
131                    <td><?= \htmlentities($directory) ?></td>
132                </tr>
133            <?php endforeach ?>
134            </tbody>
135        </table>
136        <?php
137        return \ob_get_clean(); // @phpstan-ignore-line
138    }
139
140    protected function renderLines() : string
141    {
142        $lines = $this->getLines();
143        if (empty($lines)) {
144            return '<p>No file lines available for this Language instance.</p>';
145        }
146        $count = \count($lines);
147        \ob_start(); ?>
148        <p>There <?= $count === 1 ? 'is 1 message line' : "are {$count} message lines"
149        ?> available to the current locale (<?= $this->language->getCurrentLocale() ?>).
150        </p>
151        <table>
152            <thead>
153            <tr>
154                <th>#</th>
155                <th>File</th>
156                <th>Line</th>
157                <th>Message Pattern</th>
158                <th>Locale</th>
159                <th>Fallback</th>
160            </tr>
161            </thead>
162            <tbody>
163            <?php foreach ($lines as $index => $line): ?>
164                <tr>
165                    <td><?= $index + 1 ?></td>
166                    <td><?= \htmlentities($line['file']) ?></td>
167                    <td><?= \htmlentities($line['line']) ?></td>
168                    <td>
169                        <pre><code class="language-icu-message-format"><?= \htmlentities($line['message']) ?></code></pre>
170                    </td>
171                    <td><?= \htmlentities($line['locale']) ?></td>
172                    <td><?= \htmlentities($line['fallback']) ?></td>
173                </tr>
174            <?php endforeach ?>
175            </tbody>
176        </table>
177        <?php
178        return \ob_get_clean(); // @phpstan-ignore-line
179    }
180
181    /**
182     * @return array<int,array<string,string>>
183     */
184    protected function getLines() : array
185    {
186        $allLines = $this->language->getLines();
187        $this->language->resetLines();
188        $files = [];
189        foreach ($this->language->getDirectories() as $directory) {
190            foreach ((array) \glob($directory . '*/*.php') as $file) {
191                $file = (string) $file;
192                $pos = \strrpos($file, \DIRECTORY_SEPARATOR);
193                $file = \substr($file, $pos + 1, -4);
194                $files[$file] = true;
195            }
196        }
197        $files = \array_keys($files);
198        foreach ($files as $file) {
199            $this->language->render($file, '.·*·.');
200        }
201        $result = [];
202        foreach ($this->language->getLines() as $locale => $lines) {
203            \ksort($lines);
204            foreach ($lines as $file => $messages) {
205                \ksort($messages);
206                foreach ($messages as $line => $message) {
207                    foreach ($result as $data) {
208                        if ($data['file'] === $file && $data['line'] === $line) {
209                            continue 2;
210                        }
211                    }
212                    $result[] = [
213                        'file' => $file,
214                        'line' => $line,
215                        'message' => $message,
216                        'locale' => $locale,
217                        'fallback' => $this->getFallbackName($locale),
218                    ];
219                }
220            }
221        }
222        \usort($result, static function ($str1, $str2) {
223            $cmp = \strcmp($str1['file'], $str2['file']);
224            if ($cmp === 0) {
225                $cmp = \strcmp($str1['line'], $str2['line']);
226            }
227            return $cmp;
228        });
229        foreach ($allLines as $locale => $lines) {
230            foreach ($lines as $file => $messages) {
231                $this->language->addLines($locale, $file, $messages);
232            }
233        }
234        return $result;
235    }
236
237    protected function getFallbackName(string $locale) : string
238    {
239        $currentLocale = $this->language->getCurrentLocale();
240        if ($locale === $currentLocale) {
241            return 'none';
242        }
243        $parentLocale = \explode('-', $currentLocale)[0];
244        if ($locale === $parentLocale) {
245            return 'parent';
246        }
247        if ($locale === $this->language->getDefaultLocale()) {
248            return 'default';
249        }
250        return '';
251    }
252}