• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

JBZoo / Codestyle / 8299306877

27 Jan 2024 09:57PM UTC coverage: 87.805% (-0.6%) from 88.424%
8299306877

push

github

web-flow
PHP 8.3 + Update deps (#48)

5 of 15 new or added lines in 1 file covered. (33.33%)

44 existing lines in 5 files now uncovered.

540 of 615 relevant lines covered (87.8%)

10.35 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

91.4
/src/PHPUnit/TraitCopyright.php
1
<?php
2

3
/**
4
 * JBZoo Toolbox - Codestyle.
5
 *
6
 * This file is part of the JBZoo Toolbox project.
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 *
10
 * @license    MIT
11
 * @copyright  Copyright (C) JBZoo.com, All rights reserved.
12
 * @see        https://github.com/JBZoo/Codestyle
13
 */
14

15
declare(strict_types=1);
16

17
namespace JBZoo\Codestyle\PHPUnit;
18

19
use Symfony\Component\Finder\Finder;
20

21
use function JBZoo\PHPUnit\fail;
22
use function JBZoo\PHPUnit\skip;
23
use function JBZoo\PHPUnit\success;
24

25
/**
26
 * @phan-file-suppress PhanUndeclaredProperty
27
 */
28
trait TraitCopyright
29
{
30
    /** @var string[] */
31
    protected array $excludedPathsForCopyrights = [
32
        '.git',
33
        '.idea',
34
        'bower_components',
35
        'build',
36
        'fonts',
37
        'fixtures',
38
        'logs',
39
        'node_modules',
40
        'resources',
41
        'vendor',
42
        'temp',
43
        'tmp',
44
    ];
45

46
    /** @var string[] */
47
    protected array $packageDesc = [
48
        'This file is part of the _VENDOR_ project.',
49
        'For the full copyright and license information, please view the LICENSE',
50
        'file that was distributed with this source code.',
51
    ];
52

53
    // ### Patterns of copyrights. #####################################################################################
54

55
    /** @var string[] */
56
    protected array $validHeaderPHP = [
57
        '/**',
58
        ' * _VENDOR_ - _PACKAGE_.',
59
        ' *',
60
        ' * _DESCRIPTION_PHP_',
61
        ' *',
62
        ' * @license    _LICENSE_',
63
        ' * @copyright  _COPYRIGHTS_',
64
        ' * @see        _LINK_',
65
    ];
66

67
    /** @var string[] */
68
    protected array $validHeaderJS = [
69
        '/**',
70
        ' * _VENDOR_ - _PACKAGE_.',
71
        ' *',
72
        ' * _DESCRIPTION_JS_',
73
        ' *',
74
        ' * @license    _LICENSE_',
75
        ' * @copyright  _COPYRIGHTS_',
76
        ' * @see        _LINK_',
77
    ];
78

79
    /** @var string[] */
80
    protected array $validHeaderCSS = [
81
        '/**',
82
        ' * _VENDOR_ - _PACKAGE_.',
83
        ' *',
84
        ' * _DESCRIPTION_CSS_',
85
        ' *',
86
        ' * @license    _LICENSE_',
87
        ' * @copyright  _COPYRIGHTS_',
88
        ' * @see        _LINK_',
89
        ' */',
90
        '',
91
    ];
92

93
    /** @var string[] */
94
    protected array $validHeaderLESS = [
95
        '//',
96
        '// _VENDOR_ - _PACKAGE_.',
97
        '//',
98
        '// _DESCRIPTION_LESS_',
99
        '//',
100
        '// @license    _LICENSE_',
101
        '// @copyright  _COPYRIGHTS_',
102
        '// @see        _LINK_',
103
        '//',
104
    ];
105

106
    /** @var string[] */
107
    protected array $validHeaderXML = [
108
        '<?xml version="1.0" encoding="UTF-8" ?>',
109
        '<!--',
110
        '    _VENDOR_ - _PACKAGE_.',
111
        '',
112
        '    _DESCRIPTION_XML_',
113
        '',
114
        '    @license    _LICENSE_',
115
        '    @copyright  _COPYRIGHTS_',
116
        '    @see        _LINK_',
117
        '-->',
118
    ];
119

120
    /** @var string[] */
121
    protected array $validHeaderINI = [
122
        ';',
123
        '; _VENDOR_ - _PACKAGE_.',
124
        ';',
125
        '; _DESCRIPTION_INI_',
126
        ';',
127
        '; @license    _LICENSE_',
128
        '; @copyright  _COPYRIGHTS_',
129
        '; @see        _LINK_',
130
        ';',
131
        '; Note: All ini files need to be saved as UTF-8 (no BOM)',
132
        ';',
133
    ];
134

135
    /** @var string[] */
136
    protected array $validHeaderSH = [
137
        '#!/usr/bin/env sh',
138
        '',
139
        '#',
140
        '# _VENDOR_ - _PACKAGE_.',
141
        '#',
142
        '# _DESCRIPTION_SH_',
143
        '#',
144
        '# @license    _LICENSE_',
145
        '# @copyright  _COPYRIGHTS_',
146
        '# @see        _LINK_',
147
        '#',
148
        '',
149
    ];
150

151
    /** @var string[] */
152
    protected array $validHeaderSQL = [
153
        '--',
154
        '-- _VENDOR_ - _PACKAGE_.',
155
        '--',
156
        '-- _DESCRIPTION_SQL_',
157
        '--',
158
        '-- @license    _LICENSE_',
159
        '-- @copyright  _COPYRIGHTS_',
160
        '-- @see        _LINK_',
161
        '--',
162
        '',
163
    ];
164

165
    /** @var string[] */
166
    protected array $validHeaderHash = [
167
        '#',
168
        '# _VENDOR_ - _PACKAGE_.',
169
        '#',
170
        '# _DESCRIPTION_HASH_',
171
        '#',
172
        '# @license    _LICENSE_',
173
        '# @copyright  _COPYRIGHTS_',
174
        '# @see        _LINK_',
175
        '#',
176
        '',
177
    ];
178

179
    public function testHeadersPhp(): void
180
    {
181
        $phpTemplate = $this->prepareTemplate($this->validHeaderPHP);
6✔
182

183
        $phpTemplate = "<?php\n\n{$phpTemplate}" . \implode("\n", [
6✔
184
            '',
3✔
185
            ' */',
3✔
186
            '',
3✔
187
            'declare(strict_types=1);',
3✔
188
            '',
3✔
189
        ]);
3✔
190

191
        $finder = $this->createFinder(['.php', '.phtml']);
6✔
192
        static::checkHeaderInFiles($finder, $phpTemplate);
6✔
193
    }
194

195
    public function testHeadersJs(): void
196
    {
197
        $finder = $this->createFinder(['.js', '.jsx'], ['*.min.js', '*.min.jsx']);
6✔
198
        static::checkHeaderInFiles($finder, $this->prepareTemplate($this->validHeaderJS));
6✔
199
    }
200

201
    public function testHeadersCss(): void
202
    {
203
        $finder = $this->createFinder(['.css'], ['*.min.css']);
6✔
204
        static::checkHeaderInFiles($finder, $this->prepareTemplate($this->validHeaderCSS));
6✔
205
    }
206

207
    public function testHeadersLess(): void
208
    {
209
        $finder = $this->createFinder(['.less']);
6✔
210
        static::checkHeaderInFiles($finder, $this->prepareTemplate($this->validHeaderLESS));
6✔
211
    }
212

213
    public function testHeadersXml(): void
214
    {
215
        $finder = $this->createFinder(['.xml']);
6✔
216
        static::checkHeaderInFiles($finder, $this->prepareTemplate($this->validHeaderXML));
6✔
217
    }
218

219
    public function testHeadersIni(): void
220
    {
221
        $finder = $this->createFinder(['.ini']);
6✔
222
        static::checkHeaderInFiles($finder, $this->prepareTemplate($this->validHeaderINI));
6✔
223
    }
224

225
    public function testHeadersSh(): void
226
    {
227
        $finder = $this->createFinder(['.sh', '.bash', '.fish']);
6✔
228
        static::checkHeaderInFiles($finder, $this->prepareTemplate($this->validHeaderSH));
6✔
229
    }
230

231
    public function testHeadersSql(): void
232
    {
233
        $finder = $this->createFinder(['.sql']);
6✔
234
        static::checkHeaderInFiles($finder, $this->prepareTemplate($this->validHeaderSQL));
6✔
235
    }
236

237
    public function testHeadersOtherConfigs(): void
238
    {
239
        $finder = $this->createFinder([
6✔
240
            'Dockerfile',
3✔
241
            'Makefile',
3✔
242
            '.Makefile',
3✔
243
            '.yml',
3✔
244
            '.yaml',
3✔
245
            '.neon',
3✔
246
            '.htaccess',
3✔
247
            '.editorconfig',
3✔
248
            '.gitattributes',
3✔
249
            '.gitignore',
3✔
250
        ]);
3✔
251
        static::checkHeaderInFiles($finder, $this->prepareTemplate($this->validHeaderHash));
6✔
252
    }
253

254
    // ### Internal tools for test case ################################################################################
255

256
    /**
257
     * @param array<string> $inclusions
258
     * @param array<string> $exclusions
259
     */
260
    protected function createFinder(array $inclusions = [], array $exclusions = []): Finder
261
    {
262
        $finder = (new Finder())
54✔
263
            ->files()
54✔
264
            ->in(PROJECT_ROOT)
54✔
265
            ->exclude($this->excludedPathsForCopyrights)
54✔
266
            ->ignoreDotFiles(false)
54✔
267
            ->ignoreVCS(true)
54✔
268
            ->followLinks();
54✔
269

270
        foreach ($inclusions as $inclusion) {
54✔
271
            $finder->name($inclusion);
54✔
272
            if (\str_contains($inclusion, '.')) {
54✔
273
                $finder
27✔
274
                    ->name('/\\' . $inclusion . '$/')
54✔
275
                    ->name('/dist\\' . $inclusion . '$/')
54✔
276
                    ->name('/\\' . $inclusion . '.dist$/');
54✔
277
            }
278
        }
279

280
        foreach ($exclusions as $exclusion) {
54✔
281
            $finder->notName($exclusion);
12✔
282
        }
283

284
        return $finder;
54✔
285
    }
286

287
    /**
288
     * Render copyrights.
289
     */
290
    protected function prepareTemplate(array $templateRows): string
291
    {
292
        $template = \implode("\n", $templateRows);
54✔
293

294
        // Important! Order of replacements is important!
295
        $replace = [
54✔
296
            '_DESCRIPTION_PHP_'  => \implode("\n * ", $this->packageDesc),
54✔
297
            '_DESCRIPTION_JS_'   => \implode("\n * ", $this->packageDesc),
54✔
298
            '_DESCRIPTION_CSS_'  => \implode("\n * ", $this->packageDesc),
54✔
299
            '_DESCRIPTION_LESS_' => \implode("\n// ", $this->packageDesc),
54✔
300
            '_DESCRIPTION_XML_'  => \implode("\n    ", $this->packageDesc),
54✔
301
            '_DESCRIPTION_INI_'  => \implode("\n; ", $this->packageDesc),
54✔
302
            '_DESCRIPTION_SH_'   => \implode("\n# ", $this->packageDesc),
54✔
303
            '_DESCRIPTION_SQL_'  => \implode("\n-- ", $this->packageDesc),
54✔
304
            '_DESCRIPTION_HASH_' => \implode("\n# ", $this->packageDesc),
54✔
305
            '_LINK_'             => $this->copyrightSee,
54✔
306
            '_NAMESPACE_'        => '_VENDOR_\_PACKAGE_',
27✔
307
            '_COPYRIGHTS_'       => $this->copyrightRights,
54✔
308
            '_PACKAGE_'          => $this->packageName,
54✔
309
            '_LICENSE_'          => $this->copyrightLicense,
54✔
310
            '_VENDOR_NS_'        => $this->vendorName,
54✔
311
            '_VENDOR_'           => $this->copyrightVendorName,
54✔
312
        ];
27✔
313

314
        foreach ($replace as $const => $value) {
54✔
315
            $template = \str_replace($const, $value, $template);
54✔
316
        }
317

318
        return $template;
54✔
319
    }
320

321
    /**
322
     * Checks for the presence of a valid header in files found by a Finder object.
323
     * If any invalid files are found, it generates an error indicating the incorrect files.
324
     * On successful validation of all files, it outputs a success message.
325
     * If no files are found, it outputs a skipped check message.
326
     *
327
     * @param Finder $finder      finder object used to search for files
328
     * @param string $validHeader string containing the correct header for validation
329
     */
330
    protected static function checkHeaderInFiles(Finder $finder, string $validHeader): void
331
    {
332
        $invalidFiles = [];
54✔
333

334
        $testFunction = static function (string $content, string $pathname) use ($validHeader, &$invalidFiles): void {
54✔
335
            if (!\str_starts_with($content, $validHeader)) {
54✔
336
                $invalidFiles[] = $pathname;
×
337
            }
338
        };
27✔
339

340
        $testName   = \debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS, 2)[1]['function'];
54✔
341
        $filesCount = AbstractPackageTest::checkFiles($testName, $finder, $testFunction);
54✔
342

343
        if (\count($invalidFiles) > 0) {
54✔
344
            $errorMessage = \implode("\n", [
×
UNCOV
345
                'The file has no valid copyright in header.',
UNCOV
346
                'Expected file header:',
347
                \str_repeat('-', 60),
×
UNCOV
348
                $validHeader,
349
                \str_repeat('-', 60),
×
350
                'Invalid Files (' . \count($invalidFiles) . '):',
×
351
                'See: ' . \implode("\nSee: ", $invalidFiles),
×
UNCOV
352
                '',
UNCOV
353
            ]);
354
            fail($errorMessage);
×
355
        }
356

357
        if ($filesCount > 0) {
54✔
358
            success();
54✔
359
        } else {
360
            skip('Files not found');
×
361
        }
362
    }
363
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc