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.

IllustrationsPlugin   A
last analyzed

Complexity

Total Complexity 18

Size/Duplication

Total Lines 198
Duplicated Lines 8.59 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 99.09%

Importance

Changes 0
Metric Value
wmc 18
lcom 1
cbo 2
dl 17
loc 198
ccs 109
cts 110
cp 0.9909
rs 10
c 0
b 0
f 0

6 Methods

Rating   Name   Duplication   Size   Complexity  
A getSubscribedEvents() 7 7 1
A onItemPreParse() 10 10 1
A onItemPostParse() 0 10 1
B parseAndRenderIllustrations() 0 88 7
A preProcessHeaders() 0 27 3
A replaceTablesWithIllustrations() 0 23 5

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

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\EasybookEvents;
13
use Easybook\Events\ParseEvent;
14
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
15
use Trefoil\Plugins\BasePlugin;
16
17
/**
18
 * Manage the illustrations in the book item.
19
 *
20
 * An illustration is a block delimited by '<<' and '<</' marks.
21
 *
22
 * Expected syntax:
23
 *
24
 * << ========= "This is the illustration caption" ========= {.optional-class}
25
 * . . . whatever Markdown or HTML content
26
 * <</ =================
27
 *
28
 * where the '=' in the opening and closing block marks are optional, just to visually
29
 * delimit the illustration, and one or several classes can be specified between
30
 * curly brackets.
31
 *
32
 * ATX-style headers can be used inside of the illustration content and
33
 * will not be parsed by easybook (i.e. not added labels and ignored in the TOC).
34
 *
35
 * WARNINGS:
36
 *
37
 *  - When enabled, this functionality will take over the "tables" numbering
38
 *    and listing of easybook. If a table is needed as an illustration it will
39
 *    need to be done with this new markup.
40
 *    Ordinary tables (outside an illustration markup) will be ignored and just
41
 *    parsed as Markdown tables, not easybook tables.
42
 *
43
 *  - It needs the "lot.twig" templates present in the theme if used.
44
 *
45
 *  - Illustration HTML can be customized with "illustration.twig" template, but
46
 *    the plugin will apply a default HTML if the template is not present.
47
 *
48
 */
49
class IllustrationsPlugin extends BasePlugin implements EventSubscriberInterface
50
{
51
    protected $illustrations = [];
52
53 2 View Code Duplication
    public static function getSubscribedEvents()
54
    {
55
        return [
56 2
            EasybookEvents::PRE_PARSE  => ['onItemPreParse', -100],
57 2
            EasybookEvents::POST_PARSE => ['onItemPostParse', -1100]
58 2
        ];
59
    }
60
61
    /**
62
     * @param ParseEvent $event
63
     */
64 2 View Code Duplication
    public function onItemPreParse(ParseEvent $event)
65
    {
66 2
        $this->init($event);
67
68 2
        $content = $event->getItemProperty('original');
69
70 2
        $content = $this->parseAndRenderIllustrations($content);
71
72 2
        $event->setItemProperty('original', $content);
73 2
    }
74
75 2
    public function onItemPostParse(ParseEvent $event)
76
    {
77 2
        $this->init($event);
78
79 2
        $content = $event->getItemProperty('content');
80
81 2
        $this->replaceTablesWithIllustrations();
82
83 2
        $event->setItemProperty('content', $content);
84 2
    }
85
86
    /**
87
     * Parse illustrations and convert them to HTML.
88
     *
89
     * @param $content
90
     *
91
     * @return mixed
92
     */
93 2
    protected function parseAndRenderIllustrations($content)
94
    {
95 2
        $this->app['publishing.active_item.illustrations'] = [];
96
97 2
        $addIllustrationsLabels = in_array('illustration', $this->app->edition('labels') ?: array());
98 2
        $listOfTables = [];
99 2
        $parentItemNumber = $this->item['config']['number'];
100 2
        $counter = 0;
101
102 2
        $regExp = '/';
103 2
        $regExp .= '^<<'; // block opening
104 2
        $regExp .= '(?<p1> +=+)?'; // caption previous delimiter (optional)
105 2
        $regExp .= ' +"(?<caption>.*)"'; // caption
106 2
        $regExp .= '(?<p2>[ =]*)(?=[\n{])'; // caption post delimiter (optional)
107 2
        $regExp .= '(?<classGroup>\{(?<class>.*)\}.*)??'; // class (optional)
108 2
        $regExp .= '(?<data>.*)'; // text inside the block
109 2
        $regExp .= '^<<\/'; // block closing
110 2
        $regExp .= '(?<p3>.*)?$'; // closing delimiter (optional)
111 2
        $regExp .= '/Ums'; // Ungreedy, multiline, dotall
112
113 2
        $content = preg_replace_callback(
114 2
            $regExp,
115
            function ($matches) use ($parentItemNumber, &$addIllustrationsLabels, &$listOfTables, &$counter) {
116
117 2
                $caption = $matches['caption'];
118
119 2
                $data = $this->preProcessHeaders($matches['data']);
120
                
121 2
                $counter++;
122
123 2
                $slug = $this->app->slugify('Illustration ' . $parentItemNumber . '-' . $counter);
124
125
                $parameters = array(
126
                    'item'    => array(
127 2
                        'caption' => $caption,
128 2
                        'content' => $data,
129 2
                        'label'   => '',
130 2
                        'number'  => $counter,
131 2
                        'slug'    => $slug,
132 2
                    ),
133
                    'element' => array(
134 2
                        'number' => $parentItemNumber,
135 2
                    ),
136 2
                );
137
138
                // the publishing edition wants to label illustrations
139 2
                $label = '';
140 2
                if ($addIllustrationsLabels) {
141 2
                    if (isset($this->app['labels']['label']['illustration'])) {
142 2
                        $label = $this->app->getLabel('illustration', $parameters);
143 2
                    } else {
144
                        $label = $this->app->getLabel('table', $parameters);
145
                    }
146 2
                }
147
148 2
                $listOfTables[] = $parameters;
149
150 2
                $classes = implode(' ', explode(' ', str_replace('.', ' ', $matches['class'])));
151
                
152
                // complete the template parameters
153 2
                $parameters['item']['label'] = $label;
154 2
                $parameters['item']['classes'] = $classes;
155
                
156
                try {
157
                    // render with a template
158 2
                    return $this->app->render('illustration.twig', $parameters);
159 2
                } catch (\Twig_Error_Loader $e) {
160
                    // render anyway with a string
161 2
                    return sprintf(
162
                        '<div class="illustration%s" markdown="1" id="%s"><blockquote markdown="1">' .
163 2
                        '<div class="caption" markdown="1">%s%s<hr/></div>' .
164 2
                        '<div class="content" markdown="1">%s</div>' .
165 2
                        '</blockquote></div>',
166 2
                        $parameters['item']['classes'] ? ' ' . $parameters['item']['classes'] : '',
167 2
                        $parameters['item']['slug'],
168 2
                        $parameters['item']['label'] ? $parameters['item']['label']. ' - ' : '',
169 2
                        $parameters['item']['caption'],
170 2
                        $parameters['item']['content']
171 2
                    );
172
                }
173 2
            },
174
            $content
175 2
        );
176
177 2
        $this->app['publishing.active_item.illustrations'] = $listOfTables;
178
179 2
        return $content;
180
    }
181
182
    /**
183
     * Convert the ATX Markdown headers inside the illustration to HTML
184
     * to keep easybook from parsing them (so it does not add labels and ids).
185
     *
186
     * @param $content
187
     *
188
     * @return mixed
189
     */
190 2
    protected function preProcessHeaders($content)
191
    {
192 2
        $regExp = '/';
193 2
        $regExp .= '^(?<atx>#{5,6}) '; // atx header
194 2
        $regExp .= '(?<htext>.*)$'; // header text/rest
195 2
        $regExp .= '/Ums'; // Ungreedy, multiline, dotall
196
197 2
        $content = preg_replace_callback(
198 2
            $regExp,
199 2
            function ($matches) {
200
201 2
                $level = strlen($matches['atx']);
202
203 2
                $html = sprintf(
204 2
                    '<p class="heading" markdown="1">%s%s%s</p>',
205 2
                    $level == 5 ? '**' : '*',
206 2
                    $matches['htext'],
207 2
                    $level == 5 ? '**' : '*'
208 2
                );
209
210 2
                return $html;
211 2
            },
212
            $content
213 2
        );
214
215 2
        return $content;
216
    }
217
    
218
    /**
219
     * Replace all tables (in the internal list of tables) in the current item
220
     * with the detected illustrations.
221
     */
222 2
    protected function replaceTablesWithIllustrations()
223 2
    {
224 2
        $newTables = [];
225
226
        // filter out the tables of this item
227 2
        foreach ($this->app['publishing.list.tables'] as $itemTables) {
228 2
            $newItemTables = [];
229
230 2
            foreach ($itemTables as $table) {
231 2
                if ($table['element']['number'] !== $this->item['config']['number']) {
232 2
                    $newItemTables[] = $table;
233 2
                }
234 2
            }
235
236 2
            if (count($newItemTables)) {
237 2
                $newTables[] = $newItemTables;
238 2
            }
239 2
        }
240
241
        // and append the illustrations of this item
242 2
        $this->app['publishing.list.tables'] = $newTables;
243 2
        $this->app->append('publishing.list.tables', array_values($this->app['publishing.active_item.illustrations']));
244 2
    }
245
246
}
247