Passed
Pull Request — master (#3)
by Carlos C
03:04 queued 01:30
created

AbstractBaseRetriever::getDownloader()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Eclipxe\XmlResourceRetriever;
6
7
use Eclipxe\XmlResourceRetriever\Downloader\DownloaderInterface;
8
use Eclipxe\XmlResourceRetriever\Downloader\PhpDownloader;
9
use InvalidArgumentException;
10
use RuntimeException;
11
use UnexpectedValueException;
12
13
/**
14
 * This is an abstract base imlementation of RetrieverInterface
15
 *
16
 * It contains basic helper functions and implement for construct, getters, setters, history, buildPath and download
17
 * There are other type of resources that could be retrieved and might use all this logic
18
 */
19
abstract class AbstractBaseRetriever implements RetrieverInterface
20
{
21
    /** @var string */
22
    private $basePath;
23
24
    /** @var DownloaderInterface */
25
    private $downloader;
26
27
    /**
28
     * This variable stores the list of retrieved resources to avoid infinite recursion
29
     * @var array<string, string>
30
     */
31
    private $history = [];
32
33
    /**
34
     * This method checks if the recently downloaded file from $source located at $path
35
     * is a valid resource, if not will remove the file and throw an exception
36
     *
37
     * @param string $source
38
     * @param string $localpath
39
     * @throws RuntimeException when the source is not valid
40
     * @return void
41
     */
42
    abstract protected function checkIsValidDownloadedFile(string $source, string $localpath): void;
43
44
    /**
45
     * Retriever constructor.
46
     *
47
     * @param string $basePath
48
     * @param DownloaderInterface|null $downloader
49
     */
50 19
    public function __construct(string $basePath, DownloaderInterface $downloader = null)
51
    {
52 19
        $this->basePath = $basePath;
53 19
        $this->setDownloader($downloader ? : new PhpDownloader());
54 19
    }
55
56 2
    public function getBasePath(): string
57
    {
58 2
        return $this->basePath;
59
    }
60
61 1
    public function getDownloader(): DownloaderInterface
62
    {
63 1
        return $this->downloader;
64
    }
65
66
    /**
67
     * @param DownloaderInterface $downloader
68
     * @return void
69
     */
70 19
    public function setDownloader(DownloaderInterface $downloader): void
71
    {
72 19
        $this->downloader = $downloader;
73 19
    }
74
75 16
    public function buildPath(string $url): string
76
    {
77 16
        if (false === $parts = $this->urlParts($url)) {
1 ignored issue
show
introduced by
The condition false === $parts = $this->urlParts($url) is always true.
Loading history...
78 3
            throw new InvalidArgumentException("Invalid URL: $url");
79
        }
80 13
        return $this->basePath . '/' . $parts['host'] . '/' . ltrim($parts['path'], '/');
81
    }
82
83 13
    public function download(string $url): string
84
    {
85
        // validate resource
86 13
        if ('' === $url) {
87 1
            throw new UnexpectedValueException('The argument to download is empty');
88
        }
89
90
        // set destination
91 12
        $localPath = $this->buildPath($url);
92
93
        // create local path
94 12
        $dirname = dirname($localPath);
95
        /** @noinspection PhpUsageOfSilenceOperatorInspection */
96 12
        if (! is_dir($dirname) && ! @mkdir($dirname, 0777, true)) {
97 1
            throw new RuntimeException("Unable to create directory $dirname");
98
        }
99
100
        // download the file into its final destination
101 11
        $this->downloader->downloadTo($url, $localPath);
102
103
        // check content is valid
104 10
        $this->checkIsValidDownloadedFile($url, $localPath);
105
106 8
        return $localPath;
107
    }
108
109
    /**
110
     * @return array<string, string>
111
     */
112 3
    public function retrieveHistory(): array
113
    {
114 3
        return $this->history;
115
    }
116
117
    /**
118
     * @return void
119
     */
120 7
    protected function clearHistory(): void
121
    {
122 7
        $this->history = [];
123 7
    }
124
125
    /**
126
     * @param string $source
127
     * @param string $localpath
128
     * @return void
129
     */
130 7
    protected function addToHistory(string $source, string $localpath): void
131
    {
132 7
        $this->history[$source] = $localpath;
133 7
    }
134
135
    /**
136
     * Retrieve url parts (as in parse_url)
137
     * If url is malformed return false
138
     *
139
     * @param string $url
140
     * @return string[]|false
141
     */
142 16
    protected function urlParts(string $url)
143
    {
144 16
        if (false === filter_var($url, FILTER_VALIDATE_URL, FILTER_FLAG_PATH_REQUIRED)) {
145 4
            return false;
146
        }
147 13
        $parsed = parse_url($url);
148 13
        if (false === $parsed) {
149
            return false; // @codeCoverageIgnore
150
        }
151 13
        return array_map('strval', $parsed);
152
    }
153
}
154