Current File : //var/www/vinorea/modules/autoupgrade/classes/UpgradeTools/Module/ModuleDownloader.php
<?php
/**
 * Copyright since 2007 PrestaShop SA and Contributors
 * PrestaShop is an International Registered Trademark & Property of PrestaShop SA
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the Academic Free License version 3.0
 * that is bundled with this package in the file LICENSE.md.
 * It is also available through the world-wide-web at this URL:
 * https://opensource.org/licenses/AFL-3.0
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@prestashop.com so we can send you a copy immediately.
 *
 * @author    PrestaShop SA and Contributors <contact@prestashop.com>
 * @copyright Since 2007 PrestaShop SA and Contributors
 * @license   https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
 */

namespace PrestaShop\Module\AutoUpgrade\UpgradeTools\Module;

use Exception;
use LogicException;
use PrestaShop\Module\AutoUpgrade\Exceptions\UpgradeException;
use PrestaShop\Module\AutoUpgrade\Log\Logger;
use PrestaShop\Module\AutoUpgrade\Services\DownloadService;
use PrestaShop\Module\AutoUpgrade\UpgradeTools\Translator;
use Symfony\Component\Filesystem\Filesystem;

class ModuleDownloader
{
    /** @var Translator */
    private $translator;

    /** @var DownloadService */
    private $downloadService;

    /** @var Logger */
    private $logger;

    /** @var string */
    private $downloadFolder;

    public function __construct(DownloadService $downloadService, Translator $translator, Logger $logger, string $downloadFolder)
    {
        $this->downloadService = $downloadService;
        $this->translator = $translator;
        $this->logger = $logger;
        $this->downloadFolder = $downloadFolder;
    }

    /**
     * @throws UpgradeException
     */
    public function downloadModule(ModuleDownloaderContext $moduleDownloaderContext): void
    {
        if (empty($moduleDownloaderContext->getUpdateSources())) {
            throw new LogicException('List of updates is empty.');
        }

        $downloadSuccessful = false;

        for ($i = 0; !$downloadSuccessful && $i < count($moduleDownloaderContext->getUpdateSources()); ++$i) {
            try {
                $this->attemptDownload($moduleDownloaderContext, $i);
                $downloadSuccessful = true;
            } catch (Exception $e) {
                $this->logger->debug($e->getMessage());
                $this->logger->debug($this->translator->trans('Download of source #%s has failed.', [$i]));
            }
        }

        if (!$downloadSuccessful) {
            $message = $this->translator->trans('All download attempts have failed. The module %s has been disabled. You can try to update it manually afterwards.', [$moduleDownloaderContext->getModuleName()]);
            throw (new UpgradeException($message))->setSeverity(UpgradeException::SEVERITY_WARNING);
        }
    }

    /**
     * @throws UpgradeException
     */
    private function attemptDownload(ModuleDownloaderContext $moduleDownloaderContext, int $index): void
    {
        $moduleSource = $moduleDownloaderContext->getUpdateSources()[$index];
        $filesystem = new Filesystem();

        $destinationPath = $this->downloadFolder;

        if ($moduleSource->isZipped()) {
            $destinationPath .= '/' . $moduleDownloaderContext->getModuleName() . '.zip';
            $this->downloadService->downloadWithRetry($moduleSource->getPath(), $destinationPath);
        } else {
            // Module contents is already unzipped.
            // We move it first in the sandbox folder to make sure all the files can be read.
            $filesystem->mirror($moduleSource->getPath(), $this->downloadFolder);
        }

        $this->assertDownloadedContentsIsValid($destinationPath);
        $moduleDownloaderContext->setPathToModuleUpdate($destinationPath);

        $this->logger->notice($this->translator->trans('Module %s update files (%s => %s) have been fetched from %s.', [
            $moduleDownloaderContext->getModuleName(),
            $moduleDownloaderContext->getReferenceVersion(),
            $moduleSource->getNewVersion(),
            $moduleSource->getPath(),
        ]));
    }

    /**
     * @throws UpgradeException If download content is invalid
     */
    private function assertDownloadedContentsIsValid(string $destinationPath): void
    {
        if (is_file($destinationPath)) {
            // Arbitrary size value checking the zip file has at least a file in it.
            if (filesize($destinationPath) <= 300) {
                throw (new UpgradeException($this->translator->trans('The received module archive is empty.')))->setSeverity(UpgradeException::SEVERITY_WARNING);
            }

            $downloadedFile = fopen($destinationPath, 'r');
            if (!$downloadedFile || fread($downloadedFile, 5) == '<?xml') {
                throw (new UpgradeException($this->translator->trans('Invalid contents from provider (Got an XML file).')))->setSeverity(UpgradeException::SEVERITY_WARNING);
            }
            fclose($downloadedFile);
        }
    }
}