Views
YAMBE Code
From Shadowfax
Contents |
Notes on Stability
YAMBE works on my site (as you can see above). Version (0.1.5) has been tested and is stable on MediaWiki 1.13.1, 1.14.0 and 1.15.0 on installations using the traditional wiki URLs and short URLs.
Version 0.2.0 fixed an impending issue with MediaWiki 1.16.0 and later. It has been tested and appears stable on 1.15.0, 1.16.0 and the alpha release of 1.17.0 . There is no reason to assume it should not also work with 1.13.0 and 1.14.0, however, the previous stable version (0.1.5) is retained on this site just in case.
If you do encounter any problems please comment below and I will attempt to address them.
Yambe ChangeLog and To Do List
Configuration
There are five variables in the YAMBE code which can be set to configure the way that YAMBE behaves on your system. These are shown below:
//Some global config declarations // where to split the URL to find page name. Usually either /index.php/ or /wiki/ $URLSplit = "/index.php/"; $bcDelim = " > "; // Character to mark the stages of the breadcrumb? $maxCountBack = 5; // Maximum number of links in breadcrumb $overflowPre = "[...]"; // Prefix if breadcrumb is longer than $maxCountBack links $selfLink = false; // Set true if last page in breadcrumb should be a link
$URLSplit
This is the most important of the four. It should be set to the element which divides your site URL from your wiki page name. In the following example $URLSplit should be set to "/thisbit/"
http://www.mysite.com/thisbit/MyPage
In the default wiki installation the URLSplit is /index.php/. Where you are using friendly URLs this is often changed to /wiki/
$bcDelim
This is the string used to break up elements of the breadcrumb. It allows you to configure what the breadcrumb looks like. The default is to use the greater than chevron, but this can be changed to whatever you need.
$maxCountBack
This is how many elements the breadcrumb should show. It stops YAMBE from looping back over too many pages. Once YAMBE reaches this limit it stops building the breadcrumb and shows the overflow prefix.
$overflowPre
The overflow prefix that YAMBE puts in front of the breadcrumb when the number of pages in the breadcrumb exceeds $maxCountBack.
$selfLink
Set this to true if the last item on the breadcrumb should be a link, otherwise false.
CSS Styles
Yambe encloses the breadcrumb in a div with the id yambe. This can be used to configure the breadcrumb style in the CSS.
The Code
Add the following to LocalSettings.php
require_once ('extensions/yambe.php');
Save the following as yambe.php in MediaWiki extensions directory and edit the global config declarations to fit your wiki.
<?php /** * Yet Another MediaWiki Breadcrumb Extension (Yambe) * For documentation, please see http://shadowfax.org.uk/wiki/YAMBE * * @ingroup Extensions * @author Ian Coleman * @version 0.2.2 */ define('YAMBE_VERSION','0.2.2, 2011-08-29'); //Extension credits that show up on Special:Version $wgExtensionCredits['parserhook'][] = array( 'name' => 'YAMBE Hierarchical Breadcrumb', 'url' => 'http://shadowfax.org.uk/wiki/YAMBE_Code', 'version' => YAMBE_VERSION, 'author' => '[http://shadowfax.org.uk/wiki Ian Coleman]', 'description' => 'Parser hook to show Breadcumb on MediaWiki.' ); //Some global config declarations // where to split the URL to find page name. Usually either /index.php/ or /wiki/ $URLSplit = "/index.php/"; $bcDelim = " > "; // Character to mark the stages of the breadcrumb? $maxCountBack = 5; // Maximum number of links in breadcrumb $overflowPre = "[...]"; // Prefix if breadcrumb is longer than $maxCountBack links $selfLink = false; //Set up the hooks $wgHooks['EditFormPreloadText'][] = array('yambeSetParent'); // Avoid unstubbing $wgParser on setHook() too early on modern (1.12+) MW versions, as // per r35980 if ( defined( 'MW_SUPPORTS_PARSERFIRSTCALLINIT' ) ) { $wgHooks['ParserFirstCallInit'][] = 'yambeInit'; } else { $wgExtensionFunctions[] = 'yambeInit'; } function yambeInit(){ global $wgParser; $wgParser->setHook ( 'yambe:breadcrumb', 'yambeBreadcrumb' ); return true; } // Function to build the breadcrumb function yambeBreadcrumb ($data, $args) { global $wgTitle, $wgParser; global $bcDelim, $maxCountBack, $overflowPre, $selfLink; $wgParser->disableCache(); // Grab the self argument if it exists if (isset($args['self'])) $yambeSelf = $args['self']; else $yambeSelf = $wgTitle->getText(); // Breadcrumb is built in reverse and ends with this rather gratuitous self-link if ($selfLink) $breadcrumb = linkFromText($wgTitle->getText(),$yambeSelf,$wgTitle->getNamespace()); else $breadcrumb = $yambeSelf; $cur = str_replace(" ", "_", ($wgTitle->getText())); // Store the current link details to prevent circular references if ($wgTitle->getNsText() == "Main") $bcList[$cur] = ""; else $bcList[$cur] = $wgTitle->getNsText(); if ($data!="") { $cont = true; $count = 2; // because by first check, breadcrumb will have 2 elements! do { // Grab the parent information from the tag $parent = explode("|",$data); $page = splitName(trim($parent[0])); // Allow for use of only the parent page, no display text if(count($parent) < 2) $parent[1] = ""; // Check link not already in stored in list to prevent circular references if (array_key_exists($page['title'],$bcList)) if ($bcList[$page['title']] == $page['namespace']) $cont = false; if ($cont) { // Store the current link details to prevent circular references $bcList[str_replace(" ", "_",$page['title'])] = $page['namespace']; // make a url from the parent $url = yambeMakeURL($page, trim($parent[1])); // And if valid add to the front of the breadcrumb if ($url != "") { $breadcrumb = $url . $bcDelim . $breadcrumb; // Get the next parent from the database $par = getTagFromParent($page['title'], $page['namespaceid']); // Check to see if we've tracked back too far if ($count >= $maxCountBack) { $cont = false; if ($par['data'] != "") $breadcrumb = $overflowPre . $bcDelim . $breadcrumb; } else { $page['title'] = str_replace(" ", "_", $page['title']); $data = $par['data']; if ($data == "") $cont = false; } } } $count++; } while ($cont); // Loop back to get next parent } // Encapsulate the final breadcrumb in its div and send it back to the parser return "<div id='yambe'>$breadcrumb</div>\n"; } // Function to get namespace id from name function getNamespaceID($namespace) { if ($namespace == "") return 0; else { $ns = new MWNamespace(); return $ns->getCanonicalIndex(trim(strtolower($namespace))); } } // Function to build a url from text function linkFromText($page, $displayText, $nsID=0) { global $wgUser; $skin = $wgUser->getSkin(); $title = Title::newFromText (trim($page), $nsID); if (!is_null($title)) return $skin->makeKnownLinkObj($title, $displayText, ""); else return ""; } function pageExists($page, $nsID=0) { $page = str_replace(" ", "_", $page); $dbr = wfGetDB( DB_SLAVE ); if ($dbr->selectField( 'page', 'page_id', array("page_title" => $page, "page_namespace" => $nsID), __METHOD__ ) == "") return false; else return true; } // Function checks that the parent page exists and if so builds a link to it function yambeMakeURL($page, $display) { if (pageExists($page['title'],$page['namespaceid'])) return linkFromText($page['title'],$display,$page['namespaceid']); else return ""; } // Get the parents tag function getTagFromParent($pgName, $ns = 0) { $par['data']= ""; $par['exists']= false; $par['self']=""; $dbr = wfGetDB( DB_SLAVE ); $pgName = str_replace(" ", "_", $pgName); $res = $dbr->select(array ("revision", "text", "page",), "old_text", array( "page_title" =>$pgName, "page_namespace" => $ns), __METHOD__, array ("ORDER BY"=>"rev_id desc limit 1"), array("text" => array ("LEFT JOIN", "old_id=rev_text_id" ), "revision" => array( 'LEFT JOIN', 'rev_page=page_id'))); // Check to see if the query worked if ($res) { if ($dbr->numRows( $res) > 0) { // We've got the parent text. Now locate it's parent tag $row = $dbr->fetchRow( $res ); $text = $row["old_text"]; $dbr->freeResult( $res ); $par = yambeUnpackTag ($text); } } return $par; } function splitName($in) { if (substr_count($in,":")) { // Parent name includes Namespace - grab the page name out for display element $fullName = explode (":", $in); $page['title'] = str_replace(" ", "_", $fullName[1]); $page['namespace'] = $fullName[0]; $page['namespaceid'] = getNamespaceID($fullName[0]); } else { $page['title'] = str_replace(" ", "_", $in); $page['namespace'] = ""; $page['namespaceid'] = 0; } return $page; } // Set up the breadcrumb link in a new page function yambeSetParent(&$textbox, &$title) { global $URLSplit; $parent = explode($URLSplit,$_SERVER['HTTP_REFERER']); // If the code breaks on this line check declaration of $URLSplit on line 23 matches your wiki $page = splitName($parent[1]); $par = getTagFromParent($page['title'],$page['namespaceid']); if ($par['exists']) { if ($par['self'] != "") $display = $par['self']; else $display = str_replace("_", " ", $page['title']); $textbox = "<yambe:breadcrumb>$parent[1]|$display</yambe:breadcrumb>"; } return true; } // Bit of a kludge to get data and arguments from a yambe tag function yambeUnpackTag ($text) { $ret['exists']=false; $ret['data']= ""; $ret['self']= ""; $end = false; // Find the opening tag in the supplied text $start = strpos($text,"<yambe:breadcrumb"); // Find the end of the tag // Grab it and convert <yambe_breadcrumb> because simplexml doesn't like <yambe:breadcrumb> if ($start !== false) { $end = strpos($text,"</yambe:breadcrumb>", $start); if ($end !== false) $tag = substr($text, $start, $end-$start+19); else { $end = strpos($text,"/>", $start); if ($end !== false) $tag = substr($text, $start, $end-$start+2); } if ($end !== false) { $tag = str_replace("yambe:breadcrumb", "yambe_breadcrumb", $tag); // encapsulate in standalone XML doc $xmlstr = "<?xml version='1.0' standalone='yes'?><root>$tag</root>"; $xml = new SimpleXMLElement($xmlstr); // And read the data out of it $ret['self'] = $xml->yambe_breadcrumb['self']; $ret['data'] = $xml->yambe_breadcrumb[0]; $ret['exists'] = true; } } return $ret; } ?>
To kick things off enter a yambe tag in the root page of your hierarchy. Because this is the root page it has no parent so the data element of the tag is blank
<yambe:breadcrumb />
The normal form of the yambe tags is:
<yambe:breadcrumb>Page Title|Display Text for Breadcrumb</yambe:breadcrumb>
As of 0.2.1 the Display Text for Breadcrumb can be omitted (Thanks to Chris Cauthen for suggesting this) eg
<yambe:breadcrumb>Page Title</yambe:breadcrumb>
Tags are automatically produced when creating pages under pages that are already tagged, and the display text defaults to the page title.
Leave your comment
Comments
Dec 16 2010 2:52 pm
i have an error:
Notice: Undefined offset: 1 in /www/htdocs/SomeNumbers/wiki/extensions/yambe.php on line 230
Dec 07 2010 1:48 am
Given: Main Page > Page AAA > BBB (with all pages having the yambe tag and they are working).
I renamed "PAGE AAA" to "PAGE A" (officially move in mediawiki).
I get "Page A > BBB" since the parent name in the yambe tag did not get changed. But I get and undefined index "data" on line 111. I took a look and $ret is not initialised with 'data' or 'self'. Once I initialised $ret I then proceeded to edit all the pages and change the parent. Not related to the PHP error, maybe there is a way to put out something to remind the user that the parent lookup failed Like: ERR > PAGE A > BBB (Just a thought)
Nov 02 2010 7:44 pm
Oct 15 2010 9:00 am
So I made this small change to remove the error and make sure the title was set correctly:
In function: yambeBreadcrumb
Line: 77 just after "$page = splitName(trim($parent[0]));
I added the following:
// Allow for use of only the parent page, no display text
if( count($parent) < 2 )
{
$parent[1] = $page['title'];
}
You may want to require the second parameter, but just in case it doesn't matter, I thought I would share what I found.
Thanks Again!
Oct 15 2010 2:57 am
Oct 01 2010 8:06 am
Sep 29 2010 8:18 pm
Mar 31 2010 11:34 pm
Mar 31 2010 10:14 am
Mar 31 2010 8:47 am
Mar 31 2010 7:15 am
Mar 30 2010 1:26 pm
Mar 30 2010 11:46 am
I've not used YAMBE with the FCK Editor. My guess is that the FCK Editor extension also overrides the EditFormPreloadText hook and this is taking precedence over Yambe. If that is the case it should be a relatively simple matter of getting the FCK editor's hook to call yambeSetParent. I'll take a quick look at the FCK editor extension later on today and see if this is the case. Hope this makes sense.
Mar 23 2010 11:06 am
Mar 23 2010 10:35 am