https://www.mediawiki.org/wiki/Special:Code/MediaWiki/113252

Revision: 113252
Author:   netbrain
Date:     2012-03-07 17:31:29 +0000 (Wed, 07 Mar 2012)
Log Message:
-----------
initial import of SideBarMenu wikimedia extension

Modified Paths:
--------------
    trunk/extensions/SideBarMenu/README

Added Paths:
-----------
    trunk/extensions/SideBarMenu/SideBarMenu.body.php
    trunk/extensions/SideBarMenu/SideBarMenu.i18n.php
    trunk/extensions/SideBarMenu/SideBarMenu.php
    trunk/extensions/SideBarMenu/includes/
    trunk/extensions/SideBarMenu/includes/MenuItem.php
    trunk/extensions/SideBarMenu/includes/MenuParser.php
    trunk/extensions/SideBarMenu/test/
    trunk/extensions/SideBarMenu/test/MenuItemTest.php
    trunk/extensions/SideBarMenu/test/MenuParserTest.php

Modified: trunk/extensions/SideBarMenu/README
===================================================================
--- trunk/extensions/SideBarMenu/README 2012-03-07 17:31:18 UTC (rev 113251)
+++ trunk/extensions/SideBarMenu/README 2012-03-07 17:31:29 UTC (rev 113252)
@@ -0,0 +1,4 @@
+== INSTALL ==
+1. Copy SideBarMenu to /path/to/mediawiki/extension/
+2. append "require_once( "$IP/extensions/SideBarMenu/SideBarMenu.php" );" to 
LocalSettings.php
+

Copied: trunk/extensions/SideBarMenu/SideBarMenu.body.php (from rev 113251, 
trunk/extensions/SideBarMenu/README)
===================================================================
Copied: trunk/extensions/SideBarMenu/SideBarMenu.i18n.php (from rev 113251, 
trunk/extensions/SideBarMenu/README)
===================================================================
Added: trunk/extensions/SideBarMenu/SideBarMenu.php
===================================================================
--- trunk/extensions/SideBarMenu/SideBarMenu.php                                
(rev 0)
+++ trunk/extensions/SideBarMenu/SideBarMenu.php        2012-03-07 17:31:29 UTC 
(rev 113252)
@@ -0,0 +1,63 @@
+<?php
+
+if (!defined('MEDIAWIKI')) {
+    die('Not an entry point.');
+}
+
+$wgExtensionCredits['parserhook'][] = array(
+    'path' => __FILE__,
+    'name' => 'SideBarMenu',
+    'version' => 0.1,
+    'author' => 'Kim Eik',
+    'url' => 'https://www.mediawiki.org/wiki/Extension:SideBarMenu',
+    'descriptionmsg' => 'A simple sidebar menu parser which creates 
collapsable/expandable menus and sub-menus.'
+);
+
+
+// Specify the function that will initialize the parser function.
+$wgHooks['ParserFirstCallInit'][] = 'init';
+
+// Specify the function that will register the magic words for the parser 
function.
+$wgHooks['LanguageGetMagic'][] = 'registerMagicWords';
+
+// Sepcify phpunit tests
+$wgHooks['UnitTestsList'][] = 'registerUnitTests';
+
+//Autoload
+$wgMyExtensionIncludes = dirname(__FILE__) . '/includes';
+## Special page class
+$wgAutoloadClasses['MenuParser'] = $wgMyExtensionIncludes . '/MenuParser.php';
+$wgAutoloadClasses['MenuItem'] = $wgMyExtensionIncludes . '/MenuItem.php';
+
+
+function init(&$parser){
+    $parser->setHook('sidebarmenu','renderFromTag');
+    return true;
+}
+
+function registerMagicWords(&$magicWords, $langCode){
+    $magicWords['sidebarmenu'] = array(0,'sidebarmenu');
+    return true;
+}
+
+function renderFromTag( $input, array $args, Parser $parser, PPFrame $frame ){
+    try{
+        $menuHTML = MenuParser::getMenuTree($input)->toHTML();
+        return $parser->recursiveTagParse($menuHTML,$frame);
+    }catch(Exception $x){
+        wfDebug("An error occured during parsing of: '$input' caught 
exception: $x");
+        return "FATAL ERROR: Could not parse the following 
input:</br><pre>$input</pre>";
+    }
+}
+
+function registerUnitTests( &$files ) {
+    $testDir = dirname( __FILE__ ) . '/test/';
+    $testFiles = scandir($testDir);
+    foreach($testFiles as $testFile){
+        $absoluteFile = $testDir . $testFile;
+        if(is_file($absoluteFile)){
+            $files[] = $absoluteFile;
+        }
+    }
+    return true;
+}

Added: trunk/extensions/SideBarMenu/includes/MenuItem.php
===================================================================
--- trunk/extensions/SideBarMenu/includes/MenuItem.php                          
(rev 0)
+++ trunk/extensions/SideBarMenu/includes/MenuItem.php  2012-03-07 17:31:29 UTC 
(rev 113252)
@@ -0,0 +1,99 @@
+<?php
+
+class MenuItem
+{
+    private $expanded;
+    private $children = array();
+    private $parent = null;
+    private $text;
+
+    public function setExpanded($expanded)
+    {
+        $this->expanded = $expanded;
+    }
+
+    public function isExpanded()
+    {
+        return $this->expanded;
+    }
+
+    public function setText($link)
+    {
+        $this->text = $link;
+    }
+
+    public function getText()
+    {
+        return $this->text;
+    }
+
+    public function addChild(MenuItem $child)
+    {
+        if(!in_array($child,$this->children)){
+            $this->children[] = $child;
+            $child->setParent($this);
+        }
+    }
+
+    public function getChildren()
+    {
+        return $this->children;
+    }
+
+    public function hasChildren()
+    {
+        return sizeof($this->children) > 0;
+    }
+
+    public function setParent(MenuItem $parent)
+    {
+        if($this->parent !== $parent){
+            $this->parent = $parent;
+            $parent->addChild($this);
+        }
+    }
+
+    public function getParent()
+    {
+        return $this->parent;
+    }
+    
+    public function isRoot(){
+        return  is_null($this->parent);
+    }
+
+    public function getLevel(){
+        if($this->isRoot()){
+            return 0;
+        }else{
+            return 1+$this->getParent()->getLevel();
+        }
+    }
+
+    public function toHTML()
+    {
+        $output = "";
+        if($this->isRoot()){
+            $output .= $this->childrenToHTML();
+        }else{
+            $output .= "<li class=\"sidebar-menu-item 
sidebar-menu-item-".$this->getLevel().' '.($this->isExpanded() ? 
'sidebar-menu-item-expanded' : 'sidebar-menu-item-collapsed')."\"><div 
class=\"sidebar-menu-item-text 
sidebar-menu-item-text-".$this->getLevel()."\">".$this->getText()."</div>";
+            $output .= $this->childrenToHTML();
+            $output .= "</li>";
+        }
+
+        return $output;
+    }
+
+    private function childrenToHTML()
+    {
+        if($this->hasChildren()){
+            $output = "<ul class=\"sidebar-menu 
sidebar-menu-".$this->getLevel()."\">";
+            foreach ($this->getChildren() as $child) {
+                $output .= $child->toHTML();
+            }
+            $output .= "</ul>";
+            return $output;
+        }
+    }
+
+}

Added: trunk/extensions/SideBarMenu/includes/MenuParser.php
===================================================================
--- trunk/extensions/SideBarMenu/includes/MenuParser.php                        
        (rev 0)
+++ trunk/extensions/SideBarMenu/includes/MenuParser.php        2012-03-07 
17:31:29 UTC (rev 113252)
@@ -0,0 +1,123 @@
+<?php
+class MenuParser {
+
+    public static function isRoot($line)
+    {
+        return !self::startsWith($line, '*');
+    }
+
+    public static function isValidInput($data)
+    {
+        return !(is_null($data) || strlen($data) == 0);
+    }
+
+
+    public static function getLevel($line)
+    {
+        return substr_count($line, '*');
+    }
+
+    public static function getExpandedParameter($line)
+    {
+        if (self::startsWith($line, '+')) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    public static function getTextParameter($line)
+    {
+        return preg_filter("/\+|\-?\**(.*)/", "$1", $line);
+    }
+
+
+    public static function getMenuTree($data){
+        if(self::isValidInput($data)){
+            $data = self::cleanupData($data);
+            $root = new MenuItem();
+            $root->setExpanded(true);
+            $arrayData = self::parseDataIntoHierarchicalArray($data);
+            self::addChildrenToMenuItemFromArrayData($root,$arrayData);
+            return $root;
+        }
+    }
+
+
+    public static function getMenuItem($line)
+    {
+        $line = trim($line);
+        if(self::isValidInput($line)){
+            $menuItem = new MenuItem();
+            $menuItem->setExpanded(self::getExpandedParameter($line));
+            $menuItem->setText(self::getTextParameter($line));
+            return $menuItem;
+        }else{
+            throw new InvalidArgumentException();
+        }
+    }
+
+    public static function parseDataIntoHierarchicalArray($data)
+    {
+        $rootArray = array();
+        $prevArray = &$rootArray;
+        $prevLevel = 0;
+        $levelArray[0] = &$rootArray;
+        foreach(preg_split("/\n/",$data) as $line){
+            $level = self::getLevel($line);
+            if($level == $prevLevel){
+                $levelArray[$level][] = $line;
+            }else if($level-1 == $prevLevel){
+                //child of previous line
+                $parent = array_pop($levelArray[$level-1]);
+                $levelArray[$level-1][$parent][] = $line;
+                $levelArray[$level] = &$levelArray[$level-1][$parent];
+            }else if($level < $prevLevel){
+                //back some levels
+                $levelArray[$level][] = $line;
+            }else{
+                //syntax error
+                throw new InvalidArgumentException();
+            }
+            $prevLevel = $level;
+        }
+        return $rootArray;
+    }
+
+    public static function 
addChildrenToMenuItemFromArrayData(&$rootMenuItem,$arrayData)
+    {
+        foreach ($arrayData as $key => $val) {
+            if (is_string($key)) {
+                $menuItem = self::getMenuItem($key);
+                $rootMenuItem->addChild($menuItem);
+                self::addChildrenToMenuItemFromArrayData($menuItem,$val);
+            } else {
+                $menuItem = self::getMenuItem($val);
+                $rootMenuItem->addChild($menuItem);
+            }
+        }
+    }
+
+    private static function startsWith($haystack, $needle)
+    {
+        $length = strlen($needle);
+        return (substr($haystack, 0, $length) === $needle);
+    }
+
+    private static function cleanupData($data){
+        for($x = 0; $x < 2; $x++){
+            $data = self::removeLineBreaksFromStartOfString($data);
+            $data = strrev($data);
+        }
+        return $data;
+    }
+
+    private static function removeLineBreaksFromStartOfString($data)
+    {
+        while (self::startsWith($data, "\n")) {
+            $data = substr($data, 1);
+        }
+        return $data;
+    }
+
+}
\ No newline at end of file

Added: trunk/extensions/SideBarMenu/test/MenuItemTest.php
===================================================================
--- trunk/extensions/SideBarMenu/test/MenuItemTest.php                          
(rev 0)
+++ trunk/extensions/SideBarMenu/test/MenuItemTest.php  2012-03-07 17:31:29 UTC 
(rev 113252)
@@ -0,0 +1,104 @@
+<?php
+
+class MenuItemTest extends MediaWikiTestCase
+{
+    private $menuItem;
+
+    protected function setUp()
+    {
+        $this->menuItem = new MenuItem();
+    }
+
+    public function testIsRoot(){
+        $this->assertTrue($this->menuItem->isRoot());
+    }
+
+    public function testIsNotRoot(){
+        $this->menuItem->setParent(new MenuItem());
+        $this->assertFalse($this->menuItem->isRoot());
+    }
+
+    public function testGetLevelWhenRoot(){
+        $this->assertEquals(0,$this->menuItem->getLevel());
+    }
+
+    public function testGetLevelWhenChild(){
+        $this->menuItem->setParent(new MenuItem());
+        $this->assertEquals(1,$this->menuItem->getLevel());
+    }
+
+    public function testGetLevelWhenSeveralChildren(){
+        $prev = $this->menuItem;
+        for($x = 0; $x < 10; $x++){
+            $child = new MenuItem();
+            $child->setParent($prev);
+            $prev = $child;
+
+        }
+        $this->assertEquals(10,$prev->getLevel());
+    }
+
+    public function testAddChildAlsoAddsParent(){
+        $child = new MenuItem();
+        $this->menuItem->addChild($child);
+        $this->assertContains($child,$this->menuItem->getChildren());
+        $this->assertEquals($child->getParent(),$this->menuItem);
+    }
+
+    public function testAddSameChildSeveralTimes(){
+        $child = new MenuItem();
+        for($x = 0; $x < 3; $x++){
+            $this->menuItem->addChild($child);
+        }
+        $this->assertEquals(1,sizeof($this->menuItem->getChildren()));
+    }
+
+    public function testAddParentAlsoAddsChild(){
+        $parent = new MenuItem();
+        $this->menuItem->setParent($parent);
+        $this->assertContains($this->menuItem,$parent->getChildren());
+    }
+
+    public function testToHTMLOnRootMenuItem(){
+        $html = $this->menuItem->toHTML();
+        $this->assertEquals("",$html);
+    }
+
+    public function testToHTMLOnProperMenuItem(){
+        $menuItemChild = new MenuItem();
+        $menuItemChild->setText("MenuItem1");
+        $this->menuItem->addChild($menuItemChild);
+        $html = $this->menuItem->toHTML();
+        $this->assertEquals('<ul class="sidebar-menu sidebar-menu-0"><li 
class="sidebar-menu-item sidebar-menu-item-1 sidebar-menu-item-collapsed"><div 
class="sidebar-menu-item-text 
sidebar-menu-item-text-1">MenuItem1</div></li></ul>',$html);
+    }
+
+    public function testToHTMLOnSeveralMenuItems(){
+        $menuItemChild1 = new MenuItem();
+        $menuItemChild1->setText("MenuItem1");
+        $menuItemChild2 = new MenuItem();
+        $menuItemChild2->setText("MenuItem2");
+
+        $this->menuItem->addChild($menuItemChild1);
+        $this->menuItem->addChild($menuItemChild2);
+
+        $html = $this->menuItem->toHTML();
+        $this->assertEquals('<ul class="sidebar-menu sidebar-menu-0"><li 
class="sidebar-menu-item sidebar-menu-item-1 sidebar-menu-item-collapsed"><div 
class="sidebar-menu-item-text sidebar-menu-item-text-1">MenuItem1</div></li><li 
class="sidebar-menu-item sidebar-menu-item-1 sidebar-menu-item-collapsed"><div 
class="sidebar-menu-item-text 
sidebar-menu-item-text-1">MenuItem2</div></li></ul>',$html);
+    }
+
+    public function testToHTMLOnSeveralMenuItemsWithSublevels(){
+        $menuItemChild1 = new MenuItem();
+        $menuItemChild1->setText("MenuItem1");
+        $menuItemChild2 = new MenuItem();
+        $menuItemChild2->setText("MenuItem2");
+
+        $this->menuItem->addChild($menuItemChild1);
+        $this->menuItem->addChild($menuItemChild2);
+
+        $subLevel1 = new MenuItem();
+        $subLevel1->setText("SubMenuItem1");
+        $subLevel1->setParent($menuItemChild2);
+
+        $html = $this->menuItem->toHTML();
+        $this->assertEquals('<ul class="sidebar-menu sidebar-menu-0"><li 
class="sidebar-menu-item sidebar-menu-item-1 sidebar-menu-item-collapsed"><div 
class="sidebar-menu-item-text sidebar-menu-item-text-1">MenuItem1</div></li><li 
class="sidebar-menu-item sidebar-menu-item-1 sidebar-menu-item-collapsed"><div 
class="sidebar-menu-item-text sidebar-menu-item-text-1">MenuItem2</div><ul 
class="sidebar-menu sidebar-menu-1"><li class="sidebar-menu-item 
sidebar-menu-item-2 sidebar-menu-item-collapsed"><div 
class="sidebar-menu-item-text 
sidebar-menu-item-text-2">SubMenuItem1</div></li></ul></li></ul>',$html);
+    }
+}

Added: trunk/extensions/SideBarMenu/test/MenuParserTest.php
===================================================================
--- trunk/extensions/SideBarMenu/test/MenuParserTest.php                        
        (rev 0)
+++ trunk/extensions/SideBarMenu/test/MenuParserTest.php        2012-03-07 
17:31:29 UTC (rev 113252)
@@ -0,0 +1,214 @@
+<?php
+
+class MenuParserTest extends MediaWikiTestCase
+{
+
+    public function testValidInputWhenNull(){
+        $this->assertFalse(MenuParser::isValidInput(null));
+    }
+
+    public function testValidInputWhenEmpty(){
+        $this->assertFalse(MenuParser::isValidInput(""));
+    }
+
+    public function testValidInput(){
+        $this->assertTrue(MenuParser::isValidInput("+MenuItem"));
+    }
+
+    public function testIsRoot(){
+        $isRoot = MenuParser::isRoot("MenuItem");
+        $this->assertTrue($isRoot);
+    }
+
+    public function testIsNotRoot(){
+        $isRoot = MenuParser::isRoot("*MenuItem");
+        $this->assertFalse($isRoot);
+    }
+
+    public function testGetLevelWhenNull(){
+        $this->assertEquals(0,MenuParser::getLevel(null));
+    }
+
+    public function testGetLevelWhenEmpty(){
+        $this->assertEquals(0,MenuParser::getLevel(""));
+    }
+
+    public function testGetLevelWhenValidButNoStars(){
+        $this->assertEquals(0,MenuParser::getLevel(""));
+    }
+
+    public function testGetLevelWithValid(){
+        $this->assertEquals(3,MenuParser::getLevel("***MenuItem"));
+    }
+
+    public function testGetExpandedParameterWhenNoneSupplied(){
+        //default is false
+        $this->assertFalse(MenuParser::getExpandedParameter("MenuItem"));
+    }
+
+    public function testGetExpandedParameterWhenNotExpanded(){
+        $this->assertFalse(MenuParser::getExpandedParameter("-MenuItem"));
+    }
+
+    public function testGetExpandedParameterWhenExpanded(){
+        $this->assertTrue(MenuParser::getExpandedParameter("+MenuItem"));
+    }
+
+    public function testGetTextParameter(){
+        
$this->assertEquals("MenuItem",MenuParser::getTextParameter("+***MenuItem"));
+        
$this->assertEquals("+MenuItem",MenuParser::getTextParameter("+***+MenuItem"));
+        
$this->assertEquals("MenuItem",MenuParser::getTextParameter("-MenuItem"));
+        
$this->assertEquals("MenuItem",MenuParser::getTextParameter("-*MenuItem"));
+        
$this->assertEquals("MenuItem",MenuParser::getTextParameter("MenuItem"));
+        
$this->assertEquals("+*MenuItem",MenuParser::getTextParameter("+***+*MenuItem"));
+    }
+
+    public function testGetMenuItemWhenInputIsNull(){
+        $this->setExpectedException('InvalidArgumentException');
+        $this->assertNull(MenuParser::getMenuItem(null));
+    }
+
+    public function testGetMenuItemWhenInputIsEmpty(){
+        $this->setExpectedException('InvalidArgumentException');
+        $this->assertNull(MenuParser::getMenuItem(""));
+    }
+
+    public function testGetMenuItemWhenInputIsValid(){
+        $data = "MenuItem";
+        $menuItem = MenuParser::getMenuItem($data);
+        $this->assertNotNull($menuItem);
+        $this->assertEquals($data,$menuItem->getText());
+        $this->assertFalse($menuItem->isExpanded()); //false is default
+    }
+
+    public function testGetMenuItemWhenInputIsValidAndExpandIsSet(){
+        $text = "MenuItem";
+        $data = "+".$text;
+        $menuItem = MenuParser::getMenuItem($data);
+        $this->assertNotNull($menuItem);
+        $this->assertEquals($text,$menuItem->getText());
+        $this->assertTrue($menuItem->isExpanded()); //false is default
+    }
+
+    public function testParseDataIntoHierarchicalArray(){
+        $data = "MenuItem";
+        $array = MenuParser::parseDataIntoHierarchicalArray($data);
+        $this->assertNotNull($array);
+        $this->assertEquals($data,$array[0]);
+    }
+
+    public function testParseDataIntoHierarchicalArrayWithSubLevel(){
+        $lines = array("MenuItem","*SubMenuItem");
+        $data = join("\n",$lines);
+        $array = MenuParser::parseDataIntoHierarchicalArray($data);
+        $this->assertNotNull($array);
+        $this->assertArrayHasKey($lines[0],$array);
+        $this->assertEquals(
+            array(
+                'MenuItem' => array(
+                    '*SubMenuItem'
+                )
+            ),$array
+        );
+    }
+
+    public function testParseDataIntoHierarchicalArrayWithSeveralSubLevels(){
+        $lines = 
array("MenuItem","*SubMenuItem","*SubMenuItem2","**SubMenuItemOf2");
+        $data = join("\n",$lines);
+        $array = MenuParser::parseDataIntoHierarchicalArray($data);
+        $this->assertNotNull($array);
+        $this->assertEquals(
+            array(
+                'MenuItem' => array(
+                    '*SubMenuItem',
+                    '*SubMenuItem2' => array(
+                        '**SubMenuItemOf2'
+                    )
+                )
+            ),$array
+        );
+    }
+
+    public function testParseDataIntoHierarchicalArrayWithSubLevelAndBack(){
+        $lines = array("MenuItem","*SubMenuItem","MenuItem2");
+        $data = join("\n",$lines);
+        $array = MenuParser::parseDataIntoHierarchicalArray($data);
+        $this->assertNotNull($array);
+        $this->assertEquals(
+            array(
+                'MenuItem' => array(
+                    '*SubMenuItem'
+                ),
+                'MenuItem2'
+            ),$array
+        );
+    }
+
+    public function 
testParseDataIntoHierarchicalArrayWithSubLevelAndBackSeveralLevels(){
+        $lines = 
array("MenuItem","*SubMenuItem1","**SubMenuItem2","***SubMenuItem3","MenuItem2");
+        $data = join("\n",$lines);
+        $array = MenuParser::parseDataIntoHierarchicalArray($data);
+        $this->assertNotNull($array);
+        $this->assertEquals(
+            array(
+                'MenuItem' => array(
+                    '*SubMenuItem1' => array(
+                        '**SubMenuItem2' => array(
+                            '***SubMenuItem3'
+                        )
+                    )
+                ),
+                'MenuItem2'
+            ),$array
+        );
+    }
+
+
+    public function testGetMenuWithInvalidInput(){
+        $this->assertNull(MenuParser::getMenuTree(null));
+        $this->assertNull(MenuParser::getMenuTree(""));
+    }
+
+    public function testGetMenuWithValidInput(){
+        $menu = MenuParser::getMenuTree("MenuItem");
+        $this->assertNotNull($menu);
+        $this->assertTrue($menu->isRoot());
+        $this->assertEquals(1,sizeof($menu->getChildren()));
+
+        $children = $menu->getChildren();
+        $this->assertEquals("MenuItem",$children[0]->getText());
+    }
+
+    public function testGetMenuWithValidComplexInput(){
+        $data = array(
+            'MenuItem1',
+            '*SubMenuItem1',
+            '*SubMenuItem2',
+            '*SubMenuItem3',
+            '**SubMenuItem1Of1',
+            '**SubMenuItem2Of1',
+            'MenuItem2',
+            '*SubMenuItem1OfMenuItem2'
+        );
+        $menu = MenuParser::getMenuTree(join("\n",$data));
+        $this->assertNotNull($menu);
+        $this->assertEquals(2,sizeof($menu->getChildren()));
+
+    }
+
+    public function testGetMenuWithSeveralLineBreaks(){
+        $data = array(
+            '',
+            'MenuItem1',
+            '',
+            ''
+        );
+        $menu = MenuParser::getMenuTree(join("\n",$data));
+        $this->assertNotNull($menu);
+        $this->assertEquals(1,sizeof($menu->getChildren()));
+
+        $children = $menu->getChildren();
+        $this->assertEquals("MenuItem1",$children[0]->getText());
+
+    }
+}


_______________________________________________
MediaWiki-CVS mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-cvs

Reply via email to