137748cd8SNickeau<?php 237748cd8SNickeau 337748cd8SNickeau 437748cd8SNickeaunamespace ComboStrap; 537748cd8SNickeau 637748cd8SNickeau 737748cd8SNickeauuse dokuwiki\Extension\Plugin; 837748cd8SNickeauuse dokuwiki\Extension\SyntaxPlugin; 937748cd8SNickeau 1037748cd8SNickeaurequire_once(__DIR__ . '/../vendor/autoload.php'); 1137748cd8SNickeau 1237748cd8SNickeau/** 131fa8c418SNickeau * Parent in th hierarchy should be first 141fa8c418SNickeau * Ie before {@link ImageLink, SvgImageLink, RasterImageLink) 151fa8c418SNickeau */ 16*c3437056SNickeaurequire_once(__DIR__ . '/CachedDocument.php'); 17*c3437056SNickeaurequire_once(__DIR__ . '/PageCompilerDocument.php'); 18*c3437056SNickeaurequire_once(__DIR__ . '/OutputDocument.php'); 19*c3437056SNickeaurequire_once(__DIR__ . '/FileSystem.php'); 20*c3437056SNickeaurequire_once(__DIR__ . '/Path.php'); 21*c3437056SNickeaurequire_once(__DIR__ . '/PathAbs.php'); 22*c3437056SNickeaurequire_once(__DIR__ . '/File.php'); 23*c3437056SNickeaurequire_once(__DIR__ . '/DokuFs.php'); 241fa8c418SNickeaurequire_once(__DIR__ . '/DokuPath.php'); 25*c3437056SNickeaurequire_once(__DIR__ . '/ResourceCombo.php'); 26*c3437056SNickeaurequire_once(__DIR__ . '/ResourceComboAbs.php'); 271fa8c418SNickeaurequire_once(__DIR__ . '/Media.php'); 281fa8c418SNickeaurequire_once(__DIR__ . '/MediaLink.php'); 29*c3437056SNickeaurequire_once(__DIR__ . '/Metadata.php'); 30*c3437056SNickeaurequire_once(__DIR__ . '/MetadataBoolean.php'); 31*c3437056SNickeaurequire_once(__DIR__ . '/MetadataDateTime.php'); 32*c3437056SNickeaurequire_once(__DIR__ . '/MetadataMultiple.php'); 33*c3437056SNickeaurequire_once(__DIR__ . '/MetadataTabular.php'); 34*c3437056SNickeaurequire_once(__DIR__ . '/MetadataText.php'); 35*c3437056SNickeaurequire_once(__DIR__ . '/MetadataJson.php'); 36*c3437056SNickeaurequire_once(__DIR__ . '/MetadataWikiPath.php'); 37*c3437056SNickeaurequire_once(__DIR__ . '/MetadataStore.php'); 38*c3437056SNickeaurequire_once(__DIR__ . '/MetadataStoreAbs.php'); 39*c3437056SNickeaurequire_once(__DIR__ . '/MetadataSingleArrayStore.php'); 401fa8c418SNickeau 411fa8c418SNickeau/** 4237748cd8SNickeau * Plugin Utility is added in all Dokuwiki extension 4337748cd8SNickeau * and 4437748cd8SNickeau * all classes are added in plugin utility 4537748cd8SNickeau * 4637748cd8SNickeau * This is an utility master and the class loader 4737748cd8SNickeau * 4837748cd8SNickeau * If the load is relative, the load path is used 4937748cd8SNickeau * and the bad php file may be loaded 5037748cd8SNickeau * Furthermore, the absolute path helps 5137748cd8SNickeau * the IDE when refactoring 5237748cd8SNickeau */ 5337748cd8SNickeaurequire_once(__DIR__ . '/AdsUtility.php'); 54*c3437056SNickeaurequire_once(__DIR__ . '/Alias.php'); 55*c3437056SNickeaurequire_once(__DIR__ . '/AliasPath.php'); 56*c3437056SNickeaurequire_once(__DIR__ . '/AliasType.php'); 57*c3437056SNickeaurequire_once(__DIR__ . '/Aliases.php'); 5837748cd8SNickeaurequire_once(__DIR__ . '/Align.php'); 59*c3437056SNickeaurequire_once(__DIR__ . '/AnalyticsDocument.php'); 6037748cd8SNickeaurequire_once(__DIR__ . '/AnalyticsMenuItem.php'); 6137748cd8SNickeaurequire_once(__DIR__ . '/Animation.php'); 6237748cd8SNickeaurequire_once(__DIR__ . '/ArrayCaseInsensitive.php'); 6337748cd8SNickeaurequire_once(__DIR__ . '/ArrayUtility.php'); 6437748cd8SNickeaurequire_once(__DIR__ . '/Background.php'); 65*c3437056SNickeaurequire_once(__DIR__ . '/BacklinkCount.php'); 66*c3437056SNickeaurequire_once(__DIR__ . '/BacklinkMenuItem.php'); 6737748cd8SNickeaurequire_once(__DIR__ . '/Boldness.php'); 68*c3437056SNickeaurequire_once(__DIR__ . '/Boolean.php'); 6937748cd8SNickeaurequire_once(__DIR__ . '/Bootstrap.php'); 7037748cd8SNickeaurequire_once(__DIR__ . '/BreadcrumbHierarchical.php'); 71*c3437056SNickeaurequire_once(__DIR__ . '/CacheExpirationDate.php'); 72*c3437056SNickeaurequire_once(__DIR__ . '/CacheExpirationFrequency.php'); 7337748cd8SNickeaurequire_once(__DIR__ . '/CacheByLogicalKey.php'); 7437748cd8SNickeaurequire_once(__DIR__ . '/CacheInstructionsByLogicalKey.php'); 7537748cd8SNickeaurequire_once(__DIR__ . '/CacheManager.php'); 7637748cd8SNickeaurequire_once(__DIR__ . '/CacheMedia.php'); 7737748cd8SNickeaurequire_once(__DIR__ . '/Call.php'); 7837748cd8SNickeaurequire_once(__DIR__ . '/CallStack.php'); 79*c3437056SNickeaurequire_once(__DIR__ . '/Canonical.php'); 8037748cd8SNickeaurequire_once(__DIR__ . '/ColorUtility.php'); 8137748cd8SNickeaurequire_once(__DIR__ . '/ConditionalValue.php'); 82*c3437056SNickeaurequire_once(__DIR__ . '/Console.php'); 83*c3437056SNickeaurequire_once(__DIR__ . '/Cron.php'); 84*c3437056SNickeaurequire_once(__DIR__ . '/DatabasePageRow.php'); 85*c3437056SNickeaurequire_once(__DIR__ . '/DataType.php'); 8637748cd8SNickeaurequire_once(__DIR__ . '/Dimension.php'); 87*c3437056SNickeaurequire_once(__DIR__ . '/DisqusIdentifier.php'); 8837748cd8SNickeaurequire_once(__DIR__ . '/DokuwikiUrl.php'); 89*c3437056SNickeaurequire_once(__DIR__ . '/DokuwikiId.php'); 90*c3437056SNickeaurequire_once(__DIR__ . '/EndDate.php'); 91*c3437056SNickeaurequire_once(__DIR__ . '/Event.php'); 921fa8c418SNickeaurequire_once(__DIR__ . '/ExitException.php'); 93*c3437056SNickeaurequire_once(__DIR__ . '/ExceptionCombo.php'); 94*c3437056SNickeaurequire_once(__DIR__ . '/ExceptionComboRuntime.php'); 95*c3437056SNickeaurequire_once(__DIR__ . '/FileSystems.php'); 9637748cd8SNickeaurequire_once(__DIR__ . '/FloatAttribute.php'); 97*c3437056SNickeaurequire_once(__DIR__ . '/FormMeta.php'); 98*c3437056SNickeaurequire_once(__DIR__ . '/FormMetaTab.php'); 99*c3437056SNickeaurequire_once(__DIR__ . '/FormMetaField.php'); 10037748cd8SNickeaurequire_once(__DIR__ . '/FontSize.php'); 10137748cd8SNickeaurequire_once(__DIR__ . '/FsWikiUtility.php'); 10237748cd8SNickeaurequire_once(__DIR__ . '/HeaderUtility.php'); 103*c3437056SNickeaurequire_once(__DIR__ . '/HtmlDocument.php'); 10437748cd8SNickeaurequire_once(__DIR__ . '/HistoricalBreadcrumbMenuItem.php'); 10537748cd8SNickeaurequire_once(__DIR__ . '/Hover.php'); 106*c3437056SNickeaurequire_once(__DIR__ . '/Html.php'); 10737748cd8SNickeaurequire_once(__DIR__ . '/Http.php'); 108*c3437056SNickeaurequire_once(__DIR__ . '/HttpResponse.php'); 10937748cd8SNickeaurequire_once(__DIR__ . '/Icon.php'); 11037748cd8SNickeaurequire_once(__DIR__ . '/Identity.php'); 1111fa8c418SNickeaurequire_once(__DIR__ . '/Image.php'); 1121fa8c418SNickeaurequire_once(__DIR__ . '/ImageLink.php'); 1131fa8c418SNickeaurequire_once(__DIR__ . '/ImageRaster.php'); 1141fa8c418SNickeaurequire_once(__DIR__ . '/ImageSvg.php'); 115*c3437056SNickeaurequire_once(__DIR__ . '/Index.php'); 116*c3437056SNickeaurequire_once(__DIR__ . '/InstructionsDocument.php'); 117*c3437056SNickeaurequire_once(__DIR__ . '/InternetPath.php'); 118*c3437056SNickeaurequire_once(__DIR__ . '/InterWikiPath.php'); 11937748cd8SNickeaurequire_once(__DIR__ . '/Iso8601Date.php'); 1201fa8c418SNickeaurequire_once(__DIR__ . '/Json.php'); 121*c3437056SNickeaurequire_once(__DIR__ . '/JavascriptLibrary.php'); 12237748cd8SNickeaurequire_once(__DIR__ . '/Lang.php'); 123*c3437056SNickeaurequire_once(__DIR__ . '/LdJson.php'); 12437748cd8SNickeaurequire_once(__DIR__ . '/LineSpacing.php'); 125*c3437056SNickeaurequire_once(__DIR__ . '/Locale.php'); 126*c3437056SNickeaurequire_once(__DIR__ . '/LocalFs.php'); 127*c3437056SNickeaurequire_once(__DIR__ . '/LocalPath.php'); 1281fa8c418SNickeaurequire_once(__DIR__ . '/LogException.php'); 12937748cd8SNickeaurequire_once(__DIR__ . '/LogUtility.php'); 13037748cd8SNickeaurequire_once(__DIR__ . '/LowQualityPage.php'); 131*c3437056SNickeaurequire_once(__DIR__ . '/LowQualityPageOverwrite.php'); 132*c3437056SNickeaurequire_once(__DIR__ . '/LowQualityCalculatedIndicator.php'); 133*c3437056SNickeaurequire_once(__DIR__ . '/MetaManagerForm.php'); 134*c3437056SNickeaurequire_once(__DIR__ . '/MetaManagerMenuItem.php'); 135*c3437056SNickeaurequire_once(__DIR__ . '/MetadataDokuWikiStore.php'); 136*c3437056SNickeaurequire_once(__DIR__ . '/MetadataFormDataStore.php'); 137*c3437056SNickeaurequire_once(__DIR__ . '/MetadataFrontmatterStore.php'); 138*c3437056SNickeaurequire_once(__DIR__ . '/MetadataDbStore.php'); 139*c3437056SNickeaurequire_once(__DIR__ . '/MetadataStoreTransfer.php'); 1401fa8c418SNickeaurequire_once(__DIR__ . '/Message.php'); 1411fa8c418SNickeaurequire_once(__DIR__ . '/Mermaid.php'); 142*c3437056SNickeaurequire_once(__DIR__ . '/Mime.php'); 143*c3437056SNickeaurequire_once(__DIR__ . '/ModificationDate.php'); 14437748cd8SNickeaurequire_once(__DIR__ . '/NavBarUtility.php'); 14537748cd8SNickeaurequire_once(__DIR__ . '/Opacity.php'); 1461fa8c418SNickeaurequire_once(__DIR__ . '/Os.php'); 14737748cd8SNickeaurequire_once(__DIR__ . '/Page.php'); 148*c3437056SNickeaurequire_once(__DIR__ . '/PageDescription.php'); 149*c3437056SNickeaurequire_once(__DIR__ . '/PageId.php'); 150*c3437056SNickeaurequire_once(__DIR__ . '/PageKeywords.php'); 151*c3437056SNickeaurequire_once(__DIR__ . '/PageImages.php'); 152*c3437056SNickeaurequire_once(__DIR__ . '/PageImage.php'); 153*c3437056SNickeaurequire_once(__DIR__ . '/PageImagePath.php'); 154*c3437056SNickeaurequire_once(__DIR__ . '/PageImageUsage.php'); 155*c3437056SNickeaurequire_once(__DIR__ . '/PageLayout.php'); 156*c3437056SNickeaurequire_once(__DIR__ . '/PagePath.php'); 15737748cd8SNickeaurequire_once(__DIR__ . '/PageProtection.php'); 15837748cd8SNickeaurequire_once(__DIR__ . '/PageRules.php'); 159*c3437056SNickeaurequire_once(__DIR__ . '/PageScope.php'); 16037748cd8SNickeaurequire_once(__DIR__ . '/PageSql.php'); 16137748cd8SNickeaurequire_once(__DIR__ . '/PageSqlParser/PageSqlLexer.php'); 16237748cd8SNickeaurequire_once(__DIR__ . '/PageSqlParser/PageSqlParser.php'); 16337748cd8SNickeaurequire_once(__DIR__ . '/PageSqlTreeListener.php'); 164*c3437056SNickeaurequire_once(__DIR__ . '/PageType.php'); 165*c3437056SNickeaurequire_once(__DIR__ . '/PageTitle.php'); 166*c3437056SNickeaurequire_once(__DIR__ . '/PageUrlPath.php'); 167*c3437056SNickeaurequire_once(__DIR__ . '/PageUrlType.php'); 16837748cd8SNickeaurequire_once(__DIR__ . '/PipelineUtility.php'); 16937748cd8SNickeaurequire_once(__DIR__ . '/Position.php'); 17037748cd8SNickeaurequire_once(__DIR__ . '/Prism.php'); 171*c3437056SNickeaurequire_once(__DIR__ . '/PagePublicationDate.php'); 172*c3437056SNickeaurequire_once(__DIR__ . '/PageCreationDate.php'); 173*c3437056SNickeaurequire_once(__DIR__ . '/PageH1.php'); 174*c3437056SNickeaurequire_once(__DIR__ . '/QualityDynamicMonitoringOverwrite.php'); 175*c3437056SNickeaurequire_once(__DIR__ . '/QualityMenuItem.php'); 17637748cd8SNickeaurequire_once(__DIR__ . '/RasterImageLink.php'); 177*c3437056SNickeaurequire_once(__DIR__ . '/Region.php'); 17837748cd8SNickeaurequire_once(__DIR__ . '/RenderUtility.php'); 179*c3437056SNickeaurequire_once(__DIR__ . '/ReplicationDate.php'); 18037748cd8SNickeaurequire_once(__DIR__ . '/Resources.php'); 181*c3437056SNickeaurequire_once(__DIR__ . '/ResourceName.php'); 1821fa8c418SNickeaurequire_once(__DIR__ . '/Sanitizer.php'); 18337748cd8SNickeaurequire_once(__DIR__ . '/Shadow.php'); 18437748cd8SNickeaurequire_once(__DIR__ . '/Site.php'); 18537748cd8SNickeaurequire_once(__DIR__ . '/Skin.php'); 186*c3437056SNickeaurequire_once(__DIR__ . '/Slug.php'); 18737748cd8SNickeaurequire_once(__DIR__ . '/Snippet.php'); 18837748cd8SNickeaurequire_once(__DIR__ . '/SnippetManager.php'); 18937748cd8SNickeaurequire_once(__DIR__ . '/Spacing.php'); 19037748cd8SNickeaurequire_once(__DIR__ . '/Sqlite.php'); 191*c3437056SNickeaurequire_once(__DIR__ . '/SqliteRequest.php'); 192*c3437056SNickeaurequire_once(__DIR__ . '/SqliteResult.php'); 19337748cd8SNickeaurequire_once(__DIR__ . '/StringUtility.php'); 194*c3437056SNickeaurequire_once(__DIR__ . '/StartDate.php'); 19537748cd8SNickeaurequire_once(__DIR__ . '/StyleUtility.php'); 19637748cd8SNickeaurequire_once(__DIR__ . '/SvgDocument.php'); 19737748cd8SNickeaurequire_once(__DIR__ . '/SvgImageLink.php'); 19837748cd8SNickeaurequire_once(__DIR__ . '/Syntax.php'); 19937748cd8SNickeaurequire_once(__DIR__ . '/TableUtility.php'); 20037748cd8SNickeaurequire_once(__DIR__ . '/Tag.php'); 20137748cd8SNickeaurequire_once(__DIR__ . '/TagAttributes.php'); 20237748cd8SNickeaurequire_once(__DIR__ . '/Template.php'); 203*c3437056SNickeaurequire_once(__DIR__ . '/TemplateStore.php'); 20437748cd8SNickeaurequire_once(__DIR__ . '/TemplateUtility.php'); 20537748cd8SNickeaurequire_once(__DIR__ . '/TextAlign.php'); 20637748cd8SNickeaurequire_once(__DIR__ . '/TextColor.php'); 207*c3437056SNickeaurequire_once(__DIR__ . '/ThirdMedia.php'); 20837748cd8SNickeaurequire_once(__DIR__ . '/ThirdMediaLink.php'); 20937748cd8SNickeaurequire_once(__DIR__ . '/ThirdPartyPlugins.php'); 21037748cd8SNickeaurequire_once(__DIR__ . '/TocUtility.php'); 21137748cd8SNickeaurequire_once(__DIR__ . '/Toggle.php'); 212*c3437056SNickeaurequire_once(__DIR__ . '/References.php'); 213*c3437056SNickeaurequire_once(__DIR__ . '/Reference.php'); 21437748cd8SNickeaurequire_once(__DIR__ . '/Underline.php'); 21537748cd8SNickeaurequire_once(__DIR__ . '/Unit.php'); 216*c3437056SNickeaurequire_once(__DIR__ . '/Url.php'); 21737748cd8SNickeaurequire_once(__DIR__ . '/UrlManagerBestEndPage.php'); 21837748cd8SNickeaurequire_once(__DIR__ . '/XhtmlUtility.php'); 21937748cd8SNickeaurequire_once(__DIR__ . '/XmlDocument.php'); 22037748cd8SNickeaurequire_once(__DIR__ . '/XmlUtility.php'); 22137748cd8SNickeau 22237748cd8SNickeau 22337748cd8SNickeau/** 22437748cd8SNickeau * Class url static 22537748cd8SNickeau * List of static utilities 22637748cd8SNickeau */ 22737748cd8SNickeauclass PluginUtility 22837748cd8SNickeau{ 22937748cd8SNickeau 23037748cd8SNickeau const DOKU_DATA_DIR = '/dokudata/pages'; 23137748cd8SNickeau const DOKU_CACHE_DIR = '/dokudata/cache'; 23237748cd8SNickeau 23337748cd8SNickeau /** 23437748cd8SNickeau * Key in the data array between the handle and render function 23537748cd8SNickeau */ 23637748cd8SNickeau const STATE = "state"; 23737748cd8SNickeau const PAYLOAD = "payload"; // The html or text 23837748cd8SNickeau const ATTRIBUTES = "attributes"; 23937748cd8SNickeau // The context is generally the parent tag but it may be also the grandfather. 24037748cd8SNickeau // It permits to determine the HTML that is outputted 24137748cd8SNickeau const CONTEXT = 'context'; 24237748cd8SNickeau const TAG = "tag"; 24337748cd8SNickeau 24437748cd8SNickeau /** 24537748cd8SNickeau * The name of the hidden/private namespace 24637748cd8SNickeau * where the icon and other artifactory are stored 24737748cd8SNickeau */ 24837748cd8SNickeau const COMBOSTRAP_NAMESPACE_NAME = "combostrap"; 24937748cd8SNickeau 25037748cd8SNickeau const PARENT = "parent"; 25137748cd8SNickeau const POSITION = "position"; 25237748cd8SNickeau 25337748cd8SNickeau /** 25437748cd8SNickeau * Class to center an element 25537748cd8SNickeau */ 25637748cd8SNickeau const CENTER_CLASS = "mx-auto"; 25737748cd8SNickeau 25837748cd8SNickeau 25937748cd8SNickeau const EDIT_SECTION_TARGET = 'section'; 26037748cd8SNickeau const ERROR_MESSAGE = "errorAtt"; 2611fa8c418SNickeau const ERROR_LEVEL = "errorLevel"; 2621fa8c418SNickeau const DISPLAY = "display"; 26337748cd8SNickeau 26437748cd8SNickeau /** 26537748cd8SNickeau * The URL base of the documentation 26637748cd8SNickeau */ 267*c3437056SNickeau static $URL_APEX; 26837748cd8SNickeau 26937748cd8SNickeau 27037748cd8SNickeau /** 27137748cd8SNickeau * @var string - the plugin base name (ie the directory) 27237748cd8SNickeau * ie $INFO_PLUGIN['base']; 27337748cd8SNickeau * This is a constant because it permits code analytics 27437748cd8SNickeau * such as verification of a path 27537748cd8SNickeau */ 27637748cd8SNickeau const PLUGIN_BASE_NAME = "combo"; 27737748cd8SNickeau 27837748cd8SNickeau /** 27937748cd8SNickeau * The name of the template plugin 28037748cd8SNickeau */ 28137748cd8SNickeau const TEMPLATE_STRAP_NAME = "strap"; 28237748cd8SNickeau 28337748cd8SNickeau /** 28437748cd8SNickeau * @var array 28537748cd8SNickeau */ 28637748cd8SNickeau static $INFO_PLUGIN; 28737748cd8SNickeau 28837748cd8SNickeau static $PLUGIN_LANG; 28937748cd8SNickeau 29037748cd8SNickeau /** 29137748cd8SNickeau * The plugin name 29237748cd8SNickeau * (not the same than the base as it's not related to the directory 29337748cd8SNickeau * @var string 29437748cd8SNickeau */ 29537748cd8SNickeau public static $PLUGIN_NAME; 29637748cd8SNickeau /** 29737748cd8SNickeau * @var mixed the version 29837748cd8SNickeau */ 29937748cd8SNickeau private static $VERSION; 30037748cd8SNickeau 30137748cd8SNickeau 30237748cd8SNickeau /** 30337748cd8SNickeau * Initiate the static variable 30437748cd8SNickeau * See the call after this class 30537748cd8SNickeau */ 30637748cd8SNickeau static function init() 30737748cd8SNickeau { 30837748cd8SNickeau 30937748cd8SNickeau $pluginInfoFile = __DIR__ . '/../plugin.info.txt'; 31037748cd8SNickeau self::$INFO_PLUGIN = confToHash($pluginInfoFile); 31137748cd8SNickeau self::$PLUGIN_NAME = 'ComboStrap'; 31237748cd8SNickeau global $lang; 31337748cd8SNickeau self::$PLUGIN_LANG = $lang[self::PLUGIN_BASE_NAME]; 314*c3437056SNickeau self::$URL_APEX = "https://" . parse_url(self::$INFO_PLUGIN['url'], PHP_URL_HOST); 31537748cd8SNickeau self::$VERSION = self::$INFO_PLUGIN['version']; 31637748cd8SNickeau 31737748cd8SNickeau } 31837748cd8SNickeau 31937748cd8SNickeau /** 32037748cd8SNickeau * @param $inputExpression 32137748cd8SNickeau * @return false|int 1|0 32237748cd8SNickeau * returns: 32337748cd8SNickeau * - 1 if the input expression is a pattern, 32437748cd8SNickeau * - 0 if not, 32537748cd8SNickeau * - FALSE if an error occurred. 32637748cd8SNickeau */ 32737748cd8SNickeau static function isRegularExpression($inputExpression) 32837748cd8SNickeau { 32937748cd8SNickeau 33037748cd8SNickeau $regularExpressionPattern = "/(\\/.*\\/[gmixXsuUAJ]?)/"; 33137748cd8SNickeau return preg_match($regularExpressionPattern, $inputExpression); 33237748cd8SNickeau 33337748cd8SNickeau } 33437748cd8SNickeau 33537748cd8SNickeau /** 33637748cd8SNickeau * Return a mode from a tag (ie from a {@link Plugin::getPluginComponent()} 33737748cd8SNickeau * @param $tag 33837748cd8SNickeau * @return string 33937748cd8SNickeau * 34037748cd8SNickeau * A mode is just a name for a class 34137748cd8SNickeau * Example: $Parser->addMode('listblock',new Doku_Parser_Mode_ListBlock()); 34237748cd8SNickeau */ 34337748cd8SNickeau public static function getModeFromTag($tag) 34437748cd8SNickeau { 34537748cd8SNickeau return "plugin_" . self::getComponentName($tag); 34637748cd8SNickeau } 34737748cd8SNickeau 34837748cd8SNickeau /** 34937748cd8SNickeau * @param $tag 35037748cd8SNickeau * @return string 35137748cd8SNickeau * 35237748cd8SNickeau * Create a lookahead pattern for a container tag used to enter in a mode 35337748cd8SNickeau */ 35437748cd8SNickeau public static function getContainerTagPattern($tag) 35537748cd8SNickeau { 35637748cd8SNickeau // this pattern ensure that the tag 35737748cd8SNickeau // `accordion` will not intercept also the tag `accordionitem` 35837748cd8SNickeau // where: 35937748cd8SNickeau // ?: means non capturing group (to not capture the last >) 36037748cd8SNickeau // (\s.*?): is a capturing group that starts with a space 36137748cd8SNickeau $pattern = "(?:\s.*?>|>)"; 36237748cd8SNickeau return '<' . $tag . $pattern . '(?=.*?<\/' . $tag . '>)'; 36337748cd8SNickeau } 36437748cd8SNickeau 36537748cd8SNickeau /** 36637748cd8SNickeau * This pattern allows space after the tag name 36737748cd8SNickeau * for an end tag 36837748cd8SNickeau * As XHTML (https://www.w3.org/TR/REC-xml/#dt-etag) 36937748cd8SNickeau * @param $tag 37037748cd8SNickeau * @return string 37137748cd8SNickeau */ 37237748cd8SNickeau public static function getEndTagPattern($tag) 37337748cd8SNickeau { 37437748cd8SNickeau return "</$tag\s*>"; 37537748cd8SNickeau } 37637748cd8SNickeau 37737748cd8SNickeau /** 37837748cd8SNickeau * @param $tag 37937748cd8SNickeau * @return string 38037748cd8SNickeau * 38137748cd8SNickeau * Create a open tag pattern without lookahead. 382*c3437056SNickeau * Used for 383*c3437056SNickeau * @link https://dev.w3.org/html5/html-author/#void-elements-0 38437748cd8SNickeau */ 38537748cd8SNickeau public static function getVoidElementTagPattern($tag) 38637748cd8SNickeau { 38737748cd8SNickeau return '<' . $tag . '.*?>'; 38837748cd8SNickeau } 38937748cd8SNickeau 39037748cd8SNickeau 39137748cd8SNickeau /** 39237748cd8SNickeau * Take an array where the key is the attribute name 39337748cd8SNickeau * and return a HTML tag string 39437748cd8SNickeau * 39537748cd8SNickeau * The attribute name and value are escaped 39637748cd8SNickeau * 39737748cd8SNickeau * @param $attributes - combo attributes 39837748cd8SNickeau * @return string 39937748cd8SNickeau * @deprecated to allowed background and other metadata, use {@link TagAttributes::toHtmlEnterTag()} 40037748cd8SNickeau */ 40137748cd8SNickeau public static function array2HTMLAttributesAsString($attributes) 40237748cd8SNickeau { 40337748cd8SNickeau 40437748cd8SNickeau $tagAttributes = TagAttributes::createFromCallStackArray($attributes); 40537748cd8SNickeau return $tagAttributes->toHTMLAttributeString(); 40637748cd8SNickeau 40737748cd8SNickeau } 40837748cd8SNickeau 40937748cd8SNickeau /** 41037748cd8SNickeau * 41137748cd8SNickeau * Parse the attributes part of a match 41237748cd8SNickeau * 41337748cd8SNickeau * Example: 41437748cd8SNickeau * line-numbers="value" 41537748cd8SNickeau * line-numbers='value' 41637748cd8SNickeau * 41737748cd8SNickeau * This value may be in: 41837748cd8SNickeau * * configuration value 41937748cd8SNickeau * * as well as in the match of a {@link SyntaxPlugin} 42037748cd8SNickeau * 42137748cd8SNickeau * @param $string 42237748cd8SNickeau * @return array 42337748cd8SNickeau * 42437748cd8SNickeau * To parse a match, use {@link PluginUtility::getTagAttributes()} 42537748cd8SNickeau * 42637748cd8SNickeau * 42737748cd8SNickeau */ 42837748cd8SNickeau public static function parseAttributes($string) 42937748cd8SNickeau { 43037748cd8SNickeau 43137748cd8SNickeau $parameters = array(); 43237748cd8SNickeau 43337748cd8SNickeau // Rules 43437748cd8SNickeau // * name may be alone (ie true boolean attribute) 43537748cd8SNickeau // * a name may get a `-` 43637748cd8SNickeau // * there may be space every everywhere when the value is enclosed with a quote 43737748cd8SNickeau // * there may be no space in the value and between the equal sign when the value is not enclosed 43837748cd8SNickeau // 43937748cd8SNickeau // /i not case sensitive 44037748cd8SNickeau $attributePattern = '\s*([-\w]+)\s*(?:=(\s*[\'"]([^`"]*)[\'"]\s*|[^\s]*))?'; 44137748cd8SNickeau $result = preg_match_all('/' . $attributePattern . '/i', $string, $matches); 44237748cd8SNickeau if ($result != 0) { 44337748cd8SNickeau foreach ($matches[1] as $key => $parameterKey) { 44437748cd8SNickeau 44537748cd8SNickeau // group 3 (ie the value between quotes) 44637748cd8SNickeau $value = $matches[3][$key]; 44737748cd8SNickeau if ($value == "") { 44837748cd8SNickeau // check the value without quotes 44937748cd8SNickeau $value = $matches[2][$key]; 45037748cd8SNickeau } 45137748cd8SNickeau // if there is no value, this is a boolean 45237748cd8SNickeau if ($value == "") { 45337748cd8SNickeau $value = true; 45437748cd8SNickeau } else { 45537748cd8SNickeau $value = hsc($value); 45637748cd8SNickeau } 45737748cd8SNickeau $parameters[hsc(strtolower($parameterKey))] = $value; 45837748cd8SNickeau } 45937748cd8SNickeau } 46037748cd8SNickeau return $parameters; 46137748cd8SNickeau 46237748cd8SNickeau } 46337748cd8SNickeau 46437748cd8SNickeau public static function getTagAttributes($match) 46537748cd8SNickeau { 46637748cd8SNickeau return self::getQualifiedTagAttributes($match, false, ""); 46737748cd8SNickeau } 46837748cd8SNickeau 46937748cd8SNickeau /** 47037748cd8SNickeau * Return the attribute of a tag 47137748cd8SNickeau * Because they are users input, they are all escaped 47237748cd8SNickeau * @param $match 47337748cd8SNickeau * @param $hasThirdValue - if true, the third parameter is treated as value, not a property and returned in the `third` key 47437748cd8SNickeau * use for the code/file/console where they accept a name as third value 47537748cd8SNickeau * @param $keyThirdArgument - if a third argument is found, return it with this key 47637748cd8SNickeau * @return array 47737748cd8SNickeau */ 47837748cd8SNickeau public static function getQualifiedTagAttributes($match, $hasThirdValue, $keyThirdArgument) 47937748cd8SNickeau { 48037748cd8SNickeau 48137748cd8SNickeau $match = PluginUtility::getPreprocessEnterTag($match); 48237748cd8SNickeau 48337748cd8SNickeau // Suppress the tag name (ie until the first blank) 48437748cd8SNickeau $spacePosition = strpos($match, " "); 48537748cd8SNickeau if (!$spacePosition) { 48637748cd8SNickeau // No space, meaning this is only the tag name 48737748cd8SNickeau return array(); 48837748cd8SNickeau } 48937748cd8SNickeau $match = trim(substr($match, $spacePosition)); 49037748cd8SNickeau if ($match == "") { 49137748cd8SNickeau return array(); 49237748cd8SNickeau } 49337748cd8SNickeau 49437748cd8SNickeau // Do we have a type as first argument ? 49537748cd8SNickeau $attributes = array(); 49637748cd8SNickeau $spacePosition = strpos($match, " "); 49737748cd8SNickeau if ($spacePosition) { 49837748cd8SNickeau $nextArgument = substr($match, 0, $spacePosition); 49937748cd8SNickeau } else { 50037748cd8SNickeau $nextArgument = $match; 50137748cd8SNickeau } 50237748cd8SNickeau if (!strpos($nextArgument, "=")) { 50337748cd8SNickeau $attributes["type"] = $nextArgument; 50437748cd8SNickeau // Suppress the type 50537748cd8SNickeau $match = substr($match, strlen($nextArgument)); 50637748cd8SNickeau $match = trim($match); 50737748cd8SNickeau 50837748cd8SNickeau // Do we have a value as first argument ? 50937748cd8SNickeau if (!empty($hasThirdValue)) { 51037748cd8SNickeau $spacePosition = strpos($match, " "); 51137748cd8SNickeau if ($spacePosition) { 51237748cd8SNickeau $nextArgument = substr($match, 0, $spacePosition); 51337748cd8SNickeau } else { 51437748cd8SNickeau $nextArgument = $match; 51537748cd8SNickeau } 51637748cd8SNickeau if (!strpos($nextArgument, "=") && !empty($nextArgument)) { 51737748cd8SNickeau $attributes[$keyThirdArgument] = $nextArgument; 51837748cd8SNickeau // Suppress the third argument 51937748cd8SNickeau $match = substr($match, strlen($nextArgument)); 52037748cd8SNickeau $match = trim($match); 52137748cd8SNickeau } 52237748cd8SNickeau } 52337748cd8SNickeau } 52437748cd8SNickeau 52537748cd8SNickeau // Parse the remaining attributes 52637748cd8SNickeau $parsedAttributes = self::parseAttributes($match); 52737748cd8SNickeau 52837748cd8SNickeau // Merge 52937748cd8SNickeau $attributes = array_merge($attributes, $parsedAttributes);; 53037748cd8SNickeau 53137748cd8SNickeau return $attributes; 53237748cd8SNickeau 53337748cd8SNickeau } 53437748cd8SNickeau 53537748cd8SNickeau /** 53637748cd8SNickeau * @param array $styleProperties - an array of CSS properties with key, value 53737748cd8SNickeau * @return string - the value for the style attribute (ie all rules where joined with the comma) 53837748cd8SNickeau */ 53937748cd8SNickeau public static function array2InlineStyle(array $styleProperties) 54037748cd8SNickeau { 54137748cd8SNickeau $inlineCss = ""; 54237748cd8SNickeau foreach ($styleProperties as $key => $value) { 54337748cd8SNickeau $inlineCss .= "$key:$value;"; 54437748cd8SNickeau } 54537748cd8SNickeau // Suppress the last ; 54637748cd8SNickeau if ($inlineCss[strlen($inlineCss) - 1] == ";") { 54737748cd8SNickeau $inlineCss = substr($inlineCss, 0, -1); 54837748cd8SNickeau } 54937748cd8SNickeau return $inlineCss; 55037748cd8SNickeau } 55137748cd8SNickeau 55237748cd8SNickeau /** 55337748cd8SNickeau * @param $tag 55437748cd8SNickeau * @return string 55537748cd8SNickeau * Create a pattern used where the tag is not a container. 55637748cd8SNickeau * ie 55737748cd8SNickeau * <br/> 55837748cd8SNickeau * <icon/> 55937748cd8SNickeau * This is generally used with a subtition plugin 56037748cd8SNickeau * and a {@link Lexer::addSpecialPattern} state 56137748cd8SNickeau * where the tag is just replaced 56237748cd8SNickeau */ 56319494974Sgerardnico public static function getEmptyTagPattern($tag): string 56437748cd8SNickeau { 56519494974Sgerardnico 56619494974Sgerardnico return '<' . $tag . '[^>]*/>'; 56737748cd8SNickeau } 56837748cd8SNickeau 56937748cd8SNickeau /** 57037748cd8SNickeau * Just call this function from a class like that 57137748cd8SNickeau * getTageName(get_called_class()) 57237748cd8SNickeau * to get the tag name (ie the component plugin) 57337748cd8SNickeau * of a syntax plugin 57437748cd8SNickeau * 57537748cd8SNickeau * @param $get_called_class 57637748cd8SNickeau * @return string 57737748cd8SNickeau */ 57837748cd8SNickeau public static function getTagName($get_called_class) 57937748cd8SNickeau { 58037748cd8SNickeau list(/* $t */, /* $p */, /* $n */, $c) = explode('_', $get_called_class, 4); 58137748cd8SNickeau return (isset($c) ? $c : ''); 58237748cd8SNickeau } 58337748cd8SNickeau 58437748cd8SNickeau /** 58537748cd8SNickeau * Just call this function from a class like that 58637748cd8SNickeau * getAdminPageName(get_called_class()) 58737748cd8SNickeau * to get the page name of a admin plugin 58837748cd8SNickeau * 58937748cd8SNickeau * @param $get_called_class 59037748cd8SNickeau * @return string - the admin page name 59137748cd8SNickeau */ 59237748cd8SNickeau public static function getAdminPageName($get_called_class) 59337748cd8SNickeau { 59437748cd8SNickeau $names = explode('_', $get_called_class); 59537748cd8SNickeau $names = array_slice($names, -2); 59637748cd8SNickeau return implode('_', $names); 59737748cd8SNickeau } 59837748cd8SNickeau 59937748cd8SNickeau public static function getNameSpace() 60037748cd8SNickeau { 60137748cd8SNickeau // No : at the begin of the namespace please 60237748cd8SNickeau return self::PLUGIN_BASE_NAME . ':'; 60337748cd8SNickeau } 60437748cd8SNickeau 60537748cd8SNickeau /** 60637748cd8SNickeau * @param $get_called_class - the plugin class 60737748cd8SNickeau * @return array 60837748cd8SNickeau */ 60937748cd8SNickeau public static function getTags($get_called_class) 61037748cd8SNickeau { 61137748cd8SNickeau $elements = array(); 61237748cd8SNickeau $elementName = PluginUtility::getTagName($get_called_class); 61337748cd8SNickeau $elements[] = $elementName; 61437748cd8SNickeau $elements[] = strtoupper($elementName); 61537748cd8SNickeau return $elements; 61637748cd8SNickeau } 61737748cd8SNickeau 61837748cd8SNickeau /** 61937748cd8SNickeau * Render a text 62037748cd8SNickeau * @param $pageContent 62137748cd8SNickeau * @return string|null 62237748cd8SNickeau */ 62337748cd8SNickeau public static function render($pageContent) 62437748cd8SNickeau { 62537748cd8SNickeau return RenderUtility::renderText2XhtmlAndStripPEventually($pageContent, false); 62637748cd8SNickeau } 62737748cd8SNickeau 62837748cd8SNickeau 62937748cd8SNickeau /** 63037748cd8SNickeau * This method will takes attributes 63137748cd8SNickeau * and process the plugin styling attribute such as width and height 63237748cd8SNickeau * to put them in a style HTML attribute 63337748cd8SNickeau * @param TagAttributes $attributes 63437748cd8SNickeau */ 63537748cd8SNickeau public static function processStyle(&$attributes) 63637748cd8SNickeau { 63737748cd8SNickeau // Style 63837748cd8SNickeau $styleAttributeName = "style"; 63937748cd8SNickeau if ($attributes->hasComponentAttribute($styleAttributeName)) { 64037748cd8SNickeau $properties = explode(";", $attributes->getValueAndRemove($styleAttributeName)); 64137748cd8SNickeau foreach ($properties as $property) { 64237748cd8SNickeau list($key, $value) = explode(":", $property); 64337748cd8SNickeau if ($key != "") { 64437748cd8SNickeau $attributes->addStyleDeclaration($key, $value); 64537748cd8SNickeau } 64637748cd8SNickeau } 64737748cd8SNickeau } 64837748cd8SNickeau 64937748cd8SNickeau 65037748cd8SNickeau /** 65137748cd8SNickeau * Border Color 65237748cd8SNickeau * For background color, see {@link TagAttributes::processBackground()} 65337748cd8SNickeau * For text color, see {@link TextColor} 65437748cd8SNickeau */ 65537748cd8SNickeau 65637748cd8SNickeau if ($attributes->hasComponentAttribute(ColorUtility::BORDER_COLOR)) { 65737748cd8SNickeau $colorValue = $attributes->getValueAndRemove(ColorUtility::BORDER_COLOR); 65837748cd8SNickeau $attributes->addStyleDeclaration(ColorUtility::BORDER_COLOR, ColorUtility::getColorValue($colorValue)); 65937748cd8SNickeau self::checkDefaultBorderColorAttributes($attributes); 66037748cd8SNickeau } 66137748cd8SNickeau 66237748cd8SNickeau 66337748cd8SNickeau } 66437748cd8SNickeau 66537748cd8SNickeau /** 66637748cd8SNickeau * Return the name of the requested script 66737748cd8SNickeau */ 66837748cd8SNickeau public 66937748cd8SNickeau static function getRequestScript() 67037748cd8SNickeau { 67137748cd8SNickeau $scriptPath = null; 67237748cd8SNickeau $testPropertyValue = self::getPropertyValue("SCRIPT_NAME"); 67337748cd8SNickeau if (defined('DOKU_UNITTEST') && $testPropertyValue != null) { 67437748cd8SNickeau return $testPropertyValue; 67537748cd8SNickeau } 67637748cd8SNickeau if (array_key_exists("DOCUMENT_URI", $_SERVER)) { 67737748cd8SNickeau $scriptPath = $_SERVER["DOCUMENT_URI"]; 67837748cd8SNickeau } 67937748cd8SNickeau if ($scriptPath == null && array_key_exists("SCRIPT_NAME", $_SERVER)) { 68037748cd8SNickeau $scriptPath = $_SERVER["SCRIPT_NAME"]; 68137748cd8SNickeau } 68237748cd8SNickeau if ($scriptPath == null) { 68337748cd8SNickeau msg("Unable to find the main script", LogUtility::LVL_MSG_ERROR); 68437748cd8SNickeau } 68537748cd8SNickeau $path_parts = pathinfo($scriptPath); 68637748cd8SNickeau return $path_parts['basename']; 68737748cd8SNickeau } 68837748cd8SNickeau 68937748cd8SNickeau /** 69037748cd8SNickeau * 69137748cd8SNickeau * @param $name 69237748cd8SNickeau * @param $default 69337748cd8SNickeau * @return string - the value of a query string property or if in test mode, the value of a test variable 69437748cd8SNickeau * set with {@link self::setTestProperty} 69537748cd8SNickeau * This is used to test script that are not supported by the dokuwiki test framework 69637748cd8SNickeau * such as css.php 69737748cd8SNickeau */ 69837748cd8SNickeau public 69937748cd8SNickeau static function getPropertyValue($name, $default = null) 70037748cd8SNickeau { 70137748cd8SNickeau global $INPUT; 70237748cd8SNickeau $value = $INPUT->str($name); 70337748cd8SNickeau if ($value == null && defined('DOKU_UNITTEST')) { 70437748cd8SNickeau global $COMBO; 70537748cd8SNickeau $value = $COMBO[$name]; 70637748cd8SNickeau } 70737748cd8SNickeau if ($value == null) { 70837748cd8SNickeau return $default; 70937748cd8SNickeau } else { 71037748cd8SNickeau return $value; 71137748cd8SNickeau } 71237748cd8SNickeau 71337748cd8SNickeau } 71437748cd8SNickeau 71537748cd8SNickeau /** 71637748cd8SNickeau * Create an URL to the documentation website 71737748cd8SNickeau * @param $canonical - canonical id or slug 718*c3437056SNickeau * @param $label - the text of the link 71937748cd8SNickeau * @param bool $withIcon - used to break the recursion with the message in the {@link Icon} 72037748cd8SNickeau * @return string - an url 72137748cd8SNickeau */ 72237748cd8SNickeau public 723*c3437056SNickeau static function getDocumentationHyperLink($canonical, $label, $withIcon = true, $tooltip = ""): string 72437748cd8SNickeau { 72537748cd8SNickeau /** @noinspection SpellCheckingInspection */ 72637748cd8SNickeau 72737748cd8SNickeau $xhtmlIcon = ""; 72837748cd8SNickeau if ($withIcon) { 72937748cd8SNickeau 73037748cd8SNickeau /** 73137748cd8SNickeau * We don't include it as an external resource via url 73237748cd8SNickeau * because it then make a http request for every logo 73337748cd8SNickeau * in the configuration page and makes it really slow 734*c3437056SNickeau * TODO: when we have made a special fetch ajax with cache 735*c3437056SNickeau * for application resource, we can serve it statically 73637748cd8SNickeau */ 737*c3437056SNickeau $path = LocalPath::createFromPath(Resources::getImagesDirectory() . "/logo.svg"); 73837748cd8SNickeau $tagAttributes = TagAttributes::createEmpty(SvgImageLink::CANONICAL); 73937748cd8SNickeau $tagAttributes->addComponentAttributeValue(TagAttributes::TYPE_KEY, SvgDocument::ICON_TYPE); 74037748cd8SNickeau $tagAttributes->addComponentAttributeValue(Dimension::WIDTH_KEY, "20"); 74137748cd8SNickeau $cache = new CacheMedia($path, $tagAttributes); 74237748cd8SNickeau if (!$cache->isCacheUsable()) { 743*c3437056SNickeau $xhtmlIcon = SvgDocument::createSvgDocumentFromPath($path) 74437748cd8SNickeau ->setShouldBeOptimized(true) 74537748cd8SNickeau ->getXmlText($tagAttributes); 74637748cd8SNickeau $cache->storeCache($xhtmlIcon); 74737748cd8SNickeau } 748*c3437056SNickeau $xhtmlIcon = FileSystems::getContent($cache->getFile()); 74937748cd8SNickeau 75037748cd8SNickeau } 751*c3437056SNickeau $urlApex = self::$URL_APEX; 752*c3437056SNickeau $path = str_replace(":", "/", $canonical); 753*c3437056SNickeau if (empty($tooltip)) { 754*c3437056SNickeau $title = $label; 755*c3437056SNickeau } else { 756*c3437056SNickeau $title = $tooltip; 757*c3437056SNickeau } 758*c3437056SNickeau $htmlToolTip = ""; 759*c3437056SNickeau if (!empty($tooltip)) { 760*c3437056SNickeau $dataAttributeNamespace = Bootstrap::getDataNamespace(); 761*c3437056SNickeau $htmlToolTip = "data{$dataAttributeNamespace}-toggle=\"tooltip\""; 762*c3437056SNickeau } 763*c3437056SNickeau return "$xhtmlIcon<a href=\"$urlApex/$path\" title=\"$title\" $htmlToolTip style=\"text-decoration:none;\">$label</a>"; 76437748cd8SNickeau } 76537748cd8SNickeau 76637748cd8SNickeau /** 76737748cd8SNickeau * An utility function to not search every time which array should be first 76837748cd8SNickeau * @param array $inlineAttributes - the component inline attributes 76937748cd8SNickeau * @param array $defaultAttributes - the default configuration attributes 77037748cd8SNickeau * @return array - a merged array 77137748cd8SNickeau */ 77237748cd8SNickeau public 77337748cd8SNickeau static function mergeAttributes(array $inlineAttributes, array $defaultAttributes = array()) 77437748cd8SNickeau { 77537748cd8SNickeau return array_merge($defaultAttributes, $inlineAttributes); 77637748cd8SNickeau } 77737748cd8SNickeau 77837748cd8SNickeau /** 77937748cd8SNickeau * A pattern for a container tag 78037748cd8SNickeau * that needs to catch the content 78137748cd8SNickeau * 78237748cd8SNickeau * Use as a special pattern (substition) 78337748cd8SNickeau * 78437748cd8SNickeau * The {@link \syntax_plugin_combo_math} use it 78537748cd8SNickeau * @param $tag 78637748cd8SNickeau * @return string - a pattern 78737748cd8SNickeau */ 78837748cd8SNickeau public 78937748cd8SNickeau static function getLeafContainerTagPattern($tag) 79037748cd8SNickeau { 79137748cd8SNickeau return '<' . $tag . '.*?>.*?<\/' . $tag . '>'; 79237748cd8SNickeau } 79337748cd8SNickeau 79437748cd8SNickeau /** 79537748cd8SNickeau * Return the content of a tag 79637748cd8SNickeau * <math>Content</math> 79737748cd8SNickeau * @param $match 79837748cd8SNickeau * @return string the content 79937748cd8SNickeau */ 80037748cd8SNickeau public 80137748cd8SNickeau static function getTagContent($match) 80237748cd8SNickeau { 80337748cd8SNickeau // From the first > 80437748cd8SNickeau $start = strpos($match, ">"); 80537748cd8SNickeau if ($start == false) { 80637748cd8SNickeau LogUtility::msg("The match does not contain any opening tag. Match: {$match}", LogUtility::LVL_MSG_ERROR); 80737748cd8SNickeau return ""; 80837748cd8SNickeau } 80937748cd8SNickeau $match = substr($match, $start + 1); 81037748cd8SNickeau // If this is the last character, we get a false 81137748cd8SNickeau if ($match == false) { 81237748cd8SNickeau LogUtility::msg("The match does not contain any closing tag. Match: {$match}", LogUtility::LVL_MSG_ERROR); 81337748cd8SNickeau return ""; 81437748cd8SNickeau } 81537748cd8SNickeau 81637748cd8SNickeau $end = strrpos($match, "</"); 81737748cd8SNickeau if ($end == false) { 81837748cd8SNickeau LogUtility::msg("The match does not contain any closing tag. Match: {$match}", LogUtility::LVL_MSG_ERROR); 81937748cd8SNickeau return ""; 82037748cd8SNickeau } 82137748cd8SNickeau 82237748cd8SNickeau return substr($match, 0, $end); 82337748cd8SNickeau } 82437748cd8SNickeau 82537748cd8SNickeau /** 82637748cd8SNickeau * 82737748cd8SNickeau * Check if a HTML tag was already added for a request 82837748cd8SNickeau * The request id is just the timestamp 82937748cd8SNickeau * An indicator array should be provided 83037748cd8SNickeau * @return string 83137748cd8SNickeau */ 83237748cd8SNickeau public 83337748cd8SNickeau static function getRequestId() 83437748cd8SNickeau { 83537748cd8SNickeau 83637748cd8SNickeau if (isset($_SERVER['REQUEST_TIME_FLOAT'])) { 83737748cd8SNickeau // since php 5.4 83837748cd8SNickeau $requestTime = $_SERVER['REQUEST_TIME_FLOAT']; 83937748cd8SNickeau } else { 84037748cd8SNickeau // DokuWiki test framework use this 84137748cd8SNickeau $requestTime = $_SERVER['REQUEST_TIME']; 84237748cd8SNickeau } 84337748cd8SNickeau $keyPrefix = 'combo_'; 84437748cd8SNickeau 84537748cd8SNickeau global $ID; 84637748cd8SNickeau return $keyPrefix . hash('crc32b', $_SERVER['REMOTE_ADDR'] . $_SERVER['REMOTE_PORT'] . $requestTime . $ID); 84737748cd8SNickeau 84837748cd8SNickeau } 84937748cd8SNickeau 85037748cd8SNickeau /** 85137748cd8SNickeau * Get the page id 85237748cd8SNickeau * If the page is a sidebar, it will not return the id of the sidebar 85337748cd8SNickeau * but the one of the page 854*c3437056SNickeau * Return the main/requested page id 855*c3437056SNickeau * (Not the sidebar) 856*c3437056SNickeau * @return string|null - null in test 85737748cd8SNickeau */ 85837748cd8SNickeau public 859*c3437056SNickeau static function getMainPageDokuwikiId(): ?string 86037748cd8SNickeau { 861*c3437056SNickeau global $ID; 862*c3437056SNickeau global $INFO; 863*c3437056SNickeau $callingId = $ID; 864*c3437056SNickeau // If the component is in a sidebar, we don't want the ID of the sidebar 865*c3437056SNickeau // but the ID of the page. 866*c3437056SNickeau if ($INFO != null) { 867*c3437056SNickeau $callingId = $INFO['id']; 868*c3437056SNickeau } 869*c3437056SNickeau /** 870*c3437056SNickeau * This is the case with event triggered 871*c3437056SNickeau * before DokuWiki such as 872*c3437056SNickeau * https://www.dokuwiki.org/devel:event:init_lang_load 873*c3437056SNickeau */ 874*c3437056SNickeau if ($callingId == null) { 875*c3437056SNickeau global $_REQUEST; 876*c3437056SNickeau if (isset($_REQUEST["id"])) { 877*c3437056SNickeau $callingId = $_REQUEST["id"]; 878*c3437056SNickeau } 879*c3437056SNickeau } 880*c3437056SNickeau return $callingId; 881*c3437056SNickeau 88237748cd8SNickeau } 88337748cd8SNickeau 88437748cd8SNickeau /** 88537748cd8SNickeau * Transform special HTML characters to entity 88637748cd8SNickeau * Example: 88737748cd8SNickeau * <hello>world</hello> 88837748cd8SNickeau * to 88937748cd8SNickeau * "<hello>world</hello>" 89037748cd8SNickeau * 89137748cd8SNickeau * @param $text 89237748cd8SNickeau * @return string 89337748cd8SNickeau */ 89437748cd8SNickeau public 895*c3437056SNickeau static function htmlEncode($text): string 89637748cd8SNickeau { 89737748cd8SNickeau /** 89837748cd8SNickeau * See https://stackoverflow.com/questions/46483/htmlentities-vs-htmlspecialchars/3614344 89937748cd8SNickeau * {@link htmlentities } 90037748cd8SNickeau */ 90137748cd8SNickeau //return htmlspecialchars($text, ENT_QUOTES); 90237748cd8SNickeau return htmlentities($text); 90337748cd8SNickeau } 90437748cd8SNickeau 905*c3437056SNickeau public 906*c3437056SNickeau static function xmlEncode($text) 907*c3437056SNickeau { 908*c3437056SNickeau /** 909*c3437056SNickeau * {@link htmlentities } 910*c3437056SNickeau */ 911*c3437056SNickeau return htmlentities($text, ENT_XML1); 912*c3437056SNickeau } 913*c3437056SNickeau 91437748cd8SNickeau 91537748cd8SNickeau /** 91637748cd8SNickeau * Add a class 91737748cd8SNickeau * @param $classValue 91837748cd8SNickeau * @param array $attributes 91937748cd8SNickeau */ 92037748cd8SNickeau public 92137748cd8SNickeau static function addClass2Attributes($classValue, array &$attributes) 92237748cd8SNickeau { 92337748cd8SNickeau self::addAttributeValue("class", $classValue, $attributes); 92437748cd8SNickeau } 92537748cd8SNickeau 92637748cd8SNickeau /** 92737748cd8SNickeau * Add a style property to the attributes 92837748cd8SNickeau * @param $property 92937748cd8SNickeau * @param $value 93037748cd8SNickeau * @param array $attributes 93137748cd8SNickeau * @deprecated use {@link TagAttributes::addStyleDeclaration()} instead 93237748cd8SNickeau */ 93337748cd8SNickeau public 93437748cd8SNickeau static function addStyleProperty($property, $value, array &$attributes) 93537748cd8SNickeau { 93637748cd8SNickeau if (isset($attributes["style"])) { 93737748cd8SNickeau $attributes["style"] .= ";$property:$value"; 93837748cd8SNickeau } else { 93937748cd8SNickeau $attributes["style"] = "$property:$value"; 94037748cd8SNickeau } 94137748cd8SNickeau 94237748cd8SNickeau } 94337748cd8SNickeau 94437748cd8SNickeau /** 94537748cd8SNickeau * Add default border attributes 94637748cd8SNickeau * to see a border 94737748cd8SNickeau * Doc 94837748cd8SNickeau * https://combostrap.com/styling/color#border_color 94937748cd8SNickeau * @param TagAttributes $tagAttributes 95037748cd8SNickeau */ 95137748cd8SNickeau private 95237748cd8SNickeau static function checkDefaultBorderColorAttributes(&$tagAttributes) 95337748cd8SNickeau { 95437748cd8SNickeau /** 95537748cd8SNickeau * border color was set without the width 95637748cd8SNickeau * setting the width 95737748cd8SNickeau */ 95837748cd8SNickeau if (!( 95937748cd8SNickeau $tagAttributes->hasStyleDeclaration("border") 96037748cd8SNickeau || 96137748cd8SNickeau $tagAttributes->hasStyleDeclaration("border-width") 96237748cd8SNickeau ) 96337748cd8SNickeau ) { 96437748cd8SNickeau $tagAttributes->addStyleDeclaration("border-width", "1px"); 96537748cd8SNickeau } 96637748cd8SNickeau /** 96737748cd8SNickeau * border color was set without the style 96837748cd8SNickeau * setting the style 96937748cd8SNickeau */ 97037748cd8SNickeau if (! 97137748cd8SNickeau ( 97237748cd8SNickeau $tagAttributes->hasStyleDeclaration("border") 97337748cd8SNickeau || 97437748cd8SNickeau $tagAttributes->hasStyleDeclaration("border-style") 97537748cd8SNickeau ) 97637748cd8SNickeau ) { 97737748cd8SNickeau $tagAttributes->addStyleDeclaration("border-style", "solid"); 97837748cd8SNickeau 97937748cd8SNickeau } 98037748cd8SNickeau if (!$tagAttributes->hasStyleDeclaration("border-radius")) { 98137748cd8SNickeau $tagAttributes->addStyleDeclaration("border-radius", ".25rem"); 98237748cd8SNickeau } 98337748cd8SNickeau 98437748cd8SNickeau } 98537748cd8SNickeau 98637748cd8SNickeau public 98737748cd8SNickeau static function getConfValue($confName, $defaultValue = null) 98837748cd8SNickeau { 98937748cd8SNickeau global $conf; 99037748cd8SNickeau if (isset($conf['plugin'][PluginUtility::PLUGIN_BASE_NAME][$confName])) { 99137748cd8SNickeau return $conf['plugin'][PluginUtility::PLUGIN_BASE_NAME][$confName]; 99237748cd8SNickeau } else { 99337748cd8SNickeau return $defaultValue; 99437748cd8SNickeau } 99537748cd8SNickeau } 99637748cd8SNickeau 99737748cd8SNickeau /** 99837748cd8SNickeau * @param $match 99937748cd8SNickeau * @return null|string - return the tag name or null if not found 100037748cd8SNickeau */ 100137748cd8SNickeau public 100237748cd8SNickeau static function getTag($match) 100337748cd8SNickeau { 100437748cd8SNickeau 100537748cd8SNickeau // Trim to start clean 100637748cd8SNickeau $match = trim($match); 100737748cd8SNickeau 100837748cd8SNickeau // Until the first > 100937748cd8SNickeau $pos = strpos($match, ">"); 101037748cd8SNickeau if ($pos == false) { 101137748cd8SNickeau LogUtility::msg("The match does not contain any tag. Match: {$match}", LogUtility::LVL_MSG_ERROR); 101237748cd8SNickeau return null; 101337748cd8SNickeau } 101437748cd8SNickeau $match = substr($match, 0, $pos); 101537748cd8SNickeau 101637748cd8SNickeau // Suppress the < 101737748cd8SNickeau if ($match[0] == "<") { 101837748cd8SNickeau $match = substr($match, 1); 101937748cd8SNickeau } else { 102037748cd8SNickeau LogUtility::msg("This is not a text tag because it does not start with the character `>`"); 102137748cd8SNickeau } 102237748cd8SNickeau 102337748cd8SNickeau // Suppress the tag name (ie until the first blank) 102437748cd8SNickeau $spacePosition = strpos($match, " "); 102537748cd8SNickeau if (!$spacePosition) { 102637748cd8SNickeau // No space, meaning this is only the tag name 102737748cd8SNickeau return $match; 102837748cd8SNickeau } else { 102937748cd8SNickeau return substr($match, 0, $spacePosition); 103037748cd8SNickeau } 103137748cd8SNickeau 103237748cd8SNickeau } 103337748cd8SNickeau 103437748cd8SNickeau 103537748cd8SNickeau /** 103637748cd8SNickeau * @param string $string add a command into HTML 103737748cd8SNickeau */ 103837748cd8SNickeau public 103937748cd8SNickeau static function addAsHtmlComment($string) 104037748cd8SNickeau { 104137748cd8SNickeau print_r('<!-- ' . self::htmlEncode($string) . '-->'); 104237748cd8SNickeau } 104337748cd8SNickeau 104437748cd8SNickeau public 104537748cd8SNickeau static function getResourceBaseUrl() 104637748cd8SNickeau { 104737748cd8SNickeau return DOKU_URL . 'lib/plugins/' . PluginUtility::PLUGIN_BASE_NAME . '/resources'; 104837748cd8SNickeau } 104937748cd8SNickeau 105037748cd8SNickeau 105137748cd8SNickeau 105237748cd8SNickeau public 105337748cd8SNickeau static function getComponentName($tag) 105437748cd8SNickeau { 105537748cd8SNickeau return strtolower(PluginUtility::PLUGIN_BASE_NAME) . "_" . $tag; 105637748cd8SNickeau } 105737748cd8SNickeau 105837748cd8SNickeau public 105937748cd8SNickeau static function addAttributeValue($attribute, $value, array &$attributes) 106037748cd8SNickeau { 106137748cd8SNickeau if (array_key_exists($attribute, $attributes) && $attributes[$attribute] !== "") { 106237748cd8SNickeau $attributes[$attribute] .= " {$value}"; 106337748cd8SNickeau } else { 106437748cd8SNickeau $attributes[$attribute] = "{$value}"; 106537748cd8SNickeau } 106637748cd8SNickeau } 106737748cd8SNickeau 106837748cd8SNickeau /** 106937748cd8SNickeau * Plugin Utility is available to all plugin, 107037748cd8SNickeau * this is a convenient way to the the snippet manager 107137748cd8SNickeau * @return SnippetManager 107237748cd8SNickeau */ 107337748cd8SNickeau public 1074*c3437056SNickeau static function getSnippetManager(): SnippetManager 107537748cd8SNickeau { 107637748cd8SNickeau return SnippetManager::get(); 107737748cd8SNickeau } 107837748cd8SNickeau 1079*c3437056SNickeau 108037748cd8SNickeau 108137748cd8SNickeau /** 108237748cd8SNickeau * Function used in a render 108337748cd8SNickeau * @param $data - the data from {@link PluginUtility::handleAndReturnUnmatchedData()} 108437748cd8SNickeau * @return string 108537748cd8SNickeau */ 108637748cd8SNickeau public 108737748cd8SNickeau static function renderUnmatched($data) 108837748cd8SNickeau { 108937748cd8SNickeau /** 109037748cd8SNickeau * Attributes 109137748cd8SNickeau */ 109237748cd8SNickeau if (isset($data[PluginUtility::ATTRIBUTES])) { 109337748cd8SNickeau $attributes = $data[PluginUtility::ATTRIBUTES]; 109437748cd8SNickeau } else { 109537748cd8SNickeau $attributes = []; 109637748cd8SNickeau } 109737748cd8SNickeau $tagAttributes = TagAttributes::createFromCallStackArray($attributes); 109837748cd8SNickeau $display = $tagAttributes->getValue(TagAttributes::DISPLAY); 109937748cd8SNickeau if ($display != "none") { 110037748cd8SNickeau $payload = $data[self::PAYLOAD]; 11011fa8c418SNickeau $previousTagDisplayType = $data[self::CONTEXT]; 11021fa8c418SNickeau if ($previousTagDisplayType !== Call::INLINE_DISPLAY) { 110337748cd8SNickeau $payload = ltrim($payload); 110437748cd8SNickeau } 110537748cd8SNickeau return PluginUtility::htmlEncode($payload); 110637748cd8SNickeau } else { 110737748cd8SNickeau return ""; 110837748cd8SNickeau } 110937748cd8SNickeau } 111037748cd8SNickeau 1111*c3437056SNickeau public 1112*c3437056SNickeau static function renderUnmatchedXml($data) 1113*c3437056SNickeau { 1114*c3437056SNickeau $payload = $data[self::PAYLOAD]; 1115*c3437056SNickeau $previousTagDisplayType = $data[self::CONTEXT]; 1116*c3437056SNickeau if ($previousTagDisplayType !== Call::INLINE_DISPLAY) { 1117*c3437056SNickeau $payload = ltrim($payload); 1118*c3437056SNickeau } 1119*c3437056SNickeau return PluginUtility::xmlEncode($payload); 1120*c3437056SNickeau 1121*c3437056SNickeau } 1122*c3437056SNickeau 112337748cd8SNickeau /** 112437748cd8SNickeau * Function used in a handle function of a syntax plugin for 112537748cd8SNickeau * unmatched context 112637748cd8SNickeau * @param $tagName 112737748cd8SNickeau * @param $match 112837748cd8SNickeau * @param \Doku_Handler $handler 112937748cd8SNickeau * @return array 113037748cd8SNickeau */ 113137748cd8SNickeau public 11321fa8c418SNickeau static function handleAndReturnUnmatchedData($tagName, $match, \Doku_Handler $handler): array 113337748cd8SNickeau { 11341fa8c418SNickeau $callStack = CallStack::createFromHandler($handler); 11351fa8c418SNickeau $sibling = $callStack->previous(); 113637748cd8SNickeau $context = null; 113737748cd8SNickeau if (!empty($sibling)) { 11381fa8c418SNickeau $context = $sibling->getDisplay(); 113937748cd8SNickeau } 114037748cd8SNickeau return array( 114137748cd8SNickeau PluginUtility::STATE => DOKU_LEXER_UNMATCHED, 114237748cd8SNickeau PluginUtility::PAYLOAD => $match, 114337748cd8SNickeau PluginUtility::CONTEXT => $context 114437748cd8SNickeau ); 114537748cd8SNickeau } 114637748cd8SNickeau 114737748cd8SNickeau public 114837748cd8SNickeau static function setConf($key, $value, $namespace = 'plugin') 114937748cd8SNickeau { 115037748cd8SNickeau global $conf; 1151*c3437056SNickeau if ($namespace !== null) { 115237748cd8SNickeau $conf[$namespace][PluginUtility::PLUGIN_BASE_NAME][$key] = $value; 115337748cd8SNickeau } else { 115437748cd8SNickeau $conf[$key] = $value; 115537748cd8SNickeau } 115637748cd8SNickeau 115737748cd8SNickeau } 115837748cd8SNickeau 115937748cd8SNickeau /** 116037748cd8SNickeau * Utility methodPreprocess a start tag to be able to extract the name 116137748cd8SNickeau * and the attributes easily 116237748cd8SNickeau * 116337748cd8SNickeau * It will delete: 116437748cd8SNickeau * * the characters <> and the /> if present 116537748cd8SNickeau * * and trim 116637748cd8SNickeau * 116737748cd8SNickeau * It will remain the tagname and its attributes 116837748cd8SNickeau * @param $match 116937748cd8SNickeau * @return false|string|null 117037748cd8SNickeau */ 117137748cd8SNickeau private 117237748cd8SNickeau static function getPreprocessEnterTag($match) 117337748cd8SNickeau { 117437748cd8SNickeau // Until the first > 117537748cd8SNickeau $pos = strpos($match, ">"); 117637748cd8SNickeau if ($pos == false) { 117737748cd8SNickeau LogUtility::msg("The match does not contain any tag. Match: {$match}", LogUtility::LVL_MSG_WARNING); 117837748cd8SNickeau return null; 117937748cd8SNickeau } 118037748cd8SNickeau $match = substr($match, 0, $pos); 118137748cd8SNickeau 118237748cd8SNickeau 118337748cd8SNickeau // Trim to start clean 118437748cd8SNickeau $match = trim($match); 118537748cd8SNickeau 118637748cd8SNickeau // Suppress the < 118737748cd8SNickeau if ($match[0] == "<") { 118837748cd8SNickeau $match = substr($match, 1); 118937748cd8SNickeau } 119037748cd8SNickeau 119137748cd8SNickeau // Suppress the / for a leaf tag 119237748cd8SNickeau if ($match[strlen($match) - 1] == "/") { 119337748cd8SNickeau $match = substr($match, 0, strlen($match) - 1); 119437748cd8SNickeau } 119537748cd8SNickeau return $match; 119637748cd8SNickeau } 119737748cd8SNickeau 119837748cd8SNickeau /** 119937748cd8SNickeau * Retrieve the tag name used in the text document 120037748cd8SNickeau * @param $match 120137748cd8SNickeau * @return false|string|null 120237748cd8SNickeau */ 120337748cd8SNickeau public 120437748cd8SNickeau static function getSyntaxTagNameFromMatch($match) 120537748cd8SNickeau { 120637748cd8SNickeau $preprocessMatch = PluginUtility::getPreprocessEnterTag($match); 120737748cd8SNickeau 120837748cd8SNickeau // Tag name (ie until the first blank) 120937748cd8SNickeau $spacePosition = strpos($match, " "); 121037748cd8SNickeau if (!$spacePosition) { 121137748cd8SNickeau // No space, meaning this is only the tag name 121237748cd8SNickeau return $preprocessMatch; 121337748cd8SNickeau } else { 121437748cd8SNickeau return trim(substr(0, $spacePosition)); 121537748cd8SNickeau } 121637748cd8SNickeau 121737748cd8SNickeau } 121837748cd8SNickeau 121937748cd8SNickeau /** 122037748cd8SNickeau * @param \Doku_Renderer_xhtml $renderer 122137748cd8SNickeau * @param $position 122237748cd8SNickeau * @param $name 122337748cd8SNickeau */ 122437748cd8SNickeau public 122537748cd8SNickeau static function startSection($renderer, $position, $name) 122637748cd8SNickeau { 122737748cd8SNickeau 122837748cd8SNickeau 122937748cd8SNickeau if (empty($position)) { 123037748cd8SNickeau LogUtility::msg("The position for a start section should not be empty", LogUtility::LVL_MSG_ERROR, "support"); 123137748cd8SNickeau } 123237748cd8SNickeau if (empty($name)) { 123337748cd8SNickeau LogUtility::msg("The name for a start section should not be empty", LogUtility::LVL_MSG_ERROR, "support"); 123437748cd8SNickeau } 123537748cd8SNickeau 123637748cd8SNickeau /** 123737748cd8SNickeau * New Dokuwiki Version 123837748cd8SNickeau * for DokuWiki Greebo and more recent versions 123937748cd8SNickeau */ 124037748cd8SNickeau if (defined('SEC_EDIT_PATTERN')) { 124137748cd8SNickeau $renderer->startSectionEdit($position, array('target' => self::EDIT_SECTION_TARGET, 'name' => $name)); 124237748cd8SNickeau } else { 124337748cd8SNickeau /** 124437748cd8SNickeau * Old version 124537748cd8SNickeau */ 124637748cd8SNickeau /** @noinspection PhpParamsInspection */ 124737748cd8SNickeau $renderer->startSectionEdit($position, self::EDIT_SECTION_TARGET, $name); 124837748cd8SNickeau } 124937748cd8SNickeau } 125037748cd8SNickeau 125137748cd8SNickeau /** 125237748cd8SNickeau * Add an enter call to the stack 125337748cd8SNickeau * @param \Doku_Handler $handler 125437748cd8SNickeau * @param $tagName 125537748cd8SNickeau * @param array $callStackArray 125637748cd8SNickeau */ 125737748cd8SNickeau public 125837748cd8SNickeau static function addEnterCall( 125937748cd8SNickeau \Doku_Handler &$handler, 126037748cd8SNickeau $tagName, 126137748cd8SNickeau $callStackArray = array() 126237748cd8SNickeau ) 126337748cd8SNickeau { 126437748cd8SNickeau $pluginName = PluginUtility::getComponentName($tagName); 126537748cd8SNickeau $handler->addPluginCall( 126637748cd8SNickeau $pluginName, 126737748cd8SNickeau $callStackArray, 126837748cd8SNickeau DOKU_LEXER_ENTER, 126937748cd8SNickeau null, 127037748cd8SNickeau null 127137748cd8SNickeau ); 127237748cd8SNickeau } 127337748cd8SNickeau 127437748cd8SNickeau /** 127537748cd8SNickeau * Add an end call dynamically 127637748cd8SNickeau * @param \Doku_Handler $handler 127737748cd8SNickeau * @param $tagName 127837748cd8SNickeau * @param array $callStackArray 127937748cd8SNickeau */ 128037748cd8SNickeau public 128137748cd8SNickeau static function addEndCall(\Doku_Handler $handler, $tagName, $callStackArray = array()) 128237748cd8SNickeau { 128337748cd8SNickeau $pluginName = PluginUtility::getComponentName($tagName); 128437748cd8SNickeau $handler->addPluginCall( 128537748cd8SNickeau $pluginName, 128637748cd8SNickeau $callStackArray, 128737748cd8SNickeau DOKU_LEXER_END, 128837748cd8SNickeau null, 128937748cd8SNickeau null 129037748cd8SNickeau ); 129137748cd8SNickeau } 129237748cd8SNickeau 129337748cd8SNickeau /** 129437748cd8SNickeau * General Debug 129537748cd8SNickeau */ 129637748cd8SNickeau public 129737748cd8SNickeau static function isDebug() 129837748cd8SNickeau { 129937748cd8SNickeau global $conf; 130037748cd8SNickeau return $conf["allowdebug"] === 1; 130137748cd8SNickeau 130237748cd8SNickeau } 130337748cd8SNickeau 130437748cd8SNickeau /** 130537748cd8SNickeau * @return bool true if loaded, false otherwise 130637748cd8SNickeau * Strap is loaded only if this is the same version 130737748cd8SNickeau * to avoid function, class, or members that does not exist 130837748cd8SNickeau */ 130937748cd8SNickeau public 131037748cd8SNickeau static function loadStrapUtilityTemplateIfPresentAndSameVersion() 131137748cd8SNickeau { 131237748cd8SNickeau $templateUtilityFile = __DIR__ . '/../../../tpl/strap/class/TplUtility.php'; 131337748cd8SNickeau if (file_exists($templateUtilityFile)) { 131437748cd8SNickeau /** 131537748cd8SNickeau * Check the version 131637748cd8SNickeau */ 131737748cd8SNickeau $templateInfo = confToHash(__DIR__ . '/../../../tpl/strap/template.info.txt'); 131837748cd8SNickeau $templateVersion = $templateInfo['version']; 131937748cd8SNickeau $comboVersion = self::$INFO_PLUGIN['version']; 132037748cd8SNickeau if ($templateVersion != $comboVersion) { 132137748cd8SNickeau if ($comboVersion > $templateVersion) { 132237748cd8SNickeau LogUtility::msg("You should upgrade <a href=\"https://www.dokuwiki.org/template:strap\">strap</a> to the latest version to get a fully functional experience. The version of Combo is ($comboVersion) while the version of Strap is ($templateVersion)."); 132337748cd8SNickeau } else { 132437748cd8SNickeau LogUtility::msg("You should upgrade <a href=\"https://www.dokuwiki.org/plugin:combo\">combo</a> to the latest version to get a fully functional experience. The version of Combo is ($comboVersion) while the version of Strap is ($templateVersion)."); 132537748cd8SNickeau } 132637748cd8SNickeau return false; 132737748cd8SNickeau } else { 132837748cd8SNickeau /** @noinspection PhpIncludeInspection */ 132937748cd8SNickeau require_once($templateUtilityFile); 133037748cd8SNickeau return true; 133137748cd8SNickeau } 133237748cd8SNickeau } else { 133337748cd8SNickeau $level = LogUtility::LVL_MSG_DEBUG; 133437748cd8SNickeau if (defined('DOKU_UNITTEST')) { 133537748cd8SNickeau // fail 133637748cd8SNickeau $level = LogUtility::LVL_MSG_ERROR; 133737748cd8SNickeau } 133837748cd8SNickeau if (Site::getTemplate() != "strap") { 133937748cd8SNickeau LogUtility::msg("The strap template is not installed", $level); 134037748cd8SNickeau } else { 134137748cd8SNickeau LogUtility::msg("The file ($templateUtilityFile) was not found", $level); 134237748cd8SNickeau } 134337748cd8SNickeau return false; 134437748cd8SNickeau } 134537748cd8SNickeau } 134637748cd8SNickeau 134737748cd8SNickeau 134837748cd8SNickeau /** 134937748cd8SNickeau * 135037748cd8SNickeau * See also dev.md file 135137748cd8SNickeau */ 135237748cd8SNickeau public static function isDevOrTest() 135337748cd8SNickeau { 135437748cd8SNickeau if (self::isDev()) { 135537748cd8SNickeau return true; 135637748cd8SNickeau } 135737748cd8SNickeau return self::isTest(); 135837748cd8SNickeau } 135937748cd8SNickeau 136037748cd8SNickeau public static function isDev() 136137748cd8SNickeau { 136237748cd8SNickeau global $_SERVER; 136337748cd8SNickeau if ($_SERVER["REMOTE_ADDR"] == "127.0.0.1") { 136437748cd8SNickeau return true; 136537748cd8SNickeau } 136637748cd8SNickeau return false; 136737748cd8SNickeau } 136837748cd8SNickeau 136937748cd8SNickeau public static function getInstructions($markiCode) 137037748cd8SNickeau { 137137748cd8SNickeau return p_get_instructions($markiCode); 137237748cd8SNickeau } 137337748cd8SNickeau 137437748cd8SNickeau public static function getInstructionsWithoutRoot($markiCode) 137537748cd8SNickeau { 137637748cd8SNickeau return RenderUtility::getInstructionsAndStripPEventually($markiCode); 137737748cd8SNickeau } 137837748cd8SNickeau 137937748cd8SNickeau /** 138037748cd8SNickeau * Transform a text into a valid HTML id 138137748cd8SNickeau * @param $string 138237748cd8SNickeau * @return string 138337748cd8SNickeau */ 138437748cd8SNickeau public static function toHtmlId($string) 138537748cd8SNickeau { 138637748cd8SNickeau /** 138737748cd8SNickeau * sectionId calls cleanID 138837748cd8SNickeau * cleanID delete all things before a ':' 138937748cd8SNickeau * we do then the replace before to not 139037748cd8SNickeau * lost a minus '-' separator 139137748cd8SNickeau */ 139237748cd8SNickeau $string = str_replace(array(':', '.'), '', $string); 139337748cd8SNickeau return sectionID($string, $check); 139437748cd8SNickeau } 139537748cd8SNickeau 139637748cd8SNickeau public static function isTest() 139737748cd8SNickeau { 139837748cd8SNickeau return defined('DOKU_UNITTEST'); 139937748cd8SNickeau } 140037748cd8SNickeau 140137748cd8SNickeau 1402*c3437056SNickeau public static function getCacheManager(): CacheManager 140337748cd8SNickeau { 1404*c3437056SNickeau return CacheManager::getOrCreate(); 140537748cd8SNickeau } 140637748cd8SNickeau 140737748cd8SNickeau public static function getModeFromPluginName($name) 140837748cd8SNickeau { 140937748cd8SNickeau return "plugin_$name"; 141037748cd8SNickeau } 141137748cd8SNickeau 141237748cd8SNickeau public static function isCi(): bool 141337748cd8SNickeau { 141437748cd8SNickeau // https://docs.travis-ci.com/user/environment-variables/#default-environment-variables 141537748cd8SNickeau return getenv("CI") === "true"; 141637748cd8SNickeau } 141737748cd8SNickeau 141837748cd8SNickeau 141937748cd8SNickeau} 142037748cd8SNickeau 142137748cd8SNickeauPluginUtility::init(); 1422