Location: PHPKode > scripts > PAX > pax/core/classes/Model.class.php
<?php

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

/**
 * Model class definition.
 * This class will do all the work regarding current model.
 * 
 * @author Marius Zadara <hide@address.com>
 * @category Classes
 * @copyright (C) 2008-2009 Marius Zadara
 * @license Free for non-comercial use
 * @package org.zadara.marius.pax
 * @final 
 * @see PAXObject
 * @see IModel
 * @version 6.0
 * @since 6.0
 */
final class Model extends PAXObject implements IModel  
{
	private static $tagsContent;
	
	/**
	 * Class constructor.
	 * 
	 * @access public
	 */
	public function __construct()
	{
		parent::__construct();		
	}
	
	/**
	 * Method to extract the model name.
	 * By convention, the model name is the name of the root tag 
	 * from the file being parse
	 *
	 * @param array <b>$data</b> The nodes list
	 * @return mixed The model name or false in case of error
	 */	
	public static function extractModelName(&$data)
	{
		return isset($data[0]['tag']) ? $data[0]['tag'] : false; 			
	}
	
	/**
	 * Method to update the directories paths using the model name.
	 *
	 * @access public
	 * @static 
	 * @param config <b>$directories</b> The PAX config object
	 * @param string <b>$modelName</b> The current model name
	 * @return false in case of error or void
	 */
	public static function updateDirectories(&$directories, $modelName)
	{
		if (is_null($directories))
			return false;
		
		// get the models directory
		$modelsDir = $directories->get("models", "models");

		// update the current model directory
		$directories->set("models", $modelsDir.$modelName.DIRECTORY_SEPARATOR);	
		
		// update the current model definitions directory
		$dir = $directories->get("definitions", "definitions");
		$directories->set("definitions", $modelsDir.$modelName.DIRECTORY_SEPARATOR.$dir.DIRECTORY_SEPARATOR);
		
		// update the current model implementation directory		
		$dir = $directories->get("implementations", "implementations");
		$directories->set("implementations", $modelsDir.$modelName.DIRECTORY_SEPARATOR.$dir.DIRECTORY_SEPARATOR);

		// update the current model libraries directory		
		$dir = $directories->get("libraries", "libraries");
		$directories->set("libraries", $modelsDir.$modelName.DIRECTORY_SEPARATOR.$dir.DIRECTORY_SEPARATOR);

		// update the current model extra directory		
		$dir = $directories->get("extra", "extra");
		$directories->set("extra", $modelsDir.$modelName.DIRECTORY_SEPARATOR.$dir.DIRECTORY_SEPARATOR);		
	}
	
	
	/**
	 * Method to extract the namespaces from the nodes.
	 *
	 * @access public
	 * @static 
	 * @param array <b>$nodes</b> The nodes list
	 * @param config <b>$elements</b> The PAX elements 
	 * @return Array with te namespaces or null in case of no namespace found
	 */
	public static function extractNamespaces(&$nodes, &$elements)
	{
		$namespaces = array();
		$namespaceAdded = false;	

		// get the namespace separator
		$paxNsSeparator = $elements->get("paxNsSeparator", ":");
		
		foreach ($nodes as $currentNode)
		{
		    $data = Tags::extractNamesFromTag($currentNode['tag'], $paxNsSeparator);
		    
		    if ($data === false)
		        continue;
		        
            if ($data['namespace'] === false)
                continue;

			// at least one namespace added
			$namespaceAdded = true;

			// save the namespace
			if (!isset($namespaces[$data['namespace']]))
				$namespaces[$data['namespace']] = $data['namespace'];												    
		}

		// check the flag indicating if at least
		// one namespace has been added
		if (!$namespaceAdded)
			$namespaces = null;

		return $namespaces;
	}

	/**
	 * Method to get defined namespaces from the file.
	 * 
	 * @access public
	 * @static 
	 * @param array <b>$rootNodeAttributes</b> The root node attributes
	 * @param config <b>$elements</b> The PAX elements 
	 * @return mixed Array with the defined namespaces or null in case of no namespace found
	 */
	public static function getDefinedNamespaces($rootNodeAttributes, &$elements)
	{
		// init the defined namespaces
		$definedNamespaces = null;

		// check the root node attributes
		if (is_null($rootNodeAttributes) || !is_array($rootNodeAttributes))
			return $definedNamespaces;

		// get the namespace and namespace separator from the elements
		$paxNs = $elements->get("paxNs", "paxns");
		$paxNsSeparator = $elements->get("paxNsSeparator", ":");		
			
		// parse each root attribute
		foreach ($rootNodeAttributes as $attributeName => $attributeValue)
		{
			$paxNsPrefixPos = stripos($attributeName, $paxNs . $paxNsSeparator);

			// if namespace prefix found ...
			if ($paxNsPrefixPos !== false)
			{
				// get the namespace
				$definedNamespace = substr($attributeName, $paxNsPrefixPos + strlen($paxNs . $paxNsSeparator));
				
				// remove extra spaces
				$definedNamespace = trim($definedNamespace);
				
				// skip if empty namespace
				if ($definedNamespace == "")
					continue;
				
				// init the namespaces array for the first time
				if (is_null($definedNamespaces))
					$definedNamespaces = array();
					
				// set the namespace only once
				if (!isset($definedNamespaces[$definedNamespace]))
					$definedNamespaces[$definedNamespace] = $attributeValue;
			}
		}
		
		// return the data
		return $definedNamespaces;
	}
	

	/**
	 * Method to check the defined namespaces against the used namespaces.
	 *
	 * @param array <b>$definedNamespaces</b> The list with defined namespaces
	 * @param array <b>$usedNamespaces</b> The list with the used namespaces
	 * @return mixed Array with the corrected namespaces or null
	 */
	public static function checkNamespaces($definedNamespaces, $usedNamespaces)
	{
		// init the default result
		$namespaces = null;

		// check the namespaces
		if (is_null($definedNamespaces) || is_null($usedNamespaces) || !is_array($definedNamespaces) || !is_array($usedNamespaces)) 
			return $namespaces;

		// check each used namespace to see if has been declared
		foreach ($usedNamespaces as $usedNamespace)
		{			
			if (isset($definedNamespaces[$usedNamespace]))
			{
				// init the result only the first time
				if (!is_array($namespaces))
					$namespaces = array();
				
				// update the result with the complete path
				if (!isset($namespaces[$usedNamespace]))
					$namespaces[$usedNamespace] = $definedNamespaces[$usedNamespace];
			} 
		}		

		// return the data
		return $namespaces;
	}
	
	/**
	 * Method to validate the namespaces from the file.
	 * Each namespace should be a directory in the 'namespaces' directory.
	 *
	 * @access public
	 * @static 
	 * @param array $namespaces
	 * @param array $pathToNamespaces
	 * @return void
	 */
	public static function validateNamespaces(&$namespaces, $pathToNamespaces)	
	{
		// check the namespaces for data
		if (is_null($namespaces) || !is_array($namespaces))
		{
			$namespaces = null;
			return;
		}
		
		if (sizeof($namespaces) == 0)
		{
			$namespaces = null;
			return;
		}

		// create the Directory object
		$namespaceDir = new Dir();	
			
		// validate each namespace
		foreach ($namespaces as $code => $path)
		{
			// update the path of the namespace
			$namespaces[$code] = $pathToNamespaces . $path . DIRECTORY_SEPARATOR;
			
			$namespaceDir->setPath($namespaces[$code]);
			
			// check the directory for existence
			if (!$namespaceDir->exists())
			{
				unset($namespaces[$code]);
				continue;
			}

			// check the directory if is readable			
			if (!$namespaceDir->isReadable())
			{
				unset($namespaces[$code]);
				continue;
			}
		}

		// update the namespaces if none exists
		if (sizeof($namespaces) == 0)
			$namespaces = null;	
			
		return;
	}

	
	/**
	 * Method to see if a value is in a list
	 *
	 * @param string <b>$true</b> The value seached for
	 * @param mixed <b>$dictionary</b> The container were to search
	 * @return boolean
	 */
	public static function isInList($text, &$dictionary)
	{
		// if the dictionary is not array,
		// compare the value using standard method
		if (!is_array($dictionary))		
			return (is_null($dictionary) ? false : (strcmp($text, $dictionary) == 0));

		// get the size of the dictionary
		$count = sizeof($dictionary);

		// if empty dictionary, return false
		if ($count == 0)
			return false;
		
		// if not empty dictionary, 
		// compare the value with every entry in the dictionary
		// if found, return
		for ($i=0; $i < $count; $i++)
		{
			if (Model::isInList($text, $dictionary[$i]) === true)
				return true;
		}
		
		// at this point, the value has not been found
		return false;			
	}
	
	
	/**
	 * Method to filter the tags according to the definition file.
	 * 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 array with the current nodes 
	 * @param array <b>$namespaces</b> The array with the current namespaces
	 * @param string <b>$paxNsSeparator</b> The separator used in tag namespace definition
	 * @return void
	 */	
	public static function filterTags(&$config, &$elements, $directories, $filenames, &$nodes, &$namespaces, $paxNsSeparator)
	{		
		try 
		{
			// call the method from the Tags class
			Tags::filterTags($config, $elements, $directories, $filenames, $nodes, $namespaces, $paxNsSeparator);	
		}
		catch (PAXException $pe)
		{
			// if any exception, throw it further
			throw $pe;			
		}
		catch (Exception  $e)
		{
			// if any exception, throw it further			
			throw $e;	
		}
	}
	
	/**
	 * 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)
	{
		try 
		{
			// call the method from the Attributes class
			Attributes::filterTagAttributes($config, $elements, $directories, $filenames, $nodes, $attributesDefinitions);
		}
		catch (PAXException $pe)
		{
			// if any exception, throw it further
			throw $pe;
		}
		catch (Exception  $e)
		{
			// if any exception, throw it further			
			throw $e;	
		}
	}
	
	
	/**
	 * Method to filter tag attribute's value.
	 * 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 filterTagAttributesValue(&$config, $elements, $directories, $filenames, &$nodes, &$attributesDefinitions)
	{
		try 
		{
			// call the method from the Attributes class
			Attributes::filterTagAttributesValue($config, $elements, $directories, $filenames, $nodes, $attributesDefinitions);					
		}
		catch (PAXException  $pe)
		{
			// if any exception, throw it further						
			throw $pe;
		}	
		catch (Exception  $e)
		{
			// if any exception, throw it further						
			throw $e;	
		}		
	}
	
	/**
	 * Method to filter the tag content.
	 * Throws exception in case of error.
	 * 
	 * @access public
	 * @static 
	 * @param config <b>$config</b> The PAX config object
	 * @param config <b>$elements</b> The PAX elements object
	 * @param array <b>$nodes</b> The nodes array
	 * @return void
	 */	
	public static function filterTagContent(&$config, $elements, &$nodes)
	{
		try 
		{
			// call the method from the Tags class
			Tags::filterTagContent($config, $elements, $nodes);
		}
		catch (PAXException $pe)
		{
			// if any exception, throw it further
			throw $pe;		
		}	
		catch (Exception  $e)
		{
			// if any exception, throw it further			
			throw $e;	
		}		
	}
	
	
	/**
	 * Method to compile instruction found in source
	 *
	 * @access public
	 * @static 
	 * @param config <b>$config</b> The PAX config object
	 * @param config <b>$elements</b> The PAX elements object
	 * @param config <b>$variables</b> The PAX variables
	 * @param config <b>$instructions</b> The PAX instructions
	 * @param array <b>$nodes</b> The nodes array
	 * @param array <b>$attributesDefinitions</b> The attributes definitions array
	 * @return void
	 */
	public static function compileInstructions(&$config, &$elements, &$variables, &$instructions, &$nodes)
	{
		// check the compile instructions flag from config
		$doCompile = $config->get("compileInstructions", true);
		
		$compileInstructionsAttributeName = $config->get("compileInstructionsAttributeName", "compileInstructions");
				
		// overwrite the flag from definition?
		if (isset($nodes[0]['attributes'][$compileInstructionsAttributeName]))
			$doCompile = Model::isInList($nodes[0]['attributes'][$compileInstructionsAttributeName], $elements->get("trueTexts"));
		
		// stop if not needed to compile the instructions
		if (!$doCompile)
			return;
		
		
		// parse the nodes list
		// and replace each variable with its value
		// before compiling the instructions
		foreach ($nodes as $nodeIndex => $nodeData)
		{
			// if empty node, skip
			if ($nodeData === false)
				continue;
			
			// translate the variables
			// add the custom to the list
			Model::translateVariables($variables, $nodeData);
			
			// get the pairs (key-value) from definition
			$pairs = $variables->getKeyValuePairs();
			
			// no pairs? then skip the current node
			if ($pairs === false)
				continue;
				
			// translate each variable
			foreach ($pairs as $varName => $varValue)
			{
				// in the content of the node
				if (isset($nodeData['value']))
					$nodes[$nodeIndex]['value'] = str_ireplace($varName, $varValue, $nodes[$nodeIndex]['value']);
				
				// the node has attributes? 
				if (!isset($nodeData['attributes']))
					continue;
					
				// and they are valid
				if ($nodeData['attributes'] === false)
					continue;
				
				if (!is_array($nodeData['attributes']))
					continue;

				// at least one attribute
				if (sizeof($nodeData['attributes']) == 0)
					continue;

				// replace each variable in the attribute
				foreach ($nodeData['attributes'] as $attributeName => $attributeValue)
					$nodes[$nodeIndex]['attributes'][$attributeName] = str_ireplace($varName, $varValue, $nodes[$nodeIndex]['attributes'][$attributeName]);
			}
		}
			
		// compile the instructions		
		try 
		{
			// in the tags
			Tags::compileInstructions($instructions, $nodes);
			
			// in the attributes
			Attributes::compileInstructions($instructions, $nodes);
		}
		catch (PAXException $pe)
		{
			// if error, throw further
			throw $pe;
		}
		catch (Exception $e)
		{
			// if error, throw furthe
			throw $e;
		}		
	}
	
	
	/**
	 * Method to creat the custom variables 
	 * according to the node data.
	 *
	 * @access private
	 * @static 
	 * @param config $variables The config object for variables
	 * @param array $nodeData Current node data
	 * @return void
	 */
	private static function translateVariables(&$variables, $nodeData)
	{
		$default = "N/A";
		
		$variables->set("_NODE_NAME_", (($nodeData === false) || (!isset($nodeData['tag']))) ? $default : $nodeData['tag']);
		$variables->set("_NODE_TYPE_", (($nodeData === false) || (!isset($nodeData['type']))) ? $default : $nodeData['type']);
		$variables->set("_NODE_LEVEL_", (($nodeData === false) || (!isset($nodeData['level']))) ? $default : $nodeData['level']);
		$variables->set("_NODE_VALUE_", (($nodeData === false) || (!isset($nodeData['value']))) ? $default : $nodeData['value']);
		
		$variables->set("_NODE_IS_ROOT_", ($variables->get("_NODE_LEVEL_", 1) == 1) ? 1 : 0);
		
		$variables->set("_NODE_HAS_ATTRIBUTES_", (($nodeData === false) || (!isset($nodeData['attributes'])) || (!is_array($nodeData['attributes'])) ? 0 : 1));		
		$variables->set("_NODE_ATTRIBUTES_COUNT_",  ($variables->get("_NODE_HAS_ATTRIBUTES_", 0) == 0) ? 0 : sizeof($nodeData['attributes']));
		
		if ($variables->get("_NODE_HAS_ATTRIBUTES_", 0) == 1)
		{
			if ($variables->get("_NODE_ATTRIBUTES_COUNT_", 0) > 0)
			{
				// add a custom variable for each attribute
				foreach ($nodeData['attributes'] as $attributeName => $attributeValue)
					$variables->set(sprintf("_NODE_ATTRIBUTE_%s_", strtoupper($attributeName)), "".$attributeValue);
			}
		}
		else
		{
			// if the node has no attributes, 
			// delete the present one
			$variables->deleteKeysLike("_NODE_ATTRIBUTE_");
		}				
	}
	
	
	/**
	 * Class destructor.
	 * 
	 * @access private
	 */
	function __destruct()
	{
	}
}


?>
Return current item: PAX