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.

AutoGlossaryPlugin::getNotUsedTermsReport()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 3

Importance

Changes 0
Metric Value
dl 0
loc 19
ccs 12
cts 12
cp 1
rs 9.6333
c 0
b 0
f 0
cc 3
nc 3
nop 0
crap 3
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 Easybook\Events\ParseEvent;
15
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
16
use Trefoil\Helpers\Glossary;
17
use Trefoil\Helpers\GlossaryItem;
18
use Trefoil\Helpers\GlossaryLoader;
19
use Trefoil\Helpers\GlossaryReplacer;
20
use Trefoil\Helpers\TextPreserver;
21
use Trefoil\Plugins\BasePlugin;
22
use Trefoil\Util\SimpleReport;
23
24
/**
25
 * This plugin takes care of the automatic interactive glossary feature.
26
 *
27
 * Configuration:
28
 *
29
 * - Configuration:
30
 *
31
 *     editions:
32
 *         <edition-name>
33
 *             plugins:
34
 *                 ...
35
 *                 options:
36
 *                     AutoGlossary:
37
 *                         pagebreaks: true   # use pagebreaks between defined terms
38
 *
39
 * - Global glossary (per book):
40
 *
41
 *     <book_dir>/
42
 *         Contents/
43
 *             auto-glossary.yml
44
 *
45
 * - Per book item glossary:
46
 *
47
 *     <book_dir>/
48
 *         Contents/
49
 *             <item_name>-auto-glossary.yml
50
 *
51
 * @see GlossaryLoader for format details
52
 * @see GlossaryReplacer for contents detail
53
 *
54
 */
55
class AutoGlossaryPlugin extends BasePlugin implements EventSubscriberInterface
56
{
57
58
    /**
59
     * The book-wide glossary
60
     *
61
     * @var Glossary
62
     */
63
    protected $bookGlossary;
64
65
    /**
66
     * The item-wide glossary
67
     *
68
     * @var Glossary
69
     */
70
    protected $itemGlossary;
71
72
    /**
73
     * The glossary to apply for the current item (book + item)
74
     *
75
     * @var Glossary
76
     */
77
    protected $glossary;
78
79
    /**
80
     * The processed glossary items
81
     *
82
     * @var Glossary
83
     */
84
    protected $processedGlossary;
85
86
    /**
87
     * Options that govern the glossary processing
88
     *
89
     * @var array
90
     */
91
    protected $glossaryOptions = array();
92
93
    /**
94
     * Terms already defined, to detect duplicated definitions in different files
95
     *
96
     * @var array
97
     */
98
    protected $alreadyDefinedTerms = array();
99
100
    /**
101
     * Cross-references of replaced terms for reporting
102
     *
103
     * @var array
104
     */
105
    protected $xrefs = array();
106
107
    /**
108
     * Whether or not the glossary item has been generated
109
     *
110
     * @var bool
111
     */
112
    protected $generated = false;
113
114
    /**
115
     * Whether a term has been replaced at least once into the current item
116
     *
117
     * @var bool
118
     */
119
    protected $termReplaced;
120
121
    /* ********************************************************************************
122
     * Event handlers
123
     * ********************************************************************************
124
     */
125 1
    public static function getSubscribedEvents()
126
    {
127
        return array(
128 1
            EasybookEvents::PRE_PARSE    => array('onItemPreParse', +100),
129 1
            EasybookEvents::POST_PARSE   => array('onItemPostParse', -1110), // after EbookQuizPlugin to avoid interferences
130 1
            EasybookEvents::POST_PUBLISH => 'onPostPublish');
131
    }
132
133 1
    public function onItemPostParse(ParseEvent $event)
134
    {
135 1
        $this->init($event);
136
137
        // get all the book-wide glossary definitions and options
138 1
        if (!$this->bookGlossary) {
139 1
            $this->loadBookGlossary();
140 1
        }
141
142
        // get all the item-wide glossary definitions
143 1
        $this->loadItemGlossary();
144
145
        // process this item replacing terms into
146 1
        $this->processItem();
147
148
        // reload changed item
149 1
        $event->setItem($this->item);
150 1
    }
151
152 1
    public function onItemPreParse(ParseEvent $event)
153
    {
154 1
        $this->init($event);
155
156 1
        if ('auto-glossary' == $this->item['config']['element']) {
157 1
            $this->saveAutoGlossary();
158 1
        }
159
160 1
    }
161
162 1
    public function onPostPublish(BaseEvent $event)
163
    {
164 1
        $this->init($event);
165
166
        // create the processing report
167 1
        $this->createReport();
168 1
    }
169
170
    /* ********************************************************************************
171
     * Implementation
172
     * ********************************************************************************
173
     */
174
175
    /**
176
     * Load the book-wide glossary and options.
177
     */
178 1
    protected function loadBookGlossary()
179
    {
180
        // initializations
181 1
        $this->glossary = new Glossary();
182 1
        $this->processedGlossary = new Glossary();
183
184
        // get all the book-wide glossary terms from file and create the definitions data structure
185 1
        $contentsDir = $this->app['publishing.dir.book'] . '/Contents';
186 1
        $glossaryFile = $contentsDir . '/auto-glossary.yml';
187
188 1
        $loader = new GlossaryLoader($glossaryFile, $this->app['slugger']);
189 1
        $this->bookGlossary = $loader->load(true); // with options
190 1
        $this->glossaryOptions = $loader->getOptions();
191
192 1
        if (!$loader->isLoaded()) {
193
            $this->writeLn(
194
                 sprintf(
195
                     "No book glossary definition file '%s' found in the book's \"Contents\" directory.",
196
                     basename($glossaryFile)
197
                 ),
198
                 'warning'
199
            );
200
        }
201 1
    }
202
203
    /**
204
     * Load the item-wide glossary and merge it with the book-wide glossary
205
     * to get the definitions to be applied to the item.
206
     */
207 1
    protected function loadItemGlossary()
208
    {
209 1
        if (!$this->item['config']['content']) {
210
            // no content, nothing to do
211 1
            return;
212
        }
213
214
        // read item glossary and merge it with book glossary
215 1
        $contentsDir = $this->app['publishing.dir.book'] . '/Contents';
216
217 1
        $fileName = pathinfo($this->item['config']['content'], PATHINFO_FILENAME);
218 1
        $glossaryFile = $contentsDir . '/' . $fileName . '-auto-glossary.yml';
219
220 1
        $loader = new GlossaryLoader($glossaryFile, $this->app['slugger']);
221 1
        $this->itemGlossary = $loader->load(false);
222
223
        // start with a fresh copy of the book-wide definitions
224 1
        $this->glossary = clone($this->bookGlossary);
225
226
        // and add the item-wide definitions
227 1
        $this->glossary->merge($this->itemGlossary);
228 1
    }
229
230
    /**
231
     * For a content item to be processed for glossary terms, replace glossary terms into the text.
232
     */
233 1
    public function processItem()
234
    {
235
        // look type of processing
236 1
        if (in_array($this->item['config']['element'], $this->glossaryOptions['elements'])) {
237
238
            // replace each term with a link to its definition
239 1
            $this->replaceTerms();
240
241
            // append a copy of the processed definitions to the processed glossary
242
            // to avoid losing all xrefs and anchorlinks for this item
243 1
            $this->processedGlossary->merge(clone($this->glossary));
244 1
        }
245 1
    }
246
247
    /**
248
     * Replace all glossary terms into the current item.
249
     */
250 1
    protected function replaceTerms()
251
    {
252
        // instantiate the GlossaryReplacer object
253 1
        $replacer = new GlossaryReplacer(
254 1
            $this->glossary,
255 1
            new TextPreserver(),
256 1
            $this->item['content'],
257 1
            $this->item['config']['content'],
258 1
            $this->glossaryOptions,
259 1
            $this->app['twig']
260 1
        );
261
262
        // do the replacements (also modifies the glossary object)
263 1
        $this->item['content'] = $replacer->replace();
264 1
    }
265
266
    /**
267
     * Save the auto glossary definitions to be generated on item rendering
268
     */
269 1
    protected function saveAutoGlossary()
270
    {
271 1
        $this->app['publishing.glossary.definitions'] = $this->processedGlossary;
272 1
        $this->app['publishing.glossary.pagebreaks'] =
273 1
            $this->getEditionOption('plugins.options.AutoGlossary.pagebreaks', true);
274
275 1
        $this->generated = true;
276 1
    }
277
278
    /**
279
     * Writes the report with the summary of processing done.
280
     */
281 1
    protected function createReport()
282
    {
283 1
        $report = '';
284 1
        $report .= $this->getUsedTermsReport();
285 1
        $report .= "\n\n";
286 1
        $report .= $this->getNotUsedTermsReport();
287
288 1
        if (!$this->generated) {
289
            $this->writeLn(
290
                 "No glossary has been generated, check for missing 'auto-glosssary' contents element.",
291
                 "error"
292
            );
293
        }
294
295 1
        $outputDir = $this->app['publishing.dir.output'];
296 1
        $reportFile = $outputDir . '/report-AutoGlossaryPlugin.txt';
297
298 1
        file_put_contents($reportFile, $report);
299 1
    }
300
301 1
    protected function getUsedTermsReport()
302
    {
303 1
        $report = new SimpleReport();
304 1
        $report->setTitle('AutoGlossaryPlugin');
305 1
        $report->setSubtitle('Used terms');
306
307 1
        $report->addIntroLine('Coverage: ' . $this->glossaryOptions['coverage']);
308 1
        $report->addIntroLine('Elements: ' . '"' . join('", "', $this->glossaryOptions['elements']) . '"');
309
310 1
        $report->setHeaders(array('Term', 'Variant', 'Item', 'Count', 'Source'));
311
312 1
        $report->setColumnsWidth(array(30, 30, 30, 5, 30));
313 1
        $report->setColumnsAlignment(array('', '', '', 'right', ''));
314
315 1
        foreach ($this->processedGlossary as $processedItem) {
316
            /* @var GlossaryItem $processedItem */
317 1
            $auxTerm = $processedItem->getTerm();
318 1
            foreach ($processedItem->getXref() as $variant => $items) {
319 1
                $auxVariant = $variant;
320 1
                foreach ($items as $item => $count) {
321 1
                    $report->addline(array($auxTerm, $auxVariant, $item, $count, $processedItem->getSource()));
322 1
                    $auxTerm = '';
323 1
                    $auxVariant = '';
324 1
                }
325 1
            }
326 1
        }
327
328 1
        return $report->getText();
329
    }
330
331 1
    protected function getNotUsedTermsReport()
332
    {
333 1
        $report = new SimpleReport();
334 1
        $report->setTitle('AutoGlossaryPlugin');
335 1
        $report->setSubtitle('Not used terms');
336
337 1
        $report->setHeaders(array('Term', 'Source'));
338
339 1
        $report->setColumnsWidth(array(30, 30));
340
341 1
        foreach ($this->processedGlossary as $item) {
342
            /* @var GlossaryItem $item */
343 1
            if (!count($item->getXref())) {
344 1
                $report->addLine(array($item->getTerm(), $item->getSource()));
345 1
            }
346 1
        }
347
348 1
        return $report->getText();
349
    }
350
}
351