Passed
Branch merge_replace_relative (af7c75)
by Enjoys
15:19
created

ReplaceRelative::getContent()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 25
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 14
c 1
b 0
f 0
nc 2
nop 0
dl 0
loc 25
rs 9.7998
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Enjoys\AssetsCollector\Content;
6
7
use Enjoys\AssetsCollector\Asset;
8
use Enjoys\AssetsCollector\Environment;
9
use Enjoys\AssetsCollector\Helpers;
10
use Enjoys\UrlConverter;
11
use Psr\Log\LoggerInterface;
12
use Psr\Log\NullLogger;
13
14
/**
15
 * Class ReplaceRelative
16
 * @package Enjoys\AssetsCollector\Content
17
 */
18
class ReplaceRelative
19
{
20
    private string $content;
21
    private LoggerInterface $logger;
22
    private Asset $asset;
23
    private Environment $environment;
24
    private string $path;
25
26
    public function __construct(string $content, string $path, Asset $asset, Environment $environment)
27
    {
28
        $this->logger = new NullLogger();
29
        $this->content = $content;
30
        $this->asset = $asset;
31
        $this->environment = $environment;
32
        $this->path = $path;
33
    }
34
35
36
    /**
37
     * @return string
38
     * @throws \Exception
39
     */
40
    public function getContent(): string
41
    {
42
43
        $result = preg_replace_callback(
44
            '/(url\([\'"]?)(?!["\'a-z]+:|[\'"]?\/{2})(.+?[^\'"])([\'"]?\))/i',
45
            function (array $m) {
46
                /** @var string[] $m */
47
                $normalizedPath = $this->getNormalizedPath($m[2]);
48
                if ($normalizedPath === false) {
49
                    return $m[1] . $m[2] . $m[3];
50
                }
51
52
                return $m[1] . $normalizedPath . $m[3];
53
            },
54
            $this->content
55
        );
56
57
        if ($result === null) {
58
            $this->logger->notice(
59
                sprintf('Regex return null value. Returned empty string: %s', $this->path)
60
            );
61
            return '';
62
        }
63
        $this->logger->info(sprintf('ReplaceRelativeUrls: %s', $this->path));
64
        return $result;
65
    }
66
67
    /**
68
     * @param LoggerInterface $logger
69
     */
70
    public function setLogger(LoggerInterface $logger): void
71
    {
72
        $this->logger = $logger;
73
    }
74
75
    /**
76
     * @param string $relativePath
77
     * @return false|string
78
     * @throws \Exception
79
     */
80
    private function getNormalizedPath(string $relativePath)
81
    {
82
        if ($this->asset->isUrl()) {
83
            return $this->replaceUrls($this->path, $relativePath);
84
        }
85
        return $this->replacePath($this->path, $relativePath);
86
    }
87
88
    /**
89
     * @param string $baseUrl
90
     * @param string $relativeUrl
91
     * @return false|string
92
     * @psalm-suppress MixedReturnStatement
93
     * @psalm-suppress MixedInferredReturnType
94
     */
95
    private function replaceUrls(string $baseUrl, string $relativeUrl)
96
    {
97
        $urlConverter = new UrlConverter();
98
        return $urlConverter->relativeToAbsolute($baseUrl, $relativeUrl);
99
    }
100
101
    /**
102
     * @param string $filePath
103
     * @param string $relativePath
104
     * @return false|string
105
     * @throws \Exception
106
     */
107
    private function replacePath(string $filePath, string $relativePath)
108
    {
109
        $realpath = realpath(
110
            pathinfo($filePath, PATHINFO_DIRNAME) . DIRECTORY_SEPARATOR
0 ignored issues
show
Bug introduced by
Are you sure pathinfo($filePath, Enjo...ntent\PATHINFO_DIRNAME) of type array|string can be used in concatenation? ( Ignorable by Annotation )

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

110
            /** @scrutinizer ignore-type */ pathinfo($filePath, PATHINFO_DIRNAME) . DIRECTORY_SEPARATOR
Loading history...
111
            . parse_url($relativePath, PHP_URL_PATH)
112
        );
113
114
        if ($realpath === false) {
115
            return false;
116
        }
117
118
        $relativeFullPath = \str_replace(
119
            '\\',
120
            '/',
121
            \str_replace(
122
                [
123
                    $this->environment->getCompileDir(),
124
                    $this->environment->getProjectDir()
125
                ],
126
                '',
127
                $realpath
128
            )
129
        );
130
131
        Helpers::createSymlink($this->environment->getCompileDir() . $relativeFullPath, $realpath, $this->logger);
132
133
        return $this->environment->getBaseUrl() . $relativeFullPath;
134
    }
135
}
136