Location: PHPKode > projects > Content*Builder > contentbuilder/lib/CB_NestedSet.class.php
<?php 
// +----------------------------------------------------------------------+
// | CB_NestedSet                                                         |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2003 The C*B Development Group                    |
// +----------------------------------------------------------------------+
// | This source file is subject to version 1.0 of the CB license,        |
// | that is bundled with this package in the file license.txt            |
// | If you did not receive a copy of the CB license please send a        |
// | note to hide@address.com so we can mail you            |
// | a copy immediately.                                                  |
// +----------------------------------------------------------------------+
// | Author:  Joerg Stoeber <hide@address.com>                |
// +----------------------------------------------------------------------+
/* 
* Konstante für Move Methoden. Gibt an das ein Zweig in der Hierarchie 
* unter einem anderen Zweig stehen soll
*/
define("CB_NESE_MOVEBELOW", 1);

/* 
* Konstante für Move Methoden. Gibt an das ein Zweig in der selben Hierarchie
* vor einem anderen stehen soll
*/
define("CB_NESE_MOVEBEFORE", 2);

/* 
* Konstante für Move Methoden. Gibt an das ein Zweig in der selben Hierarchie
* nach einem anderen stehen soll
*/
define("CB_NESE_MOVEAFTER", 3);

/**
 * CB_NestedSet
 * 
 * @package CB_NestedSet
 * @author Joerg Stoeber <hide@address.com> 
 * @copyright Copyright (c) 2003 The C*B Development Group
 * @version $Id: CB_NestedSet.class.php,v 1.6 2004/09/03 20:17:20 cb_fog Exp $
 * @access public 
 */
class CB_NestedSet {
	function CB_NestedSet($params, $otherFields)
	{
		$this->params = $params;
		$this->additional = $otherFields;
	} 

	/**
	 * CB_NestedSet::factory()
	 * 
	 * @param array $params Array mit folgenden zwingenden Werten:
	 *          table  -> Tabellenname
	 *          id     -> Feldname des ID Feldes
	 *          parent -> Feldname der ElternID
	 *          root   -> Feldname der Root ID
	 *          l      -> Feldname der leftID
	 *          r      -> Feldname der rightID
	 *          norder -> Feldname des order Wertes
	 * @param array $otherFields Alle anderen Felder, die es noch in der
	 *          Tabelle gibt und die bearbeitbar sein sollen
	 * @return mixed Entweder angefordertes Objekt oder false, wenn Fehler auftrat
	 */
	function &factory($params, $otherFields = array())
	{
		if (is_array($params)) {
			return new CB_NestedSet($params, $otherFields);
		} else {
			return false;
		} 
	} 

	/*
	* getNode()
	* liefert ein Blatt des Baumes zurueck
	* 
	* @access public
	* @param int $id ID des Blattes
	* @param boolean $aliasFields Stellt bei true fuer alle Felder die 
	*        Aliasnamen ein, die in den Parameter Tabellen auf der 
	*        linken Seite stehen. Bei false werden die realen Felder 
	*        der rechten Seite zurueck geliefert
	* @return mixed $result entweder Array mit Node Werten oder false falls Abfrage fehl schlug
	*/
	function getNode($id, $aliasFields = false, $additionalSQL = array())
	{
		$this->_setActualFieldNames();

		if (count($additionalSQL) > 0) {
			$joinParameters = $additionalSQL['join'];
			$fieldParameters = $additionalSQL['field'];
			$whereParameters = $additionalSQL['where'];
			$appendParameters = $additionalSQL['append'];
		} 

		$nodeSQL = sprintf("SELECT %s %s FROM %s AS n %s WHERE n.%s = '$id' %s %s",
			$this->_queryFieldNameConvert('n', $aliasFields),
			$fieldParameters,
			$this->params['table'],
			$joinParameters,
			$this->params['id'],
			$whereParameters,
			$appendParameters
			);

		$nodeQuery = mysql_query($nodeSQL);
		if (mysql_num_rows($nodeQuery) > 0) {
			return mysql_fetch_array($nodeQuery);
		} else {
			return false;
		} 
	} 

	/*
	* getRootNodes()
	* Liefert alle Wurzelknoten zurueck
	* Rueckgabe eines Array's mit Werten, erstes Array Level = ID des Nodes, 2. Level = alle Werte
	* 
	* @access public
	* @param boolean $aliasFields Stellt bei true fuer alle Felder die 
	*        Aliasnamen ein, die in den Parameter Tabellen auf der 
	*        linken Seite stehen. Bei false werden die realen Felder 
	*        der rechten Seite zurueck geliefert
	* @return mixed $result entweder Array mit Node Werten oder false falls Abfrage fehl schlug
	*/
	function getRootNodes($aliasFields = false, $additionalSQL = array())
	{
		$this->_setActualFieldNames();

		if (count($additionalSQL) > 0) {
			$joinParameters = $additionalSQL['join'];
			$fieldParameters = $additionalSQL['field'];
			$whereParameters = $additionalSQL['where'];
			$appendParameters = $additionalSQL['append'];
			$orderByParameters = $additionalSQL['orderby'];
		} 

		if ($orderByParameters == "") {
			$orderByParameters = "ORDER BY n." . $this->params['norder'] . " ASC";
		} 

		$nodesSQL = sprintf("SELECT %s %s FROM %s AS n %s WHERE n.%s = n.%s %s %s %s",
			$this->_queryFieldNameConvert('n', $aliasFields),
			$fieldParameters,
			$this->params['table'],
			$joinParameters,
			$this->params['id'],
			$this->params['root'],
			$whereParameters,
			$orderByParameters,
			$appendParameters
			);

		$nodesQuery = mysql_query($nodesSQL);
		if ($nodesQuery) {
			while ($nodesRow = mysql_fetch_array($nodesQuery)) {
				$branch[$nodesRow[$this->actualFieldNames['id']]] = $nodesRow;
			} 
			return $branch;
		} else {
			return false;
		} 
	} 

	/*
	* getBranch()
	* einen ganzen Zweig eines Baumes zurueck
	* Rueckgabe eines Array's mit Werten, erstes Array Level = ID des Nodes, 2. Level = alle Werte
	* 
	* @access public
	* @param int $id ID des Blattes
	* @param boolean $aliasFields Stellt bei true fuer alle Felder die 
	*        Aliasnamen ein, die in den Parameter Tabellen auf der 
	*        linken Seite stehen. Bei false werden die realen Felder 
	*        der rechten Seite zurueck geliefert
	* @return mixed $result entweder Array mit Node Werten oder false falls Abfrage fehl schlug
	*/
	function getBranch($id, $aliasFields = false, $additionalSQL = array())
	{
		$this->_setActualFieldNames();

		if (count($additionalSQL) > 0) {
			$joinParameters = $additionalSQL['join'];
			$fieldParameters = $additionalSQL['field'];
			$whereParameters = $additionalSQL['where'];
			$appendParameters = $additionalSQL['append'];
			$orderByParameters = $additionalSQL['orderby'];
		} 

		if ($orderByParameters == "") {
			$orderByParameters = "ORDER BY n." . $this->params['l'] . " ASC";
		} 

		$node = $this->getNode($id);
		$nodesSQL = sprintf("SELECT %s %s FROM %s AS n %s WHERE n.%s BETWEEN %s AND %s AND n.%s = '%s' %s GROUP BY n.%s %s %s",
			$this->_queryFieldNameConvert('n', $aliasFields),
			$fieldParameters,
			$this->params['table'],
			$joinParameters,
			$this->params['l'],
			$node[$this->params['l']],
			$node[$this->params['r']],
			$this->params['root'],
			$node[$this->params['root']],
			$whereParameters,
			$this->params['l'],
			$orderByParameters,
			$appendParameters
			);

		$nodesQuery = mysql_query($nodesSQL);
		if ($nodesQuery) {
			while ($nodesRow = mysql_fetch_array($nodesQuery)) {
				$branch[$nodesRow[$this->actualFieldNames['id']]] = $nodesRow;
			} 
			return $branch;
		} else {
			return false;
		} 
	} 

	/*
	* getAllNodes()
	* Methode gibt den ganzen Baum zurueck. Alle Root Nodes mit Subnodes
	* Rueckgabe eines Array's mit Werten, erstes Array Level = ID des Nodes, 2. Level = alle Werte
	* 
	* @access public
	* @param boolean $aliasFields Stellt bei true fuer alle Felder die 
	*        Aliasnamen ein, die in den Parameter Tabellen auf der 
	*        linken Seite stehen. Bei false werden die realen Felder 
	*        der rechten Seite zurueck geliefert
	* @return mixed $result entweder Array mit Node Werten oder false falls Abfrage fehl schlug
	*/
	function getAllNodes($aliasFields = false, $additionalSQL = array())
	{
		$this->_setActualFieldNames();

		if (count($additionalSQL) > 0) {
			$joinParameters = $additionalSQL['join'];
			$fieldParameters = $additionalSQL['field'];
			$whereParameters = $additionalSQL['where'];
			$appendParameters = $additionalSQL['append'];
			$orderByParameters = $additionalSQL['orderby'];
		} 

		if ($orderByParameters == "") {
			$orderByParameters = "ORDER BY n." . $this->params['norder'] . ", n." . $this->params['l'] . " ASC";
		} 

		$nodesSQL = sprintf("SELECT %s %s FROM %s AS n, %s AS p %s WHERE n.%s BETWEEN p.%s AND p.%s %s GROUP BY n.%s, n.%s %s %s",
			$this->_queryFieldNameConvert('n', $aliasFields),
			$fieldParameters,
			$this->params['table'],
			$this->params['table'],
			$joinParameters,
			$this->params['l'],
			$this->params['l'],
			$this->params['r'],
			$whereParameters,
			$this->params['root'],
			$this->params['l'],
			$orderByParameters,
			$appendParameters
			);

		$nodesQuery = mysql_query($nodesSQL);
		if ($nodesQuery) {
			while ($nodesRow = mysql_fetch_array($nodesQuery)) {
				$branch[$nodesRow[$this->actualFieldNames['id']]] = $nodesRow;
			} 
			return $branch;
		} else {
			return false;
		} 
	} 

	/*
	* getParent()
	* Liefert den Elternknoten
	* 
	* @access public
	* @param int $id ID von dem Knoten, dessen Eltern Knoten ermittelt wird
	* @param boolean $aliasFields Stellt bei true fuer alle Felder die 
	*        Aliasnamen ein, die in den Parameter Tabellen auf der 
	*        linken Seite stehen. Bei false werden die realen Felder 
	*        der rechten Seite zurueck geliefert
	* @return mixed $result entweder Array mit Node Werten oder false falls Abfrage fehl schlug
	*/
	function getParent($id, $aliasFields = false, $additionalSQL = array())
	{
		$this->_setActualFieldNames();

		$node = $this->getNode($id);
		$parent = false;
		if ($node != false) {
			$parent = $this->getNode($node[$this->params['parent']], $aliasFields, $additionalSQL);
		} 
		if ($parent != false) {
			return $parent;
		} else {
			return false;
		} 
	} 

	/*
	* getParents()
	* Liefert alle Eltern des angebenen Knotens
	* 
	* @access public
	* @param int $id ID zu dem der Pfad gefuehrt werden soll
	* @param boolean $aliasFields Stellt bei true fuer alle Felder die 
	*        Aliasnamen ein, die in den Parameter Tabellen auf der 
	*        linken Seite stehen. Bei false werden die realen Felder 
	*        der rechten Seite zurueck geliefert
	* @return mixed $result entweder Array mit Node Werten oder false falls Abfrage fehl schlug
	*/
	function getParents($id, $aliasFields = false, $additionalSQL = array())
	{
		$this->_setActualFieldNames();

		if (count($additionalSQL) > 0) {
			$joinParameters = $additionalSQL['join'];
			$fieldParameters = $additionalSQL['field'];
			$whereParameters = $additionalSQL['where'];
			$appendParameters = $additionalSQL['append'];
			$orderByParameters = $additionalSQL['orderby'];
		} 

		if ($orderByParameters == "") {
			$orderByParameters = "ORDER BY n." . $this->params['l'] . " ASC";
		} 

		$nodesSQL = sprintf("SELECT %s %s FROM %s AS n, %s AS p %s WHERE n.%s BETWEEN p.%s AND p.%s AND n.%s = '$id' AND p.%s != '$id' AND n.%s = p.%s %s ORDER BY n.%s ASC %s",
			$this->_queryFieldNameConvert('p', $aliasFields),
			$fieldParameters,
			$this->params['table'],
			$this->params['table'],
			$joinParameters,
			$this->params['l'],
			$this->params['l'],
			$this->params['r'],
			$this->params['id'],
			$this->params['id'],
			$this->params['root'],
			$this->params['root'],
			$whereParameters,
			$orderByParameters,
			$appendParameters
			);
		$nodesQuery = mysql_query($nodesSQL);
		if ($nodesQuery) {
			while ($nodesRow = mysql_fetch_array($nodesQuery)) {
				$branch[$nodesRow[$this->actualFieldNames['id']]] = $nodesRow;
			} 
			return $branch;
		} else {
			return false;
		} 
	} 

	/*
	* getPath()
	* Liefert den Pfad von der Wurzel bis zum angegebenen Knoten
	* 
	* @access public
	* @param int $id ID zu dem der Pfad gefuehrt werden soll
	* @param boolean $aliasFields Stellt bei true fuer alle Felder die 
	*        Aliasnamen ein, die in den Parameter Tabellen auf der 
	*        linken Seite stehen. Bei false werden die realen Felder 
	*        der rechten Seite zurueck geliefert
	* @return mixed $result entweder Array mit Node Werten oder false falls Abfrage fehl schlug
	*/
	function getPath($id, $aliasFields = false, $additionalSQL = array())
	{
		$this->_setActualFieldNames();

		if (count($additionalSQL) > 0) {
			$joinParameters = $additionalSQL['join'];
			$fieldParameters = $additionalSQL['field'];
			$whereParameters = $additionalSQL['where'];
			$appendParameters = $additionalSQL['append'];
			$orderByParameters = $additionalSQL['orderby'];
		} 

		if ($orderByParameters == "") {
			$orderByParameters = "ORDER BY n." . $this->params['l'] . " ASC";
		} 

		$nodesSQL = sprintf("SELECT %s %s FROM %s AS n, %s AS p %s WHERE n.%s BETWEEN p.%s AND p.%s AND n.%s = '$id' AND n.%s = p.%s %s %s %s",
			$this->_queryFieldNameConvert('p', $aliasFields),
			$fieldParameters,
			$this->params['table'],
			$this->params['table'],
			$joinParameters,
			$this->params['l'],
			$this->params['l'],
			$this->params['r'],
			$this->params['id'],
			$this->params['root'],
			$this->params['root'],
			$whereParameters,
			$orderByParameters,
			$appendParameters
			);
		$nodesQuery = mysql_query($nodesSQL);
		if ($nodesQuery) {
			while ($nodesRow = mysql_fetch_array($nodesQuery)) {
				$branch[$nodesRow[$this->actualFieldNames['id']]] = $nodesRow;
			} 
			return $branch;
		} else {
			return false;
		} 
	} 

	function getPrecedents($id, $aliasFields = false, $additionalSQL = array())
	{
		$this->_setActualFieldNames();

		if (count($additionalSQL) > 0) {
			$joinParameters = $additionalSQL['join'];
			$fieldParameters = $additionalSQL['field'];
			$whereParameters = $additionalSQL['where'];
			$appendParameters = $additionalSQL['append'];
			$orderByParameters = $additionalSQL['orderby'];
		} 

		if ($orderByParameters == "") {
			$orderByParameters = "ORDER BY n." . $this->params['l'] . " ASC";
		} 

		$nodesSQL = sprintf("SELECT %s %s FROM %s AS n, %s AS p %s WHERE n.%s BETWEEN p.%s AND p.%s AND n.%s = '$id' %s %s %s",
			$this->_queryFieldNameConvert('p', $aliasFields),
			$fieldParameters,
			$this->params['table'],
			$this->params['table'],
			$joinParameters,
			$this->params['l'],
			$this->params['l'],
			$this->params['r'],
			$this->params['id'],
			$whereParameters,
			$orderByParameters,
			$appendParameters
			);
		$nodesQuery = mysql_query($nodesSQL);
		if ($nodesQuery) {
			while ($nodesRow = mysql_fetch_array($nodesQuery)) {
				$branch[$nodesRow[$this->actualFieldNames['id']]] = $nodesRow;
			} 
			return $branch;
		} else {
			return false;
		} 
	} 

	/*
	* getDescendants()
	* liefert alle Nachkommen eines Zweiges
	* Rueckgabe eines Array's mit Werten, erstes Array Level = ID des Nodes, 2. Level = alle Werte
	* 
	* @access public
	* @param int $id ID des Knotens dessen Nachfahren ermittelt werden 
	*        sollen
	* @param boolean $aliasFields Stellt bei true fuer alle Felder die 
	*        Aliasnamen ein, die in den Parameter Tabellen auf der 
	*        linken Seite stehen. Bei false werden die realen Felder 
	*        der rechten Seite zurueck geliefert
	* @return mixed $result entweder Array mit Node Werten oder false falls Abfrage fehl schlug
	*/
	function getDescendants($id, $aliasFields = false, $additionalSQL = array())
	{
		$this->_setActualFieldNames();

		if (count($additionalSQL) > 0) {
			$joinParameters = $additionalSQL['join'];
			$fieldParameters = $additionalSQL['field'];
			$whereParameters = $additionalSQL['where'];
			$appendParameters = $additionalSQL['append'];
			$orderByParameters = $additionalSQL['orderby'];
		} 

		if ($orderByParameters == "") {
			$orderByParameters = "ORDER BY n." . $this->params['l'] . " ASC";
		} 

		$node = $this->getNode($id);
		$nodesSQL = sprintf("SELECT %s %s FROM %s AS n %s WHERE n.%s BETWEEN %s AND %s AND n.%s = '%s' %s GROUP BY n.%s %s %s",
			$this->_queryFieldNameConvert('n', $aliasFields),
			$fieldParameters,
			$this->params['table'],
			$joinParameters,
			$this->params['l'],
			$node[$this->params['l']] + 1,
			$node[$this->params['r']] - 1,
			$this->params['root'],
			$node[$this->params['root']],
			$whereParameters,
			$this->params['l'],
			$orderByParameters,
			$appendParameters
			);

		$nodesQuery = mysql_query($nodesSQL);
		if ($nodesQuery) {
			while ($nodesRow = mysql_fetch_array($nodesQuery)) {
				$branch[$nodesRow[$this->actualFieldNames['id']]] = $nodesRow;
			} 
			return $branch;
		} else {
			return false;
		} 
	} 

	/*
	* getChildren()
	* liefert die direkten Nachkommen eines Zweiges
	* Rueckgabe eines Array's mit Werten, erstes Array Level = ID des Nodes, 2. Level = alle Werte
	* 
	* @access public
	* @param int $id ID des Knotens dessen Nachfahren ermittelt werden 
	*        sollen
	* @param boolean $aliasFields Stellt bei true fuer alle Felder die 
	*        Aliasnamen ein, die in den Parameter Tabellen auf der 
	*        linken Seite stehen. Bei false werden die realen Felder 
	*        der rechten Seite zurueck geliefert
	* @return mixed $result entweder Array mit Node Werten oder false falls Abfrage fehl schlug
	*/
	function getChildren($id, $aliasFields = false, $additionalSQL = array())
	{
		$this->_setActualFieldNames();

		if (count($additionalSQL) > 0) {
			$joinParameters = $additionalSQL['join'];
			$fieldParameters = $additionalSQL['field'];
			$whereParameters = $additionalSQL['where'];
			$appendParameters = $additionalSQL['append'];
			$orderByParameters = $additionalSQL['orderby'];
		} 

		if ($orderByParameters == "") {
			$orderByParameters = "ORDER BY n." . $this->params['l'] . " ASC";
		} 

		$nodesSQL = sprintf("SELECT %s %s FROM %s AS n %s WHERE n.%s = '%s' %s %s %s",
			$this->_queryFieldNameConvert('n', $aliasFields),
			$fieldParameters,
			$this->params['table'],
			$joinParameters,
			$this->params['parent'],
			$id,
			$whereParameters,
			$orderByParameters,
			$appendParameters
			);

		$nodesQuery = mysql_query($nodesSQL);
		if ($nodesQuery) {
			while ($nodesRow = mysql_fetch_array($nodesQuery)) {
				$children[$nodesRow[$this->actualFieldNames['id']]] = $nodesRow;
			} 
			return $children;
		} else {
			return false;
		} 
	} 

	/*
	* getSiblings()
	* Liefert alle Geschwister eines Knotens
	* 
	* @access public
	* @param int $id ID von dem Knoten, dessen Geschwister ermittelt werden sollen
	* @param boolean $aliasFields Stellt bei true fuer alle Felder die 
	*        Aliasnamen ein, die in den Parameter Tabellen auf der 
	*        linken Seite stehen. Bei false werden die realen Felder 
	*        der rechten Seite zurueck geliefert
	* @return mixed $result entweder Array mit Node Werten oder false falls Abfrage fehl schlug
	*/
	function getSiblings($id, $aliasFields = false, $additionalSQL = array())
	{
		$this->_setActualFieldNames();

		if (count($additionalSQL) > 0) {
			$joinParameters = $additionalSQL['join'];
			$fieldParameters = $additionalSQL['field'];
			$whereParameters = $additionalSQL['where'];
			$appendParameters = $additionalSQL['append'];
			$orderByParameters = $additionalSQL['orderby'];
		} 

		$actualNode = $this->getNode($id);
		if ($actualNode[$this->params['root']] != $actualNode[$this->params['id']]) {
			if ($orderByParameters == "") {
				$orderByParameters = "ORDER BY n." . $this->params['l'] . " ASC";
			} 
			$nodesSQL = sprintf("SELECT %s %s FROM %s AS n %s WHERE n.%s = '%s' %s %s %s",
				$this->_queryFieldNameConvert('n', $aliasFields),
				$fieldParameters,
				$this->params['table'],
				$joinParameters,
				$this->params['parent'],
				$actualNode[$this->params['parent']],
				$whereParameters,
				$orderByParameters,
				$appendParameters
				);
		} else {
			if ($orderByParameters == "") {
				$orderByParameters = "ORDER BY n." . $this->params['norder'] . " ASC";
			} 
			$nodesSQL = sprintf("SELECT %s %s FROM %s AS n %s WHERE n.%s = n.%s %s %s %s",
				$this->_queryFieldNameConvert('n', $aliasFields),
				$fieldParameters,
				$this->params['table'],
				$joinParameters,
				$this->params['root'],
				$this->params['id'],
				$whereParameters,
				$orderByParameters,
				$appendParameters
				);
		} 
		$nodesQuery = mysql_query($nodesSQL);
		if ($nodesQuery) {
			while ($nodesRow = mysql_fetch_array($nodesQuery)) {
				$branch[$nodesRow[$this->actualFieldNames['id']]] = $nodesRow;
			} 
			return $branch;
		} else {
			return false;
		} 
	} 

	/*
	* createRootNode()
	* Erzeugt einen Wurzeleintrag
	* 
	* @access public
	* @param array $values Zusatzinformation zum Wurzelknoten 
	*        Hier koennen Werte fuer die Felder uebergeben werden, die als 
	*        Zusatzfeldarray an die Factory uebergeben wurden. Als Key gilt 
	*        der Aliasname (linke Seite des Array's)
	*        Keine Ueberpruefung ob diese Felder korrekt sind.
	* @return int $id ID des erzeugten Eintrags
	*/
	function createRootNode($values)
	{
		mysql_query("LOCK TABLES " . $this->params['table'] . " WRITE");

		/* 
		* Eindeutige letzte ID bekommen 
		*/
		$idQuery = mysql_fetch_array(mysql_query("SELECT " . $this->params['id'] . " FROM " . $this->params['table'] . " ORDER BY " . $this->params['id'] . " DESC LIMIT 1"));
		$id = $idQuery[$this->params['id']] + 1;

		$orderQuery = mysql_query("SELECT " . $this->params['norder'] . " FROM " . $this->params['table'] . " WHERE " . $this->params['root'] . " = " . $this->params['id'] . " ORDER BY " . $this->params['norder'] . " DESC LIMIT 1");
		if ($orderQuery) {
			$orderRow = mysql_fetch_array($orderQuery);
			$order = $orderRow[$this->params['norder']] + 1;
		} else {
			$order = 1;
		} 

		$sql = sprintf("INSERT INTO %s %s",
			$this->params['table'],
			$this->_insertFields($values, array ('id' => $id, 'norder' => $order))
			);
		mysql_query($sql);

		mysql_query("UNLOCK TABLES");
		return $id;
	} 

	/**
	 * CB_NestedSet::updateNode()
	 * Methode zum Aktualisieren von Knoten
	 * 
	 * @param int $id ID des Knotens der upgedated werden soll
	 * @param array $values Array mit Werten die erneuert werden sollen
	 * @return boolean $error
	 */
	function updateNode($id, $values)
	{
		$checkQuery = $this->getNode($id, true);

		mysql_query("LOCK TABLES " . $this->params['table'] . " WRITE");
		$error = false;
		/* 
		* Eindeutige letzte ID bekommen 
		*/
		if ($checkQuery === false) {
			$error = true;
		} 

		if (!is_array($values)) {
			$error = true;
		} 

		if (count($values) == 0) {
			$error = true;
		} 

		if (!$error) {
			$sql = sprintf("UPDATE %s SET %s WHERE %s = '%s'",
				$this->params['table'],
				$this->_updateFields($values),
				$this->params['id'],
				$id
				);
			mysql_query($sql);
		} 

		mysql_query("UNLOCK TABLES");
		return $error;
	} 

	/*
	* createRootNode()
	* Erzeugt einen Kindknoten, Kind wird ans Ende auf dieser Ebene gesetzt
	* 
	* @access public
	* @param  int   $parent ID des Elternknotens
	* @param  array $values Zusatzinformation zum Kindknoten
	*         Hier koennen Werte fuer die Felder uebergeben werden, die als 
	*         Zusatzfeldarray an die Factory uebergeben wurden. Als Key gilt 
	*         der Aliasname (linke Seite des Array's)
	*         Keine Ueberpruefung ob diese Felder korrekt sind.
	* @return int $id ID des erzeugten Eintrags
	*/
	function createSubNode($parent, $values)
	{
		/* 
		* Eltern Infos bekommen
		* SubNode muss zwingend Eltern haben. Diese haben dann weitere benoetigte Infos
		*/
		$parentQuery = $this->getNode($parent);

		if ($parentQuery != false) {
			/* 
			* Wurzel Infos bekommen
			*/
			$rootQuery = $this->getNode($parentQuery[$this->params['root']], true);

			mysql_query("LOCK TABLES " . $this->params['table'] . " WRITE");

			/* 
			* Eindeutige letzte ID bekommen 
			*/
			$idQuery = mysql_fetch_array(mysql_query("SELECT " . $this->params['id'] . " FROM " . $this->params['table'] . " ORDER BY " . $this->params['id'] . " DESC LIMIT 1"));
			$id = $idQuery[$this->params['id']] + 1;

			/*
			* Order Wert der Rootnodes übernehmen
			*/
			$order = $rootQuery[norder];

			/*
			* Standard Daten Array aufbauen. 
			*/
			$standardFields = array ('id' => $id,
				'norder' => $order,
				'parent' => $parent,
				'l' => $parentQuery[$this->params['r']],
				'r' => $parentQuery[$this->params['r']] + 1,
				'level' => $parentQuery[$this->params['level']] + 1,
				'root' => $parentQuery[$this->params['root']]
				);

			/* 
			* Luecke schaffen. Es wird anhand der rechten ID der Mutter 
			* (right der Mutter = right + 1 des letzten Geschisterchens)
			* der Baum um 2 ID Werte vergroeßert
			*/
			$sql = sprintf("UPDATE %s SET %s = %s + 2 WHERE %s >= '%s' AND %s = '%s'",
				$this->params['table'],
				$this->params['r'],
				$this->params['r'],
				$this->params['r'],
				$parentQuery[$this->params['r']],
				$this->params['root'],
				$parentQuery[$this->params['root']]
				);
			mysql_query($sql);

			/* 
			* Luecke schaffen. Das gleiche noch mal fuer die linke ID
			*/
			$sql = sprintf("UPDATE %s SET %s = %s + 2 WHERE %s > '%s' AND %s = '%s'",
				$this->params['table'],
				$this->params['l'],
				$this->params['l'],
				$this->params['l'],
				$parentQuery[$this->params['r']],
				$this->params['root'],
				$parentQuery[$this->params['root']]
				);
			mysql_query($sql);

			/* 
			* Einfuegen des neuen Nodes
			*/
			$sql = sprintf("INSERT INTO %s %s",
				$this->params['table'],
				$this->_insertFields($values, $standardFields)
				);
			mysql_query($sql);

			$result = $id;
			mysql_query("UNLOCK TABLES");
		} else {
			$result = false;
		} 

		return $result;
	} 

	/*
	* sortNodeUp()
	* Methode ermittelt den vorhergehenden Knoten und gibt das ganze an 
	* moveBranch weiter, mit der Option CB_NESE_MOVEBEFORE
	* 
	* @access public
	* @param  int $nodeID ID des zu sortierenden Knoten
	*/
	function sortNodeUp($nodeID)
	{
		$nodeRow = $this->getNode($nodeID, true);
		if ($nodeRow != false) {
			// SQL erzeugen, um den Vorgänger zu bekommen
			if ($nodeRow[root] == $nodeRow[id]) {
				// Wenn der Node Wurzel ist, dann per norder sortieren
				$sql = sprintf("SELECT %s FROM %s WHERE %s = %s AND %s < %s ORDER BY %s DESC LIMIT 0,1",
					$this->params['id'],
					$this->params['table'],
					$this->params['id'],
					$this->params['root'],
					$this->params['norder'],
					$nodeRow[norder],
					$this->params['norder']
					);
			} else {
				// wenn der Node keine Wurzel ist, per leftID sortieren
				$sql = sprintf("SELECT %s FROM %s WHERE %s = %s AND %s < %s AND %s = %s ORDER BY %s DESC LIMIT 0,1",
					$this->params['id'],
					$this->params['table'],
					$this->params['level'],
					$nodeRow[level],
					$this->params['l'],
					$nodeRow['l'],
					$this->params['root'],
					$nodeRow['root'],
					$this->params['l']
					);
			} 
			$result = mysql_query($sql);

			if ($result) {
				$targetNodeID = mysql_fetch_array($result);
				$this->moveBranch($nodeID, $targetNodeID[$this->params['id']], CB_NESE_MOVEBEFORE);
			} 
		} 
	} 

	/*
	* sortNodeDown()
	* Methode ermittelt den vorhergehenden Knoten und gibt das ganze an 
	* moveBranch weiter, mit der Option CB_NESE_MOVEAFTER
	* 
	* @access public
	* @param  int $nodeID ID des zu sortierenden Knoten
	*/
	function sortNodeDown($nodeID)
	{
		$nodeRow = $this->getNode($nodeID, true);
		if ($nodeRow != false) {
			if ($nodeRow[root] == $nodeRow[id]) {
				$sql = sprintf("SELECT %s FROM %s WHERE %s = %s AND %s > %s ORDER BY %s ASC LIMIT 0,1",
					$this->params['id'],
					$this->params['table'],
					$this->params['id'],
					$this->params['root'],
					$this->params['norder'],
					$nodeRow[norder],
					$this->params['norder']
					);
			} else {
				$sql = sprintf("SELECT %s FROM %s WHERE %s = %s AND %s > %s AND %s = %s ORDER BY %s ASC LIMIT 0,1",
					$this->params['id'],
					$this->params['table'],
					$this->params['level'],
					$nodeRow[level],
					$this->params['l'],
					$nodeRow['r'],
					$this->params['root'],
					$nodeRow['root'],
					$this->params['l']
					);
			} 
			$result = mysql_query($sql);

			if ($result) {
				$targetNodeID = mysql_fetch_array($result);
				$this->moveBranch($nodeID, $targetNodeID[$this->params['id']], CB_NESE_MOVEAFTER);
			} 
		} 
	} 

	/*
	* moveBranch()
	* Verschiebt einen Zweig
	* 
	* @access public
	* @param int $nodeID ID des zu verschiebenden Zweiges
	* @param int $targetID ID des Zielzweiges
	* @param int $moveAction 1 für verschieben des Zweiges unter den 
	*            anderen, 2 für verschieben und einsortieren in der 
	*            selben Hierarchie vor dem Zielzweig, 3 für verschieben 
	*            und einsortieren in der selben Hierarchie nach dem Zielzweig
	*/
	function moveBranch($nodeID, $targetID, $moveAction = CB_NESE_MOVEBELOW)
	{
		/*
		* zu verschiebenden Zweig abfragen und testen
		*/
		$moveNode = $this->getNode($nodeID, true);
		if ($moveNode == false) {
			$error[] = "node not found";
		} 

		/*
		* Zielzweig abfragen und testen
		*/
		$targetNode = $this->getNode($targetID, true);
		if ($targetNode == false) {
			$error[] = "targetnode not found";
		} 

		/* 
		* Check auf Rekursion
		*/
		if (($targetNode['root'] == $moveNode['root']) && (($moveNode['l'] <= $targetNode['l']) && ($moveNode['r'] >= $targetNode['r']))) {
			$error[] = "recursion error";
		} 

		/* 
		* wenn keine Fehler auftraten, dann weiter
		*/
		if (!isset($error)) {
			if ($moveAction != CB_NESE_MOVEBELOW) {
				if (($targetNode[root] == $targetNode[id]) && ($moveNode[root] == $moveNode[id])) {
					/*
					* wenn beide Nodes RootNodes sind, muss man anhand norder sortieren.
					*/
					$this->_moveBetweenRootNodes($moveNode, $targetNode, $moveAction);
				} else {
					/*
					* der Einfachheit halber wird der zu verschiebende Zweig als RootNode zwischengespeichert
					*/
					$this->_moveToRoot($nodeID);

					if ($targetNode[root] == $targetNode[id]) {
						/*
						* wenn target auch Root ist, sinds JETZT beide....also sortieren über norder.
						*/
						$this->_moveBetweenRootNodes($moveNode, $targetNode, $moveAction);
					} else {
						/*
						* Ansonsten müssen Löcher gebohrt werden, wo der Zweig 
						* rein passt
						*/
						if ($moveAction == CB_NESE_MOVEBEFORE) {
							$this->_moveRootBeforeTarget($nodeID, $targetID);
						} elseif ($moveAction == CB_NESE_MOVEAFTER) {
							$this->_moveRootAfterTarget($nodeID, $targetID);
						} 
					} 
				} 
			} else {
				if ($moveNode[root] != $moveNode[id]) {
					/*
					* der Einfachheit halber wird der zu verschiebende Zweig als RootNode zwischengespeichert
					*/
					$this->_moveToRoot($nodeID);
				} 
				$this->_moveRootBelowTarget($nodeID, $targetID);
				/*
				* Dem alten Node noch neue ParentID geben
				*/
				$sql = mysql_query("UPDATE " . $this->params['table'] . " SET " . $this->params['parent'] . " = '$targetID' WHERE " . $this->params['id'] . " = '$nodeID'");
			}
			
			$this->setOrderIntegrity();
		} 
	} 
	
	/**
	 * CB_NestedSet::setOrderIntegrity()
	 * Methode stellt sicher, dass die Kinder von Wurzeln immer den selben norder Wert haben
	 * wie die Wurzeln. Des weiteren werden Löcher in den norder Werten gestopft.
	 * Wichtig für die Methode getAllNodes, damit bei der Ausgabe des Baumes die Reihenfolge stimmt
	 * 
	 * @return 
	 **/
	function setOrderIntegrity() {
		$roots = $this->getRootNodes(true);
		if($roots != false) {
			$counter = 1;
			foreach($roots as $v) {
				mysql_query("UPDATE " . $this->params['table'] . " SET " . $this->params['norder'] . " = '$counter' WHERE " . $this->params['root'] . " = '".$v[id]."'");
				++$counter;
			}
		}
	}
	
	/*
	* deleteNode()
	* Loescht einen Zweig
	* 
	* @access public
	* @param int $nodeID ID des zu loeschenden Zweiges
	* @param int $children Was soll mit den Kindern passieren? 1 = loeschen, 2 = verschieben auf die Ebene der jeweiligen Mutter
	* @return array $result ID's aller zu loeschenden Nodes ... zur Weiterverarbeitung
	*/
	function deleteNode($nodeID, $children = '1')
	{
		$nodeQuery = $this->getNode($nodeID);

		mysql_query("LOCK TABLES " . $this->params['table'] . " WRITE");
		if ($nodeQuery != false) {
			/* 
			* alle Nodes auswählen, die nach dem zu löschenden Node kommen,
			* einschließlich dem zu löschenden Node
			*/
			$deleteIDSQL = sprintf("SELECT %s FROM %s WHERE %s BETWEEN %s AND %s AND %s = %s",
				$this->params['id'],
				$this->params['table'],
				$this->params['l'],
				$nodeQuery[$this->params['l']],
				$nodeQuery[$this->params['r']],
				$this->params['root'],
				$nodeQuery[$this->params['root']]
				);

			/* 
			* Array mit allen zu löschenden Nodes aufbauen
			*/
			$deleteIDQuery = mysql_query($deleteIDSQL);
			while ($deleteIDRow = mysql_fetch_array($deleteIDQuery)) {
				$resultSet[] = $deleteIDRow[$this->params['id']];
			} 

			/*
			* Alle Nodes löschen, die nach $nodeID kommen, einschließlich 
			* $nodeID
			*/
			$sql = sprintf("DELETE FROM %s WHERE %s BETWEEN %s AND %s AND %s = %s",
				$this->params['table'],
				$this->params['l'],
				$nodeQuery[$this->params['l']],
				$nodeQuery[$this->params['r']],
				$this->params['root'],
				$nodeQuery[$this->params['root']]
				);
			mysql_query($sql);

			/* 
			* Enstandenes Loch bei den leftIDs schließen
			*/
			$sql = sprintf("UPDATE %s SET %s = %s - ROUND((%s - %s + 1)) WHERE %s > %s AND %s = %s",
				$this->params['table'],
				$this->params['l'],
				$this->params['l'],
				$nodeQuery[$this->params['r']],
				$nodeQuery[$this->params['l']],
				$this->params['l'],
				$nodeQuery[$this->params['r']],
				$this->params['root'],
				$nodeQuery[$this->params['root']]
				);
			mysql_query($sql);

			/* 
			* Enstandenes Loch bei den rightIDs schließen
			*/
			$sql = sprintf("UPDATE %s SET %s = %s - ROUND((%s - %s + 1)) WHERE %s > %s AND %s = %s",
				$this->params['table'],
				$this->params['r'],
				$this->params['r'],
				$nodeQuery[$this->params['r']],
				$nodeQuery[$this->params['l']],
				$this->params['r'],
				$nodeQuery[$this->params['r']],
				$this->params['root'],
				$nodeQuery[$this->params['root']]
				);
			mysql_query($sql);
		} 

		mysql_query("UNLOCK TABLES");

		/*
		* zurücklieferung aller gelöschten ID's zur Weiterverarbeitung
		* bestimmte Elemente, die zu diesen ID's eine Beziehung haben, können
		* dadurch auch gelöscht werden
		*/
		return $resultSet;
	} 

	/*
	* _insertFields()
	* Erzeugt den Feld und Werte Teil des Insert Query's
	* 
	* @access private
	* @param array $values   Zusatzinformation zum Knoten (alles was nicht zum Nested Set gehoert)
	* @param array $standard Array mit Standard Infos, 'id' und 'order' sind zwingende Array Eintraege, alle anderen ('left', 'right', 'level', 'parent') nicht, werden aber auf Standardwerte gesetzt
	* @return string $insertFields Insert String fuer's Query
	*/
	function _insertFields($values, $standard)
	{
		/*
		* Bei den INSERT Werten werden die Grundwerte von CB_NestedSet bestimmt
		*/
		$insertFields = sprintf("(%s, %s, %s, %s, %s, %s, %s",
			$this->params['id'],
			$this->params['parent'],
			$this->params['root'],
			$this->params['l'],
			$this->params['r'],
			$this->params['level'],
			$this->params['norder']
			);

		/*
		* individuelle Felder, die an die Methode übergeben wurden, werden als 
		* zusätzliche INSERT Felder in den String gesetzt
		* $values enthält im Schlüssel die zusätzlichen Felder
		*/
		foreach($values as $k => $v) {
			$insertFields .= sprintf(", %s",
				$this->additional[$k]
				);
		} 

		/*
		* wenn im Standard Feld Array bestimmte wichtige Elemente leer sin, werden
		* Standard Werte gesetzt
		*/
		if ($standard['parent'] == "") {
			$standard['parent'] = '0';
		} 
		if ($standard['root'] == "") {
			$standard['root'] = $standard['id'];
		} 
		if ($standard['l'] == "") {
			$standard['l'] = '1';
		} 
		if ($standard['r'] == "") {
			$standard['r'] = '2';
		} 
		if ($standard['level'] == "") {
			$standard['level'] = '1';
		} 
		if ($standard['norder'] == "") {
			$standard['norder'] = '1';
		} 

		/*
		* die Werte aus dem Standard Array mit den Grundwerten werden ins 
		* INSERT Statement geschrieben
		*/
		$insertFields .= sprintf(") VALUES ('%s', '%s', '%s', '%s', '%s', '%s', '%s'",
			$standard['id'],
			$standard['parent'],
			$standard['root'],
			$standard['l'],
			$standard['r'],
			$standard['level'],
			$standard['norder']
			);

		/* 
		* Nun werden alle Werte der zusätzlichen Felder aus dem $values 
		* Array an den String angefügt
		*/
		foreach($values as $v) {
			$insertFields .= ", '$v'";
		} 

		/*
		* INSERT Statement abschließen
		*/
		$insertFields .= ")";

		/*
		* fertig iss
		*/
		return $insertFields;
	} 

	/**
	 * CB_NestedSet::_updateFields()
	 * 
	 * @param array $values Array mit Additional Werten die erneuert werden sollen
	 * @return string $updateFields alle Felder mit neuen Werten
	 */
	function _updateFields($values)
	{
		/*
		* individuelle UPDATE Felder 
		*/
		$multiple = false;
		foreach($values as $k => $v) {
			if ($multiple == true) {
				$updateFields .= ", ";
			} 
			$updateFields .= sprintf("%s = '%s'",
				$this->additional[$k],
				$v
				);
			$multiple = true;
		} 

		/*
		* fertig iss
		*/
		return $updateFields;
	} 

	/**
	 * CB_NestedSet::_queryFieldNameConvert()
	 * Konvertiert die real existierenden Spaltennamen in die im Parameter 
	 * Array angegebenen Arbeitsnamen.
	 * 
	 * @access private 
	 * @param array $tableIdent Alias Name der Tabelle im Query, da in 
	 *          den einzelnen Get Funktionen teilweise mehrere Versionen 
	 *          der selben Tabelle gehalten werden.
	 * @param array $getArray Array mit Feldern, die im Select String 
	 *          auftauchen sollen. Dadurch soll der Query String so klein 
	 *          wie moeglich gehalten werden koennen.
	 * @return 
	 */
	function _queryFieldNameConvert($tableIdent = false, $aliasFields = false, $getArray = false)
	{
		$convertFields = array_merge($this->params, $this->additional);

		if (!$tableIdent) {
			$tableIdent = "";
		} else {
			$tableIdent = $tableIdent . ".";
		} 

		foreach($convertFields as $k => $v) {
			if ($v != "" && $k != "table") {
				if (($v == $k) || ($aliasFields == false)) {
					$tempField = $tableIdent . $v;
				} else {
					$tempField = $tableIdent . $v . " AS " . $k;
					$this->actualFieldNames[$k] = $k;
				} 
				$queryFields[] = $tempField;
			} 
		} 

		return implode(', ', $queryFields);
	} 

	/**
	 * CB_NestedSet::_setActualFieldNames()
	 * Initialisiert ein Array in dem das param Array und das Additional
	 * Array zusammengefasst sind. Die Werte werden dann gegebenfalls 
	 * ueberschrieben (fuer Alias Funktion)
	 * 
	 * @access private 
	 */
	function _setActualFieldNames()
	{
		$this->actualFieldNames = array_merge($this->params, $this->additional);
	} 

	/**
	 * CB_NestedSet::_moveBetweenRootNodes()
	 * Verschieben von Rootnodes untereinander. RootNodes werden nur anhand der $oder Werte sortiert, stehen also ausserhalb der left - right Regeln
	 * 
	 * @access private 
	 * @param array $moveNode ResultSet von $this->getNode() mit Aliasflag
	 * @param array $targetNode ResultSet von $this->getNode() mit Aliasflag
	 * @param int $moveAction Was soll gemacht werden?
	 */
	function _moveBetweenRootNodes($moveNode, $targetNode, $moveAction)
	{
		mysql_query("LOCK TABLES " . $this->params['table'] . " WRITE");

		/*
		* Alle Root Nodes nach $moveNode müssen einen vorrücken, weil $moveNode
		* ja wegzieht
		*/
		$sql = sprintf("UPDATE %s SET %s = (%s - 1) WHERE %s > %s AND %s != '%s' AND %s = %s",
			$this->params['table'],
			$this->params['norder'],
			$this->params['norder'],
			$this->params['norder'],
			$moveNode[norder] + 1,
			$this->params['id'],
			$moveNode[id],
			$this->params['root'],
			$this->params['id']
			);
		mysql_query($sql);

		mysql_query("UNLOCK TABLES");

		/*
		* $targetNode könnte auch gewandert sein, also aktuelle Werte 
		* ermitteln
		*/
		$targetNode = $this->getNode($targetNode[id], true);

		mysql_query("LOCK TABLES " . $this->params['table'] . " WRITE");

		if ($moveAction == CB_NESE_MOVEBEFORE) {
			/*
			* Loch vor $targetNode einbauen
			*/
			$sql = sprintf("UPDATE %s SET %s = (%s + 1) WHERE %s >= %s AND %s != '%s' AND %s = %s",
				$this->params['table'],
				$this->params['norder'],
				$this->params['norder'],
				$this->params['norder'],
				$targetNode[norder],
				$this->params['id'],
				$moveNode[id],
				$this->params['root'],
				$this->params['id']
				);
			mysql_query($sql);

			/*
			* $moveNode ins Loch setzen
			*/
			$sql = sprintf("UPDATE %s SET %s = '%s' WHERE %s = '%s'",
				$this->params['table'],
				$this->params['norder'],
				$targetNode[norder],
				$this->params['id'],
				$moveNode['id']
				);
			mysql_query($sql);
		} 

		if ($moveAction == CB_NESE_MOVEAFTER) {
			/*
			* Loch hinter $targetNode einbauen
			*/
			$sql = sprintf("UPDATE %s SET %s = %s + 1 WHERE %s >= %s AND %s != '%s' AND %s != '%s' AND %s = %s",
				$this->params['table'],
				$this->params['norder'],
				$this->params['norder'],
				$this->params['norder'],
				$targetNode[norder],
				$this->params['id'],
				$moveNode[id],
				$this->params['id'],
				$targetNode[id],
				$this->params['root'],
				$this->params['id']
				);
			mysql_query($sql);

			/*
			* $moveNode ins Loch setzen
			*/
			$sql = sprintf("UPDATE %s SET %s = '%s' WHERE %s = '%s'",
				$this->params['table'],
				$this->params['norder'],
				$targetNode[norder] + 1,
				$this->params['id'],
				$moveNode['id']
				);
			mysql_query($sql);
		} 

		/*
		* Neue norder Werte auf alle Kinder übertragen
		*/
		// Wurzelknoten abfragen
		$rootNodes = $this->getRootNodes(true);
		if ($rootNodes != false) {
			foreach($rootNodes as $v) {
				mysql_query("UPDATE " . $this->params['table'] . " SET " . $this->params['norder'] . " = '" . $v['norder'] . "' WHERE " . $this->params['root'] . " = '" . $v[id] . "'");
			} 
		} 

		mysql_query("UNLOCK TABLES");
	} 

	/**
	 * CB_NestedSet::_moveToRoot()
	 * Verschiebt einen Node und dessen Kinder und macht aus dem Node
	 * eine Wurzel
	 * 
	 * @access private 
	 * @param array $nodeID ID des zu verschiebenden Zweiges
	 */
	function _moveToRoot($nodeID)
	{
		$orderQuery = mysql_fetch_array(mysql_query("SELECT " . $this->params['norder'] . " FROM " . $this->params['table'] . " ORDER BY " . $this->params['norder'] . " DESC LIMIT 0,1"));

		/*
		* Daten herausfinden. Ist wegen der Left / Right Berechnungen 
		* wichtig, um alle Kinder mit zu verschieben
		*/
		$moveNode = $this->getNode($nodeID, true);

		mysql_query("LOCK TABLES " . $this->params['table'] . " WRITE");

		if ($moveNode != false) {
			/*
			* Verschieben des Nodes und aller Kinder zur Wurzel
			*/
			$sql = sprintf("UPDATE %s SET %s = %s - %s + 1, %s = %s - %s + 1, %s = '%s', %s = %s - %s + 1, %s = '%s' WHERE %s BETWEEN %s AND %s AND %s = '%s'",
				$this->params['table'],
				$this->params['l'],
				$this->params['l'],
				$moveNode[l],
				$this->params['r'],
				$this->params['r'],
				$moveNode[l],
				$this->params['root'],
				$moveNode[id],
				$this->params['level'],
				$this->params['level'],
				$moveNode[level],
				$this->params['norder'],
				$orderQuery[$this->params['norder']] + 1,
				$this->params['l'],
				$moveNode['l'],
				$moveNode['r'],
				$this->params['root'],
				$moveNode['root']
				);
			mysql_query($sql);

			/* 
			* Jetzt ist im alten Zweig ein Loch in den Left / Right Werten
			* Enstandenes Loch bei den leftIDs schließen
			*/
			$sql = sprintf("UPDATE %s SET %s = %s - ROUND((%s - %s + 1)) WHERE %s > %s AND %s = %s",
				$this->params['table'],
				$this->params['l'],
				$this->params['l'],
				$moveNode['r'],
				$moveNode['l'],
				$this->params['l'],
				$moveNode['r'],
				$this->params['root'],
				$moveNode['root']
				);
			mysql_query($sql);

			/* 
			* Jetzt ist im alten Zweig ein Loch in den Left / Right Werten
			* Enstandenes Loch bei den rightIDs schließen
			*/
			$sql = sprintf("UPDATE %s SET %s = %s - ROUND((%s - %s + 1)) WHERE %s > %s AND %s = %s",
				$this->params['table'],
				$this->params['r'],
				$this->params['r'],
				$moveNode['r'],
				$moveNode['l'],
				$this->params['r'],
				$moveNode['r'],
				$this->params['root'],
				$moveNode['root']
				);
			mysql_query($sql);
		} 

		mysql_query("UPDATE " . $this->params['table'] . " SET " . $this->params['parent'] . " = '0' WHERE " . $this->params['id'] . " = '$nodeID'");
		mysql_query("UNLOCK TABLES");
	} 

	/**
	 * CB_NestedSet::_moveRootBelowTarget()
	 * Verschiebt einen Node und dessen Kinder und setzt den Zweig in 
	 * der Hierarchie unter einen bestimmten Zielknoten
	 * 
	 * @access private 
	 * @param array $nodeID ID des zu verschiebenden Zweiges
	 * @param array $targetID ID des Zielknotens
	 */
	function _moveRootBelowTarget($nodeID, $targetID)
	{
		$targetNode = $this->getNode($targetID, true);
		$rootNode = $this->getNode($targetNode['root'], true);
		$moveNode = $this->getNode($nodeID, true);

		/* 
		* Loch in die LeftID's reissen
		*/
		$sql = sprintf("UPDATE %s SET %s = %s + ROUND((%s - %s + 1)) WHERE %s > %s AND %s = %s",
			$this->params['table'],
			$this->params['l'],
			$this->params['l'],
			$moveNode['r'],
			$moveNode['l'],
			$this->params['l'],
			$targetNode['l'],
			$this->params['root'],
			$targetNode['root']
			);
		mysql_query($sql);

		/* 
		* Loch in die RightID's reissen
		*/
		$sql = sprintf("UPDATE %s SET %s = %s + ROUND((%s - %s + 1)) WHERE %s > %s AND %s = %s",
			$this->params['table'],
			$this->params['r'],
			$this->params['r'],
			$moveNode['r'],
			$moveNode['l'],
			$this->params['r'],
			$targetNode['l'],
			$this->params['root'],
			$targetNode['root']
			);
		mysql_query($sql);

		/* 
		* Verschieben des Nodes in das entstandene Loch unter target
		*/
		$sql = sprintf("UPDATE %s SET %s = %s + %s, %s = %s + %s, %s = '%s', %s = %s + %s, %s = '%s' WHERE %s BETWEEN %s AND %s AND %s = '%s'",
			$this->params['table'],
			$this->params['l'],
			$this->params['l'],
			$targetNode[l],
			$this->params['r'],
			$this->params['r'],
			$targetNode[l],
			$this->params['root'],
			$targetNode[root],
			$this->params['level'],
			$this->params['level'],
			$targetNode[level],
			$this->params['norder'],
			$rootNode['norder'],
			$this->params['l'],
			$moveNode['l'],
			$moveNode['r'],
			$this->params['root'],
			$moveNode['root']
			);
		mysql_query($sql);
	} 

	/**
	 * CB_NestedSet::_moveRootBeforeTarget()
	 * Verschiebt einen Node und dessen Kinder und setzt den Zweig in 
	 * der gleichen Hierarchiestufe vor einen bestimmten Zielknoten
	 * 
	 * @access private 
	 * @param array $nodeID ID des zu verschiebenden Zweiges
	 * @param array $targetID ID des Zielknotens
	 */
	function _moveRootBeforeTarget($nodeID, $targetID)
	{
		$targetNode = $this->getNode($targetID, true);
		$rootNode = $this->getNode($targetNode['root'], true);
		$moveNode = $this->getNode($nodeID, true);

		/* 
		* Loch in die LeftID's reissen
		*/
		$sql = sprintf("UPDATE %s SET %s = %s + ROUND((%s - %s + 1)) WHERE %s >= %s AND %s = %s",
			$this->params['table'],
			$this->params['l'],
			$this->params['l'],
			$moveNode['r'],
			$moveNode['l'],
			$this->params['l'],
			$targetNode['l'],
			$this->params['root'],
			$targetNode['root']
			);
		mysql_query($sql);

		/* 
		* Loch in die RightID's reissen
		*/
		$sql = sprintf("UPDATE %s SET %s = %s + ROUND((%s - %s + 1)) WHERE %s >= %s AND %s = %s",
			$this->params['table'],
			$this->params['r'],
			$this->params['r'],
			$moveNode['r'],
			$moveNode['l'],
			$this->params['r'],
			$targetNode['l'],
			$this->params['root'],
			$targetNode['root']
			);
		mysql_query($sql);

		/*
		* Füllen des Loches mit dem Zweig
		*/
		$sql = sprintf("UPDATE %s SET %s = %s + %s - 1, %s = %s + %s - 1, %s = '%s', %s = %s + %s - 1, %s = '%s' WHERE %s BETWEEN %s AND %s AND %s = '%s'",
			$this->params['table'],
			$this->params['l'],
			$this->params['l'],
			$targetNode[l],
			$this->params['r'],
			$this->params['r'],
			$targetNode[l],
			$this->params['root'],
			$targetNode[root],
			$this->params['level'],
			$this->params['level'],
			$targetNode[level],
			$this->params['norder'],
			$rootNode['norder'],
			$this->params['l'],
			$moveNode['l'],
			$moveNode['r'],
			$this->params['root'],
			$moveNode['root']
			);
		mysql_query($sql);

		/*
		* Dem alten Node noch neue ParentID geben
		*/
		$sql = mysql_query("UPDATE " . $this->params['table'] . " SET " . $this->params['parent'] . " = '" . $targetNode['parent'] . "' WHERE " . $this->params['id'] . " = '$nodeID'");
	} 

	/**
	 * CB_NestedSet::_moveRootBeforeTarget()
	 * Verschiebt einen Node und dessen Kinder und setzt den Zweig in 
	 * der gleichen Hierarchiestufe hinter einen bestimmten Zielknoten
	 * 
	 * @access private 
	 * @param array $nodeID ID des zu verschiebenden Zweiges
	 * @param array $targetID ID des Zielknotens
	 */
	function _moveRootAfterTarget($nodeID, $targetID)
	{
		$targetNode = $this->getNode($targetID, true);
		$rootNode = $this->getNode($targetNode['root'], true);
		$moveNode = $this->getNode($nodeID, true);

		/* 
		* Loch in die LeftID's reissen
		*/
		$sql = sprintf("UPDATE %s SET %s = %s + ROUND((%s - %s + 1)) WHERE %s > %s AND %s = %s",
			$this->params['table'],
			$this->params['l'],
			$this->params['l'],
			$moveNode['r'],
			$moveNode['l'],
			$this->params['l'],
			$targetNode['r'],
			$this->params['root'],
			$targetNode['root']
			);
		mysql_query($sql);

		/* 
		* Loch in die RightID's reissen
		*/
		$sql = sprintf("UPDATE %s SET %s = %s + ROUND((%s - %s + 1)) WHERE %s > %s AND %s = %s",
			$this->params['table'],
			$this->params['r'],
			$this->params['r'],
			$moveNode['r'],
			$moveNode['l'],
			$this->params['r'],
			$targetNode['r'],
			$this->params['root'],
			$targetNode['root']
			);
		mysql_query($sql);

		/*
		* Füllen des Loches mit dem Zweig
		*/
		$sql = sprintf("UPDATE %s SET %s = %s + %s, %s = %s + %s, %s = '%s', %s = %s + %s - 1, %s = '%s' WHERE %s BETWEEN %s AND %s AND %s = '%s'",
			$this->params['table'],
			$this->params['l'],
			$this->params['l'],
			$targetNode[r],
			$this->params['r'],
			$this->params['r'],
			$targetNode[r],
			$this->params['root'],
			$targetNode[root],
			$this->params['level'],
			$this->params['level'],
			$targetNode[level],
			$this->params['norder'],
			$rootNode['norder'],
			$this->params['l'],
			$moveNode['l'],
			$moveNode['r'],
			$this->params['root'],
			$moveNode['root']
			);
		mysql_query($sql);

		/*
		* Dem alten Node noch neue ParentID geben
		*/
		$sql = mysql_query("UPDATE " . $this->params['table'] . " SET " . $this->params['parent'] . " = '" . $targetNode['parent'] . "' WHERE " . $this->params['id'] . " = '$nodeID'");
	} 
} 

?>
Return current item: Content*Builder