Chris@0: getFilename(), -4)); Chris@0: if ($fileExtension !== 'info') { Chris@0: return ($phpcsFile->numTokens + 1); Chris@0: } Chris@0: Chris@0: $contents = file_get_contents($phpcsFile->getFilename()); Chris@0: $duplicates = $this->findDuplicateInfoFileEntries($contents); Chris@0: if (empty($duplicates) === false) { Chris@0: foreach ($duplicates as $duplicate) { Chris@0: $error = 'Duplicate entry for "%s" in info file'; Chris@0: $phpcsFile->addError($error, $stackPtr, 'DuplicateEntry', array($duplicate)); Chris@0: } Chris@0: } Chris@0: Chris@0: return ($phpcsFile->numTokens + 1); Chris@0: Chris@0: }//end process() Chris@0: Chris@0: Chris@0: /** Chris@0: * Parses a Drupal info file and checsk if a key apperas more than once. Chris@0: * Chris@0: * @param string $data The contents of the info file to parse Chris@0: * Chris@0: * @return array A list of configuration keys that appear more than once. Chris@0: */ Chris@0: protected function findDuplicateInfoFileEntries($data) Chris@0: { Chris@0: $info = array(); Chris@0: $duplicates = array(); Chris@0: $constants = get_defined_constants(); Chris@0: Chris@0: if (preg_match_all( Chris@0: ' Chris@0: @^\s* # Start at the beginning of a line, ignoring leading whitespace Chris@0: ((?: Chris@0: [^=;\[\]]| # Key names cannot contain equal signs, semi-colons or square brackets, Chris@0: \[[^\[\]]*\] # unless they are balanced and not nested Chris@0: )+?) Chris@0: \s*=\s* # Key/value pairs are separated by equal signs (ignoring white-space) Chris@0: (?: Chris@0: ("(?:[^"]|(?<=\\\\)")*")| # Double-quoted string, which may contain slash-escaped quotes/slashes Chris@0: (\'(?:[^\']|(?<=\\\\)\')*\')| # Single-quoted string, which may contain slash-escaped quotes/slashes Chris@0: ([^\r\n]*?) # Non-quoted string Chris@0: )\s*$ # Stop at the next end of a line, ignoring trailing whitespace Chris@0: @msx', Chris@0: $data, Chris@0: $matches, Chris@0: PREG_SET_ORDER Chris@0: ) !== false Chris@0: ) { Chris@0: foreach ($matches as $match) { Chris@0: // Fetch the key and value string. Chris@0: $i = 0; Chris@0: foreach (array('key', 'value1', 'value2', 'value3') as $var) { Chris@0: if (isset($match[++$i]) === true) { Chris@0: $$var = $match[$i]; Chris@0: } else { Chris@0: $$var = ''; Chris@0: } Chris@0: } Chris@0: Chris@0: $value = stripslashes(substr($value1, 1, -1)).stripslashes(substr($value2, 1, -1)).$value3; Chris@0: Chris@0: // Parse array syntax. Chris@0: $keys = preg_split('/\]?\[/', rtrim($key, ']')); Chris@0: $last = array_pop($keys); Chris@0: $parent = &$info; Chris@0: Chris@0: // Create nested arrays. Chris@0: foreach ($keys as $key) { Chris@0: if ($key === '') { Chris@0: $key = count($parent); Chris@0: } Chris@0: Chris@0: if (isset($parent[$key]) === false || is_array($parent[$key]) === false) { Chris@0: $parent[$key] = array(); Chris@0: } Chris@0: Chris@0: $parent = &$parent[$key]; Chris@0: } Chris@0: Chris@0: // Handle PHP constants. Chris@0: if (isset($constants[$value]) === true) { Chris@0: $value = $constants[$value]; Chris@0: } Chris@0: Chris@0: // Insert actual value. Chris@0: if ($last === '') { Chris@0: $last = count($parent); Chris@0: } Chris@0: Chris@0: if (array_key_exists($last, $parent) === true) { Chris@0: $duplicates[] = $last; Chris@0: } Chris@0: Chris@0: $parent[$last] = $value; Chris@0: }//end foreach Chris@0: }//end if Chris@0: Chris@0: return $duplicates; Chris@0: Chris@0: }//end findDuplicateInfoFileEntries() Chris@0: Chris@0: Chris@0: }//end class