Summary: Edit a page's title, description and other attributes using separate EditForm fields
Version: 2022-03-15
Prerequisites: PmWiki 2.2.x
Status: beta
Maintainer: Eemeli Aro
Categories: Editing, GUI
Download: editattr.phpΔ
Users: +6 (View / Edit)

Questions answered by this recipe

  • How can I add a separate edit form field for a page's title, description, or other attributes?
  • How can I add and edit a completely new page attribute, such as an introduction, notes, header/footer, etc.?


By default, each PmWiki page is stored not only with its text, but with some additional attributes or meta information as well, such as the page's title and description, the character set the page is saved in, and information about the last page edit. EditAttributes allows you to directly edit these attributes as well as adding your own.

EditAttributes is partly based on and partly duplicates the functionality of Mike Shanley's EditMore, which in turn is based on Waylan Limberg's EditTitle. Unlike those recipes, EditAttributes is easily customisable for completely new attributes.

To install this recipe:

  • download editattr.phpΔ to your cookbook directory
  • add the following to your config file, adjusted for your configuration:
$EditAttrFields = array(
  'title' => array(
    'attribute' => 1,
    'markup' => '(:title $1:)',
    'filter' => 'EditAttrAutofillTitle' ),
  'description' => array( 'attribute' => 1, 'markup' => '(:description $1:)' ),
  'keywords' => array( 'attribute' => 1, 'markup' => '(:keywords $1:)' )
if ( $action == 'edit' ) include_once("$FarmD/cookbook/editattr.php");


NOTE: The format of $EditAttrFields has changed substantially in version 2009-03-12.

EditAttributes is configured using an array $EditAttrFields, which defines the names and types of the editable page fields. Entries in the array have the format $name => array( $property => value, ... ), where each $property is one of the following strings:

'attribute' Is the field stored as a page attribute? Use a value greater than 1 to keep a history of the field's values.
'markup' If non-empty, this is the markup to read and add in the page text. For eg. the default (:title:) page directive you may use '(:title $1:)'. '$1' is replaced with the field value, with invalid characters corrected. For the full, raw value you may use '$0'. For more direct control, you may use array( $pat => $repl ) where $pat is a regular expression pattern to search for (not including the / delimiters) with one parenthetical subpattern and $repl is the string used for replacement.
'auth' The authentication level required to read or modify a field; defaults to 'edit'. Passwords and other fields editable using action=attr automatically require 'postattr' authentication.
'filter' The name of a function to verify or change field contents before posting a page.
'input' An array of attributes and values to apply to the HTML form field. For example, to make a field shorter you may use: array( 'size' => 40 ).

The example given above in the installation instructions sets up the page title, description and keywords to be stored both as a directive in the page text and as a separate page attribute; this is in fact the normal state of affairs for PmWiki. If using the above, you'll also need to add the following to Site.EditForm:

(:input e_title:)
(:input e_description:)
(:input e_keywords:)

If these are not present, editing and saving a page may clear these values. The general form for these input directives is (:input e_FIELDNAME:).

For another example, I currently use the following:

$EditAttrFields = array(
  'title' => array(
    'attribute' => 2,
    'markup' => array( '\(:title (.*?):\)' => '' ),
    'filter' => 'EditAttrAutofillTitle',
    'input' => array( 'tabindex' => 1 ) ),
  'description' => array(
    'attribute' => 2,
    'markup' => array( '\(:description (.*?):\)' => '' ),
    'input' => array( 'tabindex' => 2 ) )

The 2 value for 'attribute' means that if these fields change, that change is noted in the page history. The 'markup' mappings extract the (:title ...:) and (:description ...:) directives from the page text, but only saves them as page attributes since the replacement markup is blank. The 'input' array sets the edit fields' tabindex values to more useful values -- note that this last one requires a change to the $InputAttrs array in forms.php.

The title's 'filter', EditAttrAutofillTitle is a function that generates a default title if it's empty. This is disabled for eg. RecentChanges pages. To add to these rules, you may add an entry to the $EditAttrAutofillTitlePatterns array, which accepts the same format as the MatchPageNames function.


Effectively, this recipe is a byproduct of a partial thought towards implementing something like what Pm describes here — a way to keep information about users in page attributes. In order to be able to do that, we need a way of editing them; hence EditAttributes.

It is quite possible to define edit fields for already existing attributes such as page read or edit passwords, but viewing or editing these will require the same permissions as otherwise. Also, some attributes, such as those pertaining to the current modification, are overwritten by PageStore::write() when posting the page; hence modifying them is essentially useless.

If you want to require a field to be non-empty in order to save a page, set its 'filter' to 'EditAttrRequireNotEmpty'. For more complex actions, you may define your own functions in the same form as 'EditAttrAutofillTitle' and 'EditAttrRequireNotEmpty'.

Page markup is inserted to the end of a page, not the beginning. Doing it this ways means that an included page can't overwrite the current page's title with the normal page directive markup.

Accessing any new page attributes is for now left to the user, as this may vary significantly between use cases. For the simplest approach, you may use as a reference 'description', which has in pmwiki.php defined the following:

$FmtPV['$Description'] => '@$page["description"]'

Which sets up a page variable {$Description}.

Example: page text variable checkbox

The following allows you to toggle the value of the page text variable myPTV between '1' and '' using a checkbox.

on Site.EditForm: (:input e_myPTV:)

in config.php, before including editattr.php:

$EditAttrFields['myPTV'] = array(
  'markup' => '(:myPTV:$1:)',
  'input' => array(':html' => "<input type='checkbox' \$InputFormArgs />"));

Example: ctime

For a more complex example, the Bloge recipe uses EditAttributes to make the page ctime a user-modifiable field with the following. The text box will accept a variety of date/time expressions.

on Site.EditForm: (:input e_ctime:)

in config.php, before including editattr.php:

$EditAttrFields['ctime'] = array( 'attribute' => 2, 'filter' => 'BlogeFilterCtime' );
function BlogeFilterCtime($pagename, $fn, &$new) {
  global $Now, $MessagesFmt, $TimeFmt, $EnablePost;
  $ct = trim($new['ctime']);
  $t = ( empty($ct)
    ? $Now
    : preg_match('/^\d{9,}$/', $ct) )
      ? intval($ct)
      : strtotime($ct);
  if (!$t) {
    $t = $Now;
    $MessagesFmt[] = "<h3 class='wikimessage'>$[Error parsing time:] $ct</h3>";
  $new['ctime'] = $EnablePost ? $t : strftime($TimeFmt, $t);

Release Notes

  • 2022-03-28Δ — bugfix for PHP 8 compatibility (but still not fully compatible, see note below)
  • 2022-03-15Δ — update for PmWiki 2.3 (changed strftime to PSFT)
  • 2015-03-16Δ — update for PHP5.5 (fix EditAttrKeep(' being inserted). Additionally add support for ctime, checkbox defaults and html area
  • 2009-08-28Δ — bugfix: rm premature return on empty $EditAttrFields
  • 2009-07-30Δ — any markup within conditional markup is now ignored
  • 2009-06-01Δ — bugfix: title autofill was disabling templates
  • 2009-03-12Δ — new $EditAttrFields syntax, filter functions, user-definable authorization requirements
  • 2009-02-24Δ — bugfix: double-escaping symbols
  • 2009-02-18Δ — first public release
Note on Version 2022-03-28

This version works with PHP 8.0 but still has the warning "Deprecated: Function create_function() is deprecated" because it uses the PPRE function which is deprecated since PHP 7.2. You can use the cookbook PccfToPcfOverride to override this warnings, bit this results in other warnings from the PccfToPcfOverride script. For me it was a problem, that the instructions for PPRE in PmWiki.Functions have no example for defining a callback function for $GLOBALS[\'KPV\'][$m[1]] , which is used in editattr.php. Would be great if this can be solved in future. Siegfried Seibert

I'll look into it. UpdateMe --Petko

See Also



See discussion at EditAttributes-Talk

User notes +6: If you use, used or reviewed this recipe, you can add your name. These statistics appear in the Cookbook listings and will help newcomers browsing through the wiki.