Scripts

OO Html Tabel

Omdat ik laatste dagen wat table classen ben tegen gekomen zal ik diegene die ik ook altijd gebruik ook posten. Dit is volledig OO opgezet en maakt ook gebruik van SPL interfaces. Heb poor mans namespacing toegepast omdat ik het voor 5.x compatible wil hebben.

oo-html-tabel
library/My/Html/Element/Abstract.php:

<?php
	/**
	 *
	 */

	/**
	 * Class from which every html should be extended
	 * 
	 * @abstract
	 */
	abstract class My_Html_Element_Abstract {
		
		/**
		 * Are the elements defined in XHTML?
		 * @static
		 * @var	bool
		 */
		protected static $_xhtml = true;
		
		/**
		 * Set/get whether xhtml will be used
		 * 
		 * @param	bool|null	$bool
		 *
		 * @return	void|bool
		 */
		public static function xhtml ( $bool = null ) {
			
			if ( $bool === null ) {
				return self::$_xhtml;
				
			}
			
			self::$_xhtml = (bool)$bool;
		
		}
		
		/**
		 * Holds all the attributes for this element.
		 * @var	array
		 */
		protected $_attribs = array ();
		
		/**
		 * Class constructor
		 *
		 * @param	array	$attribs
		 */
		public function __construct ( array $attribs = array () ) {
			
			if ( count ( $attribs ) ) {
				$this->setAttribs ( $attribs );
				
			}
		
		}
		
		/**
		 * Try to render the element
		 *
		 * @return	string
		 */
		public function __toString () {
			
			try {
				return $this->render ();
				
			} catch ( Exception $e ) {
				return '';
				
			}
			
		}
		
		/**
		 * The method for rendering
		 *
		 * @abstract
		 *
		 * @return	string
		 */
		public abstract function render ();
		
		/**
		 * Set an attribute
		 *
		 * @param	string	$attrib
		 * @param	string 	$value
		 *
		 * @return 	My_Html_Element_Abstract
		 */
		public function setAttrib ( $attrib, $value ) {
			$this->_attribs [ $attrib ] = $value;
			
			return $this;
			
		}
		
		/**
		 * Set attributes
		 *
		 * @param	array	$attribs
		 *
		 * @return	My_Html_Element_Abstract
		 */
		public function setAttribs ( $attribs ) {
			$this->_attribs = array_merge ( $this->_attribs, $attribs );
			
			return $this;
			
		}
		
		/**
		 * Has this elment an attribute?
		 *
		 * @param	string	$attrib
		 *
		 * @return	bool
		 */
		public function hasAttrib ( $attrib ) {
			return array_key_exists ( $attrib, $this->_attribs );
			
		}
		
		/**
		 * Method for rendering the attribute string
		 *
		 * @param	array	$extras	OPTIONAL
		 *
		 * @return	string
		 */
		protected function _attribString ( array $extras = array () ) {
			
			// First initialize
			$return = array ();
			$attribs = $this->_attribs;
			
			// Maybe some extra attributes were given
			foreach ( $extras as $attrib => $value ) {
				
				if ( empty ( $value ) ) {
					continue;
					
				}
				
				// Maybe special functions are used? (+, -)
				$first = substr ( $attrib, 0, 1 );
				$key = substr ( $attrib, 1 );
				
				// Switch on special function
				switch ( $first ) {
					case '+':	// Append this new value to the current value
						
						if ( isset ( $attribs [ $key ] ) ) {
							$attribs [ $key ] .= ' ' . $value;
							
						} else {
							$attribs [ $key ] = $value;
							
						}
						
						break;
					
					case '-':	// Remove this new value from the current value
						
						if ( isset ( $attribs [ $key ] ) ) {
							$exploded = explode ( ' ', $attribs [ $key ] );
							
							foreach ( $exploded as $k => $v ) {
								
								if ( $v === $value ) {
									unset ( $exploded [ $k ] );
									
								}
								
							}
							
							$attribs [ $key ] = implode ( ' ', $exploded );
							
						}
						
						break;
					
					default:	// Just set the value
						$attribs [ $attrib ] = $value;
					
				}
				
			}
			
			// Render the string
			foreach ( $attribs as $attrib => $value ) {
				
				if ( $value === null ) {
					continue;
					
				}
				
				$return [] = $attrib . '=' . '"' . htmlentities ( $value ) . '"';
				
			}
			
			// Return nothing on empty, else separated by spaces
			if ( count ( $return ) === 0 ) {
				return  '';
				
			} else {
				return ' ' . implode ( ' ', $return );
				
			}
			
		}
		
	}
?>

library/My/Html/Element/Table.php:
<?php
	/**
	 *
	 */
	
	/**
	 * Base class for the table element
	 */
	class My_Html_Element_Table extends My_Html_Element_Abstract implements IteratorAggregate, Countable, ArrayAccess {
		
		const TAG = 'table';
		
		/**
		 * The head element
		 * @var	My_Html_Element_THead
		 */
		protected $_head;
		
		/**
		 * The body element
		 * @var	My_Html_Element_TBody
		 */
		protected $_body;
		
		/**
		 * Class constructor
		 *
		 * @param	array	$rows
		 * @param	array	$attribs
		 *
		 * @return	void
		 */
		public function __construct ( array $rows = array (), array $attribs = array () ) {
			parent::__construct ( $attribs );
			
			$this->addRows ( $rows );
			
		}
		
		/**
		 * Overloads to body when possible
		 *
		 * @param	string	$method
		 * @param	array	$argumentsS
		 *
		 * @return	mixed
		 */
		public function __call ( $method, array $arguments ) {
			
			// Check if method exists in the body, if so proxy to it.
			if ( method_exists ( $this->getBody (), $method ) ) {
				$result = call_user_func_array ( array ( $this->getBody (), $method ), $arguments );
				
				// Maybe the method had a fluent interface, make sure we redirect to this object
				return ($result instanceof My_Html_Element_TBody) ? $this : $result;
					
			}
			
			trigger_error ( 'Call to undefined method ' . get_class ( $this ) . '::' . $method . '()', E_USER_ERROR );
			
		}
		
		/**
		 * Returns the head element of this table.
		 *
		 * @return	My_Html_Element_THead
		 */
		public function getHead () {
			
			if ( $this->_head === null ) {
				$this->_head = new My_Html_Element_THead;
				
			}
			
			return $this->_head;
			
		}
		
		/**
		 * If instance of THead, it sets the head value of this class
		 * else it proxies to THead::setRow
		 *
		 * @param	My_Html_Element_THead|My_Html_Element_TR|array	$head
		 *
		 * @return	My_Html_Element_Table
		 */
		public function setHead ( $head ) {
			
			if ( $head instanceof My_Html_Element_THead ) {
				$this->_head = $head;
			
			} else {
				$this->getHead ()->setRow ( $head );
				
			}
			
			return $this;
			
		}
		
		/**
		 * Returns the body element of this table.
		 *
		 * @return	My_Html_Element_TBody
		 */
		public function getBody () {
			
			if ( $this->_body === null ) {
				$this->_body = new My_Html_Element_TBody;
				
			}
			
			return $this->_body;
			
		}
		
		/**
		 * Sets the body element of this table.
		 *
		 * @param	My_Html_Element_TBody	$body
		 *
		 * @return	My_Html_Element_Table
		 */
		public function setBody ( My_Html_Element_TBody $body ) {
			$this->_body = $body;
			
			return $this;
			
		}
		
		/**
		 * Returns the element as a string
		 *
		 * @return	string
		 */
		public function render () {
			
			$return = '<' . self::TAG . $this->_attribString () . '>';
			$return .= PHP_EOL;
			
			$return .= $this->getHead ()->render ();
			$return .= PHP_EOL;
			
			$return .= $this->getBody ()->render ();
			$return .= PHP_EOL;
			
			$return .= '</' . self::TAG . '>';
			
			return $return;
			
		}
		
		// INTERFACES
		
		/**
		 * IteratorAggregate implementation
		 *
		 * @return	Iterator
		 */
		public function getIterator () {
			return $this->getBody ()->getIterator ();
			
		}
		
		/**
		 * Countable implementation
		 *
		 * @return	int
		 */
		public function count () {
			return count ( $this->getBody () );
			
		}
		
		/**
		 * Partial ArrayAccess implementation
		 *
		 * @return	My_Html_Element_TR
		 */
		public function offsetGet ( $offset ) {
			return $this->getBody ()->offsetGet ( $offset );
			
		}
		
		/**
		 * Partial ArrayAccess implementation
		 *
		 * @return	void
		 */
		public function offsetSet ( $offset, $value ) {
			$this->getBody ()->offsetSet ( $offset );
			
		}
		
		/**
		 * Partial ArrayAccess implementation
		 *
		 * @return	bool
		 */
		public function offsetExists ( $offset ) {
			return $this->getBody ()->offsetExists ( $offset );
			
		}
		
		/**
		 * Partial ArrayAccess implementation
		 *
		 * @return	void
		 */
		public function offsetUnset ( $offset ) {
			$this->getBody ()->offsetUnset ( $offset );
		
		}
		
	}
?>

library/My/Html/Element/THead.php:
<?php
	/**
	 *
	 */
	
	/**
	 * Base class for the thead element
	 */
	class My_Html_Element_THead extends My_Html_Element_Abstract {
		
		const TAG = 'thead';
		
		/**
		 * Holds the row for thead element
		 * @var	My_Html_Element_TR
		 */
		protected $_row = null;
		
		/**
		 * Class constructor
		 *
		 * @return	void
		 */
		public function __construct () {
			$this->_row = new My_Html_Element_TR ( array (), true );
			
		}
		
		/**
		 * Set the row values for this element
		 *
		 * @param	My_Html_Element_TR|array	$row
		 *
		 * @return My_Html_Element_THead
		 */
		public function setRow ( $row ) {
			
			if ( $row instanceof My_Html_Element_TR ) { 
				$this->_row = $row;
			
			} elseif ( is_array ( $row ) ) {
				$this->_row->setCells ( $row );
				
			} else {
				throw new InvalidArgumentException ( gettype ( $row ) . ' given where array or instanceof My_Html_Element_TR expected' );
				
			}
			
			return $this;
			
		}
		
		/**
		 * Returns the row for this element
		 *
		 * @return	My_Html_Element_TR
		 */
		public function getRow () {
			
			if ( $this->_row === null ) {
				$this->_row = new My_Html_Element_TR;
				
			}
			
			return $this->_row;
			
		}
		
		/**
		 * Returns this element as a string
		 *
		 * @return	string
		 */
		public function render () {
			
			$return = '<' . self::TAG . $this->_attribString () . '>';
			$return .= PHP_EOL;
			
			$return .= $this->getRow ()->render ();
			$return .= PHP_EOL;
			
			$return .= '</' . self::TAG . '>';
			
			return $return;
			
		}
		
	}
?>

library/My/Html/Element/TR.php:
<?php
	/**
	 *
	 */
	
	/**
	 * Base class for the tr element
	 */
	class My_Html_Element_TR extends My_Html_Element_Abstract implements IteratorAggregate, Countable, ArrayAccess {
		
		const TAG = 'tr';
		
		/**
		 * Holds the cells
		 * @var	array
		 */
		protected $_cells = array ();
		
		/**
		 * The class which this class excepts as cell element
		 * @var	string
		 */
		protected $_accept = 'My_Html_Element_TD';
		
		/**
		 * Class constructor
		 *
		 * @param	array	$cells
		 * @param	bool	$head	Is this tr part of THead?
		 */
		public function __construct ( array $cells = array (), $head = false ) {
			
			if  ( $head ) {
				$this->_accept = 'My_Html_Element_TH';
				
			}
			
			$this->setCells ( $cells );
			
		}
		
		/**
		 * Get a cell
		 *
		 * @param	int	$cell
		 *
		 * @return My_Html_Element_TD|My_Html_Element_TH
		 */
		public function getCell ( $cell ) {
			
			if ( !isset ( $this->_cells [ $cell ] ) ) {
				throw new OutOfBoundsException ( 'Offset does not exist' );
				
			}
			
			return $this->_cells [ $cell ];
			
		}
		
		/**
		 * Set a cell
		 *
		 * @param	int	$cell
		 * @param	My_Html_Element_TD|My_Html_Element_TH	$value
		 *
		 * @return My_Html_Element_TR
		 */
		public function setCell ( $cell, $value ) {
			$this->_cells [ $cell ] = $value;
			
			return $this;
			
		}
		
		/**
		 * Set multiple cells
		 * 
		 * @param	array	$cells
		 *
		 * @return	My_Html_Element_TR
		 */
		public function setCells ( array $cells ) {
			
			$store = array ();
			foreach ( $cells as $cell ) {
				
				if ( is_object ( $cell ) && get_class ( $cell ) === $this->_accept ) {
					throw new RuntimeException ( 'Cell should be of type ' . $this->_accept );
					
				} elseif ( is_object ( $cell ) ) {
					$store [] = $cell;
					
				} else {
					$store [] = new $this->_accept ( $cell );
					
				}
			
			}
				
			$this->_cells = $store;
			
			return $this;
		}
		
		/**
		 * Returns this element as a string
		 *
		 * @return	string
		 */
		public function render () {
			
			$args = func_get_args ();
			$class = isset ( $args [ 0 ] ) && is_string ( $args [ 0 ] ) ? $args [ 0 ] : '';
			
			$return = '<' . self::TAG . $this->_attribString ( array ( '+class' => $class ) ) . '>';
			$return .= PHP_EOL;
			
			foreach ( $this as $cell ) {
				$return .= $cell->render ();
				$return .= PHP_EOL;
			
			}
			
			$return .= '</' . self::TAG . '>';
			
			return $return;
			
		}
		
		// INTERFACES
		
		/**
		 * IteratorAggregate implementation
		 *
		 * @return	Iterator
		 */
		public function getIterator () {
			return new ArrayIterator ( $this->_cells );
			
		}
		
		/**
		 * Countable implementation
		 *
		 * @return	int
		 */
		public function count () {
			return count ( $this->_cells );
			
		}
		
		/**
		 * Partial ArrayAccess implementation
		 *
		 * @return	My_Html_Element_TR
		 */
		public function offsetGet ( $offset ) {
			return $this->getCell ( $offset );
			
		}
		
		/**
		 * Partial ArrayAccess implementation
		 *
		 * @return	void
		 */
		public function offsetSet ( $offset, $value ) {
			$this->_cells [ $offset ] = $value;
			
		}
		
		/**
		 * Partial ArrayAccess implementation
		 *
		 * @return	bool
		 */
		public function offsetExists ( $offset ) {
			
			try { 
				$this->getCell ( $offset );
				
			} catch ( Exception $e ) {
				return false;
			
			}
			
			return true;
			
		}
		
		/**
		 * Partial ArrayAccess implementation
		 *
		 * @return	void
		 */
		public function offsetUnset ( $offset ) {
			unset ( $this->_cells [ $offset ] );
		
		}
		
	}
?>

library/My/Html/Element/TH.php:
<?php
	/**
	 *
	 */
	
	/**
	 * Base class for the th element
	 */
	class My_Html_Element_TH extends My_Html_Element_Abstract {
		
		const TAG = 'th';
		
		/**
		 * Holds the value of this element
		 * @var	string
		 */
		protected $_value;
		
		/**
		 * Class constructor
		 *
		 * @param	string	$value OPTIONAL
		 *
		 * @return	void
		 */
		public function __construct ( $value = null ) {
			$this->_value = $value;
			
		}
		
		/**
		 * Returns the value of this element
		 *
		 * @return	string
		 */
		public function getValue () {
			return $this->_value;
			
		}
		
		/**
		 * Sets the value of this element
		 *
		 * @param	string	$value
		 *
		 * @return	My_Html_Element_TD
		 */
		public function setValue ( $value ) {
			$this->_value = $value;
			
			return $this;
			
		}
		
		/**
		 * Returns this element as a string
		 *
		 * @return	string
		 */
		public function render () {
			
			$return = '<' . self::TAG . $this->_attribString () . '>';
			
			$return .= $this->getValue ();
			
			$return .= '</' . self::TAG . '>';
			
			return $return;
			
		}
		
	}
?>

library/My/Html/Element/TBody.php:
<?php
	/**
	 *
	 */
	
	/**
	 * Base class for the tbody element
	 */
	class My_Html_Element_TBody extends My_Html_Element_Abstract implements IteratorAggregate, Countable, ArrayAccess {
		
		const TAG = 'tbody';
		
		/**
		 * Holds the classes for rows
		 * @var	array
		 */
		protected $_rowClasses = array ();
		
		/**
		 * Holds the rows of this body.
		 * @var	array
		 */
		protected $_rows = array ();
		
		/**
		 * Class constructor
		 *
		 * @param	array	$rows
		 * @param	array	$attribs 
		 *
		 * @return	void
		 */
		public function __construct ( array $rows = array (), array $attribs = array () ) {
			parent::__construct ( $attribs );
			
		}
		
		/**
		 * Returns the row classes for this table.
		 *
		 * @return	array
		 */
		public function getRowClasses () {
			return $this->_rowClasses;
			
		}
		
		/**
		 * Sets the row classes for this table.
		 *
		 * @param	array	$classes
		 *
		 * @return 	My_Html_Element_Table
		 */
		public function setRowClasses ( array $classes ) {
			$this->_rowClasses = $classes;
			
			return $this;
			
		}		 
		
		/**
		 * Adds a new row
		 *
		 * @param	My_Html_Element_TR|array	$row
		 *
		 * @return	My_Html_Element_TBody
		 */
		public function addRow ( $row ) {
			
			if ( $row instanceof My_Html_Element_TR ) {
				$this->_rows [] = $row;
				
			} elseif ( is_array ( $row ) ) {
				$this->_rows [] = new My_Html_Element_TR ( $row );
				
			} else {
				throw new InvalidArgumentException ( gettype ( $row ) . ' given where array or instanceof My_Html_Element_TR expected' );
				
			}
			
			return $this;
			
		}
		
		/**
		 * Adds rows
		 *
		 * @param	array	$rows
		 *
		 * @return	My_Html_Element_TBody
		 */
		public function addRows ( array $rows ) {
			
			foreach ( $rows as $row ) {
				$this->addRow ( $row );
				
			}
			
			return $this;
			
		}
		
		/**
		 * Removes a row
		 *
		 * @param	My_Html_Element_TR|int	$row
		 *
		 * @return	My_Html_Element_TBody
		 */
		public function removeRow ( $row ) {
			
			// Make sure we have a My_Html_Element_TR
			$row = $this->getRow ( $row );
			
			foreach ( $this->_rows as $key => $r ) {
				
				if ( $row === $r ) {
					unset ( $this->_rows [ $key ] );
					
				}
				
			}
			
			return $this;
			
		}
		
		/**
		 * Returns the given row for this index
		 *
		 * @param	My_Html_Element_TR|int	$row
		 *
		 * @return	My_Html_Element_TR
		 */
		public function getRow ( $tr ) {
			
			if ( $tr instanceof My_Html_Element_TR ) {
				return $tr;
				
			} elseif ( ctype_digit ( (string)$tr ) ) {
				
				if ( !isset ( $this->_rows [ $tr ] ) ) {
					throw new OutOfRangeException ( 'Index not set' );
					
				}
				
				return $this->_rows [ $tr ];
				
			} else {
				throw new InvalidArgumentException ( 'Row type not supported' );
				
			}
			
		}
		
		/**
		 * Returns all the rows in this element
		 *
		 * @returns	array
		 */
		public function getRows () {
			return $this->_rows;
			
		}
		
		/**
		 * Returns this element as a string
		 *
		 * @return	string
		 */
		public function render () {
			
			$return = '<' . self::TAG . $this->_attribString () . '>';
			$return .= PHP_EOL;
			
			$classCount = count ( $this->_rowClasses );
			
			foreach ( $this as $key => $row ) {
				$return .= $classCount > 0 ? $row->render ( $this->_rowClasses [ $key % $classCount ] ) : $row->render ();
				$return .= PHP_EOL;
			
			}
			
			$return .= '</' . self::TAG . '>';
			
			return $return;
			
		}
		
		// INTERFACES
		
		/**
		 * IteratorAggregate implementation
		 *
		 * @return	Iterator
		 */
		public function getIterator () {
			return new ArrayIterator ( $this->_rows );
			
		}
		
		/**
		 * Countable implementation
		 *
		 * @return	int
		 */
		public function count () {
			return count ( $this->_rows );
			
		}
		
		/**
		 * Partial ArrayAccess implementation
		 *
		 * @return	My_Html_Element_TR
		 */
		public function offsetGet ( $offset ) {
			return $this->getRow ( $offset );
			
		}
		
		/**
		 * Partial ArrayAccess implementation
		 *
		 * @return	void
		 */
		public function offsetSet ( $offset, $value ) {
			$this->_rows [ $offset ] = $value;
			
		}
		
		/**
		 * Partial ArrayAccess implementation
		 *
		 * @return	bool
		 */
		public function offsetExists ( $offset ) {
			
			try { 
				$this->getRow ( $offset );
				
			} catch ( Exception $e ) {
				return false;
			
			}
			
			return true;
			
		}
		
		/**
		 * Partial ArrayAccess implementation
		 *
		 * @return	void
		 */
		public function offsetUnset ( $offset ) {
			unset ( $this->_rows [ $offset ] );
		
		}
		
	}
?>

library/My/Html/Element/TD.php:
<?php
	/**
	 *
	 */
	
	/**
	 * Base class for the td element
	 */
	class My_Html_Element_TD extends My_Html_Element_Abstract {
		
		const TAG = 'td';
		
		/**
		 * Holds the value of this element
		 * @var	string
		 */
		protected $_value;
		
		/**
		 * Class constructor
		 *
		 * @param	string	$value OPTIONAL
		 *
		 * @return	void
		 */
		public function __construct ( $value = null ) {
			$this->_value = $value;
			
		}
		
		/**
		 * Returns the value of this element
		 *
		 * @return	string
		 */
		public function getValue () {
			return $this->_value;
			
		}
		
		/**
		 * Sets the value of this element
		 *
		 * @param	string	$value
		 *
		 * @return	My_Html_Element_TD
		 */
		public function setValue ( $value ) {
			$this->_value = $value;
			
			return $this;
			
		}
		
		/**
		 * Returns this element as a string
		 *
		 * @return	string
		 */
		public function render () {
			
			$return = '<' . self::TAG . $this->_attribString () . '>';
			
			$return .= $this->getValue ();
			
			$return .= '</' . self::TAG . '>';
			
			return $return;
			
		}
		
	}
?>

index.php:
<?php
	require_once 'library/My/Html/Element/Abstract.php';
	require_once 'library/My/Html/Element/Table.php';
	require_once 'library/My/Html/Element/THead.php';
	require_once 'library/My/Html/Element/TR.php';
	require_once 'library/My/Html/Element/TH.php';
	require_once 'library/My/Html/Element/TBody.php';
	require_once 'library/My/Html/Element/TD.php';
	
	$table = new My_Html_Element_Table ( array (
						array ( 'alkd', ' dddd' ),
						array ( 'adf333', 'dd' ),
						array ( 'asdfkasdf', 'dd' )
					) );
					
	$table->setAttrib ( 'id', 'bla' )
		  ->setHead ( array ( 'col1', 'col2', 'col3' ) )
		  ->addRow ( array ( 'test', 'test', 'test' ) )
		  ->setRowClasses ( array ( 'odd', 'even', 'drie' ) );
		  
	$table->getBody ()->setAttrib ( 'id', 'kkkkk' );
	
	$table [ 1 ] [ 0 ]->setAttrib ( 'id', 'blaaaa' );
	$table->getBody ()->getRow ( 0 )->setAttrib ( 'class', 'test-class' );
	
	echo $table;			
	
	foreach ( $table as $row ) {
		
		foreach ( $row as $cell ) {
			echo $cell->getValue () . ', ';
			
		}
		
		echo '<br />';
		
	}
?>

Reacties

0
Nog geen reacties.