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