PX : code

php_tree by Ralf Roeber
Rating: 1.00
Download this code


<?php

class php_tree
{

/***
*
*    +------------------------------------------------------------------------+
*    |                                                                        |
*    | php_tree                                                               |
*    |                                                                        |
*    +------------------------------------------------------------------------+
*    |                                                                        |
*    |   Supplies raw functions to display, inject, retrieve                  |
*    |   and safely delete information from MySQL-database                    |
*    |   holding 'flat' tree information in rows ident, parent,               |
*    |   haschild.                                                            |
*    |                                                                        |
*    +------------------------------------------------------------------------+
*    |                                                                        |
*    |   Auhor:     Ralf Roeber (phpclasses@zeitfenster.de)                   |
*    |              An der Reling 1                                           |
*    |              D-27721 Ritterhude                                        |
*    |              Germany/Deutschland                                       |
*    |   Version:   0.3 - 2003-06-03                                          |
*    |   License:   LGPL;                                                     |
*    |              Cardware ... sending postcard required if used in         |
*    |                           production environment!                      |
*    |                                                                        |
*    +------------------------------------------------------------------------+
*    |   Changelog:                                                           |
*    |   2003-06-03  changed uid to not unique                                |
*    |               added display_full_tree link in header                   |
*    |               added styles_win.css to package                          |
*    |               synchronized example.php and demo.php                    |
*    |               delete_from_db_wholetree($node) introduced               |
*    |               added function to demo                                   |
*    |               set_parameters() ... $debug added                        |
*    |               changed version from 0.2. to 0.3                         |
*    |               got ranked top-2 downloaded class of the week            |
*    |               @ www.phpclasses.org  ... woa                            |
*    |   2003-06-02  added documentation                                      |
*    |               change order in display_full_tree                        |
*    |   2003-06-01  added display_full_tree,                                 |
*    |               populated database with 11000 entries                    |
*    |               and checked on behavior                                  |
*    |                                                                        |
*    +------------------------------------------------------------------------+
*    |                                                                        |
*    |   MySQL-table definition (you need to set this up manually!)           |
*    |                                                                        |
*    |   CREATE TABLE adr_network (                                           |
*    |   ident int(12) NOT NULL auto_increment,                               |
*    |   uid int(12) NOT NULL default '0',                                    |
*    |   gui int(12) NOT NULL default '0',                                    |
*    |   parent int(12) NOT NULL default '-1',                                |
*    |   haschild enum('0','1') NOT NULL default '0',                         |
*    |   email varchar(80) default NULL,                                      |
*    |   UNIQUE KEY ident (ident),                                            |
*    |   KEY parent (parent)                                                  |
*    |   ) TYPE=ISAM PACK_KEYS=1;                                             |
*    |                                                                        |
*    |   ident    .... stores number of database_row_entry,                   |
*    |                 will be incremented automatically on new row inserted  |
*    |   uid      .... uid for special purpose (not essentially needed)       |
*    |   gui      .... stores group id's, makes everything system multi-client|
*    |                 -capable (mandantenfähig)                              |
*    |   parent   .... -1=no parent, x=ident of parent object                 |
*    |   haschild .... 0=has no child, 1=has childs                           |
*    |   email    .... stores text-information to display                     |
*    |                                                                        |
*    |   ident    parent    haschild    uid    gui email                      |
*    |   -----------------------------------------------                      |
*    |    1        -1        1          xxx    999 about first node on root   |
*    |                                                   level with child     |
*    |    2         1        0          xxx    999 faq   1st child of node 1  |
*    |    2        -1        0          xxx    999 news  2nd node root level  |
*    |                                                                        |
*    +------------------------------------------------------------------------+
*    |                                                                        |
*    |   Supplied functions:                                                  |
*    |   ===================                                                  |
*    |                                                                        |
*    |   function set_parameters ($gui,$mode,$db,$table)                      |
*    |                                                                        |
*    |   * set's parameters of class                                          |
*    |   * no return                                                          |
*    |                                                                        |
*    |                                                                        |
*    |   function display_path($node,$reverse_path)                           |
*    |                                                                        |
*    |   * displays the path to given node                                    |
*    |   * returns number of branches and path in array                       |
*    |    -> 11 branches from root node out of 11000 nodes in database        |
*    |       take around 0.2 seconds to compute                               |
*    |                                                                        |
*    |                                                                        |
*    |   function display_reverse_path ($node)                                |
*    |                                                                        |
*    |   * displays reverse path from array gathered in display_path()        |
*    |   * returns html-output                                                |
*    |    -> 11 branches from root node out of 11000 nodes in database        |
*    |       take around 0.2 seconds to compute                               |
*    |                                                                        |
*    |   function display_branch($node)                                       |
*    |                                                                        |
*    |   * displays the branch from given node                                |
*    |   * returns html-output                                                |
*    |   -> 39 root nodes from 11000 nodes in database take around 0.3        |
*    |      seconds to compute                                                |
*    |                                                                        |
*    |   function display_full_tree($node)                                    |
*    |                                                                        |
*    |   * displays the full tree below a given node                          |
*    |   * returns html output                                                |
*    |   -> 11000 nodes take 55 seconds to compute                            |
*    |                                                                        |
*    |   function insert_into_db($father,$child)                              |
*    |                                                                        |
*    |   * insert an object to database                                       |
*    |   * no return                                                          |
*    |                                                                        |
*    |   function delete_from_db($node)                                       |
*    |                                                                        |
*    |   * delete the object refelected by $node from database                |
*    |   * moves childs up to parent                                          |
*    |   * no return                                                          |
*    |                                                                        |
*    |   function delete_from_db_wholetree($node)                             |
*    |                                                                        |
*    |   * deletes the object refelected by $node from database               |
*    |   * deletes also all objects below given $node                         |
*    |   * sets haschild to 0 if noone is left in tree below parent           |
*    |   * no return                                                          |
*    |                                                                        |
*    +------------------------------------------------------------------------+
*    |                                                                        |
*    |   Dedicated to my wife and our son - who give me the trength to        |
*    |   manage my and their life as it everything comes up ...               |
*    |                                                                        |
*    +------------------------------------------------------------------------+
*
*/

    
var $gui;
    var 
$uid;
    var 
$node;
    var 
$mode;
    var 
$father;
    var 
$child;
    var 
$db;
    var 
$branches;
    var 
$reverse_path;
    var 
$display_db_identifier;
    var 
$debug;
    var 
$display_remove_button;

    
/* ************************************* */
    
function set_parameters ($gui,$mode,$db,$table,$show_db_identifier,$debug) {
    
/* ************************************* */
    /***
    *    init class parameter
    */

        
$this->gui $gui;                                   // client-number (mandant)
        
$this->mode $mode;                                 // display mode: 1 ... shows db's values, 3 show's path
        
$this->db $db;                                     // database connection pointer
        
$this->table $table;                               // database table name to work on
        
$this->branches "0";                               // number of branches above node
        
$this->reverse_path = array();                       // stores texts and id for reverse path display
        
$this->display_db_identifier $show_db_identifier;  // show db identifier in tree-view
        
$this->debug $debug;                               // 0=don't show debug information, 1=show debug information
        
$this->display_remove_button "1";                  // 1=show delete button in branch_view

    
}

    
/* *************************************** */
    
function display_path($node,$reverse_path,$print) {
    
/* *************************************** */
    /***
    *    displays the path to the node ... root is right most
    *    return's number of branches above actual node
    */

        
if ($node!="-1") {
            
$qs="SELECT     ident,
                    parent,
                    email
                    FROM     "
.$this->table."
                    WHERE     ident='$node'
                    AND     gui='"
.$this->gui."'";

            if (
$this->debug=="1") { echo $qs."<br>"; }

            
$rc=mysql($this->db,$qs); fehler();
            
$ar=mysql_fetch_array($rc);

            
/*

                print out path to html if $print == 1

            */
            
if ($print=="1") {
                echo 
'\\<a href="?node='.$ar['ident'].'">'.$ar['email'].'</a>';
            }

            if ( 
$ar['parent']!="-1")
            {
                
$this->branches=$this->display_path($ar['parent'],$this->reverse_path,$print);
            };
            
array_push$this->reverse_path, array($this->branches$ar['ident'], $ar['email']) );
        }

        return (
$this->branches+1);

    } 
/* end of function display path */


    /* ******************************* */
    
function display_reverse_path ($node) {
    
/* ******************************* */
    /**
    *    display's reverse path
    *
    *
    */


    /*

        Reset everything to 0

    */
    
$this->branches=0;
    
$this->reverse_path=array();

    
/*

        gather path information without printing (mind trailing 0)

    */
    
$this->display_path($node,$this->reverse_path,"0");

    
/*

        print number of branches above actual node found to display

    */
    
echo "branche no. ".($this->branches+1)." in tree<br>";
    echo 
'\\\\<a href="?node=-1">root</a>\\';

    
/*

        display the path from root to actual node

    */
    
for ($i=0;$i<($this->branches+1);$i++)
    {
        echo 
' <a href="?node='.$this->reverse_path[$i][1].'">'.$this->reverse_path[$i][2].'</a>\\';
    }

    } 
/* end of function display_reverse_path() */



    /* *************************** */
    
function display_branch($node) {
    
/* *************************** */
    /**
    *
    *    displays the branch from selected node one level deep
    *
    */


        /*

            SQL-Query to retrieve all node/branches below current node

        */
        
$qs="SELECT *
                FROM     "
.$this->table."
                WHERE     (parent='$node' or ident='$node')
                AND     gui='"
.$this->gui."'
                ORDER BY ident, parent"
;

        
$rc=mysql($this->db,$qs); fehler();
        
$num=mysql_numrows($rc);


        
/*

            how many nodes have been found in database

        */
        
echo $num." nodes in tree from node $node ($this->mode, $this->gui)<br>";



        
/*

            display branch in html-table style "table_tree"

        */
        
echo '<table class="table_tree">';

        
/*

            tripple through the SQL-resultset and show branch
            each node/branch is one table row

        */
        
for($i=0;$i<$num;$i++) {

            
$ar=mysql_fetch_array($rc);
            echo 
'<tr>';
            
// echo '<td>'.$i.'</td>';

            
if ($ar['haschild']=="1") {
                
/*
                    yes, has childs
                */
                
if ($node==$ar['ident']) {
                    
// root of the tree
                    
$link_node=$ar['parent'];
                    echo 
'<td class="row_root"> </td><td><a href="?node='.$link_node.'">-</a></td><td>'.$ar['email'].'</td>';
                }
                else
                {
                    
// leaf with childs
                    
$link_node=$ar['ident'];
                    echo 
'<td class="row_leaf">  </td><td><a href="?node='.$link_node.'">+</a></td><td><a href="?node='.$ar['ident'].'">'.$ar['email'].'</a></td>';
                }
            }
            else
            {
                
/*
                    no, childs not present
                */
                
if ($node!=$ar['ident']) {
                    
// root of the tree without childs
                    
echo '<td class="row_leaf"> </td><td> </td><td><a href="?node='.$ar['ident'].'">'.$ar['email'].'</a></td>';
                }
                else
                {
                    
// leaf without childs
                    
echo '<td class="row_leaf"> </td><td> </td><td>'.$ar['email'].'</td>';
                }
            }

            
// echo '<td>'.$ar['uid'].'</td>';

            /*

                show database values ...

            */
            
if ($this->display_db_identifier=="1") {
                echo 
'<td>'.$ar['haschild'].'</td>';
                echo 
'<td>'.$ar['parent'].'</td>';
                echo 
'<td>'.$ar['ident'].'</td>';
            }



            
/*

                show delete button to ease destroying data

            */
            
if ($this->display_remove_button=="1") {
                echo 
'<td>';
                echo 
'<form method="POST">';
                echo 
'<input type="hidden" name="action" value="delete">';
                echo 
'<input type="hidden" name="node" value="'.$ar['ident'].'">';
                echo 
'<input type="hidden" name="parent_node" value="'.$ar['parent'].'">';
                echo 
'<input type="submit" name="submit" value="DEL" class="button">';
                echo 
'</form>';
                echo 
'</td>';
            }

            echo 
'</tr>';

        }

        echo 
"</table>";

    } 
/* end of function display_tree */


    /* ****************************** */
    
function display_full_tree($node,$branches) {
    
/* ****************************** */
    /***
    *
    *    displays full tree
    *
    */


        // $this->node="89";    // just for testing


        
$pix_node="pixel/ftv2mnode.gif";
        
$pix_node1="pixel/ftv2node.gif";
        
$pix_node2="pixel/ftv2lastnode.gif";

        
$qs="SELECT *
                FROM     "
.$this->table."
                WHERE     (parent='$node')
                AND     gui='"
.$this->gui."'
                ORDER BY parent"
;

        
$rc=mysql($this->db,$qs); fehler();
        
$num=mysql_numrows($rc);

        echo 
'<div style="border-left:1px solid blue; background-color:#E0E0E0; width:400px; border-collapse:collapse">';
        for (
$i=0;$i<$num;$i++) {
            
$ar=mysql_fetch_array($rc);
            
$link_node=$ar['ident'];
            
$disp_string=$ar['email']."...[".$ar['haschild']." ".$ar['ident']." ".$ar['parent']."]";
            echo 
'<div style="border:1px solid black; background-color:#E0E000; width:300px; vertical-align:middle; padding:2px;">';
            echo 
'<a href="?node='.$link_node.'">'.$disp_string.'</a>';
            echo 
'</div>';
            if ( 
$ar['haschild']=="1" ) {
                
$branches=$branches+1;
                echo 
'<div style="margin-left:10px; background-color:#E0E0E0; width:400px; border-collapse:collapse">';
                
$branches=$this->display_full_tree($ar['ident'],$branches);
                echo 
'</div>';
            }
        }
        echo 
'</div>';

        return(
$branches-1);

    } 
/* end of function display_full_tree */



    /* ********************************** */
    
function insert_into_db($father$child$uid) {
    
/* ********************************** */
    /**
    *
    *    injects an object to the database
    *
    */


        /*

            first retrieve information about father
            (just in case someone has changed database
            in between)


        */
        
$qs="SELECT
                ident,
                uid,
                gui,
                parent
            FROM "
.$this->table."
            WHERE ident='"
.$father."'
            AND gui='$this->gui'"
;
        
$rc=mysql($this->db,$qs); fehler();
        
$num=mysql_numrows($rc);


        
/*

            Check if father still present

        */
        
if ($num=="0")
        {
            
// if father not present anymore or not given
            // put new object in root position
            
$parent="-1";
        }
        else
        {
            
// father present
            
$parent=$father;
        }

        
/*

            SQL-statement to insert new object

        */
        
if (!isset($this->uid)) { $this->uid=time(); }
        
$qs="INSERT INTO ".$this->table."
            SET parent='$parent',
                uid='"
.$this->uid."',
                gui='"
.$this->gui."',
                email='"
.$child."'";
        
$rc=mysql($this->db,$qs); fehler();


        
/*

            if father present, set father.haschild to 1

        */
        
if ( $parent!="-1") {

            
// update parent set haschild=1
            
$qs="UPDATE ".$this->table."
                SET haschild='1'
                WHERE ident='"
.$parent."'
                AND gui='"
.$this->gui."'";
            
$rc=mysql($this->db,$qs); fehler();
        }

    } 
/* end of function insert_into_db */



    /* *************************** */
    
function delete_from_db $node )
    
/* *************************** */
    /**
    *
    *     remove data in a save way
    *     -> moves childs one level up to parents
    *
    */
    
{

        
// see if node has_childs
        
$qs="SELECT
                ident,
                uid,
                gui,
                parent,
                haschild
            FROM "
.$this->table."
            WHERE ident='"
.$node."'
            AND gui='$this->gui'"
;
        
$rc=mysql($this->db,$qs); fehler();
        
$num=mysql_numrows($rc);

        if (
$this->debug=="1") { echo $qs."<br>"; }

        
$ar=mysql_fetch_array($rc);

        
// if haschilds
        
if ($ar['haschild']=="1")
        {
            
// move childs up to parents
            
$qs="UPDATE ".$this->table."
                SET PARENT='"
.$ar['parent']."'
                WHERE parent='"
.$node."'";
            
$rc2=mysql($this->db,$qs); fehler();
            
$num2=mysql_numrows($rc);

            echo 
$num2." childs moved to parent node ".$ar['parent']."<br>";

            if (
$this->debug=="1") { echo $qs."<br>"; }

        }

        
// remove node itself is now save
        
$qs="DELETE FROM ".$this->table."
            WHERE ident='"
.$node."'
            LIMIT 1"
;                    // limit just for safety reason ;-)
        
$rc3=mysql($this->db,$qs); fehler();
        
$num3=mysql_numrows($rc);

        if (
$this->debug=="1") { echo $qs."<br>"; }

        echo 
$node." removed from database.<br>";

    } 
/* end of function delete_from_db */

    /* *************************** */
    
function delete_from_db_wholetree $node )
    
/* *************************** */
    /**
    *
    *     remove all data below given node
    *     -> also removes childs and childs of child
    *
    */
    
{

        
// see what to delete
        
$qs="SELECT *
                FROM     "
.$this->table."
                WHERE    parent='$node'
                AND     gui='"
.$this->gui."'
                ORDER BY parent"
;

        
$rc=mysql($this->db,$qs); fehler();
        
$num=mysql_numrows($rc);


        
// delete everything below
        
for ($i=0;$i<$num;$i++) {
            
$ar=mysql_fetch_array($rc);
            
$link_node=$ar['ident'];

            
// remove node
            
$qs="DELETE FROM ".$this->table."
                WHERE ident='"
.$link_node."'
                AND     gui='"
.$this->gui."'
                LIMIT 1"
;                    // limit just for safety reason ;-)
            
$rc3=mysql($this->db,$qs); fehler();
            
$num3=mysql_numrows($rc);

            if (
$this->debug=="1") { echo $qs."<br>"; }

            
// if haschild remove them
            
if ( $ar['haschild']=="1" ) {
                
$this->delete_from_db_wholetree($ar['ident']);
            }
        }

        
// see what has been deleted and where is the parent
        
$qs="SELECT *
                FROM     "
.$this->table."
                WHERE     (ident='"
.$node."')
                AND     gui='"
.$this->gui."'
                ORDER BY parent"
;

        
$rc=mysql($this->db,$qs); fehler();
        
$num=mysql_numrows($rc);
        if (
$this->debug=="1") { echo $qs."<br>"; }

        
// update parent ... remove haschild information if only one is left
        
$parent=mysql_result($rc,0,"parent");
        
$qs="SELECT *
                FROM     "
.$this->table."
                WHERE    ident='"
.$parent."'
                AND      gui='"
.$this->gui."'";

        
$rc=mysql($this->db,$qs); fehler();
        
$num=mysql_numrows($rc);

        if (
$num==1) {
            
// change haschild to 0 if no one else is here
            
$qs="UPDATE ".$this->table."
                SET haschild='0'
                WHERE ident='"
.$parent."'
                AND     gui='"
.$this->gui."'
                LIMIT 1"
;                // limit 1 just for safety
            
if ($this->debug=="1") { echo $qs."<br>"; }
            
$rc=mysql($this->db,$qs); fehler();
            
$num=mysql_numrows($rc);
        }

        
// remove node itself
        
$qs="DELETE FROM ".$this->table."
            WHERE ident='"
.$node."'
            AND     gui='"
.$this->gui."'
            LIMIT 1"
;                    // limit just for safety reason ;-)
        
$rc3=mysql($this->db,$qs); fehler();
        
$num3=mysql_numrows($rc);


    } 
/* end of function delete_from_db_wholetree */



/* end of php_tree class */
?>

Comments or questions?
PX is running PHP 5.2.17
Thanks to Miranda Productions for hosting and bandwidth.
Use of any code from PX is at your own risk.