Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
23 / 23
100.00% covered (success)
100.00%
3 / 3
CRAP
100.00% covered (success)
100.00%
1 / 1
RegexWindowsFilename
100.00% covered (success)
100.00%
23 / 23
100.00% covered (success)
100.00%
3 / 3
6
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
2
 getIllegalFilenames
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
2
 getIllegalChars
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2/**
3 * @package: pvc
4 * @author: Doug Wilbourne (dougwilbourne@gmail.com)
5 */
6
7declare(strict_types = 1);
8
9namespace pvc\regex\filename;
10
11use pvc\regex\err\RegexInvalidDelimiterException;
12use pvc\regex\Regex;
13
14/**
15 * Class RegexWindowsFilename
16 *
17 * Documentation for windows file names can be found at
18 * https://docs.microsoft.com/en-us/windows/desktop/FileIO/naming-a-file
19 */
20class RegexWindowsFilename extends Regex
21{
22    public function __construct(bool $allowFileExtension = true)
23    {
24        /**
25         * illegal filenames are coded as a series of case-insensitive negative lookahead assertions
26         * first bracket each filename with begin / end of subject
27         */
28
29        $badFileNames = [];
30        foreach ($this->getIllegalFilenames() as $filename) {
31            $badFileNames[] = '^' . $filename . '$';
32        }
33
34        $pattern = '';
35        $pattern .= '/^(?!(?i)(' . implode('|', $badFileNames) . '))';
36
37        // illegal characters are coded as a negative character class.
38        $pattern .= '[^' . $this->getIllegalChars($allowFileExtension) . ']*';
39
40        // assert end of subject / end of pattern
41        $pattern .= '$/';
42
43        $label = 'windows filename';
44
45        $this->setPattern($pattern);
46        $this->setLabel($label);
47    }
48
49    /**
50     * getIllegalFilenames
51     * @return array<string>
52     */
53    private function getIllegalFilenames(): array
54    {
55        $illegalFilenames = [];
56        $illegalFilenames[] = 'CON';
57        $illegalFilenames[] = 'PRN';
58        $illegalFilenames[] = 'AUX';
59        $illegalFilenames[] = 'NUL';
60        for ($i = 1; $i < 10; $i++) {
61            $illegalFilenames[] = 'COM' . $i;
62            $illegalFilenames[] = 'LPT' . $i;
63        }
64        return $illegalFilenames;
65    }
66
67    /**
68     * getIllegalChars
69     * @param bool $allowFileExtension
70     * @return string
71     * @throws RegexInvalidDelimiterException
72     * @throws RegexInvalidDelimiterException
73     */
74    // the following chars are illegal: < > : " \ / | ? *
75    private function getIllegalChars(bool $allowFileExtension): string
76    {
77        $result = '<>:"\/|?*';
78        if (!$allowFileExtension) {
79            $result .= '.';
80        }
81        return Regex::escapeString($result, '/');
82    }
83}