Chris@18: findByAlias($path); Chris@18: if ($invocation !== null) { Chris@18: return $invocation; Chris@18: } Chris@18: } Chris@18: Chris@18: $baseName = $this->resolveBaseName($path, $flags); Chris@18: if ($baseName === null) { Chris@18: return null; Chris@18: } Chris@18: Chris@18: if ($flags & static::RESOLVE_REALPATH) { Chris@18: $baseName = $this->baseNames[$baseName]; Chris@18: } Chris@18: Chris@18: return $this->retrieveInvocation($baseName, $flags); Chris@18: } Chris@18: Chris@18: /** Chris@18: * Retrieves PharInvocation, either existing in collection or created on demand Chris@18: * with resolving a potential alias name used in the according Phar archive. Chris@18: * Chris@18: * @param string $baseName Chris@18: * @param int $flags Chris@18: * @return PharInvocation Chris@18: */ Chris@18: private function retrieveInvocation($baseName, $flags) Chris@18: { Chris@18: $invocation = $this->findByBaseName($baseName); Chris@18: if ($invocation !== null) { Chris@18: return $invocation; Chris@18: } Chris@18: Chris@18: if ($flags & static::RESOLVE_ALIAS) { Chris@18: $reader = new Reader($baseName); Chris@18: $alias = $reader->resolveContainer()->getAlias(); Chris@18: } else { Chris@18: $alias = ''; Chris@18: } Chris@18: // add unconfirmed(!) new invocation to collection Chris@18: $invocation = new PharInvocation($baseName, $alias); Chris@18: Manager::instance()->getCollection()->collect($invocation); Chris@18: return $invocation; Chris@18: } Chris@18: Chris@18: /** Chris@18: * @param string $path Chris@18: * @param int $flags Chris@18: * @return null|string Chris@18: */ Chris@18: private function resolveBaseName($path, $flags) Chris@18: { Chris@18: $baseName = $this->findInBaseNames($path); Chris@18: if ($baseName !== null) { Chris@18: return $baseName; Chris@18: } Chris@18: Chris@18: $baseName = Helper::determineBaseFile($path); Chris@18: if ($baseName !== null) { Chris@18: $this->addBaseName($baseName); Chris@18: return $baseName; Chris@18: } Chris@18: Chris@18: $possibleAlias = $this->resolvePossibleAlias($path); Chris@18: if (!($flags & static::RESOLVE_ALIAS) || $possibleAlias === null) { Chris@18: return null; Chris@18: } Chris@18: Chris@18: $trace = debug_backtrace(); Chris@18: foreach ($trace as $item) { Chris@18: if (!isset($item['function']) || !isset($item['args'][0]) Chris@18: || !in_array($item['function'], $this->invocationFunctionNames, true)) { Chris@18: continue; Chris@18: } Chris@18: $currentPath = $item['args'][0]; Chris@18: if (Helper::hasPharPrefix($currentPath)) { Chris@18: continue; Chris@18: } Chris@18: $currentBaseName = Helper::determineBaseFile($currentPath); Chris@18: if ($currentBaseName === null) { Chris@18: continue; Chris@18: } Chris@18: // ensure the possible alias name (how we have been called initially) matches Chris@18: // the resolved alias name that was retrieved by the current possible base name Chris@18: $reader = new Reader($currentBaseName); Chris@18: $currentAlias = $reader->resolveContainer()->getAlias(); Chris@18: if ($currentAlias !== $possibleAlias) { Chris@18: continue; Chris@18: } Chris@18: $this->addBaseName($currentBaseName); Chris@18: return $currentBaseName; Chris@18: } Chris@18: Chris@18: return null; Chris@18: } Chris@18: Chris@18: /** Chris@18: * @param string $path Chris@18: * @return null|string Chris@18: */ Chris@18: private function resolvePossibleAlias($path) Chris@18: { Chris@18: $normalizedPath = Helper::normalizePath($path); Chris@18: return strstr($normalizedPath, '/', true) ?: null; Chris@18: } Chris@18: Chris@18: /** Chris@18: * @param string $baseName Chris@18: * @return null|PharInvocation Chris@18: */ Chris@18: private function findByBaseName($baseName) Chris@18: { Chris@18: return Manager::instance()->getCollection()->findByCallback( Chris@18: function (PharInvocation $candidate) use ($baseName) { Chris@18: return $candidate->getBaseName() === $baseName; Chris@18: }, Chris@18: true Chris@18: ); Chris@18: } Chris@18: Chris@18: /** Chris@18: * @param string $path Chris@18: * @return null|string Chris@18: */ Chris@18: private function findInBaseNames($path) Chris@18: { Chris@18: // return directly if the resolved base name was submitted Chris@18: if (in_array($path, $this->baseNames, true)) { Chris@18: return $path; Chris@18: } Chris@18: Chris@18: $parts = explode('/', Helper::normalizePath($path)); Chris@18: Chris@18: while (count($parts)) { Chris@18: $currentPath = implode('/', $parts); Chris@18: if (isset($this->baseNames[$currentPath])) { Chris@18: return $currentPath; Chris@18: } Chris@18: array_pop($parts); Chris@18: } Chris@18: Chris@18: return null; Chris@18: } Chris@18: Chris@18: /** Chris@18: * @param string $baseName Chris@18: */ Chris@18: private function addBaseName($baseName) Chris@18: { Chris@18: if (isset($this->baseNames[$baseName])) { Chris@18: return; Chris@18: } Chris@18: $this->baseNames[$baseName] = realpath($baseName); Chris@18: } Chris@18: Chris@18: /** Chris@18: * Finds confirmed(!) invocations by alias. Chris@18: * Chris@18: * @param string $path Chris@18: * @return null|PharInvocation Chris@18: * @see \TYPO3\PharStreamWrapper\PharStreamWrapper::collectInvocation() Chris@18: */ Chris@18: private function findByAlias($path) Chris@18: { Chris@18: $possibleAlias = $this->resolvePossibleAlias($path); Chris@18: if ($possibleAlias === null) { Chris@18: return null; Chris@18: } Chris@18: return Manager::instance()->getCollection()->findByCallback( Chris@18: function (PharInvocation $candidate) use ($possibleAlias) { Chris@18: return $candidate->isConfirmed() && $candidate->getAlias() === $possibleAlias; Chris@18: }, Chris@18: true Chris@18: ); Chris@18: } Chris@18: }