PHP Classes

File: core/classes/Attributes.class.php

Recommend this page to a friend!
  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: 15 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() { } } ?>