Passed
Push — master ( c79df9...45a681 )
by Enjoys
49s queued 13s
created

Reader::replaceRelativeUrlsAndCreatedSymlinks()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 13
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 4.0312

Importance

Changes 1
Bugs 1 Features 0
Metric Value
cc 4
eloc 7
c 1
b 1
f 0
nc 3
nop 0
dl 0
loc 13
ccs 7
cts 8
cp 0.875
crap 4.0312
rs 10
1
<?php
2
3
namespace Enjoys\AssetsCollector\Content;
4
5
use Enjoys\AssetsCollector\Asset;
6
use Enjoys\AssetsCollector\Content\Minify\MinifyFactory;
7
use Enjoys\AssetsCollector\Environment;
8
use Psr\Http\Client\ClientInterface;
9
use Psr\Http\Message\RequestFactoryInterface;
10
use Psr\Log\LoggerInterface;
11
use Psr\Log\NullLogger;
12
13
/**
14
 * Class Reader
15
 * @package Enjoys\AssetsCollector\Content
16
 */
17
class Reader
18
{
19
    /**
20
     * @var Asset
21
     */
22
    private Asset $asset;
23
24
    /**
25
     * @var false|string
26
     */
27
    private $content;
28
    /**
29
     * @var false|string
30
     */
31
    private $path;
32
33
    private Environment $environment;
34
    /**
35
     * @var LoggerInterface|NullLogger
36
     */
37
    private LoggerInterface $logger;
38
39
    /**
40
     * Reader constructor.
41
     * @param Asset $asset
42
     * @param Environment $environment
43
     * @param LoggerInterface|null $logger
44
     */
45 21
    public function __construct(
46
        Asset $asset,
47
        Environment $environment,
48
        LoggerInterface $logger = null
49
    ) {
50 21
        $this->environment = $environment;
51 21
        $this->asset = $asset;
52 21
        $this->logger = $logger ?? $this->environment->getLogger();
53 21
        $this->path = $this->asset->getPath();
54 21
        $this->content = $this->getContent();
55
    }
56
57
    /**
58
     * @throws \Exception
59
     */
60 13
    public function getContents(): string
61
    {
62 13
        if ($this->content === false || $this->path === false) {
63 4
            $this->logger->notice(sprintf('Nothing return: path is `%s`', $this->asset->getOrigPath()));
64 4
            return '';
65
        }
66 9
        return $this->content;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->content could return the type true which is incompatible with the type-hinted return string. Consider adding an additional type-check to rule them out.
Loading history...
67
    }
68
69
70
    /**
71
     * @return false|string
72
     */
73 21
    private function getContent()
74
    {
75 21
        if ($this->path === false) {
76 1
            return false;
77
        }
78
79 20
        if ($this->asset->isUrl()) {
80 4
            return $this->readUrl($this->path);
0 ignored issues
show
Bug introduced by
It seems like $this->path can also be of type true; however, parameter $url of Enjoys\AssetsCollector\Content\Reader::readUrl() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

80
            return $this->readUrl(/** @scrutinizer ignore-type */ $this->path);
Loading history...
81
        }
82 16
        return $this->readFile($this->path);
0 ignored issues
show
Bug introduced by
It seems like $this->path can also be of type true; however, parameter $filename of Enjoys\AssetsCollector\Content\Reader::readFile() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

82
        return $this->readFile(/** @scrutinizer ignore-type */ $this->path);
Loading history...
83
    }
84
85
    /**
86
     * @return false|string
87
     */
88 4
    private function readUrl(string $url)
89
    {
90
        if (
91 4
            null !== ($httpClient = $this->environment->getHttpClient())
92 4
            && null !== ($requestFactory = $this->environment->getRequestFactory())
93
        ) {
94 2
            return $this->readWithPsrHttpClient($url, $httpClient, $requestFactory);
95
        }
96
97 2
        return $this->readWithPhpFileGetContents($url);
98
    }
99
100
    /**
101
     * @return false|string
102
     * @throws \RuntimeException
103
     */
104 18
    private function readWithPhpFileGetContents(string $url)
105
    {
106
        try {
107
            //Clear the most recent error
108 18
            error_clear_last();
109 18
            $content = @file_get_contents($url);
110
            /** @var null|string[] $error */
111 18
            $error = error_get_last();
112 18
            if ($error !== null) {
113 2
                throw new \RuntimeException(sprintf("%s", $error['message']));
114
            }
115 16
            return $content;
116 2
        } catch (\Throwable $e) {
117 2
            $this->logger->notice($e->getMessage());
118 2
            return false;
119
        }
120
    }
121
122
    /**
123
     * @return false|string
124
     */
125 2
    private function readWithPsrHttpClient(
126
        string $url,
127
        ClientInterface $client,
128
        RequestFactoryInterface $requestFactory
129
    ) {
130
        try {
131 2
            $response = $client->sendRequest(
132 2
                $requestFactory->createRequest('get', $url)
133 2
            );
134
135 2
            if ($response->getStatusCode() !== 200) {
136 1
                throw new \RuntimeException(
137 1
                    sprintf('HTTP error: %s - %s', $response->getStatusCode(), $response->getReasonPhrase())
138 1
                );
139
            }
140
141 1
            $this->logger->info(sprintf('Read: %s', $url));
142 1
            return $response->getBody()->getContents();
143 1
        } catch (\Throwable $e) {
144 1
            $this->logger->notice($e->getMessage());
145 1
            return false;
146
        }
147
    }
148
149
    /**
150
     * @param string $filename
151
     * @return false|string
152
     */
153 16
    private function readFile(string $filename)
154
    {
155 16
        if (!file_exists($filename)) {
156
            $this->logger->notice(sprintf("Файла по указанному пути нет: %s", $filename));
157
            return false;
158
        }
159
160
        try {
161 16
            $content = $this->readWithPhpFileGetContents($filename);
162
        } catch (\RuntimeException $e) {
163
            $this->logger->notice(sprintf("Ошибка чтения содержимого файла: %s", $e->getMessage()));
164
            return false;
165
        }
166
167 16
        $this->logger->info(sprintf('Read: %s', $filename));
168 16
        return $content;
169
    }
170
171
    /**
172
     * @param LoggerInterface|NullLogger $logger
173
     */
174
    public function setLogger($logger): void
175
    {
176
        $this->logger = $logger;
177
    }
178
179
    /**
180
     * @throws \Exception
181
     */
182 12
    public function replaceRelativeUrlsAndCreatedSymlinks(): Reader
183
    {
184 12
        if ($this->content === false || $this->path === false) {
185
            return $this;
186
        }
187
188 12
        if ($this->asset->getOptions()->isReplaceRelativeUrls()) {
189 12
            $replaceRelativeUrls = new ReplaceRelative($this->content, $this->path, $this->asset, $this->environment);
0 ignored issues
show
Bug introduced by
It seems like $this->content can also be of type true; however, parameter $content of Enjoys\AssetsCollector\C...Relative::__construct() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

189
            $replaceRelativeUrls = new ReplaceRelative(/** @scrutinizer ignore-type */ $this->content, $this->path, $this->asset, $this->environment);
Loading history...
Bug introduced by
It seems like $this->path can also be of type true; however, parameter $path of Enjoys\AssetsCollector\C...Relative::__construct() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

189
            $replaceRelativeUrls = new ReplaceRelative($this->content, /** @scrutinizer ignore-type */ $this->path, $this->asset, $this->environment);
Loading history...
190 12
            $replaceRelativeUrls->setLogger($this->logger);
191 12
            $this->content = $replaceRelativeUrls->getContent();
192
        }
193
194 12
        return $this;
195
    }
196
197 5
    public function minify(): Reader
198
    {
199 5
        if ($this->content === false || $this->path === false) {
200
            return $this;
201
        }
202 5
        if ($this->asset->getOptions()->isMinify()) {
203 4
            $this->content = MinifyFactory::minify(
204 4
                    $this->content,
0 ignored issues
show
Bug introduced by
It seems like $this->content can also be of type true; however, parameter $content of Enjoys\AssetsCollector\C...MinifyFactory::minify() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

204
                    /** @scrutinizer ignore-type */ $this->content,
Loading history...
205 4
                    $this->asset->getType(),
206 4
                    $this->environment
207 4
                )->getContent() . "\n";
208 4
            $this->logger->info(sprintf('Minify: %s', $this->path));
0 ignored issues
show
Bug introduced by
It seems like $this->path can also be of type true; however, parameter $values of sprintf() does only seem to accept double|integer|string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

208
            $this->logger->info(sprintf('Minify: %s', /** @scrutinizer ignore-type */ $this->path));
Loading history...
209
        }
210
211 5
        return $this;
212
    }
213
}
214