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