/** * An utility method that cleans the contents of the section node, by * moving the alternative section (opt:sectionelse etc. tags) code to the end * of the children list. * * In the parameters, we must specify the name and the namespace of the * tags that will be treated as the alternative content tags. * * @param Opt_Xml_Element $node The section node * @param String $ns The namespace * @param String $name The alternative section content tag name */ protected function _sortSectionContents(Opt_Xml_Element $node, $ns, $name) { $else = $node->getElementsByTagNameNS($ns, $name, false); if (sizeof($else) == 1) { if (!$node->hasAttributes()) { throw new Opt_InstructionTooManyItems_Exception($ns . ':' . $name, $node->getXmlName(), 'Zero'); } $node->bringToEnd($else[0]); } elseif (sizeof($else) > 1) { throw new Opt_InstructionTooManyItems_Exception($ns . ':' . $name, $node->getXmlName(), 'Zero or one'); } }
/** * The internal magic shared by the selector elements. Locates the node elements * and constructs the switch() statement for them. * @internal * @param Opt_Xml_Element $node The found element * @param array $section The reference to the section data. * @param string $type The name of the selection item. * @throws Opt_InstructionTooManyItems_Exception */ private function _internalMagic($node, &$section, $type) { $section['format']->assign('item', !$type ? $section['test'] : 'item'); // Check, if there are no instruction tags in the children list. $instructions = array(); $cases = array(); $alternative = null; foreach ($node as $subnode) { if ($subnode instanceof Opt_Xml_Element && $this->_compiler->isNamespace($subnode->getNamespace())) { if ($this->_compiler->isInstruction($subnode->getXmlName()) || $subnode->getXmlName() == 'opt:separator') { if ($subnode != 'opt:selectorelse') { $instructions[] = $subnode; } else { if (!is_null($alternative)) { throw new Opt_InstructionTooManyItems_Exception('opt:selectorelse', $node->getXmlName(), 'Zero or one'); } $alternative = $subnode; } } else { $cases[] = $subnode; } } else { $node->removeChild($subnode); } } if (sizeof($instructions) > 0) { // There are instructions in opt:selector. We have to move the // cases to a fake node in order to sanitize them. $node->removeChildren(); foreach ($instructions as $instruction) { $node->appendChild($instruction); } $fake = new Opt_Xml_Element('opt:_'); foreach ($cases as $case) { $fake->appendChild($case); } $fake->set('processAll', true); $fake->set('hidden', false); $node->appendChild($fake); if (!is_null($alternative)) { $node->appendChild($alternative); } } else { $fake = $node; } $fake->addAfter(Opt_Xml_Buffer::TAG_CONTENT_BEFORE, 'switch(' . $section['format']->get('section:variable') . '){'); // If opt:selectorelse is used, the ending curly bracket is created by // _processSelectorelse(). if (is_null($alternative)) { $fake->addBefore(Opt_Xml_Buffer::TAG_CONTENT_AFTER, ' } '); } foreach ($cases as $case) { if ($case->getXmlName() == 'opt:separator') { Opl_Debug::write('Print shit'); } if ($case->getName() == 'default') { $case->addAfter(Opt_Xml_Buffer::TAG_CONTENT_BEFORE, ' default: '); } else { $case->addAfter(Opt_Xml_Buffer::TAG_CONTENT_BEFORE, ' case \'' . $case->getName() . '\': '); } $case->addBefore(Opt_Xml_Buffer::TAG_CONTENT_AFTER, ' break; '); $case->set('processAll', true); $case->set('hidden', false); } }
/** * Tries to extract a single attribute, using the specified value type. * * @final * @internal * @param Opt_Xml_Element $item The scanned XML element. * @param Opt_Xml_Attribute $attr The parsed attribute * @param Int $type The requested value type. * @return Mixed The extracted attribute value */ private final function _extractAttribute(Opt_Xml_Element $item, Opt_Xml_Attribute $attr, $type, $exprType = null) { $value = (string) $attr; switch ($type) { // An identifier, but with empty values allowed. case self::ID_EMP: if ($value == '') { return $value; } // An identifier // An identifier case self::ID: if (!preg_match('/^[a-zA-Z0-9\\_\\.]+$/', $value)) { throw new Opt_InvalidAttributeType_Exception($attr->getXmlName(), $item->getXmlName(), 'identifier'); } return $value; // A number // A number case self::NUMBER: if (!preg_match('/^\\-?([0-9]+\\.?[0-9]*)|(0[xX][0-9a-fA-F]+)$/', $value)) { throw new Opt_InvalidAttributeType_Exception($attr->getXmlName(), $item->getXmlName(), 'number'); } return $value; // Boolean value: "yes" or "no" // Boolean value: "yes" or "no" case self::BOOL: if ($value != 'yes' && $value != 'no') { throw new Opt_InvalidAttributeType_Exception($attr->getXmlName(), $item->getXmlName(), '"yes" or "no"'); } return $value == 'yes'; // A string packed into PHP expression. Can be switched to EXPRESSION. // A string packed into PHP expression. Can be switched to EXPRESSION. case self::STRING: return $value; break; // An OPT expression. // An OPT expression. case self::EXPRESSION: case self::ASSIGN_EXPR: if (strlen(trim($value)) == 0) { throw new Opt_AttributeEmpty_Exception($attr->getXmlName(), $item->getXmlName()); } if (preg_match('/^([a-zA-Z0-9\\_]{2,})\\:([^\\:].*)$/', $value, $found)) { $result = $this->_compiler->parseExpression($found[2], $found[1]); } else { $result = $this->_compiler->parseExpression($value, $exprType); } if ($result['type'] == Opt_Expression_Interface::ASSIGNMENT && $type != self::ASSIGN_EXPR) { Opt_ExpressionOptionDisabled_Exception('Assignments', 'compiler requirements'); } return $result['bare']; } }