1:  2:  3:  4:  5:  6:  7:  8:  9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 
<?php
namespace Omeka\File;

use Omeka\Stdlib\ErrorStore;
use Zend\Log\Logger;
use Zend\ServiceManager\ServiceLocatorInterface;
use Omeka\Stdlib\Message;

/**
 * File downloader service
 */
class Downloader
{
    /**
     * @var ServiceLocatorInterface
     */
    protected $services;

    /**
     * @var TempFileFactory
     */
    protected $tempFileFactory;

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

    /**
     * @param ServiceLocatorInterface $services
     * @param TempFileFactory $tempFileFactory
     */
    public function __construct(ServiceLocatorInterface $services,
        TempFileFactory $tempFileFactory, Logger $logger
    ) {
        $this->services = $services;
        $this->tempFileFactory = $tempFileFactory;
        $this->logger = $logger;
    }

    /**
     * Download a file from a remote URI.
     *
     * Pass the $errorStore object if an error should raise an API validation
     * error.
     *
     * @param string|\Zend\Uri\Http $uri
     * @param null|ErrorStore $errorStore
     * @return TempFile|false False on error
     */
    public function download($uri, ErrorStore $errorStore = null)
    {
        $client = $this->services->get('Omeka\HttpClient'); // non-shared service
        $tempFile = $this->tempFileFactory->build();

        // Disable compressed response; it's broken alongside streaming
        $client->getRequest()->getHeaders()->addHeaderLine('Accept-Encoding', 'identity');
        $client->setUri($uri)->setStream($tempFile->getTempPath());

        // Attempt three requests before handling an exception.
        $attempt = 0;
        while (true) {
            try {
                $response = $client->send();
                break;
            } catch (\Exception $e) {
                if (++$attempt === 3) {
                    $this->logger->err((string) $e);
                    if ($errorStore) {
                        $message = new Message(
                            'Error downloading %s: %s', // @translate
                            (string) $uri, $e->getMessage()
                            );
                        $errorStore->addError('download', $message);
                    }
                    return false;
                }
            }
        }

        if (!$response->isOk()) {
            $message = sprintf(
                'Error downloading %s: %s %s', // @translate
                (string) $uri, $response->getStatusCode(), $response->getReasonPhrase()
                );
            if ($errorStore) {
                $errorStore->addError('download', $message);
            }
            $this->logger->err($message);
            return false;
        }

        return $tempFile;
    }
}