Login   Register  
PHP Classes
elePHPant
Icontem

File: core/classes/Attributes.class.php

Recommend this page to a friend!
Stumble It! Stumble It! Bookmark in del.icio.us Bookmark in del.icio.us
  Classes of Marius Zadara  >  PAX  >  core/classes/Attributes.class.php  >  Download  
File: core/classes/Attributes.class.php
Role: Auxiliary script
Content type: text/plain
Description: Attributes classes
Class: PAX
Interpret XML command scripts with PHP classes
Author: By
Last change: Version update
Date: 5 years ago
Size: 18,602 bytes
 

Contents

Class file image Download
<?php


/**
 * Page DocBlock definition
 * @package org.zadara.marius.pax
 */


/**
 * Attributes class definition.
 * This class is responsible with all the work done on tag's attributes
 * 
 * @author Marius Zadara <marius@zadara.org>
 * @category Classes
 * @copyright (C) 2008-2009 Marius Zadara
 * @license Free for non-comercial use
 * @package org.zadara.marius.pax
 * @final 
 * @see File
 * @see IAttributes
 * @version 6.0
 * @since 5.0
 */
final class Attributes extends File implements IAttributes
{
	/**
	 * The atributes file definition content.
	 *
	 * @access private
	 * @var string
	 */
	private $attributesFileContent;
	
	/**
	 * Array with all the attributes for a tag.
	 *
	 * @access private
	 * @var array
	 */
	private $tagAttributes;
	
	/**
	 * Array with the namespaces.
	 *
	 * @access private
	 * @var array
	 */
	private $registeredNamespaces;
	
	
	/**
	 * Class constructor.
	 * 
	 * @access public
	 * @see PAXObject::__construct()
	 */
	public function __construct()
	{
		// init the parent
		parent::__construct();
		
		// init the class members
		$this->tagAttributes = null;
		$this->attributesFileContent = null;
		$this->registeredNamespaces = null;
	}
	
	/**
	 * Method to get the tag attributes from the definition file.
	 * Throws exception if error encountered.
	 *
	 * @param string <b>$rootTag</b> The attributes definition root tag
	 * @param string <b>$tag</b> The searched tag
	 * @param string <b>$paxNsSeparator</b> The namespaces separator used in tag's name
	 * @param string <b>$namespaceURL</b> The name used in defining tags from other namespaces 
	 * @return Array if the tag has attributes or false if no attribute found
	 */
	public function getTagAttributes($rootTag, $tag, $paxNsSeparator, $namespaceURL)
	{
		// if already seached for the current tag's attributes
		// return them
		if (isset($this->tagAttributes[$tag]))
			return $this->tagAttributes[$tag];		
		
		// try to load the content for the first time
		if (!is_object($this->attributesFileContent))
		{
			try
			{
				// get the content as xml from the file
				$this->attributesFileContent = @simplexml_load_file($this->path);
				
				// if failed, throw exception
				if ($this->attributesFileContent === false)
					throw new PAXException(sprintf(Messages::$MSG_037, $this->path), 37);	
			}
			catch (PAXException $pe)
			{
				// if exception caught, send it further
				throw $pe;
			}
			catch (Exception $e)
			{
				// if exception caught, send it further				
				throw new PAXException($e->getMessage());
			}
		}
		
		// get the separator position inside the tag's name
		$paxNsSepPos = strpos($tag, $paxNsSeparator);
		
		if ($paxNsSepPos !== false)
		{
			// get the namespace
			$namespace = substr($tag, 0, $paxNsSepPos);
			
			// init the namespaces array the first time
			if (!is_array($this->registeredNamespaces))
				$this->registeredNamespaces = array();
			
			// register the namespace 
			if (!in_array($namespace, $this->registeredNamespaces))
			{
				if ($this->attributesFileContent->registerXPathNamespace($namespace, sprintf("%s%s", $namespaceURL, $namespace)))
					array_push($this->registeredNamespaces, $namespace);
				else
					throw new PAXException(sprintf(Messages::$MSG_041), 41);
			}
		}
		
		// search the tag's attributes using XPath expressions
		$result = @$this->attributesFileContent->xPath(sprintf("/%s/%s", $rootTag, $tag));		
		
		if ($result == false)
			return false;
			
		if (sizeof($result) == 0)
			return false;
		
		$result = $result[0];
		$tagAttributes = array();

		// get each attribute for the tag
		foreach ($result as $attribute)
		{
			$attributeName = $attribute->getName();
			
			// skip duplicate attributes
			if (isset($tagAttributes[$attributeName]))
				continue;
				
			// get also each attribute for the current tag's attribute
			$defs = $attribute->attributes();
				
			$tagAttributes[$attributeName] = array();
			
			foreach ($defs as $def => $val)
			{
				// cast to string
				$def = (string) $def;
				$val = (string) $val;
				
				// skip duplicate attribute definition
				if (!isset($tagAttributes[$attributeName][$def]))
					$tagAttributes[$attributeName][$def] = $val;
			}
			
			if (sizeof($tagAttributes[$attributeName]) == 0)
				$tagAttributes[$attributeName] = true;
		}

		// init the array with all the tags attributes
		// only the first time
		if (!is_array($this->tagAttributes))
			$this->tagAttributes = array();
		
		// save the attributes definitions
		$this->tagAttributes[$tag] = $tagAttributes;
		
		// return the attributes definitions
		return $tagAttributes;
	}	
	
	
	
	
	/**
	 * Method to filter the tag's attributes according to its definition. 
	 * Throws exception if error encountered.
	 *
	 * @access public
	 * @static 
	 * @param config <b>$config</b> The PAX config object
	 * @param config <b>$elements</b> The PAX elements object
	 * @param config <b>$directories</b> The PAX directories object
	 * @param config <b>$filenames</b> The PAX filenames object
	 * @param array <b>$nodes</b> The nodes array
	 * @param array <b>$attributesDefinitions</b> The attributes definitions array
	 * @return void
	 */
	public static function filterTagAttributes(&$config, $elements, $directories, $filenames, &$nodes, &$attributesDefinitions)
	{
		// catch any exception
		try 
		{
			// get the filtering status from the config
			$filterAttributes = $config->get("filterTagAttributes", true);
			
			// get the filtering attribute name 
			$filterAttributesName = $config->get("filterAttributesAttributeName", "filterAttributes");

			// if the attribute has been found in the root,
			// update the filtering status using the 'true texts' dictionary
			if (isset($nodes[0]['attributes'][$filterAttributesName]))
				$filterAttributes = Model::isInList($nodes[0]['attributes'][$filterAttributesName], $elements->get("trueTexts")); 

			// continue with the filtering?
			if ($filterAttributes)
			{
				// allow no attributes definition?
				$allowNoAttributes = $config->get("allowNoAttributes", false);
				
				// if not ...
				if (!$allowNoAttributes)
				{
					// validate the attributes definition file
					// using the configuration
					
					$attributes = new Attributes();
					
					$attributesPath = $directories->get("definitions", "definitions");
					$attributesPath .= $filenames->get("attributes", "attributes.xml");
					
					$attributes->setPath($attributesPath);
					
					if (!$attributes->exists())
						throw new PAXException(sprintf(Messages::$MSG_034, $tagsPath), 34);

					if (!$attributes->isOrdinary())
						throw new PAXException(sprintf(Messages::$MSG_035, $tagsPath), 35);
						
					if (!$attributes->isReadable())
						throw new PAXException(sprintf(Messages::$MSG_036, $tagsPath), 36);
						
					// get extra informations
					// usefull in attribute parsing
					$rootTagAttributes = $config->get("attributesRoot", "attributes");
					$mandatoryText = $elements->get("mandatoryText", "mandatory");
					$defaultValueText = $elements->get("defaultValueText", "defaultValue");
					$namespaceURL = $elements->get("namespaceURL", "http://pax.org/");
					
					// parse the nodes list
					foreach ($nodes as $index => $nodeData)
					{
						// if invalid node, skip
						if ($nodeData === false)
							continue;
						
						// if the node type is close, skip
						// (the closed nodes don't have attributes)
						if ($nodeData['type'] == "close")
							continue;
						
						if (!isset($nodes[$index]['attributes']))
							$nodes[$index]['attributes'] = array();
							
							
						$paxNsSeparator = $elements->get("paxNsSeparator", ":");	
						
						// get the tag attributes according to the definition
						$tagAttributes = $attributes->getTagAttributes($rootTagAttributes, $nodeData['tag'], $paxNsSeparator, $namespaceURL);

						// if no attributes were defined, 
						// update the values and continue
						if ($tagAttributes === false)
						{
							$nodes[$index]['attributes'] = false;							
							continue;
						}
								
						$attributesCount = sizeof($tagAttributes);

						// if no attributes were defined, 
						// update the values and continue						
						if ($attributesCount == 0)
						{
							$nodes[$index]['attributes'] = false;							
							continue;
						}
							
						if (isset($nodeData['attributes']) && is_array($nodeData['attributes']))
						{
							// validate each attribute from the file according to the definition
							foreach ($nodeData['attributes'] as $attributeName => $attributeValue)
							{								
								if (stripos($attributeName, $paxNsSeparator) !== false)
								{
									unset($nodes[$index]['attributes'][$attributeName]);
									continue;
								}
								
								// if not found in the definition, unset it
								if (!isset($tagAttributes[$attributeName]))
									unset($nodes[$index]['attributes'][$attributeName]);								
							}
						}
						
						
						// add the mandatory attributes with their's default values
						foreach ($tagAttributes as $attributeName => $attributeData)
						{
							if (isset($nodes[$index]['attributes'][$attributeName]))
								continue;
								
							if (isset($attributeData[$mandatoryText]))
							{
								$isMandatory = Model::isInList($attributeData[$mandatoryText], $elements->get('trueTexts'));
								
								if (!$isMandatory)
									continue;

								if (!isset($attributeData[$defaultValueText]))
									continue;
								
								if (!isset($nodes[$index]['attributes']))
									$nodes[$index]['attributes'] = array();
									 	
								$nodes[$index]['attributes'][$attributeName] = $attributeData[$defaultValueText]; 
							}
						}
						
						// if at the end the attributes list is empty, set it to false
						if ((isset($nodes[$index]['attributes'])) && (sizeof($nodes[$index]['attributes']) == 0))
							$nodes[$index]['attributes'] = false;
							
						if ($nodes[$index]['attributes'] === false)
							continue;
							
						if ($attributesDefinitions == null)
							$attributesDefinitions = array();

							
						$attributesDefinitions[$index] = array();
						
						// clear the 'mandatory' and 'defaultValue' attributes from the definition
						// and save the new attributes list for the current index
						foreach ($nodes[$index]['attributes'] as $attributeName => $attributeValue)
						{
							$attributesDefinitions[$index][$attributeName] = $tagAttributes[$attributeName];
							
							if (isset($attributesDefinitions[$index][$attributeName][$mandatoryText]))
								unset($attributesDefinitions[$index][$attributeName][$mandatoryText]);

							if (isset($attributesDefinitions[$index][$attributeName][$defaultValueText]))
								unset($attributesDefinitions[$index][$attributeName][$defaultValueText]);	

							if (sizeof($attributesDefinitions[$index][$attributeName]) == 0)
								unset($attributesDefinitions[$index][$attributeName]);
						}

						if (sizeof($attributesDefinitions[$index]) == 0)
							unset($attributesDefinitions[$index]);
					}
				}
			}
		}
		catch (PAXException $pe)
		{
			// in case of exception, send it further
			throw $pe;
		}
		catch (Exception $e)
		{
			// in case of exception, send it further
			throw $e;						
		}
	}
	
	/**
	 * Method to filter tag attribute's value.
	 * Throws exception if error encountered.
	 *
	 * @param config <b>$config</b> The PAX config
	 * @param config <b>$elements</b> The PAX elements
	 * @param config <b>$directories</b> The PAX directories
	 * @param config <b>$filenames</b> The PAX filenames
	 * @param array <b>$nodes</b> The list of nodes
	 * @param array <b>$attributesDefinitions</b> Attributes definitions
	 * @return void
	 */
	public static function filterTagAttributesValue(&$config, $elements, $directories, $filenames, &$nodes, &$attributesDefinitions)
	{
		// catch any exception
		try 
		{	
			// get the filtering status from the config
			$filterAttributesValue = $config->get("filterTagAttributesValues", true);

			// get the filtering attribute name
			$filterAttributesValueTagName = $config->get("filterAttributesValueAttributeName", "filterAttributesValue");

			// update the filtering value if the attribute has been found
			if (isset($nodes[0]['attributes'][$filterAttributesValueTagName]))
				$filterAttributesValue = Model::isInList($nodes[0]['attributes'][$filterAttributesValueTagName], $elements->get("trueTexts")); 
			
			// continue with the filtering? 
			if ($filterAttributesValue)
			{
				// there are some attributes definitions?
				if (is_array($attributesDefinitions) && (sizeof($attributesDefinitions) > 0))
				{
					// get the attribute value validation name
					$attributeValueValidationMethodName = $elements->get("attrbuteValueValidationMethodName", "validateAttributeValue_[ATTRIBUTE]");					
					$paxNsSeparator = $elements->get("paxNsSeparator", ":");
					
					// parse the nodes list
					foreach ($nodes as $index => $nodeData)
					{
						// skip the invalid nodes
						if ($nodeData === false)
							continue;
						
						// skip the closed nodes
						if ($nodeData['type'] == 'close')
							continue;

						if (!isset($nodeData['attributes']))
							continue;	
							
						// skip the nodes without any attributes
						if ($nodeData['attributes'] === false)
							continue;
							
						// skip the nodes without any attributes definitions
						if (!isset($attributesDefinitions[$index]))
							continue;
						
						$paxNsSepPos = strpos($nodeData['tag'], $paxNsSeparator);
						
						// get the node name either from the a namespace or local
						if ($paxNsSepPos !== false)
							$currentNodeName = substr($nodeData['tag'], $paxNsSepPos + 1);
						else
							$currentNodeName = $nodeData['tag']; 
							
						// beautify the node name
						$currentNodeName = ucfirst($currentNodeName);

						// at this point, the class should already exists
						// (loaded at the moment of filtering tags)
						if (!class_exists($currentNodeName))
							throw new PAXException(sprintf(Messages::$MSG_038, $currentNodeName), 38);

						// validate each attribute 
						foreach ($nodeData['attributes'] as $attributeName => $attributeValue)
						{
							// skip the attributes without any definitions
							if (!isset($attributesDefinitions[$index][$attributeName]))
								continue;
							
							// update the validation method name
							$validationMethodName = str_ireplace("[ATTRIBUTE]", strtoupper($attributeName), $attributeValueValidationMethodName);	

							// seach the method inside the current class
							// if not found, skip filtering for the current attribute
							if (!method_exists($currentNodeName, $validationMethodName))
								continue;
							
								
							// create the evaluation string
							$evalString = sprintf("\$newAttributeValue = %s::%s('%s', \$attributesDefinitions[\$index][\$attributeName]);", $currentNodeName, $validationMethodName, $attributeValue);	

							// try to evaluate the string
							// if failed, thow exception
							if (@eval($evalString) === false)
								throw new PAXException(sprintf(Messages::$MSG_039, $currentNodeName, $attributeName, $nodeData['value']), 39);	

							if (is_null($newAttributeValue))
							{
								// if the result of validation method is null,
								// unset the attribute							
								unset($nodes[$index]['attributes'][$attributeName]);
							}
							else
							{
								// update the attribute value with the new one 
								$nodes[$index]['attributes'][$attributeName] = $newAttributeValue;
							}
						}
						
						// if at the end, the node has no attributes, 
						// update the record
						if (sizeof($nodes[$index]['attributes']) == 0)
							$nodes[$index]['attributes'] = false;
					}
				}
			}
		}
		catch (PAXException  $pe)
		{
			// in case of exception, throw it further
			throw $pe;
		}				
		catch (Exception $e)
		{
			// in case of exception, throw it further			
			throw $e;
		}
	}
	
	
	
	/**
	 * Method to compile the instructions
	 *
	 * @access public
	 * @static 
	 * @param config <b>$instructions</b> The PAX config
	 * @param array </b>$nodes</b> The nodes list
	 * @return void
	 */
	public static function compileInstructions(&$instructions, &$nodes)
	{
		// validate the instructions
		if (is_null($instructions))
			return;
		
		// create the pattern
		$pattern = new Pattern();
		$instructionExtractor = new InstructionExtractor();
		$instructionEvaluator = new InstructionEvaluator();
		$currentInstructions = array();	
			
		$startDelimiter = $instructions->get("startDelimiter", "!#");
		$endDelimiter = $instructions->get("endDelimiter", "#!");
		
		// parse each node
		foreach ($nodes as $nodeIndex => $nodeData)
		{
			if ($nodeData === false)
				continue;
				
			if (!isset($nodeData['attributes']))
				continue;
				
			if ($nodeData['attributes'] === false)
				continue;

			foreach ($nodeData['attributes'] as $attributeName => $attributeValue)
			{
				try
				{
					// try to extract instructions from the value of the current attribute
					$currentInstructions = $instructionExtractor->extract($attributeValue, $startDelimiter, $endDelimiter);
				}
				catch (PAXException $pe)
				{
					// if exception, throw it further
					throw $pe;
				}
				catch (Exception $e)
				{
					// if exception, throw it further
					throw $e;
				}
				
				// validate the instructions
				if ($currentInstructions === false)
					continue;

				// compile each instruction
				// and replace it by its value
				foreach ($currentInstructions as $instruction)
				{
					$replacePattern = $pattern->makeInstructionReplacePattern($instruction, $startDelimiter, $endDelimiter);
					$nodes[$nodeIndex]['attributes'][$attributeName] = InstructionReplacer::replace($replacePattern, $instructionEvaluator->evaluate($instruction), $nodes[$nodeIndex]['attributes'][$attributeName]);
				}
			}
		}
	}
	
	
	
	/**
	 * Class destructor.
	 * 
	 * @access public
	 */
	function __destruct()
	{
		
	}
}

?>