Graphical tree like Explorer


کد PHP:


<?PHP
  
/* 
Here  are  the  database  definitions used in  this  code.
It should be fairly east to  adapt  it  to  another  database.
*/
  
/*
CREATE  TABLE  dirent_types  (
        id        INTEGER  NOT  NULL,
        icon        VARCHAR(50),
        name        VARCHAR(50),
        PRIMARY  KEY(id)
);
  
INSERT  INTO  dirent_types  VALUES(1,  'folderclosed',  'Directory');
INSERT  INTO  dirent_types  VALUES(2,  'document',  'File');
  
CREATE  TABLE  directory  (
        id        INTEGER  NOT  NULL,
        parent        INTEGER  REFERENCES  directory(id),
        name        VARCHAR(200),
        icon        VARCHAR(50),
        type        INTEGER  REFERENCES  dirent_types(id),
        url        VARCHAR(200),
        PRIMARY  KEY(id)
);
  
DROP  INDEX  directory_idx;
  
CREATE  UNIQUE  INDEX  directory_idx  ON  directory(parent,  name);
  
CREATE  SEQUENCE  dirent_id;
  
"CREATE  PROCEDURE  insert_dir_entry
        (name  VARCHAR,  parent  INTEGER,  type  INTEGER)
        RETURNS(id  INTEGER)
BEGIN
        EXEC  SQL  WHENEVER  SQLERROR  ABORT;
        EXEC  SEQUENCE  dirent_id.NEXT  INTO  id;
        EXEC  SQL  PREPARE  c_insert
                INSERT  INTO  directory
                        (id,  parent,  type,  name)
                        VALUES(?,  ?,  ?,  ?);
        EXEC  SQL  EXECUTE  c_insert  USING  (id,  parent,  type,  name);
        EXEC  SQL  DROP  c_insert;
END";
  
CALL  insert_dir_entry('My  Computer',  NULL,  1);
CALL  insert_dir_entry('Network  Neighbourhood',  NULL,  1);
CALL  insert_dir_entry('lucifer.guardian.no',  2,  1);
CALL  insert_dir_entry('rafael.guardian.no',  2,  1);
CALL  insert_dir_entry('uriel.guardian.no',  2,  1);
CALL  insert_dir_entry('Control  Panel',  NULL,  1);
CALL  insert_dir_entry('Services',  6,  1);
CALL  insert_dir_entry('Apache',  7,  2);
CALL  insert_dir_entry('Solid  Server  2.2',  7,  2);
  
*/
  
FUNCTION  icon($icon,  $name  =  '',  $width  =  0,  $height  =  0)  {
        GLOBAL  
$DOCUMENT_ROOT;
        
$icon_loc  =  '/pics/menu';
        
$file  =  "$DOCUMENT_ROOT$icon_loc/$icon.gif";
        IF  (!
$width  ||  !$height)  {
        
$iconinfo  =  GETIMAGESIZE($file);
        IF  (!
$width)  {
                
$width  =  $iconinfo[0];
        }
        IF  (!
$height)  {
                
$height  =  $iconinfo[1];
        }
        }
        
PRINTF'<img%s  border=0  align=top  src="/pics/menu/%s.gif"  '.
              
'width="%d"  height="%d">',  $name  ?  "  name=\"$name\""  :  '',
              
$icon,  $width,  $height);
}
  
/*
  *  Displays,  recursively,  the  contents  of  a  tree  given  a  starting
  *  point.
  *
  *  Parameters:
  *      $parent  -  the  parent  node  (not  listed  in  the  directory).    Node
  *          0  is  the  root  node.
  *
  *      $maxdepth  (optional)  -  maximum  number  of  recursion  levels.    -1
  *          (the  default  value)  means  no  limits.
  *
  *      $ancestors  (optional)  -  an  array  of  the  ancestor  nodes  in  the
  *          current  branch  of  the  tree,  with  the  node  closest  to  the
  *          top  at  index  0.
  *
  *  Global  variables  used:
  *      $child_nodes
  *      $node_data
  *      $last_child
  *
  *  Global  variables  modified:
  *      The  array  pointers  in  $child_nodes  will  be  modified.
  */
FUNCTION  display_directory($parent,  $showdepth  =  0,  $ancestors  =  FALSE)  {
        GLOBAL  
$child_nodes,  $node_data,  $last_child;
        
RESET($child_nodes[$parent]);
        
$size  =  SIZEOF($child_nodes[$parent]);
        
$lastindex  =  $size  -  1;
        IF  (!
$ancestors)  {
        
$ancestors  =  ARRAY();
        }
        
$depth  =  SIZEOF($ancestors);
        
PRINTF'<div  id="node_%d"  class="dirEntry"  visibility="%s">',
              
$parent,  $showdepth  >  0  ?  'show'  :  'hide');
        WHILE  (LIST(
$index,  $node)  =  EACH($child_nodes[$parent]))  {
        
/*
            For  each  of  the  uptree  nodes:
            If  an  uptree  node  is  not  the  last  one  on  its  depth
            of  the  branch,  there  should  be  a  line  instead  of  a  blank
            before  this  node's  icon.
          */
        
FOR  ($i  =  0;  $i  <  $depth;  $i++)  {
                
$up_parent  =  (int)$node_data[$ancestors[$i]][ 'parent'];
                
$last_node_on_generation  =  $last_child[$up_parent];
                
$uptree_node_on_generation  =  $ancestors[$i];
                IF  (
$last_node_on_generation  ==  $uptree_node_on_generation)  {
                
icon"blank");
                }  ELSE  {
                
icon"line");
                }
        }
        IF  (
$child_nodes[$node])  {  //  has  children,  i.e.  it  is  a  folder
                
$conn_icon  =  "plus";
                
$expand  =  TRUE;
        }  ELSE  {
                
$conn_icon  =  "join";
                
$expand  =  FALSE;
        }
        IF  (
$index  ==  $lastindex)  {
                
$conn_icon  .=  "bottom";
        }  ELSEIF  (
$depth  ==  0  &&  $index  ==  0)  {
                
$conn_icon  .=  "top";
        }
        IF  (
$expand)  {
                
PRINTF"<a  href=\"javascript<b></b>:document.layers['node_%d'].visibility='show'\">",  $node);
        }
        
icon($conn_icon,  "connImg_$node");
        IF  (
$expand)  {
                PRINT( 
"</a>");
        }
        
$icon  =  $node_data[$node][ 'icon'];
        IF  (!
$icon)  {
                
$type  =  $node_data[$node][ 'type'];
                
$icon  =  $GLOBALS'dirent_icons'][$type];
        }
        
icon($icon,  "nodeImg_$node");
         
$name  =  $node_data[$node][ 'name'];
        
PRINTF'?<font  size="%d">%s</font><br%c>',  -1,  $name,  10);
        IF  (
$child_nodes[$node])  {
                
$newdepth  =  $showdepth;
                IF  (
$newdepth  >  0)  {
                
$newdepth--;
                }
                
$new_ancestors  =  $ancestors;
                
$new_ancestors[]  =  $node;
                
display_directory($node,  $newdepth,  $new_ancestors);
        }
        }
        PRINT( 
"</div\n>");
}
 FUNCTION  
setup_directory($parent,  $maxdepth)
{
        GLOBAL  
$dirent_icons,  $child_nodes,  $node_data,  $last_child;
         
$dirent_icons  =  sql_assoc'SELECT  id,icon  FROM  dirent_types');
         
$query  =  'SELECT  id,parent,type,icon,name  '.
                  
'FROM  directory  '.
                  
'ORDER  BY  parent,name';
         
$child_nodes  =  ARRAY();
        
$node_data  =  ARRAY();
        
$res  =  sql($query);
        WHILE  (LIST(
$id,  $parent,  $type,  $icon,  $name)  =  db_fetch_row($res))  {
        
$child_nodes[(int)$parent][]  =  $id;
        
$node_data[$id]  =  ARRAY( 'id'  =>  $id,
                                
'parent'  =>  $parent,
                                
'type'  =>  $type,
                                
'icon'  =>  $icon,
                                
'name'  =>  $name);
        
$last_child[(int)$parent]  =  $id;
        }
}
 
?>