Passed
Push — master ( 287999...316c8c )
by Dev
11:15
created

AppExtension::renderPhoneNumber()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 4
nc 1
nop 3
dl 0
loc 6
ccs 0
cts 0
cp 0
crap 2
rs 10
c 1
b 0
f 0
1
<?php
2
3
namespace PiedWeb\CMSBundle\Twig;
4
5
use Cocur\Slugify\Slugify;
6
use Doctrine\ORM\EntityManager;
7
use Doctrine\ORM\EntityManagerInterface;
8
use Exception;
9
use PiedWeb\CMSBundle\Entity\Media;
10
use PiedWeb\CMSBundle\Entity\PageInterface as Page;
11
use PiedWeb\CMSBundle\Service\MainContentManager;
12
use PiedWeb\CMSBundle\Service\PageCanonicalService;
13
use PiedWeb\RenderAttributes\AttributesTrait;
14
use Twig\Environment as Twig;
15
use Twig\Extension\AbstractExtension;
16
use Twig\TwigFilter;
17
use Twig\TwigFunction;
18
19
class AppExtension extends AbstractExtension
20
{
21
    use AttributesTrait;
22
23
    /** @var PageCanonicalService */
24
    protected $pageCanonical;
25
26
    /** @var EntityManagerInterface */
27
    private $em;
28
29
    /** @var string */
30
    private $page_class;
31
32
    public function __construct(EntityManager $em, string $page_class, PageCanonicalService $pageCanonical)
33
    {
34
        $this->em = $em;
35
        $this->pageCanonical = $pageCanonical;
36
        $this->page_class = $page_class;
37
    }
38
39
    public function getFilters()
40
    {
41
        return [
42
            //new TwigFilter('markdown', [AppExtension::class, 'markdownToHtml'], ['is_safe' => ['all']]),
43
            new TwigFilter('html_entity_decode', 'html_entity_decode'),
44
            new TwigFilter('preg_replace', [AppExtension::class, 'pregReplace']),
45
            new TwigFilter('slugify', [AppExtension::class, 'slugify']),
46
            new TwigFilter(
47
                'punctuation_beautifer',
48
                [MainContentManager::class, 'punctuationBeautifer'],
49
                ['is_safe' => ['html']]
50
            ),
51
        ];
52
    }
53
54
    public static function slugify($string)
55
    {
56
        return (new Slugify())->slugify($string);
57
    }
58
59
    public static function pregReplace($subject, $pattern, $replacement)
60
    {
61
        return preg_replace($pattern, $replacement, $subject);
62
    }
63
64
    public function getFunctions()
65
    {
66
        return [
67
            new TwigFunction('homepage', [$this->pageCanonical, 'generatePathForHomepage']),
68
            new TwigFunction('page', [$this->pageCanonical, 'generatePathForPage']),
69
            new TwigFunction('jslink', [AppExtension::class, 'renderJavascriptLink'], [
70
                'is_safe' => ['html'],
71
                'needs_environment' => true,
72
            ]),
73
            new TwigFunction('link', [AppExtension::class, 'renderJavascriptLink'], [
74
                'is_safe' => ['html'],
75
                'needs_environment' => true,
76
            ]),
77
            new TwigFunction('mail', [AppExtension::class, 'renderEncodedMail'], [
78
                'is_safe' => ['html'],
79
                'needs_environment' => true,
80
            ]),
81
            new TwigFunction('tel', [AppExtension::class, 'renderPhoneNumber'], [
82
                'is_safe' => ['html'],
83
                'needs_environment' => true,
84
            ]),
85
            new TwigFunction(
86
                'bookmark', // = anchor
87
                [AppExtension::class, 'renderTxtAnchor'],
88
                ['is_safe' => ['html'], 'needs_environment' => true]
89
            ),
90
            new TwigFunction(
91
                'anchor', // = bookmark
92
                [AppExtension::class, 'renderTxtAnchor'],
93
                ['is_safe' => ['html'], 'needs_environment' => true]
94
            ),
95
            new TwigFunction(
96
                'isCurrentPage',
97
                [$this, 'isCurrentPage'],
98
                ['is_safe' => ['html'], 'needs_environment' => false]
99
            ),
100
            new TwigFunction(
101
                'gallery',
102
                [$this, 'renderGallery'],
103
                ['is_safe' => ['html'], 'needs_environment' => true]
104
            ),
105
            new TwigFunction(
106
                'video',
107
                [$this, 'renderVideo'],
108
                ['is_safe' => ['html'], 'needs_environment' => true]
109
            ),
110
            new TwigFunction(
111
                'encode',
112
                [AppExtension::class, 'encode'],
113
                ['is_safe' => ['html']]
114
            ),
115
            new TwigFunction(
116
                'list',
117
                [$this, 'renderPagesList'],
118
                ['is_safe' => ['html'], 'needs_environment' => true]
119
            ),
120
            new TwigFunction('isInternalImage', [AppExtension::class, 'isInternalImage']),
121
            new TwigFunction('getImageFrom', [AppExtension::class, 'transformInlineImageToMedia']),
122
            new TwigFunction('getEmbedCode', [AppExtension::class, 'getEmbedCode']),
123
            new TwigFunction('extract', [$this, 'extract'], ['is_safe' => ['html'], 'needs_environment' => true]),
124
        ];
125
    }
126
127
    public function extract(Twig $env, string $name, Page $page)
128
    {
129
        $mainContentManager = new MainContentManager($env, $page); // todo cache it ?!
130
131
        $extractorFunction = 'get'.ucfirst($name);
132
133
        if (!method_exists($mainContentManager, $extractorFunction)) {
134
            throw new Exception('`'.$name.'` does not exist');
135
        }
136
137
        return $mainContentManager->$extractorFunction();
138
    }
139
140
    public static function getEmbedCode(
141
        $embed_code
142
    ) {
143
        if ($id = self::getYoutubeVideo($embed_code)) {
144
            $embed_code = '<iframe src=https://www.youtube-nocookie.com/embed/'.$id.' frameborder=0'
145
                    .' allow=autoplay;encrypted-media allowfullscreen class=w-100></iframe>';
146
        }
147
148
        return $embed_code;
149
    }
150
151
    public function renderVideo(
152
        Twig $env,
153
        $embed_code,
154
        $image,
155
        $alt,
156
        $btn_title = null,
157
        $btn_style = null
158
    ) {
159
        $embed_code = self::getEmbedCode($embed_code);
160
161
        $params = [
162
            'embed_code' => $embed_code,
163
            'image' => $image,
164
            'alt' => $alt,
165
        ];
166
167
        if (null !== $btn_title) {
168
            $params['btn_title'] = $btn_title;
169
        }
170
        if (null !== $btn_style) {
171
            $params['btn_style'] = $btn_style;
172
        }
173
174
        return $env->render('@PiedWebCMS/component/_video.html.twig', $params);
175
    }
176
177
    protected static function getYoutubeVideo($url)
178
    {
179
        if (preg_match('~^(?:https?://)?(?:www[.])?(?:youtube[.]com/watch[?]v=|youtu[.]be/)([^&]{11})~', $url, $m)) {
180
            return $m[1];
181
        }
182
    }
183
184
    public function renderPagesList(
185
        Twig $env,
186
        string $containing = '',
187
        int $number = 3,
188
        string $orderBy = 'createdAt',
189
        string $template = '@PiedWebCMS/page/_pages_list.html.twig'
190
    ) {
191
        $qb = $this->em->getRepository($this->page_class)->getQueryToFindPublished('p');
0 ignored issues
show
Bug introduced by
The method getQueryToFindPublished() does not exist on Doctrine\Persistence\ObjectRepository. It seems like you code against a sub-type of Doctrine\Persistence\ObjectRepository such as Doctrine\ORM\EntityRepository. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

191
        $qb = $this->em->getRepository($this->page_class)->/** @scrutinizer ignore-call */ getQueryToFindPublished('p');
Loading history...
192
        $qb->andWhere('p.mainContent LIKE :containing')->setParameter('containing', '%'.$containing.'%');
193
        $qb->orderBy('p.'.$orderBy, 'DESC');
194
        $qb->setMaxResults($number);
195
196
        $pages = $qb->getQuery()->getResult();
197
198
        return $env->render($template, ['pages' => $pages]);
199
    }
200
201
    public static function isInternalImage(string $media): bool
202
    {
203
        return 0 === strpos($media, '/media/default/');
204
    }
205
206
    public static function transformInlineImageToMedia(string $src)
207
    {
208
        if (self::isInternalImage($src)) {
209
            $src = substr($src, strlen('/media/default/'));
210
211
            $media = new Media();
212
            $media->setRelativeDir('/media');
213
            $media->setMedia($src);
214
            $media->setSlug(preg_replace('@(\.jpg|\.jpeg|\.png|\.gif)$@', '', $src), true);
215
216
            return $media;
217
        }
218
219
        $media = new Media();
220
        $media->setRelativeDir($src);
221
        $media->setMedia('');
222
        $media->setSlug('', true);
223
224
        return $media;
225
    }
226
227
    public function renderGallery(Twig $env, Page $currentPage, $filterImageFrom = 1, $length = 1001)
228
    {
229
        return $env->render('@PiedWebCMS/page/_gallery.html.twig', [
230
            'page' => $currentPage,
231
            'galleryFilterFrom' => $filterImageFrom - 1,
232
            'length' => $length,
233
        ]);
234
    }
235
236
    public function isCurrentPage(string $uri, ?Page $currentPage)
237
    {
238
        return
239
            null === $currentPage || $uri != $this->pageCanonical->generatePathForPage($currentPage->getRealSlug())
240
            ? false
241
            : true;
242
    }
243
244
    public static function renderTxtAnchor(Twig $env, $name)
245
    {
246
        $slugify = new Slugify();
247
        $name = $slugify->slugify($name);
248
249
        return $env->render('@PiedWebCMS/component/_txt_anchor.html.twig', ['name' => $name]);
250
    }
251
252
    public static function renderEncodedMail(Twig $env, $mail, $class = '')
253
    {
254
        return trim($env->render('@PiedWebCMS/component/_encoded_mail.html.twig', [
255
            'mail_readable' => self::readableEncodedMail($mail),
256
            'mail_encoded' => str_rot13($mail),
257
            'mail' => $mail,
258
            'class' => $class,
259
        ]));
260
    }
261
262
    public static function renderPhoneNumber(Twig $env, $number, $class = '')
263
    {
264
        return trim($env->render('@PiedWebCMS/component/_phone_number.html.twig', [
265
            'number' => str_replace([' ', '&nbsp;', '.'], '', $number),
266
            'number_readable' => str_replace(' ', '&nbsp;', preg_replace('#^\+33#', '0', $number)),
267
            'class' => $class,
268
        ]));
269
    }
270
271
    public static function readableEncodedMail($mail)
272
    {
273
        return str_replace('@', '<svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-at" '
274
        .'fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M13.106 '
275
        .'7.222c0-2.967-2.249-5.032-5.482-5.032-3.35 0-5.646 2.318-5.646 5.702 0 3.493 2.235 5.708 5.762'
276
        .' 5.708.862 0 1.689-.123 2.304-.335v-.862c-.43.199-1.354.328-2.29.328-2.926 0-4.813-1.88-4.813-4.798'
277
        .' 0-2.844 1.921-4.881 4.594-4.881 2.735 0 4.608 1.688 4.608 4.156 0 1.682-.554 2.769-1.416 2.769-.492'
278
        .' 0-.772-.28-.772-.76V5.206H8.923v.834h-.11c-.266-.595-.881-.964-1.6-.964-1.4 0-2.378 1.162-2.378 2.823 0'
279
        .' 1.737.957 2.906 2.379 2.906.8 0 1.415-.39 1.709-1.087h.11c.081.67.703 1.148 1.503 1.148 1.572 0 2.57-1.415'
280
        .' 2.57-3.643zm-7.177.704c0-1.197.54-1.907 1.456-1.907.93 0 1.524.738 1.524 1.907S8.308 9.84 7.371 9.84c-.895'
281
        .' 0-1.442-.725-1.442-1.914z"/></svg>', $mail);
282
    }
283
284
    public static function renderJavascriptLink(Twig $env, $anchor, $path, $attr = [])
285
    {
286
        if (0 === strpos($path, 'http://')) {
287
            $path = '-'.substr($path, 7);
288
        } elseif (0 === strpos($path, 'https://')) {
289
            $path = '_'.substr($path, 8);
290
        } elseif (0 === strpos($path, 'mailto:')) {
291
            $path = '@'.substr($path, 7);
292
        }
293
294
        return $env->render(
295
            '@PiedWebCMS/component/_javascript_link.html.twig',
296
            [
297
            'attr' => self::mergeAndMapAttributes($attr, ['class' => 'a', 'data-rot' => str_rot13($path)]),
298
            'anchor' => $anchor,
299
            ]
300
        );
301
    }
302
303
    public static function encode($string)
304
    {
305
        return str_rot13($string);
306
    }
307
}
308