MacroInlineFileLink::runMacro()   B
last analyzed

Complexity

Conditions 3
Paths 1

Size

Total Lines 39
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 39
rs 8.8571
c 0
b 0
f 0
cc 3
eloc 23
nc 1
nop 3
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Ublaboo\Anabelle\Markdown\Macros;
6
7
use Nette\Utils\Html;
8
use Ublaboo\Anabelle\Generator\Exception\DocuGeneratorException;
9
use Ublaboo\Anabelle\Markdown\DocuScope;
10
use Ublaboo\Anabelle\Markdown\Macros\Utils\FileHash;
11
12
final class MacroInlineFileLink implements IMacro
13
{
14
15
	const LINK_PATTERN = '/\[((?:[^][]++|(?R))*+)\]\(([^\)]*)\)/um';
16
17
	/**
18
	 * @var DocuScope
19
	 */
20
	private $docuScope;
21
22
	/**
23
	 * @var callable
24
	 */
25
	private $fileHashAlgo;
26
27
28
	public function __construct(DocuScope $docuScope, callable $fileHashAlgo = null)
29
	{
30
		$this->docuScope = $docuScope;
31
		$this->fileHashAlgo = $fileHashAlgo ?: [FileHash::class, 'md5File'];
32
	}
33
34
35
	/**
36
	 * @throws DocuGeneratorException
37
	 */
38
	public function runMacro(
39
		string $inputDirectory,
40
		string $outputDirectory,
41
		string & $content // Intentionally &
42
	): void
43
	{
44
		/**
45
		 * Substitute "#include" macros with actual files
46
		 */
47
		$content = preg_replace_callback(
48
			self::LINK_PATTERN,
49
			function(array $input) use ($inputDirectory): string {
50
				$text = $input[1];
51
				$path = trim($input[2], '/');
52
53
				if (file_exists($inputDirectory . '/' . $path)) {
54
					$fileHash = call_user_func($this->fileHashAlgo, $inputDirectory . '/' . $path);
55
					$fileName = $fileHash . '.' . pathinfo($path, PATHINFO_EXTENSION);
56
57
					$targetPath = $this->docuScope->getOutputDirectory() . '/_files' . '/' . $fileName;
58
59
					if (!file_exists(dirname($targetPath))) {
60
						mkdir(dirname($targetPath), 0755, true);
61
					}
62
63
					copy($inputDirectory . '/' . $path, $targetPath);
64
65
					$targetPath = preg_replace('~^[^/]+/~', '', $targetPath);
66
67
					return (string) Html::el('a')->href('_files/' . basename($targetPath))
68
						->setText($text)
69
						->target('_blank');
70
				}
71
72
				return "[$text]($path)";
73
			},
74
			$content
75
		);
76
	}
77
}
78