121913ab3SNickeau<?php 221913ab3SNickeau 321913ab3SNickeau 4e8b2ff59SNickeauuse ComboStrap\Analytics; 537748cd8SNickeauuse ComboStrap\CallStack; 623723136Sgerardnicouse ComboStrap\DokuPath; 7*1fa8c418SNickeauuse ComboStrap\Image; 823723136Sgerardnicouse ComboStrap\LogUtility; 923723136Sgerardnicouse ComboStrap\MediaLink; 1021913ab3SNickeauuse ComboStrap\PluginUtility; 1137748cd8SNickeauuse ComboStrap\ThirdPartyPlugins; 1221913ab3SNickeau 1321913ab3SNickeau 1437748cd8SNickeaurequire_once(__DIR__ . '/../ComboStrap/PluginUtility.php'); 1521913ab3SNickeau 1621913ab3SNickeau 1721913ab3SNickeau/** 1823723136Sgerardnico * Media 1923723136Sgerardnico * 2023723136Sgerardnico * Takes over the {@link \dokuwiki\Parsing\ParserMode\Media media mode} 2123723136Sgerardnico * that is processed by {@link Doku_Handler_Parse_Media} 2223723136Sgerardnico * 2323723136Sgerardnico * 2423723136Sgerardnico * 2523723136Sgerardnico * It can be a internal / external media 2637748cd8SNickeau * 27*1fa8c418SNickeau * 2837748cd8SNickeau * See: 2937748cd8SNickeau * https://developers.google.com/search/docs/advanced/guidelines/google-images 3021913ab3SNickeau */ 3121913ab3SNickeauclass syntax_plugin_combo_media extends DokuWiki_Syntax_Plugin 3221913ab3SNickeau{ 3321913ab3SNickeau 3421913ab3SNickeau 3521913ab3SNickeau const TAG = "media"; 3621913ab3SNickeau 3721913ab3SNickeau /** 3821913ab3SNickeau * Used in the move plugin 3921913ab3SNickeau * !!! The two last word of the plugin class !!! 4021913ab3SNickeau */ 4121913ab3SNickeau const COMPONENT = 'combo_' . self::TAG; 4221913ab3SNickeau 4321913ab3SNickeau 4421913ab3SNickeau /** 4523723136Sgerardnico * Found at {@link \dokuwiki\Parsing\ParserMode\Media} 4621913ab3SNickeau */ 4723723136Sgerardnico const MEDIA_PATTERN = "\{\{(?:[^>\}]|(?:\}[^\}]))+\}\}"; 4821913ab3SNickeau 49531e725cSNickeau /** 50531e725cSNickeau * Enable or disable the image 51531e725cSNickeau */ 52531e725cSNickeau const CONF_IMAGE_ENABLE = "imageEnable"; 53531e725cSNickeau 5437748cd8SNickeau /** 5537748cd8SNickeau * Svg Rendering error 5637748cd8SNickeau */ 5737748cd8SNickeau const SVG_RENDERING_ERROR_CLASS = "combo-svg-rendering-error"; 5837748cd8SNickeau 5937748cd8SNickeau 6037748cd8SNickeau /** 6137748cd8SNickeau * @param $attributes 6237748cd8SNickeau * @param renderer_plugin_combo_analytics $renderer 6337748cd8SNickeau */ 6437748cd8SNickeau public static function updateStatistics($attributes, renderer_plugin_combo_analytics $renderer) 6537748cd8SNickeau { 6637748cd8SNickeau $media = MediaLink::createFromCallStackArray($attributes); 67*1fa8c418SNickeau $renderer->stats[Analytics::MEDIA_COUNT]++; 68*1fa8c418SNickeau $scheme = $media->getDefaultImage()->getScheme(); 6937748cd8SNickeau switch ($scheme) { 7037748cd8SNickeau case DokuPath::LOCAL_SCHEME: 71*1fa8c418SNickeau $renderer->stats[Analytics::INTERNAL_MEDIA_COUNT]++; 72*1fa8c418SNickeau if (!$media->getDefaultImage()->exists()) { 73*1fa8c418SNickeau $renderer->stats[Analytics::INTERNAL_BROKEN_MEDIA_COUNT]++; 7437748cd8SNickeau } 7537748cd8SNickeau break; 7637748cd8SNickeau case DokuPath::INTERNET_SCHEME: 77*1fa8c418SNickeau $renderer->stats[Analytics::EXTERNAL_MEDIA_COUNT]++; 7837748cd8SNickeau break; 7937748cd8SNickeau } 8037748cd8SNickeau } 8137748cd8SNickeau 8221913ab3SNickeau 8321913ab3SNickeau function getType() 8421913ab3SNickeau { 8521913ab3SNickeau return 'formatting'; 8621913ab3SNickeau } 8721913ab3SNickeau 8821913ab3SNickeau /** 8921913ab3SNickeau * How Dokuwiki will add P element 9021913ab3SNickeau * 9121913ab3SNickeau * * 'normal' - The plugin can be used inside paragraphs (inline) 9221913ab3SNickeau * * 'block' - Open paragraphs need to be closed before plugin output - block should not be inside paragraphs 9321913ab3SNickeau * * 'stack' - Special case. Plugin wraps other paragraphs. - Stacks can contain paragraphs 9421913ab3SNickeau * 9521913ab3SNickeau * @see DokuWiki_Syntax_Plugin::getPType() 9621913ab3SNickeau */ 9721913ab3SNickeau function getPType() 9821913ab3SNickeau { 9923723136Sgerardnico /** 10023723136Sgerardnico * An image is not a block (it can be inside paragraph) 10123723136Sgerardnico */ 10221913ab3SNickeau return 'normal'; 10321913ab3SNickeau } 10421913ab3SNickeau 10521913ab3SNickeau function getAllowedTypes() 10621913ab3SNickeau { 10721913ab3SNickeau return array('substition', 'formatting', 'disabled'); 10821913ab3SNickeau } 10921913ab3SNickeau 11023723136Sgerardnico /** 11123723136Sgerardnico * It should be less than {@link \dokuwiki\Parsing\ParserMode\Media::getSort()} 11223723136Sgerardnico * (It was 320 at the time of writing this code) 11323723136Sgerardnico * @return int 11423723136Sgerardnico * 11523723136Sgerardnico */ 11621913ab3SNickeau function getSort() 11721913ab3SNickeau { 11823723136Sgerardnico return 319; 11921913ab3SNickeau } 12021913ab3SNickeau 12121913ab3SNickeau 12221913ab3SNickeau function connectTo($mode) 12321913ab3SNickeau { 124531e725cSNickeau $enable = $this->getConf(self::CONF_IMAGE_ENABLE, 1); 12521913ab3SNickeau if (!$enable) { 12621913ab3SNickeau 12721913ab3SNickeau // Inside a card, we need to take over and enable it 12821913ab3SNickeau $modes = [ 1299337a630SNickeau PluginUtility::getModeFromTag(syntax_plugin_combo_card::TAG), 13021913ab3SNickeau ]; 13121913ab3SNickeau $enable = in_array($mode, $modes); 13221913ab3SNickeau } 13321913ab3SNickeau 13421913ab3SNickeau if ($enable) { 13537748cd8SNickeau if ($mode !== PluginUtility::getModeFromPluginName(ThirdPartyPlugins::IMAGE_MAPPING_NAME)) { 1369337a630SNickeau $this->Lexer->addSpecialPattern(self::MEDIA_PATTERN, $mode, PluginUtility::getModeFromTag($this->getPluginComponent())); 13721913ab3SNickeau } 13821913ab3SNickeau } 13937748cd8SNickeau } 14021913ab3SNickeau 14121913ab3SNickeau 142*1fa8c418SNickeau function handle($match, $state, $pos, Doku_Handler $handler): array 14321913ab3SNickeau { 14421913ab3SNickeau 14521913ab3SNickeau switch ($state) { 14621913ab3SNickeau 14721913ab3SNickeau 14821913ab3SNickeau // As this is a container, this cannot happens but yeah, now, you know 14921913ab3SNickeau case DOKU_LEXER_SPECIAL : 15037748cd8SNickeau 15123723136Sgerardnico $media = MediaLink::createFromRenderMatch($match); 15221913ab3SNickeau $attributes = $media->toCallStackArray(); 15337748cd8SNickeau 15437748cd8SNickeau $callStack = CallStack::createFromHandler($handler); 15537748cd8SNickeau 15637748cd8SNickeau /** 15737748cd8SNickeau * Parent 15837748cd8SNickeau */ 15937748cd8SNickeau $parent = $callStack->moveToParent(); 16021913ab3SNickeau $parentTag = ""; 16121913ab3SNickeau if (!empty($parent)) { 16237748cd8SNickeau $parentTag = $parent->getTagName(); 16321913ab3SNickeau if ($parentTag == syntax_plugin_combo_link::TAG) { 16421913ab3SNickeau /** 165*1fa8c418SNickeau * TODO: should be on the exit tag of the link 16621913ab3SNickeau * The image is in a link, we don't want another link 16721913ab3SNickeau * to the image 16821913ab3SNickeau */ 169a6bf47aaSNickeau $attributes[MediaLink::LINKING_KEY] = MediaLink::LINKING_NOLINK_VALUE; 17021913ab3SNickeau } 17121913ab3SNickeau } 17237748cd8SNickeau 17321913ab3SNickeau return array( 17421913ab3SNickeau PluginUtility::STATE => $state, 17521913ab3SNickeau PluginUtility::ATTRIBUTES => $attributes, 17637748cd8SNickeau PluginUtility::CONTEXT => $parentTag 17721913ab3SNickeau ); 17821913ab3SNickeau 17921913ab3SNickeau 18021913ab3SNickeau } 18121913ab3SNickeau return array(); 18221913ab3SNickeau 18321913ab3SNickeau } 18421913ab3SNickeau 18521913ab3SNickeau /** 18621913ab3SNickeau * Render the output 18721913ab3SNickeau * @param string $format 18821913ab3SNickeau * @param Doku_Renderer $renderer 18921913ab3SNickeau * @param array $data - what the function handle() return'ed 19021913ab3SNickeau * @return boolean - rendered correctly? (however, returned value is not used at the moment) 19121913ab3SNickeau * @see DokuWiki_Syntax_Plugin::render() 19221913ab3SNickeau * 19321913ab3SNickeau * 19421913ab3SNickeau */ 19521913ab3SNickeau function render($format, Doku_Renderer $renderer, $data) 19621913ab3SNickeau { 19721913ab3SNickeau 19821913ab3SNickeau switch ($format) { 19921913ab3SNickeau 20021913ab3SNickeau case 'xhtml': 20121913ab3SNickeau 20221913ab3SNickeau /** @var Doku_Renderer_xhtml $renderer */ 20321913ab3SNickeau $attributes = $data[PluginUtility::ATTRIBUTES]; 204*1fa8c418SNickeau $mediaLink = MediaLink::createFromCallStackArray($attributes); 205*1fa8c418SNickeau $media = $mediaLink->getMedia(); 20623723136Sgerardnico if ($media->getScheme() == DokuPath::LOCAL_SCHEME) { 207*1fa8c418SNickeau $mediaLink = MediaLink::createFromCallStackArray($attributes, $renderer->date_at); 20837748cd8SNickeau if ($media->isImage() || $media->getExtension() === "svg") { 20937748cd8SNickeau try { 210*1fa8c418SNickeau $renderer->doc .= $mediaLink->renderMediaTagWithLink(); 21137748cd8SNickeau } catch (RuntimeException $e) { 21237748cd8SNickeau $errorClass = self::SVG_RENDERING_ERROR_CLASS; 21337748cd8SNickeau $message = "Media ({$media->getPath()}). Error while rendering: {$e->getMessage()}"; 214*1fa8c418SNickeau $renderer->doc .= "<span class=\"text-alert $errorClass\">" . hsc(trim($message)) . "</span>"; 215*1fa8c418SNickeau LogUtility::msg($message, LogUtility::LVL_MSG_ERROR, MediaLink::CANONICAL); 21637748cd8SNickeau } 21723723136Sgerardnico return true; 21823723136Sgerardnico } 21923723136Sgerardnico } 22021913ab3SNickeau 22121913ab3SNickeau /** 22223723136Sgerardnico * This is not an local internal media image (a video or an url image) 22321913ab3SNickeau * Dokuwiki takes over 22421913ab3SNickeau */ 225531e725cSNickeau $type = $attributes[MediaLink::MEDIA_DOKUWIKI_TYPE]; 22621913ab3SNickeau $src = $attributes['src']; 22721913ab3SNickeau $title = $attributes['title']; 22821913ab3SNickeau $align = $attributes['align']; 22921913ab3SNickeau $width = $attributes['width']; 23021913ab3SNickeau $height = $attributes['height']; 23121913ab3SNickeau $cache = $attributes['cache']; 232a6bf47aaSNickeau if ($cache == null) { 233a6bf47aaSNickeau // Dokuwiki needs a value 234a6bf47aaSNickeau // If their is no value it will output it without any value 235a6bf47aaSNickeau // in the query string. 236a6bf47aaSNickeau $cache = "cache"; 237a6bf47aaSNickeau } 23821913ab3SNickeau $linking = $attributes['linking']; 23923723136Sgerardnico switch ($type) { 240531e725cSNickeau case MediaLink::INTERNAL_MEDIA_CALL_NAME: 24121913ab3SNickeau $renderer->doc .= $renderer->internalmedia($src, $title, $align, $width, $height, $cache, $linking, true); 24223723136Sgerardnico break; 243531e725cSNickeau case MediaLink::EXTERNAL_MEDIA_CALL_NAME: 24423723136Sgerardnico $renderer->doc .= $renderer->externalmedia($src, $title, $align, $width, $height, $cache, $linking, true); 24523723136Sgerardnico break; 24623723136Sgerardnico default: 24723723136Sgerardnico LogUtility::msg("The dokuwiki media type ($type) is unknown"); 24823723136Sgerardnico break; 24921913ab3SNickeau } 25021913ab3SNickeau 25123723136Sgerardnico return true; 25221913ab3SNickeau 2539337a630SNickeau case 2549337a630SNickeau "metadata": 25521913ab3SNickeau 25621913ab3SNickeau /** 25721913ab3SNickeau * Keep track of the metadata 25821913ab3SNickeau * @var Doku_Renderer_metadata $renderer 25921913ab3SNickeau */ 26037748cd8SNickeau $attributes = $data[PluginUtility::ATTRIBUTES]; 26121913ab3SNickeau self::registerImageMeta($attributes, $renderer); 26223723136Sgerardnico return true; 26321913ab3SNickeau 264e8b2ff59SNickeau case renderer_plugin_combo_analytics::RENDERER_FORMAT: 265e8b2ff59SNickeau 266e8b2ff59SNickeau /** 267e8b2ff59SNickeau * Special pattern call 268e8b2ff59SNickeau * @var renderer_plugin_combo_analytics $renderer 269e8b2ff59SNickeau */ 270e8b2ff59SNickeau $attributes = $data[PluginUtility::ATTRIBUTES]; 27137748cd8SNickeau self::updateStatistics($attributes, $renderer); 272e8b2ff59SNickeau return true; 273e8b2ff59SNickeau 27421913ab3SNickeau } 27521913ab3SNickeau // unsupported $mode 27621913ab3SNickeau return false; 27721913ab3SNickeau } 27821913ab3SNickeau 27921913ab3SNickeau /** 28037748cd8SNickeau * Update the index for the move plugin 28137748cd8SNickeau * and {@link Page::FIRST_IMAGE_META_RELATION} 28237748cd8SNickeau * 28321913ab3SNickeau * @param array $attributes 28421913ab3SNickeau * @param Doku_Renderer_metadata $renderer 28521913ab3SNickeau */ 28621913ab3SNickeau static public function registerImageMeta($attributes, $renderer) 28721913ab3SNickeau { 288531e725cSNickeau $type = $attributes[MediaLink::MEDIA_DOKUWIKI_TYPE]; 28921913ab3SNickeau $src = $attributes['src']; 290531e725cSNickeau if ($src == null) { 291531e725cSNickeau $src = $attributes[DokuPath::PATH_ATTRIBUTE]; 292531e725cSNickeau } 29321913ab3SNickeau $title = $attributes['title']; 29421913ab3SNickeau $align = $attributes['align']; 29521913ab3SNickeau $width = $attributes['width']; 29621913ab3SNickeau $height = $attributes['height']; 29721913ab3SNickeau $cache = $attributes['cache']; // Cache: https://www.dokuwiki.org/images#caching 29821913ab3SNickeau $linking = $attributes['linking']; 29923723136Sgerardnico 30023723136Sgerardnico switch ($type) { 301531e725cSNickeau case MediaLink::INTERNAL_MEDIA_CALL_NAME: 30221913ab3SNickeau $renderer->internalmedia($src, $title, $align, $width, $height, $cache, $linking); 30323723136Sgerardnico break; 304531e725cSNickeau case MediaLink::EXTERNAL_MEDIA_CALL_NAME: 30523723136Sgerardnico $renderer->externalmedia($src, $title, $align, $width, $height, $cache, $linking); 30623723136Sgerardnico break; 30723723136Sgerardnico default: 30823723136Sgerardnico LogUtility::msg("The dokuwiki media type ($type) for metadata registration is unknown"); 30923723136Sgerardnico break; 31023723136Sgerardnico } 31123723136Sgerardnico 31221913ab3SNickeau } 31321913ab3SNickeau 31421913ab3SNickeau 31521913ab3SNickeau} 31621913ab3SNickeau 317