PageRenderTime 52ms CodeModel.GetById 6ms RepoModel.GetById 0ms app.codeStats 0ms

/script/lib/PHP/CodeSniffer/Standards/MySource/Sniffs/Channels/IncludeSystemSniff.php

https://bitbucket.org/chamilo/chamilo-dev/
PHP | 338 lines | 257 code | 23 blank | 58 comment | 15 complexity | e31e027e055112b0464b1d3363318530 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause, LGPL-2.1, LGPL-3.0, GPL-3.0, MIT
  1. <?php
  2. /**
  3. * Ensures that systems, asset types and libs are included before they are used.
  4. *
  5. * PHP version 5
  6. *
  7. * @category PHP
  8. * @package PHP_CodeSniffer_MySource
  9. * @author Greg Sherwood <gsherwood@squiz.net>
  10. * @copyright 2006 Squiz Pty Ltd (ABN 77 084 670 600)
  11. * @license http://matrix.squiz.net/developer/tools/php_cs/licence BSD Licence
  12. * @version CVS: $Id: IncludeSystemSniff.php 293522 2010-01-13 22:28:20Z squiz $
  13. * @link http://pear.php.net/package/PHP_CodeSniffer
  14. */
  15. if (class_exists('PHP_CodeSniffer_Standards_AbstractScopeSniff', true) === false)
  16. {
  17. $error = 'Class PHP_CodeSniffer_Standards_AbstractScopeSniff not found';
  18. throw new PHP_CodeSniffer_Exception($error);
  19. }
  20. /**
  21. * Ensures that systems, asset types and libs are included before they are used.
  22. *
  23. * @category PHP
  24. * @package PHP_CodeSniffer_MySource
  25. * @author Greg Sherwood <gsherwood@squiz.net>
  26. * @copyright 2006 Squiz Pty Ltd (ABN 77 084 670 600)
  27. * @license http://matrix.squiz.net/developer/tools/php_cs/licence BSD Licence
  28. * @version Release: 1.2.2
  29. * @link http://pear.php.net/package/PHP_CodeSniffer
  30. */
  31. class MySource_Sniffs_Channels_IncludeSystemSniff extends PHP_CodeSniffer_Standards_AbstractScopeSniff
  32. {
  33. /**
  34. * A list of classes that don't need to be included.
  35. *
  36. * @var array(string)
  37. */
  38. private $_ignore = array('self', 'parent', 'channels', 'basesystem', 'dal', 'init', 'pdo', 'util', 'ziparchive',
  39. 'phpunit_framework_assert', 'abstractmysourceunittest', 'abstractdatacleanunittest', 'exception',
  40. 'abstractwidgetwidgettype');
  41. /**
  42. * Constructs a Squiz_Sniffs_Scope_MethodScopeSniff.
  43. */
  44. public function __construct()
  45. {
  46. parent :: __construct(array(T_FUNCTION), array(T_DOUBLE_COLON, T_EXTENDS), true);
  47. } //end __construct()
  48. /**
  49. * Processes the function tokens within the class.
  50. *
  51. * @param PHP_CodeSniffer_File $phpcsFile The file where this token was found.
  52. * @param integer $stackPtr The position where the token was found.
  53. * @param integer $currScope The current scope opener token.
  54. *
  55. * @return void
  56. */
  57. protected function processTokenWithinScope(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $currScope)
  58. {
  59. $tokens = $phpcsFile->getTokens();
  60. // Determine the name of the class that the static function
  61. // is being called on.
  62. $classNameToken = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true);
  63. $className = $tokens[$classNameToken]['content'];
  64. if (in_array(strtolower($className), $this->_ignore) === true)
  65. {
  66. return;
  67. }
  68. $includedClasses = array();
  69. $fileName = strtolower($phpcsFile->getFilename());
  70. $matches = array();
  71. if (preg_match('|/systems/(.*)/([^/]+)?actions.inc$|', $fileName, $matches) !== 0)
  72. {
  73. // This is an actions file, which means we don't
  74. // have to include the system in which it exists
  75. // We know the system from the path.
  76. $includedClasses[] = $matches[2];
  77. }
  78. // Go searching for includeSystem and includeAsset calls within this
  79. // function, or the inclusion of .inc files, which
  80. // would be library files.
  81. for($i = ($currScope + 1); $i < $stackPtr; $i ++)
  82. {
  83. $name = $this->getIncludedClassFromToken($phpcsFile, $tokens, $i);
  84. if ($name !== false)
  85. {
  86. $includedClasses[] = $name;
  87. // Special case for Widgets cause they are, well, special.
  88. }
  89. else
  90. if (strtolower($tokens[$i]['content']) === 'includewidget')
  91. {
  92. $typeName = $phpcsFile->findNext(T_CONSTANT_ENCAPSED_STRING, ($i + 1));
  93. $typeName = trim($tokens[$typeName]['content'], " '");
  94. $includedClasses[] = strtolower($typeName) . 'widgettype';
  95. }
  96. }
  97. // Now go searching for includeSystem, includeAsset or require/include
  98. // calls outside our scope. If we are in a class, look outside the
  99. // class. If we are not, look outside the function.
  100. $condPtr = $currScope;
  101. if ($phpcsFile->hasCondition($stackPtr, T_CLASS) === true)
  102. {
  103. foreach ($tokens[$stackPtr]['conditions'] as $condPtr => $condType)
  104. {
  105. if ($condType === T_CLASS)
  106. {
  107. break;
  108. }
  109. }
  110. }
  111. for($i = 0; $i < $condPtr; $i ++)
  112. {
  113. // Skip other scopes.
  114. if (isset($tokens[$i]['scope_closer']) === true)
  115. {
  116. $i = $tokens[$i]['scope_closer'];
  117. continue;
  118. }
  119. $name = $this->getIncludedClassFromToken($phpcsFile, $tokens, $i);
  120. if ($name !== false)
  121. {
  122. $includedClasses[] = $name;
  123. }
  124. } //end for
  125. // If we are in a testing class, we might have also included
  126. // some systems and classes in our setUp() method.
  127. $setupFunction = null;
  128. if ($phpcsFile->hasCondition($stackPtr, T_CLASS) === true)
  129. {
  130. foreach ($tokens[$stackPtr]['conditions'] as $condPtr => $condType)
  131. {
  132. if ($condType === T_CLASS)
  133. {
  134. // Is this is a testing class?
  135. $name = $phpcsFile->findNext(T_STRING, $condPtr);
  136. $name = $tokens[$name]['content'];
  137. if (substr($name, - 8) === 'UnitTest')
  138. {
  139. // Look for a method called setUp().
  140. $end = $tokens[$condPtr]['scope_closer'];
  141. $function = $phpcsFile->findNext(T_FUNCTION, ($condPtr + 1), $end);
  142. while ($function !== false)
  143. {
  144. $name = $phpcsFile->findNext(T_STRING, $function);
  145. if ($tokens[$name]['content'] === 'setUp')
  146. {
  147. $setupFunction = $function;
  148. break;
  149. }
  150. $function = $phpcsFile->findNext(T_FUNCTION, ($function + 1), $end);
  151. }
  152. }
  153. }
  154. } //end foreach
  155. } //end if
  156. if ($setupFunction !== null)
  157. {
  158. $start = ($tokens[$setupFunction]['scope_opener'] + 1);
  159. $end = $tokens[$setupFunction]['scope_closer'];
  160. for($i = $start; $i < $end; $i ++)
  161. {
  162. $name = $this->getIncludedClassFromToken($phpcsFile, $tokens, $i);
  163. if ($name !== false)
  164. {
  165. $includedClasses[] = $name;
  166. }
  167. }
  168. } //end if
  169. if (in_array(strtolower($className), $includedClasses) === false)
  170. {
  171. $error = "Static method called on non-included class or system \"$className\"; include system with Channels::includeSystem() or include class with require_once";
  172. $phpcsFile->addError($error, $stackPtr);
  173. }
  174. } //end processTokenWithinScope()
  175. /**
  176. * Processes a token within the scope that this test is listening to.
  177. *
  178. * @param PHP_CodeSniffer_File $phpcsFile The file where the token was found.
  179. * @param int $stackPtr The position in the stack where
  180. * this token was found.
  181. *
  182. * @return void
  183. */
  184. protected function processTokenOutsideScope(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
  185. {
  186. $tokens = $phpcsFile->getTokens();
  187. if ($tokens[$stackPtr]['code'] === T_EXTENDS)
  188. {
  189. // Find the class name.
  190. $classNameToken = $phpcsFile->findNext(T_STRING, ($stackPtr + 1));
  191. $className = $tokens[$classNameToken]['content'];
  192. }
  193. else
  194. {
  195. // Determine the name of the class that the static function
  196. // is being called on.
  197. $classNameToken = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true);
  198. $className = $tokens[$classNameToken]['content'];
  199. }
  200. // Some systems are always available.
  201. if (in_array(strtolower($className), $this->_ignore) === true)
  202. {
  203. return;
  204. }
  205. $includedClasses = array();
  206. $fileName = strtolower($phpcsFile->getFilename());
  207. $matches = array();
  208. if (preg_match('|/systems/([^/]+)/([^/]+)?actions.inc$|', $fileName, $matches) !== 0)
  209. {
  210. // This is an actions file, which means we don't
  211. // have to include the system in which it exists
  212. // We know the system from the path.
  213. $includedClasses[] = $matches[1];
  214. }
  215. // Go searching for includeSystem, includeAsset or require/include
  216. // calls outside our scope.
  217. for($i = 0; $i < $stackPtr; $i ++)
  218. {
  219. // Skip classes and functions as will we never get
  220. // into their scopes when including this file, although
  221. // we have a chance of getting into IF's, WHILE's etc.
  222. $ignoreTokens = array(T_CLASS, T_INTERFACE, T_FUNCTION);
  223. if (in_array($tokens[$i]['code'], $ignoreTokens) === true && isset($tokens[$i]['scope_closer']) === true)
  224. {
  225. $i = $tokens[$i]['scope_closer'];
  226. continue;
  227. }
  228. $name = $this->getIncludedClassFromToken($phpcsFile, $tokens, $i);
  229. if ($name !== false)
  230. {
  231. $includedClasses[] = $name;
  232. // Special case for Widgets cause they are, well, special.
  233. }
  234. else
  235. if (strtolower($tokens[$i]['content']) === 'includewidget')
  236. {
  237. $typeName = $phpcsFile->findNext(T_CONSTANT_ENCAPSED_STRING, ($i + 1));
  238. $typeName = trim($tokens[$typeName]['content'], " '");
  239. $includedClasses[] = strtolower($typeName) . 'widgettype';
  240. }
  241. } //end for
  242. if (in_array(strtolower($className), $includedClasses) === false)
  243. {
  244. if ($tokens[$stackPtr]['code'] === T_EXTENDS)
  245. {
  246. $error = "Class extends non-included class or system \"$className\"; include system with Channels::includeSystem() or include class with require_once";
  247. }
  248. else
  249. {
  250. $error = "Static method called on non-included class or system \"$className\"; include system with Channels::includeSystem() or include class with require_once";
  251. }
  252. $phpcsFile->addError($error, $stackPtr);
  253. }
  254. } //end processTokenOutsideScope()
  255. /**
  256. * Determines the included class name from given token.
  257. *
  258. * @param PHP_CodeSniffer_File $phpcsFile The file where this token was found.
  259. * @param array $tokens The array of file tokens.
  260. * @param int $stackPtr The position in the tokens array of the
  261. * potentially included class.
  262. *
  263. * @return string
  264. */
  265. protected function getIncludedClassFromToken(PHP_CodeSniffer_File $phpcsFile, array $tokens, $stackPtr)
  266. {
  267. if (strtolower($tokens[$stackPtr]['content']) === 'includesystem')
  268. {
  269. $systemName = $phpcsFile->findNext(T_CONSTANT_ENCAPSED_STRING, ($stackPtr + 1));
  270. $systemName = trim($tokens[$systemName]['content'], " '");
  271. return strtolower($systemName);
  272. }
  273. else
  274. if (strtolower($tokens[$stackPtr]['content']) === 'includeasset')
  275. {
  276. $typeName = $phpcsFile->findNext(T_CONSTANT_ENCAPSED_STRING, ($stackPtr + 1));
  277. $typeName = trim($tokens[$typeName]['content'], " '");
  278. return strtolower($typeName) . 'assettype';
  279. }
  280. else
  281. if (in_array($tokens[$stackPtr]['code'], PHP_CodeSniffer_Tokens :: $includeTokens) === true)
  282. {
  283. $filePath = $phpcsFile->findNext(T_CONSTANT_ENCAPSED_STRING, ($stackPtr + 1));
  284. $filePath = $tokens[$filePath]['content'];
  285. $filePath = trim($filePath, " '");
  286. $filePath = basename($filePath, '.inc');
  287. return strtolower($filePath);
  288. }
  289. return false;
  290. } //end getIncludedClassFromToken()
  291. } //end class
  292. ?>