12e6b7ea4Sfiwswe<?php 22e6b7ea4Sfiwswe/** 32e6b7ea4Sfiwswe * DokuWiki Plugin embeddedphp (Syntax Component) 42e6b7ea4Sfiwswe * 514c252b2Sfiwswe * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 62e6b7ea4Sfiwswe * @author fiwswe <dwplugin@fwml.de> 72e6b7ea4Sfiwswe */ 869545d01Sfiwswe 92e6b7ea4Sfiwsweclass syntax_plugin_embeddedphp_phpinline extends \dokuwiki\Extension\SyntaxPlugin 102e6b7ea4Sfiwswe{ 112e6b7ea4Sfiwswe /** 122e6b7ea4Sfiwswe * Return the tag this plugin instance reacts to 132e6b7ea4Sfiwswe * 142e6b7ea4Sfiwswe * @return string 152e6b7ea4Sfiwswe */ 1669545d01Sfiwswe protected function GetTag(): string 172e6b7ea4Sfiwswe { 182e6b7ea4Sfiwswe return 'php'; 192e6b7ea4Sfiwswe } 202e6b7ea4Sfiwswe 2181e4a891Sfiwswe /** 2281e4a891Sfiwswe * Return the exit pattern as we need this more than once 2381e4a891Sfiwswe * 2481e4a891Sfiwswe * @return string 2581e4a891Sfiwswe */ 2681e4a891Sfiwswe protected function GetExitPattern(): string 2781e4a891Sfiwswe { 2881e4a891Sfiwswe return '</'.$this->GetTag().'>'; 2981e4a891Sfiwswe } 3081e4a891Sfiwswe 312e6b7ea4Sfiwswe /** @inheritDoc */ 322e6b7ea4Sfiwswe public function getType() 332e6b7ea4Sfiwswe { 3469545d01Sfiwswe return 'protected'; 352e6b7ea4Sfiwswe } 362e6b7ea4Sfiwswe 372e6b7ea4Sfiwswe /** @inheritDoc */ 382e6b7ea4Sfiwswe public function getSort() 392e6b7ea4Sfiwswe { 402e6b7ea4Sfiwswe // The default <php>/<PHP> handler up to "Igor" has priority 180. By setting a 412e6b7ea4Sfiwswe // lower priority we override the built-in functionality. 422e6b7ea4Sfiwswe return 179; 432e6b7ea4Sfiwswe } 442e6b7ea4Sfiwswe 45144f9a0aSfiwswe 462e6b7ea4Sfiwswe /* 472e6b7ea4Sfiwswe * Return the plugin Lexer mode 48144f9a0aSfiwswe * This works fine for most trivial cases. But some plugins 49144f9a0aSfiwswe * may need to override this method. 502e6b7ea4Sfiwswe * 512e6b7ea4Sfiwswe * @return string 522e6b7ea4Sfiwswe */ 5369545d01Sfiwswe protected function getPluginModeName(): string 542e6b7ea4Sfiwswe { 55144f9a0aSfiwswe $x = ['plugin', 56144f9a0aSfiwswe $this->getPluginName(), 57144f9a0aSfiwswe $this->getPluginComponent()]; // If component is empty it will be filtered later. 58144f9a0aSfiwswe 59144f9a0aSfiwswe return implode('_', array_filter($x)); 602e6b7ea4Sfiwswe } 612e6b7ea4Sfiwswe 622e6b7ea4Sfiwswe /** @inheritDoc */ 632e6b7ea4Sfiwswe public function connectTo($mode) 642e6b7ea4Sfiwswe { 6581e4a891Sfiwswe $p = '<'.$this->GetTag().'\b>(?=.*?'.$this->GetExitPattern().')'; 662e6b7ea4Sfiwswe $m = $this->getPluginModeName(); 672e6b7ea4Sfiwswe $this->Lexer->addEntryPattern($p, $mode, $m); 682e6b7ea4Sfiwswe } 692e6b7ea4Sfiwswe 702e6b7ea4Sfiwswe /** @inheritDoc */ 712e6b7ea4Sfiwswe public function postConnect() 722e6b7ea4Sfiwswe { 732e6b7ea4Sfiwswe $m = $this->getPluginModeName(); 74*d3666e41Sfiwswe $this->Lexer->addExitPattern('.*?'.$this->GetExitPattern(), $m); 752e6b7ea4Sfiwswe } 762e6b7ea4Sfiwswe 772e6b7ea4Sfiwswe /** @inheritDoc */ 782e6b7ea4Sfiwswe public function handle($match, $state, $pos, Doku_Handler $handler) 792e6b7ea4Sfiwswe { 8069545d01Sfiwswe global $INPUT; 8169545d01Sfiwswe 822e6b7ea4Sfiwswe // If we are parsing a submitted comment. Executing embedded PHP in comments is 832e6b7ea4Sfiwswe // not a good idea! 8469545d01Sfiwswe if ($INPUT->has('comment')) { 852e6b7ea4Sfiwswe return false; 862e6b7ea4Sfiwswe } 872e6b7ea4Sfiwswe 882e6b7ea4Sfiwswe switch($state) { 89*d3666e41Sfiwswe case DOKU_LEXER_EXIT: 90*d3666e41Sfiwswe return [$state, substr($match, 0, -strlen($this->GetExitPattern()))]; 912e6b7ea4Sfiwswe } 922e6b7ea4Sfiwswe 932e6b7ea4Sfiwswe return false; 942e6b7ea4Sfiwswe } 952e6b7ea4Sfiwswe 962e6b7ea4Sfiwswe /** @inheritDoc */ 972e6b7ea4Sfiwswe public function render($mode, Doku_Renderer $renderer, $data) 982e6b7ea4Sfiwswe { 992e6b7ea4Sfiwswe if ($mode === 'xhtml') { 10041f0cbf0Sfiwswe if (is_array($data)) { 10141f0cbf0Sfiwswe @[$state, $phpsource] = $data; 102*d3666e41Sfiwswe switch($state) { 103*d3666e41Sfiwswe case DOKU_LEXER_EXIT: 10441f0cbf0Sfiwswe $this->php($phpsource, $renderer); 1052e6b7ea4Sfiwswe 1062e6b7ea4Sfiwswe return true; 1072e6b7ea4Sfiwswe } 1082e6b7ea4Sfiwswe } 109*d3666e41Sfiwswe } 1102e6b7ea4Sfiwswe 1112e6b7ea4Sfiwswe return false; 1122e6b7ea4Sfiwswe } 1132e6b7ea4Sfiwswe 1142e6b7ea4Sfiwswe /** 1152e6b7ea4Sfiwswe * Determine whether embedding PHP code is allowed 1162e6b7ea4Sfiwswe * 1172e6b7ea4Sfiwswe * @return bool true if executing embedded PHP code is allowed 1182e6b7ea4Sfiwswe */ 11969545d01Sfiwswe protected function allowEmbedding(): bool 1202e6b7ea4Sfiwswe { 1212e6b7ea4Sfiwswe $allow = ($this->getConf('embedphpok') == 1) && 1222e6b7ea4Sfiwswe ($this->getConf('privatewiki') == 1); 1232e6b7ea4Sfiwswe 1242e6b7ea4Sfiwswe return $allow; 1252e6b7ea4Sfiwswe } 1262e6b7ea4Sfiwswe 1272e6b7ea4Sfiwswe /** 1282e6b7ea4Sfiwswe * Execute PHP code if allowed 1292e6b7ea4Sfiwswe * 13041f0cbf0Sfiwswe * @param string $phpsource PHP code that is either executed or printed 1312e6b7ea4Sfiwswe * @param Doku_Renderer $renderer Renderer used for output 1322e6b7ea4Sfiwswe */ 13341f0cbf0Sfiwswe protected function php($phpsource, Doku_Renderer $renderer): void 13469545d01Sfiwswe { 1352e6b7ea4Sfiwswe if ($this->allowEmbedding()) { 1362e6b7ea4Sfiwswe ob_start(); 13741f0cbf0Sfiwswe eval($phpsource); 1382e6b7ea4Sfiwswe $o = ob_get_contents(); 1392e6b7ea4Sfiwswe if (!empty($o)) { 1402e6b7ea4Sfiwswe if ($this->isBlockElement()) { 1412e6b7ea4Sfiwswe $renderer->doc .= '<div class="embeddedphp">'.$o.'</div>'; 1422e6b7ea4Sfiwswe } else { 1432e6b7ea4Sfiwswe $renderer->doc .= '<span class="embeddedphp">'.$o.'</span>'; 1442e6b7ea4Sfiwswe } 1452e6b7ea4Sfiwswe } 1462e6b7ea4Sfiwswe ob_end_clean(); 1472e6b7ea4Sfiwswe } else { 14869545d01Sfiwswe $wrapper = $this->isBlockElement() ? 'pre' : 'code'; 14941f0cbf0Sfiwswe $renderer->doc .= /*'###.get_class($this)'.*/p_xhtml_cached_geshi($phpsource, 'php', $wrapper); 1502e6b7ea4Sfiwswe } 1512e6b7ea4Sfiwswe } 1522e6b7ea4Sfiwswe 1532e6b7ea4Sfiwswe /** 1542e6b7ea4Sfiwswe * Generic test to differentiate between inline and block modes 1552e6b7ea4Sfiwswe * 1562e6b7ea4Sfiwswe * @return bool true if this generates a block element, false otherwise. 1572e6b7ea4Sfiwswe */ 15869545d01Sfiwswe protected function isBlockElement(): bool 1592e6b7ea4Sfiwswe { 1602e6b7ea4Sfiwswe return false; 1612e6b7ea4Sfiwswe } 1622e6b7ea4Sfiwswe} 1632e6b7ea4Sfiwswe 164