User:Woozle/tree.php

from HTYP, the free directory anyone can edit if they can prove to me that they're not a spambot
Jump to: navigation, search

About

This implements a hierarchy ("acyclic directional graph", I think...) where each node can have zero or more children and zero or one parent.

This is the version where node names are only kept in the parent, which can make debugging difficult.

Code

<php><?php /*

 FILE: tree.php -- general tree-handling classes
 HISTORY:
   2010-10-13 Extricated from shop.php
   2011-12-18 added access counter ($intRefs)
  • /

class clsTreeNode {

   public $vVal;	// data value
   protected $arSubs;	// sub-nodes
   protected $objParent;
   protected $intRefs;
   /*----
     ACTION: Creates node with a set of subnodes
     USED BY: clsShopCart::AddrShipObj() etc.
     DEPRECATED:

- difficult to search for - blocks other possible initializations (PHP has no function overloading)

   */
   public function __construct($iNodes=NULL) {

if (is_array($iNodes)) { $this->arSubs = $iNodes;

foreach ($iNodes as $name => $node) { $node->Parent($this); } } $this->objParent = NULL;

   }
   public function Parent(clsTreeNode $iNode=NULL) {

if (!is_null($iNode)) { $this->objParent = $iNode; } return $this->objParent;

   }
   public function HasParent() {

return (!is_null($this->objParent));

   }
   protected function NodeAdd($iName,clsTreeNode $iNode) {

$this->arSubs[$iName] = $iNode; $iNode->Parent($this);

   }
   public function Node($iName,clsTreeNode $iNode=NULL) {

if (!is_null($iNode)) { $this->NodeAdd($iName,$iNode); } if (isset($this->arSubs[$iName])) { return $this->arSubs[$iName]; } else { return NULL; }

   }
   public function Exists($iName) {

if (isset($this->arSubs[$iName])) { return isset($this->arSubs[$iName]); } else { return FALSE; }

   }
   public function Loaded($iName=NULL) {

if (is_null($iName)) { return isset($this->vVal); } else { if ($this->Exists($iName)) { return $this->Node($iName)->Loaded(); } else { return FALSE; } }

   }
   /*----
     RETURNS: TRUE if there's a value by that name that is loaded.
     NOTE: The value may exist, but if it's not loaded this will still be FALSE.

Why do we do it that way? DOCUMENT!! Might not be the way to do it.

   */
   public function Filled($iName=NULL) {

if (is_null($iName)) { if (!$this->Loaded()) { $this->vVal = $this->Value(); // is this in danger of being recursive? } return !empty($this->vVal); } else { if ($this->Loaded($iName)) { return $this->Node($iName)->Filled(); } else { return FALSE; } }

   }
   public function Spawn() {

$obj = new clsTreeNode(); return $obj;

   }
   public function Value($iVal=NULL) {

if (!is_null($iVal)) { $this->vVal = $iVal; } return $this->vVal;

   }
   /*----
     FUTURE: For consistency, should probably be renamed NodeValue()
   */
   public function SubValue($iName,$iVal=NULL) {

if (!is_null($iVal)) { $obj = $this->Spawn(); $obj->Value($iVal); } else { $obj = NULL; } return $this->Node($iName,$obj)->Value();

   }
   public function Nodes($iNodes=NULL) {

if (is_array($iNodes)) { $this->arSubs = $iNodes; } return $this->arSubs;

   }
   public function HasNodes() {

if (isset($this->arSubs)) { return (count($this->arSubs) > 0); } else { return FALSE; }

   }
   public function AccessCount() {

return $this->intRefs;

   }
   public function IncCount() {

$this->intRefs++;

   }
   public function ResetCount() {

$this->intRefs = 0; if ($this->HasNodes()) { foreach ($this->Nodes() as $name => $node) { $node->ResetCount(); } }

   }
   public function DumpHTML() {

$out = NULL; if ($this->intRefs > 0) { $out = '[x'.$this->intRefs.']'; } $this->intRefs++; if ($this->HasNodes()) {

$out = '

    '; foreach ($this->Nodes() as $name => $node) { $isAlias = ($node->Parent() != $this); if ($isAlias) { $out .= ''; } $strCls = get_class($node); $out .= '
  • ['.$strCls.'] '.$name.' = ['.$node->Value().']'; $out .= $node->DumpHTML(); if ($isAlias) { $out .= ''; } if (!$node->HasParent()) { $out .= '
    • INTERNAL ERROR: parent not set
    ';

    } }

    $out .= '

';

} return $out;

   }

}</php>