@@ -1543,6 +1543,75 @@ protected function is_token_namespaced( $stackPtr ) {
15431543 return true ;
15441544 }
15451545
1546+ /**
1547+ * Check if a token is (part of) a parameter for a function call to a select list of functions.
1548+ *
1549+ * @since 2.1.0
1550+ *
1551+ * @param int $stackPtr The index of the token in the stack.
1552+ * @param array $valid_functions List of valid function names.
1553+ * Note: The keys to this array should be the function names
1554+ * in lowercase. Values are irrelevant.
1555+ * @param bool $global Optional. Whether to make sure that the function call is
1556+ * to a global function. If `false`, methods and namespaced
1557+ * function calls will also be allowed.
1558+ * Defaults to `true`.
1559+ * @param bool $allow_nested Optional. Whether to allow for nested function calls within the
1560+ * call to this function.
1561+ * I.e. when checking whether a token is within a function call
1562+ * to `strtolower()`, whether to accept `strtolower( trim( $var ) )`
1563+ * or only `strtolower( $var )`.
1564+ * Defaults to `false`.
1565+ *
1566+ * @return int|bool Stack pointer to the function call T_STRING token or false otherwise.
1567+ */
1568+ protected function is_in_function_call ( $ stackPtr , $ valid_functions , $ global = true , $ allow_nested = false ) {
1569+ if ( ! isset ( $ this ->tokens [ $ stackPtr ]['nested_parenthesis ' ] ) ) {
1570+ return false ;
1571+ }
1572+
1573+ $ nested_parenthesis = $ this ->tokens [ $ stackPtr ]['nested_parenthesis ' ];
1574+ if ( false === $ allow_nested ) {
1575+ $ nested_parenthesis = array_reverse ( $ nested_parenthesis , true );
1576+ }
1577+
1578+ foreach ( $ nested_parenthesis as $ open => $ close ) {
1579+
1580+ $ prev_non_empty = $ this ->phpcsFile ->findPrevious ( Tokens::$ emptyTokens , ( $ open - 1 ), null , true , null , true );
1581+ if ( false === $ prev_non_empty || \T_STRING !== $ this ->tokens [ $ prev_non_empty ]['code ' ] ) {
1582+ continue ;
1583+ }
1584+
1585+ if ( isset ( $ valid_functions [ strtolower ( $ this ->tokens [ $ prev_non_empty ]['content ' ] ) ] ) === false ) {
1586+ if ( false === $ allow_nested ) {
1587+ // Function call encountered, but not to one of the allowed functions.
1588+ return false ;
1589+ }
1590+
1591+ continue ;
1592+ }
1593+
1594+ if ( false === $ global ) {
1595+ return $ prev_non_empty ;
1596+ }
1597+
1598+ /*
1599+ * Now, make sure it is a global function.
1600+ */
1601+ if ( $ this ->is_class_object_call ( $ prev_non_empty ) === true ) {
1602+ continue ;
1603+ }
1604+
1605+ if ( $ this ->is_token_namespaced ( $ prev_non_empty ) === true ) {
1606+ continue ;
1607+ }
1608+
1609+ return $ prev_non_empty ;
1610+ }
1611+
1612+ return false ;
1613+ }
1614+
15461615 /**
15471616 * Check if something is only being sanitized.
15481617 *
0 commit comments