Extension:SubPageList3

Introduction
The Wikiversity community voted overwhelmingly for a subpagelist extension. However Extension:SubPageList2 was declined by Mediawiki developers for technical reasons. The current extension simplifies and fixes the previous extension to meet criteria for implementation on Wikiversity. Generally there is nothing ambitious here. On the contrary this is supposed to be a small, reliable, sound and useful extension with no thrills and a modest but significant organisational value.

Need
Some wikis tend to create their content in clusters of pages rather than as individual articles (e.g. Wikibooks, Wikiversity), and when they do so, they typically use a lot of subpages. This creates an additional layer of organisational complexity, with a corresponding need to help users through this layer of complexity.

Previous versions

 * SubPageList1 was a very simple script which did the same as what you now do instead with.
 * SubPageList2 was a feature-rich enhancement of the above, described as follows: Sub Page List 2 is an extension that automaticaly 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.

This version

 * 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.

Difference between this extension and Special:prefixindex
Please see discussion on talk page.

History

 * SubPageList1 was written by User:Robchurch and is no longer available seems to have reappeared on SVN again recently. It was a very simple script which behaved much like the newer Special:Prefixindex (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).
 * A note on the SVN code says (correctly) that SubPageList1 was "Obsoleted by includable Special:Prefixindex".
 * SubPageList2 was an extension of the above by Schaelles, probably written for a non-Wikimedia project. Date: 2006.
 * A simplified variant was written by User:Karora in January 2008. See below for code.

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).

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.

Detailed list of changes from Extension:SubPageList2
Currently this is a list of all the bells and whistles in SubPageList2, with comments about their fate.

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.

Things changed

 * 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.

Outcomes of discussion on IRC on 26th Feb '08

 * 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)
 * Internationalisation. (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)

Things changed

 * Added internationalisation file and calls.
 * Added cache disabled call in constructor.
 * Changed: Werdna changed the way the namespace was detected (SVN version differs from code posted on Mediawiki).

Development notes for 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.

Development notes for version 1.04
PaulHat kindly submitted some code which addressed the "background issue" mentioned above.

Development notes for version 1.05
This revision follows Brion Vibbers 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.

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.

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 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
 * For inherited code: Martin Schaelles and Rob Church.
 * For coding help / bug reports / SVN uploads: Duesentrieb, FlyingParchment, Sayuri, PeterBlaise, JeLuF, Fungiblename, Werdna, Tim Starling, Splarka, Siebrand, PaulHat.
 * For encouragement: everyone at Wikiversity who wanted this extension.