Tiki::insertDashTableOfContents()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 5
nc 1
nop 1
dl 0
loc 8
ccs 5
cts 5
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace App\Docsets;
4
5
use Godbout\DashDocsetBuilder\Docsets\BaseDocset;
6
use Illuminate\Support\Collection;
7
use Illuminate\Support\Facades\Storage;
8
use Illuminate\Support\Str;
9
use Wa72\HtmlPageDom\HtmlPageCrawler;
10
11
class Tiki extends BaseDocset
12
{
13
    public const CODE = 'tiki';
14
    public const NAME = 'Tiki';
15
    public const URL = 'doc.tiki.org';
16
    public const INDEX = 'All-the-Documentation.html';
17
    public const PLAYGROUND = 'https://tiki.org/Demo';
18
    public const ICON_16 = '../../icons/icon.png';
19
    public const ICON_32 = '../../icons/[email protected]';
20
    public const EXTERNAL_DOMAINS = [
21
        'themes.tiki.org',
22
    ];
23
24
25
    public function grab(): bool
26
    {
27
        $toIgnore = implode('|', [
28
            '\?refresh',
29
            '\?session_filters',
30
            '\?sort_mode',
31
            '/Plugins-',
32
            'comzone=',
33
            'cookietab=',
34
            'fullscreen=',
35
            'offset=',
36
            'todate=',
37
            'viewmode=',
38
            'PDF\.js',
39
            'Plugins(\?structure=.*)?$',
40
            'tikiversion=',
41
            'wp_files_sort_mode[0-9]=',
42
        ]);
43
44
        $toGet = implode('|', [
45
            '\.css',
46
            '\.gif',
47
            '\.ico',
48
            '\.jpg',
49
            '\.js',
50
            '\.png',
51
            '\.svg',
52
            '\.webmanifest',
53
            '/display',
54
            '/LIST',
55
            '/Module-',
56
            '/Plugin[^-]',
57
            '-Field(s)?(\?structure=HomePage\+UserGuide)?$',
58
            'Tiki_org_family',
59
            '[^:=]Wiki-Syntax'
60
        ]);
61
62
        system(
63
            "echo; wget doc.tiki.org/All-the-Documentation \
64
                --mirror \
65
                --trust-server-names \
66
                --header 'Cookie: javascript_enabled_detect=true' \
67
                --reject-regex='{$toIgnore}' \
68
                --accept-regex='{$toGet}' \
69
                --ignore-case \
70
                --page-requisites \
71
                --adjust-extension \
72
                --convert-links \
73
                --span-hosts \
74
                --domains={$this->externalDomains()} \
75
                --directory-prefix=storage/{$this->downloadedDirectory()} \
76
                -e robots=off \
77
                --quiet \
78
                --show-progress",
79
            $result
80
        );
81
82
        return $result === 0;
83
    }
84
85 12
    public function entries(string $file): Collection
86
    {
87 12
        $crawler = HtmlPageCrawler::create(Storage::get($file));
88
89 12
        $entries = collect();
90 12
        $entries = $entries->merge($this->pluginEntries($crawler, $file));
91 12
        $entries = $entries->merge($this->moduleEntries($crawler, $file));
92 12
        $entries = $entries->merge($this->fieldEntries($crawler, $file));
93 12
        $entries = $entries->merge($this->styleEntries($crawler, $file));
94
95 12
        return $entries;
96
    }
97
98 12
    protected function pluginEntries(HtmlPageCrawler $crawler, string $file)
99
    {
100 12
        $entries = collect();
101
102 12
        if (preg_match('/Plugin/i', $file)) {
103 12
            $path = $crawler->filter('link[rel=canonical]')->attr('href');
104
105
            $crawler->filter('#page-data > h1:first-of-type')->each(function (HtmlPageCrawler $node) use ($entries, $file, $path) {
106 12
                $entries->push([
107 12
                        'name' => $node->text(),
108 12
                        'type' => 'Plugin',
109 12
                        'path' => Str::after($file . '#' . Str::slug($path), $this->innerDirectory()),
110
                    ]);
111 12
            });
112
        }
113
114 12
        return $entries;
115
    }
116
117 12
    protected function moduleEntries(HtmlPageCrawler $crawler, string $file)
118
    {
119 12
        $entries = collect();
120
121 12
        if (preg_match('/Module/i', $file)) {
122 6
            $path = $crawler->filter('link[rel=canonical]')->attr('href');
123
124
            $crawler->filter('#page-data > h1:first-of-type')->each(function (HtmlPageCrawler $node) use ($entries, $file, $path) {
125 6
                $entries->push([
126 6
                        'name' => $node->text(),
127 6
                        'type' => 'Module',
128 6
                        'path' => Str::after($file . '#' . Str::slug($path), $this->innerDirectory()),
129
                    ]);
130 6
            });
131
        }
132
133 12
        return $entries;
134
    }
135
136 12
    protected function fieldEntries(HtmlPageCrawler $crawler, string $file)
137
    {
138 12
        $entries = collect();
139
140 12
        if (preg_match('/Tracker-Field/i', $file)) {
141 6
            $path = $crawler->filter('link[rel=canonical]')->attr('href');
142
143
            $crawler->filter('#page-data > h1:first-of-type')->each(function (HtmlPageCrawler $node) use ($entries, $file, $path) {
144 6
                $entries->push([
145 6
                        'name' => $node->text(),
146 6
                        'type' => 'Field',
147 6
                        'path' => Str::after($file . '#' . Str::slug($path), $this->innerDirectory()),
148
                    ]);
149 6
            });
150
        }
151
152 12
        return $entries;
153
    }
154
155 12
    protected function styleEntries(HtmlPageCrawler $crawler, string $file)
156
    {
157 12
        $entries = collect();
158
159 12
        if (preg_match('/Wiki-Syntax/i', $file)) {
160 6
            $path = $crawler->filter('link[rel=canonical]')->attr('href');
161
162
            $crawler->filter('#page-data > h1:first-of-type')->each(function (HtmlPageCrawler $node) use ($entries, $file, $path) {
163 6
                $entries->push([
164 6
                        'name' => $node->text(),
165 6
                        'type' => 'Style',
166 6
                        'path' => Str::after($file . '#' . Str::slug($path), $this->innerDirectory()),
167
                    ]);
168 6
            });
169
        }
170
171 12
        return $entries;
172
    }
173
174 12
    public function format(string $file): string
175
    {
176 12
        $crawler = HtmlPageCrawler::create(Storage::get($file));
177
178 12
        $this->removeNavbar($crawler);
179 12
        $this->removeLeftSidebarButton($crawler);
180 12
        $this->removeFullscreenButton($crawler);
181 12
        $this->removePageTopModules($crawler);
182 12
        $this->removeWikiActionsWrapper($crawler);
183 12
        $this->removeBreadcrumb($crawler);
184 12
        $this->removeTopbar($crawler);
185 12
        $this->removeLeftSidebar($crawler);
186 12
        $this->removeRightSidebar($crawler);
187 12
        $this->removePagebar($crawler);
188 12
        $this->removeFooter($crawler);
189 12
        $this->removeUnwantedJavaScript($crawler);
190
191 12
        $this->updateCss($crawler);
192
193 12
        $this->insertOnlineRedirection($crawler);
194 12
        $this->insertDashTableOfContents($crawler);
195
196 12
        return $crawler->saveHTML();
197
    }
198
199 12
    protected function removeNavbar(HtmlPageCrawler $crawler)
200
    {
201 12
        $crawler->filter('nav.navbar')->remove();
202 12
    }
203
204 12
    protected function removeLeftSidebarButton(HtmlPageCrawler $crawler)
205
    {
206 12
        $crawler->filter('#row-middle > div.side-col-toggle-container')->remove();
207 12
    }
208
209 12
    protected function removeFullscreenButton(HtmlPageCrawler $crawler)
210
    {
211 12
        $crawler->filter('#fullscreenbutton')->remove();
212 12
    }
213
214 12
    protected function removePageTopModules(HtmlPageCrawler $crawler)
215
    {
216 12
        $crawler->filter('#pagetop_modules')->remove();
217 12
    }
218
219 12
    protected function removeWikiActionsWrapper(HtmlPageCrawler $crawler)
220
    {
221 12
        $crawler->filter('#col1 > div.wikiactions_wrapper')->remove();
222 12
    }
223
224 12
    protected function removeBreadcrumb(HtmlPageCrawler $crawler)
225
    {
226 12
        $crawler->filter('nav.nav-breadcrumb')->remove();
227 12
    }
228
229 12
    protected function removeTopbar(HtmlPageCrawler $crawler)
230
    {
231 12
        $crawler->filter('#topbar')->remove();
232 12
    }
233
234 12
    protected function removeLeftSidebar(HtmlPageCrawler $crawler)
235
    {
236 12
        $crawler->filter('#col2')->remove();
237 12
    }
238
239 12
    protected function removeRightSidebar(HtmlPageCrawler $crawler)
240
    {
241 12
        $crawler->filter('script[src*="autoToc.js"]')->remove();
242 12
    }
243
244 12
    protected function removePagebar(HtmlPageCrawler $crawler)
245
    {
246 12
        $crawler->filter('#page-bar')->remove();
247 12
    }
248
249 12
    protected function removeFooter(HtmlPageCrawler $crawler)
250
    {
251 12
        $crawler->filter('#footer')->remove();
252 12
    }
253
254 12
    protected function removeUnwantedJavaScript(HtmlPageCrawler $crawler)
255
    {
256 12
        $crawler->filter('script[src*=autosave]')->remove();
257 12
        $crawler->filter('script[src*=gtag]')->remove();
258 12
        $crawler->filter('noscript')->remove();
259 12
        $crawler->filterXPath("//script[text()[contains(.,'piwik.tiki.org')]]")->remove();
260 12
        $crawler->filterXPath("//script[text()[contains(.,'gtag')]]")->remove();
261 12
    }
262
263 12
    protected function updateCSS(HtmlPageCrawler $crawler)
264
    {
265 12
        $this->updateTopPadding($crawler);
266 12
        $this->updateArticlePadding($crawler);
267 12
    }
268
269 12
    protected function updateTopPadding(HtmlPageCrawler $crawler)
270
    {
271 12
        $crawler->filter('body')
272 12
            ->removeClass('navbar-padding')
273 12
            ->addClass('hide_zone_left')
274 12
            ->css('padding-top', '0')
275
        ;
276 12
    }
277
278 12
    protected function updateArticlePadding(HtmlPageCrawler $crawler)
279
    {
280 12
        $crawler->filter('article#top')
281 12
            ->css('padding-top', '44px')
282
        ;
283 12
    }
284
285 12
    protected function insertOnlineRedirection(HtmlPageCrawler $crawler)
286
    {
287 12
        $onlineUrl = '';
288 12
        $meta = $crawler->filter('meta[property="og:url"]');
289
290 12
        if ($meta->getDOMDocument()) {
291 12
            $onlineUrl = $meta->attr('content');
292
        }
293
294 12
        $crawler->filter('html')->prepend("<!-- Online page at $onlineUrl -->");
295 12
    }
296
297 12
    protected function insertDashTableOfContents(HtmlPageCrawler $crawler)
298
    {
299 12
        $crawler->filter('#page-data > h1:first-of-type')
300 12
            ->before('<a name="//apple_ref/cpp/Section/Top" class="dashAnchor"></a>');
301
302
        $crawler->filter('h2')->each(static function (HtmlPageCrawler $node) {
303 12
            $node->before(
304 12
                '<a id="' . Str::slug($node->text()) . '" name="//apple_ref/cpp/Section/' . rawurlencode($node->text()) . '" class="dashAnchor"></a>'
305
            );
306 12
        });
307 12
    }
308
}
309