xref: /plugin/combo/ComboStrap/MarkupDynamicRender.php (revision 04fd306c7c155fa133ebb3669986875d65988276)
1*04fd306cSNickeau<?php
2*04fd306cSNickeau
3*04fd306cSNickeaunamespace ComboStrap;
4*04fd306cSNickeau
5*04fd306cSNickeauuse Doku_Renderer;
6*04fd306cSNickeauuse PHPUnit\Exception;
7*04fd306cSNickeau
8*04fd306cSNickeau/**
9*04fd306cSNickeau *
10*04fd306cSNickeau * Adaptation of the function {@link p_render()}
11*04fd306cSNickeau * for dynamic rendering because the {@link \Doku_Renderer_xhtml Renderer} has also state
12*04fd306cSNickeau * such as the `counter_row` for the function {@link \Doku_Renderer_xhtml::table_open()}
13*04fd306cSNickeau *
14*04fd306cSNickeau * If {@link p_render()} is used multiple time, the renderer is recreated and the counter is reset to zero and the
15*04fd306cSNickeau * row of each table is lost.
16*04fd306cSNickeau *
17*04fd306cSNickeau */
18*04fd306cSNickeauclass MarkupDynamicRender
19*04fd306cSNickeau{
20*04fd306cSNickeau    /**
21*04fd306cSNickeau     * @var MarkupDynamicRender[]
22*04fd306cSNickeau     */
23*04fd306cSNickeau    static array $DYNAMIC_RENDERERS_CACHE = array();
24*04fd306cSNickeau
25*04fd306cSNickeau
26*04fd306cSNickeau    /**
27*04fd306cSNickeau     * @var string the format (xhtml, ...)
28*04fd306cSNickeau     */
29*04fd306cSNickeau    private string $format;
30*04fd306cSNickeau
31*04fd306cSNickeau
32*04fd306cSNickeau    /**
33*04fd306cSNickeau     * @var Doku_Renderer the renderer that calls the render function
34*04fd306cSNickeau     */
35*04fd306cSNickeau    private Doku_Renderer $renderer;
36*04fd306cSNickeau
37*04fd306cSNickeau    /**
38*04fd306cSNickeau     * @throws ExceptionNotFound
39*04fd306cSNickeau     */
40*04fd306cSNickeau    public function __construct($format)
41*04fd306cSNickeau    {
42*04fd306cSNickeau        $this->format = $format;
43*04fd306cSNickeau        $renderer = p_get_renderer($format);
44*04fd306cSNickeau        if (is_null($renderer)) {
45*04fd306cSNickeau            throw new ExceptionNotFound("No renderer was found for the format $format");
46*04fd306cSNickeau        }
47*04fd306cSNickeau
48*04fd306cSNickeau        $this->renderer = $renderer;
49*04fd306cSNickeau        $this->renderer->reset();
50*04fd306cSNickeau        $this->renderer->smileys = getSmileys();
51*04fd306cSNickeau        $this->renderer->entities = getEntities();
52*04fd306cSNickeau        $this->renderer->acronyms = getAcronyms();
53*04fd306cSNickeau        $this->renderer->interwiki = getInterwiki();
54*04fd306cSNickeau    }
55*04fd306cSNickeau
56*04fd306cSNickeau    /**
57*04fd306cSNickeau     * @throws ExceptionNotFound
58*04fd306cSNickeau     */
59*04fd306cSNickeau    public static function create($format): MarkupDynamicRender
60*04fd306cSNickeau    {
61*04fd306cSNickeau        /**
62*04fd306cSNickeau         * Don't create a static object
63*04fd306cSNickeau         * to preserve the build because
64*04fd306cSNickeau         * the instructions may also recursively render.
65*04fd306cSNickeau         *
66*04fd306cSNickeau         * Therefore, a small instructions rendering such as a tooltip
67*04fd306cSNickeau         * would take the actual rendering and close the previous.
68*04fd306cSNickeau         */
69*04fd306cSNickeau        return new MarkupDynamicRender($format);
70*04fd306cSNickeau    }
71*04fd306cSNickeau
72*04fd306cSNickeau    public static function createXhtml(): MarkupDynamicRender
73*04fd306cSNickeau    {
74*04fd306cSNickeau        try {
75*04fd306cSNickeau            return self::create("xhtml");
76*04fd306cSNickeau        } catch (ExceptionNotFound $e) {
77*04fd306cSNickeau            throw new ExceptionRuntimeInternal("xhtml should be available");
78*04fd306cSNickeau        }
79*04fd306cSNickeau    }
80*04fd306cSNickeau
81*04fd306cSNickeau    public function setDateAt($date_at)
82*04fd306cSNickeau    {
83*04fd306cSNickeau        if ($this->renderer instanceof \Doku_Renderer_xhtml) {
84*04fd306cSNickeau            $this->renderer->date_at = $date_at;
85*04fd306cSNickeau        }
86*04fd306cSNickeau
87*04fd306cSNickeau    }
88*04fd306cSNickeau
89*04fd306cSNickeau    /**
90*04fd306cSNickeau     * @throws ExceptionCompile
91*04fd306cSNickeau     * @throws ExceptionBadState
92*04fd306cSNickeau     */
93*04fd306cSNickeau    public function processInstructions($callStackHeaderInstructions): string
94*04fd306cSNickeau    {
95*04fd306cSNickeau
96*04fd306cSNickeau        try {
97*04fd306cSNickeau
98*04fd306cSNickeau            // Loop through the instructions
99*04fd306cSNickeau            foreach ($callStackHeaderInstructions as $instruction) {
100*04fd306cSNickeau                // Execute the callback against the Renderer
101*04fd306cSNickeau                if (method_exists($this->renderer, $instruction[0])) {
102*04fd306cSNickeau                    call_user_func_array(array(&$this->renderer, $instruction[0]), $instruction[1] ?: array());
103*04fd306cSNickeau                }
104*04fd306cSNickeau            }
105*04fd306cSNickeau
106*04fd306cSNickeau            // Post process
107*04fd306cSNickeau            // $data = array($this->format, & $this->renderer->doc);
108*04fd306cSNickeau            // \dokuwiki\Extension\Event::createAndTrigger('RENDERER_CONTENT_POSTPROCESS', $data);
109*04fd306cSNickeau
110*04fd306cSNickeau            return $this->renderer->doc;
111*04fd306cSNickeau
112*04fd306cSNickeau
113*04fd306cSNickeau        } /** @noinspection PhpRedundantCatchClauseInspection */ catch (Exception $e) {
114*04fd306cSNickeau            /**
115*04fd306cSNickeau             * Example of errors;
116*04fd306cSNickeau             * method_exists() expects parameter 2 to be string, array given
117*04fd306cSNickeau             * inc\parserutils.php:672
118*04fd306cSNickeau             */
119*04fd306cSNickeau            throw new ExceptionCompile("Error while rendering instructions. Error was: {$e->getMessage()}", "dynamic renderer", 1, $e);
120*04fd306cSNickeau        } finally {
121*04fd306cSNickeau            $this->renderer->reset();
122*04fd306cSNickeau        }
123*04fd306cSNickeau    }
124*04fd306cSNickeau
125*04fd306cSNickeau    public function __toString()
126*04fd306cSNickeau    {
127*04fd306cSNickeau        return "Dynamic $this->format renderer";
128*04fd306cSNickeau    }
129*04fd306cSNickeau
130*04fd306cSNickeau
131*04fd306cSNickeau}
132