Issues (11)

src/Http/Controller/DocumentationController.php (2 issues)

Labels
Severity
1
<?php
2
3
declare(strict_types=1);
4
5
namespace ReliqArts\Docweaver\Http\Controller;
6
7
use Illuminate\Http\RedirectResponse;
8
use Illuminate\View\View;
9
use ReliqArts\Docweaver\Contract\ConfigProvider;
10
use ReliqArts\Docweaver\Contract\Documentation\Provider;
11
use ReliqArts\Docweaver\Contract\Logger;
12
use ReliqArts\Docweaver\Contract\Product\Finder;
13
use ReliqArts\Docweaver\Model\Product;
14
use Symfony\Component\DomCrawler\Crawler;
15
16
class DocumentationController
17
{
18
    private const DEFAULT_PAGE = 'installation';
19
20
    /**
21
     * @var ConfigProvider
22
     */
23
    protected ConfigProvider $configProvider;
24
25
    /**
26
     * The documentation repository.
27
     *
28
     * @var Provider
29
     */
30
    protected Provider $documentationProvider;
31
32
    /**
33
     * Doc home path.
34
     *
35
     * @var string
36
     */
37
    protected string $documentationHome;
38
39
    /**
40
     * @var Finder
41
     */
42
    protected Finder $productFinder;
43
44
    /**
45
     * @var Logger
46
     */
47
    protected Logger $logger;
48
49
    /**
50
     * Create a new controller instance.
51
     */
52
    public function __construct(ConfigProvider $configProvider, Logger $logger, Provider $docs, Finder $productFinder)
53
    {
54
        $this->logger = $logger;
55
        $this->documentationProvider = $docs;
56
        $this->productFinder = $productFinder;
57
        $this->documentationHome = $configProvider->getRoutePrefix();
58
        $this->configProvider = $configProvider;
59
    }
60
61
    /**
62
     * Show the documentation home page (docs).
63
     */
64
    public function index(): View
65
    {
66
        $templateConfig = $this->configProvider->getTemplateConfig();
67
        $title = $templateConfig->getIndexTitle();
68
        $products = $this->productFinder->listProducts();
69
70
        return view('docweaver::index', [
71
            'title' => $title,
72
            'products' => $products,
73
        ]);
74
    }
75
76
    /**
77
     * Show the index page for a product (docs/foo).
78
     *
79
     * @param mixed $productName
80
     */
81
    public function productIndex(string $productName): RedirectResponse
82
    {
83
        $product = $this->productFinder->findProduct($productName);
84
85
        if ($product === null || $product->getDefaultVersion() === Product::VERSION_UNKNOWN) {
86
            abort(404);
87
        }
88
89
        // route to default version
90
        return redirect()->route($this->configProvider->getProductPageRouteName(), [
91
            $product->getKey(),
92
            $product->getDefaultVersion(),
93
        ]);
94
    }
95
96
    /**
97
     * Show a documentation page.
98
     *
99
     * @param string $page
100
     *
101
     * @return RedirectResponse|View
102
     */
103
    public function show(string $productKey, string $version, string $page = null)
104
    {
105
        // ensure product exists
106
        $product = $this->productFinder->findProduct($productKey);
107
        if ($product === null) {
108
            abort(404);
109
        }
110
111
        // get default version for product
112
        $defaultVersion = $product->getDefaultVersion();
113
        if (!$product->hasVersion($version)) {
114
            return redirect(route(
115
                $this->configProvider->getProductPageRouteName(),
116
                [$product->getKey(), $defaultVersion]
117
            ), 301);
118
        }
119
120
        // get page content
121
        $page = $page ?: self::DEFAULT_PAGE;
122
        $content = $this->documentationProvider->getPage($product, $version, $page);
0 ignored issues
show
It seems like $product can also be of type null; however, parameter $product of ReliqArts\Docweaver\Cont...ion\Provider::getPage() does only seem to accept ReliqArts\Docweaver\Model\Product, 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

122
        $content = $this->documentationProvider->getPage(/** @scrutinizer ignore-type */ $product, $version, $page);
Loading history...
123
124
        // ensure page has content
125
        if (empty($content)) {
126
            $this->logger->warning(
127
                sprintf('Documentation page (%s) for %s has no content.', $page, $product->getName()),
128
                ['product' => $product]
129
            );
130
            abort(404);
131
        }
132
133
        $title = (new Crawler($content))->filterXPath('//h1');
134
        $section = '';
135
136
        // ensure section exists
137
        if ($this->documentationProvider->sectionExists($product, $version, $page)) {
0 ignored issues
show
It seems like $product can also be of type null; however, parameter $product of ReliqArts\Docweaver\Cont...ovider::sectionExists() does only seem to accept ReliqArts\Docweaver\Model\Product, 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

137
        if ($this->documentationProvider->sectionExists(/** @scrutinizer ignore-type */ $product, $version, $page)) {
Loading history...
138
            $section .= "/${page}";
139
        } elseif (!empty($page)) {
140
            // section does not exist, go to version index
141
            return redirect()->route($this->configProvider->getProductPageRouteName(), [$product->getKey(), $version]);
142
        }
143
144
        // set canonical
145
        $canonical = null;
146
        if ($this->documentationProvider->sectionExists($product, $defaultVersion, $page)) {
147
            $canonical = route(
148
                $this->configProvider->getProductPageRouteName(),
149
                [$product->getKey(), $defaultVersion, $page]
150
            );
151
        }
152
153
        return view('docweaver::page', [
154
            'canonical' => $canonical,
155
            'content' => $content,
156
            'currentProduct' => $product,
157
            'currentSection' => $section,
158
            'currentVersion' => $version,
159
            'index' => $this->documentationProvider->getPage($product, $version),
160
            'page' => $page,
161
            'title' => count($title) ? $title->text() : null,
162
            'versions' => $product->getVersions(),
163
        ]);
164
    }
165
}
166