private function record_potential_prefix_metric( $stackPtr, $construct_name ) {
		if ( preg_match( '`^([A-Z]*[a-z0-9]*+)`', ltrim( $construct_name, '\$_' ), $matches ) > 0
			&& isset( $matches[1] ) && '' !== $matches[1]
		) {
			$this->phpcsFile->recordMetric( $stackPtr, 'Prefix all globals: potential prefixes - start of non-prefixed construct', strtolower( $matches[1] ) );
		}
	}

Record the "potential prefix" metric.

@since 1.0.1

@param int    $stackPtr       The position of the token to record the metric against.
@param string $construct_name Name of the global construct to try and distill a potential prefix from.

@return void


protected function setup_groups() {
		$this->groups_cache = $this->getGroups();

		if ( empty( $this->groups_cache ) && empty( self::$groups ) ) {
			return false;
		}

		// Allow for adding extra unit tests.
		if ( ! empty( self::$groups ) ) {
			$this->groups_cache = array_merge( $this->groups_cache, self::$groups );
		}

		return true;
	}

protected
function
setup_groups
(
)
{
$
this
->
groups_cache
=
$
this
->
getGroups
(
)
;
if
(
empty
(
$
this
->
groups_cache
)
&&
empty
(
self
::
$
groups
)
)
{
return
false
;
}
// Allow for adding extra unit tests.
if
(
!
empty
(
self
::
$
groups
)
)
{
$
this
->
groups_cache
=
array_merge
(
$
this
->
groups_cache
,
self
::
$
groups
)
;
}
return
true
;
}

Cache the groups.

@since 0.13.0

@return bool True if the groups were setup. False if not.


protected function validate_align_multiline_items() {
		$alignMultilineItems = $this->alignMultilineItems;

		if ( 'always' === $alignMultilineItems || 'never' === $alignMultilineItems ) {
			return;
		} else {
			// Correct for a potentially added % sign.
			$alignMultilineItems = rtrim( $alignMultilineItems, '%' );

			if ( preg_match( '`^([=<>!]{1,2})(100|[0-9]{1,2})$`', $alignMultilineItems, $matches ) > 0 ) {
				$operator = $matches[1];
				$number   = (int) $matches[2];

				if ( \in_array( $operator, array( '<', '<=', '>', '>=', '==', '=', '!=', '<>' ), true ) === true
					&& ( $number >= 0 && $number <= 100 )
				) {
					$this->alignMultilineItems = $alignMultilineItems;
					$this->number              = (string) $number;
					$this->operator            = $operator;
					return;
				}
			}
		}

		$this->phpcsFile->addError(
			'Invalid property value passed: "%s". The value for the "alignMultilineItems" property for the "WordPress.Arrays.MultipleStatementAlignment" sniff should be either "always", "never" or an comparison operator + a number between 0 and 100.',
			0,
			'InvalidPropertyPassed',
			array( $this->alignMultilineItems )
		);

		// Reset to the default if an invalid value was received.
		$this->alignMultilineItems = 'always';
	}

Validate that a valid value has been received for the alignMultilineItems property.

This message may be thrown more than once if the property is being changed inline in a file.

@since 0.14.0

Validate that a valid value has been received for the alignMultilineItems property .


protected function is_local_data_stream( $raw_param_value ) {

		$raw_stripped = $this->strip_quotes( $raw_param_value );
		if ( isset( $this->allowed_local_streams[ $raw_stripped ] )
			|| isset( $this->allowed_local_stream_constants[ $raw_param_value ] )
		) {
			return true;
		}

		foreach ( $this->allowed_local_stream_partials as $partial ) {
			if ( strpos( $raw_stripped, $partial ) === 0 ) {
				return true;
			}
		}

		return false;
	}

protected function is_local_data_stream ( $ raw_param_value ) { $ raw_stripped = $ this -> strip_quotes ( $ raw_param_value ) ; if ( isset ( $ this -> allowed_local_streams [ $ raw_stripped ] ) || isset ( $ this -> allowed_local_stream_constants [ $ raw_param_value ] ) ) { return true ; } foreach ( $ this -> allowed_local_stream_partials as $ partial ) { if ( strpos ( $ raw_stripped , $ partial ) === 0 ) { return true ; } } return false ; }

Determine based on the "raw" parameter value, whether a file parameter points to
a local data stream.

@param string $raw_param_value Raw parameter value.

@return bool True if this is a local data stream. False otherwise.

Determine based on the raw parameter value whether a file parameter points to a local data stream .


protected function processVariableInString( File $phpcs_file, $stack_ptr ) {

		$tokens = $phpcs_file->getTokens();

		if ( preg_match_all( '|[^\\\]\${?([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)|', $tokens[ $stack_ptr ]['content'], $matches ) > 0 ) {

			// Merge any custom variables with the defaults.
			$this->mergeWhiteList();

			foreach ( $matches[1] as $var_name ) {
				// If it's a php reserved var, then its ok.
				if ( isset( $this->phpReservedVars[ $var_name ] ) ) {
					continue;
				}

				// Likewise if it is a mixed-case var used by WordPress core.
				if ( isset( $this->wordpress_mixed_case_vars[ $var_name ] ) ) {
					return;
				}

				if ( false === self::isSnakeCase( $var_name ) ) {
					$error = 'Variable "$%s" is not in valid snake_case format, try "$%s"';
					$data  = array(
						$var_name,
						Sniff::get_snake_case_name_suggestion( $var_name ),
					);
					$phpcs_file->addError( $error, $stack_ptr, 'InterpolatedVariableNotSnakeCase', $data );
				}
			}
		}
	}

Processes the variable found within a double quoted string.

@param \PHP_CodeSniffer\Files\File $phpcs_file The file being scanned.
@param int                         $stack_ptr  The position of the double quoted
string.

@return void

Processes the variable found within a double quoted string .


protected function mergeWhiteList() {
		if ( $this->customPropertiesWhitelist !== $this->addedCustomProperties['properties'] ) {
			// Fix property potentially passed as comma-delimited string.
			$customProperties = Sniff::merge_custom_array( $this->customPropertiesWhitelist, array(), false );

			$this->whitelisted_mixed_case_member_var_names = Sniff::merge_custom_array(
				$customProperties,
				$this->whitelisted_mixed_case_member_var_names
			);

			$this->addedCustomProperties['properties'] = $this->customPropertiesWhitelist;
		}
	}

Merge a custom whitelist provided via a custom ruleset with the predefined whitelist,
if we haven't already.

@since 0.10.0
@since 2.0.0  Removed unused $phpcs_file parameter.

@return void

Merge a custom whitelist provided via a custom ruleset with the predefined whitelist if we haven t already .


protected function ignore_token( $ptr ) {
		$token_code = $this->tokens[ $ptr ]['code'];

		if ( isset( $this->ignore_tokens[ $token_code ] ) ) {
			return true;
		}

		/*
		 * If it's a subsequent line of a multi-line sting, it will not start with a quote
		 * character, nor just *be* a quote character.
		 */
		if ( \T_CONSTANT_ENCAPSED_STRING === $token_code
			|| \T_DOUBLE_QUOTED_STRING === $token_code
		) {
			// Deal with closing quote of a multi-line string being on its own line.
			if ( "'" === $this->tokens[ $ptr ]['content']
				|| '"' === $this->tokens[ $ptr ]['content']
			) {
				return true;
			}

			// Deal with subsequent lines of a multi-line string where the token is broken up per line.
			if ( "'" !== $this->tokens[ $ptr ]['content'][0]
				&& '"' !== $this->tokens[ $ptr ]['content'][0]
			) {
				return true;
			}
		}

		return false;
	}

Should the token be ignored ?

This method is only intended to be used with the first token on a line
for subsequent lines in an multi-line array item.

@param int $ptr Stack pointer to the first token on a line.

@return bool


protected function get_indentation_size( $ptr ) {

		// Find the first token on the line.
		for ( ; $ptr >= 0; $ptr-- ) {
			if ( 1 === $this->tokens[ $ptr ]['column'] ) {
				break;
			}
		}

		$whitespace = '';

		if ( \T_WHITESPACE === $this->tokens[ $ptr ]['code']
			|| \T_DOC_COMMENT_WHITESPACE === $this->tokens[ $ptr ]['code']
		) {
			return $this->tokens[ $ptr ]['length'];
		}

		/*
		 * Special case for multi-line, non-docblock comments.
		 * Only applicable for subsequent lines in an array item.
		 *
		 * First/Single line is tokenized as T_WHITESPACE + T_COMMENT
		 * Subsequent lines are tokenized as T_COMMENT including the indentation whitespace.
		 */
		if ( \T_COMMENT === $this->tokens[ $ptr ]['code'] ) {
			$content        = $this->tokens[ $ptr ]['content'];
			$actual_comment = ltrim( $content );
			$whitespace     = str_replace( $actual_comment, '', $content );
		}

		return \strlen( $whitespace );
	}

Determine the line indentation whitespace.

@param int $ptr Stack pointer to an arbitrary token on a line.

@return int Nr of spaces found. Where necessary, tabs are translated to spaces.

Determine the line indentation whitespace .


protected function get_indentation_string( $nr ) {
		if ( 0 >= $nr ) {
			return '';
		}

		// Space-based indentation.
		if ( false === $this->tabIndent ) {
			return str_repeat( ' ', $nr );
		}

		// Tab-based indentation.
		$num_tabs    = (int) floor( $nr / $this->tab_width );
		$remaining   = ( $nr % $this->tab_width );
		$tab_indent  = str_repeat( "\t", $num_tabs );
		$tab_indent .= str_repeat( ' ', $remaining );

		return $tab_indent;
	}

protected
function
get_indentation_string
(
$
nr
)
{
if
(
0
>=
$
nr
)
{
return
''
;
}
// Space-based indentation.
if
(
false
===
$
this
->
tabIndent
)
{
return
str_repeat
(
' '
,
$
nr
)
;
}
// Tab-based indentation.
$
num_tabs
=
(
int
)
floor
(
$
nr
/
$
this
->
tab_width
)
;
$
remaining
=
(
$
nr
%
$
this
->
tab_width
)
;
$
tab_indent
=
str_repeat
(
"\t"
,
$
num_tabs
)
;
$
tab_indent
.=
str_repeat
(
' '
,
$
remaining
)
;
return
$
tab_indent
;
}

Create an indentation string.

@param int $nr Number of spaces the indentation should be.

@return string


protected function add_array_alignment_error( $ptr, $error, $error_code, $expected, $found, $new_indent ) {

		$fix = $this->phpcsFile->addFixableError( $error, $ptr, $error_code, array( $expected, $found ) );
		if ( true === $fix ) {
			$this->fix_alignment_error( $ptr, $new_indent );
		}
	}

protected function add_array_alignment_error ( $ ptr , $ error , $ error_code , $ expected , $ found , $ new_indent ) { $ fix = $ this -> phpcsFile -> addFixableError ( $ error , $ ptr , $ error_code , array ( $ expected , $ found ) ) ; if ( true === $ fix ) { $ this -> fix_alignment_error ( $ ptr , $ new_indent ) ; } }

Throw an error and fix incorrect array alignment.

@param int    $ptr        Stack pointer to the first content on the line.
@param string $error      Error message.
@param string $error_code Error code.
@param int    $expected   Expected nr of spaces (tabs translated to space value).
@param int    $found      Found nr of spaces (tabs translated to space value).
@param string $new_indent Whitespace indent replacement content.

Throw an error and fix incorrect array alignment .


protected function fix_alignment_error( $ptr, $new_indent ) {
		if ( 1 === $this->tokens[ $ptr ]['column'] ) {
			$this->phpcsFile->fixer->addContentBefore( $ptr, $new_indent );
		} else {
			$this->phpcsFile->fixer->replaceToken( ( $ptr - 1 ), $new_indent );
		}
	}

protected function fix_alignment_error ( $ ptr , $ new_indent ) { if ( 1 === $ this -> tokens [ $ ptr ] [ 'column' ] ) { $ this -> phpcsFile -> fixer -> addContentBefore ( $ ptr , $ new_indent ) ; } else { $ this -> phpcsFile -> fixer -> replaceToken ( ( $ ptr - 1 ) , $ new_indent ) ; } }

Fix incorrect array alignment.

@param int    $ptr        Stack pointer to the first content on the line.
@param string $new_indent Whitespace indent replacement content.


protected function is_falsy( $start, $end ) {

		// Find anything excluding the false tokens.
		$has_non_false = $this->phpcsFile->findNext( $this->false_tokens, $start, ( $end + 1 ), true );
		// If no non-false tokens are found, we are good.
		if ( false === $has_non_false ) {
			return true;
		}

		$code_string = '';
		for ( $i = $start; $i <= $end; $i++ ) {
			if ( isset( $this->safe_tokens[ $this->tokens[ $i ]['code'] ] ) === false ) {
				// Function call/variable or other token which makes it neigh impossible
				// to determine whether the actual value would evaluate to false.
				return false;
			}

			if ( isset( Tokens::$emptyTokens[ $this->tokens[ $i ]['code'] ] ) === true ) {
				continue;
			}

			$code_string .= $this->tokens[ $i ]['content'];
		}

		if ( '' === $code_string ) {
			return false;
		}

		// Evaluate the argument to figure out the outcome is false or not.
		// phpcs:ignore Squiz.PHP.Eval -- No harm here.
		return ( false === eval( "return (bool) $code_string;" ) );
	}

Determine if a range has a falsy value.

@param int $start The position to start looking from.
@param int $end   The position to stop looking (inclusive).

@return bool True if the parameter is falsy.
False if the parameter is not falsy or when it
couldn't be reliably determined.

Determine if a range has a falsy value .


protected function compare_single_and_plural_arguments( $stack_ptr, $single_context, $plural_context ) {
		$single_content = $single_context['tokens'][0]['content'];
		$plural_content = $plural_context['tokens'][0]['content'];

		preg_match_all( self::SPRINTF_PLACEHOLDER_REGEX, $single_content, $single_placeholders );
		$single_placeholders = $single_placeholders[0];

		preg_match_all( self::SPRINTF_PLACEHOLDER_REGEX, $plural_content, $plural_placeholders );
		$plural_placeholders = $plural_placeholders[0];

		// English conflates "singular" with "only one", described in the codex:
		// https://codex.wordpress.org/I18n_for_WordPress_Developers#Plurals .
		if ( \count( $single_placeholders ) < \count( $plural_placeholders ) ) {
			$error_string = 'Missing singular placeholder, needed for some languages. See https://codex.wordpress.org/I18n_for_WordPress_Developers#Plurals';
			$single_index = $single_context['tokens'][0]['token_index'];

			$this->phpcsFile->addError( $error_string, $single_index, 'MissingSingularPlaceholder' );
		}

		// Reordering is fine, but mismatched placeholders is probably wrong.
		sort( $single_placeholders );
		sort( $plural_placeholders );

		if ( $single_placeholders !== $plural_placeholders ) {
			$this->phpcsFile->addWarning( 'Mismatched placeholders is probably an error', $stack_ptr, 'MismatchedPlaceholders' );
		}
	}

Check for inconsistencies between single and plural arguments.

@param int   $stack_ptr      The position of the current token in the stack.
@param array $single_context Single context (@todo needs better description).
@param array $plural_context Plural context (@todo needs better description).
@return void

Check for inconsistencies between single and plural arguments .


protected function check_text( $context ) {
		$stack_ptr = $context['stack_ptr'];
		$arg_name  = $context['arg_name'];
		$content   = $context['tokens'][0]['content'];
		$is_error  = empty( $context['warning'] );

		// UnorderedPlaceholders: Check for multiple unordered placeholders.
		$unordered_matches_count = preg_match_all( self::UNORDERED_SPRINTF_PLACEHOLDER_REGEX, $content, $unordered_matches );
		$unordered_matches       = $unordered_matches[0];
		$all_matches_count       = preg_match_all( self::SPRINTF_PLACEHOLDER_REGEX, $content, $all_matches );

		if ( $unordered_matches_count > 0 && $unordered_matches_count !== $all_matches_count && $all_matches_count > 1 ) {
			$code = $this->string_to_errorcode( 'MixedOrderedPlaceholders' . ucfirst( $arg_name ) );
			$this->phpcsFile->addError(
				'Multiple placeholders should be ordered. Mix of ordered and non-ordered placeholders found. Found: %s.',
				$stack_ptr,
				$code,
				array( implode( ', ', $all_matches[0] ) )
			);

		} elseif ( $unordered_matches_count >= 2 ) {
			$code = $this->string_to_errorcode( 'UnorderedPlaceholders' . ucfirst( $arg_name ) );

			$suggestions     = array();
			$replace_regexes = array();
			$replacements    = array();
			for ( $i = 0; $i < $unordered_matches_count; $i++ ) {
				$to_insert         = ( $i + 1 );
				$to_insert        .= ( '"' !== $content[0] ) ? '$' : '\$';
				$suggestions[ $i ] = substr_replace( $unordered_matches[ $i ], $to_insert, 1, 0 );

				// Prepare the strings for use a regex.
				$replace_regexes[ $i ] = '`\Q' . $unordered_matches[ $i ] . '\E`';
				// Note: the initial \\ is a literal \, the four \ in the replacement translate to also to a literal \.
				$replacements[ $i ] = str_replace( '\\', '\\\\', $suggestions[ $i ] );
				// Note: the $ needs escaping to prevent numeric sequences after the $ being interpreted as match replacements.
				$replacements[ $i ] = str_replace( '$', '\\$', $replacements[ $i ] );
			}

			$fix = $this->addFixableMessage(
				'Multiple placeholders should be ordered. Expected \'%s\', but got %s.',
				$stack_ptr,
				$is_error,
				$code,
				array( implode( ', ', $suggestions ), implode( ', ', $unordered_matches ) )
			);

			if ( true === $fix ) {
				$fixed_str = preg_replace( $replace_regexes, $replacements, $content, 1 );

				$this->phpcsFile->fixer->replaceToken( $stack_ptr, $fixed_str );
			}
		}

		/*
		 * NoEmptyStrings.
		 *
		 * Strip placeholders and surrounding quotes.
		 */
		$non_placeholder_content = trim( $this->strip_quotes( $content ) );
		$non_placeholder_content = preg_replace( self::SPRINTF_PLACEHOLDER_REGEX, '', $non_placeholder_content );

		if ( '' === $non_placeholder_content ) {
			$this->phpcsFile->addError( 'Strings should have translatable content', $stack_ptr, 'NoEmptyStrings' );
		}
	}

Check the string itself for problems.

@param array $context Context (@todo needs better description).
@return void


public function is_targetted_token( $stackPtr ) {

		$token     = $this->tokens[ $stackPtr ];
		$classname = '';

		if ( \in_array( $token['code'], array( \T_NEW, \T_EXTENDS, \T_IMPLEMENTS ), true ) ) {
			if ( \T_NEW === $token['code'] ) {
				$nameEnd = ( $this->phpcsFile->findNext( array( \T_OPEN_PARENTHESIS, \T_WHITESPACE, \T_SEMICOLON, \T_OBJECT_OPERATOR ), ( $stackPtr + 2 ) ) - 1 );
			} else {
				$nameEnd = ( $this->phpcsFile->findNext( array( \T_CLOSE_CURLY_BRACKET, \T_WHITESPACE ), ( $stackPtr + 2 ) ) - 1 );
			}

			$length    = ( $nameEnd - ( $stackPtr + 1 ) );
			$classname = $this->phpcsFile->getTokensAsString( ( $stackPtr + 2 ), $length );

			if ( \T_NS_SEPARATOR !== $this->tokens[ ( $stackPtr + 2 ) ]['code'] ) {
				$classname = $this->get_namespaced_classname( $classname, ( $stackPtr - 1 ) );
			}
		}

		if ( \T_DOUBLE_COLON === $token['code'] ) {
			$nameEnd   = $this->phpcsFile->findPrevious( \T_STRING, ( $stackPtr - 1 ) );
			$nameStart = ( $this->phpcsFile->findPrevious( array( \T_STRING, \T_NS_SEPARATOR, \T_NAMESPACE ), ( $nameEnd - 1 ), null, true, null, true ) + 1 );
			$length    = ( $nameEnd - ( $nameStart - 1 ) );
			$classname = $this->phpcsFile->getTokensAsString( $nameStart, $length );

			if ( \T_NS_SEPARATOR !== $this->tokens[ $nameStart ]['code'] ) {
				$classname = $this->get_namespaced_classname( $classname, ( $nameStart - 1 ) );
			}
		}

		// Stop if we couldn't determine a classname.
		if ( empty( $classname ) ) {
			return false;
		}

		// Nothing to do if 'parent', 'self' or 'static'.
		if ( \in_array( $classname, array( 'parent', 'self', 'static' ), true ) ) {
			return false;
		}

		$this->classname = $classname;
		return true;
	}

Determine if we have a valid classname for the target token.

@since 0.11.0 This logic was originally contained in the `process()` method.

@param int $stackPtr The position of the current token in the stack.

@return bool

Determine if we have a valid classname for the target token .


public function check_for_matches( $stackPtr ) {
		$skip_to = array();

		foreach ( $this->groups as $groupName => $group ) {

			if ( isset( $this->excluded_groups[ $groupName ] ) ) {
				continue;
			}

			if ( preg_match( $group['regex'], $this->classname ) === 1 ) {
				$skip_to[] = $this->process_matched_token( $stackPtr, $groupName, $this->classname );
			}
		}

		if ( empty( $skip_to ) || min( $skip_to ) === 0 ) {
			return;
		}

		return min( $skip_to );
	}

public function check_for_matches ( $ stackPtr ) { $ skip_to = array ( ) ; foreach ( $ this -> groups as $ groupName => $ group ) { if ( isset ( $ this -> excluded_groups [ $ groupName ] ) ) { continue ; } if ( preg_match ( $ group [ 'regex' ] , $ this -> classname ) === 1 ) { $ skip_to [ ] = $ this -> process_matched_token ( $ stackPtr , $ groupName , $ this -> classname ) ; } } if ( empty ( $ skip_to ) || min ( $ skip_to ) === 0 ) { return ; } return min ( $ skip_to ) ; }

Verify if the current token is one of the targetted classes.

@since 0.11.0 Split out from the `process()` method.

@param int $stackPtr The position of the current token in the stack.

@return int|void Integer stack pointer to skip forward or void to continue
normal file processing.

Verify if the current token is one of the targetted classes .


protected function get_namespaced_classname( $classname, $search_from ) {
		// Don't do anything if this is already a fully qualified classname.
		if ( empty( $classname ) || '\\' === $classname[0] ) {
			return $classname;
		}

		// Remove the namespace keyword if used.
		if ( 0 === strpos( $classname, 'namespace\\' ) ) {
			$classname = substr( $classname, 10 );
		}

		$namespace_keyword = $this->phpcsFile->findPrevious( \T_NAMESPACE, $search_from );
		if ( false === $namespace_keyword ) {
			// No namespace keyword found at all, so global namespace.
			$classname = '\\' . $classname;
		} else {
			$namespace = $this->determine_namespace( $search_from );

			if ( ! empty( $namespace ) ) {
				$classname = '\\' . $namespace . '\\' . $classname;
			} else {
				// No actual namespace found, so global namespace.
				$classname = '\\' . $classname;
			}
		}

		return $classname;
	}

See if the classname was found in a namespaced file and if so, add the namespace to the classname.

@param string $classname   The full classname as found.
@param int    $search_from The token position to search up from.
@return string Classname, potentially prefixed with the namespace.

See if the classname was found in a namespaced file and if so add the namespace to the classname .


public function register() {
		$this->assignment_tokens = Tokens::$assignmentTokens;
		unset( $this->assignment_tokens[ \T_DOUBLE_ARROW ] );

		$starters                        = Tokens::$booleanOperators;
		$starters[ \T_SEMICOLON ]        = \T_SEMICOLON;
		$starters[ \T_OPEN_PARENTHESIS ] = \T_OPEN_PARENTHESIS;
		$starters[ \T_INLINE_ELSE ]      = \T_INLINE_ELSE;

		$this->condition_start_tokens = $starters;

		return array(
			\T_IF,
			\T_ELSEIF,
			\T_FOR,
			\T_SWITCH,
			\T_CASE,
			\T_WHILE,
			\T_INLINE_THEN,
		);
	}

public function register ( ) { $ this -> assignment_tokens = Tokens :: $ assignmentTokens ; unset ( $ this -> assignment_tokens [ \ T_DOUBLE_ARROW ] ) ; $ starters = Tokens :: $ booleanOperators ; $ starters [ \ T_SEMICOLON ] = \ T_SEMICOLON ; $ starters [ \ T_OPEN_PARENTHESIS ] = \ T_OPEN_PARENTHESIS ; $ starters [ \ T_INLINE_ELSE ] = \ T_INLINE_ELSE ; $ this -> condition_start_tokens = $ starters ; return array ( \ T_IF , \ T_ELSEIF , \ T_FOR , \ T_SWITCH , \ T_CASE , \ T_WHILE , \ T_INLINE_THEN , ) ; }

Registers the tokens that this sniff wants to listen for.

@since 0.14.0

@return array

Registers the tokens that this sniff wants to listen for .


public function execute($queue)
    {
        $serializer = new Serializer();
        $closure = $serializer->unserialize($this->serialized);
        return $closure();
    }

public function execute ( $ queue ) { $ serializer = new Serializer ( ) ; $ closure = $ serializer -> unserialize ( $ this -> serialized ) ; return $ closure ( ) ; }

Unserializes and executes a closure.
@inheritdoc


protected function reserve($timeout)
    {
        $response = $this->getClient()->receiveMessage([
            'QueueUrl' => $this->url,
            'AttributeNames' => ['ApproximateReceiveCount'],
            'MessageAttributeNames' => ['TTR'],
            'MaxNumberOfMessages' => 1,
            'VisibilityTimeout' => $this->ttr,
            'WaitTimeSeconds' => $timeout,
        ]);
        if (!$response['Messages']) {
            return null;
        }

        $payload = reset($response['Messages']);

        $ttr = (int) $payload['MessageAttributes']['TTR']['StringValue'];
        if ($ttr != $this->ttr) {
            $this->getClient()->changeMessageVisibility([
                'QueueUrl' => $this->url,
                'ReceiptHandle' => $payload['ReceiptHandle'],
                'VisibilityTimeout' => $ttr,
            ]);
        }

        return $payload;
    }

protected function reserve ( $ timeout ) { $ response = $ this -> getClient ( ) -> receiveMessage ( [ 'QueueUrl' => $ this -> url , 'AttributeNames' => [ 'ApproximateReceiveCount' ] , 'MessageAttributeNames' => [ 'TTR' ] , 'MaxNumberOfMessages' => 1 , 'VisibilityTimeout' => $ this -> ttr , 'WaitTimeSeconds' => $ timeout , ] ) ; if ( ! $ response [ 'Messages' ] ) { return null ; } $ payload = reset ( $ response [ 'Messages' ] ) ; $ ttr = ( int ) $ payload [ 'MessageAttributes' ] [ 'TTR' ] [ 'StringValue' ] ; if ( $ ttr != $ this -> ttr ) { $ this -> getClient ( ) -> changeMessageVisibility ( [ 'QueueUrl' => $ this -> url , 'ReceiptHandle' => $ payload [ 'ReceiptHandle' ] , 'VisibilityTimeout' => $ ttr , ] ) ; } return $ payload ; }

Gets a single message from SQS queue and sets the visibility to reserve message.

@param int $timeout number of seconds for long polling. Must be between 0 and 20.
@return null|array payload.

Gets a single message from SQS queue and sets the visibility to reserve message .


protected function close()
    {
        if (!$this->context) {
            return;
        }

        $this->context->close();
        $this->context = null;
        $this->setupBrokerDone = false;
    }

protected function close ( ) { if ( ! $ this -> context ) { return ; } $ this -> context -> close ( ) ; $ this -> context = null ; $ this -> setupBrokerDone = false ; }


public function validateNamespace($attribute)
    {
        $value = $this->$attribute;
        $value = ltrim($value, '\\');
        $path = Yii::getAlias('@' . str_replace('\\', '/', $value), false);
        if ($path === false) {
            $this->addError($attribute, 'Namespace must be associated with an existing directory.');
        }
    }

Validates the namespace.

@param string $attribute Namespace attribute name.


public function push($job)
    {
        $event = new PushEvent([
            'job' => $job,
            'ttr' => $this->pushTtr ?: (
                $job instanceof RetryableJobInterface
                    ? $job->getTtr()
                    : $this->ttr
            ),
            'delay' => $this->pushDelay ?: 0,
            'priority' => $this->pushPriority,
        ]);
        $this->pushTtr = null;
        $this->pushDelay = null;
        $this->pushPriority = null;

        $this->trigger(self::EVENT_BEFORE_PUSH, $event);
        if ($event->handled) {
            return null;
        }

        if ($this->strictJobType && !($event->job instanceof JobInterface)) {
            throw new InvalidArgumentException('Job must be instance of JobInterface.');
        }

        if (!is_numeric($event->ttr)) {
            throw new InvalidArgumentException('Job TTR must be integer.');
        }
        $event->ttr = (int) $event->ttr;
        if ($event->ttr <= 0) {
            throw new InvalidArgumentException('Job TTR must be greater that zero.');
        }

        if (!is_numeric($event->delay)) {
            throw new InvalidArgumentException('Job delay must be integer.');
        }
        $event->delay = (int) $event->delay;
        if ($event->delay < 0) {
            throw new InvalidArgumentException('Job delay must be positive.');
        }

        $message = $this->serializer->serialize($event->job);
        $event->id = $this->pushMessage($message, $event->ttr, $event->delay, $event->priority);
        $this->trigger(self::EVENT_AFTER_PUSH, $event);

        return $event->id;
    }

public
function
push
(
$
job
)
{
$
event
=
new
PushEvent
(
[
'job'
=>
$
job
,
'ttr'
=>
$
this
->
pushTtr
:
(
$
job
instanceof
RetryableJobInterface
$
job
->
getTtr
(
)
:
$
this
->
ttr
)
,
'delay'
=>
$
this
->
pushDelay
:
0
,
'priority'
=>
$
this
->
pushPriority
,
]
)
;
$
this
->
pushTtr
=
;
$
this
->
pushDelay
=
;
$
this
->
pushPriority
=
;
$
this
->
trigger
(
self
::
EVENT_BEFORE_PUSH
,
$
event
)
;
if
(
$
event
->
handled
)
{
return
;
}
if
(
$
this
->
strictJobType
&&
!
(
$
event
->
job
instanceof
JobInterface
)
)
{
throw
new
InvalidArgumentException
(
'Job must be instance of JobInterface.'
)
;
}
if
(
!
is_numeric
(
$
event
->
ttr
)
)
{
throw
new
InvalidArgumentException
(
'Job TTR must be integer.'
)
;
}
$
event
->
ttr
=
(
int
)
$
event
->
ttr
;
if
(
$
event
->
ttr
<=
0
)
{
throw
new
InvalidArgumentException
(
'Job TTR must be greater that zero.'
)
;
}
if
(
!
is_numeric
(
$
event
->
delay
)
)
{
throw
new
InvalidArgumentException
(
'Job delay must be integer.'
)
;
}
$
event
->
delay
=
(
int
)
$
event
->
delay
;
if
(
$
event
->
delay
<
0
)
{
throw
new
InvalidArgumentException
(
'Job delay must be positive.'
)
;
}
$
message
=
$
this
->
serializer
->
serialize
(
$
event
->
job
)
;
$
event
->
id
=
$
this
->
pushMessage
(
$
message
,
$
event
->
ttr
,
$
event
->
delay
,
$
event
->
priority
)
;
$
this
->
trigger
(
self
::
EVENT_AFTER_PUSH
,
$
event
)
;
return
$
event
->
id
;
}

Pushes job into queue.

@param JobInterface|mixed $job
@return string|null id of a job message


public function actionListen($timeout = 3)
    {
        if (!is_numeric($timeout)) {
            throw new Exception('Timeout must be numeric.');
        }
        if ($timeout < 1) {
            throw new Exception('Timeout must be greater than zero.');
        }

        return $this->queue->run(true, $timeout);
    }

public
function
actionListen
(
$
timeout
=
3
)
{
if
(
!
is_numeric
(
$
timeout
)
)
{
throw
new
Exception
(
'Timeout must be numeric.'
)
;
}
if
(
$
timeout
<
1
)
{
throw
new
Exception
(
'Timeout must be greater than zero.'
)
;
}
return
$
this
->
queue
->
run
(
true
,
$
timeout
)
;
}

Listens file-queue and runs new jobs.
It can be used as daemon process.

@param int $timeout number of seconds to sleep before next reading of the queue.
@throws Exception when params are invalid.
@return null|int exit code.

Listens file - queue and runs new jobs . It can be used as daemon process .


public function actionExec($id, $ttr, $attempt, $pid)
    {
        if ($this->queue->execute($id, file_get_contents('php://stdin'), $ttr, $attempt, $pid ?: null)) {
            return self::EXEC_DONE;
        }
        return self::EXEC_RETRY;
    }

public function actionExec ( $ id , $ ttr , $ attempt , $ pid ) { if ( $ this -> queue -> execute ( $ id , file_get_contents ( 'php://stdin' ) , $ ttr , $ attempt , $ pid ? : null ) ) { return self :: EXEC_DONE ; } return self :: EXEC_RETRY ; }

Executes a job.
The command is internal, and used to isolate a job execution. Manual usage is not provided.

@param string|null $id of a message
@param int $ttr time to reserve
@param int $attempt number
@param int $pid of a worker
@return int exit code
@internal It is used with isolate mode.

Executes a job . The command is internal and used to isolate a job execution . Manual usage is not provided .


protected function handleMessage($id, $message, $ttr, $attempt)
    {
        // Child process command: php yii queue/exec "id" "ttr" "attempt" "pid"
        $cmd = [
            $this->phpBinary,
            $_SERVER['SCRIPT_FILENAME'],
            $this->uniqueId . '/exec',
            $id,
            $ttr,
            $attempt,
            $this->queue->getWorkerPid() ?: 0,
        ];

        foreach ($this->getPassedOptions() as $name) {
            if (in_array($name, $this->options('exec'), true)) {
                $cmd[] = '--' . $name . '=' . $this->$name;
            }
        }
        if (!in_array('color', $this->getPassedOptions(), true)) {
            $cmd[] = '--color=' . $this->isColorEnabled();
        }

        $process = new Process($cmd, null, null, $message, $ttr);
        try {
            $result = $process->run(function ($type, $buffer) {
                if ($type === Process::ERR) {
                    $this->stderr($buffer);
                } else {
                    $this->stdout($buffer);
                }
            });
            if (!in_array($result, [self::EXEC_DONE, self::EXEC_RETRY])) {
                throw new ProcessFailedException($process);
            }
            return $result === self::EXEC_DONE;
        } catch (ProcessRuntimeException $error) {
            list($job) = $this->queue->unserializeMessage($message);
            return $this->queue->handleError(new ExecEvent([
                'id' => $id,
                'job' => $job,
                'ttr' => $ttr,
                'attempt' => $attempt,
                'error' => $error,
            ]));
        }
    }

Handles message using child process.

@param string|null $id of a message
@param string $message
@param int $ttr time to reserve
@param int $attempt number
@return bool
@throws
@see actionExec()


public function run()
    {
        while (($payload = array_shift($this->payloads)) !== null) {
            list($ttr, $message) = $payload;
            $this->startedId = $this->finishedId + 1;
            $this->handleMessage($this->startedId, $message, $ttr, 1);
            $this->finishedId = $this->startedId;
            $this->startedId = 0;
        }
    }

public function run ( ) { while ( ( $ payload = array_shift ( $ this -> payloads ) ) !== null ) { list ( $ ttr , $ message ) = $ payload ; $ this -> startedId = $ this -> finishedId + 1 ; $ this -> handleMessage ( $ this -> startedId , $ message , $ ttr , 1 ) ; $ this -> finishedId = $ this -> startedId ; $ this -> startedId = 0 ; } }


protected function reserve()
    {
        return $this->db->useMaster(function () {
            if (!$this->mutex->acquire(__CLASS__ . $this->channel, $this->mutexTimeout)) {
                throw new Exception('Has not waited the lock.');
            }

            try {
                $this->moveExpired();

                // Reserve one message
                $payload = (new Query())
                    ->from($this->tableName)
                    ->andWhere(['channel' => $this->channel, 'reserved_at' => null])
                    ->andWhere('[[pushed_at]] <= :time - [[delay]]', [':time' => time()])
                    ->orderBy(['priority' => SORT_ASC, 'id' => SORT_ASC])
                    ->limit(1)
                    ->one($this->db);
                if (is_array($payload)) {
                    $payload['reserved_at'] = time();
                    $payload['attempt'] = (int) $payload['attempt'] + 1;
                    $this->db->createCommand()->update($this->tableName, [
                        'reserved_at' => $payload['reserved_at'],
                        'attempt' => $payload['attempt'],
                    ], [
                        'id' => $payload['id'],
                    ])->execute();

                    // pgsql
                    if (is_resource($payload['job'])) {
                        $payload['job'] = stream_get_contents($payload['job']);
                    }
                }
            } finally {
                $this->mutex->release(__CLASS__ . $this->channel);
            }

            return $payload;
        });
    }

protected
function
reserve
(
)
{
return
$
this
->
db
->
useMaster
(
function
(
)
{
if
(
!
$
this
->
mutex
->
acquire
(
__CLASS__
.
$
this
->
channel
,
$
this
->
mutexTimeout
)
)
{
throw
new
Exception
(
'Has not waited the lock.'
)
;
}
try
{
$
this
->
moveExpired
(
)
;
// Reserve one message
$
payload
=
(
new
Query
(
)
)
->
from
(
$
this
->
tableName
)
->
andWhere
(
[
'channel'
=>
$
this
->
channel
,
'reserved_at'
=>
]
)
->
andWhere
(
'[[pushed_at]] <= :time - [[delay]]'
,
[
':time'
=>
time
(
)
]
)
->
orderBy
(
[
'priority'
=>
SORT_ASC
,
'id'
=>
SORT_ASC
]
)
->
limit
(
1
)
->
one
(
$
this
->
db
)
;
if
(
is_array
(
$
payload
)
)
{
$
payload
[
'reserved_at'
]
=
time
(
)
;
$
payload
[
'attempt'
]
=
(
int
)
$
payload
[
'attempt'
]
+
1
;
$
this
->
db
->
createCommand
(
)
->
update
(
$
this
->
tableName
,
[
'reserved_at'
=>
$
payload
[
'reserved_at'
]
,
'attempt'
=>
$
payload
[
'attempt'
]
,
]
,
[
'id'
=>
$
payload
[
'id'
]
,
]
)
->
execute
(
)
;
// pgsql
if
(
is_resource
(
$
payload
[
'job'
]
)
)
{
$
payload
[
'job'
]
=
stream_get_contents
(
$
payload
[
'job'
]
)
;
}
}
}
finally
{
$
this
->
mutex
->
release
(
__CLASS__
.
$
this
->
channel
)
;
}
return
$
payload
;
}
)
;
}

Takes one message from waiting list and reserves it for handling.

@return array|false payload
@throws Exception in case it hasn't waited the lock

Takes one message from waiting list and reserves it for handling .


private function moveExpired()
    {
        if ($this->reserveTime !== time()) {
            $this->reserveTime = time();
            $this->db->createCommand()->update(
                $this->tableName,
                ['reserved_at' => null],
                '[[reserved_at]] < :time - [[ttr]] and [[done_at]] is null',
                [':time' => $this->reserveTime]
            )->execute();
        }
    }

Moves expired messages into waiting list.

Moves expired messages into waiting list .


public function beforePush(PushEvent $event)
    {
        if ($event->job instanceof \Closure) {
            $serializer = new Serializer();
            $serialized = $serializer->serialize($event->job);
            $event->job = new Job();
            $event->job->serialized = $serialized;
        }
    }

public function beforePush ( PushEvent $ event ) { if ( $ event -> job instanceof \ Closure ) { $ serializer = new Serializer ( ) ; $ serialized = $ serializer -> serialize ( $ event -> job ) ; $ event -> job = new Job ( ) ; $ event -> job -> serialized = $ serialized ; } }

Converts the closure to a job object.
@param PushEvent $event


protected function delete($id)
    {
        $this->redis->zrem("$this->channel.reserved", $id);
        $this->redis->hdel("$this->channel.attempts", $id);
        $this->redis->hdel("$this->channel.messages", $id);
    }

protected function delete ( $ id ) { $ this -> redis -> zrem ( "$this->channel.reserved" , $ id ) ; $ this -> redis -> hdel ( "$this->channel.attempts" , $ id ) ; $ this -> redis -> hdel ( "$this->channel.messages" , $ id ) ; }

Deletes message by ID.

@param int $id of a message


protected function runWorker(callable $handler)
    {
        $this->_workerPid = getmypid();
        /** @var LoopInterface $loop */
        $loop = Yii::createObject($this->loopConfig, [$this]);

        $event = new WorkerEvent(['loop' => $loop]);
        $this->trigger(self::EVENT_WORKER_START, $event);
        if ($event->exitCode !== null) {
            return $event->exitCode;
        }

        $exitCode = null;
        try {
            call_user_func($handler, function () use ($loop, $event) {
                $this->trigger(self::EVENT_WORKER_LOOP, $event);
                return $event->exitCode === null && $loop->canContinue();
            });
        } finally {
            $this->trigger(self::EVENT_WORKER_STOP, $event);
            $this->_workerPid = null;
        }

        return $event->exitCode;
    }

protected
function
runWorker
(
callable
$
handler
)
{
$
this
->
_workerPid
=
getmypid
(
)
;
/** @var LoopInterface $loop */
$
loop
=
Yii
::
createObject
(
$
this
->
loopConfig
,
[
$
this
]
)
;
$
event
=
new
WorkerEvent
(
[
'loop'
=>
$
loop
]
)
;
$
this
->
trigger
(
self
::
EVENT_WORKER_START
,
$
event
)
;
if
(
$
event
->
exitCode
!==
)
{
return
$
event
->
exitCode
;
}
$
exitCode
=
;
try
{
call_user_func
(
$
handler
,
function
(
)
use
(
$
loop
,
$
event
)
{
$
this
->
trigger
(
self
::
EVENT_WORKER_LOOP
,
$
event
)
;
return
$
event
->
exitCode
===
&&
$
loop
->
canContinue
(
)
;
}
)
;
}
finally
{
$
this
->
trigger
(
self
::
EVENT_WORKER_STOP
,
$
event
)
;
$
this
->
_workerPid
=
;
}
return
$
event
->
exitCode
;
}

Runs worker.

@param callable $handler
@return null|int exit code
@since 2.0.2


public function handle($id, $message, $ttr, $attempt)
    {
        return $this->handleMessage($id, $message, $ttr, $attempt);
    }

public function handle ( $ id , $ message , $ ttr , $ attempt ) { return $ this -> handleMessage ( $ id , $ message , $ ttr , $ attempt ) ; }

Provides public access for `handleMessage`

@param $id string
@param $message string
@param $ttr int
@param $attempt int
@return bool
@since 2.0.2

Provides public access for handleMessage


public function init()
    {
        parent::init();
        if (extension_loaded('pcntl')) {
            foreach ($this->exitSignals as $signal) {
                pcntl_signal($signal, function () {
                    self::$exit = true;
                });
            }
            foreach ($this->suspendSignals as $signal) {
                pcntl_signal($signal, function () {
                    self::$pause = true;
                });
            }
            foreach ($this->resumeSignals as $signal) {
                pcntl_signal($signal, function () {
                    self::$pause = false;
                });
            }
        }
    }

public function init ( ) { parent :: init ( ) ; if ( extension_loaded ( 'pcntl' ) ) { foreach ( $ this -> exitSignals as $ signal ) { pcntl_signal ( $ signal , function ( ) { self :: $ exit = true ; } ) ; } foreach ( $ this -> suspendSignals as $ signal ) { pcntl_signal ( $ signal , function ( ) { self :: $ pause = true ; } ) ; } foreach ( $ this -> resumeSignals as $ signal ) { pcntl_signal ( $ signal , function ( ) { self :: $ pause = false ; } ) ; } } }


public function canContinue()
    {
        if (extension_loaded('pcntl')) {
            pcntl_signal_dispatch();
            // Wait for resume signal until loop is suspended
            while (self::$pause && !self::$exit) {
                usleep(10000);
                pcntl_signal_dispatch();
            }
        }

        return !self::$exit;
    }


protected function reserve()
    {
        $id = null;
        $ttr = null;
        $attempt = null;
        $this->touchIndex(function (&$data) use (&$id, &$ttr, &$attempt) {
            if (!empty($data['reserved'])) {
                foreach ($data['reserved'] as $key => $payload) {
                    if ($payload[1] + $payload[3] < time()) {
                        list($id, $ttr, $attempt, $time) = $payload;
                        $data['reserved'][$key][2] = ++$attempt;
                        $data['reserved'][$key][3] = time();
                        return;
                    }
                }
            }

            if (!empty($data['delayed']) && $data['delayed'][0][2] <= time()) {
                list($id, $ttr, $time) = array_shift($data['delayed']);
            } elseif (!empty($data['waiting'])) {
                list($id, $ttr) = array_shift($data['waiting']);
            }
            if ($id) {
                $attempt = 1;
                $data['reserved']["job$id"] = [$id, $ttr, $attempt, time()];
            }
        });

        if ($id) {
            return [$id, file_get_contents("$this->path/job$id.data"), $ttr, $attempt];
        }

        return null;
    }

protected function reserve ( ) { $ id = null ; $ ttr = null ; $ attempt = null ; $ this -> touchIndex ( function ( & $ data ) use ( & $ id , & $ ttr , & $ attempt ) { if ( ! empty ( $ data [ 'reserved' ] ) ) { foreach ( $ data [ 'reserved' ] as $ key => $ payload ) { if ( $ payload [ 1 ] + $ payload [ 3 ] < time ( ) ) { list ( $ id , $ ttr , $ attempt , $ time ) = $ payload ; $ data [ 'reserved' ] [ $ key ] [ 2 ] = ++ $ attempt ; $ data [ 'reserved' ] [ $ key ] [ 3 ] = time ( ) ; return ; } } } if ( ! empty ( $ data [ 'delayed' ] ) && $ data [ 'delayed' ] [ 0 ] [ 2 ] <= time ( ) ) { list ( $ id , $ ttr , $ time ) = array_shift ( $ data [ 'delayed' ] ) ; } elseif ( ! empty ( $ data [ 'waiting' ] ) ) { list ( $ id , $ ttr ) = array_shift ( $ data [ 'waiting' ] ) ; } if ( $ id ) { $ attempt = 1 ; $ data [ 'reserved' ] [ "job$id" ] = [ $ id , $ ttr , $ attempt , time ( ) ] ; } } ) ; if ( $ id ) { return [ $ id , file_get_contents ( "$this->path/job$id.data" ) , $ ttr , $ attempt ] ; } return null ; }

Reserves message for execute.

@return array|null payload


protected function delete($payload)
    {
        $id = $payload[0];
        $this->touchIndex(function (&$data) use ($id) {
            foreach ($data['reserved'] as $key => $payload) {
                if ($payload[0] === $id) {
                    unset($data['reserved'][$key]);
                    break;
                }
            }
        });
        unlink("$this->path/job$id.data");
    }

protected function delete ( $ payload ) { $ id = $ payload [ 0 ] ; $ this -> touchIndex ( function ( & $ data ) use ( $ id ) { foreach ( $ data [ 'reserved' ] as $ key => $ payload ) { if ( $ payload [ 0 ] === $ id ) { unset ( $ data [ 'reserved' ] [ $ key ] ) ; break ; } } } ) ; unlink ( "$this->path/job$id.data" ) ; }

Deletes reserved message.

@param array $payload


public function parse(): array
    {
        $previousEntityState = libxml_disable_entity_loader(true);
        $previousSetting = libxml_use_internal_errors(true);

        try {
            while (self::ELEMENT !== $this->nodeType) {
                if (!$this->read()) {
                    $errors = libxml_get_errors();
                    libxml_clear_errors();
                    if ($errors) {
                        throw new LibXMLException($errors);
                    }
                }
            }
            $result = $this->parseCurrentElement();

            // last line of defense in case errors did occur above
            $errors = libxml_get_errors();
            libxml_clear_errors();
            if ($errors) {
                throw new LibXMLException($errors);
            }
        } finally {
            libxml_use_internal_errors($previousSetting);
            libxml_disable_entity_loader($previousEntityState);
        }

        return $result;
    }

Reads the entire document.

This function returns an array with the following three elements:
* name - The root element name.
* value - The value for the root element.
* attributes - An array of attributes.

This function will also disable the standard libxml error handler (which
usually just results in PHP errors), and throw exceptions instead.


public function parseGetElements(array $elementMap = null): array
    {
        $result = $this->parseInnerTree($elementMap);
        if (!is_array($result)) {
            return [];
        }

        return $result;
    }

public function parseGetElements ( array $ elementMap = null ) : array { $ result = $ this -> parseInnerTree ( $ elementMap ) ; if ( ! is_array ( $ result ) ) { return [ ] ; } return $ result ; }

parseGetElements parses everything in the current sub-tree,
and returns a an array of elements.

Each element has a 'name', 'value' and 'attributes' key.

If the the element didn't contain sub-elements, an empty array is always
returned. If there was any text inside the element, it will be
discarded.

If the $elementMap argument is specified, the existing elementMap will
be overridden while parsing the tree, and restored after this process.

parseGetElements parses everything in the current sub - tree and returns a an array of elements .


public function parseInnerTree(array $elementMap = null)
    {
        $text = null;
        $elements = [];

        if (self::ELEMENT === $this->nodeType && $this->isEmptyElement) {
            // Easy!
            $this->next();

            return null;
        }

        if (!is_null($elementMap)) {
            $this->pushContext();
            $this->elementMap = $elementMap;
        }

        try {
            if (!$this->read()) {
                $errors = libxml_get_errors();
                libxml_clear_errors();
                if ($errors) {
                    throw new LibXMLException($errors);
                }
                throw new ParseException('This should never happen (famous last words)');
            }

            while (true) {
                if (!$this->isValid()) {
                    $errors = libxml_get_errors();

                    if ($errors) {
                        libxml_clear_errors();
                        throw new LibXMLException($errors);
                    }
                }

                switch ($this->nodeType) {
                    case self::ELEMENT:
                        $elements[] = $this->parseCurrentElement();
                        break;
                    case self::TEXT:
                    case self::CDATA:
                        $text .= $this->value;
                        $this->read();
                        break;
                    case self::END_ELEMENT:
                        // Ensuring we are moving the cursor after the end element.
                        $this->read();
                        break 2;
                    case self::NONE:
                        throw new ParseException('We hit the end of the document prematurely. This likely means that some parser "eats" too many elements. Do not attempt to continue parsing.');
                    default:
                        // Advance to the next element
                        $this->read();
                        break;
                }
            }
        } finally {
            if (!is_null($elementMap)) {
                $this->popContext();
            }
        }

        return $elements ? $elements : $text;
    }

Parses all elements below the current element.

This method will return a string if this was a text-node, or an array if
there were sub-elements.

If there's both text and sub-elements, the text will be discarded.

If the $elementMap argument is specified, the existing elementMap will
be overridden while parsing the tree, and restored after this process.

@return array|string|null

Parses all elements below the current element .


public function readText(): string
    {
        $result = '';
        $previousDepth = $this->depth;

        while ($this->read() && $this->depth != $previousDepth) {
            if (in_array($this->nodeType, [XMLReader::TEXT, XMLReader::CDATA, XMLReader::WHITESPACE])) {
                $result .= $this->value;
            }
        }

        return $result;
    }

public function readText ( ) : string { $ result = '' ; $ previousDepth = $ this -> depth ; while ( $ this -> read ( ) && $ this -> depth != $ previousDepth ) { if ( in_array ( $ this -> nodeType , [ XMLReader :: TEXT , XMLReader :: CDATA , XMLReader :: WHITESPACE ] ) ) { $ result .= $ this -> value ; } } return $ result ; }

Reads all text below the current element, and returns this as a string.

Reads all text below the current element and returns this as a string .


public function parseCurrentElement(): array
    {
        $name = $this->getClark();

        $attributes = [];

        if ($this->hasAttributes) {
            $attributes = $this->parseAttributes();
        }

        $value = call_user_func(
            $this->getDeserializerForElementName((string) $name),
            $this
        );

        return [
            'name' => $name,
            'value' => $value,
            'attributes' => $attributes,
        ];
    }

public function parseCurrentElement ( ) : array { $ name = $ this -> getClark ( ) ; $ attributes = [ ] ; if ( $ this -> hasAttributes ) { $ attributes = $ this -> parseAttributes ( ) ; } $ value = call_user_func ( $ this -> getDeserializerForElementName ( ( string ) $ name ) , $ this ) ; return [ 'name' => $ name , 'value' => $ value , 'attributes' => $ attributes , ] ; }

Parses the current XML element.

This method returns arn array with 3 properties:
* name - A clark-notation XML element name.
* value - The parsed value.
* attributes - A key-value list of attributes.


public function parseAttributes(): array
    {
        $attributes = [];

        while ($this->moveToNextAttribute()) {
            if ($this->namespaceURI) {
                // Ignoring 'xmlns', it doesn't make any sense.
                if ('http://www.w3.org/2000/xmlns/' === $this->namespaceURI) {
                    continue;
                }

                $name = $this->getClark();
                $attributes[$name] = $this->value;
            } else {
                $attributes[$this->localName] = $this->value;
            }
        }
        $this->moveToElement();

        return $attributes;
    }

Grabs all the attributes from the current element, and returns them as a
key-value array.

If the attributes are part of the same namespace, they will simply be
short keys. If they are defined on a different namespace, the attribute
name will be retured in clark-notation.

Grabs all the attributes from the current element and returns them as a key - value array .


public function getDeserializerForElementName(string $name): callable
    {
        if (!array_key_exists($name, $this->elementMap)) {
            if ('{}' == substr($name, 0, 2) && array_key_exists(substr($name, 2), $this->elementMap)) {
                $name = substr($name, 2);
            } else {
                return ['Sabre\\Xml\\Element\\Base', 'xmlDeserialize'];
            }
        }

        $deserializer = $this->elementMap[$name];
        if (is_subclass_of($deserializer, 'Sabre\\Xml\\XmlDeserializable')) {
            return [$deserializer, 'xmlDeserialize'];
        }

        if (is_callable($deserializer)) {
            return $deserializer;
        }

        $type = gettype($deserializer);
        if ('string' === $type) {
            $type .= ' ('.$deserializer.')';
        } elseif ('object' === $type) {
            $type .= ' ('.get_class($deserializer).')';
        }
        throw new \LogicException('Could not use this type as a deserializer: '.$type.' for element: '.$name);
    }

Returns the function that should be used to parse the element identified
by it's clark-notation name.

Returns the function that should be used to parse the element identified by it s clark - notation name .


public function pushContext()
    {
        $this->contextStack[] = [
            $this->elementMap,
            $this->contextUri,
            $this->namespaceMap,
            $this->classMap,
        ];
    }

public function pushContext ( ) { $ this -> contextStack [ ] = [ $ this -> elementMap , $ this -> contextUri , $ this -> namespaceMap , $ this -> classMap , ] ; }

Create a new "context".

This allows you to safely modify the elementMap, contextUri or
namespaceMap. After you're done, you can restore the old data again
with popContext.


public function popContext()
    {
        list(
            $this->elementMap,
            $this->contextUri,
            $this->namespaceMap,
            $this->classMap
        ) = array_pop($this->contextStack);
    }

public function popContext ( ) { list ( $ this -> elementMap , $ this -> contextUri , $ this -> namespaceMap , $ this -> classMap ) = array_pop ( $ this -> contextStack ) ; }


public function getWriter(): Writer
    {
        $w = new Writer();
        $w->namespaceMap = $this->namespaceMap;
        $w->classMap = $this->classMap;

        return $w;
    }

public function getWriter ( ) : Writer { $ w = new Writer ( ) ; $ w -> namespaceMap = $ this -> namespaceMap ; $ w -> classMap = $ this -> classMap ; return $ w ; }


public function parse($input, string $contextUri = null, string &$rootElementName = null)
    {
        if (is_resource($input)) {
            // Unfortunately the XMLReader doesn't support streams. When it
            // does, we can optimize this.
            $input = (string) stream_get_contents($input);
        }
        $r = $this->getReader();
        $r->contextUri = $contextUri;
        $r->XML($input, null, $this->options);

        $result = $r->parse();
        $rootElementName = $result['name'];

        return $result['value'];
    }

Parses a document in full.

Input may be specified as a string or readable stream resource.
The returned value is the value of the root document.

Specifying the $contextUri allows the parser to figure out what the URI
of the document was. This allows relative URIs within the document to be
expanded easily.

The $rootElementName is specified by reference and will be populated
with the root element name of the document.

@param string|resource $input

@throws ParseException

@return array|object|string


public function expect($rootElementName, $input, string $contextUri = null)
    {
        if (is_resource($input)) {
            // Unfortunately the XMLReader doesn't support streams. When it
            // does, we can optimize this.
            $input = (string) stream_get_contents($input);
        }
        $r = $this->getReader();
        $r->contextUri = $contextUri;
        $r->XML($input, null, $this->options);

        $rootElementName = (array) $rootElementName;

        foreach ($rootElementName as &$rEl) {
            if ('{' !== $rEl[0]) {
                $rEl = '{}'.$rEl;
            }
        }

        $result = $r->parse();
        if (!in_array($result['name'], $rootElementName, true)) {
            throw new ParseException('Expected '.implode(' or ', $rootElementName).' but received '.$result['name'].' as the root element');
        }

        return $result['value'];
    }

Parses a document in full, and specify what the expected root element
name is.

This function works similar to parse, but the difference is that the
user can specify what the expected name of the root element should be,
in clark notation.

This is useful in cases where you expected a specific document to be
passed, and reduces the amount of if statements.

It's also possible to pass an array of expected rootElements if your
code may expect more than one document type.

@param string|string[] $rootElementName
@param string|resource $input
@param string|null     $contextUri

@throws ParseException

@return array|object|string

Parses a document in full and specify what the expected root element name is .


public function write(string $rootElementName, $value, string $contextUri = null)
    {
        $w = $this->getWriter();
        $w->openMemory();
        $w->contextUri = $contextUri;
        $w->setIndent(true);
        $w->startDocument();
        $w->writeElement($rootElementName, $value);

        return $w->outputMemory();
    }

public function write ( string $ rootElementName , $ value , string $ contextUri = null ) { $ w = $ this -> getWriter ( ) ; $ w -> openMemory ( ) ; $ w -> contextUri = $ contextUri ; $ w -> setIndent ( true ) ; $ w -> startDocument ( ) ; $ w -> writeElement ( $ rootElementName , $ value ) ; return $ w -> outputMemory ( ) ; }

Generates an XML document in one go.

The $rootElement must be specified in clark notation.
The value must be a string, an array or an object implementing
XmlSerializable. Basically, anything that's supported by the Writer
object.

$contextUri can be used to specify a sort of 'root' of the PHP application,
in case the xml document is used as a http response.

This allows an implementor to easily create URI's relative to the root
of the domain.

@param string|array|object|XmlSerializable $value

@return string


public function mapValueObject(string $elementName, string $className)
    {
        list($namespace) = self::parseClarkNotation($elementName);

        $this->elementMap[$elementName] = function (Reader $reader) use ($className, $namespace) {
            return \Sabre\Xml\Deserializer\valueObject($reader, $className, $namespace);
        };
        $this->classMap[$className] = function (Writer $writer, $valueObject) use ($namespace) {
            return \Sabre\Xml\Serializer\valueObject($writer, $valueObject, $namespace);
        };
        $this->valueObjectMap[$className] = $elementName;
    }

public function mapValueObject ( string $ elementName , string $ className ) { list ( $ namespace ) = self :: parseClarkNotation ( $ elementName ) ; $ this -> elementMap [ $ elementName ] = function ( Reader $ reader ) use ( $ className , $ namespace ) { return \ Sabre \ Xml \ Deserializer \ valueObject ( $ reader , $ className , $ namespace ) ; } ; $ this -> classMap [ $ className ] = function ( Writer $ writer , $ valueObject ) use ( $ namespace ) { return \ Sabre \ Xml \ Serializer \ valueObject ( $ writer , $ valueObject , $ namespace ) ; } ; $ this -> valueObjectMap [ $ className ] = $ elementName ; }

Map an xml element to a PHP class.

Calling this function will automatically setup the Reader and Writer
classes to turn a specific XML element to a PHP class.

For example, given a class such as :

class Author {
public $firstName;
public $lastName;
}

and an XML element such as:

<author xmlns="http://example.org/ns">
<firstName>...</firstName>
<lastName>...</lastName>
</author>

These can easily be mapped by calling:

$service->mapValueObject('{http://example.org}author', 'Author');


public function writeValueObject($object, string $contextUri = null)
    {
        if (!isset($this->valueObjectMap[get_class($object)])) {
            throw new \InvalidArgumentException('"'.get_class($object).'" is not a registered value object class. Register your class with mapValueObject.');
        }

        return $this->write(
            $this->valueObjectMap[get_class($object)],
            $object,
            $contextUri
        );
    }

Writes a value object.

This function largely behaves similar to write(), except that it's
intended specifically to serialize a Value Object into an XML document.

The ValueObject must have been previously registered using
mapValueObject().

@param object $object

@throws \InvalidArgumentException


public static function parseClarkNotation(string $str): array
    {
        static $cache = [];

        if (!isset($cache[$str])) {
            if (!preg_match('/^{([^}]*)}(.*)$/', $str, $matches)) {
                throw new \InvalidArgumentException('\''.$str.'\' is not a valid clark-notation formatted string');
            }

            $cache[$str] = [
                $matches[1],
                $matches[2],
            ];
        }

        return $cache[$str];
    }

Parses a clark-notation string, and returns the namespace and element
name components.

If the string was invalid, it will throw an InvalidArgumentException.

@throws \InvalidArgumentException

Parses a clark - notation string and returns the namespace and element name components .


public static function xmlDeserialize(Reader $reader)
    {
        $result = new self($reader->readInnerXml());
        $reader->next();

        return $result;
    }

public static function xmlDeserialize ( Reader $ reader ) { $ result = new self ( $ reader -> readInnerXml ( ) ) ; $ reader -> next ( ) ; return $ result ; }

The deserialize method is called during xml parsing.

This method is called statictly, this is because in theory this method
may be used as a type of constructor, or factory method.

Often you want to return an instance of the current class, but you are
free to return other data as well.

You are responsible for advancing the reader to the next element. Not
doing anything will result in a never-ending loop.

If you just want to skip parsing for this element altogether, you can
just call $reader->next();

$reader->parseInnerTree() will parse the entire sub-tree, and advance to
the next element.

@return mixed

The deserialize method is called during xml parsing .


public static function xmlDeserialize(Xml\Reader $reader)
    {
        return new self(
            \Sabre\Uri\resolve(
                (string) $reader->contextUri,
                $reader->readText()
            )
        );
    }

public static function xmlDeserialize ( Xml \ Reader $ reader ) { return new self ( \ Sabre \ Uri \ resolve ( ( string ) $ reader -> contextUri , $ reader -> readText ( ) ) ) ; }

This method is called during xml parsing.

This method is called statically, this is because in theory this method
may be used as a type of constructor, or factory method.

Often you want to return an instance of the current class, but you are
free to return other data as well.

Important note 2: You are responsible for advancing the reader to the
next element. Not doing anything will result in a never-ending loop.

If you just want to skip parsing for this element altogether, you can
just call $reader->next();

$reader->parseSubTree() will parse the entire sub-tree, and advance to
the next element.

@return mixed

This method is called during xml parsing .


public function startElement($name): bool
    {
        if ('{' === $name[0]) {
            list($namespace, $localName) =
                Service::parseClarkNotation($name);

            if (array_key_exists($namespace, $this->namespaceMap)) {
                $result = $this->startElementNS(
                    '' === $this->namespaceMap[$namespace] ? null : $this->namespaceMap[$namespace],
                    $localName,
                    null
                );
            } else {
                // An empty namespace means it's the global namespace. This is
                // allowed, but it mustn't get a prefix.
                if ('' === $namespace || null === $namespace) {
                    $result = $this->startElement($localName);
                    $this->writeAttribute('xmlns', '');
                } else {
                    if (!isset($this->adhocNamespaces[$namespace])) {
                        $this->adhocNamespaces[$namespace] = 'x'.(count($this->adhocNamespaces) + 1);
                    }
                    $result = $this->startElementNS($this->adhocNamespaces[$namespace], $localName, $namespace);
                }
            }
        } else {
            $result = parent::startElement($name);
        }

        if (!$this->namespacesWritten) {
            foreach ($this->namespaceMap as $namespace => $prefix) {
                $this->writeAttribute(($prefix ? 'xmlns:'.$prefix : 'xmlns'), $namespace);
            }
            $this->namespacesWritten = true;
        }

        return $result;
    }

Opens a new element.

You can either just use a local elementname, or you can use clark-
notation to start a new element.

Example:

$writer->startElement('{http://www.w3.org/2005/Atom}entry');

Would result in something like:

<entry xmlns="http://w3.org/2005/Atom">

Note: this function doesn't have the string typehint, because PHP's
XMLWriter::startElement doesn't either.

@param string $name


public function writeElement($name, $content = null): bool
    {
        $this->startElement($name);
        if (!is_null($content)) {
            $this->write($content);
        }
        $this->endElement();

        return true;
    }

public function writeElement ( $ name , $ content = null ) : bool { $ this -> startElement ( $ name ) ; if ( ! is_null ( $ content ) ) { $ this -> write ( $ content ) ; } $ this -> endElement ( ) ; return true ; }

Write a full element tag and it's contents.

This method automatically closes the element as well.

The element name may be specified in clark-notation.

Examples:

$writer->writeElement('{http://www.w3.org/2005/Atom}author',null);
becomes:
<author xmlns="http://www.w3.org/2005" />

$writer->writeElement('{http://www.w3.org/2005/Atom}author', [
'{http://www.w3.org/2005/Atom}name' => 'Evert Pot',
]);
becomes:
<author xmlns="http://www.w3.org/2005" /><name>Evert Pot</name></author>

Note: this function doesn't have the string typehint, because PHP's
XMLWriter::startElement doesn't either.

@param array|string|object|null $content

@return bool

Write a full element tag and it s contents .


public function writeAttributes(array $attributes)
    {
        foreach ($attributes as $name => $value) {
            $this->writeAttribute($name, $value);
        }
    }

public function writeAttributes ( array $ attributes ) { foreach ( $ attributes as $ name => $ value ) { $ this -> writeAttribute ( $ name , $ value ) ; } }

Writes a list of attributes.

Attributes are specified as a key->value array.

The key is an attribute name. If the key is a 'localName', the current
xml namespace is assumed. If it's a 'clark notation key', this namespace
will be used instead.


public function writeAttribute($name, $value): bool
    {
        if ('{' !== $name[0]) {
            return parent::writeAttribute($name, $value);
        }

        list(
            $namespace,
            $localName
        ) = Service::parseClarkNotation($name);

        if (array_key_exists($namespace, $this->namespaceMap)) {
            // It's an attribute with a namespace we know
            return $this->writeAttribute(
                $this->namespaceMap[$namespace].':'.$localName,
                $value
            );
        }

        // We don't know the namespace, we must add it in-line
        if (!isset($this->adhocNamespaces[$namespace])) {
            $this->adhocNamespaces[$namespace] = 'x'.(count($this->adhocNamespaces) + 1);
        }

        return $this->writeAttributeNS(
            $this->adhocNamespaces[$namespace],
            $localName,
            $namespace,
            $value
        );
    }

Writes a new attribute.

The name may be specified in clark-notation.

Returns true when successful.

Note: this function doesn't have typehints, because for some reason
PHP's XMLWriter::writeAttribute doesn't either.

@param string $name
@param string $value


public function getModelRelations(string $model)
    {
        $class = new ReflectionClass($model);

        $traitMethods = Collection::make($class->getTraits())->map(function (ReflectionClass $trait) {
            return Collection::make($trait->getMethods(ReflectionMethod::IS_PUBLIC));
        })->flatten();

        $methods = Collection::make($class->getMethods(ReflectionMethod::IS_PUBLIC))
            ->merge($traitMethods)
            ->reject(function (ReflectionMethod $method) use ($model) {
                return $method->class !== $model || $method->getNumberOfParameters() > 0;
            });

        $relations = Collection::make();

        $methods->map(function (ReflectionMethod $method) use ($model, &$relations) {
            $relations = $relations->merge($this->getRelationshipFromMethodAndModel($method, $model));
        });

        $relations = $relations->filter();

        if ($ignoreRelations = array_get(config('erd-generator.ignore', []),$model))
        {
            $relations = $relations->diffKeys(array_flip($ignoreRelations));
        }

        return $relations;
    }

public function getModelRelations ( string $ model ) { $ class = new ReflectionClass ( $ model ) ; $ traitMethods = Collection :: make ( $ class -> getTraits ( ) ) -> map ( function ( ReflectionClass $ trait ) { return Collection :: make ( $ trait -> getMethods ( ReflectionMethod :: IS_PUBLIC ) ) ; } ) -> flatten ( ) ; $ methods = Collection :: make ( $ class -> getMethods ( ReflectionMethod :: IS_PUBLIC ) ) -> merge ( $ traitMethods ) -> reject ( function ( ReflectionMethod $ method ) use ( $ model ) { return $ method -> class !== $ model || $ method -> getNumberOfParameters ( ) > 0 ; } ) ; $ relations = Collection :: make ( ) ; $ methods -> map ( function ( ReflectionMethod $ method ) use ( $ model , & $ relations ) { $ relations = $ relations -> merge ( $ this -> getRelationshipFromMethodAndModel ( $ method , $ model ) ) ; } ) ; $ relations = $ relations -> filter ( ) ; if ( $ ignoreRelations = array_get ( config ( 'erd-generator.ignore' , [ ] ) , $ model ) ) { $ relations = $ relations -> diffKeys ( array_flip ( $ ignoreRelations ) ) ; } return $ relations ; }

Return all relations from a fully qualified model class name.

@param string $model
@return Collection
@throws \ReflectionException

Return all relations from a fully qualified model class name .


protected function validateJobName($name)
    {
        if (!$name || strlen($name) == 0) {
            throw new \InvalidArgumentException('Please set a name.');
        }

        if ($this->queryJob($name)) {
            throw new \InvalidArgumentException('Name already in use.');
        }

        return $name;
    }

protected
function
validateJobName
(
$
name
)
{
if
(
!
$
name
||
strlen
(
$
name
)
==
0
)
{
throw
new
\
InvalidArgumentException
(
'Please set a name.'
)
;
}
if
(
$
this
->
queryJob
(
$
name
)
)
{
throw
new
\
InvalidArgumentException
(
'Name already in use.'
)
;
}
return
$
name
;
}

Validate the job name.

@param  string                    $name
@return string
@throws \InvalidArgumentException


protected function validateCommand($command)
    {
        $parts = explode(' ', $command);
        $this->getApplication()->get((string) $parts[0]);

        return $command;
    }

protected
function
validateCommand
(
$
command
)
{
$
parts
=
explode
(
' '
,
$
command
)
;
$
this
->
getApplication
(
)
->
get
(
(
string
)
$
parts
[
0
]
)
;
return
$
command
;
}

Validate the command.

@param  string                    $command
@return string
@throws \InvalidArgumentException


protected function createJob(CronJob $dbJob)
    {
        $job = new ShellJob();
        $job->setCommand($this->commandBuilder->build($dbJob->getCommand()), $this->rootDir);
        $job->setSchedule(new CrontabSchedule($dbJob->getSchedule()));
        $job->raw = $dbJob;

        return $job;
    }

protected function createJob ( CronJob $ dbJob ) { $ job = new ShellJob ( ) ; $ job -> setCommand ( $ this -> commandBuilder -> build ( $ dbJob -> getCommand ( ) ) , $ this -> rootDir ) ; $ job -> setSchedule ( new CrontabSchedule ( $ dbJob -> getSchedule ( ) ) ) ; $ job -> raw = $ dbJob ; return $ job ; }

Transform a CronJon into a ShellJob.

@param  CronJob  $dbJob
@return ShellJob


public function createScopeAndRetrieveItsCloser(?TraceContext $currentContext = null): callable
    {
        $previous = $this->context;
        $self = $this;
        $this->context = $currentContext;

        return function () use ($previous, $self) {
            $self->context = $previous;
        };
    }

public function createScopeAndRetrieveItsCloser ( ? TraceContext $ currentContext = null ) : callable { $ previous = $ this -> context ; $ self = $ this ; $ this -> context = $ currentContext ; return function ( ) use ( $ previous , $ self ) { $ self -> context = $ previous ; } ; }

Sets the current span in scope until the returned callable is called. It is a programming
error to drop or never close the result.

@param TraceContext|null $currentContext
@return callable The scope closed

Sets the current span in scope until the returned callable is called . It is a programming error to drop or never close the result .


public function finish(?int $finishTimestamp = null): void
    {
        if ($this->finished) {
            return;
        }

        if ($this->timestamp !== null && $finishTimestamp !== null) {
            $this->duration = $finishTimestamp - $this->timestamp;
        }

        $this->finished = true;
    }

public function finish ( ? int $ finishTimestamp = null ) : void { if ( $ this -> finished ) { return ; } if ( $ this -> timestamp !== null && $ finishTimestamp !== null ) { $ this -> duration = $ finishTimestamp - $ this -> timestamp ; } $ this -> finished = true ; }

Completes and reports the span

@param int|null $finishTimestamp


public function getCurrentSpan(): ?Span
    {
        $currentContext = $this->currentTraceContext->getContext();
        return $currentContext === null ? null : $this->toSpan($currentContext);
    }

public function getCurrentSpan ( ) : ? Span { $ currentContext = $ this -> currentTraceContext -> getContext ( ) ; return $ currentContext === null ? null : $ this -> toSpan ( $ currentContext ) ; }

Returns the current span in scope or null if there isn't one.

@return Span|null

Returns the current span in scope or null if there isn t one .


private function toSpan(TraceContext $context): Span
    {
        if (!$this->isNoop && $context->isSampled()) {
            return RealSpan::create($context, $this->recorder);
        }

        return NoopSpan::create($context);
    }

private function toSpan ( TraceContext $ context ) : Span { if ( ! $ this -> isNoop && $ context -> isSampled ( ) ) { return RealSpan :: create ( $ context , $ this -> recorder ) ; } return NoopSpan :: create ( $ context ) ; }

Converts the context as-is to a Span object

@param TraceContext $context
@return Span

Converts the context as - is to a Span object


public function start(?int $timestamp = null): void
    {
        if ($timestamp === null) {
            $timestamp = now();
        } else {
            if (!isValid($timestamp)) {
                throw new InvalidArgumentException(
                    sprintf('Invalid timestamp. Expected int, got %s', $timestamp)
                );
            }
        }

        $this->recorder->start($this->traceContext, $timestamp);
    }

Starts the span with an implicit timestamp.

Spans can be modified before calling start. For example, you can add tags to the span and
set its name without lock contention.

@param int $timestamp
@return void
@throws \InvalidArgumentException

Starts the span with an implicit timestamp .


public function setName(string $name): void
    {
        $this->recorder->setName($this->traceContext, $name);
    }

public function setName ( string $ name ) : void { $ this -> recorder -> setName ( $ this -> traceContext , $ name ) ; }

Sets the string name for the logical operation this span represents.

@param string $name
@return void

Sets the string name for the logical operation this span represents .


public function annotate(string $value, ?int $timestamp = null): void
    {
        if (!isValid($timestamp)) {
            throw new InvalidArgumentException(
                sprintf('Valid timestamp represented microtime expected, got \'%s\'', $timestamp)
            );
        }

        $this->recorder->annotate($this->traceContext, $timestamp, $value);
    }

Associates an event that explains latency with the current system time.

@param string $value A short tag indicating the event, like "finagle.retry"
@param int|null $timestamp
@return void
@throws \InvalidArgumentException
@see Zipkin\Annotations

Associates an event that explains latency with the current system time .


public function setRemoteEndpoint(Endpoint $remoteEndpoint): void
    {
        $this->recorder->setRemoteEndpoint($this->traceContext, $remoteEndpoint);
    }

public function setRemoteEndpoint ( Endpoint $ remoteEndpoint ) : void { $ this -> recorder -> setRemoteEndpoint ( $ this -> traceContext , $ remoteEndpoint ) ; }

For a client span, this would be the server's address.

It is often expensive to derive a remote address: always check {@link #isNoop()} first!

@param Endpoint $remoteEndpoint
@return void

For a client span this would be the server s address .


public function generateNewToken(ServerRequestInterface $request)
    {

        $pair = $this->generateToken();

        $request = $this->attachRequestAttributes($request, $pair);

        return $request;
    }

public function generateNewToken ( ServerRequestInterface $ request ) { $ pair = $ this -> generateToken ( ) ; $ request = $ this -> attachRequestAttributes ( $ request , $ pair ) ; return $ request ; }

Generates a new CSRF token and attaches it to the Request Object

@param  ServerRequestInterface $request PSR7 response object.

@return ServerRequestInterface PSR7 response object.


protected function getFromStorage($name)
    {
        return isset($this->storage[$name]) ? $this->storage[$name] : false;
    }

protected function getFromStorage ( $ name ) { return isset ( $ this -> storage [ $ name ] ) ? $ this -> storage [ $ name ] : false ; }

Get token from storage

@param  string      $name CSRF token name

@return string|bool CSRF token value or `false` if not present


protected function getLastKeyPair()
    {
        // Use count, since empty ArrayAccess objects can still return false for `empty`
        if (count($this->storage) < 1) {
            return null;
        }

        foreach ($this->storage as $name => $value) {
            continue;
        }

        $keyPair = [
            $this->prefix . '_name' => $name,
            $this->prefix . '_value' => $value
        ];

        return $keyPair;
    }

Get the most recent key pair from storage.

@return string[]|null Array containing name and value if found, null otherwise

Get the most recent key pair from storage .


protected function enforceStorageLimit()
    {
        if ($this->storageLimit < 1) {
            return;
        }

        // $storage must be an array or implement Countable and Traversable
        if (!is_array($this->storage)
            && !($this->storage instanceof Countable && $this->storage instanceof Traversable)
        ) {
            return;
        }

        if (is_array($this->storage)) {
            while (count($this->storage) > $this->storageLimit) {
                array_shift($this->storage);
            }
        } else {
            // array_shift() doesn't work for ArrayAccess, so we need an iterator in order to use rewind()
            // and key(), so that we can then unset
            $iterator = $this->storage;
            if ($this->storage instanceof \IteratorAggregate) {
                $iterator = $this->storage->getIterator();
            }
            while (count($this->storage) > $this->storageLimit) {
                $iterator->rewind();
                unset($this->storage[$iterator->key()]);
            }
        }
    }

Remove the oldest tokens from the storage array so that there
are never more than storageLimit tokens in the array.

This is required as a token is generated every request and so
most will never be used.

Remove the oldest tokens from the storage array so that there are never more than storageLimit tokens in the array .


public static function create(array $config): SanitizerInterface
    {
        $builder = new SanitizerBuilder();
        $builder->registerExtension(new BasicExtension());
        $builder->registerExtension(new ListExtension());
        $builder->registerExtension(new ImageExtension());
        $builder->registerExtension(new CodeExtension());
        $builder->registerExtension(new TableExtension());
        $builder->registerExtension(new IframeExtension());
        $builder->registerExtension(new DetailsExtension());
        $builder->registerExtension(new ExtraExtension());

        return $builder->build($config);
    }

public static function create ( array $ config ) : SanitizerInterface { $ builder = new SanitizerBuilder ( ) ; $ builder -> registerExtension ( new BasicExtension ( ) ) ; $ builder -> registerExtension ( new ListExtension ( ) ) ; $ builder -> registerExtension ( new ImageExtension ( ) ) ; $ builder -> registerExtension ( new CodeExtension ( ) ) ; $ builder -> registerExtension ( new TableExtension ( ) ) ; $ builder -> registerExtension ( new IframeExtension ( ) ) ; $ builder -> registerExtension ( new DetailsExtension ( ) ) ; $ builder -> registerExtension ( new ExtraExtension ( ) ) ; return $ builder -> build ( $ config ) ; }

Quickly create an already configured sanitizer using the default builder.

@param array $config

@return SanitizerInterface

Quickly create an already configured sanitizer using the default builder .


private function setAttributes(\DOMNode $domNode, TagNodeInterface $node, array $allowedAttributes = [])
    {
        if (!\count($domNode->attributes)) {
            return;
        }

        /** @var \DOMAttr $attribute */
        foreach ($domNode->attributes as $attribute) {
            $name = strtolower($attribute->name);

            if (\in_array($name, $allowedAttributes, true)) {
                $node->setAttribute($name, $attribute->value);
            }
        }
    }

private
function
setAttributes
(
\
DOMNode
$
domNode
,
TagNodeInterface
$
node
,
array
$
allowedAttributes
=
[
]
)
{
if
(
!
\
count
(
$
domNode
->
attributes
)
)
{
return
;
}
/** @var \DOMAttr $attribute */
foreach
(
$
domNode
->
attributes
as
$
attribute
)
{
$
name
=
strtolower
(
$
attribute
->
name
)
;
if
(
\
in_array
(
$
name
,
$
allowedAttributes
,
true
)
)
{
$
node
->
setAttribute
(
$
name
,
$
attribute
->
value
)
;
}
}
}

Set attributes from a DOM node to a sanitized node.

@param \DOMNode         $domNode
@param TagNodeInterface $node
@param array            $allowedAttributes

Set attributes from a DOM node to a sanitized node .


private function getAttribute(\DOMNode $domNode, string $name): ?string
    {
        if (!\count($domNode->attributes)) {
            return null;
        }

        /** @var \DOMAttr $attribute */
        foreach ($domNode->attributes as $attribute) {
            if ($attribute->name === $name) {
                return $attribute->value;
            }
        }

        return null;
    }

private
function
getAttribute
(
\
DOMNode
$
domNode
,
string
$
name
)
:
string
{
if
(
!
\
count
(
$
domNode
->
attributes
)
)
{
return
;
}
/** @var \DOMAttr $attribute */
foreach
(
$
domNode
->
attributes
as
$
attribute
)
{
if
(
$
attribute
->
name
===
$
name
)
{
return
$
attribute
->
value
;
}
}
return
;
}

Read the value of a DOMNode attribute.

@param \DOMNode $domNode
@param string   $name

@return null|string


private function processDefaultEntity(array $backendConfig)
    {
        $entityNames = \array_keys($backendConfig['entities']);
        $firstEntityName = $entityNames[0] ?? null;
        $backendConfig['default_entity_name'] = $firstEntityName;

        return $backendConfig;
    }

private function processDefaultEntity ( array $ backendConfig ) { $ entityNames = \ array_keys ( $ backendConfig [ 'entities' ] ) ; $ firstEntityName = $ entityNames [ 0 ] ?? null ; $ backendConfig [ 'default_entity_name' ] = $ firstEntityName ; return $ backendConfig ; }

Finds the default entity to display when the backend index is not
defined explicitly.

@param array $backendConfig

@return array

Finds the default entity to display when the backend index is not defined explicitly .


private function processDefaultMenuItem(array $backendConfig)
    {
        $defaultMenuItem = $this->findDefaultMenuItem($backendConfig['design']['menu']);

        if ('empty' === $defaultMenuItem['type']) {
            throw new \RuntimeException(\sprintf('The "menu" configuration sets "%s" as the default item, which is not possible because its type is "empty" and it cannot redirect to a valid URL.', $defaultMenuItem['label']));
        }

        $backendConfig['default_menu_item'] = $defaultMenuItem;

        return $backendConfig;
    }

Finds the default menu item to display when browsing the backend index.

@param array $backendConfig

@return array

Finds the default menu item to display when browsing the backend index .


public static function getTypeName($typeFqcn)
    {
        // needed to avoid collisions between immutable and non-immutable date types,
        // which are mapped to the same Symfony Form type classes
        $filteredNameToClassMap = \array_filter(self::$nameToClassMap, function ($typeName) {
            return !\in_array($typeName, ['datetime_immutable', 'date_immutable', 'time_immutable']);
        }, ARRAY_FILTER_USE_KEY);
        $classToNameMap = \array_flip($filteredNameToClassMap);

        return $classToNameMap[$typeFqcn] ?? $typeFqcn;
    }

It returns the short type name of the given FQCN. If the type name is not
found, it returns the given value.

@param string $typeFqcn

@return string

It returns the short type name of the given FQCN . If the type name is not found it returns the given value .


private function getFormTypeOptionsOfProperty(array $mergedConfig, array $guessedConfig, array $userDefinedConfig)
    {
        $resolvedFormOptions = $mergedConfig['type_options'];

        // if the user has defined a 'type', the type options
        // must be reset so they don't get mixed with the form components guess.
        // Only the 'required' and user defined option are kept
        if (
            isset($userDefinedConfig['type'], $guessedConfig['fieldType'])
            && $userDefinedConfig['type'] !== $guessedConfig['fieldType']
        ) {
            $resolvedFormOptions = \array_merge(
                \array_intersect_key($resolvedFormOptions, ['required' => null]),
                isset($userDefinedConfig['type_options']) ? $userDefinedConfig['type_options'] : []
            );
        }
        // if the user has defined the "type" or "type_options"
        // AND the "type" is the same as the default one
        elseif (
            (
                isset($userDefinedConfig['type'])
                && isset($guessedConfig['fieldType'])
                && $userDefinedConfig['type'] === $guessedConfig['fieldType']
            ) || (
                !isset($userDefinedConfig['type']) && isset($userDefinedConfig['type_options'])
            )
        ) {
            $resolvedFormOptions = \array_merge(
                $resolvedFormOptions,
                isset($userDefinedConfig['type_options']) ? $userDefinedConfig['type_options'] : []
            );
        }

        return $resolvedFormOptions;
    }

Resolves from type options of field

@param array $mergedConfig
@param array $guessedConfig
@param array $userDefinedConfig

@return array


protected function initialize(Request $request)
    {
        $this->dispatch(EasyAdminEvents::PRE_INITIALIZE);

        $this->config = $this->get('easyadmin.config.manager')->getBackendConfig();

        if (0 === \count($this->config['entities'])) {
            throw new NoEntitiesConfiguredException();
        }

        // this condition happens when accessing the backend homepage and before
        // redirecting to the default page set as the homepage
        if (null === $entityName = $request->query->get('entity')) {
            return;
        }

        if (!\array_key_exists($entityName, $this->config['entities'])) {
            throw new UndefinedEntityException(['entity_name' => $entityName]);
        }

        $this->entity = $this->get('easyadmin.config.manager')->getEntityConfig($entityName);

        $action = $request->query->get('action', 'list');
        if (!$request->query->has('sortField')) {
            $sortField = $this->entity[$action]['sort']['field'] ?? $this->entity['primary_key_field_name'];
            $request->query->set('sortField', $sortField);
        }
        if (!$request->query->has('sortDirection')) {
            $sortDirection = $this->entity[$action]['sort']['direction'] ?? 'DESC';
            $request->query->set('sortDirection', $sortDirection);
        }

        $this->em = $this->getDoctrine()->getManagerForClass($this->entity['class']);
        $this->request = $request;

        $this->dispatch(EasyAdminEvents::POST_INITIALIZE);
    }

Utility method which initializes the configuration of the entity on which
the user is performing the action.

@param Request $request

@throws NoEntitiesConfiguredException
@throws UndefinedEntityException

Utility method which initializes the configuration of the entity on which the user is performing the action .


protected function autocompleteAction()
    {
        $results = $this->get('easyadmin.autocomplete')->find(
            $this->request->query->get('entity'),
            $this->request->query->get('query'),
            $this->request->query->get('page', 1)
        );

        return new JsonResponse($results);
    }

protected function autocompleteAction ( ) { $ results = $ this -> get ( 'easyadmin.autocomplete' ) -> find ( $ this -> request -> query -> get ( 'entity' ) , $ this -> request -> query -> get ( 'query' ) , $ this -> request -> query -> get ( 'page' , 1 ) ) ; return new JsonResponse ( $ results ) ; }

The method that returns the values displayed by an autocomplete field
based on the user's input.

@return JsonResponse

The method that returns the values displayed by an autocomplete field based on the user s input .


protected function listAction()
    {
        $this->dispatch(EasyAdminEvents::PRE_LIST);

        $fields = $this->entity['list']['fields'];
        $paginator = $this->findAll($this->entity['class'], $this->request->query->get('page', 1), $this->entity['list']['max_results'], $this->request->query->get('sortField'), $this->request->query->get('sortDirection'), $this->entity['list']['dql_filter']);

        $this->dispatch(EasyAdminEvents::POST_LIST, ['paginator' => $paginator]);

        $parameters = [
            'paginator' => $paginator,
            'fields' => $fields,
            'batch_form' => $this->createBatchForm($this->entity['name'])->createView(),
            'delete_form_template' => $this->createDeleteForm($this->entity['name'], '__id__')->createView(),
        ];

        return $this->executeDynamicMethod('render<EntityName>Template', ['list', $this->entity['templates']['list'], $parameters]);
    }

protected function listAction ( ) { $ this -> dispatch ( EasyAdminEvents :: PRE_LIST ) ; $ fields = $ this -> entity [ 'list' ] [ 'fields' ] ; $ paginator = $ this -> findAll ( $ this -> entity [ 'class' ] , $ this -> request -> query -> get ( 'page' , 1 ) , $ this -> entity [ 'list' ] [ 'max_results' ] , $ this -> request -> query -> get ( 'sortField' ) , $ this -> request -> query -> get ( 'sortDirection' ) , $ this -> entity [ 'list' ] [ 'dql_filter' ] ) ; $ this -> dispatch ( EasyAdminEvents :: POST_LIST , [ 'paginator' => $ paginator ] ) ; $ parameters = [ 'paginator' => $ paginator , 'fields' => $ fields , 'batch_form' => $ this -> createBatchForm ( $ this -> entity [ 'name' ] ) -> createView ( ) , 'delete_form_template' => $ this -> createDeleteForm ( $ this -> entity [ 'name' ] , '__id__' ) -> createView ( ) , ] ; return $ this -> executeDynamicMethod ( 'render<EntityName>Template' , [ 'list' , $ this -> entity [ 'templates' ] [ 'list' ] , $ parameters ] ) ; }

The method that is executed when the user performs a 'list' action on an entity.

@return Response

The method that is executed when the user performs a list action on an entity .


protected function editAction()
    {
        $this->dispatch(EasyAdminEvents::PRE_EDIT);

        $id = $this->request->query->get('id');
        $easyadmin = $this->request->attributes->get('easyadmin');
        $entity = $easyadmin['item'];

        if ($this->request->isXmlHttpRequest() && $property = $this->request->query->get('property')) {
            $newValue = 'true' === \mb_strtolower($this->request->query->get('newValue'));
            $fieldsMetadata = $this->entity['list']['fields'];

            if (!isset($fieldsMetadata[$property]) || 'toggle' !== $fieldsMetadata[$property]['dataType']) {
                throw new \RuntimeException(\sprintf('The type of the "%s" property is not "toggle".', $property));
            }

            $this->updateEntityProperty($entity, $property, $newValue);

            // cast to integer instead of string to avoid sending empty responses for 'false'
            return new Response((int) $newValue);
        }

        $fields = $this->entity['edit']['fields'];

        $editForm = $this->executeDynamicMethod('create<EntityName>EditForm', [$entity, $fields]);
        $deleteForm = $this->createDeleteForm($this->entity['name'], $id);

        $editForm->handleRequest($this->request);
        if ($editForm->isSubmitted() && $editForm->isValid()) {
            $this->dispatch(EasyAdminEvents::PRE_UPDATE, ['entity' => $entity]);
            $this->executeDynamicMethod('update<EntityName>Entity', [$entity, $editForm]);
            $this->dispatch(EasyAdminEvents::POST_UPDATE, ['entity' => $entity]);

            return $this->redirectToReferrer();
        }

        $this->dispatch(EasyAdminEvents::POST_EDIT);

        $parameters = [
            'form' => $editForm->createView(),
            'entity_fields' => $fields,
            'entity' => $entity,
            'delete_form' => $deleteForm->createView(),
        ];

        return $this->executeDynamicMethod('render<EntityName>Template', ['edit', $this->entity['templates']['edit'], $parameters]);
    }

The method that is executed when the user performs a 'edit' action on an entity.

@return Response|RedirectResponse

@throws \RuntimeException

The method that is executed when the user performs a edit action on an entity .


protected function showAction()
    {
        $this->dispatch(EasyAdminEvents::PRE_SHOW);

        $id = $this->request->query->get('id');
        $easyadmin = $this->request->attributes->get('easyadmin');
        $entity = $easyadmin['item'];

        $fields = $this->entity['show']['fields'];
        $deleteForm = $this->createDeleteForm($this->entity['name'], $id);

        $this->dispatch(EasyAdminEvents::POST_SHOW, [
            'deleteForm' => $deleteForm,
            'fields' => $fields,
            'entity' => $entity,
        ]);

        $parameters = [
            'entity' => $entity,
            'fields' => $fields,
            'delete_form' => $deleteForm->createView(),
        ];

        return $this->executeDynamicMethod('render<EntityName>Template', ['show', $this->entity['templates']['show'], $parameters]);
    }

protected function showAction ( ) { $ this -> dispatch ( EasyAdminEvents :: PRE_SHOW ) ; $ id = $ this -> request -> query -> get ( 'id' ) ; $ easyadmin = $ this -> request -> attributes -> get ( 'easyadmin' ) ; $ entity = $ easyadmin [ 'item' ] ; $ fields = $ this -> entity [ 'show' ] [ 'fields' ] ; $ deleteForm = $ this -> createDeleteForm ( $ this -> entity [ 'name' ] , $ id ) ; $ this -> dispatch ( EasyAdminEvents :: POST_SHOW , [ 'deleteForm' => $ deleteForm , 'fields' => $ fields , 'entity' => $ entity , ] ) ; $ parameters = [ 'entity' => $ entity , 'fields' => $ fields , 'delete_form' => $ deleteForm -> createView ( ) , ] ; return $ this -> executeDynamicMethod ( 'render<EntityName>Template' , [ 'show' , $ this -> entity [ 'templates' ] [ 'show' ] , $ parameters ] ) ; }

The method that is executed when the user performs a 'show' action on an entity.

@return Response

The method that is executed when the user performs a show action on an entity .