1<?php 2/** 3 * DokuWiki Plugin embeddedphp (Syntax Component) 4 * 5 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 6 * @author fiwswe <dwplugin@fwml.de> 7 */ 8 9class syntax_plugin_embeddedphp_phpinline extends \dokuwiki\Extension\SyntaxPlugin 10{ 11 /** 12 * Return the tag this plugin instance reacts to 13 * 14 * @return string 15 */ 16 protected function GetTag(): string 17 { 18 return 'php'; 19 } 20 21 /** 22 * Return the exit pattern as we need this more than once 23 * 24 * @return string 25 */ 26 protected function GetExitPattern(): string 27 { 28 return '</'.$this->GetTag().'>'; 29 } 30 31 /** @inheritDoc */ 32 public function getType() 33 { 34 return 'protected'; 35 } 36 37 /** @inheritDoc */ 38 public function getSort() 39 { 40 // The default <php>/<PHP> handler up to "Igor" has priority 180. By setting a 41 // lower priority we override the built-in functionality. 42 return 179; 43 } 44 45 46 /* 47 * Return the plugin Lexer mode 48 * This works fine for most trivial cases. But some plugins 49 * may need to override this method. 50 * 51 * @return string 52 */ 53 protected function getPluginModeName(): string 54 { 55 $x = ['plugin', 56 $this->getPluginName(), 57 $this->getPluginComponent()]; // If component is empty it will be filtered later. 58 59 return implode('_', array_filter($x)); 60 } 61 62 /** @inheritDoc */ 63 public function connectTo($mode) 64 { 65 $p = '<'.$this->GetTag().'\b>(?=.*?'.$this->GetExitPattern().')'; 66 $m = $this->getPluginModeName(); 67 $this->Lexer->addEntryPattern($p, $mode, $m); 68 } 69 70 /** @inheritDoc */ 71 public function postConnect() 72 { 73 $m = $this->getPluginModeName(); 74 $this->Lexer->addExitPattern('.*?'.$this->GetExitPattern(), $m); 75 } 76 77 /** @inheritDoc */ 78 public function handle($match, $state, $pos, Doku_Handler $handler) 79 { 80 global $INPUT; 81 82 // If we are parsing a submitted comment. Executing embedded PHP in comments is 83 // not a good idea! 84 if ($INPUT->has('comment')) { 85 return false; 86 } 87 88 switch($state) { 89 case DOKU_LEXER_EXIT: 90 return [$state, substr($match, 0, -strlen($this->GetExitPattern()))]; 91 } 92 93 return false; 94 } 95 96 /** @inheritDoc */ 97 public function render($mode, Doku_Renderer $renderer, $data) 98 { 99 if ($mode === 'xhtml') { 100 if (is_array($data)) { 101 @[$state, $phpsource] = $data; 102 switch($state) { 103 case DOKU_LEXER_EXIT: 104 $this->php($phpsource, $renderer); 105 106 return true; 107 } 108 } 109 } 110 111 return false; 112 } 113 114 /** 115 * Determine whether embedding PHP code is allowed 116 * 117 * @return bool true if executing embedded PHP code is allowed 118 */ 119 protected function allowEmbedding(): bool 120 { 121 $allow = ($this->getConf('embedphpok') == 1) && 122 ($this->getConf('privatewiki') == 1); 123 124 return $allow; 125 } 126 127 /** 128 * Execute PHP code if allowed 129 * 130 * @param string $phpsource PHP code that is either executed or printed 131 * @param Doku_Renderer $renderer Renderer used for output 132 */ 133 protected function php($phpsource, Doku_Renderer $renderer): void 134 { 135 if ($this->allowEmbedding()) { 136 ob_start(); 137 eval($phpsource); 138 $o = ob_get_contents(); 139 if (!empty($o)) { 140 if ($this->isBlockElement()) { 141 $renderer->doc .= '<div class="embeddedphp">'.$o.'</div>'; 142 } else { 143 $renderer->doc .= '<span class="embeddedphp">'.$o.'</span>'; 144 } 145 } 146 ob_end_clean(); 147 } else { 148 $wrapper = $this->isBlockElement() ? 'pre' : 'code'; 149 $renderer->doc .= /*'###.get_class($this)'.*/p_xhtml_cached_geshi($phpsource, 'php', $wrapper); 150 } 151 } 152 153 /** 154 * Generic test to differentiate between inline and block modes 155 * 156 * @return bool true if this generates a block element, false otherwise. 157 */ 158 protected function isBlockElement(): bool 159 { 160 return false; 161 } 162} 163 164