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 ( 602388...236759 )
by Miguel Angel
03:28
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
 * This plugin extends Twig to provide some useful functionalities:
18
 *
19
 * <li>
20
 * <b>Use configuration options in book contents</b> (instead of only in templates).
21
 * For example, in "chapter1.md" you can write "The title is {{ book.title }}".
22
 * This is mainly useful with user-defined configuration options.
23
 *
24
 * <li>
25
 * <b>itemtoc()</b> function automatically generates the Table of Contents of the current item.
26
 * The deep of the itemtoc can be tweaked by the configuration option <i>edition.itemtoc.deep</i>,
27
 * which defaults to one less than the main TOC deep <i>edition.toc.deep</i>.
28
 * It uses de <i>itemtoc.twig</i> template that must be available either as local or global template.
29
 *
30
 * <li>
31
 * <b>file()</b> function works like PHP's <i>include()</i>, allowing the inclusion of another file
32
 * into the current item.
33
 * The syntax is <i>file(filename, variables, options)</i> where "variables" and "options" are
34
 * optional hash tables where you can pass variables {'variable': 'value'} or
35
 * options {'nopagebreak': true} to the included file.
36
 * 
37
 * <li>
38
 * <b>embed()</b> function is a simplified version of <i>file()</i> without any variables or options.
39
 * The syntax is <i>embed(filename)</i>. No page break will be inserted after the file contents. 
40
 * 
41
 * 
42
 */
43
class TwigExtensionPlugin extends BasePlugin implements EventSubscriberInterface
44
{
45 1
    public static function getSubscribedEvents()
46
    {
47
        return array(
48 1
            EasybookEvents::PRE_PARSE  => 'onItemPreParse',
49 1
            EasybookEvents::POST_PARSE => array('onItemPostParse', -1010)
50 1
        );
51
    }
52
53 1
    public function onItemPreParse(ParseEvent $event)
54
    {
55 1
        $this->init($event);
56
57 1
        $content = $event->getItemProperty('original');
58
59
        // replace "{#" to avoid problems with markdown extra syntax for ids in headers
60 1
        $content = str_replace('{#', '@%@&', $content);
61
62
        // replace configuration options on PreParse to take care of normal replacements
63
        // and the first pass of "itemtoc()"
64 1
        $content = $this->renderString($content);
65
66
        # replace back "{#"
67 1
        $content = str_replace('@%@&', '{#', $content);
68
69 1
        $event->setItemProperty('original', $content);
70 1
    }
71
72 1
    public function onItemPostParse(ParseEvent $event)
73
    {
74 1
        $this->init($event);
75
76 1
        $content = $event->getItemProperty('content');
77
78
        // ensure the Twig function call is not enclosed into a '<p>..</p>' tag
79
        // as it will result in epub checking erros
80 1
        $content = preg_replace('/<p>\s*{{/', '{{', $content);
81 1
        $content = preg_replace('/}}\s*<\/p>/', '}}', $content);
82
83
        // replace "{#" to avoid problems with markdown extra syntax for ids in headers
84 1
        $content = str_replace('{#', '@%@&', $content);
85
86
        // replace also in PostParse to process the second pass of "itemtoc()" ("itemtoc_internal()")
87 1
        $content = $this->renderString($content);
88
89
        # replace back "{#"
90 1
        $content = str_replace('@%@&', '{#', $content);
91
92 1
        $event->setItemProperty('content', $content);
93 1
    }
94
95 1
    protected function renderString($string, $variables = array())
96
    {
97
        // we need a new Twig String Renderer environment
98 1
        $twig = new \Twig_Environment(new \Twig_Loader_String(), $this->app['twig.options']);
99
100 1
        $this->addTwigGlobals($twig);
101 1
        $this->registerExtensions($twig);
102
103 1
        return $twig->render($string, $variables);
104
    }
105
106 1
    protected function addTwigGlobals(\Twig_Environment $twig)
107
    {
108 1
        $twig->addGlobal('app', $this->app);
109
110 1
        if (null !== $this->app['publishing.book.config']['book']) {
111 1
            $twig->addGlobal('book', $this->app['publishing.book.config']['book']);
112
113 1
            $publishingEdition = $this->edition;
114 1
            $editions = $this->app->book('editions');
115 1
            $twig->addGlobal('edition', $editions[$publishingEdition]);
116 1
        }
117
118 1
        $twig->addGlobal('item', $this->item);
119 1
    }
120
121
    /**
122
     * Register all the extensions here.
123
     */
124 1
    protected function registerExtensions(\Twig_Environment $twig)
125
    {
126
        // file()
127 1
        $twig->addFunction(new \Twig_SimpleFunction('file', array($this, 'fileFunction')));
128
        
129
        // embed()
130 1
        $twig->addFunction(new \Twig_SimpleFunction('embed', array($this, 'embedFunction')));
131
132
        // itemtoc() and its internal counterpart
133 1
        $twig->addFunction(new \Twig_SimpleFunction('itemtoc', array($this, 'itemTocFunction')));
134 1
        $twig->addFunction(
135 1
             new \Twig_SimpleFunction('_itemtoc_internal', array($this, 'itemTocInternalFunction'))
136 1
        );
137 1
    }
138
139
    /**
140
     * Twig function: <b>file(filename, variables, options)</b>
141
     *
142
     * @param string $filename  to be included (relative to book Contents dir)
143
     * @param array  $variables to be passed to the template
144
     * @param array  $options   (default: 'nopagebreak: false' => add a page break after the included text)
145
     *
146
     * @return string included text with all the replacements done.
147
     */
148 1
    public function fileFunction($filename, $variables = array(), $options = array())
149
    {
150 1
        $dir = $this->app['publishing.dir.contents'];
151 1
        $file = $dir . '/' . $filename;
152
153 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...
154
            $this->writeLn(
155
                 sprintf('Included content file "%s" not found in "%s"', $filename, $this->item['config']['content']),
156
                 'error'
157
            );
158
159
            return $filename;
160
        }
161
162 1
        $rendered = $this->renderString(file_get_contents($file), $variables);
163
        
164
        // pagebreak is added by default
165 1
        $addPageBreak = !isset($options['nopagebreak']) || (isset($options['nopagebreak']) && !$options['nopagebreak']);
166 1
        if ($addPageBreak) {
167 1
            $rendered .= '<div class="page-break"></div>';
168 1
        }
169
170 1
        return $rendered;
171
    }
172
173
    /**
174
     * Twig function: <b>embed(filename)</b>
175
     *
176
     * @param string $filename  to be included (relative to book Contents dir)
177
     *
178
     * @return string included text with all the replacements done.
179
     */
180
    public function embedFunction($filename)
181
    {
182
        $dir = $this->app['publishing.dir.contents'];
183
        $file = $dir . '/' . $filename;
184
185 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...
186
            $this->writeLn(
187
                sprintf('Included content file "%s" not found in "%s"', $filename, $this->item['config']['content']),
188
                'error'
189
            );
190
191
            return $filename;
192
        }
193
194
        $rendered = $this->renderString(file_get_contents($file));
195
196
        return $rendered;
197
    }
198
    
199
    /**
200
     * Twig function: <b>itemtoc()</b>
201
     *
202
     * @return string The _itemtoc_internal() function call
203
     *
204
     * Generating the item toc requires two phases to ensure that included files got parsed after being
205
     * included (with file()). The second phase does the actual rendering of the itemtoc
206
     * template.
207
     */
208 1
    public function itemTocFunction()
209
    {
210 1
        return '{{ _itemtoc_internal() }}';
211
    }
212
213
    /**
214
     * Twig function: <b>_itemtoc_internal()</b>
215
     * <b>This is an internal function so is not to be used directly in content files.</b>
216
     * It will be invoked on itemPostParse, after all the file() functions have been resolved and all
217
     * the included item contents have been parsed.
218
     *
219
     * @uses Configuration option <i>edition.plugins.TwigExtension.itemtoc.deep</i>
220
     *       (default: <i>edition.toc.deep + 1 </i>
221
     *
222
     * @return string The item toc rendered
223
     *
224
     */
225 1
    public function itemTocInternalFunction()
226
    {
227 1
        $template = 'itemtoc.twig';
228
229
        // note that we need to use the normal Twig template renderer, not our Twig string renderer
230 1
        $twig = $this->app['twig'];
231 1
        $this->addTwigGlobals($twig);
232
233 1
        $itemtoc_deep = $this->getEditionOption(
234 1
                             'plugins.options.TwigExtension.itemtoc.deep',
235 1
                             $this->getEditionOption('toc.deep') + 1
236 1
        );
237
238 1
        $rendered = $twig->render($template, array('itemtoc_deep' => $itemtoc_deep));
239
240 1
        return $rendered;
241
    }
242
}
243