xref: /plugin/combo/syntax/media.php (revision e8b2ff590c848541e718216df3a67061e98c1761)
121913ab3SNickeau<?php
221913ab3SNickeau
321913ab3SNickeau
4*e8b2ff59SNickeauuse ComboStrap\Analytics;
523723136Sgerardnicouse ComboStrap\DokuPath;
623723136Sgerardnicouse ComboStrap\LogUtility;
723723136Sgerardnicouse ComboStrap\MediaLink;
821913ab3SNickeauuse ComboStrap\PluginUtility;
921913ab3SNickeauuse ComboStrap\Tag;
1021913ab3SNickeau
1121913ab3SNickeau
1221913ab3SNickeauif (!defined('DOKU_INC')) die();
1321913ab3SNickeau
1421913ab3SNickeau
1521913ab3SNickeau/**
1623723136Sgerardnico * Media
1723723136Sgerardnico *
1823723136Sgerardnico * Takes over the {@link \dokuwiki\Parsing\ParserMode\Media media mode}
1923723136Sgerardnico * that is processed by {@link Doku_Handler_Parse_Media}
2023723136Sgerardnico *
2123723136Sgerardnico *
2223723136Sgerardnico *
2323723136Sgerardnico * It can be a internal / external media
2421913ab3SNickeau */
2521913ab3SNickeauclass syntax_plugin_combo_media extends DokuWiki_Syntax_Plugin
2621913ab3SNickeau{
2721913ab3SNickeau
2821913ab3SNickeau
2921913ab3SNickeau    const TAG = "media";
3021913ab3SNickeau
3121913ab3SNickeau    /**
3221913ab3SNickeau     * Used in the move plugin
3321913ab3SNickeau     * !!! The two last word of the plugin class !!!
3421913ab3SNickeau     */
3521913ab3SNickeau    const COMPONENT = 'combo_' . self::TAG;
3621913ab3SNickeau
3721913ab3SNickeau    /**
3821913ab3SNickeau     * The attribute that defines if the image is the first image in
3921913ab3SNickeau     * the component
4021913ab3SNickeau     *
4121913ab3SNickeau     */
4221913ab3SNickeau    const IS_FIRST_IMAGE_KEY = "isFirstImage";
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
5421913ab3SNickeau
5521913ab3SNickeau    function getType()
5621913ab3SNickeau    {
5721913ab3SNickeau        return 'formatting';
5821913ab3SNickeau    }
5921913ab3SNickeau
6021913ab3SNickeau    /**
6121913ab3SNickeau     * How Dokuwiki will add P element
6221913ab3SNickeau     *
6321913ab3SNickeau     *  * 'normal' - The plugin can be used inside paragraphs (inline)
6421913ab3SNickeau     *  * 'block'  - Open paragraphs need to be closed before plugin output - block should not be inside paragraphs
6521913ab3SNickeau     *  * 'stack'  - Special case. Plugin wraps other paragraphs. - Stacks can contain paragraphs
6621913ab3SNickeau     *
6721913ab3SNickeau     * @see DokuWiki_Syntax_Plugin::getPType()
6821913ab3SNickeau     */
6921913ab3SNickeau    function getPType()
7021913ab3SNickeau    {
7123723136Sgerardnico        /**
7223723136Sgerardnico         * An image is not a block (it can be inside paragraph)
7323723136Sgerardnico         */
7421913ab3SNickeau        return 'normal';
7521913ab3SNickeau    }
7621913ab3SNickeau
7721913ab3SNickeau    function getAllowedTypes()
7821913ab3SNickeau    {
7921913ab3SNickeau        return array('substition', 'formatting', 'disabled');
8021913ab3SNickeau    }
8121913ab3SNickeau
8223723136Sgerardnico    /**
8323723136Sgerardnico     * It should be less than {@link \dokuwiki\Parsing\ParserMode\Media::getSort()}
8423723136Sgerardnico     * (It was 320 at the time of writing this code)
8523723136Sgerardnico     * @return int
8623723136Sgerardnico     *
8723723136Sgerardnico     */
8821913ab3SNickeau    function getSort()
8921913ab3SNickeau    {
9023723136Sgerardnico        return 319;
9121913ab3SNickeau    }
9221913ab3SNickeau
9321913ab3SNickeau
9421913ab3SNickeau    function connectTo($mode)
9521913ab3SNickeau    {
96531e725cSNickeau        $enable = $this->getConf(self::CONF_IMAGE_ENABLE, 1);
9721913ab3SNickeau        if (!$enable) {
9821913ab3SNickeau
9921913ab3SNickeau            // Inside a card, we need to take over and enable it
10021913ab3SNickeau            $modes = [
1019337a630SNickeau                PluginUtility::getModeFromTag(syntax_plugin_combo_card::TAG),
10221913ab3SNickeau            ];
10321913ab3SNickeau            $enable = in_array($mode, $modes);
10421913ab3SNickeau        }
10521913ab3SNickeau
10621913ab3SNickeau        if ($enable) {
1079337a630SNickeau            $this->Lexer->addSpecialPattern(self::MEDIA_PATTERN, $mode, PluginUtility::getModeFromTag($this->getPluginComponent()));
10821913ab3SNickeau        }
10921913ab3SNickeau    }
11021913ab3SNickeau
11121913ab3SNickeau
11221913ab3SNickeau    function handle($match, $state, $pos, Doku_Handler $handler)
11321913ab3SNickeau    {
11421913ab3SNickeau
11521913ab3SNickeau        switch ($state) {
11621913ab3SNickeau
11721913ab3SNickeau
11821913ab3SNickeau            // As this is a container, this cannot happens but yeah, now, you know
11921913ab3SNickeau            case DOKU_LEXER_SPECIAL :
12023723136Sgerardnico                $media = MediaLink::createFromRenderMatch($match);
12121913ab3SNickeau                $attributes = $media->toCallStackArray();
12221913ab3SNickeau                $tag = new Tag(self::TAG, $attributes, $state, $handler);
12321913ab3SNickeau                $parent = $tag->getParent();
12421913ab3SNickeau                $parentTag = "";
12521913ab3SNickeau                if (!empty($parent)) {
12621913ab3SNickeau                    $parentTag = $parent->getName();
12721913ab3SNickeau                    if ($parentTag == syntax_plugin_combo_link::TAG) {
12821913ab3SNickeau                        /**
12921913ab3SNickeau                         * The image is in a link, we don't want another link
13021913ab3SNickeau                         * to the image
13121913ab3SNickeau                         */
132a6bf47aaSNickeau                        $attributes[MediaLink::LINKING_KEY] = MediaLink::LINKING_NOLINK_VALUE;
13321913ab3SNickeau                    }
13421913ab3SNickeau                }
13521913ab3SNickeau                $isFirstSibling = $tag->isFirstMeaningFullSibling();
13621913ab3SNickeau                return array(
13721913ab3SNickeau                    PluginUtility::STATE => $state,
13821913ab3SNickeau                    PluginUtility::ATTRIBUTES => $attributes,
13921913ab3SNickeau                    PluginUtility::CONTEXT => $parentTag,
14021913ab3SNickeau                    self::IS_FIRST_IMAGE_KEY => $isFirstSibling
14121913ab3SNickeau                );
14221913ab3SNickeau
14321913ab3SNickeau
14421913ab3SNickeau        }
14521913ab3SNickeau        return array();
14621913ab3SNickeau
14721913ab3SNickeau    }
14821913ab3SNickeau
14921913ab3SNickeau    /**
15021913ab3SNickeau     * Render the output
15121913ab3SNickeau     * @param string $format
15221913ab3SNickeau     * @param Doku_Renderer $renderer
15321913ab3SNickeau     * @param array $data - what the function handle() return'ed
15421913ab3SNickeau     * @return boolean - rendered correctly? (however, returned value is not used at the moment)
15521913ab3SNickeau     * @see DokuWiki_Syntax_Plugin::render()
15621913ab3SNickeau     *
15721913ab3SNickeau     *
15821913ab3SNickeau     */
15921913ab3SNickeau    function render($format, Doku_Renderer $renderer, $data)
16021913ab3SNickeau    {
16121913ab3SNickeau
16221913ab3SNickeau        $attributes = $data[PluginUtility::ATTRIBUTES];
16321913ab3SNickeau        switch ($format) {
16421913ab3SNickeau
16521913ab3SNickeau            case 'xhtml':
16621913ab3SNickeau
16721913ab3SNickeau                /** @var Doku_Renderer_xhtml $renderer */
16821913ab3SNickeau                $attributes = $data[PluginUtility::ATTRIBUTES];
16923723136Sgerardnico                $media = MediaLink::createFromCallStackArray($attributes);
17023723136Sgerardnico                if ($media->getScheme() == DokuPath::LOCAL_SCHEME) {
17123723136Sgerardnico                    $media = MediaLink::createFromCallStackArray($attributes, $renderer->date_at);
17221913ab3SNickeau                    if ($media->isImage()) {
1739337a630SNickeau                        /**
1749337a630SNickeau                         * We don't support crop
1759337a630SNickeau                         */
1769337a630SNickeau                        $crop = false;
1779337a630SNickeau                        if ($media->getRequestedWidth() != null && $media->getRequestedHeight() != null) {
1789337a630SNickeau                            /**
1799337a630SNickeau                             * Width of 0 = resizing by height (supported)
1809337a630SNickeau                             */
1819337a630SNickeau                            if ($media->getRequestedWidth() != "0") {
1829337a630SNickeau                                $crop = true;
1839337a630SNickeau                            }
1849337a630SNickeau                        }
1859337a630SNickeau                        if (!$crop) {
18621913ab3SNickeau                            $renderer->doc .= $media->renderMediaTagWithLink();
18723723136Sgerardnico                            return true;
18823723136Sgerardnico                        }
18923723136Sgerardnico                    }
1909337a630SNickeau                }
19121913ab3SNickeau
19221913ab3SNickeau                /**
19323723136Sgerardnico                 * This is not an local internal media image (a video or an url image)
19421913ab3SNickeau                 * Dokuwiki takes over
19521913ab3SNickeau                 */
196531e725cSNickeau                $type = $attributes[MediaLink::MEDIA_DOKUWIKI_TYPE];
19721913ab3SNickeau                $src = $attributes['src'];
19821913ab3SNickeau                $title = $attributes['title'];
19921913ab3SNickeau                $align = $attributes['align'];
20021913ab3SNickeau                $width = $attributes['width'];
20121913ab3SNickeau                $height = $attributes['height'];
20221913ab3SNickeau                $cache = $attributes['cache'];
203a6bf47aaSNickeau                if ($cache == null) {
204a6bf47aaSNickeau                    // Dokuwiki needs a value
205a6bf47aaSNickeau                    // If their is no value it will output it without any value
206a6bf47aaSNickeau                    // in the query string.
207a6bf47aaSNickeau                    $cache = "cache";
208a6bf47aaSNickeau                }
20921913ab3SNickeau                $linking = $attributes['linking'];
21023723136Sgerardnico                switch ($type) {
211531e725cSNickeau                    case MediaLink::INTERNAL_MEDIA_CALL_NAME:
21221913ab3SNickeau                        $renderer->doc .= $renderer->internalmedia($src, $title, $align, $width, $height, $cache, $linking, true);
21323723136Sgerardnico                        break;
214531e725cSNickeau                    case MediaLink::EXTERNAL_MEDIA_CALL_NAME:
21523723136Sgerardnico                        $renderer->doc .= $renderer->externalmedia($src, $title, $align, $width, $height, $cache, $linking, true);
21623723136Sgerardnico                        break;
21723723136Sgerardnico                    default:
21823723136Sgerardnico                        LogUtility::msg("The dokuwiki media type ($type) is unknown");
21923723136Sgerardnico                        break;
22021913ab3SNickeau                }
22121913ab3SNickeau
22223723136Sgerardnico                return true;
22321913ab3SNickeau
2249337a630SNickeau            case
2259337a630SNickeau            "metadata":
22621913ab3SNickeau
22721913ab3SNickeau                /**
22821913ab3SNickeau                 * Keep track of the metadata
22921913ab3SNickeau                 * @var Doku_Renderer_metadata $renderer
23021913ab3SNickeau                 */
23121913ab3SNickeau                self::registerImageMeta($attributes, $renderer);
23223723136Sgerardnico                return true;
23321913ab3SNickeau
234*e8b2ff59SNickeau            case renderer_plugin_combo_analytics::RENDERER_FORMAT:
235*e8b2ff59SNickeau
236*e8b2ff59SNickeau                /**
237*e8b2ff59SNickeau                 * Special pattern call
238*e8b2ff59SNickeau                 * @var renderer_plugin_combo_analytics $renderer
239*e8b2ff59SNickeau                 */
240*e8b2ff59SNickeau                $attributes = $data[PluginUtility::ATTRIBUTES];
241*e8b2ff59SNickeau                $media = MediaLink::createFromCallStackArray($attributes);
242*e8b2ff59SNickeau                $renderer->stats[Analytics::MEDIAS_COUNT]++;
243*e8b2ff59SNickeau                $scheme = $media->getScheme();
244*e8b2ff59SNickeau                switch($scheme){
245*e8b2ff59SNickeau                    case DokuPath::LOCAL_SCHEME:
246*e8b2ff59SNickeau                        $renderer->stats[Analytics::INTERNAL_MEDIAS_COUNT]++;
247*e8b2ff59SNickeau                        if(!$media->exists()){
248*e8b2ff59SNickeau                            $renderer->stats[Analytics::INTERNAL_BROKEN_MEDIAS_COUNT]++;
249*e8b2ff59SNickeau                        }
250*e8b2ff59SNickeau                        break;
251*e8b2ff59SNickeau                    case DokuPath::INTERNET_SCHEME:
252*e8b2ff59SNickeau                        $renderer->stats[Analytics::EXTERNAL_MEDIAS_COUNT]++;
253*e8b2ff59SNickeau                        break;
254*e8b2ff59SNickeau                }
255*e8b2ff59SNickeau                return true;
256*e8b2ff59SNickeau
25721913ab3SNickeau        }
25821913ab3SNickeau        // unsupported $mode
25921913ab3SNickeau        return false;
26021913ab3SNickeau    }
26121913ab3SNickeau
26221913ab3SNickeau    /**
26321913ab3SNickeau     * @param array $attributes
26421913ab3SNickeau     * @param Doku_Renderer_metadata $renderer
26521913ab3SNickeau     */
26621913ab3SNickeau    static public function registerImageMeta($attributes, $renderer)
26721913ab3SNickeau    {
268531e725cSNickeau        $type = $attributes[MediaLink::MEDIA_DOKUWIKI_TYPE];
26921913ab3SNickeau        $src = $attributes['src'];
270531e725cSNickeau        if ($src == null) {
271531e725cSNickeau            $src = $attributes[DokuPath::PATH_ATTRIBUTE];
272531e725cSNickeau        }
27321913ab3SNickeau        $title = $attributes['title'];
27421913ab3SNickeau        $align = $attributes['align'];
27521913ab3SNickeau        $width = $attributes['width'];
27621913ab3SNickeau        $height = $attributes['height'];
27721913ab3SNickeau        $cache = $attributes['cache']; // Cache: https://www.dokuwiki.org/images#caching
27821913ab3SNickeau        $linking = $attributes['linking'];
27923723136Sgerardnico
28023723136Sgerardnico        switch ($type) {
281531e725cSNickeau            case MediaLink::INTERNAL_MEDIA_CALL_NAME:
28221913ab3SNickeau                $renderer->internalmedia($src, $title, $align, $width, $height, $cache, $linking);
28323723136Sgerardnico                break;
284531e725cSNickeau            case MediaLink::EXTERNAL_MEDIA_CALL_NAME:
28523723136Sgerardnico                $renderer->externalmedia($src, $title, $align, $width, $height, $cache, $linking);
28623723136Sgerardnico                break;
28723723136Sgerardnico            default:
28823723136Sgerardnico                LogUtility::msg("The dokuwiki media type ($type)  for metadata registration is unknown");
28923723136Sgerardnico                break;
29023723136Sgerardnico        }
29123723136Sgerardnico
29221913ab3SNickeau    }
29321913ab3SNickeau
29421913ab3SNickeau
29521913ab3SNickeau}
29621913ab3SNickeau
297