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.

LinkCheckPlugin::checkExternalLinks()   B
last analyzed

Complexity

Conditions 7
Paths 21

Size

Total Lines 38

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 25
CRAP Score 7.0199

Importance

Changes 0
Metric Value
dl 0
loc 38
ccs 25
cts 27
cp 0.9259
rs 8.3786
c 0
b 0
f 0
cc 7
nc 21
nop 0
crap 7.0199
1
<?php
2
/*
3
 * This file is part of the trefoil application.
4
 *
5
 * (c) Miguel Angel Gabriel <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
namespace Trefoil\Plugins\Optional;
11
12
use Easybook\Events\BaseEvent;
13
use Easybook\Events\EasybookEvents;
14
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
15
use Trefoil\Helpers\LinkChecker;
16
use Trefoil\Util\SimpleReport;
17
use Trefoil\Plugins\BasePlugin;
18
/**
19
 * Plugin to check internal and external links in book.
20
 *
21
 * Internal links are checked by looking for a valid link target, i.e. an html element
22
 * whith id="the-link-target" in the whole book.
23
 *
24
 * External links are (optionally) checked for existence by performing a network lookup.
25
 * This behaviour is off by default because could be very time consuming if the book
26
 * has a large number of external links. To turn it on, set the following option in
27
 * the book's config.yml:
28
 *
29
 *     editions:
30
 *         <edition-name>
31
 *             plugins:
32
 *                 ...
33
 *                 options:
34
 *                     LinkCheck:
35
 *                         check_external_links: true
36
 *
37
 * The plugin will generate a report in the output directory for all the links
38
 * in the book with its status from the check (OK or error).
39
 *
40
 */
41
class LinkCheckPlugin extends BasePlugin implements EventSubscriberInterface
42
{
43
    protected $links = array(
44
        'internal' => array(),
45
        'external' => array()
46
    );
47
48
    protected $linkTargets = array();
49
50 1
    public static function getSubscribedEvents()
51
    {
52
        return array(
53 1
            EasybookEvents::POST_DECORATE => array('onItemPostDecorate', -1100), // the latest possible
54 1
            EasybookEvents::POST_PUBLISH  => array('onPostPublish', -1100) // the latest possible
55 1
        );
56
    }
57
58 1
    public function onItemPostDecorate(BaseEvent $event)
59
    {
60 1
        $this->init($event);
61
62
        // retrieve all the links for this item
63 1
        $links = $this->findLinks($this->item['content'], $this->item['config']['content']);
64 1
        $this->links = array_merge_recursive($this->links, $links);
65
66
        // retrieve all the internal link targets for this item
67 1
        $linkTargets = $this->findLinkTargets($this->item['content']);
68 1
        $this->linkTargets = array_merge_recursive($this->linkTargets, $linkTargets);
69 1
    }
70
71 1
    public function onPostPublish(BaseEvent $event)
72
    {
73 1
        $this->init($event);
74
75 1
        $this->checkInternalLinks();
76 1
        $this->checkExternalLinks();
77
78 1
        $this->createReport();
79 1
    }
80
81
    /**
82
     * Extract all links in content
83
     *
84
     * @param string $content
85
     * @param        $xref
86
     *
87
     * @return array
88
     */
89 1
    protected function findLinks($content, $xref)
90
    {
91
        $links = array(
92
            'internal' => array(
93 1
                $xref => array()
94 1
            ),
95
            'external' => array(
96 1
                $xref => array()
97 1
            )
98 1
        );
99
100 1
        preg_match_all('/<a .*href="(?<uri>.*)".*>(?<text>.*)<\/a>/Ums', $content, $matches, PREG_SET_ORDER);
101
102 1
        if ($matches) {
103 1
            foreach ($matches as $match) {
104
                $link = array(
105 1
                    'text' => $match['text'],
106 1
                    'uri'  => $match['uri']
107 1
                );
108
109 1
                if ('#' == substr($match['uri'], 0, 1)) {
110 1
                    $links['internal'][$xref][] = $link;
111 1
                } else {
112 1
                    $links['external'][$xref][] = $link;
113
                }
114 1
            }
115 1
        }
116
117 1
        return $links;
118
    }
119
120
    /**
121
     * Extract all possible link targets in content
122
     *
123
     * @param string $content
124
     *
125
     * @return array
126
     */
127 1
    protected function findLinkTargets($content)
128
    {
129 1
        $linkTargets = array();
130
131 1
        preg_match_all('/<.*id="(?<id>.*)".*>/Ums', $content, $matches);
132
133 1
        foreach ($matches['id'] as $match) {
134 1
            $linkTargets[] = $match;
135 1
        }
136
137 1
        return $linkTargets;
138
    }
139
140
    /**
141
     * Check all the internal links for existence
142
     */
143 1
    protected function checkInternalLinks()
144
    {
145 1
        $errors = false;
146
147 1
        foreach ($this->links['internal'] as $xref => $links) {
148 1
            foreach ($links as $index => $link) {
149 1
                if (!in_array(substr($link['uri'], 1), $this->linkTargets)) {
150 1
                    $this->links['internal'][$xref][$index]['status'] = 'Not found';
151 1
                    $errors = true;
152 1
                } else {
153 1
                    $this->links['internal'][$xref][$index]['status'] = 'OK';
154
                }
155 1
            }
156 1
        }
157
158 1
        if ($errors) {
159 1
            $this->writeLn('Some internal links are not correct.', 'error');
160 1
        }
161 1
    }
162
163
    /**
164
     * Check external links for existence
165
     */
166 1
    protected function checkExternalLinks()
167
    {
168 1
        if (!$this->getEditionOption('plugins.options.LinkCheck.check_external_links')) {
169
            return;
170
        }
171
172 1
        $checker = new LinkChecker();
173
174 1
        $this->writeLn('Checking external links....');
175
176 1
        $errors = false;
177
178 1
        $numLinks = 0;
179 1
        foreach ($this->links['external'] as $links) {
180 1
            $numLinks += count($links);
181 1
        }
182
183 1
        $this->progressStart($numLinks);
184 1
        foreach ($this->links['external'] as $xref => $links) {
185 1
            foreach ($links as $index => $link) {
186
                try {
187 1
                    $checker->check($link['uri']);
188 1
                    $this->links['external'][$xref][$index]['status'] = 'OK';
189 1
                } catch (\Exception $e) {
190 1
                    $this->links['external'][$xref][$index]['status'] = $e->getMessage();
191 1
                    $errors = true;
192
                }
193 1
                $this->progressAdvance();
194 1
            }
195 1
        }
196 1
        $this->progressFinish();
197
198 1
        if ($errors) {
199 1
            $this->writeLn('Some external links are not correct.', 'error');
200 1
        } else {
201
            $this->writeLn('All external links are correct.');
202
        }
203 1
    }
204
205 1
    protected function createReport()
206
    {
207 1
        $report = new SimpleReport();
208 1
        $report->setTitle('LinkCheckPlugin');
209
210 1
        $checkExternalLinks = $this->getEditionOption('plugins.options.LinkCheck.check_external_links');
211 1
        $report->setSubtitle(sprintf('check_external_links: %s', $checkExternalLinks ? 'true' : 'false'));
212
213 1
        $report->setHeaders(
214
               array(
215 1
                   'Type',
216 1
                   'Item',
217 1
                   'Status',
218 1
                   'Link')
219 1
        );
220 1
        $report->setColumnsWidth(
221
               array(
222 1
                   8,
223 1
                   4,
224 1
                   20,
225
                   100
226 1
               )
227 1
        );
228
229 1
        $countOk = 0;
230 1
        $countError = 0;
231 1
        $countNotChecked = 0;
232
233 1
        foreach ($this->links as $type => $linksByType) {
234
235 1
            $report->addLine(array(ucfirst($type)));
236 1
            $report->addLine();
237
238 1
            foreach ($linksByType as $xref => $links) {
239 1
                $report->addLine(array('', $xref));
240 1
                $report->addLine();
241 1
                foreach ($links as $link) {
242
243 1
                    $status = isset($link['status']) ? $link['status'] : 'Not checked';
244
245 1
                    if ('OK' == $status) {
246 1
                        $countOk++;
247 1
                    } elseif ('Not checked' == $status) {
248
                        $countNotChecked++;
249
                    } else {
250 1
                        $countError++;
251
                    }
252
253 1
                    $report->addLine(array('', '', $status, trim($link['text'])));
254 1
                    if ($link['text'] != $link['uri']) {
255 1
                        $report->addLine(array('', '', '', '<' . $link['uri'] . '>'));
256 1
                    }
257 1
                }
258 1
                if (!$links) {
259 1
                    $report->addLine(array('', '', '== No links =='));
260 1
                    $report->addLine();
261 1
                }
262 1
            }
263 1
        }
264
265 1
        $report->addSummaryLine(sprintf('Total OK.........: %s', $countOk));
266 1
        $report->addSummaryLine(sprintf('Total Error......: %s', $countError));
267 1
        $report->addSummaryLine(sprintf('Total Not checked: %s', $countNotChecked));
268
269 1
        $text = $report->getText();
270
271
        // write report
272 1
        $outputDir = $this->app['publishing.dir.output'];
273 1
        $reportFile = $outputDir . '/report-LinkCheckPlugin.txt';
274
275 1
        file_put_contents($reportFile, $text);
276 1
    }
277
}
278