Skip to main content
Drupal API
User account menu
  • Log in

Breadcrumb

  1. Drupal Core 11.1.x
  2. ComposerRepository.php

function ComposerRepository::fetchFile

Return value

array<mixed>

4 calls to ComposerRepository::fetchFile()
ComposerRepository::loadIncludes in vendor/composer/composer/src/Composer/Repository/ComposerRepository.php
ComposerRepository::loadProviderListings in vendor/composer/composer/src/Composer/Repository/ComposerRepository.php
ComposerRepository::loadRootServerFile in vendor/composer/composer/src/Composer/Repository/ComposerRepository.php
ComposerRepository::whatProvides in vendor/composer/composer/src/Composer/Repository/ComposerRepository.php
@phpstan-param array<key-of<BasePackage::STABILITIES>, BasePackage::STABILITY_*>|null $acceptableStabilities

File

vendor/composer/composer/src/Composer/Repository/ComposerRepository.php, line 1457

Class

ComposerRepository
@author Jordi Boggiano <j.boggiano@seld.be>

Namespace

Composer\Repository

Code

protected function fetchFile(string $filename, ?string $cacheKey = null, ?string $sha256 = null, bool $storeLastModifiedTime = false) {
    if ('' === $filename) {
        throw new \InvalidArgumentException('$filename should not be an empty string');
    }
    if (null === $cacheKey) {
        $cacheKey = $filename;
        $filename = $this->baseUrl . '/' . $filename;
    }
    // url-encode $ signs in URLs as bad proxies choke on them
    if (($pos = strpos($filename, '$')) && Preg::isMatch('{^https?://}i', $filename)) {
        $filename = substr($filename, 0, $pos) . '%24' . substr($filename, $pos + 1);
    }
    $retries = 3;
    while ($retries--) {
        try {
            $options = $this->options;
            if ($this->eventDispatcher) {
                $preFileDownloadEvent = new PreFileDownloadEvent(PluginEvents::PRE_FILE_DOWNLOAD, $this->httpDownloader, $filename, 'metadata', [
                    'repository' => $this,
                ]);
                $preFileDownloadEvent->setTransportOptions($this->options);
                $this->eventDispatcher
                    ->dispatch($preFileDownloadEvent->getName(), $preFileDownloadEvent);
                $filename = $preFileDownloadEvent->getProcessedUrl();
                $options = $preFileDownloadEvent->getTransportOptions();
            }
            $response = $this->httpDownloader
                ->get($filename, $options);
            $json = (string) $response->getBody();
            if ($sha256 && $sha256 !== hash('sha256', $json)) {
                // undo downgrade before trying again if http seems to be hijacked or modifying content somehow
                if ($this->allowSslDowngrade) {
                    $this->url = str_replace('http://', 'https://', $this->url);
                    $this->baseUrl = str_replace('http://', 'https://', $this->baseUrl);
                    $filename = str_replace('http://', 'https://', $filename);
                }
                if ($retries > 0) {
                    usleep(100000);
                    continue;
                }
                // TODO use scarier wording once we know for sure it doesn't do false positives anymore
                throw new RepositorySecurityException('The contents of ' . $filename . ' do not match its signature. This could indicate a man-in-the-middle attack or e.g. antivirus software corrupting files. Try running composer again and report this if you think it is a mistake.');
            }
            if ($this->eventDispatcher) {
                $postFileDownloadEvent = new PostFileDownloadEvent(PluginEvents::POST_FILE_DOWNLOAD, null, $sha256, $filename, 'metadata', [
                    'response' => $response,
                    'repository' => $this,
                ]);
                $this->eventDispatcher
                    ->dispatch($postFileDownloadEvent->getName(), $postFileDownloadEvent);
            }
            $data = $response->decodeJson();
            HttpDownloader::outputWarnings($this->io, $this->url, $data);
            if ($cacheKey && !$this->cache
                ->isReadOnly()) {
                if ($storeLastModifiedTime) {
                    $lastModifiedDate = $response->getHeader('last-modified');
                    if ($lastModifiedDate) {
                        $data['last-modified'] = $lastModifiedDate;
                        $json = JsonFile::encode($data, 0);
                    }
                }
                $this->cache
                    ->write($cacheKey, $json);
            }
            $response->collect();
            break;
        } catch (\Exception $e) {
            if ($e instanceof \LogicException) {
                throw $e;
            }
            if ($e instanceof TransportException && $e->getStatusCode() === 404) {
                throw $e;
            }
            if ($e instanceof RepositorySecurityException) {
                throw $e;
            }
            if ($cacheKey && ($contents = $this->cache
                ->read($cacheKey))) {
                if (!$this->degradedMode) {
                    $this->io
                        ->writeError('<warning>' . $this->url . ' could not be fully loaded (' . $e->getMessage() . '), package information was loaded from the local cache and may be out of date</warning>');
                }
                $this->degradedMode = true;
                $data = JsonFile::parseJson($contents, $this->cache
                    ->getRoot() . $cacheKey);
                break;
            }
            throw $e;
        }
    }
    if (!isset($data)) {
        throw new \LogicException("ComposerRepository: Undefined \$data. Please report at https://github.com/composer/composer/issues/new.");
    }
    return $data;
}
RSS feed
Powered by Drupal