1<?php
2
3use FYKOS\dokuwiki\Extension\PluginNewsFeed\Model\ModelNews;
4use FYKOS\dokuwiki\Extension\PluginNewsFeed\AbstractStream;
5
6/**
7 * Class syntax_plugin_newsfeed_carousel
8 * @author Michal Červeňák <miso@fykos.cz>
9 */
10class syntax_plugin_newsfeed_carousel extends AbstractStream {
11
12    public function connectTo($mode): void {
13        $this->Lexer->addSpecialPattern('{{news-carousel>.+?}}', $mode, 'plugin_newsfeed_carousel');
14    }
15
16    public function handle($match, $state, $pos, Doku_Handler $handler): array {
17        preg_match_all('/([a-z]+)="([^".]*)"/', substr($match, 16, -2), $matches);
18        $parameters = [];
19        foreach ($matches[1] as $index => $match) {
20            $parameters[$match] = $matches[2][$index];
21        }
22        return [$state, [$parameters]];
23    }
24
25    public function render($format, Doku_Renderer $renderer, $data): bool {
26        if ($format !== 'xhtml') {
27            return true;
28        }
29
30        [$state, $match] = $data;
31        switch ($state) {
32            case DOKU_LEXER_SPECIAL:
33                [$param] = $match;
34                $renderer->nocache();
35
36                $stream = $this->helper->serviceStream->findByName($param['stream']);
37
38                $allNews = $stream->getNews();
39                if (count($allNews)) {
40                    $this->renderCarousel($renderer, $allNews, $param);
41                }
42        }
43        return true;
44    }
45
46    private function renderCarousel(Doku_Renderer $renderer, array $news, array $params): void {
47        $id = uniqid();
48        $indicators = [];
49        $items = [];
50        $noFeeds = 5;
51        for ($i = 0; $i < $noFeeds; $i++) {
52            if (!isset($news[$i])) {
53                break;
54            };
55            /**
56             * @var $feed ModelNews;
57             */
58            $feed = $news[$i];
59            $indicators[] = '<li data-target="#' . $id . '" data-slide-to="' . $i . '"></li>';
60            $items[] = $this->getCarouselItem($feed, !$i);
61        }
62        $renderer->doc .= '<div id="' . $id . '" class="feed-carousel carousel slide mb-3" data-ride="carousel">';
63
64        $this->renderCarouselIndicators($renderer, $indicators);
65        $this->renderCarouselItems($renderer, $items);
66        $renderer->doc .= '<div style="position: absolute; bottom: 0; right: 0;">';
67        $this->renderEditModal($renderer, $params);
68        $renderer->doc .= '</div>';
69        $renderer->doc .= '</div>';
70    }
71
72    private function renderCarouselIndicators(Doku_Renderer $renderer, array $indicators): void {
73        $renderer->doc .= '<ol class="carousel-indicators">';
74        foreach ($indicators as $indicator) {
75            $renderer->doc .= $indicator;
76        }
77        $renderer->doc .= '</ol>';
78    }
79
80    private function renderCarouselItems(Doku_Renderer $renderer, array $items): void {
81        $renderer->doc .= '<div class="carousel-inner" role="listbox">';
82        foreach ($items as $item) {
83            $renderer->doc .= $item;
84        }
85        $renderer->doc .= '</div>';
86    }
87
88    private function getCarouselItem(ModelNews $feed, bool $active): string {
89        $style = '';
90        if ($feed->hasImage()) {
91            $style .= 'background-image: url(' . ml($feed->image, ['w' => 1200]) . ')';
92        }
93        $background = 'bg-' . $feed->category . '-fade ';
94        $html = '';
95        $html .= '<div class="carousel-item ' . ($feed->hasImage() ? '' : $background) . ($active ? ' active' : '') .
96            '" style="' . $style . '">
97            <div class="mx-auto col-lg-8 col-xl-5">
98      <div class=" jumbotron-inner-container d-block ' . ($feed->image ? $background : '') . '">';
99        $html .= $this->getHeadline($feed);
100        $html .= $this->getText($feed);
101        $html .= $this->getLink($feed);
102        $html .= '</div></div></div>';
103        return $html;
104    }
105
106    private function getText(ModelNews $feed): string {
107        return '<p>' . $feed->renderText() . '</p>';
108    }
109
110    private function getHeadline(ModelNews $feed): string {
111        return '<h1>' . hsc($feed->title) . '</h1>';
112    }
113
114    private function getLink(ModelNews $feed): string {
115        if ($feed->linkTitle) {
116            if (preg_match('|^https?://|', $feed->linkHref)) {
117                $href = hsc($feed->linkHref);
118            } else {
119                $href = wl($feed->linkHref, null, true);
120            }
121            return '<p><a class="btn btn-outline-secondary" href="' . $href . '">' . $feed->linkTitle . '</a></p>';
122        }
123        return '';
124    }
125}
126