Completed
Push — master ( 59ebde...3174b5 )
by ReliQ
01:08
created

Provider::__construct()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 18
rs 9.6666
c 0
b 0
f 0
cc 2
nc 2
nop 4
1
<?php
2
3
declare(strict_types=1);
4
5
namespace ReliqArts\Docweaver\Service\Documentation;
6
7
use Illuminate\Contracts\Cache\Repository as Cache;
8
use Illuminate\Contracts\Filesystem\FileNotFoundException;
9
use Psr\SimpleCache\InvalidArgumentException;
10
use ReliqArts\Docweaver\Contract\ConfigProvider;
11
use ReliqArts\Docweaver\Contract\Documentation\Provider as ProviderContract;
12
use ReliqArts\Docweaver\Contract\Filesystem;
13
use ReliqArts\Docweaver\Contract\MarkdownParser;
14
use ReliqArts\Docweaver\Exception\BadImplementation;
15
use ReliqArts\Docweaver\Model\Product;
16
17
final class Provider implements ProviderContract
18
{
19
    private const CACHE_TIMEOUT_SECONDS = 60 * 5;
20
    private const PAGE_INDEX = 'index';
21
    private const FILE_EXTENSION = 'md';
22
23
    /**
24
     * The cache implementation.
25
     *
26
     * @var Cache
27
     */
28
    private Cache $cache;
0 ignored issues
show
Bug introduced by
This code did not parse for me. Apparently, there is an error somewhere around this line:

Syntax error, unexpected T_STRING, expecting T_FUNCTION or T_CONST
Loading history...
29
30
    /**
31
     * The cache key.
32
     *
33
     * @var string
34
     */
35
    private string $cacheKey;
36
37
    /**
38
     * Documentation resource directory.
39
     *
40
     * @var string
41
     */
42
    private string $documentationDirectory;
43
44
    /**
45
     * @var Filesystem
46
     */
47
    private Filesystem $filesystem;
48
49
    /**
50
     * @var ConfigProvider
51
     */
52
    private ConfigProvider $configProvider;
53
54
    /**
55
     * @var MarkdownParser
56
     */
57
    private MarkdownParser $markdownParser;
58
59
    /**
60
     * Create a new documentation instance.
61
     *
62
     * @throws BadImplementation
63
     */
64
    public function __construct(
65
        Filesystem $filesystem,
66
        Cache $cache,
67
        ConfigProvider $configProvider,
68
        MarkdownParser $markdownParser
69
    ) {
70
        $this->filesystem = $filesystem;
71
        $this->cache = $cache;
72
        $this->configProvider = $configProvider;
73
        $this->documentationDirectory = $configProvider->getDocumentationDirectory();
74
        $this->cacheKey = $this->configProvider->getCacheKey();
75
        $this->markdownParser = $markdownParser;
76
        $documentationDirectoryAbsolutePath = base_path($this->documentationDirectory);
77
78
        if (!$this->filesystem->isDirectory($documentationDirectoryAbsolutePath)) {
79
            throw new BadImplementation(sprintf('Documentation resource directory `%s` does not exist.', $this->documentationDirectory));
80
        }
81
    }
82
83
    /**
84
     * @throws InvalidArgumentException
85
     * @throws FileNotFoundException
86
     */
87
    public function getPage(Product $product, string $version, string $page = null): string
88
    {
89
        $page = $page ?? self::PAGE_INDEX;
90
        $cacheKey = sprintf('%s.%s.%s.%s', $this->cacheKey, $product->getKey(), $version, $page);
91
92
        if ($this->cache->has($cacheKey)) {
93
            return $this->cache->get($cacheKey);
94
        }
95
96
        $pageContent = $this->getPageContent($product, $version, $page);
97
98
        $this->cache->put($cacheKey, $pageContent, self::CACHE_TIMEOUT_SECONDS);
99
100
        return $pageContent;
101
    }
102
103
    public function replaceLinks(Product $product, string $version, string $content): string
104
    {
105
        $routePrefix = $this->configProvider->getRoutePrefix();
106
        $versionPlaceholder = '{{version}}';
107
108
        // ensure product name exists in url
109
        if (!empty($product)) {
110
            $content = str_replace(
111
                sprintf('docs/%s', $versionPlaceholder),
112
                sprintf('%s/%s/%s', $routePrefix, $product->getKey(), $version),
113
                $content
114
            );
115
        }
116
117
        return str_replace($versionPlaceholder, $version, $content);
118
    }
119
120
    public function sectionExists(Product $product, string $version, string $page): bool
121
    {
122
        $filePath = $this->getFilePathForProductPage($product, $version, $page);
123
124
        return $this->filesystem->exists($filePath);
125
    }
126
127
    private function getFilePathForProductPage(Product $product, string $version, string $page): string
128
    {
129
        $directory = $product->getDirectory();
130
        $filename = ($page === self::PAGE_INDEX) ? $this->configProvider->getContentIndexPageName() : $page;
131
132
        return sprintf('%s/%s/%s.%s', $directory, $version, $filename, self::FILE_EXTENSION);
133
    }
134
135
    /**
136
     * @throws FileNotFoundException
137
     */
138
    private function getPageContent(Product $product, string $version, string $page): string
139
    {
140
        $filePath = $this->getFilePathForProductPage($product, $version, $page);
141
        $pageContent = '';
142
143
        if ($this->filesystem->exists($filePath)) {
144
            $fileContents = $this->filesystem->get($filePath);
145
            $pageContent = $this->replaceLinks(
146
                $product,
147
                $version,
148
                $this->markdownParser->parse($fileContents)
149
            );
150
        }
151
152
        return $pageContent;
153
    }
154
}
155