<?php
/**
* Copyright (C) 2010 Kai Dorschner
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @author Kai Dorschner <the-hide@address.com>
* @copyright Copyright 2010, Kai Dorschner
* @license http://www.gnu.org/licenses/gpl.html GPLv3
* @package mocovi
* @subpackage controls
*/
/**
* Require generic dirlist control.
*/
ControlFactory::load('dirlist');
/**
* Is able to create recursive menu from the {@link filesystem}.
*
* <b>Attributes</b>:
* - <b>directory</b>: Defines a static directory which is used to create the menu. If this is not set this control will use the "directory" value of {@link $defaultOptions}.
* - <b>recursion</b>: Sets the maximum value of recursion depth. This attribute operates with the local $depth variable of the {@see recursiveReadElementsIn()} method.
*
* <b>Parameters:</b>
* - <b>restriction</b>: A regular expression which let this control not use elements matching this pattern.
* - <b>obligation</b>: A regular expression which defines which elements MUST be used when they match this pattern.
* - <b>type</b>: Sets a datatype for the element. Can be "file", "dir" or even "array", "string", "bool", "int", etc. You can use all strings which should be inserted after "is_" to create a dynamic function such as is_file();
*
* An example with dynamic source:
* <code>
* <menu recursion="2">
* <param name="restriction" value="^\."/>
* <param name="obligation" value="^menuelement_"/>
* <param name="type" value="dir"/>
* </menu>
* </code>
*
* Or with static source:
* <code>
* <menu directory="./my/directory/" recursion="2">
* <param name="restriction" value="^\."/>
* <param name="obligation" value="^menuelement_"/>
* <param name="type" value="dir"/>
* </menu>
* </code>
*
* @package mocovi
* @subpackage controls
*/
class menu_control extends dirlist_control
{
/**
* Is the current directory from the user cut in pieces (array)
* @var array Contains all pieces of the user's directory
* @access protected
*/
protected $activeDirectory = array();
protected $defaultOptions = array
( 'directory' => '/' // Root Directory
, 'recursion' => 2 // Maximum recursion depth
, 'readSiblings' => 0 // Also read content of neighbour directories
, 'fold' => 1 // Folds peripheral elements
, 'lastModifiedFormat' => 'c' // PHP date(); format (http://de.php.net/date): c = ISO 8601 date
);
/**
* @override
*/
protected function program()
{
$this->activeDirectory = explode('/', trim($GLOBALS['page'], '/')); // clear first and last slash
$this->recursiveReadElementsIn($this->node, $this->getOption('directory'));
}
/**
* Reads all elements from the given directory in the specified container.
*
* @access protected
* @return void
* @param $container
*/
protected function recursiveReadElementsIn(DomNode &$container, $dir)
{
static $depth = 0;
$this->readElementsIn($container, $dir);
foreach($container->childNodes as $subnode)
{
$path = $this->getURIFromElement($subnode);
$current = $this->dom->createElement($this->getName()); // create empty container
/*
Optionally add to IF query:
&& $depth == count($this->activeDirectory) - 1 // Only marks the current Element as "active"
*/
if($path == $this->activeDirectoryFragment($depth))
$subnode->setAttribute('active', 'true');
if(($this->getOption('readSiblings') || $path == $this->activeDirectoryFragment($depth)) && ($this->getOption('recursion') == '*' || $depth < $this->getOption('recursion') + count($this->activeDirectory) - 1))
{
$depth++;
$this->recursiveReadElementsIn($current, $path); // Recursion
$depth--;
}
// Only if this element contains subelements
if($current->firstChild && @count($current->firstChild->childNodes) > 0)
$subnode->appendChild($current);
}
}
/**
* Returns the active part of the directory.
*
* @access protected
*/
protected function activeDirectoryFragment($index)
{
$return = '/';
for($i = 0; $i < count($this->activeDirectory) && $i < ($index + 1); $i++)
$return .= $this->activeDirectory[$i].'/';
return $return;
}
}