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

PHPCompatibility / PHPCompatibility / 19804455605

30 Nov 2025 08:31PM UTC coverage: 98.306% (-0.04%) from 98.346%
19804455605

push

github

web-flow
Merge pull request #2014 from PHPCompatibility/php-8.5/new-removedterminatingcasewithsemicolon-sniff

PHP 8.5 | ✨ New `PHPCompatibility.ControlStructures.RemovedTerminatingCaseWithSemicolon` sniff (RFC)

30 of 34 new or added lines in 1 file covered. (88.24%)

21 existing lines in 15 files now uncovered.

8355 of 8499 relevant lines covered (98.31%)

20.51 hits per line

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

93.1
/PHPCompatibility/Sniffs/ParameterValues/RemovedPCREModifiersSniff.php
1
<?php
2
/**
3
 * PHPCompatibility, an external standard for PHP_CodeSniffer.
4
 *
5
 * @package   PHPCompatibility
6
 * @copyright 2012-2020 PHPCompatibility Contributors
7
 * @license   https://opensource.org/licenses/LGPL-3.0 LGPL3
8
 * @link      https://github.com/PHPCompatibility/PHPCompatibility
9
 */
10

11
namespace PHPCompatibility\Sniffs\ParameterValues;
12

13
use PHPCompatibility\AbstractFunctionCallParameterSniff;
14
use PHPCompatibility\Helpers\PCRERegexTrait;
15
use PHPCompatibility\Helpers\ScannedCode;
16
use PHP_CodeSniffer\Files\File;
17
use PHPCSUtils\Utils\MessageHelper;
18
use PHPCSUtils\Utils\PassedParameters;
19

20
/**
21
 * Check for the use of deprecated and removed regex modifiers for PCRE regex functions.
22
 *
23
 * Initially just checks for the `e` modifier, which was deprecated since PHP 5.5
24
 * and removed as of PHP 7.0.
25
 *
26
 * {@internal If and when this sniff would need to start checking for other modifiers, a minor
27
 * refactor will be needed as all references to the `e` modifier are currently hard-coded
28
 * and the target functions are limited to the ones which supported the `e` modifier.}
29
 *
30
 * PHP version 5.5
31
 * PHP version 7.0
32
 *
33
 * @link https://wiki.php.net/rfc/remove_preg_replace_eval_modifier
34
 * @link https://wiki.php.net/rfc/remove_deprecated_functionality_in_php7
35
 * @link https://www.php.net/manual/en/reference.pcre.pattern.modifiers.php
36
 *
37
 * @since 5.6
38
 * @since 7.0.8  This sniff now throws a warning (deprecated) or an error (removed) depending
39
 *               on the `testVersion` set. Previously it would always throw an error.
40
 * @since 8.2.0  Now extends the `AbstractFunctionCallParameterSniff` instead of the base `Sniff` class.
41
 * @since 9.0.0  Renamed from `PregReplaceEModifierSniff` to `RemovedPCREModifiersSniff`.
42
 * @since 10.0.0 - Now uses the new `PCRERegexTrait`.
43
 *               - This class is now `final`.
44
 */
45
final class RemovedPCREModifiersSniff extends AbstractFunctionCallParameterSniff
46
{
47
    use PCRERegexTrait;
48

49
    /**
50
     * Functions to check for.
51
     *
52
     * @since 7.0.1
53
     * @since 8.2.0  Renamed from `$functions` to `$targetFunctions`.
54
     * @since 10.0.0 Value changed from an irrelevant value to an array.
55
     *
56
     * @var array<string, array<string, int|string>> Key is the function name, value an array containing
57
     *                                               the 1-based parameter position and the official name of the parameter.
58
     */
59
    protected $targetFunctions = [
60
        'preg_replace' => [
61
            'position' => 1,
62
            'name'     => 'pattern',
63
        ],
64
        'preg_filter' => [
65
            'position' => 1,
66
            'name'     => 'pattern',
67
        ],
68
    ];
69

70
    /**
71
     * Do a version check to determine if this sniff needs to run at all.
72
     *
73
     * @since 8.2.0
74
     *
75
     * @return bool
76
     */
77
    protected function bowOutEarly()
8✔
78
    {
79
        return (ScannedCode::shouldRunOnOrAbove('5.5') === false);
8✔
80
    }
81

82
    /**
83
     * Process the parameters of a matched function.
84
     *
85
     * @since 5.6
86
     * @since 8.2.0 Renamed from `process()` to `processParameters()` and removed
87
     *              logic superfluous now the sniff extends the abstract.
88
     * @since 10.0.0 Most logic has been moved to the new `PCRERegexTrait`.
89
     *
90
     * @param \PHP_CodeSniffer\Files\File $phpcsFile    The file being scanned.
91
     * @param int                         $stackPtr     The position of the current token in the stack.
92
     * @param string                      $functionName The token content (function name) which was matched.
93
     * @param array                       $parameters   Array with information about the parameters.
94
     *
95
     * @return void
96
     */
97
    public function processParameters(File $phpcsFile, $stackPtr, $functionName, $parameters)
4✔
98
    {
99
        $functionLC  = \strtolower($functionName);
4✔
100
        $paramInfo   = $this->targetFunctions[$functionLC];
4✔
101
        $targetParam = PassedParameters::getParameterFromStack($parameters, $paramInfo['position'], $paramInfo['name']);
4✔
102
        if ($targetParam === false) {
4✔
UNCOV
103
            return;
×
104
        }
105

106
        $patterns = $this->getRegexPatternsFromParameter($phpcsFile, $functionName, $targetParam);
4✔
107
        if (empty($patterns) === true) {
4✔
UNCOV
108
            return;
×
109
        }
110

111
        foreach ($patterns as $pattern) {
4✔
112
            $modifiers = $this->getRegexModifiers($phpcsFile, $pattern);
4✔
113
            if ($modifiers === '') {
4✔
114
                continue;
4✔
115
            }
116

117
            $this->examineModifiers($phpcsFile, $pattern['end'], $functionName, $modifiers);
4✔
118
        }
119
    }
2✔
120

121
    /**
122
     * Examine the regex modifier string.
123
     *
124
     * @since 8.2.0 Split off from the `processRegexPattern()` method.
125
     *
126
     * @param \PHP_CodeSniffer\Files\File $phpcsFile    The file being scanned.
127
     * @param int                         $stackPtr     The position of the current token in the
128
     *                                                  stack passed in $tokens.
129
     * @param string                      $functionName The function which contained the pattern.
130
     * @param string                      $modifiers    The regex modifiers found.
131
     *
132
     * @return void
133
     */
134
    protected function examineModifiers(File $phpcsFile, $stackPtr, $functionName, $modifiers)
4✔
135
    {
136
        if (\strpos($modifiers, 'e') !== false) {
4✔
137
            $error     = '%s() - /e modifier is deprecated since PHP 5.5';
4✔
138
            $isError   = false;
4✔
139
            $errorCode = 'Deprecated';
4✔
140
            $data      = [$functionName];
4✔
141

142
            if (ScannedCode::shouldRunOnOrAbove('7.0') === true) {
4✔
143
                $error    .= ' and removed since PHP 7.0';
4✔
144
                $isError   = true;
4✔
145
                $errorCode = 'Removed';
4✔
146
            }
147

148
            MessageHelper::addMessage($phpcsFile, $error, $stackPtr, $isError, $errorCode, $data);
4✔
149
        }
150
    }
2✔
151
}
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

© 2026 Coveralls, Inc