Completed
Pull Request — master (#5)
by Michal
06:52
created

ManifestService::formatOutput()   B

Complexity

Conditions 10
Paths 2

Size

Total Lines 34

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 20
CRAP Score 11.7434

Importance

Changes 0
Metric Value
dl 0
loc 34
ccs 20
cts 27
cp 0.7407
rs 7.6666
c 0
b 0
f 0
cc 10
nc 2
nop 3
crap 11.7434

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
declare(strict_types=1);
3
4
namespace Webrouse\AssetMacro;
5
6
7
use Nette\Http\IRequest;
8
use Nette\Utils\Strings;
9
use Tracy\Debugger;
10
use Webrouse\AssetMacro\Exceptions\InvalidVariableException;
11
use Webrouse\AssetMacro\Exceptions\ManifestNotFoundException;
12
13
class ManifestService
14
{
15
	/** @var Config */
16
	private $config;
17
18
	/** @var string */
19
	private $baseUrl;
20
21
	/** @var string */
22
	private $basePath;
23
24
	/** @var Manifest[] */
25
	private $manifestCache = [];
26
27
28 1
	public function __construct(Config $config, IRequest $httpRequest)
29
	{
30 1
		$this->config = $config;
31 1
		$url = $httpRequest->getUrl();
32 1
		$this->baseUrl = $url->getBaseUrl() . $this->config->getPublicPath();
33 1
		$this->basePath = $url->getBasePath() . $this->config->getPublicPath();
34 1
		Debugger::dump($this->baseUrl);
35 1
		Debugger::dump($this->basePath);
36 1
	}
37
38
39
	public function getConfig(): Config
40
	{
41 1
		return $this->config;
42
	}
43
44
45 1
	public function getManifest(string $assetPath = null, bool $needed = true): ?Manifest
46
	{
47
		// Manifest is specified by array in config
48 1
		if (($data = $this->config->getManifestAsArray()) !== null) {
49 1
			$key = '__array__';
50 1
			if (empty($this->manifestCache[$key])) {
51 1
				$this->manifestCache[$key] = new Manifest($this->config, null, $data);
52
			}
53 1
			return $this->manifestCache[$key];
54
		}
55
56
		// Load manifest from JSON file
57 1
		$path = $this->config->getManifestPath() ?? $this->autodetectManifest($assetPath, $needed);
58 1
		if (!$path) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $path of type string|null is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
59 1
			return null;
60
		}
61
62 1
		if (!file_exists($path)) {
63 1
			Utils::throwError(
64 1
				new ManifestNotFoundException(sprintf("Manifest file not found: '%s'.", $path)),
65 1
				$this->config->getMissingManifestPolicy(),
66 1
				$needed
67
			);
68 1
			return null;
69
		}
70
71 1
		if (empty($this->manifestCache[$path])) {
72 1
			$this->manifestCache[$path] = new Manifest($this->config, $path);
73
		}
74
75 1
		return $this->manifestCache[$path];
76
	}
77
78
79 1
	public function getAsset(string $path, bool $needed = true): ?Asset
80
	{
81 1
		$manifest = $this->getManifest($path, $needed);
82 1
		return $manifest ? $manifest->getAsset($path, $needed) : $this->getAssetManifestNotFound($path);
83
	}
84
85
86 1
	public function formatOutput(Asset $asset, string $format = '%url%', bool $absolute = false): string
87
	{
88 1
		$base = $absolute ? $this->baseUrl : $this->basePath;
89
90 1
		return Strings::replace($format,
91 1
			'/%([^%]+)%/',
92 1
			function ($matches) use ($asset, $format, $base) {
93 1
				switch ($matches[1]) {
94
					case 'content':
95 1
						$content = file_get_contents($asset->getAbsolutePath());
96 1
						return $content ? trim($content) : '';
97
					case 'raw':
98 1
						return $asset->getRevision()->getRawValue();
99
					case 'base':
100 1
						return $base;
101
					case 'basePath':
102 1
						return $this->basePath;
103
					case 'baseUrl':
104 1
						return $this->baseUrl;
105
					case 'path':
106 1
						return $asset->getRelativePath();
107
					case 'url':
108 1
						return sprintf('%s%s', $base, $asset->getRelativeUrl());
109
					default:
110 1
						$msg = sprintf(
111
							"Asset macro: Invalid variable '%s' in format '%s'. " .
112 1
							'Use one of allowed variables: %%raw%%, %%basePath%%, %%path%%, %%url%%.',
113 1
							$matches[1],
114 1
							$format
115
						);
116 1
						throw new InvalidVariableException($msg);
117
				}
118 1
			});
119
	}
120
121
122 1
	protected function getAssetManifestNotFound(string $path): Asset
123
	{
124 1
		$revision = new Revision($this->config, $path, null);
125 1
		return new Asset($revision);
126
	}
127
128
129 1
	private function autodetectManifest(string $assetPath = null, bool $needed = true): ?string
130
	{
131
		// Finding a manifest begins in the asset directory
132 1
		$dir = $assetPath ?
133 1
			$this->config->getAssetsPath() . DIRECTORY_SEPARATOR . Utils::normalizePath(dirname($assetPath)) :
134 1
			$this->config->getAssetsPath();
135
136
		// Autodetect manifest
137 1
		while (Strings::startsWith($dir, $this->config->getAssetsPath())) {
138 1
			foreach ($this->config->getManifestAutodetectPaths() as $path) {
139 1
				$path = $dir . DIRECTORY_SEPARATOR . $path;
140 1
				if (file_exists($path)) {
141 1
					return $path;
142
				}
143
			}
144
145 1
			$dir = dirname($dir); // go up ../
146
		}
147
148 1
		Utils::throwError(
149 1
			new ManifestNotFoundException(sprintf('Manifest not found in: %s.', implode(', ', $this->config->getManifestAutodetectPaths()))),
150 1
			$this->config->getMissingManifestPolicy(),
151 1
			$needed
152
		);
153
154 1
		return null;
155
	}
156
}
157