1<?php 2/** 3 * Squiz_Sniffs_CSS_ForbiddenStylesSniff. 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_CSS_ForbiddenStylesSniff. 17 * 18 * Bans the use of some styles, such as deprecated or browser-specific styles. 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_CSS_ForbiddenStylesSniff implements PHP_CodeSniffer_Sniff 29{ 30 31 /** 32 * A list of tokenizers this sniff supports. 33 * 34 * @var array 35 */ 36 public $supportedTokenizers = array('CSS'); 37 38 /** 39 * A list of forbidden styles with their alternatives. 40 * 41 * The value is NULL if no alternative exists. i.e., the 42 * function should just not be used. 43 * 44 * @var array(string => string|null) 45 */ 46 protected $forbiddenStyles = array( 47 '-moz-border-radius' => 'border-radius', 48 '-webkit-border-radius' => 'border-radius', 49 '-moz-border-radius-topleft' => 'border-top-left-radius', 50 '-moz-border-radius-topright' => 'border-top-right-radius', 51 '-moz-border-radius-bottomright' => 'border-bottom-right-radius', 52 '-moz-border-radius-bottomleft' => 'border-bottom-left-radius', 53 '-moz-box-shadow' => 'box-shadow', 54 '-webkit-box-shadow' => 'box-shadow', 55 ); 56 57 /** 58 * A cache of forbidden style names, for faster lookups. 59 * 60 * @var array(string) 61 */ 62 protected $forbiddenStyleNames = array(); 63 64 /** 65 * If true, forbidden styles will be considered regular expressions. 66 * 67 * @var bool 68 */ 69 protected $patternMatch = false; 70 71 /** 72 * If true, an error will be thrown; otherwise a warning. 73 * 74 * @var bool 75 */ 76 public $error = true; 77 78 79 /** 80 * Returns an array of tokens this test wants to listen for. 81 * 82 * @return array 83 */ 84 public function register() 85 { 86 $this->forbiddenStyleNames = array_keys($this->forbiddenStyles); 87 88 if ($this->patternMatch === true) { 89 foreach ($this->forbiddenStyleNames as $i => $name) { 90 $this->forbiddenStyleNames[$i] = '/'.$name.'/i'; 91 } 92 } 93 94 return array(T_STYLE); 95 96 }//end register() 97 98 99 /** 100 * Processes this test, when one of its tokens is encountered. 101 * 102 * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. 103 * @param int $stackPtr The position of the current token in 104 * the stack passed in $tokens. 105 * 106 * @return void 107 */ 108 public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) 109 { 110 $tokens = $phpcsFile->getTokens(); 111 $style = strtolower($tokens[$stackPtr]['content']); 112 $pattern = null; 113 114 if ($this->patternMatch === true) { 115 $count = 0; 116 $pattern = preg_replace( 117 $this->forbiddenStyleNames, 118 $this->forbiddenStyleNames, 119 $style, 120 1, 121 $count 122 ); 123 124 if ($count === 0) { 125 return; 126 } 127 128 // Remove the pattern delimiters and modifier. 129 $pattern = substr($pattern, 1, -2); 130 } else { 131 if (in_array($style, $this->forbiddenStyleNames) === false) { 132 return; 133 } 134 }//end if 135 136 $this->addError($phpcsFile, $stackPtr, $style, $pattern); 137 138 }//end process() 139 140 141 /** 142 * Generates the error or warning for this sniff. 143 * 144 * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. 145 * @param int $stackPtr The position of the forbidden style 146 * in the token array. 147 * @param string $style The name of the forbidden style. 148 * @param string $pattern The pattern used for the match. 149 * 150 * @return void 151 */ 152 protected function addError($phpcsFile, $stackPtr, $style, $pattern=null) 153 { 154 $data = array($style); 155 $error = 'The use of style %s is '; 156 if ($this->error === true) { 157 $type = 'Found'; 158 $error .= 'forbidden'; 159 } else { 160 $type = 'Discouraged'; 161 $error .= 'discouraged'; 162 } 163 164 if ($pattern === null) { 165 $pattern = $style; 166 } 167 168 if ($this->forbiddenStyles[$pattern] !== null) { 169 $data[] = $this->forbiddenStyles[$pattern]; 170 if ($this->error === true) { 171 $fix = $phpcsFile->addFixableError($error.'; use %s instead', $stackPtr, $type.'WithAlternative', $data); 172 } else { 173 $fix = $phpcsFile->addFixableWarning($error.'; use %s instead', $stackPtr, $type.'WithAlternative', $data); 174 } 175 176 if ($fix === true) { 177 $phpcsFile->fixer->replaceToken($stackPtr, $this->forbiddenStyles[$pattern]); 178 } 179 } else { 180 if ($this->error === true) { 181 $phpcsFile->addError($error, $stackPtr, $type, $data); 182 } else { 183 $phpcsFile->addWarning($error, $stackPtr, $type, $data); 184 } 185 } 186 187 }//end addError() 188 189 190}//end class 191