GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — develop ( ebb7bf...0a5ff4 )
by Chris
02:41 queued 11s
created

WordPress_Sniffs_VIP_DirectDatabaseQuerySniff::process()   F

Complexity

Conditions 26
Paths 2022

Size

Total Lines 120
Code Lines 66

Duplication

Lines 3
Ratio 2.5 %

Importance

Changes 0
Metric Value
cc 26
eloc 66
nc 2022
nop 2
dl 3
loc 120
rs 2
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * WordPress Coding Standard.
4
 *
5
 * @package WPCS\WordPressCodingStandards
6
 * @link    https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards
7
 * @license https://opensource.org/licenses/MIT MIT
8
 */
9
10
/**
11
 * Flag Database direct queries.
12
 *
13
 * @link    https://vip.wordpress.com/documentation/vip/code-review-what-we-look-for/#direct-database-queries
14
 * @link    https://vip.wordpress.com/documentation/vip/code-review-what-we-look-for/#database-alteration
15
 *
16
 * @package WPCS\WordPressCodingStandards
17
 *
18
 * @since   0.3.0
19
 * @since   0.6.0 Removed the add_unique_message() function as it is no longer needed.
20
 */
21
class WordPress_Sniffs_VIP_DirectDatabaseQuerySniff implements PHP_CodeSniffer_Sniff {
22
23
	/**
24
	 * List of custom cache get functions.
25
	 *
26
	 * @since 0.6.0
27
	 *
28
	 * @var string[]
29
	 */
30
	public $customCacheGetFunctions = array();
31
32
	/**
33
	 * List of custom cache set functions.
34
	 *
35
	 * @since 0.6.0
36
	 *
37
	 * @var string[]
38
	 */
39
	public $customCacheSetFunctions = array();
40
41
	/**
42
	 * List of custom cache delete functions.
43
	 *
44
	 * @since 0.6.0
45
	 *
46
	 * @var string[]
47
	 */
48
	public $customCacheDeleteFunctions = array();
49
50
	/**
51
	 * The lists of $wpdb methods.
52
	 *
53
	 * @since 0.6.0
54
	 *
55
	 * @var array[]
56
	 */
57
	protected static $methods = array(
58
		'cachable' => array(
59
			'delete' => true,
60
			'get_var' => true,
61
			'get_col' => true,
62
			'get_row' => true,
63
			'get_results' => true,
64
			'query' => true,
65
			'replace' => true,
66
			'update' => true,
67
		),
68
		'noncachable' => array(
69
			'insert' => true,
70
		),
71
	);
72
73
	/**
74
	 * Returns an array of tokens this test wants to listen for.
75
	 *
76
	 * @return array
77
	 */
78
	public function register() {
79
		return array(
80
			T_VARIABLE,
81
		);
82
83
	}
84
85
	/**
86
	 * Processes this test, when one of its tokens is encountered.
87
	 *
88
	 * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
89
	 * @param int                  $stackPtr  The position of the current token
90
	 *                                        in the stack passed in $tokens.
91
	 *
92
	 * @return int|void
93
	 */
94
	public function process( PHP_CodeSniffer_File $phpcsFile, $stackPtr ) {
95
		if ( ! isset( self::$methods['all'] ) ) {
96
			self::$methods['all'] = array_merge( self::$methods['cachable'], self::$methods['noncachable'] );
97
98
			WordPress_Sniff::$cacheGetFunctions = array_merge(
99
				WordPress_Sniff::$cacheGetFunctions,
100
				array_flip( $this->customCacheGetFunctions )
101
			);
102
103
			WordPress_Sniff::$cacheSetFunctions = array_merge(
104
				WordPress_Sniff::$cacheSetFunctions,
105
				array_flip( $this->customCacheSetFunctions )
106
			);
107
108
			WordPress_Sniff::$cacheDeleteFunctions = array_merge(
109
				WordPress_Sniff::$cacheDeleteFunctions,
110
				array_flip( $this->customCacheDeleteFunctions )
111
			);
112
		}
113
114
		$tokens = $phpcsFile->getTokens();
115
116
		// Check for $wpdb variable.
117
		if ( '$wpdb' !== $tokens[ $stackPtr ]['content'] ) {
118
			return;
119
		}
120
121
		$is_object_call = $phpcsFile->findNext( array( T_OBJECT_OPERATOR ), ( $stackPtr + 1 ), null, null, null, true );
122
		if ( false === $is_object_call ) {
123
			return; // This is not a call to the wpdb object.
124
		}
125
126
		$methodPtr = $phpcsFile->findNext( array( T_WHITESPACE ), ( $is_object_call + 1 ), null, true, null, true );
127
		$method    = $tokens[ $methodPtr ]['content'];
128
129
		if ( ! isset( self::$methods['all'][ $method ] ) ) {
130
			return;
131
		}
132
133
		$endOfStatement   = $phpcsFile->findNext( array( T_SEMICOLON ), ( $stackPtr + 1 ), null, null, null, true );
134
		$endOfLineComment = '';
135
		$tokenCount       = count( $tokens );
136
		for ( $i = ( $endOfStatement + 1 ); $i < $tokenCount; $i++ ) {
137
138
			if ( $tokens[ $i ]['line'] !== $tokens[ $endOfStatement ]['line'] ) {
139
				break;
140
			}
141
142
			if ( T_COMMENT === $tokens[ $i ]['code'] ) {
143
				$endOfLineComment .= $tokens[ $i ]['content'];
144
			}
145
		}
146
147
		$whitelisted_db_call = false;
148
		if ( preg_match( '/db call\W*(?:ok|pass|clear|whitelist)/i', $endOfLineComment ) ) {
149
			$whitelisted_db_call = true;
150
		}
151
152
		// Check for Database Schema Changes.
153
		$_pos = $stackPtr;
154
		while ( $_pos = $phpcsFile->findNext( array( T_CONSTANT_ENCAPSED_STRING, T_DOUBLE_QUOTED_STRING ), ( $_pos + 1 ), $endOfStatement, null, null, true ) ) {
155
			if ( preg_match( '#\b(?:ALTER|CREATE|DROP)\b#i', $tokens[ $_pos ]['content'] ) > 0 ) {
156
				$phpcsFile->addError( 'Attempting a database schema change is highly discouraged.', $_pos, 'SchemaChange' );
157
			}
158
		}
159
160
		// Flag instance if not whitelisted.
161
		if ( ! $whitelisted_db_call ) {
162
			$phpcsFile->addWarning( 'Usage of a direct database call is discouraged.', $stackPtr, 'DirectQuery' );
163
		}
164
165
		if ( ! isset( self::$methods['cachable'][ $method ] ) ) {
166
			return $endOfStatement;
167
		}
168
169
		$whitelisted_cache = false;
170
		$cached            = $wp_cache_get = false;
171
		if ( preg_match( '/cache\s+(?:ok|pass|clear|whitelist)/i', $endOfLineComment ) ) {
172
			$whitelisted_cache = true;
173
		}
174
		if ( ! $whitelisted_cache && ! empty( $tokens[ $stackPtr ]['conditions'] ) ) {
175
			$scope_function = $phpcsFile->getCondition( $stackPtr, T_FUNCTION );
176
177
			if ( $scope_function ) {
178
				$scopeStart = $tokens[ $scope_function ]['scope_opener'];
179
				$scopeEnd   = $tokens[ $scope_function ]['scope_closer'];
180
181
				for ( $i = ( $scopeStart + 1 ); $i < $scopeEnd; $i++ ) {
182
					if ( T_STRING === $tokens[ $i ]['code'] ) {
183
184
						if ( isset( WordPress_Sniff::$cacheDeleteFunctions[ $tokens[ $i ]['content'] ] ) ) {
185
186
							if ( in_array( $method, array( 'query', 'update', 'replace', 'delete' ), true ) ) {
187
								$cached = true;
188
								break;
189
							}
190
						} elseif ( isset( WordPress_Sniff::$cacheGetFunctions[ $tokens[ $i ]['content'] ] ) ) {
191
192
							$wp_cache_get = true;
193
194
						} elseif ( isset( WordPress_Sniff::$cacheSetFunctions[ $tokens[ $i ]['content'] ] ) ) {
195
196
							if ( $wp_cache_get ) {
197
								$cached = true;
198
								break;
199
							}
200
						}
201
					}
202
				}
203
			}
204
		}
205
206
		if ( ! $cached && ! $whitelisted_cache ) {
207
			$message = 'Usage of a direct database call without caching is prohibited. Use wp_cache_get / wp_cache_set or wp_cache_delete.';
208
			$phpcsFile->addError( $message, $stackPtr, 'NoCaching' );
209
		}
210
211
		return $endOfStatement;
212
213
	} // end process()
214
215
} // End class.
216