1<?php
2/**
3 * Squiz_Sniffs_PHP_DisallowComparisonAssignmentSniff.
4 *
5 * PHP version 5
6 *
7 * @category  PHP
8 * @package   PHP_CodeSniffer
9 * @author    Greg Sherwood <gsherwood@squiz.net>
10 * @copyright 2006-2014 Squiz Pty Ltd (ABN 77 084 670 600)
11 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
12 * @link      http://pear.php.net/package/PHP_CodeSniffer
13 */
14
15/**
16 * Squiz_Sniffs_PHP_DisallowComparisonAssignmentSniff.
17 *
18 * Ensures that the value of a comparison is not assigned to a variable.
19 *
20 * @category  PHP
21 * @package   PHP_CodeSniffer
22 * @author    Greg Sherwood <gsherwood@squiz.net>
23 * @copyright 2006-2014 Squiz Pty Ltd (ABN 77 084 670 600)
24 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
25 * @version   Release: @package_version@
26 * @link      http://pear.php.net/package/PHP_CodeSniffer
27 */
28class Squiz_Sniffs_PHP_DisallowComparisonAssignmentSniff implements PHP_CodeSniffer_Sniff
29{
30
31
32    /**
33     * Returns an array of tokens this test wants to listen for.
34     *
35     * @return array
36     */
37    public function register()
38    {
39        return array(T_EQUAL);
40
41    }//end register()
42
43
44    /**
45     * Processes this test, when one of its tokens is encountered.
46     *
47     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
48     * @param int                  $stackPtr  The position of the current token
49     *                                        in the stack passed in $tokens.
50     *
51     * @return void
52     */
53    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
54    {
55        $tokens = $phpcsFile->getTokens();
56
57        // Ignore default value assignments in function definitions.
58        $function = $phpcsFile->findPrevious(T_FUNCTION, ($stackPtr - 1), null, false, null, true);
59        if ($function !== false) {
60            $opener = $tokens[$function]['parenthesis_opener'];
61            $closer = $tokens[$function]['parenthesis_closer'];
62            if ($opener < $stackPtr && $closer > $stackPtr) {
63                return;
64            }
65        }
66
67        // Ignore values in array definitions.
68        $array = $phpcsFile->findNext(
69            T_ARRAY,
70            ($stackPtr + 1),
71            null,
72            false,
73            null,
74            true
75        );
76
77        if ($array !== false) {
78            return;
79        }
80
81        // Ignore function calls.
82        $ignore = array(
83                   T_STRING,
84                   T_WHITESPACE,
85                   T_OBJECT_OPERATOR,
86                  );
87
88        $next = $phpcsFile->findNext($ignore, ($stackPtr + 1), null, true);
89        if ($tokens[$next]['code'] === T_OPEN_PARENTHESIS
90            && $tokens[($next - 1)]['code'] === T_STRING
91        ) {
92            // Code will look like: $var = myFunction(
93            // and will be ignored.
94            return;
95        }
96
97        $endStatement = $phpcsFile->findNext(T_SEMICOLON, ($stackPtr + 1));
98        if ($tokens[$stackPtr]['conditions'] !== $tokens[$endStatement]['conditions']) {
99            // This statement doesn't end with a semicolon, which is the case for
100            // the last expression in a for loop.
101            return;
102        }
103
104        for ($i = ($stackPtr + 1); $i < $endStatement; $i++) {
105            if (isset(PHP_CodeSniffer_Tokens::$comparisonTokens[$tokens[$i]['code']]) === true
106                || $tokens[$i]['code'] === T_INLINE_THEN
107            ) {
108                $error = 'The value of a comparison must not be assigned to a variable';
109                $phpcsFile->addError($error, $stackPtr, 'AssignedComparison');
110                break;
111            }
112
113            if (isset(PHP_CodeSniffer_Tokens::$booleanOperators[$tokens[$i]['code']]) === true
114                || $tokens[$i]['code'] === T_BOOLEAN_NOT
115            ) {
116                $error = 'The value of a boolean operation must not be assigned to a variable';
117                $phpcsFile->addError($error, $stackPtr, 'AssignedBool');
118                break;
119            }
120        }
121
122    }//end process()
123
124
125}//end class
126