version=pmwiki-2.3.36 ordered=1 urlencoded=1 author=Petko charset=UTF-8 csum=Markup() pattern needs to have "/" as delimiters. (+48) name=PmWiki.Functions rev=205 targets=Cookbook.Functions,PmWiki.CustomMarkup,PmWiki.CustomActions,PmWiki.BasicVariables,PmWiki.LayoutVariables,PmWiki.Forms,PmWiki.SecurityVariables,Cookbook.PccfToPcfOverride,PmWiki.LinkVariables,PmWiki.OtherVariables,PmWiki.EditVariables,PmWiki.UploadVariables,PmWiki.Functions,PmWiki.Variables,PmWiki.Internationalizations,PmWiki.FmtPageName,PmWiki.MakeLink,PmWiki.ConditionalMarkup,PmWiki.Drafts,PmWiki.IncludeOtherPages,PmWiki.UpdatePage,Cookbook.MarkupExpressionSamples,Cookbook.ParseArgs,Category.PmWikiDeveloper,!PmWikiDeveloper text=(:Summary: How some of the functions in pmwiki.php work:)%0a(:Audience: admins (advanced) :)%0a%0aThis page describes some of the internal workings of PmWiki by explaining how some of the functions in @@pmwiki.php@@ work. For a more brief list/overview on functions useful to for instance cookbook writers, see Cookbook:Functions. %0a%0aTo use this functions you have to make sure that all relevant internal variables have been initialized correctly. See [[Custom Markup]] and [[(PmWiki:)Custom Actions]] for more information on how these functions are typically called via %25hlt php%25[@Markup()@] or [@$HandleActions[]@].%0a%0a!! [[#PSFT]] PSFT()%0a%0a%25hlt php%25[@PSFT($format, $timestamp=null, $locale=null, $tz=null)@]%0a%0aThe %25hlt php%25@@PSFT()@@ function (''PmWiki String Format Time'', added in 2.3.0) is intended to be a safe replacement for the very widely used PHP functions @@[[https://www.php.net/strftime|strftime()]]@@ and @@[[https://www.php.net/gmstrftime|gmtstrftime()]]@@ which became deprecated in PHP 8.1.%0a%0aUnlike %25hlt php%25@@strftime()@@, @@PSFT()@@ accepts 2 additional arguments @@$locale@@ and @@$tz@@, which allow to set a different language or timezone.%0a%0aPmWiki 2.3.0 uses this function in all cases where it previously used %25hlt php%25@@strftime()@@, including the %25pmhlt%25[@{(ftime)}@] Markup Expression. If your local customizations and recipes use %25hlt php%25@@strftime()@@, you should be able to safely replace all calls to @@strftime()@@ with @@PSFT()@@, without changing the arguments. Any calls to @@gmtstrftime($fmt, $stamp)@@ can be replaced with @@PSFT($fmt, $stamp, null, 'GMT')@@.%0a%0aThe old functions were deprecated by the PHP developers because they behaved inconsistently on different platforms, and were dependent on installed system locales (i.e. a language would only work if the system had its locale installed). The new function uses the PHP class [[https://www.php.net/manual/en/class.intldateformatter.php|IntlDateFormatter]] and should be better. Unfortunately, it is not always enabled by hosting providers. %0a%0aSo depending on your installation, a specific language may be available with %25hlt php%25@@strftime()@@ and/or with @@IntlDateFormatter@@.%0a%0aIn addition, some rarely used shortcut percent-formats [@%25c, %25x, %25X@] also behave inconsistently on different platforms, and the new formatter may show a slightly different output. You can always replace these shortcut formats with the full formats you require.%0a%0aFor these reasons, %25hlt php%25@@PSFT()@@ is currently a compromise, by default reusing @@strftime()@@ for PHP 8.0 or earlier. Updating your calls from @@strftime()@@ shouldn't cause any changes in your outputs.%0a%0aYou can set in @@config.php@@ the variable %25hlt php%25@@$EnableFTimeNew = 1;@@ for @@PSFT()@@ to try using @@IntlDateFormatter@@ before PHP 8.1. If @@IntlDateFormatter@@ is not available, it will show the month and day names in English. Check what works.%0a%0aSince the %25hlt php%25@@strftime()@@ function is deprecated, it is unlikely for it to add new formats. We have added 2 custom formats:%0a* [@%25o@] for the "ordinal suffix" of the date, as "st" in "January 1st". If @@IntlDateFormatter@@ is not available, it will show the suffix in English%0a* [@%25L@] for a human-readable timestamp of the format %25pmhlt%25[@@2022-09-25T11:49:08Z@]%25%25 which will be displayed formatted either as $TimeFmt or in the local time zone of the visitor, see $EnableLocalTimes.%0a%0a(:include MarkupExpressions#ftimeformats#ftimeformatsend:)%0a%0a>>frame%3c%3c%0aA difference between %25hlt php%25@@strftime($format, $stamp)@@ and @@PSFT($format, $stamp)@@ is how they interpret a false, empty or non-numeric @@$stamp@@ argument.%0a|| class=simpletable%0a||! @@$stamp@@ argument ||! @@strftime($format, $stamp)@@ ||! @@PSFT($format, $stamp)@@ ||%0a|| numeric || the stamp || the stamp ||%0a|| missing or ''null'' || current time || current time ||%0a|| ''false'' || 1970-01-01 || current time ||%0a|| "" (empty string) \\%0aother non-numeric || 1970-01-01 or ''false'' (older PHP versions) \\%0a ''Warning: TypeError'' (PHP 7.4+) || current time ||%0aFor PmWiki, it seemed reasonable to make empty strings and other non-numeric values default to the current time. If your %25hlt php%25@@$stamp@@ variable may be empty or ''false'', and your recipes rely on @@strftime()@@ returning "1970-01-01", you can cast the stamp to integer:%0a%25hlt php%25[@%0a PSFT($format, intval($stamp));%0a@]%0a>>%3c%3c%0a%0a%0a!! [[#pmtoken]] pmtoken()%0a%25hlt php%25[@pmtoken($check = 0, $abort = false)@]%0a%0aThe %25hlt php%25@@pmtoken()@@ function sets or checks a unique session identifier to be used in input forms, with the goal of preventing cross-site request forgeries (CSRF).%0a%0aCalling %25hlt php%25@@pmtoken()@@ or @@pmtoken(0)@@ will create a token if it doesn't exist, store it in the @@$_SESSION@@ array, and return it. It will also set the variables [@$FmtV['$TokenValue']@] which can be used in HTML templates and [@$InputValues['pmtoken']@] to be used in markup [[forms]], although it may be simpler to use %25pmhlt%25[@(:input pmtoken:)@] instead.%0a%0aThe name of the input element, by default 'pmtoken', can be changed by setting for example %25hlt php%25[@$FmtV['$TokenName'] = 'CSRFtoken';@].%0a%0aCalling %25hlt php%25@@pmtoken(1)@@ will check the @@$_POST['pmtoken']@@ value and will return true if it is valid.%0a%0aCalling %25hlt php%25@@pmtoken(2)@@ will check the @@$_GET['pmtoken']@@ value and will return true if it is valid.%0a%0aCalling %25hlt php%25@@pmtoken(1, true)@@ or @@pmtoken(2, true)@@ with a second truthy argument, and the token is invalid, will directly call @@Abort()@@ and exit.%0a%0a%0a!! [[#pmcrypt]] pmcrypt()%0a%25hlt php%25[@pmcrypt($password, $salt = null)@]%0a%0aThe %25hlt php%25@@pmcrypt()@@ function is intended to be a safe replacement for the [[https://www.php.net/crypt|PHP 5.6+ crypt() function]] without providing a $salt, which would raise a notice. If a salt is provided, crypt() is called to check an existing password. If a salt is not provided, [[https://www.php.net/password_hash|password_hash()]] will be called to create a cryptographically strong password hash.%0a%0a!! [[#pmsetcookie]] pmsetcookie()%0a%25hlt php%25[@pmsetcookie($name, $val="", $exp=0, $path="", $dom="", $secure=null, $httponly=null)@]%0a%0aThis function is intended as a replacement for [[https://www.php.net/setcookie|setcookie()]]. It will automatically set the $secure and $httponly arguments if they are not set by the caller function and if $EnableCookieSecure and $EnableCookieHTTPOnly are enabled.%0a%0a!![[#PCCF]] PCCF() %25red%25 Deprecated since PHP 7.2%25%25%0a%25hlt php%25[@PCCF($php_code, $callback_template='default', $callback_arguments = '$m')@] %0a%0aThe %25hlt php%25@@PCCF()@@ function (''PmWiki Create Callback Function'') can be used to create callback functions used with [[https://www.php.net/preg_replace_callback|preg_replace_callback]]. It is required for PHP 5.5, but will also work with earlier PHP versions.%0a%0aThe first argument is the PHP code to be evaluated. %0a%0aThe second argument (optional) is the callback template, a key from the global @@$CallbackFnTemplates@@ array. There are two templates that can be used by recipe authors: %0a* 'default' will pass @@$php_code@@ as a function code%0a* 'return' will wrap @@$php_code@@ like "@@return $php_code;@@" (since PmWiki 2.2.62)%0a%0aThe third argument (optional) is the argument of the callback function. Note that PmWiki uses the '$m' argument to pass the matches of a regular expression search, but your function can use other argument(s).%0a%0a%25hlt php%25@@PCCF()@@ will create an anonymous (lambda) callback function containing the supplied code, and will cache it. On subsequent calls with the same @@$php_code@@, @@PCCF()@@ will return the cached function name.%0a%0aSee the [[https://www.php.net/create_function | PHP create function]].%0a%0a>>font-style=italic%3c%3c%0aPHP 7.2 deprecates %25hlt php%25@@create_function()@@ and future versions will remove it. If you need to migrate older code that used @@PCCF()@@, you can usually write regular functions and pass the function name where you previously passed the result of PCCF(). For example, suppose you had a pattern like this:%0a-> %25hlt php%25@@'/(?%3c=^| )([a-z])/' => PCCF("return strtoupper(\$m[1]);"),@@%0a%0aFor PHP 7.2 compatibility, you can write a callback function:%0a-> %25hlt php%25@@function @@%25green%25my_callback%25hlt php%25@@($m) { return strtoupper($m[1]); }@@%0a%0athen change the pattern to look like this:%0a-> %25hlt php%25@@'/(?%3c=^| )([a-z])/' => '%25green%25my_callback%25%25',@@%0a%0aSee also: the recipe [[(Cookbook:)PccfToPcfOverride]] allows existing recipes to run on PHP 7 without causing deprecated @@create_function()@@ messages.%0a>>%3c%3c%0a%0a!![[#PPRA]] PPRA()%0a%25hlt php%25[@PPRA($array_search_replace, $string)@]%0a%0aThe %25hlt php%25@@PPRA()@@ function (''PmWiki Preg Replace Array'') can be used to perform a regular expression replacement with or without evaluation, for PHP 5.5 compatibility. %0a%0aSince PmWiki 2.2.56, PmWiki uses this function to process the following arrays: $MakePageNamePatterns, $FmtP, $QualifyPatterns, $ROEPatterns, $ROSPatterns, $SaveAttrPatterns, $MakeUploadNamePatterns. Any custom settings should continue to work for PHP 5.4 and earlier, but wikis running on PHP 5.5 may need to make a few changes.%0a%0aThe first argument contains the 'search'=>'replace' pairs, the second is the "haystack" string to be manipulated.%0a%0aThe 'replace' parts of the array can be strings or function names. If the 'replace' part is a callable function name, it will be called with the array of matches as a first argument via %25hlt php%25@@preg_replace_callback()@@. If not a callable function, a simple @@preg_replace()@@ will be performed.%0a%0aPreviously, PmWiki used such constructs:%0a-> %25hlt php%25@@$fmt = preg_replace(array_keys($FmtP), array_values($FmtP), $fmt);@@%0a%0aIt is now possible to use simply this:%0a-> %25hlt php%25@@$fmt = PPRA($FmtP, $fmt);@@%0a%0aNote that since PHP 5.5, the search patterns cannot have an /e evaluation flag. When creating the $array_search_replace array, before PHP 5.5 we could use something like (eg. for $MakePageNamePatterns):%0a-> %25hlt php%25@@'/(?%3c=^| )([a-z])/e' => "strtoupper('$1')",@@%0a%0aSince PHP 5.5, we should use this (will also work in PHP 5.4 and earlier):%0a-> %25hlt php%25@@'/(?%3c=^| )([a-z])/' => PCCF("return strtoupper(\$m[1]);"),@@%0a%0aNote that the @@/e@@ flag should be now omitted, instead of @@'$0', '$1', '$2',@@ we should use @@$m[0], $m[1], $m[2],@@ etc. in the replacement code, and there is no need to call @@PSS()@@ in the replacement code, as backslashes are not automatically added.%0a%0a>>font-style=italic%3c%3c%0aFor PHP 7.2 and newer, instead of using %25hlt php%25@@PCCF()@@ to create anonymous functions, we add a real function in our add-on, and then pass the function name as the pattern replacement (see example at [[#PCCF|PCCF]], which will also work on PHP 4 and 5):%0a-> %25hlt php%25@@'/(?%3c=^| )([a-z])/' => '%25green%25my_callback%25%25',@@%0a>>%3c%3c%0a%0a!![[#PPRE]] PPRE() %25red%25 Deprecated since PHP 7.2%25%25%0a%25hlt php%25[@PPRE($search_pattern, $replacement_code, $string)@]%0a%0aThe %25hlt php%25@@PPRE()@@ function (''PmWiki Preg Replace Evaluate'') can be used to perform a regular expression replacement with evaluation.%0a%0aSince PHP 5.5, the %25hlt php%25@@preg_replace()@@ function has deprecated the /e evaluation flag, and displays warnings when the flag is used. The @@PPRE()@@ function automatically creates a callback function with the replacement code and calls it.%0a%0aBefore PHP 5.5, it was possible to use such calls:%0a-> %25hlt php%25@@$fmt = preg_replace('/\\$([A-Z]\\w*Fmt)\\b/e','$GLOBALS["$1"]',$fmt);@@%0a%0aSince PHP 5.5, it is possible to replace the previous snippet with the following (also works before PHP 5.5):%0a-> %25hlt php%25@@$fmt = PPRE('@@%25green%25/\\$([A-Z]\\w*Fmt)\\b/%25hlt php%25@@','$GLOBALS[$m[1]]',$fmt);@@%0a%0aNote that the @@/e@@ flag should be now omitted, instead of @@'$0', '$1', '$2',@@ we should use @@$m[0], $m[1], $m[2],@@ etc. in the replacement code, and there is no need to call @@PSS()@@ in the replacement code, as backslashes are not automatically added.%0a%0a>>font-style=italic%3c%3c%0aFor PHP 7.2 and newer, calling this function will raise "deprecated" notices. You need to rewrite your code to use [[https://www.php.net/preg_replace_callback|preg_replace_callback]], by moving the code into real functions:%0a%0a-> %25hlt php%25@@$fmt = preg_replace_callback('@@%25green%25/\\$([A-Z]\\w*Fmt)\\b/%25hlt php%25@@', 'my_global_var_callback',$fmt);@@%0a-> %25hlt php%25@@function my_global_var_callback($m) { return $GLOBALS[$m[1]]; }@@%0a%0ainstead of using %25hlt php%25@@PCCF()@@ to create anonymous functions, we add a real function in our add-on, and then pass the function name as the pattern replacement (see example at [[#PCCF|PCCF]], which will also work on PHP 4 and 5):%0a=> %25hlt php%25@@'/(?%3c=^| )([a-z])/' => '%25green%25my_callback%25%25',@@%0a>>%3c%3c%0a%0a(:if false:)(:comment Needs review and may change:)%0a!![[#PRCB]] PRCB()%0a%25hlt php%25[@PRCB($pat, $repl, $subj, $vars=null, $limit=-1, &$count=null, $flags=0)@]%0a%0aThe %25hlt php%25@@PRCB()@@ function (''PmWiki Regex Replace Callback'') makes it simple to pass variables to a named callback function with [[https://php.net/preg_replace_callback|preg_replace_callback()]].%0a%0aIf you need to use preg_replace_callback() and pass some variables to the callback function, you can do something like:%0a%0a%25hlt php%25[@$result = PRCB($patern, 'my_callback', $subject, $pagename);@]%0a%0aThen your function will be called this way: %25hlt php%25[@my_callback($matches, $pagename);@]. You can pass multiple variables with an array.%0a%0aThe function can also be used without passing variables, just shorter than @@preg_replace_callback()@@:%0a%0a%25hlt php%25[@$result = PRCB($patern, 'my_callback', $subject);@]%0a%0a(:ifend:)%0a%0a!![[#Qualify]] Qualify()%0a%25hlt php%25[@Qualify($pagename, $text)@]%0a%0a%25hlt php%25@@Qualify()@@ applies $QualifyPatterns to convert relative links and references into absolute equivalents.%0aThis function is called by usual wiki markups that include text from other pages.%0aIt will rewrite links like %25pmhlt%25[@[[Page]]@] into [@[[Group/Page]]@], and page (text) variables like [@{$Title}@] into [@{Group.Page$Title}@]%0aso that they work the same way in the source page and in the including page.%0aSee also $QualifyPatterns and %25pmhlt%25@@[[({$Name}#)RetrieveAuthSection]]()@@.%0a%0a%0a!![[#PHSC]] PHSC()%0a%25hlt php%25[@PHSC($string_or_array, $flags=ENT_COMPAT, $encoding=null, $double_encode=true)@]%0a%0aThe %25hlt php%25@@PHSC()@@ function (''PmWiki HTML Special Characters'') is a replacement for the PHP function [[https://www.php.net/htmlspecialchars|htmlspecialchars]]. %0a%0aThe %25hlt php%25@@htmlspecialchars()@@ function was modified since PHP 5.4 in two ways: it now requires a valid string for the supplied encoding, and it changes the default encoding to UTF-8. This can cause sections of the page to become blank/empty on many sites using the ISO-8859-1 encoding without having set the third argument ($encoding) when calling @@htmlspecialchars()@@.%0a%0aThe %25hlt php%25@@PHSC()@@ function calls @@htmlspecialchars()@@ with an 8-bit encoding as third argument, whatever the encoding of the wiki (unless you supply an encoding). This way the string never contains invalid characters.%0a%0aIt should be safe for recipe developers to replace all calls to %25hlt php%25@@htmlspecialchars()@@ with calls to @@PHSC()@@. Only the first argument is required when calling @@PHSC()@@, although authors may wish to call @@PHSC($string_or_array, ENT_QUOTES)@@.%0a%0aUnlike %25hlt php%25@@htmlspecialchars()@@, the @@PHSC()@@ function can process arrays recursively (only the values are converted, not the keys of the array).%0a%0a!![[#PSS]] PSS()%0a%25hlt php%25[@PSS($string)@]%0a%0aThe %25hlt php%25@@PSS()@@ function (''PmWiki Strip Slashes'') removes the backslashes that are automatically inserted in front of quotation marks by the /e option of PHP's preg_replace function. @@PSS()@@ is%0amost commonly used in replacement arguments to @@Markup()@@, when the pattern specifies /e and one or more of the parenthesized subpatterns could contain a quote or backslash. %0a("PSS" stands for "PmWiki Strip Slashes".)%0a->From PM: PmWiki expects %25hlt php%25@@PSS()@@ to always occur inside of double-quoted strings and to contain single quoted strings internally. The reason for this is that we don't want the @@$1@@ or @@$2@@ to accidentally contain characters that would then be interpreted inside of the double-quoted string when the PSS is evaluated.%0a-->%25hlt php%25@@Markup('foo', 'inline', '/(something)/e', 'Foo(PSS("$1"))'); # wrong@@%0a-->%25hlt php%25@@Markup('foo', 'inline', '/(something)/e', "Foo(PSS('$1'))"); # right@@%0a%0a%25note%25 Note, the extra slashes are only added by %25hlt php%25@@preg_replace()@@ with an @@/e@@ modifier. The markup definitions with @@Markup_e()@@ do NOT need to use @@PSS()@@ in the replacement strings. The new-type markup definitions with @@Markup()@@ and a simple function name as a replacement do NOT need to use @@PSS()@@ inside the replacement function. If you migrate old markup rules to the new format, delete the @@PSS()@@ calls.%0a%0a!!! Example %25block notoc%25%0aThis is a fictitious example where %25hlt php%25@@PSS()@@ should be used.%0aLet us assume that you wish to define a directive %25pmhlt%25[@(:example:)@]%0asuch that %25pmhlt%25[@(:example "A horse":)@] results in the HTML%0a-> %25hlt html%25[@%3cdiv>"A horse"%3c/div>@].%0aHere is how the markup rule can be created:%0a-> %25hlt php%25[@%0aMarkup('example', 'directives',%0a '/\\(:example\\s(.*?):\\)/e',%0a "Keep('%3cdiv>'.PSS('$1').'%3c/div>')");%0a@]%0aWe need to use %25hlt php%25@@PSS()@@ around the '@@$1@@' because the matched text could contain quotation marks, and the @@/e@@ will add backslashes in front of them.%0a%0a!![[#stripmagic]] stripmagic()%0a%25hlt php%25[@stripmagic($string)@]%0a%0aThis function should be used when processing the contents of %25hlt php%25[@$_POST@] or [@$_GET@] variables when they could contain quotes or backslashes. It verifies [@get_magic_quotes()@], if true, strips the automatically inserted escapes from the string.%0a%0aThe function can process arrays recursively (only the values are processed).%0a%0a!![[#FmtPageName]] FmtPageName()%0a%0a%25hlt php%25[@FmtPageName($fmt, $pagename)@]%0a%0a[[#FmtPageName-desc]]Returns %25hlt php%25[@$fmt@], with @@$variable@@ and [=$[internationalisation]=] substitutions performed, under the assumption that the current page is [@pagename@]. See [[PmWiki.Variables]] for an (incomplete) list of available variables, [[PmWiki.Internationalizations]] for internationalisation. Security: not to be run on user-supplied data.%0a%0aThis is one of the major functions in PmWiki, see [[PmWiki.FmtPageName]] for%0alots of details.%0a%0a%0a!![[#Markup]] Markup()%0a%25hlt php%25[@Markup($name, $when, $pattern, $replace)@]%0a%0a[[#Markup-desc]]Adds a new markup to the conversion table. Described in greater detail at [[PmWiki.CustomMarkup]].%0a%0aThis function is used to insert translation rules into the PmWiki's translation engine. The arguments to %25hlt php%25[@Markup()@] are all strings, where:%0a%0a:%25hlt php%25[@$name@]: The string names the rule that is inserted. If a rule of the same name already exists, then this rule is ignored.%0a:%25hlt php%25[@$when@]: This string is used to control ''when'' a rule is to be applied relative to other rules. A specification of "[@%3cxyz@]" says to apply this rule prior to the rule named "xyz", while "[@>xyz@]" says to apply this rule after the rule "xyz". See [[(PmWiki:)CustomMarkup]] for more details on the order of rules.%0a:%25hlt php%25[@$pattern@]: This string is a [[regular expression -> https://www.php.net/preg_replace]] that is used by the translation engine to look for occurrences of this rule in the markup source. ''The pattern needs to use "/" as delimiters.''%0a:%25hlt php%25[@$replace@]: This string will replace the matched text when a match occurs, or the function name that will return the replacement text.%0a%0aAlso see: [[PmWiki.CustomMarkup]] and [[Cookbook:Functions#Markup]]%0a%0a!![[#MarkupToHTML]] MarkupToHTML()%0a%0a%25hlt php%25[@MarkupToHTML($pagename, $str)@]%0a%0a[[#MarkupToHTML-desc]] Converts the string %25hlt php%25[@$str@] containing PmWiki markup into the corresponding HTML code, assuming the current page is [@$pagename@].%0a%25hlt php%25@@MarkupToHTML()@@ replaces @@\n\n@@ sequences by @@%3c:vspace>@@ first thing when text is passed to it. Subsequently @@%3c:vspace>@@ is processed by the markup rules:%0a-> '@@!vspace@@' removes @@%3c:vspace>@@ after headings.%0a-> '@@%3cvspace>%3cp>@@' replaces @@%3c:vspace>%3cp>@@ with @@%3cp class='vspace'>@@%0a-> '@@%3cvspace>@@' replaces %3c:vspace> with @@%3cdiv class='vspace'>@@%0a-> and finally%0a-> '@@^%3c:@@' removes any remaining @@%3c:vspace>@@, mostly from restored [=[=]=escaped text=].%0a%0aAlso see: [[Cookbook:Functions#MarkupToHTML]]%0a%0a!![[#mkdirp]] mkdirp()%0a%25hlt php%25[@mkdirp($dir)@]%0a%0aThe function %25hlt php%25[@mkdirp($dir)@] creates a directory, [@$dir@], if it doesn't already exist, including any parent directories that might be needed. For each directory created, it checks that the permissions on the directory are sufficient to allow PmWiki scripts to read and write files in that directory. This includes checking for restrictions imposed by PHP's safe_mode setting. If [@mkdirp()@] is unable to successfully create a read/write directory, [@mkdirp()@] aborts with an error message telling the administrator the steps to take to either create @@$dir@@ manually or give PmWiki sufficient permissions to be able to do it.%0a%0a!![[#Lock]] Lock()%0a%25hlt php%25[@Lock(0)@]%0a%0aThis function is used to make sure only one instance of PmWiki is running when files are being written. It does not "lock pages" for editing.%0a%0aFrom a recipe, use:%0a* %25hlt php%25[@Lock(2);@] to acquire an ''exclusive'' lock, so that no other PHP processes can modify files. This can be used when your function is writing files on the server.%0a* %25hlt php%25[@Lock(1);@] to acquire a ''shared'' lock. This may be used when your function is reading files from the server, in case another process is writing them at the same time.%0a* %25hlt php%25[@Lock(0);@] to ''release'' a previous exclusive or shared lock. Use this immediately after your function finishes reading or writing the files.%0a%0aIf you don't release an acquired lock, it should be automatically released at the end of the processing.%0a%0a%0a!![[#MakeLink]] MakeLink()%0a%25hlt php%25[@MakeLink($pagename, $target, $txt, $suffix, $fmt)@]%0a%0aThe function %25hlt php%25[@MakeLink($pagename, $target, $txt, $suffix, $fmt)@] returns an html-formatted anchor link. Its arguments are as follows:%0a $pagename is the source page%0a $target is where the link should go%0a $txt is the value to use for '$LinkText' in the output %0a $suffix is any suffix string to be added to $txt%0a $fmt is a format string to use%0a%0aIf $txt is NULL or not specified, then it is automatically computed from $target.%0a%0aIf $fmt is NULL or not specified, then MakeLink uses the default%0aformat as specified by the type of link. For page links this%0ameans the $LinkPageExistsFmt and $LinkPageCreateFmt variables,%0afor intermap-style links it comes from either the $IMapLinkFmt%0aarray or from $UrlLinkFmt. Inside of the formatting strings,%0a$LinkUrl is replaced by the resolved url for the link, $LinkText%0ais replaced with the appropriate text, and $LinkAlt is replaced%0aby any "title" (alternate text) information associated with the%0alink.%0a%0aAlso see: [[PmWiki:MakeLink]] and [[Cookbook:Functions#MakeLink]]%0a%0a!![[#MakeUploadName]] MakeUploadName()%0a%25hlt php%25@@MakeUploadName($pagename, $x)@@%0a%0a%25hlt php%25@@MakeUploadName()@@ simply takes a string @@$x@@ (representing an attachment's%0aname) and converts it to a valid name by removing any unwanted characters.%0aIt also requires the name to begin and end with an alphanumeric character,%0aand as of 2.0.beta28 it forces any file extensions to lowercase.%0aThis function is defined in @@scripts/upload.php@@ and only used when uploads%0aare enabled.%0a%0a!![[#DownloadUrl]] DownloadUrl()%0a%25hlt php%25@@DownloadUrl($pagename, $path)@@%0a%0aThis function returns the public URL of an attached file. The arguments are as follow:%0a* $pagename - the currently processed page%0a* %25hlt php%25@@$path@@ - the file path, as in @@file.ext@@ or @@OtherPage/file.ext@@ or @@Group/OtherPage/file.ext@@%0a%0aIf the file doesn't exist, the function returns false. The global variable %25hlt php%25@@$FmtV['$LinkUpload']@@ contains the URL to the upload form, for a file with such a name to be attached. The global variable %25hlt php%25@@$FmtV['$LinkDownload']@@ contains the URL to the file, as if it were uploaded to the wiki.%0a%0aThe function calls [[#MakeUploadName|%25hlt php%25@@MakeUploadName()@@]] on the @@$path@@ argument so you don't need to do it before calling it.%0a%0aThe returned URL respects $UploadPrefixFmt and $EnableDirectDownload of the wiki.%0a%0a%0a!![[#SessionAuth]] SessionAuth()%0a%25hlt php%25[@SessionAuth($pagename, $auth=NULL)@]%0a%0a%25hlt php%25@@SessionAuth()@@ manages keeping authentication via cookie-sessions. Session contains every password or validated id and associated groups from previous calls. It adds elements passed by @@$auth@@ to session. It also writes every element saved in session to @@$AuthPw(passwords)@@ and @@$AuthList(ids and groups)@@.%0a%0a!![[#IsAuthorized]] IsAuthorized()%0a%25hlt php%25[@IsAuthorized($chal, $source, &$from)@]%0a%0a%25hlt php%25@@IsAuthorized()@@ takes a pageattributesstring (e. g. "id:user1 $1$Ff3w34HASH...") in @@$chal@@.%0a%0a%25hlt php%25@@$source@@ is simply returned and used for building the authcascade (pageattributes - groupattributes - @@$DefaultPassword@@).%0a%0a%25hlt php%25@@$from@@ will be returned if @@$chal@@ is empty, because it is not checked before calling @@IsAuthorized()@@, this is needed for the authcascade. %0a%25hlt php%25@@IsAuthorized()@@ returns an array with three values: @@$auth@@ @@1@@ - authenticated, @@0@@ - not authenticated, @@-1@@ - refused; @@$passwd@@; @@$source@@ from the parameter list.%0a%0a!![[#CondAuth]] CondAuth()%0a%25hlt php%25[@CondAuth($pagename, 'auth level')@]%0a%0a%25hlt php%25[@CondAuth()@]%25%25 implements the [[ConditionalMarkup]] for %25pmhlt%25[@(:if auth level:)@]%25%25. For instance %25hlt php%25[@ CondAuth($pagename,'edit')@]%25%25 is true if authorization level is 'edit'. Use inside local configuration files to build conditionals with a check of authorization level, similar to using %25pmhlt%25[@(:if auth level:)@]%25%25 on a wiki page.%0a%0aNote that %25hlt php%25@@CondAuth()@@ should be called after all authorization levels and passwords have been defined. For example, if you use it with [[Drafts]], you should include the @@draft.php@@ script before calling @@CondAuth()@@:%0a%25hlt php%25[@%0a $EnableDrafts = 1;%0a $DefaultPasswords['publish'] = pmcrypt('secret');%0a include_once("$FarmD/scripts/draft.php");%0a if (! CondAuth($pagename, 'edit')) { /* whatever */ }%0a@]%0aBest is to use %25hlt php%25@@CondAuth()@@ near the bottom of your @@config.php@@ script.%0a%0a!! [[#RetrieveAuthPage]] RetrieveAuthPage()%0a%25hlt php%25@@RetrieveAuthPage($pagename, $level, $authprompt=true, $since=0)@@%0a%0aPm words as said in https://www.pmwiki.org/pipermail/pmwiki-users/2005-April/012804.html %0awhere:%0a%0a $pagename - name of page to be read%0a $level - authorization level required (read/edit/auth/upload)%0a $authprompt - true if user should be prompted for a password if needed%0a $since - how much of the page history to read%0a 0 == read entire page including all of history%0a READPAGE_CURRENT == read page without loading history%0a timestamp == read history only back through timestamp%0a%0aThe @@$since@@ parameter allows PmWiki to stop reading from a page file%0aas soon as it has whatever information is needed -- i.e., if an operation%0asuch as browsing isn't going to need the page's history, then specifying%0aREADPAGE_CURRENT can result in a much faster loading time. (This can be %0aespecially important for things such as searching and page listings.)%0aHowever, if combined with %25hlt php%25@@UpdatePage()@@, the updated page will have no history.%0a%0aUse e.g. %25hlt php%25[@$page = @RetrieveAuthPage('Main.MyPage', 'read')@] to obtain a page object that contains all the information of the correspondent file in separate keys, e.g. [@$page['text']@] will contain a string with the current wiki markup of Main.MyPage. Use this generally in preference to the alternative function [@ReadPage($pagename, $since=0)@] since it respects the authorisation of the user, i.e. it checks the authorisation level before loading the page, or it can be set to do so. [@ReadPage()@] reads a page regardless of permission.%0a%0aPassing 'ALWAYS' as the authorization level (instead of 'read', 'edit', etc.) will cause %25hlt php%25@@RetrieveAuthPage()@@ to always read and return the page, even if it happens to be protected by a read password.%0a%0a%0a!! [[#RetrieveAuthSection]] RetrieveAuthSection()%0a%25hlt php%25@@RetrieveAuthSection($pagename, $pagesection, $list=NULL, $auth='read')@@%0a%0a%25hlt php%25@@RetrieveAuthSection()@@ extracts a section of text from a page. If @@$pagesection@@ starts with anything other than '@@#@@', the text before the first '@@#@@' (or all of it, if there is no '@@#@@') identifies the page to extract text from. Otherwise @@RetrieveAuthSection()@@ looks in the pages given by @@$list@@ (should be an array), or in @@$pagename@@ if @@$list@@ is not specified. %0a* The selected page is placed in the global @@$RASPageName@@ variable. %0a* The caller is responsible for calling %25hlt php%25@@Qualify()@@ as needed, i.e. if you need to control how unqualified page and variable names shall be resolved.%0a** To have them act as in the original text, let %25hlt php%25@@Qualify()@@ resolve them relative to the source page.%0a** If the imported text was not meant as wikitext but as some other kind of markup that might happen to contain double pairs of square brackets, (:comment %3c-- not: pairs of 〚double square brackets〛 = U+301A/U+301B:) or dollar signs inside curly brackets, you probably don't want to %25hlt php%25@@Qualify()@@ them. If you output them into wikitext, you'll probably need to @@Keep()@@ the text (:comment %3c-- translators: conceptually this means to have Keep() pack the text in a container that marks it as "final".:) (in case of HTML, XML, RSS or similar output, @@PHSC()@@ first!), to prevent later stages of processing from interpreting the apparent wiki markups in context of the target page.%0a** If your code produces wikitext for an auxiliary page that is meant to be included by another page higher up in the inclusion chain, and want links and variables to work as if they were in the auxiliary page, use the auxiliary page's "GroupName.PageName" as the $pagename argument for %25hlt php%25@@Qualify()@@.%0a%0aProvides a way to limit the array that is returned by ReadPage, so that it only pulls the content up to a specific section marker. For example, pulling from start of page to '##blogend':%0a->%25hlt php%25[@%0afunction FeedText($pagename, &$page, $tag) {%0a $text = RetrieveAuthSection($pagename, '##blogend');%0a $content = MarkupToHTML($pagename, $text);%0a return "%3c$tag>%3c![CDATA[$content]]>%3c/$tag>";%0a}%0a@]%0a%0aThe '##blogend' argument says to read from the beginning of the page to just before the line containing the [[#blogend]] marker. See%0a[[PmWiki:IncludeOtherPages | IncludeOtherPages]] for more information about the section specifications.%0a%0aThis version won't read text from pages that are read-protected; if you want to get text even from read-protected pages, then %0a->%25hlt php%25[@%0a $text = RetrieveAuthSection($pagename, '##blogend', NULL, 'ALWAYS');%0a@]%0a%0a%0a!! [[#UpdatePage]] UpdatePage()%0a%25hlt php%25@@UpdatePage($pagename, $old (page object), $new (page object));@@%0a%0a''[[PmWiki:UpdatePage|More Technical Notes]]''%0a%0a%25hlt php%25[@UpdatePage()@] allows cookbook recipes to mimic the behavior of editing wiki pages via the browser. Internally, PmWiki does several housekeeping tasks which are accessible via this function (preserving history/diff information, updating page revision numbers, updating RecentChanges pages, sending email notifications, etc._%0a* "Page object" refers to an array pulled from %25hlt php%25[@RetrieveAuthPage($pagename, $level, $authprompt=true, $since=0);@] (preferred), or [@ReadPage($pagename); @] (disregards page security). Note that @@$new['text']@@ should contain all page data for the new version of the page. %0a* If a page doesn't exist, %25hlt php%25@@UpdatePage()@@ will attempt to create it.%0a* Ignoring @@$old@@ (e.g. %25hlt php%25[@UpdatePage($pagename, '', $new);@]) will erase all historical page data---a ''tabula rasa''.%0a** If you retrieved @@$old@@ using %25hlt php%25@@RetrieveAuthPage($pagename,$auth,$prompt,READPAGE_CURRENT)@@ and set @@$new=$old@@, then @@UpdatePage()@@ will also erase all historical data%0a%25hlt php%25@@UpdatePage()@@ cannot be called directly from @@config.php@@ because there are necessary initializations which occur later in @@pmwiki.php@@. It is not enough to just load @@stdconfig.php@@. If you want to use @@UpdatePage()@@ you will need to do it within a [[PmWiki:CustomMarkup | custom markup]], a [[Cookbook:MarkupExpressionSamples | custom markup expression]], or a [[PmWiki:CustomActions | custom action]].%0a%0a%0a!! [[#InsertEditFunction]] InsertEditFunction()%0a%25hlt php%25@@InsertEditFunction($newfn, $where='%3cPostPage')@@%0a%0aThis function makes it easy for recipe authors to insert a custom function in a specific position of the processing, see $EditFunctions and [[#UpdatePage|UpdatePage()]]. %0a%0aThe first argument is the name of the new function.%0a%0aThe second argument is the position where to place the new function, related to other edit functions? It can be:%0a* @@"%3c"@@ at the start, before the first edit function%0a* @@">"@@ at the end, after the last edit function%0a* @@"%3cExistingEditFunction"@@ before a specified edit function%0a* @@">ExistingEditFunction"@@ after a specified edit function%0a%0aThe function will return ''true'' on success, and ''false'' on failure (when the specified position or existing function was not recognized).%0a%0a!! [[#DisableSkinParts]] DisableSkinParts()%0a%25hlt php%25@@DisableSkinParts('parts to disable');@@%0a%0aThis function allows easy disabling of the skin sections header, footer, title, actions, and sidebars, like the corresponding directives %25pmhlt%25@@[=(:notitle:) (:noleft:)=]@@ etc. In your function, use something like:%0a->%25hlt php%25[@%0a DisableSkinParts('Left Header Footer Action Title');%0a@]%0a%0a!! [[#ParseArgs]] ParseArgs()%0aSee Cookbook:ParseArgs. %0a%0a!! [[#Redirect]] Redirect()%0a%0a!! [[#PageIndexTerms]] PageIndexTerms()%0a%0a!! [[#AsSpaced]] AsSpacedUTF8(), AsSpaced()%0a>>hlt php%3c%3c%0a@@AsSpaced()@@ is declared in @@pmwiki.php@@ \\%0a@@AsSpaced()@@ converts a string with WikiWords into a spaced version of that string.%0aIt can be overridden via $AsSpacedFunction, as it is in @@AsSpacedUTF8()@@. \\%0a@@AsSpacedUTF8()@@ is declared in the @@xlpage-utf-8.php@@ script.%0a>>%3c%3c%0a%0aCategories: [[!PmWiki Developer]] time=1724101330