AbstractBaseRetriever   A
last analyzed

Complexity

Total Complexity 17

Size/Duplication

Total Lines 134
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 31
c 1
b 0
f 0
dl 0
loc 134
ccs 36
cts 36
cp 1
rs 10
wmc 17

10 Methods

Rating   Name   Duplication   Size   Complexity  
A setDownloader() 0 3 1
A __construct() 0 4 2
A getDownloader() 0 3 1
A getBasePath() 0 3 1
A buildPath() 0 7 2
A retrieveHistory() 0 3 1
A addToHistory() 0 3 1
A urlParts() 0 10 3
A clearHistory() 0 3 1
A download() 0 24 4
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
    }
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
    }
74
75 16
    public function buildPath(string $url): string
76
    {
77 16
        $parts = $this->urlParts($url);
78 16
        if (false === $parts) {
1 ignored issue
show
introduced by
The condition false === $parts is always true.
Loading history...
79 3
            throw new InvalidArgumentException("Invalid URL: $url");
80
        }
81 13
        return $this->basePath . '/' . $parts['host'] . '/' . ltrim($parts['path'], '/');
82
    }
83
84 13
    public function download(string $url): string
85
    {
86
        // validate resource
87 13
        if ('' === $url) {
88 1
            throw new UnexpectedValueException('The argument to download is empty');
89
        }
90
91
        // set destination
92 12
        $localPath = $this->buildPath($url);
93
94
        // create local path
95 12
        $dirname = dirname($localPath);
96
        /** @noinspection PhpUsageOfSilenceOperatorInspection */
97 12
        if (! is_dir($dirname) && ! @mkdir($dirname, 0777, true)) {
98 1
            throw new RuntimeException("Unable to create directory $dirname");
99
        }
100
101
        // download the file into its final destination
102 11
        $this->downloader->downloadTo($url, $localPath);
103
104
        // check content is valid
105 10
        $this->checkIsValidDownloadedFile($url, $localPath);
106
107 8
        return $localPath;
108
    }
109
110
    /**
111
     * @return array<string, string>
112
     */
113 3
    public function retrieveHistory(): array
114
    {
115 3
        return $this->history;
116
    }
117
118
    /**
119
     * @return void
120
     */
121 7
    protected function clearHistory(): void
122
    {
123 7
        $this->history = [];
124
    }
125
126
    /**
127
     * @param string $source
128
     * @param string $localpath
129
     * @return void
130
     */
131 7
    protected function addToHistory(string $source, string $localpath): void
132
    {
133 7
        $this->history[$source] = $localpath;
134
    }
135
136
    /**
137
     * Retrieve url parts (as in parse_url)
138
     * If url is malformed return false
139
     *
140
     * @param string $url
141
     * @return string[]|false
142
     */
143 16
    protected function urlParts(string $url)
144
    {
145 16
        if (false === filter_var($url, FILTER_VALIDATE_URL, FILTER_FLAG_PATH_REQUIRED)) {
146 4
            return false;
147
        }
148 13
        $parsed = parse_url($url);
149 13
        if (false === $parsed) {
150
            return false; // @codeCoverageIgnore
151
        }
152 13
        return array_map('strval', $parsed);
153
    }
154
}
155