137748cd8SNickeau<?php 237748cd8SNickeau 337748cd8SNickeau 437748cd8SNickeaunamespace ComboStrap; 537748cd8SNickeau 637748cd8SNickeau 704fd306cSNickeauuse ComboStrap\Api\ApiRouter; 837748cd8SNickeauuse dokuwiki\Extension\Plugin; 937748cd8SNickeauuse dokuwiki\Extension\SyntaxPlugin; 1037748cd8SNickeau 1137748cd8SNickeau 1237748cd8SNickeau/** 1337748cd8SNickeau * Class url static 1437748cd8SNickeau * List of static utilities 1537748cd8SNickeau */ 1637748cd8SNickeauclass PluginUtility 1737748cd8SNickeau{ 1837748cd8SNickeau 1937748cd8SNickeau const DOKU_DATA_DIR = '/dokudata/pages'; 2037748cd8SNickeau const DOKU_CACHE_DIR = '/dokudata/cache'; 2137748cd8SNickeau 2237748cd8SNickeau /** 2337748cd8SNickeau * Key in the data array between the handle and render function 2437748cd8SNickeau */ 2537748cd8SNickeau const STATE = "state"; 2637748cd8SNickeau const PAYLOAD = "payload"; // The html or text 2737748cd8SNickeau const ATTRIBUTES = "attributes"; 2837748cd8SNickeau// The context is generally the parent tag but it may be also the grandfather. 2937748cd8SNickeau// It permits to determine the HTML that is outputted 3037748cd8SNickeau const CONTEXT = 'context'; 3137748cd8SNickeau const TAG = "tag"; 3237748cd8SNickeau 3337748cd8SNickeau /** 3437748cd8SNickeau * The name of the hidden/private namespace 3537748cd8SNickeau * where the icon and other artifactory are stored 3637748cd8SNickeau */ 3737748cd8SNickeau const COMBOSTRAP_NAMESPACE_NAME = "combostrap"; 3837748cd8SNickeau 3937748cd8SNickeau const PARENT = "parent"; 4037748cd8SNickeau const POSITION = "position"; 4137748cd8SNickeau 4237748cd8SNickeau 4304fd306cSNickeau const EXIT_MESSAGE = "exit_message"; 444cadd4f8SNickeau const EXIT_CODE = "exit_code"; 4504fd306cSNickeau 461fa8c418SNickeau const DISPLAY = "display"; 4704fd306cSNickeau const MARKUP_TAG = "markup-tag"; 4804fd306cSNickeau 4937748cd8SNickeau 5037748cd8SNickeau /** 5137748cd8SNickeau * The URL base of the documentation 5237748cd8SNickeau */ 53c3437056SNickeau static $URL_APEX; 5437748cd8SNickeau 5537748cd8SNickeau 5637748cd8SNickeau /** 5737748cd8SNickeau * @var string - the plugin base name (ie the directory) 5837748cd8SNickeau * ie $INFO_PLUGIN['base']; 5937748cd8SNickeau * This is a constant because it permits code analytics 6037748cd8SNickeau * such as verification of a path 6137748cd8SNickeau */ 6237748cd8SNickeau const PLUGIN_BASE_NAME = "combo"; 6337748cd8SNickeau 6437748cd8SNickeau /** 6537748cd8SNickeau * The name of the template plugin 6637748cd8SNickeau */ 6737748cd8SNickeau const TEMPLATE_STRAP_NAME = "strap"; 6837748cd8SNickeau 6937748cd8SNickeau /** 7037748cd8SNickeau * @var array 7137748cd8SNickeau */ 7237748cd8SNickeau static $INFO_PLUGIN; 7337748cd8SNickeau 7437748cd8SNickeau static $PLUGIN_LANG; 7537748cd8SNickeau 7637748cd8SNickeau /** 7737748cd8SNickeau * The plugin name 7837748cd8SNickeau * (not the same than the base as it's not related to the directory 7937748cd8SNickeau * @var string 8037748cd8SNickeau */ 8137748cd8SNickeau public static $PLUGIN_NAME; 8237748cd8SNickeau /** 8304fd306cSNickeau * @var LocalPath 8437748cd8SNickeau */ 8504fd306cSNickeau private static $PLUGIN_INFO_FILE; 8637748cd8SNickeau 8737748cd8SNickeau 8837748cd8SNickeau /** 8937748cd8SNickeau * Initiate the static variable 9037748cd8SNickeau * See the call after this class 9137748cd8SNickeau */ 9237748cd8SNickeau static function init() 9337748cd8SNickeau { 9437748cd8SNickeau 9504fd306cSNickeau $pluginInfoFile = DirectoryLayout::getPluginInfoPath(); 9604fd306cSNickeau self::$INFO_PLUGIN = confToHash($pluginInfoFile->toAbsoluteId()); 9737748cd8SNickeau self::$PLUGIN_NAME = 'ComboStrap'; 9837748cd8SNickeau global $lang; 9937748cd8SNickeau self::$PLUGIN_LANG = $lang[self::PLUGIN_BASE_NAME]; 100c3437056SNickeau self::$URL_APEX = "https://" . parse_url(self::$INFO_PLUGIN['url'], PHP_URL_HOST); 10104fd306cSNickeau //self::$VERSION = self::$INFO_PLUGIN['version']; 10237748cd8SNickeau 10337748cd8SNickeau } 10437748cd8SNickeau 10537748cd8SNickeau /** 10637748cd8SNickeau * @param $inputExpression 10737748cd8SNickeau * @return false|int 1|0 10837748cd8SNickeau * returns: 10937748cd8SNickeau * - 1 if the input expression is a pattern, 11037748cd8SNickeau * - 0 if not, 11137748cd8SNickeau * - FALSE if an error occurred. 11237748cd8SNickeau */ 11337748cd8SNickeau static function isRegularExpression($inputExpression) 11437748cd8SNickeau { 11537748cd8SNickeau 11637748cd8SNickeau $regularExpressionPattern = "/(\\/.*\\/[gmixXsuUAJ]?)/"; 11737748cd8SNickeau return preg_match($regularExpressionPattern, $inputExpression); 11837748cd8SNickeau 11937748cd8SNickeau } 12037748cd8SNickeau 12137748cd8SNickeau /** 12237748cd8SNickeau * Return a mode from a tag (ie from a {@link Plugin::getPluginComponent()} 12337748cd8SNickeau * @param $tag 12437748cd8SNickeau * @return string 12537748cd8SNickeau * 12637748cd8SNickeau * A mode is just a name for a class 12737748cd8SNickeau * Example: $Parser->addMode('listblock',new Doku_Parser_Mode_ListBlock()); 12837748cd8SNickeau */ 12937748cd8SNickeau public static function getModeFromTag($tag) 13037748cd8SNickeau { 13137748cd8SNickeau return "plugin_" . self::getComponentName($tag); 13237748cd8SNickeau } 13337748cd8SNickeau 13437748cd8SNickeau 13537748cd8SNickeau /** 13637748cd8SNickeau * This pattern allows space after the tag name 13737748cd8SNickeau * for an end tag 13837748cd8SNickeau * As XHTML (https://www.w3.org/TR/REC-xml/#dt-etag) 13937748cd8SNickeau * @param $tag 14037748cd8SNickeau * @return string 14137748cd8SNickeau */ 14237748cd8SNickeau public static function getEndTagPattern($tag) 14337748cd8SNickeau { 14437748cd8SNickeau return "</$tag\s*>"; 14537748cd8SNickeau } 14637748cd8SNickeau 14737748cd8SNickeau /** 14837748cd8SNickeau * @param $tag 14937748cd8SNickeau * @return string 15037748cd8SNickeau * 15137748cd8SNickeau * Create a open tag pattern without lookahead. 152c3437056SNickeau * Used for 153c3437056SNickeau * @link https://dev.w3.org/html5/html-author/#void-elements-0 15437748cd8SNickeau */ 15537748cd8SNickeau public static function getVoidElementTagPattern($tag) 15637748cd8SNickeau { 15737748cd8SNickeau return ' < ' . $tag . ' .*?>'; 15837748cd8SNickeau } 15937748cd8SNickeau 16037748cd8SNickeau 16137748cd8SNickeau /** 16237748cd8SNickeau * Take an array where the key is the attribute name 16337748cd8SNickeau * and return a HTML tag string 16437748cd8SNickeau * 16537748cd8SNickeau * The attribute name and value are escaped 16637748cd8SNickeau * 16737748cd8SNickeau * @param $attributes - combo attributes 16837748cd8SNickeau * @return string 16937748cd8SNickeau * @deprecated to allowed background and other metadata, use {@link TagAttributes::toHtmlEnterTag()} 17037748cd8SNickeau */ 17137748cd8SNickeau public static function array2HTMLAttributesAsString($attributes) 17237748cd8SNickeau { 17337748cd8SNickeau 17437748cd8SNickeau $tagAttributes = TagAttributes::createFromCallStackArray($attributes); 17537748cd8SNickeau return $tagAttributes->toHTMLAttributeString(); 17637748cd8SNickeau 17737748cd8SNickeau } 17837748cd8SNickeau 17937748cd8SNickeau /** 18037748cd8SNickeau * 18137748cd8SNickeau * Parse the attributes part of a match 18237748cd8SNickeau * 18337748cd8SNickeau * Example: 18437748cd8SNickeau * line-numbers="value" 18537748cd8SNickeau * line-numbers='value' 18637748cd8SNickeau * 18737748cd8SNickeau * This value may be in: 18837748cd8SNickeau * * configuration value 18937748cd8SNickeau * * as well as in the match of a {@link SyntaxPlugin} 19037748cd8SNickeau * 19137748cd8SNickeau * @param $string 19237748cd8SNickeau * @return array 19337748cd8SNickeau * 19437748cd8SNickeau * To parse a match, use {@link PluginUtility::getTagAttributes()} 19537748cd8SNickeau * 19637748cd8SNickeau * 19737748cd8SNickeau */ 19837748cd8SNickeau public static function parseAttributes($string) 19937748cd8SNickeau { 20037748cd8SNickeau 20137748cd8SNickeau $parameters = array(); 20237748cd8SNickeau 20337748cd8SNickeau// Rules 20437748cd8SNickeau// * name may be alone (ie true boolean attribute) 20537748cd8SNickeau// * a name may get a `-` 20637748cd8SNickeau// * there may be space every everywhere when the value is enclosed with a quote 20737748cd8SNickeau// * there may be no space in the value and between the equal sign when the value is not enclosed 20837748cd8SNickeau// 20937748cd8SNickeau// /i not case sensitive 21037748cd8SNickeau $attributePattern = '\s*([-\w]+)\s*(?:=(\s*[\'"]([^`"]*)[\'"]\s*|[^\s]*))?'; 21137748cd8SNickeau $result = preg_match_all('/' . $attributePattern . '/i', $string, $matches); 21237748cd8SNickeau if ($result != 0) { 21337748cd8SNickeau foreach ($matches[1] as $key => $parameterKey) { 21437748cd8SNickeau 21537748cd8SNickeau// group 3 (ie the value between quotes) 21637748cd8SNickeau $value = $matches[3][$key]; 21737748cd8SNickeau if ($value == "") { 21837748cd8SNickeau// check the value without quotes 21937748cd8SNickeau $value = $matches[2][$key]; 22037748cd8SNickeau } 22137748cd8SNickeau// if there is no value, this is a boolean 22237748cd8SNickeau if ($value == "") { 22337748cd8SNickeau $value = true; 22437748cd8SNickeau } else { 22537748cd8SNickeau $value = hsc($value); 22637748cd8SNickeau } 22737748cd8SNickeau $parameters[hsc(strtolower($parameterKey))] = $value; 22837748cd8SNickeau } 22937748cd8SNickeau } 23037748cd8SNickeau return $parameters; 23137748cd8SNickeau 23237748cd8SNickeau } 23337748cd8SNickeau 23404fd306cSNickeau public static function getTagAttributes(string $match, array $knownTypes = [], bool $allowFirstBooleanAttributesAsType = false): array 23537748cd8SNickeau { 23604fd306cSNickeau return self::getQualifiedTagAttributes($match, false, "", $knownTypes, $allowFirstBooleanAttributesAsType); 23737748cd8SNickeau } 23837748cd8SNickeau 23937748cd8SNickeau /** 24037748cd8SNickeau * Return the attribute of a tag 24137748cd8SNickeau * Because they are users input, they are all escaped 24237748cd8SNickeau * @param $match 24337748cd8SNickeau * @param $hasThirdValue - if true, the third parameter is treated as value, not a property and returned in the `third` key 24437748cd8SNickeau * use for the code/file/console where they accept a name as third value 24537748cd8SNickeau * @param $keyThirdArgument - if a third argument is found, return it with this key 2464cadd4f8SNickeau * @param array|null $knownTypes 24704fd306cSNickeau * @param bool $allowFirstBooleanAttributesAsType 24837748cd8SNickeau * @return array 24937748cd8SNickeau */ 25004fd306cSNickeau public static function getQualifiedTagAttributes($match, $hasThirdValue, $keyThirdArgument, array $knownTypes = [], bool $allowFirstBooleanAttributesAsType = false): array 25137748cd8SNickeau { 25237748cd8SNickeau 25337748cd8SNickeau $match = PluginUtility::getPreprocessEnterTag($match); 25437748cd8SNickeau 25537748cd8SNickeau // Suppress the tag name (ie until the first blank) 25637748cd8SNickeau $spacePosition = strpos($match, " "); 25737748cd8SNickeau if (!$spacePosition) { 25837748cd8SNickeau // No space, meaning this is only the tag name 25937748cd8SNickeau return array(); 26037748cd8SNickeau } 26137748cd8SNickeau $match = trim(substr($match, $spacePosition)); 26237748cd8SNickeau if ($match == "") { 26337748cd8SNickeau return array(); 26437748cd8SNickeau } 26537748cd8SNickeau 26604fd306cSNickeau /** 26704fd306cSNickeau * Do we have a type as first argument ? 26804fd306cSNickeau */ 26937748cd8SNickeau $attributes = array(); 27037748cd8SNickeau $spacePosition = strpos($match, " "); 27137748cd8SNickeau if ($spacePosition) { 27237748cd8SNickeau $nextArgument = substr($match, 0, $spacePosition); 27337748cd8SNickeau } else { 27437748cd8SNickeau $nextArgument = $match; 27537748cd8SNickeau } 2764cadd4f8SNickeau 27704fd306cSNickeau $isBooleanAttribute = !strpos($nextArgument, "="); 2784cadd4f8SNickeau $isType = false; 27904fd306cSNickeau if ($isBooleanAttribute) { 28004fd306cSNickeau $possibleTypeLowercase = strtolower($nextArgument); 28104fd306cSNickeau if ($allowFirstBooleanAttributesAsType) { 28204fd306cSNickeau $isType = true; 28304fd306cSNickeau $nextArgument = $possibleTypeLowercase; 28404fd306cSNickeau } else { 28504fd306cSNickeau if (!empty($knownTypes) && in_array($possibleTypeLowercase, $knownTypes)) { 28604fd306cSNickeau $isType = true; 28704fd306cSNickeau $nextArgument = $possibleTypeLowercase; 28804fd306cSNickeau } 2894cadd4f8SNickeau } 2904cadd4f8SNickeau } 2914cadd4f8SNickeau if ($isType) { 2924cadd4f8SNickeau 29304fd306cSNickeau $attributes[TagAttributes::TYPE_KEY] = $nextArgument; 29404fd306cSNickeau /** 29504fd306cSNickeau * Suppress the type 29604fd306cSNickeau */ 29737748cd8SNickeau $match = substr($match, strlen($nextArgument)); 29837748cd8SNickeau $match = trim($match); 29937748cd8SNickeau 30004fd306cSNickeau /** 30104fd306cSNickeau * Do we have a value as first argument ? 30204fd306cSNickeau */ 30337748cd8SNickeau if (!empty($hasThirdValue)) { 30437748cd8SNickeau $spacePosition = strpos($match, " "); 30537748cd8SNickeau if ($spacePosition) { 30637748cd8SNickeau $nextArgument = substr($match, 0, $spacePosition); 30737748cd8SNickeau } else { 30837748cd8SNickeau $nextArgument = $match; 30937748cd8SNickeau } 31037748cd8SNickeau if (!strpos($nextArgument, "=") && !empty($nextArgument)) { 31137748cd8SNickeau $attributes[$keyThirdArgument] = $nextArgument; 31204fd306cSNickeau /** 31304fd306cSNickeau * Suppress the third argument 31404fd306cSNickeau */ 31537748cd8SNickeau $match = substr($match, strlen($nextArgument)); 31637748cd8SNickeau $match = trim($match); 31737748cd8SNickeau } 31837748cd8SNickeau } 31937748cd8SNickeau } 32037748cd8SNickeau 32104fd306cSNickeau /** 32204fd306cSNickeau * Parse the remaining attributes 32304fd306cSNickeau */ 32437748cd8SNickeau $parsedAttributes = self::parseAttributes($match); 32537748cd8SNickeau 32604fd306cSNickeau /** 32704fd306cSNickeau * Merge 32804fd306cSNickeau */ 32937748cd8SNickeau $attributes = array_merge($attributes, $parsedAttributes);; 33037748cd8SNickeau 33137748cd8SNickeau return $attributes; 33237748cd8SNickeau 33337748cd8SNickeau } 33437748cd8SNickeau 33537748cd8SNickeau /** 33637748cd8SNickeau * @param $tag 33737748cd8SNickeau * @return string 33837748cd8SNickeau * Create a pattern used where the tag is not a container. 33937748cd8SNickeau * ie 34037748cd8SNickeau * <br/> 34104fd306cSNickeau * 34237748cd8SNickeau * <icon/> 34337748cd8SNickeau * This is generally used with a subtition plugin 34437748cd8SNickeau * and a {@link Lexer::addSpecialPattern} state 34537748cd8SNickeau * where the tag is just replaced 34637748cd8SNickeau */ 34719494974Sgerardnico public static function getEmptyTagPattern($tag): string 34837748cd8SNickeau { 34919494974Sgerardnico 3504cadd4f8SNickeau /** 3514cadd4f8SNickeau * A tag should start with the tag 3524cadd4f8SNickeau * `(?=[/ ]{1})` - a space or the / (lookahead) => to allow allow tag name with minus character 3534cadd4f8SNickeau * `(?![^/]>)` - it's not a normal tag (ie a > with the previous character that is not /) 3544cadd4f8SNickeau * `[^>]*` then until the > is found (dokuwiki capture greedy, don't use the point character) 3554cadd4f8SNickeau * then until the close `/>` character 3564cadd4f8SNickeau */ 3574cadd4f8SNickeau return '<' . $tag . '(?=[/ ]{1})(?![^/]>)[^>]*\/>'; 35837748cd8SNickeau } 35937748cd8SNickeau 36004fd306cSNickeau public static function getEmptyTagPatternGeneral(): string 36104fd306cSNickeau { 36204fd306cSNickeau 36304fd306cSNickeau return self::getEmptyTagPattern("[\w-]+"); 36404fd306cSNickeau } 36504fd306cSNickeau 36637748cd8SNickeau /** 36737748cd8SNickeau * Just call this function from a class like that 36837748cd8SNickeau * getTageName(get_called_class()) 36937748cd8SNickeau * to get the tag name (ie the component plugin) 37037748cd8SNickeau * of a syntax plugin 37137748cd8SNickeau * 37237748cd8SNickeau * @param $get_called_class 37337748cd8SNickeau * @return string 37437748cd8SNickeau */ 37537748cd8SNickeau public static function getTagName($get_called_class) 37637748cd8SNickeau { 37737748cd8SNickeau list(/* $t */, /* $p */, /* $n */, $c) = explode('_', $get_called_class, 4); 37837748cd8SNickeau return (isset($c) ? $c : ''); 37937748cd8SNickeau } 38037748cd8SNickeau 38137748cd8SNickeau /** 38237748cd8SNickeau * Just call this function from a class like that 38337748cd8SNickeau * getAdminPageName(get_called_class()) 38437748cd8SNickeau * to get the page name of a admin plugin 38537748cd8SNickeau * 38637748cd8SNickeau * @param $get_called_class 38737748cd8SNickeau * @return string - the admin page name 38837748cd8SNickeau */ 38937748cd8SNickeau public static function getAdminPageName($get_called_class) 39037748cd8SNickeau { 39137748cd8SNickeau $names = explode('_', $get_called_class); 39237748cd8SNickeau $names = array_slice($names, -2); 39337748cd8SNickeau return implode('_', $names); 39437748cd8SNickeau } 39537748cd8SNickeau 39637748cd8SNickeau public static function getNameSpace() 39737748cd8SNickeau { 39837748cd8SNickeau// No : at the begin of the namespace please 39937748cd8SNickeau return self::PLUGIN_BASE_NAME . ':'; 40037748cd8SNickeau } 40137748cd8SNickeau 40237748cd8SNickeau /** 40337748cd8SNickeau * @param $get_called_class - the plugin class 40437748cd8SNickeau * @return array 40537748cd8SNickeau */ 40637748cd8SNickeau public static function getTags($get_called_class) 40737748cd8SNickeau { 40837748cd8SNickeau $elements = array(); 40937748cd8SNickeau $elementName = PluginUtility::getTagName($get_called_class); 41037748cd8SNickeau $elements[] = $elementName; 41137748cd8SNickeau $elements[] = strtoupper($elementName); 41237748cd8SNickeau return $elements; 41337748cd8SNickeau } 41437748cd8SNickeau 41537748cd8SNickeau /** 41637748cd8SNickeau * Render a text 41737748cd8SNickeau * @param $pageContent 41837748cd8SNickeau * @return string|null 41937748cd8SNickeau */ 42004fd306cSNickeau public static function render($pageContent): ?string 42137748cd8SNickeau { 42204fd306cSNickeau return MarkupRenderUtility::renderText2XhtmlAndStripPEventually($pageContent, false); 42337748cd8SNickeau } 42437748cd8SNickeau 42537748cd8SNickeau 42637748cd8SNickeau /** 42737748cd8SNickeau * This method will takes attributes 42837748cd8SNickeau * and process the plugin styling attribute such as width and height 42937748cd8SNickeau * to put them in a style HTML attribute 43037748cd8SNickeau * @param TagAttributes $attributes 43137748cd8SNickeau */ 43237748cd8SNickeau public static function processStyle(&$attributes) 43337748cd8SNickeau { 43437748cd8SNickeau // Style 43537748cd8SNickeau $styleAttributeName = "style"; 43637748cd8SNickeau if ($attributes->hasComponentAttribute($styleAttributeName)) { 43737748cd8SNickeau $properties = explode(";", $attributes->getValueAndRemove($styleAttributeName)); 43837748cd8SNickeau foreach ($properties as $property) { 43937748cd8SNickeau list($key, $value) = explode(":", $property); 44037748cd8SNickeau if ($key != "") { 44182a60d03SNickeau $attributes->addStyleDeclarationIfNotSet($key, $value); 44237748cd8SNickeau } 44337748cd8SNickeau } 44437748cd8SNickeau } 44537748cd8SNickeau 44637748cd8SNickeau 44737748cd8SNickeau /** 44837748cd8SNickeau * Border Color 44937748cd8SNickeau * For background color, see {@link TagAttributes::processBackground()} 45037748cd8SNickeau * For text color, see {@link TextColor} 45137748cd8SNickeau */ 45237748cd8SNickeau 4534cadd4f8SNickeau if ($attributes->hasComponentAttribute(ColorRgb::BORDER_COLOR)) { 4544cadd4f8SNickeau $colorValue = $attributes->getValueAndRemove(ColorRgb::BORDER_COLOR); 4554cadd4f8SNickeau $attributes->addStyleDeclarationIfNotSet(ColorRgb::BORDER_COLOR, ColorRgb::createFromString($colorValue)->toCssValue()); 45637748cd8SNickeau self::checkDefaultBorderColorAttributes($attributes); 45737748cd8SNickeau } 45837748cd8SNickeau 45937748cd8SNickeau 46037748cd8SNickeau } 46137748cd8SNickeau 46237748cd8SNickeau /** 46337748cd8SNickeau * Return the name of the requested script 46437748cd8SNickeau */ 46537748cd8SNickeau public 46637748cd8SNickeau static function getRequestScript() 46737748cd8SNickeau { 46837748cd8SNickeau $scriptPath = null; 46937748cd8SNickeau $testPropertyValue = self::getPropertyValue("SCRIPT_NAME"); 47037748cd8SNickeau if (defined('DOKU_UNITTEST') && $testPropertyValue != null) { 47137748cd8SNickeau return $testPropertyValue; 47237748cd8SNickeau } 47337748cd8SNickeau if (array_key_exists("DOCUMENT_URI", $_SERVER)) { 47437748cd8SNickeau $scriptPath = $_SERVER["DOCUMENT_URI"]; 47537748cd8SNickeau } 47637748cd8SNickeau if ($scriptPath == null && array_key_exists("SCRIPT_NAME", $_SERVER)) { 47737748cd8SNickeau $scriptPath = $_SERVER["SCRIPT_NAME"]; 47837748cd8SNickeau } 47937748cd8SNickeau if ($scriptPath == null) { 48037748cd8SNickeau msg("Unable to find the main script", LogUtility::LVL_MSG_ERROR); 48137748cd8SNickeau } 48237748cd8SNickeau $path_parts = pathinfo($scriptPath); 48337748cd8SNickeau return $path_parts['basename']; 48437748cd8SNickeau } 48537748cd8SNickeau 48637748cd8SNickeau /** 48737748cd8SNickeau * 48837748cd8SNickeau * @param $name 48937748cd8SNickeau * @param $default 49037748cd8SNickeau * @return string - the value of a query string property or if in test mode, the value of a test variable 49137748cd8SNickeau * set with {@link self::setTestProperty} 49237748cd8SNickeau * This is used to test script that are not supported by the dokuwiki test framework 49337748cd8SNickeau * such as css.php 49404fd306cSNickeau * @deprecated use {@link ApiRouter::getRequestParameter()} 49537748cd8SNickeau */ 49637748cd8SNickeau public 49737748cd8SNickeau static function getPropertyValue($name, $default = null) 49837748cd8SNickeau { 49937748cd8SNickeau global $INPUT; 50037748cd8SNickeau $value = $INPUT->str($name); 50137748cd8SNickeau if ($value == null && defined('DOKU_UNITTEST')) { 50237748cd8SNickeau global $COMBO; 503*d9ddda89Sgerardnico if ($COMBO !== null) { 50437748cd8SNickeau $value = $COMBO[$name]; 50537748cd8SNickeau } 506*d9ddda89Sgerardnico } 50737748cd8SNickeau if ($value == null) { 50837748cd8SNickeau return $default; 50937748cd8SNickeau } else { 51037748cd8SNickeau return $value; 51137748cd8SNickeau } 51237748cd8SNickeau 51337748cd8SNickeau } 51437748cd8SNickeau 51537748cd8SNickeau /** 51637748cd8SNickeau * Create an URL to the documentation website 51737748cd8SNickeau * @param $canonical - canonical id or slug 518c3437056SNickeau * @param $label - the text of the link 51904fd306cSNickeau * @param bool $withIcon - used to break the recursion with the message in the {@link IconDownloader} 52037748cd8SNickeau * @return string - an url 52137748cd8SNickeau */ 52237748cd8SNickeau public 52304fd306cSNickeau static function getDocumentationHyperLink($canonical, $label, bool $withIcon = true, $tooltip = ""): string 52437748cd8SNickeau { 52537748cd8SNickeau 52637748cd8SNickeau $xhtmlIcon = ""; 52737748cd8SNickeau if ($withIcon) { 52837748cd8SNickeau 52904fd306cSNickeau $logoPath = WikiPath::createComboResource("images:logo.svg"); 5304cadd4f8SNickeau try { 53104fd306cSNickeau $fetchImage = FetcherSvg::createSvgFromPath($logoPath); 53204fd306cSNickeau $fetchImage->setRequestedType(FetcherSvg::ICON_TYPE) 53304fd306cSNickeau ->setRequestedWidth(20); 53404fd306cSNickeau $xhtmlIcon = SvgImageLink::createFromFetcher($fetchImage) 53504fd306cSNickeau ->renderMediaTag(); 53604fd306cSNickeau } catch (ExceptionCompile $e) { 53704fd306cSNickeau /** 53804fd306cSNickeau * We don't throw because this function 53904fd306cSNickeau * is also used by: 54004fd306cSNickeau * * the log functionality to show link to the documentation creating a loop 54104fd306cSNickeau * * inside the configuration description crashing the page 54204fd306cSNickeau */ 54304fd306cSNickeau if (PluginUtility::isDevOrTest()) { 54404fd306cSNickeau// shows errors in the html only on dev/test 54504fd306cSNickeau $xhtmlIcon = "Error: {$e->getMessage()}"; 54637748cd8SNickeau } 5474cadd4f8SNickeau } 54837748cd8SNickeau 54937748cd8SNickeau } 550c3437056SNickeau $urlApex = self::$URL_APEX; 551c3437056SNickeau $path = str_replace(":", "/", $canonical); 552c3437056SNickeau if (empty($tooltip)) { 553c3437056SNickeau $title = $label; 554c3437056SNickeau } else { 555c3437056SNickeau $title = $tooltip; 556c3437056SNickeau } 557c3437056SNickeau $htmlToolTip = ""; 558c3437056SNickeau if (!empty($tooltip)) { 559c3437056SNickeau $dataAttributeNamespace = Bootstrap::getDataNamespace(); 560c3437056SNickeau $htmlToolTip = "data{$dataAttributeNamespace}-toggle=\"tooltip\""; 561c3437056SNickeau } 562c3437056SNickeau return "$xhtmlIcon<a href=\"$urlApex/$path\" title=\"$title\" $htmlToolTip style=\"text-decoration:none;\">$label</a>"; 56337748cd8SNickeau } 56437748cd8SNickeau 56537748cd8SNickeau /** 56637748cd8SNickeau * An utility function to not search every time which array should be first 56737748cd8SNickeau * @param array $inlineAttributes - the component inline attributes 56837748cd8SNickeau * @param array $defaultAttributes - the default configuration attributes 56937748cd8SNickeau * @return array - a merged array 57037748cd8SNickeau */ 57137748cd8SNickeau public 57237748cd8SNickeau static function mergeAttributes(array $inlineAttributes, array $defaultAttributes = array()) 57337748cd8SNickeau { 57437748cd8SNickeau return array_merge($defaultAttributes, $inlineAttributes); 57537748cd8SNickeau } 57637748cd8SNickeau 57737748cd8SNickeau /** 57837748cd8SNickeau * A pattern for a container tag 57937748cd8SNickeau * that needs to catch the content 58037748cd8SNickeau * 58137748cd8SNickeau * Use as a special pattern (substition) 58237748cd8SNickeau * 58337748cd8SNickeau * The {@link \syntax_plugin_combo_math} use it 58437748cd8SNickeau * @param $tag 58537748cd8SNickeau * @return string - a pattern 58637748cd8SNickeau */ 58737748cd8SNickeau public 58837748cd8SNickeau static function getLeafContainerTagPattern($tag) 58937748cd8SNickeau { 59037748cd8SNickeau return '<' . $tag . '.*?>.*?<\/' . $tag . '>'; 59137748cd8SNickeau } 59237748cd8SNickeau 59337748cd8SNickeau /** 59437748cd8SNickeau * Return the content of a tag 59504fd306cSNickeau * 59637748cd8SNickeau * <math>Content</math> 59737748cd8SNickeau * @param $match 59837748cd8SNickeau * @return string the content 59937748cd8SNickeau */ 60037748cd8SNickeau public 60137748cd8SNickeau static function getTagContent($match) 60237748cd8SNickeau { 60337748cd8SNickeau// From the first > 60437748cd8SNickeau $start = strpos($match, ">"); 60537748cd8SNickeau if ($start == false) { 60637748cd8SNickeau LogUtility::msg("The match does not contain any opening tag. Match: {$match}", LogUtility::LVL_MSG_ERROR); 60737748cd8SNickeau return ""; 60837748cd8SNickeau } 60937748cd8SNickeau $match = substr($match, $start + 1); 61037748cd8SNickeau// If this is the last character, we get a false 61137748cd8SNickeau if ($match == false) { 61237748cd8SNickeau LogUtility::msg("The match does not contain any closing tag. Match: {$match}", LogUtility::LVL_MSG_ERROR); 61337748cd8SNickeau return ""; 61437748cd8SNickeau } 61537748cd8SNickeau 61637748cd8SNickeau $end = strrpos($match, "</"); 61737748cd8SNickeau if ($end == false) { 61837748cd8SNickeau LogUtility::msg("The match does not contain any closing tag. Match: {$match}", LogUtility::LVL_MSG_ERROR); 61937748cd8SNickeau return ""; 62037748cd8SNickeau } 62137748cd8SNickeau 62237748cd8SNickeau return substr($match, 0, $end); 62337748cd8SNickeau } 62437748cd8SNickeau 62537748cd8SNickeau /** 62637748cd8SNickeau * 62737748cd8SNickeau * Check if a HTML tag was already added for a request 62837748cd8SNickeau * The request id is just the timestamp 62937748cd8SNickeau * An indicator array should be provided 63037748cd8SNickeau * @return string 63137748cd8SNickeau */ 63237748cd8SNickeau public 63337748cd8SNickeau static function getRequestId() 63437748cd8SNickeau { 63537748cd8SNickeau 63637748cd8SNickeau if (isset($_SERVER['REQUEST_TIME_FLOAT'])) { 63737748cd8SNickeau// since php 5.4 63837748cd8SNickeau $requestTime = $_SERVER['REQUEST_TIME_FLOAT']; 63937748cd8SNickeau } else { 64037748cd8SNickeau// DokuWiki test framework use this 64137748cd8SNickeau $requestTime = $_SERVER['REQUEST_TIME']; 64237748cd8SNickeau } 64337748cd8SNickeau $keyPrefix = 'combo_'; 64437748cd8SNickeau 64537748cd8SNickeau global $ID; 64637748cd8SNickeau return $keyPrefix . hash('crc32b', $_SERVER['REMOTE_ADDR'] . $_SERVER['REMOTE_PORT'] . $requestTime . $ID); 64737748cd8SNickeau 64837748cd8SNickeau } 64937748cd8SNickeau 65037748cd8SNickeau /** 6514cadd4f8SNickeau * 65204fd306cSNickeau * Return the requested wiki id (known also as page id) 6534cadd4f8SNickeau * 65404fd306cSNickeau * If the code is rendering a sidebar, it will not return the id of the sidebar 65504fd306cSNickeau * but the requested wiki id 6564cadd4f8SNickeau * 65737748cd8SNickeau * @return string 65804fd306cSNickeau * @throws ExceptionNotFound 65904fd306cSNickeau * @deprecated use {@link ExecutionContext::getRequestedPath()} 66037748cd8SNickeau */ 66104fd306cSNickeau public static function getRequestedWikiId(): string 66237748cd8SNickeau { 66304fd306cSNickeau 66404fd306cSNickeau return ExecutionContext::getActualOrCreateFromEnv()->getRequestedPath()->getWikiId(); 6654cadd4f8SNickeau 66637748cd8SNickeau } 66737748cd8SNickeau 66804fd306cSNickeau public static function xmlEncode($text) 669c3437056SNickeau { 670c3437056SNickeau /** 671c3437056SNickeau * {@link htmlentities } 672c3437056SNickeau */ 673c3437056SNickeau return htmlentities($text, ENT_XML1); 674c3437056SNickeau } 675c3437056SNickeau 67637748cd8SNickeau 67737748cd8SNickeau /** 67837748cd8SNickeau * Add a class 67937748cd8SNickeau * @param $classValue 68037748cd8SNickeau * @param array $attributes 68137748cd8SNickeau */ 68237748cd8SNickeau public 68337748cd8SNickeau static function addClass2Attributes($classValue, array &$attributes) 68437748cd8SNickeau { 68537748cd8SNickeau self::addAttributeValue("class", $classValue, $attributes); 68637748cd8SNickeau } 68737748cd8SNickeau 68837748cd8SNickeau /** 68937748cd8SNickeau * Add a style property to the attributes 69037748cd8SNickeau * @param $property 69137748cd8SNickeau * @param $value 69237748cd8SNickeau * @param array $attributes 69382a60d03SNickeau * @deprecated use {@link TagAttributes::addStyleDeclarationIfNotSet()} instead 69437748cd8SNickeau */ 69537748cd8SNickeau public 69637748cd8SNickeau static function addStyleProperty($property, $value, array &$attributes) 69737748cd8SNickeau { 69837748cd8SNickeau if (isset($attributes["style"])) { 69937748cd8SNickeau $attributes["style"] .= ";$property:$value"; 70037748cd8SNickeau } else { 70137748cd8SNickeau $attributes["style"] = "$property:$value"; 70237748cd8SNickeau } 70337748cd8SNickeau 70437748cd8SNickeau } 70537748cd8SNickeau 70637748cd8SNickeau /** 70737748cd8SNickeau * Add default border attributes 70837748cd8SNickeau * to see a border 70937748cd8SNickeau * Doc 71037748cd8SNickeau * https://combostrap.com/styling/color#border_color 71137748cd8SNickeau * @param TagAttributes $tagAttributes 71237748cd8SNickeau */ 71337748cd8SNickeau private 71437748cd8SNickeau static function checkDefaultBorderColorAttributes(&$tagAttributes) 71537748cd8SNickeau { 71637748cd8SNickeau /** 71737748cd8SNickeau * border color was set without the width 71837748cd8SNickeau * setting the width 71937748cd8SNickeau */ 72037748cd8SNickeau if (!( 72137748cd8SNickeau $tagAttributes->hasStyleDeclaration("border") 72237748cd8SNickeau || 72337748cd8SNickeau $tagAttributes->hasStyleDeclaration("border-width") 72437748cd8SNickeau ) 72537748cd8SNickeau ) { 72682a60d03SNickeau $tagAttributes->addStyleDeclarationIfNotSet("border-width", "1px"); 72737748cd8SNickeau } 72837748cd8SNickeau /** 72937748cd8SNickeau * border color was set without the style 73037748cd8SNickeau * setting the style 73137748cd8SNickeau */ 73237748cd8SNickeau if (! 73337748cd8SNickeau ( 73437748cd8SNickeau $tagAttributes->hasStyleDeclaration("border") 73537748cd8SNickeau || 73637748cd8SNickeau $tagAttributes->hasStyleDeclaration("border-style") 73737748cd8SNickeau ) 73837748cd8SNickeau ) { 73982a60d03SNickeau $tagAttributes->addStyleDeclarationIfNotSet("border-style", "solid"); 74037748cd8SNickeau 74137748cd8SNickeau } 74237748cd8SNickeau if (!$tagAttributes->hasStyleDeclaration("border-radius")) { 74382a60d03SNickeau $tagAttributes->addStyleDeclarationIfNotSet("border-radius", ".25rem"); 74437748cd8SNickeau } 74537748cd8SNickeau 74637748cd8SNickeau } 74737748cd8SNickeau 74837748cd8SNickeau /** 74937748cd8SNickeau * @param $match 75037748cd8SNickeau * @return null|string - return the tag name or null if not found 75137748cd8SNickeau */ 75237748cd8SNickeau public 75304fd306cSNickeau static function getMarkupTag($match): ?string 75437748cd8SNickeau { 75537748cd8SNickeau 75637748cd8SNickeau // Until the first > 75737748cd8SNickeau $pos = strpos($match, ">"); 75804fd306cSNickeau if (!$pos) { 75937748cd8SNickeau LogUtility::msg("The match does not contain any tag. Match: {$match}", LogUtility::LVL_MSG_ERROR); 76037748cd8SNickeau return null; 76137748cd8SNickeau } 76237748cd8SNickeau $match = substr($match, 0, $pos); 76337748cd8SNickeau 76404fd306cSNickeau // if this is a empty tag with / at the end we delete it 76504fd306cSNickeau if ($match[strlen($match) - 1] == "/") { 76604fd306cSNickeau $match = substr($match, 0, -1); 76704fd306cSNickeau } 76804fd306cSNickeau 76937748cd8SNickeau // Suppress the < 77037748cd8SNickeau if ($match[0] == "<") { 77137748cd8SNickeau $match = substr($match, 1); 77204fd306cSNickeau // closing tag 77304fd306cSNickeau if ($match[0] == "/") { 77404fd306cSNickeau $match = substr($match, 1); 77504fd306cSNickeau } 77637748cd8SNickeau } else { 77737748cd8SNickeau LogUtility::msg("This is not a text tag because it does not start with the character `>`"); 77837748cd8SNickeau } 77937748cd8SNickeau 78037748cd8SNickeau // Suppress the tag name (ie until the first blank) 78137748cd8SNickeau $spacePosition = strpos($match, " "); 78237748cd8SNickeau if (!$spacePosition) { 78337748cd8SNickeau // No space, meaning this is only the tag name 78437748cd8SNickeau return $match; 78537748cd8SNickeau } else { 78637748cd8SNickeau return substr($match, 0, $spacePosition); 78737748cd8SNickeau } 78837748cd8SNickeau 78937748cd8SNickeau } 79037748cd8SNickeau 79137748cd8SNickeau 79237748cd8SNickeau public 79304fd306cSNickeau static function getComponentName($tag): string 79437748cd8SNickeau { 79537748cd8SNickeau return strtolower(PluginUtility::PLUGIN_BASE_NAME) . "_" . $tag; 79637748cd8SNickeau } 79737748cd8SNickeau 79837748cd8SNickeau public 79937748cd8SNickeau static function addAttributeValue($attribute, $value, array &$attributes) 80037748cd8SNickeau { 80137748cd8SNickeau if (array_key_exists($attribute, $attributes) && $attributes[$attribute] !== "") { 80237748cd8SNickeau $attributes[$attribute] .= " {$value}"; 80337748cd8SNickeau } else { 80437748cd8SNickeau $attributes[$attribute] = "{$value}"; 80537748cd8SNickeau } 80637748cd8SNickeau } 80737748cd8SNickeau 80837748cd8SNickeau /** 80937748cd8SNickeau * Plugin Utility is available to all plugin, 81037748cd8SNickeau * this is a convenient way to the the snippet manager 81104fd306cSNickeau * @return SnippetSystem 81237748cd8SNickeau */ 81337748cd8SNickeau public 81404fd306cSNickeau static function getSnippetManager(): SnippetSystem 81537748cd8SNickeau { 81604fd306cSNickeau return SnippetSystem::getFromContext(); 81737748cd8SNickeau } 81837748cd8SNickeau 819c3437056SNickeau 82037748cd8SNickeau /** 82137748cd8SNickeau * Function used in a render 82237748cd8SNickeau * @param $data - the data from {@link PluginUtility::handleAndReturnUnmatchedData()} 82337748cd8SNickeau * @return string 82404fd306cSNickeau * 82504fd306cSNickeau * 82637748cd8SNickeau */ 82737748cd8SNickeau public 8284cadd4f8SNickeau static function renderUnmatched($data): string 82937748cd8SNickeau { 83037748cd8SNickeau /** 83137748cd8SNickeau * Attributes 83237748cd8SNickeau */ 83304fd306cSNickeau $attributes = $data[PluginUtility::ATTRIBUTES] ?? []; 83437748cd8SNickeau $tagAttributes = TagAttributes::createFromCallStackArray($attributes); 83504fd306cSNickeau 83604fd306cSNickeau /** 83704fd306cSNickeau * Display 83804fd306cSNickeau */ 83904fd306cSNickeau $display = $tagAttributes->getValueAndRemoveIfPresent(Display::DISPLAY); 84004fd306cSNickeau if ($display === "none") { 84104fd306cSNickeau return ""; 84204fd306cSNickeau } 84304fd306cSNickeau 84437748cd8SNickeau $payload = $data[self::PAYLOAD]; 8451fa8c418SNickeau $previousTagDisplayType = $data[self::CONTEXT]; 8461fa8c418SNickeau if ($previousTagDisplayType !== Call::INLINE_DISPLAY) { 84704fd306cSNickeau // Delete the eol at the beginning and end 84804fd306cSNickeau // otherwise we get a big block 84937748cd8SNickeau $payload = ltrim($payload); 85037748cd8SNickeau } 85104fd306cSNickeau return Html::encode($payload); 85204fd306cSNickeau 85337748cd8SNickeau } 85437748cd8SNickeau 855c3437056SNickeau public 856c3437056SNickeau static function renderUnmatchedXml($data) 857c3437056SNickeau { 858c3437056SNickeau $payload = $data[self::PAYLOAD]; 859c3437056SNickeau $previousTagDisplayType = $data[self::CONTEXT]; 860c3437056SNickeau if ($previousTagDisplayType !== Call::INLINE_DISPLAY) { 861c3437056SNickeau $payload = ltrim($payload); 862c3437056SNickeau } 863c3437056SNickeau return PluginUtility::xmlEncode($payload); 864c3437056SNickeau 865c3437056SNickeau } 866c3437056SNickeau 86737748cd8SNickeau /** 86837748cd8SNickeau * Function used in a handle function of a syntax plugin for 86937748cd8SNickeau * unmatched context 87037748cd8SNickeau * @param $tagName 87137748cd8SNickeau * @param $match 87237748cd8SNickeau * @param \Doku_Handler $handler 87337748cd8SNickeau * @return array 87437748cd8SNickeau */ 87537748cd8SNickeau public 8761fa8c418SNickeau static function handleAndReturnUnmatchedData($tagName, $match, \Doku_Handler $handler): array 87737748cd8SNickeau { 8781fa8c418SNickeau $callStack = CallStack::createFromHandler($handler); 8791fa8c418SNickeau $sibling = $callStack->previous(); 88037748cd8SNickeau $context = null; 88137748cd8SNickeau if (!empty($sibling)) { 8821fa8c418SNickeau $context = $sibling->getDisplay(); 88337748cd8SNickeau } 88437748cd8SNickeau return array( 88537748cd8SNickeau PluginUtility::STATE => DOKU_LEXER_UNMATCHED, 88637748cd8SNickeau PluginUtility::PAYLOAD => $match, 88737748cd8SNickeau PluginUtility::CONTEXT => $context 88837748cd8SNickeau ); 88937748cd8SNickeau } 89037748cd8SNickeau 89137748cd8SNickeau /** 89237748cd8SNickeau * Utility methodPreprocess a start tag to be able to extract the name 89337748cd8SNickeau * and the attributes easily 89437748cd8SNickeau * 89537748cd8SNickeau * It will delete: 89637748cd8SNickeau * * the characters <> and the /> if present 89737748cd8SNickeau * * and trim 89837748cd8SNickeau * 89937748cd8SNickeau * It will remain the tagname and its attributes 90037748cd8SNickeau * @param $match 90137748cd8SNickeau * @return false|string|null 90237748cd8SNickeau */ 90337748cd8SNickeau private 90437748cd8SNickeau static function getPreprocessEnterTag($match) 90537748cd8SNickeau { 90637748cd8SNickeau// Until the first > 90737748cd8SNickeau $pos = strpos($match, ">"); 90804fd306cSNickeau if (!$pos) { 90937748cd8SNickeau LogUtility::msg("The match does not contain any tag. Match: {$match}", LogUtility::LVL_MSG_WARNING); 91037748cd8SNickeau return null; 91137748cd8SNickeau } 91237748cd8SNickeau $match = substr($match, 0, $pos); 91337748cd8SNickeau 91437748cd8SNickeau 91537748cd8SNickeau// Trim to start clean 91637748cd8SNickeau $match = trim($match); 91737748cd8SNickeau 91837748cd8SNickeau// Suppress the < 91937748cd8SNickeau if ($match[0] == "<") { 92037748cd8SNickeau $match = substr($match, 1); 92137748cd8SNickeau } 92237748cd8SNickeau 92337748cd8SNickeau// Suppress the / for a leaf tag 92437748cd8SNickeau if ($match[strlen($match) - 1] == "/") { 92537748cd8SNickeau $match = substr($match, 0, strlen($match) - 1); 92637748cd8SNickeau } 92737748cd8SNickeau return $match; 92837748cd8SNickeau } 92937748cd8SNickeau 93037748cd8SNickeau /** 93137748cd8SNickeau * Retrieve the tag name used in the text document 93237748cd8SNickeau * @param $match 93337748cd8SNickeau * @return false|string|null 93437748cd8SNickeau */ 93537748cd8SNickeau public 93637748cd8SNickeau static function getSyntaxTagNameFromMatch($match) 93737748cd8SNickeau { 93837748cd8SNickeau $preprocessMatch = PluginUtility::getPreprocessEnterTag($match); 93937748cd8SNickeau 94037748cd8SNickeau// Tag name (ie until the first blank) 94137748cd8SNickeau $spacePosition = strpos($match, " "); 94237748cd8SNickeau if (!$spacePosition) { 94337748cd8SNickeau// No space, meaning this is only the tag name 94437748cd8SNickeau return $preprocessMatch; 94537748cd8SNickeau } else { 94637748cd8SNickeau return trim(substr(0, $spacePosition)); 94737748cd8SNickeau } 94837748cd8SNickeau 94937748cd8SNickeau } 95037748cd8SNickeau 95137748cd8SNickeau /** 95237748cd8SNickeau * Add an enter call to the stack 95337748cd8SNickeau * @param \Doku_Handler $handler 95437748cd8SNickeau * @param $tagName 95537748cd8SNickeau * @param array $callStackArray 95637748cd8SNickeau */ 95737748cd8SNickeau public 95837748cd8SNickeau static function addEnterCall( 95937748cd8SNickeau \Doku_Handler &$handler, 96037748cd8SNickeau $tagName, 96137748cd8SNickeau $callStackArray = array() 96237748cd8SNickeau ) 96337748cd8SNickeau { 96437748cd8SNickeau $pluginName = PluginUtility::getComponentName($tagName); 96537748cd8SNickeau $handler->addPluginCall( 96637748cd8SNickeau $pluginName, 96737748cd8SNickeau $callStackArray, 96837748cd8SNickeau DOKU_LEXER_ENTER, 96937748cd8SNickeau null, 97037748cd8SNickeau null 97137748cd8SNickeau ); 97237748cd8SNickeau } 97337748cd8SNickeau 97404fd306cSNickeau /** 97504fd306cSNickeau * Add an end call dynamically 97604fd306cSNickeau * @param \Doku_Handler $handler 97704fd306cSNickeau * @param $tagName 97804fd306cSNickeau * @param array $callStackArray 97904fd306cSNickeau */ 98004fd306cSNickeau public 98104fd306cSNickeau static function addEndCall(\Doku_Handler $handler, $tagName, $callStackArray = array()) 98204fd306cSNickeau { 98304fd306cSNickeau $pluginName = PluginUtility::getComponentName($tagName); 98404fd306cSNickeau $handler->addPluginCall( 98504fd306cSNickeau $pluginName, 98604fd306cSNickeau $callStackArray, 98704fd306cSNickeau DOKU_LEXER_EXIT, 98804fd306cSNickeau null, 98904fd306cSNickeau null 99004fd306cSNickeau ); 99104fd306cSNickeau } 99237748cd8SNickeau 99337748cd8SNickeau /** 99437748cd8SNickeau * General Debug 99537748cd8SNickeau */ 99637748cd8SNickeau public 99737748cd8SNickeau static function isDebug() 99837748cd8SNickeau { 99937748cd8SNickeau global $conf; 100037748cd8SNickeau return $conf["allowdebug"] === 1; 100137748cd8SNickeau 100237748cd8SNickeau } 100337748cd8SNickeau 100437748cd8SNickeau 100537748cd8SNickeau /** 100637748cd8SNickeau * 100737748cd8SNickeau * See also dev.md file 100837748cd8SNickeau */ 100937748cd8SNickeau public static function isDevOrTest() 101037748cd8SNickeau { 101137748cd8SNickeau if (self::isDev()) { 101237748cd8SNickeau return true; 101337748cd8SNickeau } 101437748cd8SNickeau return self::isTest(); 101537748cd8SNickeau } 101637748cd8SNickeau 10174cadd4f8SNickeau /** 10184cadd4f8SNickeau * Is this a dev environment (ie laptop where the dev is working) 10194cadd4f8SNickeau * @return bool 10204cadd4f8SNickeau */ 10214cadd4f8SNickeau public static function isDev(): bool 102237748cd8SNickeau { 102337748cd8SNickeau global $_SERVER; 102437748cd8SNickeau if ($_SERVER["REMOTE_ADDR"] == "127.0.0.1") { 102537748cd8SNickeau return true; 102637748cd8SNickeau } 10274cadd4f8SNickeau if ($_SERVER["COMPUTERNAME"] === "NICO") { 10284cadd4f8SNickeau return true; 10294cadd4f8SNickeau } 103037748cd8SNickeau return false; 103137748cd8SNickeau } 103237748cd8SNickeau 103337748cd8SNickeau public static function getInstructions($markiCode) 103437748cd8SNickeau { 103537748cd8SNickeau return p_get_instructions($markiCode); 103637748cd8SNickeau } 103737748cd8SNickeau 103837748cd8SNickeau public static function getInstructionsWithoutRoot($markiCode) 103937748cd8SNickeau { 104004fd306cSNickeau return MarkupRenderUtility::getInstructionsAndStripPEventually($markiCode); 104137748cd8SNickeau } 104237748cd8SNickeau 104304fd306cSNickeau public static function isTest(): bool 104437748cd8SNickeau { 104537748cd8SNickeau return defined('DOKU_UNITTEST'); 104637748cd8SNickeau } 104737748cd8SNickeau 104837748cd8SNickeau 1049c3437056SNickeau public static function getCacheManager(): CacheManager 105037748cd8SNickeau { 105104fd306cSNickeau return CacheManager::getFromContextExecution(); 105237748cd8SNickeau } 105337748cd8SNickeau 105437748cd8SNickeau public static function getModeFromPluginName($name) 105537748cd8SNickeau { 105637748cd8SNickeau return "plugin_$name"; 105737748cd8SNickeau } 105837748cd8SNickeau 105937748cd8SNickeau public static function isCi(): bool 106037748cd8SNickeau { 106137748cd8SNickeau // https://docs.travis-ci.com/user/environment-variables/#default-environment-variables 106204fd306cSNickeau // https://docs.github.com/en/actions/learn-github-actions/variables#default-environment-variables 106337748cd8SNickeau return getenv("CI") === "true"; 106437748cd8SNickeau } 106537748cd8SNickeau 10664cadd4f8SNickeau 10674cadd4f8SNickeau /** 106804fd306cSNickeau * @throws ExceptionCompile 10694cadd4f8SNickeau */ 10704cadd4f8SNickeau public static function renderInstructionsToXhtml($callStackHeaderInstructions): ?string 10714cadd4f8SNickeau { 107204fd306cSNickeau return MarkupRenderUtility::renderInstructionsToXhtml($callStackHeaderInstructions); 10734cadd4f8SNickeau } 10744cadd4f8SNickeau 10754cadd4f8SNickeau /** 107604fd306cSNickeau * @deprecated for {@link ExecutionContext::getExecutingWikiId()} 10774cadd4f8SNickeau */ 107804fd306cSNickeau public static function getCurrentSlotId(): string 10794cadd4f8SNickeau { 108004fd306cSNickeau return ExecutionContext::getActualOrCreateFromEnv()->getExecutingWikiId(); 10814cadd4f8SNickeau } 10824cadd4f8SNickeau 108337748cd8SNickeau 108437748cd8SNickeau} 108537748cd8SNickeau 108637748cd8SNickeauPluginUtility::init(); 1087