>> */ protected $targetFunctions = [ 'array_diff_assoc' => [ 2 => [ 'name' => 'arrays', '7.4' => true, '8.0' => false, ], ], 'array_diff_key' => [ 2 => [ 'name' => 'arrays', '7.4' => true, '8.0' => false, ], ], 'array_diff_uassoc' => [ /* * $rest is actually at position 2, but has another required parameter after it, * so we need to detect on the last parameter. */ 3 => [ 'name' => 'rest', '7.4' => true, '8.0' => false, ], ], 'array_diff_ukey' => [ // Note from array_diff_uassoc applies here too. 3 => [ 'name' => 'rest', '7.4' => true, '8.0' => false, ], ], 'array_diff' => [ 2 => [ 'name' => 'arrays', '7.4' => true, '8.0' => false, ], ], 'array_intersect_assoc' => [ 2 => [ 'name' => 'arrays', '7.4' => true, '8.0' => false, ], ], 'array_intersect_key' => [ 2 => [ 'name' => 'arrays', '7.4' => true, '8.0' => false, ], ], 'array_intersect_uassoc' => [ // Note from array_diff_uassoc applies here too. 3 => [ 'name' => 'rest', '7.4' => true, '8.0' => false, ], ], 'array_intersect_ukey' => [ // Note from array_diff_uassoc applies here too. 3 => [ 'name' => 'rest', '7.4' => true, '8.0' => false, ], ], 'array_intersect' => [ 2 => [ 'name' => 'arrays', '7.4' => true, '8.0' => false, ], ], 'array_merge' => [ 1 => [ 'name' => 'arrays', '7.3' => true, '7.4' => false, ], ], 'array_merge_recursive' => [ 1 => [ 'name' => 'arrays', '7.3' => true, '7.4' => false, ], ], 'array_push' => [ 2 => [ 'name' => 'values', '7.2' => true, '7.3' => false, ], ], 'array_udiff_assoc' => [ // Note from array_diff_uassoc applies here too. 3 => [ 'name' => 'rest', '7.4' => true, '8.0' => false, ], ], 'array_udiff_uassoc' => [ // Note from array_diff_uassoc applies here too. 4 => [ 'name' => 'rest', '7.4' => true, '8.0' => false, ], ], 'array_udiff' => [ // Note from array_diff_uassoc applies here too. 3 => [ 'name' => 'rest', '7.4' => true, '8.0' => false, ], ], 'array_uintersect_assoc' => [ // Note from array_diff_uassoc applies here too. 3 => [ 'name' => 'rest', '7.4' => true, '8.0' => false, ], ], 'array_uintersect_uassoc' => [ // Note from array_diff_uassoc applies here too. 4 => [ 'name' => 'rest', '7.4' => true, '8.0' => false, ], ], 'array_uintersect' => [ // Note from array_diff_uassoc applies here too. 3 => [ 'name' => 'rest', '7.4' => true, '8.0' => false, ], ], 'array_unshift' => [ 2 => [ 'name' => 'values', '7.2' => true, '7.3' => false, ], ], 'bcscale' => [ 1 => [ 'name' => 'scale', '7.2' => true, '7.3' => false, ], ], 'fgetcsv' => [ 2 => [ 'name' => 'length', '5.0' => true, '5.1' => false, ], ], 'ftp_fget' => [ 4 => [ 'name' => 'mode', '7.2' => true, '7.3' => false, ], ], 'ftp_fput' => [ 4 => [ 'name' => 'mode', '7.2' => true, '7.3' => false, ], ], 'ftp_get' => [ 4 => [ 'name' => 'mode', '7.2' => true, '7.3' => false, ], ], 'ftp_nb_fget' => [ 4 => [ 'name' => 'mode', '7.2' => true, '7.3' => false, ], ], 'ftp_nb_fput' => [ 4 => [ 'name' => 'mode', '7.2' => true, '7.3' => false, ], ], 'ftp_nb_get' => [ 4 => [ 'name' => 'mode', '7.2' => true, '7.3' => false, ], ], 'ftp_nb_put' => [ 4 => [ 'name' => 'mode', '7.2' => true, '7.3' => false, ], ], 'ftp_put' => [ 4 => [ 'name' => 'mode', '7.2' => true, '7.3' => false, ], ], 'getenv' => [ 1 => [ 'name' => 'name', '7.0' => true, '7.1' => false, ], ], 'imagepolygon' => [ /* * $points is actually at position 3, but has another required parameter after it, * so we need to detect on the last parameter. * Note: this function explicitly does NOT support named parameters for the function * signature without this parameter, but that's not the concern of this sniff. */ 4 => [ 'name' => 'num_points', '7.4' => true, '8.0' => false, ], ], 'imageopenpolygon' => [ // Note from imagepolygon applies here too. 4 => [ 'name' => 'num_points', '7.4' => true, '8.0' => false, ], ], 'imagefilledpolygon' => [ // Note from imagepolygon applies here too. 4 => [ 'name' => 'num_points', '7.4' => true, '8.0' => false, ], ], 'pg_select' => [ 3 => [ 'name' => 'conditions', '8.3' => true, '8.4' => false, ], ], 'preg_match_all' => [ 3 => [ 'name' => 'matches', '5.3' => true, '5.4' => false, ], ], 'stream_socket_enable_crypto' => [ 3 => [ 'name' => 'crypto_method', '5.5' => true, '5.6' => false, ], ], 'xmlwriter_write_element' => [ 3 => [ 'name' => 'content', '5.2.2' => true, '5.2.3' => false, ], ], 'xmlwriter_write_element_ns' => [ 5 => [ 'name' => 'content', '5.2.2' => true, '5.2.3' => false, ], ], ]; /** * Bowing out early is not applicable to this sniff. * * @since 10.0.0 * * @return bool */ protected function bowOutEarly() { return false; } /** * Process the parameters of a matched function. * * @since 10.0.0 Part of the logic in this method was previously contained in the * `process()` method (now removed). * * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. * @param int $stackPtr The position of the current token in the stack. * @param string $functionName The token content (function name) which was matched. * @param array $parameters Array with information about the parameters. * * @return void */ public function processParameters(File $phpcsFile, $stackPtr, $functionName, $parameters) { $functionLc = \strtolower($functionName); foreach ($this->targetFunctions[$functionLc] as $offset => $parameterDetails) { $targetParam = PassedParameters::getParameterFromStack($parameters, $offset, $parameterDetails['name']); if ($targetParam === false) { $itemInfo = [ 'name' => $functionName, 'nameLc' => $functionLc, 'offset' => $offset, ]; $this->handleFeature($phpcsFile, $stackPtr, $itemInfo); } } } /** * Process the function if no parameters were found. * * @since 10.0.0 * * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. * @param int $stackPtr The position of the current token in the stack. * @param string $functionName The token content (function name) which was matched. * * @return void */ public function processNoParameters(File $phpcsFile, $stackPtr, $functionName) { $this->processParameters($phpcsFile, $stackPtr, $functionName, []); } /** * Retrieve the relevant detail (version) information for use in an error message. * * @since 7.1.0 * @since 10.0.0 - Method renamed from `getErrorInfo()` to `getVersionInfo(). * - Second function parameter `$itemInfo` removed. * - Method visibility changed from `public` to `protected`. * * @param array $itemArray Version and other information about the item. * * @return array */ protected function getVersionInfo(array $itemArray) { $versionInfo = [ 'requiredVersion' => '', ]; foreach ($itemArray as $version => $required) { if (\preg_match('`^\d\.\d(\.\d{1,2})?$`', $version) !== 1) { // Not a version key. continue; } if ($required === true && ScannedCode::shouldRunOnOrBelow($version) === true) { $versionInfo['requiredVersion'] = $version; } } return $versionInfo; } /** * Handle the retrieval of relevant information and - if necessary - throwing of an * error for a matched item. * * @since 10.0.0 This was previously handled via a similar method in the `AbstractComplexVersionSniff`. * * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. * @param int $stackPtr The position of the relevant token in * the stack. * @param array $itemInfo Base information about the item. * * @return void */ protected function handleFeature(File $phpcsFile, $stackPtr, array $itemInfo) { $itemArray = $this->targetFunctions[$itemInfo['nameLc']][$itemInfo['offset']]; $versionInfo = $this->getVersionInfo($itemArray); if (empty($versionInfo['requiredVersion'])) { return; } $this->addError($phpcsFile, $stackPtr, $itemInfo, $itemArray, $versionInfo); } /** * Generates the error for this item. * * @since 7.1.0 * @since 10.0.0 - Method visibility changed from `public` to `protected`. * - Introduced $itemArray parameter. * - Renamed the last parameter from `$errorInfo` to `$versionInfo`. * * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. * @param int $stackPtr The position of the relevant token in * the stack. * @param array $itemInfo Base information about the item. * @param array $itemArray The sub-array with all the details about * this item. * @param array $versionInfo Array with detail (version) information * relevant to the item. * * @return void */ protected function addError(File $phpcsFile, $stackPtr, array $itemInfo, array $itemArray, array $versionInfo) { $error = 'The "%s" parameter for function %s() is missing, but was required for PHP version %s and lower'; $errorCode = MessageHelper::stringToErrorCode($itemInfo['name'] . '_' . $itemArray['name'], true) . 'Missing'; $data = [ $itemArray['name'], $itemInfo['name'], $versionInfo['requiredVersion'], ]; $phpcsFile->addError($error, $stackPtr, $errorCode, $data); } }