/** * Render the presentation and return the result. * * @param AgaviTemplateLayer The template layer to render. * @param array The template variables. * @param array The slots. * @param array Associative array of additional assigns. * * @return string A rendered result. * * @author David Zülke <*****@*****.**> * @since 1.1.0 */ public function render(AgaviTemplateLayer $layer, array &$attributes = array(), array &$slots = array(), array &$moreAssigns = array()) { if ($this->getParameter('envelope', true)) { if (!$moreAssigns['inner'] instanceof DOMDocument) { // plain text, load it as a document try { $inner = $this->loadDomDocumentXml($moreAssigns['inner']); } catch (DOMException $e) { throw new AgaviRenderException(sprintf("Unable to load input document for layer '%s'.\n\n%s", $layer->getName(), $e->getMessage())); } } else { $inner = $moreAssigns['inner']; } // construct envelope $doc = new DOMDocument(); $doc->appendChild($doc->createElementNS(self::ENVELOPE_XMLNS, 'envelope')); // inner content container $doc->documentElement->appendChild($innerWrapper = $doc->createElementNS(self::ENVELOPE_XMLNS, 'inner')); $innerWrapper->appendChild($doc->importNode($inner->documentElement, true)); // slots container $slotsWrapper = $doc->createElementNS(self::ENVELOPE_XMLNS, 'slots'); $doc->documentElement->appendChild($slotsWrapper); // flatten slots, iterate and wrap them each $flattenedSlots = AgaviArrayPathDefinition::flatten($slots); foreach ($flattenedSlots as $slotName => $slotContent) { if (!$slotContent instanceof DOMDocument) { try { $slot = $this->loadDomDocumentXml($slotContent); } catch (Exception $e) { throw new AgaviRenderException(sprintf("Unable to load contents for slot '%s'.\n\n%s", $slotName, $e->getMessage())); } } else { $slot = $slotContent; } $slotWrapper = $doc->createElementNS(self::ENVELOPE_XMLNS, 'slot'); $slotWrapper->setAttribute('name', $slotName); $slotWrapper->appendChild($doc->importNode($slot->documentElement, true)); $slotsWrapper->appendChild($slotWrapper); } } else { if (!$moreAssigns['inner'] instanceof DOMDocument) { // plain text, load it as a document $doc = $this->loadDomDocumentXml($moreAssigns['inner']); } else { $doc = $moreAssigns['inner']; } // This will pretty much never work, so we're not doing it. Users must enable the envelope feature to use slots. // Warning: XSLTProcessor::transformToXml() [xsltprocessor.transformtoxml]: Cannot create XPath expression (string contains both quote and double-quotes) // $flattenedSlots = AgaviArrayPathDefinition::flatten($slots); // foreach($flattenedSlots as $slotName => $slotContent) { // if($slotContent instanceof DOMDocument) { // $slotContent = $slotContent->saveXML(); // } // $xsl->setParameter('', 'slot:' . $slotName, addslashes($slotContent)); // } } try { $xslt = $this->loadDomDocument($layer->getResourceStreamIdentifier()); } catch (DOMException $e) { throw new AgaviRenderException(sprintf("Unable to load template '%s'.\n\n%s", $layer->getResourceStreamIdentifier(), $e->getMessage())); } $xsl = new XSLTProcessor(); $xsl->importStylesheet($xslt); foreach ($attributes as $name => $attribute) { if (is_scalar($attribute) || is_object($attribute) && method_exists($attribute, '__toString')) { $xsl->setParameter('', $name, $attribute); } } return $xsl->transformToXML($doc); }
/** * Returns the flattened version of an array. So the returned array * will be one dimensional with the flattened key names as keys * and their values from the original array as values. * * This method calls itself recursively to flatten the array. * * @param array The array which should be flattened. * @param string The prefix for the key names (only for internal use). * * @return array The flattened array. * * @author Dominik del Bondio <*****@*****.**> * @since 1.0.0 */ public static function flatten($array, $prefix = null) { $flatArray = array(); foreach ($array as $key => $value) { if ($prefix === null) { // create the top node when no prefix was given if (strlen($key) == 0) { // when an empty key was used at top level, create a "relative" path, so the empty string doesn't get lost $name = '[' . $key . ']'; } else { $name = $key; } } else { $name = $prefix . '[' . $key . ']'; } if (is_array($value)) { $flatArray += AgaviArrayPathDefinition::flatten($value, $name); } else { $flatArray[$name] = $value; } } return $flatArray; }