![]() Server : Apache System : Linux server2.corals.io 4.18.0-348.2.1.el8_5.x86_64 #1 SMP Mon Nov 15 09:17:08 EST 2021 x86_64 User : corals ( 1002) PHP Version : 7.4.33 Disable Function : exec,passthru,shell_exec,system Directory : /home/corals/cartforge.co/setup/src/Magento/Setup/Module/Di/Code/Reader/ |
<?php /** * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\Setup\Module\Di\Code\Reader; use Laminas\Code\Exception\InvalidArgumentException; use Laminas\Code\Exception\RuntimeException; /** * FileScanner code reader * * @SuppressWarnings(PHPMD) */ class FileScanner { /** * @var string */ protected $file; /** * @var bool */ protected $isScanned = false; /** * @var array */ protected $tokens = []; /** * @var array */ protected $infos = []; /** * @var int */ private $tokenType; /** * copied from laminas-code 3.5.1 * * @param string $file * * @throws InvalidArgumentException */ public function __construct(string $file) { $this->file = $file; // phpcs:ignore Magento2.Functions.DiscouragedFunction if (!file_exists($file)) { throw new InvalidArgumentException(sprintf( 'File "%s" not found', $file )); } // phpcs:ignore Magento2.Functions.DiscouragedFunction $tokens = token_get_all(file_get_contents($file)); $this->tokens = $tokens; } /** * @inheritDoc */ protected function scan() { if ($this->isScanned) { return; } if (!$this->tokens) { throw new RuntimeException('No tokens were provided'); } /** * Define PHP 5.4 'trait' token constant. */ if (!defined('T_TRAIT')) { define('T_TRAIT', 42001); } $namespaceContentTokenTypes = [ T_NS_SEPARATOR => T_NS_SEPARATOR, T_STRING => T_STRING, T_NAME_QUALIFIED => T_NAME_QUALIFIED, T_NAME_FULLY_QUALIFIED => T_NAME_FULLY_QUALIFIED ]; /** * Variables & Setup */ $tokens = &$this->tokens; // localize $infos = &$this->infos; // localize $tokenIndex = null; $token = null; $this->tokenType = null; $tokenContent = null; $tokenLine = null; $namespace = null; $docCommentIndex = false; $infoIndex = 0; /* * MACRO creation */ $macroTokenAdvance = function () use (&$tokens, &$tokenIndex, &$token, &$tokenContent, &$tokenLine) { $tokenIndex = ($tokenIndex === null) ? 0 : $tokenIndex + 1; if (!isset($tokens[$tokenIndex])) { $token = false; $tokenContent = false; $this->tokenType = false; $tokenLine = false; return false; } if (is_string($tokens[$tokenIndex]) && $tokens[$tokenIndex] === '"') { do { $tokenIndex++; } while (!(is_string($tokens[$tokenIndex]) && $tokens[$tokenIndex] === '"')); } $token = $tokens[$tokenIndex]; if (is_array($token)) { list($this->tokenType, $tokenContent, $tokenLine) = $token; } else { $this->tokenType = null; $tokenContent = $token; } return $tokenIndex; }; $macroTokenLogicalStartIndex = function () use (&$tokenIndex, &$docCommentIndex) { return ($docCommentIndex === false) ? $tokenIndex : $docCommentIndex; }; $macroDocCommentStart = function () use (&$tokenIndex, &$docCommentIndex) { $docCommentIndex = $tokenIndex; return $docCommentIndex; }; $macroDocCommentValidate = function () use (&$docCommentIndex) { static $validTrailingTokens = null; if ($validTrailingTokens === null) { $validTrailingTokens = [T_WHITESPACE, T_FINAL, T_ABSTRACT, T_INTERFACE, T_CLASS, T_FUNCTION]; } if ($docCommentIndex !== false && !in_array($this->tokenType, $validTrailingTokens)) { $docCommentIndex = false; } return $docCommentIndex; }; $macroInfoAdvance = function () use (&$infoIndex, &$infos, &$tokenIndex, &$tokenLine) { $infos[$infoIndex]['tokenEnd'] = $tokenIndex; $infos[$infoIndex]['lineEnd'] = $tokenLine; $infoIndex++; return $infoIndex; }; // phpcs:disable /** * START FINITE STATE MACHINE FOR SCANNING TOKENS */ // Initialize token $macroTokenAdvance(); SCANNER_TOP: if ($token === false) { goto SCANNER_END; } // Validate current doc comment index $macroDocCommentValidate(); switch ($this->tokenType) { case T_DOC_COMMENT: $macroDocCommentStart(); goto SCANNER_CONTINUE; //goto no break needed case T_NAMESPACE: $infos[$infoIndex] = [ 'type' => 'namespace', 'tokenStart' => $macroTokenLogicalStartIndex(), 'tokenEnd' => null, 'lineStart' => $token[2], 'lineEnd' => null, 'namespace' => null, ]; // start processing with next token if ($macroTokenAdvance() === false) { goto SCANNER_END; } SCANNER_NAMESPACE_TOP: if ($this->tokenType === null && $tokenContent === ';' || $tokenContent === '{') { goto SCANNER_NAMESPACE_END; } if ($this->tokenType === T_WHITESPACE) { goto SCANNER_NAMESPACE_CONTINUE; } if (isset($namespaceContentTokenTypes[$this->tokenType])) { $infos[$infoIndex]['namespace'] .= $tokenContent; } SCANNER_NAMESPACE_CONTINUE: if ($macroTokenAdvance() === false) { goto SCANNER_END; } goto SCANNER_NAMESPACE_TOP; SCANNER_NAMESPACE_END: $namespace = $infos[$infoIndex]['namespace']; $macroInfoAdvance(); goto SCANNER_CONTINUE; //goto no break needed case T_USE: $infos[$infoIndex] = [ 'type' => 'use', 'tokenStart' => $macroTokenLogicalStartIndex(), 'tokenEnd' => null, 'lineStart' => $tokens[$tokenIndex][2], 'lineEnd' => null, 'namespace' => $namespace, 'statements' => [0 => ['use' => null, 'as' => null]], ]; $useStatementIndex = 0; $useAsContext = false; // start processing with next token if ($macroTokenAdvance() === false) { goto SCANNER_END; } SCANNER_USE_TOP: if ($this->tokenType === null) { if ($tokenContent === ';') { goto SCANNER_USE_END; } elseif ($tokenContent === ',') { $useAsContext = false; $useStatementIndex++; $infos[$infoIndex]['statements'][$useStatementIndex] = ['use' => null, 'as' => null]; } } // ANALYZE if ($this->tokenType !== null) { if ($this->tokenType == T_AS) { $useAsContext = true; goto SCANNER_USE_CONTINUE; } if (\array_key_exists($this->tokenType, $namespaceContentTokenTypes)) { if ($useAsContext == false) { $infos[$infoIndex]['statements'][$useStatementIndex]['use'] .= $tokenContent; } else { $infos[$infoIndex]['statements'][$useStatementIndex]['as'] = $tokenContent; } } } SCANNER_USE_CONTINUE: if ($macroTokenAdvance() === false) { goto SCANNER_END; } goto SCANNER_USE_TOP; SCANNER_USE_END: $macroInfoAdvance(); goto SCANNER_CONTINUE; //goto no break needed case T_INCLUDE: case T_INCLUDE_ONCE: case T_REQUIRE: case T_REQUIRE_ONCE: // Static for performance static $includeTypes = [ T_INCLUDE => 'include', T_INCLUDE_ONCE => 'include_once', T_REQUIRE => 'require', T_REQUIRE_ONCE => 'require_once' ]; $infos[$infoIndex] = [ 'type' => 'include', 'tokenStart' => $macroTokenLogicalStartIndex(), 'tokenEnd' => null, 'lineStart' => $tokens[$tokenIndex][2], 'lineEnd' => null, 'includeType' => $includeTypes[$tokens[$tokenIndex][0]], 'path' => '', ]; // start processing with next token if ($macroTokenAdvance() === false) { goto SCANNER_END; } SCANNER_INCLUDE_TOP: if ($this->tokenType === null && $tokenContent === ';') { goto SCANNER_INCLUDE_END; } $infos[$infoIndex]['path'] .= $tokenContent; SCANNER_INCLUDE_CONTINUE: if ($macroTokenAdvance() === false) { goto SCANNER_END; } goto SCANNER_INCLUDE_TOP; SCANNER_INCLUDE_END: $macroInfoAdvance(); goto SCANNER_CONTINUE; //goto no break needed case T_FUNCTION: case T_FINAL: case T_ABSTRACT: case T_CLASS: case T_INTERFACE: case T_TRAIT: $infos[$infoIndex] = [ 'type' => ($this->tokenType === T_FUNCTION) ? 'function' : 'class', 'tokenStart' => $macroTokenLogicalStartIndex(), 'tokenEnd' => null, 'lineStart' => $tokens[$tokenIndex][2], 'lineEnd' => null, 'namespace' => $namespace, 'uses' => $this->getUsesNoScan($namespace), 'name' => null, 'shortName' => null, ]; $classBraceCount = 0; // start processing with current token SCANNER_CLASS_TOP: // process the name if ($infos[$infoIndex]['shortName'] == '' && (($this->tokenType === T_CLASS || $this->tokenType === T_INTERFACE || $this->tokenType === T_TRAIT ) && $infos[$infoIndex]['type'] === 'class' && $tokens[$tokenIndex - 1][0] !== T_DOUBLE_COLON || ($this->tokenType === T_FUNCTION && $infos[$infoIndex]['type'] === 'function')) ) { $infos[$infoIndex]['shortName'] = $tokens[$tokenIndex + 2][1]; $infos[$infoIndex]['name'] = (($namespace !== null) ? $namespace . '\\' : '') . $infos[$infoIndex]['shortName']; } if ($this->tokenType === null) { if ($tokenContent === '{') { $classBraceCount++; } if ($tokenContent === '}') { $classBraceCount--; if ($classBraceCount === 0) { goto SCANNER_CLASS_END; } } } SCANNER_CLASS_CONTINUE: if ($macroTokenAdvance() === false) { goto SCANNER_END; } goto SCANNER_CLASS_TOP; SCANNER_CLASS_END: $macroInfoAdvance(); goto SCANNER_CONTINUE; } SCANNER_CONTINUE: if ($macroTokenAdvance() === false) { goto SCANNER_END; } goto SCANNER_TOP; SCANNER_END: /** * END FINITE STATE MACHINE FOR SCANNING TOKENS */ $this->isScanned = true; // phpcs:enable } /** * Copied from laminas-code 3.5.1 * * @param string|null $namespace * * @return array|null */ public function getUses(string $namespace = null): ?array { $this->scan(); return $this->getUsesNoScan($namespace); } /** * Copied from laminas-code 3.5.1 * * @param string|null $namespace * * @return array|null */ protected function getUsesNoScan(string $namespace = null): ?array { $namespaces = []; foreach ($this->infos as $info) { if ($info['type'] === 'namespace') { $namespaces[] = $info['namespace']; } } if ($namespace === null) { $namespace = array_shift($namespaces); } elseif (!in_array($namespace, $namespaces, true)) { return null; } $uses = []; foreach ($this->infos as $info) { if ($info['type'] !== 'use') { continue; } foreach ($info['statements'] as $statement) { if ($info['namespace'] === $namespace) { $uses[] = $statement; } } } return $uses; } }