createResource($resourceString); if (!$resource instanceof PublicResourceInterface || !$resource->isPublished()) { throw new CanNotResolvePublicResourceException(sprintf('Resolved resource "%s" is not a public resource. Given resource identifier: "%s"', $resource, $resourceString), 1758098512); } return $resource; } /** * Use this method, when generating a URI is not required * for the resource and only e.g. file contents like for templates * is required. * * @throws CanNotResolveSystemResourceException * @throws InvalidSystemResourceIdentifierException */ public function createResource(string $resourceString): StaticResourceInterface { try { return $this->createFromIdentifier($resourceString); } catch (CanNotResolveSystemResourceIdentifierException $e) { if (str_starts_with($resourceString, Environment::getProjectPath()) || (PathUtility::isAbsolutePath($resourceString) && file_exists($resourceString)) ) { throw new CanNotResolveSystemResourceException('Absolute paths are not allowed as resource identifiers', 1760618195); } $resourceString = ltrim($resourceString, '/'); $falResource = $this->createFromLegacyFalPath($resourceString, $e); return $falResource ?? $this->createResourceFromRelativePublicPath($resourceString); } } /** * @throws CanNotResolveSystemResourceException * @throws InvalidSystemResourceIdentifierException */ private function createResourceFromRelativePublicPath(string $relativePublicPath): SystemResourceInterface { $absoluteResourcePath = Environment::getPublicPath() . '/' . $relativePublicPath; // The file must actually exist, only then we can be sure our // following string manipulation is correct. Otherwise, it could be some unexpected // string and the manipulation will lead to unexpected results // Strip potentially available query string and fragment from the path before checking, though try { $strippedAbsolutePath = (new Uri($absoluteResourcePath))->getPath(); } catch (\InvalidArgumentException) { $strippedAbsolutePath = null; } if (!file_exists($strippedAbsolutePath ?? $absoluteResourcePath)) { throw new CanNotResolveSystemResourceException(sprintf('Can not resolve relative public path "%s" to a system resource', $relativePublicPath), 1759740281); } $packageIdentifier = $this->identifierFactory->createFromPackagePath( VirtualAppPackage::APP_PACKAGE_KEY, substr($absoluteResourcePath, strlen(Environment::getProjectPath()) + 1), $relativePublicPath, ); return $this->createFromPackageIdentifier($packageIdentifier); } /** * @throws CanNotResolveSystemResourceException * @throws InvalidSystemResourceIdentifierException * @throws CanNotResolveSystemResourceIdentifierException */ private function createFromIdentifier(string $potentialIdentifier): StaticResourceInterface { $identifier = $this->identifierFactory->create($potentialIdentifier); return match (get_class($identifier)) { UriResourceIdentifier::class => new UriResource($identifier), PackageResourceIdentifier::class => $this->createFromPackageIdentifier($identifier), FalResourceIdentifier::class => $this->createFromFalIdentifier($identifier), default => throw new InvalidSystemResourceIdentifierException(sprintf('Can not resolve "%s" to a system resource. Unknown SystemResourceIdentifier', $potentialIdentifier), 1759393674), }; } /** * @throws CanNotResolveSystemResourceException */ private function createFromLegacyFalPath(string $resourceString, \Throwable $e): ?StaticResourceInterface { if (!str_starts_with($resourceString, $GLOBALS['TYPO3_CONF_VARS']['BE']['fileadminDir'])) { // For legacy resolving, we do not even try resolving any other path than // one starting with configured $GLOBALS['TYPO3_CONF_VARS']['BE']['fileadminDir'] return null; } try { $potentialFalPath = $resourceString; $storageUid = $this->storageRepository?->findBestMatchingStorageByLocalPath($potentialFalPath); } catch (\Throwable) { $storageUid = 0; } if ($storageUid <= 0) { return null; } $storage = $this->storageRepository?->findByUid($storageUid); if ($storage === null) { throw new CanNotResolveSystemResourceException(sprintf('Can not resolve "%s" to a system resource, storage %d does not exist', $resourceString, $storageUid), 1758627596, $e); } $file = null; try { $file = $storage->getFile($potentialFalPath); } catch (\Throwable) { } $this->ensureValidFalResource($file, $resourceString); return $file; } /** * @throws CanNotResolveSystemResourceException */ private function createFromFalIdentifier(FalResourceIdentifier $resourceUri): PublicResourceInterface { try { $file = $this->resourceFactory?->retrieveFileOrFolderObject($resourceUri->getIdentifier()); $this->ensureValidFalResource($file, (string)$resourceUri); return $file; } catch (FalException $e) { throw new CanNotResolveSystemResourceException(sprintf('Can not resolve "%s" to a system resource', $resourceUri), 1759397430, $e); } } /** * @throws CanNotResolveSystemResourceException */ private function ensureValidFalResource(ProcessedFile|File|Folder|null $falResource, string $resourceUri): void { if (!$falResource instanceof File || $falResource->getStorage()->getUid() === 0) { throw new CanNotResolveSystemResourceException(sprintf('Can not resolve file with URI "%s"', $resourceUri), 1758700078); } } private function createFromPackageIdentifier(PackageResourceIdentifier $packageIdentifier): SystemResourceInterface { $resourceDefinition = $packageIdentifier->getPackage()->getResources()->definitionForPath($packageIdentifier->getRelativePath()); if ($resourceDefinition instanceof PublicResourceDefinition) { return new PublicPackageFile($packageIdentifier, $resourceDefinition); } return new PackageResource($packageIdentifier, $resourceDefinition); } }