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.
Completed
Push — develop ( cf0abc...328c62 )
by Miguel Angel
02:54
created

TwigExtensionPlugin::embedFunction()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 18
Code Lines 10

Duplication

Lines 8
Ratio 44.44 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 8
loc 18
ccs 0
cts 10
cp 0
rs 9.4286
cc 2
eloc 10
nc 2
nop 1
crap 6
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
 * This plugin extends Twig to provide some useful functionalities:
19
 *
20
 * <li>
21
 * <b>Use configuration options in book contents</b> (instead of only in templates).
22
 * For example, in "chapter1.md" you can write "The title is {{ book.title }}".
23
 * This is mainly useful with user-defined configuration options.
24
 *
25
 * <li>
26
 * <b>itemtoc()</b> function automatically generates the Table of Contents of the current item.
27
 * The deep of the itemtoc can be tweaked by the configuration option <i>edition.itemtoc.deep</i>,
28
 * which defaults to one less than the main TOC deep <i>edition.toc.deep</i>.
29
 * It uses de <i>itemtoc.twig</i> template that must be available either as local or global template.
30
 *
31
 * <li>
32
 * <b>file()</b> function (deprecated, use fragment()) works like PHP's <i>include()</i>,
33
 * allowing the inclusion of another file into the current item.
34
 * The syntax is <i>file(filename, variables, options)</i> where "variables" and "options" are
35
 * optional hash tables where you can pass variables {'variable': 'value'} or
36
 * options {'nopagebreak': true} to the included file.
37
 *
38
 * <li>
39
 * <b>fragment()</b> function works like PHP's <i>include()</i>, allowing the inclusion of
40
 * another file into the current item.
41
 *
42
 * is a simplified version of <i>file()</i> without any variables or options.
43
 * The syntax is <i>fragment(filename)</i>. No page break will be inserted after the file contents.
44
 *
45
 *
46
 */
47
class TwigExtensionPlugin extends BasePlugin implements EventSubscriberInterface
48
{
49 1
    public static function getSubscribedEvents()
50 1
    {
51
        return array(
52 1
            EasybookEvents::PRE_PARSE  => 'onItemPreParse',
53 1
            EasybookEvents::POST_PARSE => array('onItemPostParse', -1010)
54 1
        );
55
    }
56
57 1
    public function onItemPreParse(ParseEvent $event)
58
    {
59 1
        $this->init($event);
60
61 1
        $content = $event->getItemProperty('original');
62
63
        // replace "{#" to avoid problems with markdown extra syntax for ids in headers
64 1
        $content = str_replace('{#', '@%@&', $content);
65
66
        // replace configuration options on PreParse to take care of normal replacements
67
        // and the first pass of "itemtoc()"
68 1
        $content = $this->renderString($content);
69
70
        # replace back "{#"
71 1
        $content = str_replace('@%@&', '{#', $content);
72
73 1
        $event->setItemProperty('original', $content);
74 1
    }
75
76 1
    public function onItemPostParse(ParseEvent $event)
77
    {
78 1
        $this->init($event);
79
80 1
        $content = $event->getItemProperty('content');
81
82
        // ensure the Twig function call is not enclosed into a '<p>..</p>' tag
83
        // as it will result in epub checking erros
84 1
        $content = preg_replace('/<p>\s*{{/', '{{', $content);
85 1
        $content = preg_replace('/}}\s*<\/p>/', '}}', $content);
86
87
        // replace "{#" to avoid problems with markdown extra syntax for ids in headers
88 1
        $content = str_replace('{#', '@%@&', $content);
89
90
        // replace also in PostParse to process the second pass of "itemtoc()" ("itemtoc_internal()")
91 1
        $content = $this->renderString($content);
92
93
        # replace back "{#"
94 1
        $content = str_replace('@%@&', '{#', $content);
95
96 1
        $event->setItemProperty('content', $content);
97 1
    }
98
99 1
    protected function renderString($string, $variables = array())
100
    {
101
        // we need a new Twig String Renderer environment
102 1
        $twig = new \Twig_Environment(new \Twig_Loader_String(), $this->app['twig.options']);
103
104 1
        $this->addTwigGlobals($twig);
105 1
        $this->registerExtensions($twig);
106
107 1
        return $twig->render($string, $variables);
108
    }
109
110 1
    protected function addTwigGlobals(\Twig_Environment $twig)
111
    {
112 1
        $twig->addGlobal('app', $this->app);
113
114 1
        if (null !== $this->app['publishing.book.config']['book']) {
115 1
            $twig->addGlobal('book', $this->app['publishing.book.config']['book']);
116
117 1
            $publishingEdition = $this->edition;
118 1
            $editions = $this->app->book('editions');
119 1
            $twig->addGlobal('edition', $editions[$publishingEdition]);
120 1
        }
121
122 1
        $twig->addGlobal('item', $this->item);
123 1
    }
124
125
    /**
126
     * Register all the extensions here.
127
     */
128 1
    protected function registerExtensions(\Twig_Environment $twig)
129
    {
130
        // file()
131 1
        $twig->addFunction(new \Twig_SimpleFunction('file', array($this, 'fileFunction')));
132
133
        // fragment()
134 1
        $twig->addFunction(new \Twig_SimpleFunction('fragment', array($this, 'fragmentFunction')));
135
136
        // itemtoc() and its internal counterpart
137 1
        $twig->addFunction(new \Twig_SimpleFunction('itemtoc', array($this, 'itemTocFunction')));
138 1
        $twig->addFunction(
139 1
            new \Twig_SimpleFunction('_itemtoc_internal', array($this, 'itemTocInternalFunction'))
140 1
        );
141 1
    }
142
143
    /**
144
     * Twig function: <b>file(filename, variables, options)</b>
145
     *
146
     * @deprecated
147
     *
148
     * @param string $filename  to be included (relative to book Contents dir)
149
     * @param array  $variables to be passed to the template
150
     * @param array  $options   (default: 'nopagebreak: false' => add a page break after the included text)
151
     *
152
     * @return string included text with all the replacements done.
153
     */
154 1
    public function fileFunction($filename, $variables = array(), $options = array())
155
    {
156 1
        $dir = $this->app['publishing.dir.contents'];
157 1
        $file = $dir . '/' . $filename;
158
159 1 View Code Duplication
        if (!file_exists($file)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
160
            $this->writeLn(
161
                sprintf('Included content file "%s" not found in "%s"', $filename, $this->item['config']['content']),
162
                'error'
163
            );
164
165
            return $filename;
166
        }
167
168 1
        $rendered = $this->renderString(file_get_contents($file), $variables);
169
170
        // pagebreak is added by default
171 1
        $addPageBreak = !isset($options['nopagebreak']) || (isset($options['nopagebreak']) && !$options['nopagebreak']);
172 1
        if ($addPageBreak) {
173 1
            $rendered .= '<div class="page-break"></div>';
174 1
        }
175
176 1
        return $rendered;
177
    }
178
179
    /**
180
     * Twig function: <b>fragment(filename)</b>
181
     *
182
     * @param string $filename  to be included (relative to book Contents dir)
183
     *
184
     * @param array  $variables to be passed to the template (example: {'name': 'John'} )
185
     * @param array  $options   (example {'pagebreak' => true} will add a page break after the included text)
186
     *
187
     * @return string included text with all the replacements done.
188
     */
189
    public function fragmentFunction($filename, $variables = array(), $options = array())
190
    {
191
        $dir = $this->app['publishing.dir.contents'];
192
        $file = $dir . '/' . $filename;
193
194 View Code Duplication
        if (!file_exists($file)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
195
            $this->writeLn(
196
                sprintf('Fragment file "%s" not found in "%s"', $filename, $this->item['config']['content']),
197
                'error'
198
            );
199
200
            return $filename;
201
        }
202
203
        $rendered = $this->renderString(file_get_contents($file), $variables);
204
205
        // add pagebreak if asked
206
        if (isset($options['pagebreak']) && $options['pagebreak']) {
207
            $rendered .= '<div class="page-break"></div>';
208
        }
209
        
210
        return $rendered;
211
    }
212
213
    /**
214
     * Twig function: <b>itemtoc()</b>
215
     *
216
     * @return string The _itemtoc_internal() function call
217
     *
218
     * Generating the item toc requires two phases to ensure that included files got parsed after being
219
     * included (with file()). The second phase does the actual rendering of the itemtoc
220
     * template.
221
     */
222 1
    public function itemTocFunction()
223
    {
224 1
        return '{{ _itemtoc_internal() }}';
225
    }
226
227
    /**
228
     * Twig function: <b>_itemtoc_internal()</b>
229
     * <b>This is an internal function so is not to be used directly in content files.</b>
230
     * It will be invoked on itemPostParse, after all the file() functions have been resolved and all
231
     * the included item contents have been parsed.
232
     *
233
     * @uses Configuration option <i>edition.plugins.TwigExtension.itemtoc.deep</i>
234
     *       (default: <i>edition.toc.deep + 1 </i>
235
     *
236
     * @return string The item toc rendered
237
     *
238
     */
239 1
    public function itemTocInternalFunction()
240
    {
241 1
        $template = 'itemtoc.twig';
242
243
        // note that we need to use the normal Twig template renderer, not our Twig string renderer
244 1
        $twig = $this->app['twig'];
245 1
        $this->addTwigGlobals($twig);
246
247 1
        $itemtoc_deep = $this->getEditionOption(
248 1
            'plugins.options.TwigExtension.itemtoc.deep',
249 1
            $this->getEditionOption('toc.deep') + 1
250 1
        );
251
252 1
        $rendered = $twig->render($template, array('itemtoc_deep' => $itemtoc_deep));
253
254 1
        return $rendered;
255
    }
256
}
257