Completed
Push — master ( 73caae...35f413 )
by Dev
11:37
created

AppExtension::readableEncodedMail()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 9
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 11
ccs 0
cts 0
cp 0
crap 2
rs 9.9666
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(
46
                'punctuation_beautifer',
47
                [MainContentManager::class, 'punctuationBeautifer'],
48
                ['is_safe' => ['html']]
49
            ),
50
        ];
51
    }
52
53
    public static function pregReplace($subject, $pattern, $replacement)
54
    {
55
        return preg_replace($pattern, $replacement, $subject);
56
    }
57
58
    public function getFunctions()
59
    {
60
        return [
61
            new TwigFunction('homepage', [$this->pageCanonical, 'generatePathForHomepage']),
62
            new TwigFunction('page', [$this->pageCanonical, 'generatePathForPage']),
63
            new TwigFunction('jslink', [AppExtension::class, 'renderJavascriptLink'], [
64
                'is_safe' => ['html'],
65
                'needs_environment' => true,
66
            ]),
67
            new TwigFunction('link', [AppExtension::class, 'renderJavascriptLink'], [
68
                'is_safe' => ['html'],
69
                'needs_environment' => true,
70
            ]),
71
            new TwigFunction('mail', [AppExtension::class, 'renderEncodedMail'], [
72
                'is_safe' => ['html'],
73
                'needs_environment' => true,
74
            ]),
75
            new TwigFunction(
76
                'bookmark', // = anchor
77
                [AppExtension::class, 'renderTxtAnchor'],
78
                ['is_safe' => ['html'], 'needs_environment' => true]
79
            ),
80
            new TwigFunction(
81
                'anchor', // = bookmark
82
                [AppExtension::class, 'renderTxtAnchor'],
83
                ['is_safe' => ['html'], 'needs_environment' => true]
84
            ),
85
            new TwigFunction(
86
                'isCurrentPage',
87
                [$this, 'isCurrentPage'],
88
                ['is_safe' => ['html'], 'needs_environment' => false]
89
            ),
90
            new TwigFunction(
91
                'gallery',
92
                [$this, 'renderGallery'],
93
                ['is_safe' => ['html'], 'needs_environment' => true]
94
            ),
95
            new TwigFunction(
96
                'video',
97
                [$this, 'renderVideo'],
98
                ['is_safe' => ['html'], 'needs_environment' => true]
99
            ),
100
            new TwigFunction(
101
                'encode',
102
                [AppExtension::class, 'encode'],
103
                ['is_safe' => ['html']]
104
            ),
105
            new TwigFunction(
106
                'list',
107
                [$this, 'renderPagesList'],
108
                ['is_safe' => ['html'], 'needs_environment' => true]
109
            ),
110
            new TwigFunction('isInternalImage', [AppExtension::class, 'isInternalImage']),
111
            new TwigFunction('getImageFrom', [AppExtension::class, 'transformInlineImageToMedia']),
112
            new TwigFunction('getEmbedCode', [AppExtension::class, 'getEmbedCode']),
113
            new TwigFunction('extract', [$this, 'extract'], ['is_safe' => ['html'], 'needs_environment' => true]),
114
        ];
115
    }
116
117
    public function extract(Twig $env, string $name, Page $page)
118
    {
119
        $mainContentManager = new MainContentManager($env, $page); // todo cache it ?!
120
121
        $extractorFunction = 'get'.ucfirst($name);
122
123
        if (!method_exists($mainContentManager, $extractorFunction)) {
124
            throw new Exception('`'.$name.'` does not exist');
125
        }
126
127
        return $mainContentManager->$extractorFunction();
128
    }
129
130
    public static function getEmbedCode(
131
        $embed_code
132
    ) {
133
        if ($id = self::getYoutubeVideo($embed_code)) {
134
            $embed_code = '<iframe src=https://www.youtube-nocookie.com/embed/'.$id.' frameborder=0'
135
                    .' allow=autoplay;encrypted-media allowfullscreen class=w-100></iframe>';
136
        }
137
138
        return $embed_code;
139
    }
140
141
    public function renderVideo(
142
        Twig $env,
143
        $embed_code,
144
        $image,
145
        $alt,
146
        $btn_title = null,
147
        $btn_style = null
148
    ) {
149
        $embed_code = self::getEmbedCode($embed_code);
150
151
        $params = [
152
            'embed_code' => $embed_code,
153
            'image' => $image,
154
            'alt' => $alt,
155
        ];
156
157
        if (null !== $btn_title) {
158
            $params['btn_title'] = $btn_title;
159
        }
160
        if (null !== $btn_style) {
161
            $params['btn_style'] = $btn_style;
162
        }
163
164
        return $env->render('@PiedWebCMS/component/_video.html.twig', $params);
165
    }
166
167
    protected static function getYoutubeVideo($url)
168
    {
169
        if (preg_match('~^(?:https?://)?(?:www[.])?(?:youtube[.]com/watch[?]v=|youtu[.]be/)([^&]{11})~', $url, $m)) {
170
            return $m[1];
171
        }
172
    }
173
174
    public function renderPagesList(
175
        Twig $env,
176
        string $containing = '',
177
        int $number = 3,
178
        string $orderBy = 'createdAt',
179
        string $template = '@PiedWebCMS/page/_pages_list.html.twig'
180
    ) {
181
        $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

181
        $qb = $this->em->getRepository($this->page_class)->/** @scrutinizer ignore-call */ getQueryToFindPublished('p');
Loading history...
182
        $qb->andWhere('p.mainContent LIKE :containing')->setParameter('containing', '%'.$containing.'%');
183
        $qb->orderBy('p.'.$orderBy, 'DESC');
184
        $qb->setMaxResults($number);
185
186
        $pages = $qb->getQuery()->getResult();
187
188
        return $env->render($template, ['pages' => $pages]);
189
    }
190
191
    public static function isInternalImage(string $media): bool
192
    {
193
        return 0 === strpos($media, '/media/default/');
194
    }
195
196
    public static function transformInlineImageToMedia(string $src)
197
    {
198
        if (self::isInternalImage($src)) {
199
            $src = substr($src, strlen('/media/default/'));
200
201
            $media = new Media();
202
            $media->setRelativeDir('/media');
203
            $media->setMedia($src);
204
            $media->setSlug(preg_replace('@(\.jpg|\.jpeg|\.png|\.gif)$@', '', $src), true);
205
206
            return $media;
207
        }
208
209
        $media = new Media();
210
        $media->setRelativeDir($src);
211
        $media->setMedia('');
212
        $media->setSlug('', true);
213
214
        return $media;
215
    }
216
217
    public function renderGallery(Twig $env, Page $currentPage, $filterImageFrom = 1, $length = 1001)
218
    {
219
        return $env->render('@PiedWebCMS/page/_gallery.html.twig', [
220
            'page' => $currentPage,
221
            'galleryFilterFrom' => $filterImageFrom - 1,
222
            'length' => $length,
223
        ]);
224
    }
225
226
    public function isCurrentPage(string $uri, ?Page $currentPage)
227
    {
228
        return
229
            null === $currentPage || $uri != $this->pageCanonical->generatePathForPage($currentPage->getRealSlug())
230
            ? false
231
            : true;
232
    }
233
234
    public static function renderTxtAnchor(Twig $env, $name)
235
    {
236
        $slugify = new Slugify();
237
        $name = $slugify->slugify($name);
238
239
        return $env->render('@PiedWebCMS/component/_txt_anchor.html.twig', ['name' => $name]);
240
    }
241
242
    public static function renderEncodedMail(Twig $env, $mail, $class = '')
243
    {
244
        return $env->render('@PiedWebCMS/component/_encoded_mail.html.twig', [
245
            'mail_readable' => self::readableEncodedMail($mail),
246
            'mail_encoded' => str_rot13($mail),
247
            'mail' => $mail,
248
            'class' => $class,
249
        ]);
250
    }
251
252
    public static function readableEncodedMail($mail)
253
    {
254
        return str_replace('@', '<svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-at" '
255
        .'fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M13.106 '
256
        .'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'
257
        .' 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'
258
        .' 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'
259
        .' 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'
260
        .' 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'
261
        .' 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'
262
        .' 0-1.442-.725-1.442-1.914z"/></svg>', $mail);
263
    }
264
265
    public static function renderJavascriptLink(Twig $env, $anchor, $path, $attr = [])
266
    {
267
        if (0 === strpos($path, 'http://')) {
268
            $path = '-'.substr($path, 7);
269
        } elseif (0 === strpos($path, 'https://')) {
270
            $path = '_'.substr($path, 8);
271
        } elseif (0 === strpos($path, 'mailto:')) {
272
            $path = '@'.substr($path, 7);
273
        }
274
275
        return $env->render(
276
            '@PiedWebCMS/component/_javascript_link.html.twig',
277
            [
278
            'attr' => self::mergeAndMapAttributes($attr, ['class' => 'a', 'data-rot' => str_rot13($path)]),
279
            'anchor' => $anchor,
280
            ]
281
        );
282
    }
283
284
    public static function encode($string)
285
    {
286
        return str_rot13($string);
287
    }
288
}
289