Chris@0
|
1 <?php
|
Chris@0
|
2 /**
|
Chris@0
|
3 * DrupalPractice_Sniffs_Objects_GlobalFunctionSniff.
|
Chris@0
|
4 *
|
Chris@0
|
5 * @category PHP
|
Chris@0
|
6 * @package PHP_CodeSniffer
|
Chris@0
|
7 * @link http://pear.php.net/package/PHP_CodeSniffer
|
Chris@0
|
8 */
|
Chris@0
|
9
|
Chris@0
|
10 /**
|
Chris@0
|
11 * Checks that global functions like t() are not used in forms or controllers.
|
Chris@0
|
12 *
|
Chris@0
|
13 * @category PHP
|
Chris@0
|
14 * @package PHP_CodeSniffer
|
Chris@0
|
15 * @link http://pear.php.net/package/PHP_CodeSniffer
|
Chris@0
|
16 */
|
Chris@0
|
17 class DrupalPractice_Sniffs_Objects_GlobalFunctionSniff implements PHP_CodeSniffer_Sniff
|
Chris@0
|
18 {
|
Chris@0
|
19
|
Chris@0
|
20 /**
|
Chris@0
|
21 * List of global functions that should not be called.
|
Chris@0
|
22 *
|
Chris@0
|
23 * @var string[]
|
Chris@0
|
24 */
|
Chris@0
|
25 protected $functions = array(
|
Chris@0
|
26 'drupal_get_destination' => 'the "redirect.destination" service',
|
Chris@0
|
27 'drupal_render' => 'the "renderer" service',
|
Chris@0
|
28 'entity_load' => 'the "entity_type.manager" service',
|
Chris@0
|
29 'file_load' => 'the "entity_type.manager" service',
|
Chris@0
|
30 'format_date' => 'the "date.formatter" service',
|
Chris@0
|
31 'node_load' => 'the "entity_type.manager" service',
|
Chris@0
|
32 'node_type_load' => 'the "entity_type.manager" service',
|
Chris@0
|
33 't' => '$this->t()',
|
Chris@0
|
34 'taxonomy_term_load' => 'the "entity_type.manager" service',
|
Chris@0
|
35 'taxonomy_vocabulary_load' => 'the "entity_type.manager" service',
|
Chris@0
|
36 'user_load' => 'the "entity_type.manager" service',
|
Chris@0
|
37 'user_role_load' => 'the "entity_type.manager" service',
|
Chris@0
|
38 );
|
Chris@0
|
39
|
Chris@0
|
40
|
Chris@0
|
41 /**
|
Chris@0
|
42 * Returns an array of tokens this test wants to listen for.
|
Chris@0
|
43 *
|
Chris@0
|
44 * @return array
|
Chris@0
|
45 */
|
Chris@0
|
46 public function register()
|
Chris@0
|
47 {
|
Chris@0
|
48 return array(T_STRING);
|
Chris@0
|
49
|
Chris@0
|
50 }//end register()
|
Chris@0
|
51
|
Chris@0
|
52
|
Chris@0
|
53 /**
|
Chris@0
|
54 * Processes this test, when one of its tokens is encountered.
|
Chris@0
|
55 *
|
Chris@0
|
56 * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
|
Chris@0
|
57 * @param int $stackPtr The position of the current token
|
Chris@0
|
58 * in the stack passed in $tokens.
|
Chris@0
|
59 *
|
Chris@0
|
60 * @return void
|
Chris@0
|
61 */
|
Chris@0
|
62 public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
|
Chris@0
|
63 {
|
Chris@0
|
64 $tokens = $phpcsFile->getTokens();
|
Chris@0
|
65
|
Chris@0
|
66 // We are only interested in function calls, which are not in the global
|
Chris@0
|
67 // scope.
|
Chris@0
|
68 if (isset($this->functions[$tokens[$stackPtr]['content']]) === false
|
Chris@0
|
69 || isset($tokens[($stackPtr + 1)]) === false
|
Chris@0
|
70 || $tokens[($stackPtr + 1)]['code'] !== T_OPEN_PARENTHESIS
|
Chris@0
|
71 || empty($tokens[$stackPtr]['conditions']) === true
|
Chris@0
|
72 ) {
|
Chris@0
|
73 return;
|
Chris@0
|
74 }
|
Chris@0
|
75
|
Chris@0
|
76 // If there is an object operator before the call then this is a method
|
Chris@0
|
77 // invocation, not a function call.
|
Chris@0
|
78 $previous = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true);
|
Chris@0
|
79 if ($tokens[$previous]['code'] === T_OBJECT_OPERATOR) {
|
Chris@0
|
80 return;
|
Chris@0
|
81 }
|
Chris@0
|
82
|
Chris@0
|
83 // Check that this statement is not in a static function.
|
Chris@0
|
84 foreach ($tokens[$stackPtr]['conditions'] as $conditionPtr => $conditionCode) {
|
Chris@0
|
85 if ($conditionCode === T_FUNCTION && $phpcsFile->getMethodProperties($conditionPtr)['is_static'] === true) {
|
Chris@0
|
86 return;
|
Chris@0
|
87 }
|
Chris@0
|
88 }
|
Chris@0
|
89
|
Chris@0
|
90 // Check if the class extends another class and get the name of the class
|
Chris@0
|
91 // that is extended.
|
Chris@0
|
92 $classPtr = key($tokens[$stackPtr]['conditions']);
|
Chris@0
|
93 $extendsName = $phpcsFile->findExtendedClassName($classPtr);
|
Chris@0
|
94
|
Chris@0
|
95 if (($extendsName === false
|
Chris@0
|
96 || in_array($extendsName, DrupalPractice_Sniffs_Objects_GlobalDrupalSniff::$baseClasses) === false)
|
Chris@0
|
97 && DrupalPractice_Project::isServiceClass($phpcsFile, $classPtr) === false
|
Chris@0
|
98 ) {
|
Chris@0
|
99 return;
|
Chris@0
|
100 }
|
Chris@0
|
101
|
Chris@0
|
102 $warning = '%s() calls should be avoided in classes, use dependency injection and %s instead';
|
Chris@0
|
103 $data = array(
|
Chris@0
|
104 $tokens[$stackPtr]['content'],
|
Chris@0
|
105 $this->functions[$tokens[$stackPtr]['content']],
|
Chris@0
|
106 );
|
Chris@0
|
107 $phpcsFile->addWarning($warning, $stackPtr, 'GlobalFunction', $data);
|
Chris@0
|
108
|
Chris@0
|
109 }//end process()
|
Chris@0
|
110
|
Chris@0
|
111
|
Chris@0
|
112 }//end class
|