1<?php 2/** 3 * Generic_Sniffs_VersionControl_SubversionPropertiesSniff. 4 * 5 * PHP version 5 6 * 7 * @category PHP 8 * @package PHP_CodeSniffer 9 * @author Jack Bates <ms419@freezone.co.uk> 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 * Generic_Sniffs_VersionControl_SubversionPropertiesSniff. 17 * 18 * Tests that the correct Subversion properties are set. 19 * 20 * @category PHP 21 * @package PHP_CodeSniffer 22 * @author Jack Bates <ms419@freezone.co.uk> 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 Generic_Sniffs_VersionControl_SubversionPropertiesSniff implements PHP_CodeSniffer_Sniff 29{ 30 31 /** 32 * The Subversion properties that should be set. 33 * 34 * Key of array is the SVN property and the value is the 35 * exact value the property should have or NULL if the 36 * property should just be set but the value is not fixed. 37 * 38 * @var array 39 */ 40 protected $properties = array( 41 'svn:keywords' => 'Author Id Revision', 42 'svn:eol-style' => 'native', 43 ); 44 45 46 /** 47 * Returns an array of tokens this test wants to listen for. 48 * 49 * @return array 50 */ 51 public function register() 52 { 53 return array(T_OPEN_TAG); 54 55 }//end register() 56 57 58 /** 59 * Processes this test, when one of its tokens is encountered. 60 * 61 * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. 62 * @param int $stackPtr The position of the current token 63 * in the stack passed in $tokens. 64 * 65 * @return void 66 */ 67 public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) 68 { 69 $tokens = $phpcsFile->getTokens(); 70 71 // Make sure this is the first PHP open tag so we don't process the 72 // same file twice. 73 $prevOpenTag = $phpcsFile->findPrevious(T_OPEN_TAG, ($stackPtr - 1)); 74 if ($prevOpenTag !== false) { 75 return; 76 } 77 78 $path = $phpcsFile->getFileName(); 79 $properties = $this->getProperties($path); 80 if ($properties === null) { 81 // Not under version control. 82 return; 83 } 84 85 $allProperties = ($properties + $this->properties); 86 foreach ($allProperties as $key => $value) { 87 if (isset($properties[$key]) === true 88 && isset($this->properties[$key]) === false 89 ) { 90 $error = 'Unexpected Subversion property "%s" = "%s"'; 91 $data = array( 92 $key, 93 $properties[$key], 94 ); 95 $phpcsFile->addError($error, $stackPtr, 'Unexpected', $data); 96 continue; 97 } 98 99 if (isset($properties[$key]) === false 100 && isset($this->properties[$key]) === true 101 ) { 102 $error = 'Missing Subversion property "%s" = "%s"'; 103 $data = array( 104 $key, 105 $this->properties[$key], 106 ); 107 $phpcsFile->addError($error, $stackPtr, 'Missing', $data); 108 continue; 109 } 110 111 if ($properties[$key] !== null 112 && $properties[$key] !== $this->properties[$key] 113 ) { 114 $error = 'Subversion property "%s" = "%s" does not match "%s"'; 115 $data = array( 116 $key, 117 $properties[$key], 118 $this->properties[$key], 119 ); 120 $phpcsFile->addError($error, $stackPtr, 'NoMatch', $data); 121 } 122 }//end foreach 123 124 }//end process() 125 126 127 /** 128 * Returns the Subversion properties which are actually set on a path. 129 * 130 * Returns NULL if the file is not under version control. 131 * 132 * @param string $path The path to return Subversion properties on. 133 * 134 * @return array 135 * @throws PHP_CodeSniffer_Exception If Subversion properties file could 136 * not be opened. 137 */ 138 protected function getProperties($path) 139 { 140 $properties = array(); 141 142 $paths = array(); 143 $paths[] = dirname($path).'/.svn/props/'.basename($path).'.svn-work'; 144 $paths[] = dirname($path).'/.svn/prop-base/'.basename($path).'.svn-base'; 145 146 $foundPath = false; 147 foreach ($paths as $path) { 148 if (file_exists($path) === true) { 149 $foundPath = true; 150 151 $handle = fopen($path, 'r'); 152 if ($handle === false) { 153 $error = 'Error opening file; could not get Subversion properties'; 154 throw new PHP_CodeSniffer_Exception($error); 155 } 156 157 while (feof($handle) === false) { 158 // Read a key length line. Might be END, though. 159 $buffer = trim(fgets($handle)); 160 161 // Check for the end of the hash. 162 if ($buffer === 'END') { 163 break; 164 } 165 166 // Now read that much into a buffer. 167 $key = fread($handle, substr($buffer, 2)); 168 169 // Suck up extra newline after key data. 170 fgetc($handle); 171 172 // Read a value length line. 173 $buffer = trim(fgets($handle)); 174 175 // Now read that much into a buffer. 176 $length = substr($buffer, 2); 177 if ($length === '0') { 178 // Length of value is ZERO characters, so 179 // value is actually empty. 180 $value = ''; 181 } else { 182 $value = fread($handle, $length); 183 } 184 185 // Suck up extra newline after value data. 186 fgetc($handle); 187 188 $properties[$key] = $value; 189 }//end while 190 191 fclose($handle); 192 }//end if 193 }//end foreach 194 195 if ($foundPath === false) { 196 return null; 197 } 198 199 return $properties; 200 201 }//end getProperties() 202 203 204}//end class 205