← Back to team overview

anewt-developers team mailing list archive

[Branch ~uws/anewt/anewt.uws] Rev 1756: [xml/dom] Implement ArrayAccess interface for DOM nodes

 

------------------------------------------------------------
revno: 1756
committer: Wouter Bolsterlee <uws@xxxxxxxxx>
branch nick: anewt.uws
timestamp: Tue 2010-02-16 20:09:07 +0100
message:
  [xml/dom] Implement ArrayAccess interface for DOM nodes
  
  The main XML DOM node class now implements the ArrayAccess
  interface.
  
  This means that you can now use fancy code like this:
  
    $div = ax_div();
    $div['style'] = 'background-color: red;'
    $div[] = ax_p('The first paragraph in the div.');
    $div[] = ax_p('The second paragraph in the div.');
    $div[0]['id'] = 'first-paragraph';
    $div[-1]['id'] = 'last-paragraph';
  
  This works for all DOM nodes, including XML document
  fragments (except for setting attributes, since fragments do
  not have attributes.)
  
  Part of bug #514479.
modified:
  xml/dom.lib.php


--
lp:anewt
https://code.launchpad.net/~uws/anewt/anewt.uws

Your team Anewt developers is subscribed to branch lp:anewt.
To unsubscribe from this branch go to https://code.launchpad.net/~uws/anewt/anewt.uws/+edit-subscription.
=== modified file 'xml/dom.lib.php'
--- xml/dom.lib.php	2010-01-06 20:56:33 +0000
+++ xml/dom.lib.php	2010-02-16 19:09:07 +0000
@@ -34,7 +34,7 @@
  * \todo: Implement first_child, last_child, previous_sibling and next_sibling
  * attributes in node trees.
  */
-abstract class AnewtXMLDomNode
+abstract class AnewtXMLDomNode implements ArrayAccess
 {
 	/**
 	 * The node type.
@@ -238,6 +238,7 @@
 			$out = $new_child; 
 		}
 
+		unset ($new_child);
 		return $out;
 	}
 
@@ -341,7 +342,7 @@
 		assert('$old_child instanceof AnewtXMLDomNode;');
 
 		/* TODO: implement */
-		trigger_error('Not implemented', E_USER_ERROR);
+		throw new AnewtException('Not implemented: %s::%s()', __CLASS__, __FUNCTION__);
 	}
 
 	/**
@@ -382,6 +383,110 @@
 	{
 		return (bool) $this->child_nodes;
 	}
+
+	/** \{
+	 * \name Array access methods
+	 *
+	 * TODO: document behaviour
+	 */
+
+	public function offsetGet($offset)
+	{
+		/* Elements */
+
+		if (is_int($offset))
+		{
+			$n_child_nodes = count($this->child_nodes);
+
+			if ($offset < 0)
+			{
+				if (abs($offset) > $n_child_nodes)
+					throw new AnewtException(
+						'No element with index %d (element has only %d child nodes)', $offset, $n_child_nodes);
+
+				$offset += $n_child_nodes;
+			}
+
+			return $this->child_nodes[$offset];
+		}
+
+
+		/* Attributes */
+
+		if (is_string($offset))
+			return $this->get_attribute($offset);
+
+		throw new AnewtException('Array offset must be a string (for attributes) or an integer (for child nodes)');
+	}
+
+	public function offsetSet($offset, $value)
+	{
+		/* Elements */
+
+		if (is_int($offset))
+			/* FIXME: hook into replace_child() when implemented */
+			throw new AnewtException('Replacing child nodes is not implemented');
+
+		elseif (is_null($offset))
+			/* Array append operator was used, e.g.
+			 *
+			 *   $parent_node[] = $child-node;
+			 *
+			 * This is perhaps the most useful part of the ArrayAccess
+			 * interface for this class, since it can make XML (or XHTML) code
+			 * much easier to read and write.
+			 */
+			$this->append_child($value);
+
+
+		/* Attributes */
+
+		elseif (is_string($offset))
+			$this->set_attribute($offset, $value);
+
+		else
+			throw new AnewtException('Array offset must be a string (for attributes) or an integer (for child nodes)');
+	}
+
+	public function offsetExists($offset)
+	{
+		/* Elements */
+
+		if (is_int($offset))
+			return array_key_exists($offset, $this->child_nodes);
+
+
+		/* Attributes */
+
+		elseif (is_string($offset))
+			return $this->has_attributes($offset);
+
+
+		throw new AnewtException('Array offset must be a string (for attributes) or an integer (for child nodes)');
+	}
+
+	public function offsetUnset($offset)
+	{
+		/* Elements */
+
+		if (is_int($offset))
+		{
+			/* Remove the child, if set */
+			if ($this->offsetExists($offset))
+				return $this->remove_child($this->offsetGet($offset));
+		}
+
+
+		/* Attributes */
+
+		elseif (is_string($offset))
+			$this->remove_attribute($offset);
+
+		else
+			throw new AnewtException('Array offset must be a string (for attributes) or an integer (for child nodes)');
+	}
+
+	/** \} */
 }