xref: /plugin/embeddedphp/syntax/phpinline.php (revision d3666e41f8c4f409eb28c2f6cecc748440f90581)
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