Extension:SubPageList3

Introduction
SubPageList3 is a tag extension based on Extension:SubPageList2 for listing subpages of a parent page with critical fixes necessary to meet criteria requirements for use on Wikimedia projects. This is especially helpful on wikis which make extensive use of subpages to organize clusters of related pages (e.g. Wikibooks, Wikiversity).

Votes for activation on Wikimedia projects
The English and Greek Wikiversities have voted unanimously in favour of activation of this extension. See discussion and voting.

Installation

 * Download the zip file and extract the one PHP file from it.
 * Upload SubPageList3.php in to the extension directory.
 * Add the following lines at the end of your LocalSettings.php:

The &lt;splist&gt; tag
Simply place where you wish your subpage list to appear.

Attributes of the splist tag
Example with use of all available attributes.




 * Liststyle: default is unordered; values are ordered|unordered|bar. Toggles list between  and  lists. The bar value causes the list to align horizontally with &middot; symbols acting as delimiters (for bar lists rather than tree lists).
 * Sort: default is asc; values are asc|desc. Toggles list between ascending and descending sort order. By default, the tag sorts subpages in ascending alphabetical order; all sorting, however, is subject to hierarchical position - i.e. pages will always be subordinated to their parents; sorting is only among siblings.
 * Sortby: default is title; values are title|lastedit. Toggles list sort determinant between title and date of the last edit.
 * Showpath: default is no; values are no|notparent|full. Determines how the title of each page is displayed in the list. "No" means that only the subpage title (i.e. the bit after the last slash) is displayed. "Notparent" shows the full path without the top level. "Full" shows all levels in the page title name including the top level (e.g. "my page/my subpage/my subpage2").
 * Kidsonly: default is no; values are yes|no. If this is set to "yes", then only the first generation of subpages (i.e. the children but not the grandchildren) is displayed. This is especially useful if the liststyle is set to bar. It's also good if you just want a list rather than a tree.
 * Parent: by default the tag analyses the subpage system of its own page. However you can set the tag to analyse and display the subpage system of any other page on the wiki. Use local name format. E.g. "parent=Template:FOO" (with a namespace) or "parent=My Page" (in the main namespace). A common source of error is typing the page name incorrectly. The extension checks whether or not the page you name actually exists, and will report an error if it doesn't.
 * Showparent: default is no; values are yes|no. If this is set to "yes", then the page indicated by parent (above) will be inserted as the top level item in the list. If the list is a bulletted list, then this top level item will have a bullet and the rest of the list will be indented one level further than it would be otherwise.
 * Debug: you can switch debugging on by setting this option to 1; the debugging goes no further than reporting invalid input for the other options.

CSS formatting
The parser puts a  around the list with the class "subpagelist".

Acknowledgements
Thanks are due to the following, all of whom helped to degrees large and small. The bugs are all mine, though! Apologies to anyone I have forgotten - so many have helped that it is difficult to remember everyone. --McCormack


 * SubPageList1 was a very simple script written by User:Robchurch which did the same as what you can now do with (see the talk page discussion of the latter).
 * A note in the code of SubPageList2 says that the orginal version of the SubpageList extension... can produce a fatal error while using the element. No further information was given about this. However it might be that the following is meant: that the original SubPageList and SubPageList2 cannot be used together (probably because the tag and hook names weren't changed).
 * Another note on the SVN code says (correctly) that SubPageList1 was "Obsoleted by including Special:Prefixindex".
 * SubPageList2 was a feature-rich enhancement of the above written by Martin Schaelles, described as an extension that automatically creates a list of the subpages of a page. The dynamic created list will be created automatically on every edit of the page where the SubPageList element is given.
 * A simplified variant was written by User:Karora in January 2008. See below for code.
 * For coding help / bug reports / SVN uploads: Duesentrieb, FlyingParchment, Sayuri, PeterBlaise, JeLuF, Fungiblename, Werdna, Tim Starling, Splarka, Siebrand and PaulHat.
 * For encouragement: everyone at Wikiversity who wanted this extension.

Version Summary

 * Uses the tag to enter a list/menu of a subpage system.
 * The subpage system is that of the current page (by default), or of any specified page elsewhere on the wiki.
 * The subpage system can be displayed as an ordered or unordered indented list, or as a horizontal bar.
 * The subpage list is updated each time the page in which the tag is embedded is updated dynamically (i.e. every time the subpages change).

The most important changes are:


 * Bugfixes.
 * Removal of the preview mode and removal of associated caching of actual content of subpages, which considerably shortened and simplified the extension.
 * Generally bringing the other features into line with what would have been expected of a simple subpage list extension.
 * Code size cut from 21kb to 14kb.

Version 1.05
This revision follows Brion Vibber's code review.

Brion changed (revision 32559):
 * Remove PHP4-ism in call params
 * Work correctly if asked to list subpages of page titled "-1"

Comments from Brion:

Some fundamental issues which need to be fixed before any Wikimedia deployment:

Sorting:

The code causes an inefficient filesort operation by sorting on UPPER(page_title) instead of page_title. Depending on how smart the database is, that may be a non-issue (small result data sets) or it may be wildly inefficient, but it's a red flag.

More generally, note that the case-insensitive intention of this sort will fail on non-ASCII characters in MySQL 4 and default compat configurations, as the transformation applied at the DB won't be correct.

Recommend sorting simply on page_title, as elsewhere in the system (eg Special:Prefixindex).

Caching:

Currently the extension outright disables caching on any page using the tag. While this ensures that up-to-date page lists are displayed, it could make a site widely using it very expensive indeed -- the entire page, however large, needs to be reparsed on every view -- even under a load spike like a Slashdotting, where the same page is hit over and over.

To correctly handle cache updates, uses on a page should be registered at links-update time, and creation/deletion of a subpage can trigger update jobs for registered pages.

Changes made:


 * Now sorts on page_title instead of UPPER(page_title).
 * Removed the page decaching again.

Discussion notes:


 * Duesentrieb and Dantman have suggested the addition of a render dependency table, which tracks pages which may need cache disabling (purging) when other pages change.

Version 1.04
PaulHat kindly submitted some code which addressed the "background issue" mentioned above.

Version 1.03
PaulHat found a bug. When the was required to list the subpages of a page which had both a parent and children, and the "kidsonly" parameter was set to "yes", then the implode function in line 478 produced an error. The background to this is that the "kidsonly" parameter assumes that the splist tag will normally be applied to a top-level item only. In version 1.03, this bug has been fixed, but the background issue will remain on the wishlist for a bigger upgrade.

Version 1.02
Outcomes of discussion on IRC on 26th Feb '08:


 * Added cache disabled call in constructor (Tim/Werdna).
 * Discussion of namespace subpage disabling and the $wgNamespacesWithSubpages variable. The issue is that on some wikis the slash is used as part of page names rather than as the marker for an "official" subpage. The user won't see the difference, but the wiki does. Currently the extension sees page titles as the user does, not as the wiki does. Is this a good thing or a bad thing? Should a flag be available to switch the extension between two different modes in this respect? For example, while Wikiversity and Wikibooks can have real subpages in the main namespace, Wikipedia doesn't so that slashes can be used as part of article titles (but the User: namespace on WP nevertheless allowed real subpages). (Splarka) (See discussion on talk page)
 * 'Added Internationalization. (Werdna)
 * Documentation should probably draw attention to and distinguish from transclusion of stuff using code like this: ; what does the extension do to add value to this? (a lot, but explain). (Splarka) See discussion on talk page)
 * Changed: Werdna changed the way the namespace was detected (SVN version differs from code posted on MediaWiki.org).

Version 1.01

 * User:Sayuri went through the code with some minor tweaks, which have been adopted: corrected URL to extension; turned authors list into an array; removed closing ?> (PHP close tag); corrected copyright symbol.

Feedback from other developers
The following feedback was given about Extension:SubPageList2:

I've done a quick review of this extension: - Unused variables in several places, including variables that get filled with data using string operations (line 547) - The content of the subpages will be loaded even if no preview is  requested (lines 567ff). This costs a lot of ressources. - Odd code: if ( $this->debug || $this->debug == 1 ) { (line 276). The "|| $this->debug == 1" part is superfluous. Overall, I don't think that we should activate this code. JeLuF

To respond to this feedback, the current extension project was created and the changes below implemented.

Things changed

 * Improved use of $wgExtensionCredits as suggested by User:Peterblaise.
 * Corrected typo of array $conditions.
 * Corrected code error where $debug was always on.
 * Removed preview mode. This is a major feature removal. The old version could (allegedly) include previews of the subpages. This was considered far too ambitious and outside the current needs. This also removed a lot of the code which "JeLuF" (above) did not like.
 * Removed the $articlecontent array used for caching subpage previews (as well as a bunch of other variables) plus the code which cached subpage previews.
 * Removed restriction of subpage choice by category and namespace.
 * Removed options for limiting and ignoring certain subpages.
 * Renamed option "deepness" to "depth".
 * Renamed option "mode" to "liststyle".
 * Renamed the tag from "subpages" to "splist" (i.e. subpagelist).
 * Renamed classes and hooks to avoid any conflict with previous extension.
 * Changed default value of showpath attribute to no and changed value normal to full.
 * Renamed options "order" and "ordermethod" to "sort" and "sortby".
 * Added the critical feature whereby grandchildren (and further descendent levels) are indented properly to indicate their level of descendence. Previously this extension simply did a one-level bulleted list which indicated inheritance/descendence only by the use of paths in the text.
 * Replaced the deepness/depth option with some more useful (and simpler) toggles (kidsonly, showparent) because the original option didn't even come near to working properly.
 * Fixed a bunch of problems with namespaces.
 * Added a visible report to the output in the event of there being no subpages to list. Previously the white space gave the feeling of a malfunction.
 * Added a limit (200) to the number of displayable subpage titles after noting that invalid inputs for the parent option might end up extracting too much from the database.
 * Added some validity tests, including a page exists check, to the parent option, because otherwise malicious wiki editing could produce a database output error.
 * Replaced use of REGEXP with LIKE following advice from FlyingParchment.

Options in Extension:SubPageList2 which were retained, tested and repaired

 * Debug. Values: 0 = show errors; 1 = hide errors. Illogical. Documentation error, plus code error.
 * Deepness (now depth). Specifies how deep to go. Note bug report by Fungiblename. Completely crazy. Replaced with: kidsonly, showparent.
 * Mode (now liststyle). Remove the "preview" value and keep just the choice between numbered and bulleted lists.
 * Showpath: whether to show just page titles or the full path in the list.
 * Order (now sort): whether to sort subpages in ascending or descending order.
 * Ordermethod (now: sortby): whether to sort subpages by date or title.
 * Parent: used to choose the top level page in the nav. Had namespace issues.

Options in Extension:SubPageList2 which were axed

 * Category: was used to restrict selected subpages to those belonging to a specific category.
 * Count: maximum number of subpages to display.
 * Ignore: list of subpages to ignore.
 * Namespace: was used to restrict subpage selection by namespace.
 * Previewcount: used to determine how much of a subpage was previewed; as the preview feature is being removed, this is no longer needed.
 * Previewmode: ditto.
 * Headline: was an option for the preview mode.

MediaWiki versions tested

 * Environment #1: MediaWiki: 1.11.1 / PHP: 5.2.3 (cgi) / MySQL: 4.1.22
 * (internal; not accessible)
 * Environment #2: MediaWiki: 1.11.1 / PHP: 5.2.3 (cgi) / MySQL: 4.1.22
 * View some of the tests here: http://www.qedoc.org/en/index.php?title=Subpagelist_Extension
 * Environment #3: MediaWiki: 1.6.10 / PHP: 4.4.7 (cgi) / MySQL: 4.1.22
 * This extension does not, unfortunately, work with Mediawiki 1.6, nor is it likely any simple hack would help.
 * Environment #4: MediaWiki: 1.12alpha / PHP: 5.2.3 (cgi) / MySQL: 4.1.22
 * (internal; not accessible)

Things actually tested

 * Tested the following options and established that they appear to work as they should: sort, sortby, liststyle, showpath.
 * Tested (after fixing): parent option (especially with namespaces), kidsonly, showparent (replacements for the depth option).
 * Tested indentation ability up to great-great-grandchildren.
 * Tested namespace stuff more.
 * Tested putting the output results inside tables and formatted divs to see how well this works with attractive menu box templates.
 * Tested namespace stuff even more.
 * Tried exploiting vulnerabilities in the parent option and successfully produced database errors; then programmed safety mechanisms to prevent such exploitation.

Observations

 * The original documentation says that the subpage list is only updated when the page containing the tag is updated. In practice it was noted that sometimes this was true and sometimes not (i.e. sometimes the list appeared to update even when the page containing the tag had not been updated).
 * Probably a mirage.
 * This is ancient history. From version 1.02 Tim's suggestion to add cache disabling means that the extension really updates dynamically.
 * The parent attribute must have the namespace removed before it does anything.

Bugs

 * The entire way SubPageList2 deals with grandchildren and their descendents was unacceptably buggy.
 * Fixed in initial release.
 * There is a namespaces issue with the parent option if any namespace crossing is attempted. First, the parent option cannot be used with a namespace. Second, the subpagelist then assumes that all subpages are in the same namespace as the page in which the tag is embedded, not the namespace of the page given as the parent of the list.
 * Fixed in initial release.

Code

 * Code snippet from the original - of interest due to the different database call.
 * Code for SubPageList2 (TWO - the older version!). Formatted into a wiki box with colours to make code inspection easy and lazy.
 * Code for Karora Variant. Possibly very experimental. See information at User:Karora/ListSubPages.
 * Code for SubPageList3 (That would be this one).

Wishlist for future versions

 * Add options for showing extra data after each page in the list; e.g. page visits, last edit date, page size.
 * Option to watch all pages shown.
 * Use a render dependency table for dynamic updating of contents.