GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Passed
Push — master ( cf39f6...a305e6 )
by Leonardo
03:52
created

AbstractContentParser::embedVideos()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 19
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 13
nc 1
nop 1
dl 0
loc 19
rs 9.8333
c 1
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace GraphQLAPI\GraphQLAPI\ContentProcessors;
6
7
use InvalidArgumentException;
8
use GraphQLAPI\GraphQLAPI\General\LocaleUtils;
9
10
abstract class AbstractContentParser implements ContentParserInterface
11
{
12
    /**
13
     * Parse the file's Markdown into HTML Content
14
     *
15
     * @param string $relativePathDir Dir relative to the /docs/${lang}/ folder
16
     */
17
    public function getContent(
18
        string $relativePathDir,
19
        string $filename,
20
        array $options = []
21
    ): string {
22
        // Make sure the relative path ends with "/"
23
        $relativePathDir = \trailingslashit($relativePathDir);
24
        $localizeFile = \trailingslashit($this->getLocalizedFileDir()) . $relativePathDir . $filename;
25
        if (file_exists($localizeFile)) {
26
            // First check if the localized version exists
27
            $file = $localizeFile;
28
        } else {
29
            // Otherwise, use the default language version
30
            $file = \trailingslashit($this->getDefaultFileDir()) . $relativePathDir . $filename;
31
            // Make sure this file exists
32
            if (!file_exists($file)) {
33
                throw new InvalidArgumentException(sprintf(
34
                    \__('File \'%s\' does not exist', 'graphql-api'),
35
                    $file
36
                ));
37
            }
38
        }
39
        $fileContent = file_get_contents($file);
40
        $htmlContent = $this->getHTMLContent($fileContent);
41
        $pathURL = \trailingslashit($this->getDefaultFileURL()). $relativePathDir;
42
        return $this->processHTMLContent($htmlContent, $pathURL, $options);
43
    }
44
45
    /**
46
     * Where the markdown file localized to the user's language is stored
47
     *
48
     * @param string $module
49
     * @return string
50
     */
51
    public function getLocalizedFileDir(): string
52
    {
53
        return $this->getFileDir(LocaleUtils::getLocaleLanguage());
54
    }
55
56
    /**
57
     * Where the default markdown file (for if the localized language is not available) is stored
58
     * Default language for documentation: English
59
     *
60
     * @param string $module
61
     * @return string
62
     */
63
    public function getDefaultFileDir(): string
64
    {
65
        return $this->getFileDir($this->getDefaultDocsLanguage());
66
    }
67
68
    /**
69
     * Default language for documentation: English
70
     */
71
    public function getDefaultDocsLanguage(): string
72
    {
73
        return 'en';
74
    }
75
76
    /**
77
     * Undocumented function
78
     *
79
     * @param string $module
80
     * @param string $lang
81
     * @return string
82
     */
83
    protected function getFileDir(string $lang): string
84
    {
85
        return constant('GRAPHQL_API_DIR') . "/docs/${lang}";
86
    }
87
88
    /**
89
     * Path URL to append to the local images referenced in the markdown file
90
     */
91
    protected function getDefaultFileURL(): string
92
    {
93
        $lang = $this->getDefaultDocsLanguage();
94
        return constant('GRAPHQL_API_URL') . "docs/${lang}";
95
    }
96
97
    /**
98
     * Process the HTML content:
99
     *
100
     * - Add the path to the images and anchors
101
     * - Add classes to HTML elements
102
     * - Append video embeds
103
     */
104
    abstract protected function getHTMLContent(string $fileContent): string;
105
106
    /**
107
     * Process the HTML content:
108
     *
109
     * - Add the path to the images and anchors
110
     * - Add classes to HTML elements
111
     * - Append video embeds
112
     */
113
    protected function processHTMLContent(string $htmlContent, string $pathURL, array $options = []): string
114
    {
115
        // Add default values for the options
116
        $options = array_merge(
117
            [
118
                ContentParserOptions::APPEND_PATH_URL_TO_IMAGES => true,
119
                ContentParserOptions::APPEND_PATH_URL_TO_ANCHORS => true,
120
                ContentParserOptions::ADD_CLASSES => true,
121
                ContentParserOptions::EMBED_VIDEOS => true,
122
                ContentParserOptions::TAB_CONTENT => false,
123
            ],
124
            $options
125
        );
126
        // Add the path to the images
127
        if ($options[ContentParserOptions::APPEND_PATH_URL_TO_IMAGES]) {
128
            $htmlContent = $this->appendPathURLToImages($pathURL, $htmlContent);
129
        }
130
        // Add the path to the anchors
131
        if ($options[ContentParserOptions::APPEND_PATH_URL_TO_ANCHORS]) {
132
            $htmlContent = $this->appendPathURLToAnchors($pathURL, $htmlContent);
133
        }
134
        // Add classes to HTML elements
135
        if ($options[ContentParserOptions::ADD_CLASSES]) {
136
            $htmlContent = $this->addClasses($htmlContent);
137
        }
138
        // Append video embeds
139
        if ($options[ContentParserOptions::EMBED_VIDEOS]) {
140
            $htmlContent = $this->embedVideos($htmlContent);
141
        }
142
        // Convert the <h2> into tabs
143
        if ($options[ContentParserOptions::TAB_CONTENT]) {
144
            $htmlContent = $this->tabContent($htmlContent);
145
        }
146
        return $htmlContent;
147
    }
148
149
    /**
150
     * Add tabs to the content wherever there is an <h2>
151
     */
152
    protected function tabContent(string $htmlContent): string
153
    {
154
        $tag = 'h2';
155
        $firstTagPos = strpos($htmlContent, '<' . $tag . '>');
156
        // Check if there is any <h2>
157
        if ($firstTagPos !== false) {
158
            // Content before the first <h2> does not go within any tab
159
            $contentStarter = substr(
160
                $htmlContent,
161
                0,
162
                $firstTagPos
163
            );
164
            // Add the markup for the tabs around every <h2>
165
            $regex = sprintf(
166
                '/<%1$s>(.*?)<\/%1$s>/',
167
                $tag
168
            );
169
            $headers = [];
170
            $panelContent = preg_replace_callback(
171
                $regex,
172
                function ($matches) use (&$headers) {
173
                    $isFirstTab = empty($headers);
174
                    if (!$isFirstTab) {
175
                        $tabbedPanel = '</div>';
176
                    } else {
177
                        $tabbedPanel = '';
178
                    }
179
                    $headers[] = $matches[1];
180
                    return $tabbedPanel . sprintf(
181
                        '<div id="doc-panel-%s" class="tab-content" style="display: %s;">',
182
                        count($headers),
183
                        $isFirstTab ? 'block' : 'none'
184
                    );// . $matches[0];
185
                },
186
                substr(
187
                    $htmlContent,
188
                    $firstTagPos
189
                )
190
            ) . '</div>';
191
192
            // Create the tabs
193
            $panelTabs = '<h2 class="nav-tab-wrapper">';
194
            $headersCount = count($headers);
195
            for ($i = 0; $i < $headersCount; $i++) {
196
                $isFirstTab = $i == 0;
197
                $panelTabs .= sprintf(
198
                    '<a href="#doc-panel-%s" class="nav-tab %s">%s</a>',
199
                    $i + 1,
200
                    $isFirstTab ? 'nav-tab-active' : '',
201
                    $headers[$i]
202
                );
203
            }
204
            $panelTabs .= '</h2>';
205
206
            return
207
                $contentStarter
208
                . '<div class="graphql-api-tabpanel">'
209
                . $panelTabs
210
                . $panelContent
211
                . '</div>';
212
        }
213
        return $htmlContent;
214
    }
215
216
    /**
217
     * Append video embeds. These are not already in the markdown file
218
     * because GitHub can't add `<iframe>`. Then, the source only contains
219
     * a link to the video. This must be identified, and transformed into
220
     * the embed.
221
     *
222
     * The match is produced when a link is pointing to a video in
223
     * Vimeo or Youtube by the end of the paragraph, with/out a final dot.
224
     */
225
    protected function embedVideos(string $htmlContent): string
226
    {
227
        // Identify videos from Vimeo/Youtube
228
        return (string)preg_replace_callback(
229
            '/<p>(.*?)<a href="https:\/\/(vimeo.com|youtube.com|youtu.be)\/(.*?)">(.*?)<\/a>\.?<\/p>/',
230
            function ($matches) {
231
                global $wp_embed;
232
                // Keep the link, and append the embed immediately after
233
                return
234
                    $matches[0]
235
                    . '<div class="video-responsive-container">' .
236
                        $wp_embed->autoembed(sprintf(
237
                            'https://%s/%s',
238
                            $matches[2],
239
                            $matches[3]
240
                        ))
241
                    . '</div>';
242
            },
243
            $htmlContent
244
        );
245
    }
246
247
    /**
248
     * Add classes to the HTML elements
249
     */
250
    protected function addClasses(string $htmlContent): string
251
    {
252
        /**
253
         * Add class "wp-list-table widefat" to all tables
254
         */
255
        return str_replace(
256
            '<table>',
257
            '<table class="wp-list-table widefat striped">',
258
            $htmlContent
259
        );
260
    }
261
262
    /**
263
     * Convert relative paths to absolute paths for image URLs
264
     *
265
     * @param string $pathURL
266
     * @param string $htmlContent
267
     * @return string
268
     */
269
    protected function appendPathURLToImages(string $pathURL, string $htmlContent): string
270
    {
271
        return $this->appendPathURLToElement('img', 'src', $pathURL, $htmlContent);
272
    }
273
274
    /**
275
     * Convert relative paths to absolute paths for image URLs
276
     *
277
     * @param string $pathURL
278
     * @param string $htmlContent
279
     * @return string
280
     */
281
    protected function appendPathURLToAnchors(string $pathURL, string $htmlContent): string
282
    {
283
        return $this->appendPathURLToElement('a', 'href', $pathURL, $htmlContent);
284
    }
285
286
    /**
287
     * Convert relative paths to absolute paths for elements
288
     *
289
     * @param string $tag
290
     * @param string $attr
291
     * @param string $pathURL
292
     * @param string $htmlContent
293
     * @return string
294
     */
295
    protected function appendPathURLToElement(string $tag, string $attr, string $pathURL, string $htmlContent): string
296
    {
297
        /**
298
         * $regex will become:
299
         * - /<img.*src="(.*?)".*?>/
300
         * - /<a.*href="(.*?)".*?>/
301
         */
302
        $regex = sprintf(
303
            '/<%s.*%s="(.*?)".*?>/',
304
            $tag,
305
            $attr
306
        );
307
        return (string)preg_replace_callback(
308
            $regex,
309
            function ($matches) use ($pathURL, $attr) {
310
                // If the element has an absolute route, then no need
311
                if (substr($matches[1], 0, strlen('http://')) == 'http://'
312
                    || substr($matches[1], 0, strlen('https://')) == 'https://'
313
                ) {
314
                    return $matches[0];
315
                }
316
                $elementURL = \trailingslashit($pathURL) . $matches[1];
317
                return str_replace(
318
                    "{$attr}=\"{$matches[1]}\"",
319
                    "{$attr}=\"{$elementURL}\"",
320
                    $matches[0]
321
                );
322
            },
323
            $htmlContent
324
        );
325
    }
326
}
327