Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
55.00% covered (warning)
55.00%
22 / 40
57.14% covered (warning)
57.14%
4 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
Pattern
55.00% covered (warning)
55.00%
22 / 40
57.14% covered (warning)
57.14%
4 / 7
35.50
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 isMatch
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
5
 generate
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 buildLike
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
2
 toLikeValue
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
2
 extract
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
6
 init
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
3
1<?php
2
3namespace MediaWiki\User\TempUser;
4
5use UnexpectedValueException;
6use Wikimedia\Rdbms\LikeValue;
7use Wikimedia\Rdbms\Platform\ISQLPlatform;
8
9/**
10 * Helper for TempUserConfig representing string patterns with "$1" indicating
11 * variable substitution.
12 *
13 * @internal
14 */
15class Pattern {
16    /** @var string */
17    private $debugName;
18    /** @var string */
19    private $pattern;
20    /** @var string */
21    private $prefix;
22    /** @var string */
23    private $suffix;
24
25    /**
26     * @param string $debugName The name of the pattern, for use in error messages
27     * @param string $pattern The pattern itself
28     */
29    public function __construct( string $debugName, string $pattern ) {
30        $this->debugName = $debugName;
31        $this->pattern = $pattern;
32    }
33
34    /**
35     * Does the pattern match the given name?
36     * @param string $name
37     * @return bool
38     */
39    public function isMatch( string $name ) {
40        $this->init();
41        $match = true;
42        if ( $this->prefix !== '' ) {
43            $match = str_starts_with( $name, $this->prefix );
44        }
45        if ( $match && $this->suffix !== '' ) {
46            $match = str_ends_with( $name, $this->suffix )
47                && strlen( $name ) >= strlen( $this->prefix ) + strlen( $this->suffix );
48        }
49        return $match;
50    }
51
52    /**
53     * Substitute the serial number into the pattern.
54     *
55     * @param string $mappedSerial
56     * @param ?string $year
57     * @return string
58     */
59    public function generate( $mappedSerial, ?string $year = null ) {
60        $this->init();
61        return $this->prefix .
62            ( $year ? $year . '-' : '' ) .
63            $mappedSerial .
64            $this->suffix;
65    }
66
67    /**
68     * Convert the pattern to an SQL like clause
69     *
70     * @deprecated since 1.42. Use toLikeValue() instead
71     * @param ISQLPlatform $db
72     * @return string
73     */
74    public function buildLike( ISQLPlatform $db ) {
75        wfDeprecated( __METHOD__, '1.42' );
76        $this->init();
77        return $db->buildLike(
78            $this->prefix,
79            $db->anyString(),
80            $this->suffix
81        );
82    }
83
84    /**
85     * Convert the pattern to an SQL builder "LIKE" value that matches it
86     *
87     * @param ISQLPlatform $db
88     * @return LikeValue
89     */
90    public function toLikeValue( ISQLPlatform $db ): LikeValue {
91        $this->init();
92        return new LikeValue(
93            $this->prefix,
94            $db->anyString(),
95            $this->suffix
96        );
97    }
98
99    /**
100     * Extract the variable part of the string (matching $1 or YYYY-$1),
101     * or null if there is no match
102     *
103     * @param string $name
104     * @return ?string
105     */
106    public function extract( string $name ) {
107        if ( $this->isMatch( $name ) ) {
108            return substr( $name,
109                strlen( $this->prefix ),
110                strlen( $name ) - strlen( $this->prefix ) - strlen( $this->suffix ) );
111        }
112        return null;
113    }
114
115    /**
116     * Initialise the prefix and suffix
117     */
118    private function init() {
119        if ( $this->prefix === null ) {
120            $varPos = strpos( $this->pattern, '$1' );
121            if ( $varPos === false ) {
122                throw new UnexpectedValueException( __CLASS__ .
123                    "pattern {$this->debugName} must be of the form \"prefix \$1 suffix\"" );
124            }
125            $this->prefix = substr( $this->pattern, 0, $varPos );
126            $this->suffix = substr( $this->pattern, $varPos + strlen( '$1' ) );
127        }
128    }
129}