/**
  * @param Node $galleryNode
  * @return \TYPO3\Flow\Persistence\QueryResultInterface
  */
 protected function selectImages(Node $galleryNode)
 {
     $tagIdentifier = $galleryNode->getProperty('tag');
     $tag = $this->tagRepository->findByIdentifier($tagIdentifier);
     /** @var \TYPO3\Media\Domain\Model\Tag $tag */
     $images = $this->imageRepository->findByTag($tag);
     return $images;
 }
 /**
  * Get indexed nodes
  *
  * @param Node $node
  * @return string
  */
 public function get(Node $node)
 {
     $nodes = array();
     $indexService = new IndexService();
     $nodesResult = $indexService->getNodes($node);
     foreach ($nodesResult as $identifier => $item) {
         $n = new \TYPO3\TYPO3CR\Domain\Model\Node($item, $node->getContext());
         if ($n->getNode('.') != null) {
             $nodes[] = $n->getNode('.');
         }
     }
     return $nodes;
 }
 /**
  * @test
  */
 public function removedNodeWithoutExistingTargetNodeDataWillBeRemovedWhenPublished()
 {
     $homepageNode = $this->rootNode->createNode('homepage');
     $homepageNode->remove();
     $this->rootNode->getWorkspace()->publish($this->liveWorkspace);
     $this->saveNodesAndTearDownRootNodeAndRepository();
     $this->setUpRootNodeAndRepository();
     $liveContext = $this->contextFactory->create(array('workspaceName' => 'live', 'removedContentShown' => TRUE));
     $liveRootNode = $liveContext->getRootNode();
     $liveHomepageNode = $liveRootNode->getNode('homepage');
     $this->assertTrue($liveHomepageNode === NULL, 'A removed node should be removed after publishing, but it was still found');
 }
 /**
  * Sets up a view with context for testing
  *
  * @return void
  */
 public function setUpMockView()
 {
     $this->mockContext = $this->getMockBuilder(ContentContext::class)->disableOriginalConstructor()->getMock();
     $mockNode = $this->getMockBuilder(NodeData::class)->disableOriginalConstructor()->getMock();
     $this->mockContextualizedNode = $this->getMockBuilder(Node::class)->setMethods(array('getContext'))->setConstructorArgs(array($mockNode, $this->mockContext))->getMock();
     $mockSiteNode = $this->createMock(NodeInterface::class);
     $this->mockContext->expects($this->any())->method('getCurrentSiteNode')->will($this->returnValue($mockSiteNode));
     $this->mockContext->expects($this->any())->method('getDimensions')->will($this->returnValue(array()));
     $this->mockContextualizedNode->expects($this->any())->method('getContext')->will($this->returnValue($this->mockContext));
     $this->mockRuntime = $this->getMockBuilder(Runtime::class)->disableOriginalConstructor()->getMock();
     $mockControllerContext = $this->getMockBuilder(ControllerContext::class)->disableOriginalConstructor()->getMock();
     $this->mockSecurityContext = $this->getMockBuilder(Context::class)->disableOriginalConstructor()->getMock();
     $mockTypoScriptService = $this->createMock(TypoScriptService::class);
     $mockTypoScriptService->expects($this->any())->method('createRuntime')->will($this->returnValue($this->mockRuntime));
     $this->mockView = $this->getAccessibleMock(TypoScriptView::class, array('getClosestDocumentNode'));
     $this->mockView->expects($this->any())->method('getClosestDocumentNode')->will($this->returnValue($this->mockContextualizedNode));
     $this->inject($this->mockView, 'controllerContext', $mockControllerContext);
     $this->inject($this->mockView, 'securityContext', $this->mockSecurityContext);
     $this->inject($this->mockView, 'typoScriptService', $mockTypoScriptService);
     $this->mockView->_set('variables', array('value' => $this->mockContextualizedNode));
 }
 /**
  * Sets up a view with context for testing
  *
  * @return void
  */
 public function setUpMockView()
 {
     $this->mockContext = $this->getMock('TYPO3\\Neos\\Domain\\Service\\ContentContext', array(), array(), '', FALSE);
     $mockNode = $this->getMock('TYPO3\\TYPO3CR\\Domain\\Model\\NodeData', array(), array(), '', FALSE);
     $this->mockContextualizedNode = $this->getMock('TYPO3\\TYPO3CR\\Domain\\Model\\Node', NULL, array($mockNode, $this->mockContext));
     $mockSiteNode = $this->getMock('TYPO3\\TYPO3CR\\Domain\\Model\\NodeInterface');
     $this->mockContext->expects($this->any())->method('getCurrentSiteNode')->will($this->returnValue($mockSiteNode));
     $this->mockContext->expects($this->any())->method('getDimensions')->will($this->returnValue(array()));
     $this->mockContextualizedNode->expects($this->any())->method('getContext')->will($this->returnValue($this->mockContext));
     $this->mockRuntime = $this->getMock('TYPO3\\TypoScript\\Core\\Runtime', array(), array(), '', FALSE);
     $mockControllerContext = $this->getMock('TYPO3\\Flow\\Mvc\\Controller\\ControllerContext', array(), array(), '', FALSE);
     $this->mockSecurityContext = $this->getMock('TYPO3\\Flow\\Security\\Context', array(), array(), '', FALSE);
     $mockTypoScriptService = $this->getMock('TYPO3\\Neos\\Domain\\Service\\TypoScriptService');
     $mockTypoScriptService->expects($this->any())->method('createRuntime')->will($this->returnValue($this->mockRuntime));
     $this->mockView = $this->getAccessibleMock('TYPO3\\Neos\\View\\TypoScriptView', array('getClosestDocumentNode'));
     $this->mockView->expects($this->any())->method('getClosestDocumentNode')->will($this->returnValue($this->mockContextualizedNode));
     $this->inject($this->mockView, 'controllerContext', $mockControllerContext);
     $this->inject($this->mockView, 'securityContext', $this->mockSecurityContext);
     $this->inject($this->mockView, 'typoScriptService', $mockTypoScriptService);
     $this->mockView->_set('variables', array('value' => $this->mockContextualizedNode));
 }
 /**
  * @test
  */
 public function aSingleNodeExportedWithNodeDataExportCanBeImportedWithNodeDataImport()
 {
     $originalNode = $this->rootNode->createNode('foo', $this->nodeTypeManager->getNodeType('TYPO3.TYPO3CR.Testing:ImportExport'));
     $originalNode->setProperty('description', 'Some node with a property');
     $originalNode->setProperty('someDate', new \DateTime());
     $this->persistenceManager->persistAll();
     $exportService = new NodeExportService();
     $xml = $exportService->export('/')->outputMemory();
     $this->nodeDataRepository->removeAll();
     $this->workspaceRepository->removeAll();
     $this->saveNodesAndTearDownRootNodeAndRepository();
     $this->setUpRootNodeAndRepository();
     $importService = new NodeImportService();
     $reader = new \XMLReader();
     $reader->XML($xml);
     $importService->import($reader, '/');
     $importedNode = $this->rootNode->getNode('foo');
     $this->assertNotNull($importedNode, 'Expected node not found');
     $this->assertSame($originalNode->getIdentifier(), $importedNode->getIdentifier());
     $this->assertSame($originalNode->getProperty('description'), $importedNode->getProperty('description'));
     $this->assertEquals($originalNode->getProperty('someDate'), $importedNode->getProperty('someDate'));
 }
 /**
  * @test
  */
 public function nodeFromLiveWorkspaceMovedInUserWorkspaceRetainsShadowNodeInGroupWorkspace()
 {
     $liveContext = $this->contextFactory->create([]);
     $liveContext->getRootNode()->createNode('foo')->createNode('bar')->createNode('baz');
     $this->persistenceManager->persistAll();
     $this->rootNode->getNode('foo/bar/baz')->moveInto($this->rootNode->getNode('foo'));
     $this->persistenceManager->persistAll();
     $this->rootNode->getContext()->getWorkspace()->publish($this->groupWorkspace);
     $this->persistenceManager->persistAll();
     $groupContext = $this->contextFactory->create(['workspaceName' => $this->currentGroupWorkspace]);
     $movedBazNode = $groupContext->getRootNode()->getNode('foo')->getNode('baz');
     $this->assertInstanceOf(NodeInterface::class, $movedBazNode);
     $shadowNode = $this->nodeDataRepository->findShadowNodeByPath('/foo/bar/baz', $this->groupWorkspace, $groupContext->getDimensions());
     $this->assertInstanceOf(NodeData::class, $shadowNode);
     $this->assertNotNull($shadowNode->getMovedTo());
     $this->assertTrue($shadowNode->isRemoved());
 }
 /**
  * @test
  */
 public function changedNodeCanBePublishedFromPersonalToLiveWorkspace()
 {
     $liveContext = $this->contextFactory->create(array('workspaceName' => 'live'));
     $liveContext->getRootNode()->createNode('homepage')->createNode('teaser')->createNode('node52697bdfee199');
     $teaserNode = $this->rootNode->getNode('/homepage/teaser/node52697bdfee199');
     $teaserNode->setProperty('text', 'Updated text!');
     $this->saveNodesAndTearDownRootNodeAndRepository();
     $this->setUpRootNodeAndRepository();
     $this->liveWorkspace = $this->workspaceRepository->findOneByName('live');
     $teaserNode = $this->rootNode->getNode('/homepage/teaser/node52697bdfee199');
     $this->rootNode->getWorkspace()->publishNode($teaserNode, $this->liveWorkspace);
     $this->saveNodesAndTearDownRootNodeAndRepository();
     $this->setUpRootNodeAndRepository();
     $liveContext = $this->contextFactory->create(array('workspaceName' => 'live'));
     $liveRootNode = $liveContext->getRootNode();
     $teaserNode = $liveRootNode->getNode('/homepage/teaser/node52697bdfee199');
     $this->assertInstanceOf('TYPO3\\TYPO3CR\\Domain\\Model\\NodeInterface', $teaserNode);
 }
 /**
  * Deletes the specified node and all of its sub nodes
  *
  * We need to call persistAll() in order to return the nextUri. We can't persist only the nodes in NodeDataRepository
  * because they might be connected to images / resources which need to be removed at the same time.
  *
  * @param Node $node
  * @return void
  */
 public function deleteAction(Node $node)
 {
     if ($this->request->getHttpRequest()->isMethodSafe() === false) {
         $this->persistenceManager->persistAll();
     }
     $q = new FlowQuery(array($node));
     $node->remove();
     $closestDocumentNode = $q->closest('[instanceof TYPO3.Neos:Document]')->get(0);
     $nextUri = $this->uriBuilder->reset()->setFormat('html')->setCreateAbsoluteUri(true)->uriFor('show', array('node' => $closestDocumentNode), 'Frontend\\Node', 'TYPO3.Neos');
     $this->view->assign('value', array('data' => array('nextUri' => $nextUri), 'success' => true));
 }
 /**
  * Get array of node selection properties
  *
  *
  *
  * @param Node $node
  * @return array
  */
 public function prepareNodeSelectionFromNode(Node $node)
 {
     foreach ($this->contentContextFactory->getInstances() as $context) {
         $this->workspace = $context->getWorkspace();
         break;
     }
     $limit = false;
     $limit_param_name = false;
     $offset = false;
     $offset_param_name = false;
     $filter = array();
     $sort = array();
     $nodetype = false;
     $nodetypeisabstract = false;
     $entryNodes = array();
     $nodeParentPath = $node->getParentPath();
     if ($node->getNodeData()->getNodeType()->getConfiguration('indexedNodes')) {
         // calculate nodetype name
         if ($node->getNodeData()->getNodeType()->getConfiguration('indexedNodes') && array_key_exists('nodeType', $node->getNodeData()->getNodeType()->getConfiguration('indexedNodes'))) {
             foreach ($node->getNodeData()->getNodeType()->getConfiguration('indexedNodes')['nodeType'] as $key => $value) {
                 switch ($key) {
                     case 'property':
                         if ($node->getProperty($value)) {
                             $nodetype = $node->getProperty($value);
                         }
                         break;
                     case 'value':
                         $nodetype = $value;
                         break;
                     case 'param':
                         if ($this->httpRequest->hasArgument($value) || $nodetype == false) {
                             $nodetype = addslashes($this->httpRequest->getArgument($value));
                         }
                         break;
                     case 'abstract':
                         $nodetypeisabstract = TRUE;
                         break;
                     default:
                         break;
                 }
             }
         } else {
             throw new IndexedNodesException($node->getNodeData()->getNodeType()->getName() . ' has no nodeType definition.');
         }
         // calculate limit
         if ($node->getNodeData()->getNodeType()->getConfiguration('indexedNodes') && array_key_exists('limit', $node->getNodeData()->getNodeType()->getConfiguration('indexedNodes'))) {
             foreach ($node->getNodeData()->getNodeType()->getConfiguration('indexedNodes')['limit'] as $key => $value) {
                 switch ($key) {
                     case 'property':
                         if ($node->getProperty($value)) {
                             $limit = $node->getProperty($value);
                         }
                         break;
                     case 'value':
                         $limit = $value;
                         break;
                     case 'param':
                         if ($this->httpRequest->hasArgument($value) || $limit == false) {
                             $limit = addslashes($this->httpRequest->getArgument($value));
                         }
                         $limit_param_name = $value;
                         if (strlen($limit) == 0) {
                             $limit = false;
                         }
                         break;
                     default:
                         break;
                 }
             }
         }
         if (!$limit) {
             // fetch default limit from internal params
             $value = "_limit-" . $node->getIdentifier();
             if ($this->httpRequest->hasArgument($value)) {
                 $limit = addslashes($this->httpRequest->getArgument($value));
             }
             if (!$limit_param_name) {
                 $limit_param_name = $value;
             }
         }
         // calculate limit offset, if limit isset
         if ($limit && $node->getNodeData()->getNodeType()->getConfiguration('indexedNodes') && array_key_exists('offset', $node->getNodeData()->getNodeType()->getConfiguration('indexedNodes'))) {
             foreach ($node->getNodeData()->getNodeType()->getConfiguration('indexedNodes')['offset'] as $key => $value) {
                 switch ($key) {
                     case 'property':
                         if ($node->getProperty($value)) {
                             $offset = $node->getProperty($value);
                         }
                         break;
                     case 'value':
                         $offset = $value;
                         break;
                     case 'param':
                         if ($this->httpRequest->hasArgument($value) || $offset == false) {
                             $offset = addslashes($this->httpRequest->getArgument($value));
                         }
                         $offset_param_name = $value;
                         if (strlen($offset) == 0) {
                             $offset = false;
                         }
                         break;
                     default:
                         break;
                 }
             }
         }
         if (!$offset) {
             // fetch default offset from internal params
             $value = "_offset-" . $node->getIdentifier();
             if ($this->httpRequest->hasArgument($value)) {
                 $offset = addslashes($this->httpRequest->getArgument($value));
             }
             if (!$offset_param_name) {
                 $offset_param_name = $value;
             }
             if (strlen($offset) == 0) {
                 $offset = 0;
             }
         }
         // calculate filters
         if ($node->getNodeData()->getNodeType()->getConfiguration('indexedNodes') && $node->getNodeData()->getNodeType()->getConfiguration('indexedNodes')['filter']) {
             foreach ($node->getNodeData()->getNodeType()->getConfiguration('indexedNodes')['filter'] as $property => $arguments) {
                 foreach ($arguments as $arg => $filterValues) {
                     switch ($arg) {
                         case 'type':
                             $filter[$property]['type'] = $filterValues;
                             break;
                         case 'operand':
                             foreach ($filterValues as $key => $value) {
                                 switch ($key) {
                                     case 'property':
                                         if ($node->getProperty($value)) {
                                             $filter[$property]['operand'] = $node->getProperty($value);
                                         }
                                         break;
                                     case 'value':
                                         $filter[$property]['operand'] = $value;
                                         break;
                                     case 'param':
                                         if ($this->httpRequest->hasArgument($value) || isset($filter[$property]['operand']) == false) {
                                             $filter[$property]['operand'] = addslashes($this->httpRequest->getArgument($value));
                                         }
                                         break;
                                     default:
                                         break;
                                 }
                             }
                             break;
                         case 'operator':
                             foreach ($filterValues as $key => $value) {
                                 switch ($key) {
                                     case 'property':
                                         if ($node->getProperty($value)) {
                                             $filter[$property]['operator'] = $node->getProperty($value);
                                         }
                                         break;
                                     case 'value':
                                         $filter[$property]['operator'] = $value;
                                         break;
                                     case 'param':
                                         if ($this->httpRequest->hasArgument($value) || isset($filter[$property]['operator']) == false) {
                                             $filter[$property]['operator'] = addslashes($this->httpRequest->getArgument($value));
                                         }
                                         break;
                                     default:
                                         break;
                                 }
                             }
                             break;
                     }
                 }
                 if (isset($filter[$property]['type']) == false) {
                     $targetNodeType = $this->nodeTypeManager->getNodeType($nodetype);
                     // get sorting type by property definition
                     if (isset($targetNodeType->getConfiguration('properties')['text'])) {
                         $filter[$property]['type'] = $targetNodeType->getConfiguration('properties')['text']['type'];
                     } else {
                         $filter[$property]['type'] = 'string';
                     }
                 }
             }
         }
         // calculate entry nodes
         if ($node->getNodeData()->getNodeType()->getConfiguration('indexedNodes') && array_key_exists('entryNodes', $node->getNodeData()->getNodeType()->getConfiguration('indexedNodes'))) {
             foreach ($node->getNodeData()->getNodeType()->getConfiguration('indexedNodes')['entryNodes'] as $property => $filterValues) {
                 foreach ($filterValues as $key => $value) {
                     switch ($key) {
                         case 'property':
                             if ($node->getProperty($value)) {
                                 $entryNodes[$property]['value'] = $node->getProperty($value);
                             }
                             break;
                         case 'value':
                             $entryNodes[$property]['value'] = $value;
                             break;
                         case 'param':
                             if ($this->httpRequest->hasArgument($value) || isset($entryNodes[$property]['value']) == false) {
                                 $entryNodes[$property]['value'] = addslashes($this->httpRequest->getArgument($value));
                             }
                             break;
                         case 'recursive':
                             $entryNodes[$property]['recursive'] = $value;
                             break;
                         case 'childNodePath':
                             $entryNodes[$property]['childNodePath'] = $value;
                             break;
                     }
                     if (isset($entryNodes[$property]['recursive']) == false) {
                         $entryNodes[$property]['recursive'] = TRUE;
                     }
                     if (isset($entryNodes[$property]['childNodePath']) == false) {
                         $entryNodes[$property]['childNodePath'] = FALSE;
                     }
                     if (isset($entryNodes[$property]['value']) && is_array($entryNodes[$property]['value']) == false) {
                         $targetNode = $this->nodeDataRepository->findOneByIdentifier($entryNodes[$property]['value'], $this->workspace);
                         if ($targetNode) {
                             $entryNodes[$property]['path'] = $targetNode->getParentPath();
                         }
                     }
                 }
                 if (isset($entryNodes[$property]['value']) && is_array($entryNodes[$property]['value'])) {
                     $t = $entryNodes[$property];
                     unset($entryNodes[$property]);
                     foreach ($t['value'] as $key => $val) {
                         $entryNodes[$property . $key] = array('path' => $val->getPath(), 'childNodePath' => $t['childNodePath'], 'parentPath' => $val->getParentPath(), 'childNodes' => $val->getNodeType()->getChildNodes(), 'recursive' => $t['recursive']);
                     }
                 }
             }
         } else {
             // set reference to self node
             $entryNodes['self'] = array('path' => '/');
         }
         // calculate sorting
         if ($node->getNodeData()->getNodeType()->getConfiguration('indexedNodes') && array_key_exists('sort', $node->getNodeData()->getNodeType()->getConfiguration('indexedNodes'))) {
             foreach ($node->getNodeData()->getNodeType()->getConfiguration('indexedNodes')['sort'] as $nullkey => $sortValues) {
                 foreach ($sortValues as $key => $value) {
                     switch ($key) {
                         case 'property':
                             if ($node->getProperty($value)) {
                                 $sort[$property]['value'] = $node->getProperty($value);
                             }
                             break;
                         case 'value':
                             $sort[$property]['value'] = $value;
                             break;
                         case 'param':
                             if ($this->httpRequest->hasArgument($value) || isset($sort[$property]) == false) {
                                 $sort[$property]['value'] = addslashes($this->httpRequest->getArgument($value));
                             }
                             break;
                         case 'type':
                             $sort[$property]['type'] = $value;
                             break;
                         case 'direction':
                             foreach ($value as $k => $v) {
                                 switch ($k) {
                                     case 'property':
                                         if ($node->getProperty($v)) {
                                             $sort[$property]['direction'] = $node->getProperty($v);
                                         }
                                         break;
                                     case 'value':
                                         $sort[$property]['direction'] = $v;
                                         break;
                                     case 'param':
                                         if ($this->httpRequest->hasArgument($v) || isset($sort[$property]['direction']) == false) {
                                             $sort[$property]['direction'] = addslashes($this->httpRequest->getArgument($v));
                                         }
                                         break;
                                 }
                             }
                             break;
                         default:
                             break;
                     }
                     if (isset($sort[$property]['type']) == false) {
                         $targetNodeType = $this->nodeTypeManager->getNodeType($nodetype);
                         // get sorting type by property definition
                         if (isset($targetNodeType->getConfiguration('properties')['text'])) {
                             $sort[$property]['type'] = $targetNodeType->getConfiguration('properties')['text']['type'];
                         } else {
                             $sort[$property]['type'] = 'string';
                         }
                     }
                 }
             }
         }
     }
     return array('limit' => $limit, 'limit_param_name' => $limit_param_name, 'offset' => $offset, 'offset_param_name' => $offset_param_name, 'filter' => $filter, 'sort' => $sort, 'nodetype' => $nodetype, 'nodetypeisabstract' => $nodetypeisabstract, 'entryNodes' => $entryNodes, 'workspace' => $this->workspace);
 }
 /**
  * @test
  */
 public function getIdentifierReturnsTheIdentifier()
 {
     $nodeData = $this->getMockBuilder(NodeData::class)->disableOriginalConstructor()->getMock();
     $nodeData->expects($this->once())->method('getIdentifier')->will($this->returnValue('theidentifier'));
     $context = $this->getMockBuilder(Context::class)->disableOriginalConstructor()->getMock();
     $contextualizedNode = new Node($nodeData, $context);
     $this->assertEquals('theidentifier', $contextualizedNode->getIdentifier());
 }
 /**
  * Export a single node.
  *
  * @param \TYPO3\TYPO3CR\Domain\Model\Node $node
  * @param \XMLWriter $xmlWriter
  * @return void
  */
 protected function exportNode(\TYPO3\TYPO3CR\Domain\Model\Node $node, \XMLWriter $xmlWriter)
 {
     $xmlWriter->startElement('node');
     // node attributes
     $xmlWriter->writeAttribute('identifier', $node->getIdentifier());
     $xmlWriter->writeAttribute('type', $node->getContentType()->getName());
     $xmlWriter->writeAttribute('nodeName', $node->getName());
     $xmlWriter->writeAttribute('locale', '');
     if ($node->isHidden() === TRUE) {
         $xmlWriter->writeAttribute('hidden', 'true');
     }
     if ($node->isHiddenInIndex() === TRUE) {
         $xmlWriter->writeAttribute('hiddenInIndex', 'true');
     }
     $hiddenBeforeDateTime = $node->getHiddenBeforeDateTime();
     if ($hiddenBeforeDateTime !== NULL) {
         $xmlWriter->writeAttribute('hiddenBeforeDateTime', $hiddenBeforeDateTime->format(\DateTime::W3C));
     }
     $hiddenAfterDateTime = $node->getHiddenAfterDateTime();
     if ($hiddenAfterDateTime !== NULL) {
         $xmlWriter->writeAttribute('hiddenAfterDateTime', $hiddenAfterDateTime->format(\DateTime::W3C));
     }
     // access roles
     $accessRoles = $node->getAccessRoles();
     if (count($accessRoles) > 0) {
         $xmlWriter->startElement('accessRoles');
         foreach ($accessRoles as $role) {
             $xmlWriter->writeElement('role', $role);
         }
         $xmlWriter->endElement();
     }
     // node properties
     $properties = $node->getProperties();
     if (count($properties) > 0) {
         $xmlWriter->startElement('properties');
         foreach ($properties as $propertyName => $propertyValue) {
             if (is_object($propertyValue)) {
                 $xmlWriter->startElement($propertyName);
                 $xmlWriter->writeAttribute('__type', 'object');
                 $xmlWriter->writeAttribute('__classname', get_class($propertyValue));
                 $this->objectToXml($propertyValue, $xmlWriter);
                 $xmlWriter->endElement();
             } elseif (strpos($propertyValue, '<') !== FALSE || strpos($propertyValue, '>') !== FALSE || strpos($propertyValue, '&') !== FALSE) {
                 $xmlWriter->startElement($propertyName);
                 if (strpos($propertyValue, '<![CDATA[') !== FALSE) {
                     $xmlWriter->writeCdata(str_replace(']]>', ']]]]><![CDATA[>', $propertyValue));
                 } else {
                     $xmlWriter->writeCdata($propertyValue);
                 }
                 $xmlWriter->endElement();
             } else {
                 $xmlWriter->writeElement($propertyName, $propertyValue);
             }
         }
         $xmlWriter->endElement();
     }
     // and the child nodes recursively
     foreach ($node->getChildNodes() as $childNode) {
         $this->exportNode($childNode, $xmlWriter);
     }
     $xmlWriter->endElement();
 }