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 ( 3495d0...595e6c )
by Leonardo
03:23
created

tabContent()   B

Complexity

Conditions 6
Paths 3

Size

Total Lines 61
Code Lines 43

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 42

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 6
eloc 43
c 2
b 0
f 0
nc 3
nop 1
dl 0
loc 61
ccs 0
cts 54
cp 0
crap 42
rs 8.6097

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace GraphQLAPI\GraphQLAPI\ModuleResolvers;
6
7
use Parsedown;
8
9
trait HasMarkdownDocumentationModuleResolverTrait
10
{
11
    /**
12
     * The module slug
13
     */
14
    abstract public function getSlug(string $module): string;
15
16
    /**
17
     * The name of the Markdown filename.
18
     * By default, it's the same as the slug
19
     *
20
     * @param string $module
21
     * @return string
22
     */
23
    public function getMarkdownFilename(string $module): ?string
24
    {
25
        return $this->getSlug($module) . '.md';
26
    }
27
28
    /**
29
     * Where the markdown file localized to the user's language is stored
30
     *
31
     * @param string $module
32
     * @return string
33
     */
34
    abstract public function getLocalizedMarkdownFileDir(string $module): string;
35
36
    /**
37
     * Where the default markdown file (for if the localized language is not available) is stored
38
     *
39
     * @param string $module
40
     * @return string
41
     */
42
    abstract public function getDefaultMarkdownFileDir(string $module): string;
43
44
    /**
45
     * Does the module have HTML Documentation?
46
     *
47
     * @param string $module
48
     * @return bool
49
     */
50
    public function hasDocumentation(string $module): bool
51
    {
52
        return !empty($this->getMarkdownFilename($module));
53
    }
54
55
    /**
56
     * Path URL to append to the local images referenced in the markdown file
57
     *
58
     * @param string $module
59
     * @return string|null
60
     */
61
    abstract protected function getDefaultMarkdownFileURL(string $module): string;
62
63
    /**
64
     * HTML Documentation for the module
65
     *
66
     * @param string $module
67
     * @return string|null
68
     */
69
    public function getDocumentation(string $module): ?string
70
    {
71
        if ($markdownFilename = $this->getMarkdownFilename($module)) {
72
            $localizedMarkdownFile = \trailingslashit($this->getLocalizedMarkdownFileDir($module)) . $markdownFilename;
73
            if (file_exists($localizedMarkdownFile)) {
74
                // First check if the localized version exists
75
                $markdownFile = $localizedMarkdownFile;
76
            } else {
77
                // Otherwise, use the default language version
78
                $markdownFile = \trailingslashit($this->getDefaultMarkdownFileDir($module)) . $markdownFilename;
79
                // Make sure this file exists
80
                if (!file_exists($markdownFile)) {
81
                    return sprintf(
82
                        '<p>%s</p>',
83
                        \__('Oops, the documentation for this module is not available', 'graphql-api')
84
                    );
85
                }
86
            }
87
            $markdownContents = file_get_contents($markdownFile);
88
            $htmlContent = (new Parsedown())->text($markdownContents);
89
            return $this->processHTMLContent($module, $htmlContent);
90
        }
91
        return null;
92
    }
93
94
    /**
95
     * Process the HTML content:
96
     *
97
     * - Add the path to the images and anchors
98
     * - Add classes to HTML elements
99
     * - Append video embeds
100
     */
101
    protected function processHTMLContent(string $module, string $htmlContent): string
102
    {
103
        $defaultModulePathURL = $this->getDefaultMarkdownFileURL($module);
104
        // Add the path to the images and anchors
105
        $htmlContent = $this->appendPathURLToImages($defaultModulePathURL, $htmlContent);
106
        $htmlContent = $this->appendPathURLToAnchors($defaultModulePathURL, $htmlContent);
107
        // Add classes to HTML elements
108
        $htmlContent = $this->addClasses($htmlContent);
109
        // Append video embeds
110
        $htmlContent = $this->embedVideos($htmlContent);
111
        // Convert the <h2> into tabs
112
        $htmlContent = $this->tabContent($htmlContent);
113
        return $htmlContent;
114
    }
115
116
    /**
117
     * Add tabs to the content wherever there is an <h2>
118
     */
119
    protected function tabContent(string $htmlContent): string
120
    {
121
        $tag = 'h2';
122
        $firstTagPos = strpos($htmlContent, '<' . $tag . '>');
123
        // Check if there is any <h2>
124
        if ($firstTagPos !== false) {
125
            // Content before the first <h2> does not go within any tab
126
            $contentStarter = substr(
127
                $htmlContent,
128
                0,
129
                $firstTagPos
130
            );
131
            // Add the markup for the tabs around every <h2>
132
            $regex = sprintf(
133
                '/<%1$s>(.*?)<\/%1$s>/',
134
                $tag
135
            );
136
            $headers = [];
137
            $panelContent = preg_replace_callback(
138
                $regex,
139
                function ($matches) use (&$headers) {
140
                    $isFirstTab = empty($headers);
141
                    if (!$isFirstTab) {
142
                        $tabbedPanel = '</div>';
143
                    } else {
144
                        $tabbedPanel = '';
145
                    }
146
                    $headers[] = $matches[1];
147
                    return $tabbedPanel . sprintf(
148
                        '<div id="doc-panel-%s" class="tab-content" style="display: %s;">',
149
                        count($headers),
150
                        $isFirstTab ? 'block' : 'none'
151
                    );// . $matches[0];
152
                },
153
                substr(
154
                    $htmlContent,
155
                    $firstTagPos
156
                )
157
            ) . '</div>';
158
159
            // Create the tabs
160
            $panelTabs = '<h2 class="nav-tab-wrapper">';
161
            for ($i = 0; $i < count($headers); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
162
                $isFirstTab = $i == 0;
163
                $panelTabs .= sprintf(
164
                    '<a href="#doc-panel-%s" class="nav-tab %s">%s</a>',
165
                    $i + 1,
166
                    $isFirstTab ? 'nav-tab-active' : '',
167
                    $headers[$i]
168
                );
169
            }
170
            $panelTabs .= '</h2>';
171
172
            return
173
                $contentStarter
174
                . '<div class="graphql-api-tabpanel">'
175
                . $panelTabs
176
                . $panelContent
177
                . '</div>';
178
        }
179
        return $htmlContent;
180
    }
181
182
    /**
183
     * Append video embeds. These are not already in the markdown file
184
     * because GitHub can't add `<iframe>`. Then, the source only contains
185
     * a link to the video. This must be identified, and transformed into
186
     * the embed.
187
     *
188
     * The match is produced when a link is pointing to a video in
189
     * Vimeo or Youtube by the end of the paragraph, with/out a final dot.
190
     */
191
    protected function embedVideos(string $htmlContent): string
192
    {
193
        // Identify videos from Vimeo/Youtube
194
        return preg_replace_callback(
195
            '/<p>(.*?)<a href="https:\/\/(vimeo.com|youtube.com|youtu.be)\/(.*?)">(.*?)<\/a>\.?<\/p>/',
196
            function ($matches) {
197
                global $wp_embed;
198
                // Keep the link, and append the embed immediately after
199
                return
200
                    $matches[0]
201
                    . '<div class="video-responsive-container">' .
202
                        $wp_embed->autoembed(sprintf(
203
                            'https://%s/%s',
204
                            $matches[2],
205
                            $matches[3]
206
                        ))
207
                    . '</div>';
208
            },
209
            $htmlContent
210
        );
211
    }
212
213
    /**
214
     * Add classes to the HTML elements
215
     */
216
    protected function addClasses(string $htmlContent): string
217
    {
218
        /**
219
         * Add class "wp-list-table widefat" to all tables
220
         */
221
        return str_replace(
222
            '<table>',
223
            '<table class="wp-list-table widefat striped">',
224
            $htmlContent
225
        );
226
    }
227
228
    /**
229
     * Convert relative paths to absolute paths for image URLs
230
     *
231
     * @param string $pathURL
232
     * @param string $htmlContent
233
     * @return string
234
     */
235
    protected function appendPathURLToImages(string $pathURL, string $htmlContent): string
236
    {
237
        return $this->appendPathURLToElement('img', 'src', $pathURL, $htmlContent);
238
    }
239
240
    /**
241
     * Convert relative paths to absolute paths for image URLs
242
     *
243
     * @param string $pathURL
244
     * @param string $htmlContent
245
     * @return string
246
     */
247
    protected function appendPathURLToAnchors(string $pathURL, string $htmlContent): string
248
    {
249
        return $this->appendPathURLToElement('a', 'href', $pathURL, $htmlContent);
250
    }
251
252
    /**
253
     * Convert relative paths to absolute paths for elements
254
     *
255
     * @param string $tag
256
     * @param string $attr
257
     * @param string $pathURL
258
     * @param string $htmlContent
259
     * @return string
260
     */
261
    protected function appendPathURLToElement(string $tag, string $attr, string $pathURL, string $htmlContent): string
262
    {
263
        /**
264
         * $regex will become:
265
         * - /<img.*src="(.*?)".*?>/
266
         * - /<a.*href="(.*?)".*?>/
267
         */
268
        $regex = sprintf(
269
            '/<%s.*%s="(.*?)".*?>/',
270
            $tag,
271
            $attr
272
        );
273
        return preg_replace_callback(
274
            $regex,
275
            function ($matches) use ($pathURL, $attr) {
276
                // If the element has an absolute route, then no need
277
                if (substr($matches[1], 0, strlen('http://')) == 'http://'
278
                    || substr($matches[1], 0, strlen('https://')) == 'https://'
279
                ) {
280
                    return $matches[0];
281
                }
282
                $elementURL = \trailingslashit($pathURL) . $matches[1];
283
                return str_replace(
284
                    "{$attr}=\"{$matches[1]}\"",
285
                    "{$attr}=\"{$elementURL}\"",
286
                    $matches[0]
287
                );
288
            },
289
            $htmlContent
290
        );
291
    }
292
}
293