private function processNodeWithType(NodeInterface $node, NodeType $nodeTypeDefinition)
{
$additionalOperations = array();
foreach ($nodeTypeDefinition->getDeclaredChildNodeDefinitions() as $childDef) {
/* @var $childDef NodeDefinitionInterface */
if (!$node->hasNode($childDef->getName())) {
if ('*' === $childDef->getName()) {
continue;
}
if ($childDef->isMandatory() && !$childDef->isAutoCreated()) {
throw new RepositoryException(sprintf('Child "%s" is mandatory, but is not present while saving "%s" at path "%s"', $childDef->getName(), $nodeTypeDefinition->getName(), $node->getPath()));
}
if ($childDef->isAutoCreated()) {
$requiredPrimaryTypeNames = $childDef->getRequiredPrimaryTypeNames();
$primaryType = count($requiredPrimaryTypeNames) ? current($requiredPrimaryTypeNames) : null;
$newNode = $node->addNode($childDef->getName(), $primaryType);
$absPath = $node->getPath() . '/' . $childDef->getName();
$operation = new AddNodeOperation($absPath, $newNode);
$additionalOperations[] = $operation;
}
}
}
foreach ($nodeTypeDefinition->getDeclaredPropertyDefinitions() as $propertyDef) {
/* @var $propertyDef PropertyDefinitionInterface */
if ('*' === $propertyDef->getName()) {
continue;
}
if (!$node->hasProperty($propertyDef->getName())) {
if ($propertyDef->isMandatory() && !$propertyDef->isAutoCreated()) {
throw new RepositoryException(sprintf('Property "%s" is mandatory, but is not present while saving "%s" at "%s"', $propertyDef->getName(), $nodeTypeDefinition->getName(), $node->getPath()));
}
if ($propertyDef->isAutoCreated()) {
switch ($propertyDef->getName()) {
case 'jcr:uuid':
$value = UUIDHelper::generateUUID();
break;
case 'jcr:createdBy':
case 'jcr:lastModifiedBy':
$value = $this->userId;
break;
case 'jcr:created':
case 'jcr:lastModified':
$value = new \DateTime();
break;
case 'jcr:etag':
// TODO: http://www.day.com/specs/jcr/2.0/3_Repository_Model.html#3.7.12.1%20mix:etag
$value = 'TODO: generate from binary properties of this node';
break;
default:
$defaultValues = $propertyDef->getDefaultValues();
if ($propertyDef->isMultiple()) {
$value = $defaultValues;
} elseif (isset($defaultValues[0])) {
$value = $defaultValues[0];
} else {
// When implementing versionable or activity, we need to handle more properties explicitly
throw new RepositoryException(sprintf('No default value for autocreated property "%s" at "%s"', $propertyDef->getName(), $node->getPath()));
}
}
$node->setProperty($propertyDef->getName(), $value, $propertyDef->getRequiredType());
}
} elseif ($propertyDef->isAutoCreated()) {
$prop = $node->getProperty($propertyDef->getName());
if (!$prop->isModified() && !$prop->isNew()) {
switch ($propertyDef->getName()) {
case 'jcr:lastModified':
if ($this->autoLastModified) {
$prop->setValue(new \DateTime());
}
break;
case 'jcr:lastModifiedBy':
if ($this->autoLastModified) {
$prop->setValue($this->userId);
}
break;
case 'jcr:etag':
// TODO: update etag if needed
break;
}
}
}
}
foreach ($nodeTypeDefinition->getDeclaredSupertypes() as $superType) {
$this->processNodeWithType($node, $superType);
}
foreach ($node->getProperties() as $property) {
$this->assertValidProperty($property);
}
return $additionalOperations;
}