public function formatValue(PropertyInterface $property, $showBinary = false, $truncate = true) { $values = $property->getValue(); if (false === $property->isMultiple()) { $values = array($values); } $return = array(); foreach ($values as $value) { switch (intval($property->getType())) { case PropertyType::UNDEFINED: $return[] = '#UNDEFINED#'; case PropertyType::BINARY: if ($showBinary) { $lines = array(); $pointer = $value; while (($line = fgets($pointer)) !== false) { $lines[] = $line; } $return[] = implode('', $lines); break; } return '(binary data)'; case PropertyType::BOOLEAN: $return[] = $value ? 'true' : 'false'; break; case PropertyType::DATE: $return[] = $value->format('c'); break; case PropertyType::REFERENCE: case PropertyType::WEAKREFERENCE: $return[] = sprintf('%s (%s)', $this->textHelper->truncate($value->getPath(), 255), $value->getIdentifier()); break; case PropertyType::URI: case PropertyType::STRING: $return[] = $truncate ? $this->textHelper->truncate($value) : $value; break; case PropertyType::NAME: case PropertyType::LONG: case PropertyType::DOUBLE: case PropertyType::DECIMAL: case PropertyType::PATH: $return[] = $value; break; default: throw new \RuntimeException('Unknown type ' . $property->getType()); } } if ($property->isMultiple()) { return implode("\n", array_map(function ($value) { static $index = 0; return sprintf('<comment>[%d]</comment> %s', $index++, $value); }, $return)); } return implode("\n", $return); }
/** * Validation if all the data is correct before writing it into the database. * * @param PropertyInterface $property * * @throws ValueFormatException */ private function assertValidProperty($property) { $type = $property->getType(); switch ($type) { case PropertyType::NAME: $values = $property->getValue(); if (!$property->isMultiple()) { $values = array($values); } foreach ($values as $value) { $pos = strpos($value, ':'); if (false !== $pos) { $prefix = substr($value, 0, $pos); $this->getNamespaces(); if (!isset($this->namespaces[$prefix])) { throw new ValueFormatException("Invalid PHPCR NAME at '" . $property->getPath() . "': The namespace prefix " . $prefix . " does not exist."); } } } break; case PropertyType::PATH: $values = $property->getValue(); if (!$property->isMultiple()) { $values = array($values); } foreach ($values as $value) { if (!preg_match('(((/|..)?[-a-zA-Z0-9:_]+)+)', $value)) { throw new ValueFormatException("Invalid PATH '$value' at '" . $property->getPath() ."': Segments are separated by / and allowed chars are -a-zA-Z0-9:_"); } } break; case PropertyType::URI: $values = $property->getValue(); if (!$property->isMultiple()) { $values = array($values); } foreach ($values as $value) { if (!preg_match(self::VALIDATE_URI_RFC3986, $value)) { throw new ValueFormatException("Invalid URI '$value' at '" . $property->getPath() ."': Has to follow RFC 3986."); } } break; case PropertyType::DECIMAL: case PropertyType::STRING: $values = (array) $property->getValue(); foreach ($values as $value) { if (!$this->isStringValid($value)) { throw new ValueFormatException('Invalid character found in property "'.$property->getName().'". Are you passing a valid string?'); } } break; } }
/** * "Decode" PHPCR property to MongoDB property * * @param $property * @return array|null * * @throws \Exception */ private function decodeProperty(PropertyInterface $property) { $path = $property->getPath(); $path = $this->validatePath($path); $name = explode('/', $path); $name = end($name); if ($name == 'jcr:uuid' || $name == 'jcr:primaryType') { return null; } if (!$property->isModified() && !$property->isNew()) { return null; } $propType = $property->getType(); $propNode = $property->getNode(); if (($propType == PropertyType::REFERENCE || $propType == PropertyType::WEAKREFERENCE) && ($propNode instanceof NodeInterface && !$propNode->isNodeType('mix:referenceable'))) { throw new ValueFormatException('Node ' . $property->getNode()->getPath() . ' is not referenceable.'); } $isMultiple = $property->isMultiple(); $typeId = $property->getType(); $type = PropertyType::nameFromValue($typeId); $data = array('multi' => $isMultiple, 'name' => $property->getName(), 'type' => $type); $binaryData = null; switch ($typeId) { case PropertyType::NAME: case PropertyType::URI: case PropertyType::WEAKREFERENCE: case PropertyType::REFERENCE: case PropertyType::PATH: $values = $property->getString(); break; case PropertyType::DECIMAL: $values = $property->getDecimal(); break; case PropertyType::STRING: $values = $property->getString(); break; case PropertyType::BOOLEAN: $values = $property->getBoolean(); break; case PropertyType::LONG: $values = $property->getLong(); break; case PropertyType::BINARY: if ($property->isMultiple()) { foreach ((array) $property->getBinary() as $binary) { $binary = stream_get_contents($binary); $binaryData[] = $binary; $values[] = strlen($binary); } } else { $binary = stream_get_contents($property->getBinary()); $binaryData[] = $binary; $values = strlen($binary); } break; case PropertyType::DATE: if ($property->isMultiple()) { $dates = $property->getDate() ?: new \DateTime('now'); foreach ((array) $dates as $date) { $value = array('date' => new \MongoDate($date->getTimestamp()), 'timezone' => $date->getTimezone()->getName()); $values[] = $value; } } else { $date = $property->getDate() ?: new \DateTime('now'); $values = array('date' => new \MongoDate($date->getTimestamp()), 'timezone' => $date->getTimezone()->getName()); } break; case PropertyType::DOUBLE: $values = $property->getDouble(); break; } if ($isMultiple) { $data['value'] = array(); foreach ((array) $values as $value) { $this->assertValidPropertyValue($data['type'], $value, $path); $data['value'][] = $value; } } else { $this->assertValidPropertyValue($data['type'], $values, $path); $data['value'] = $values; } if ($binaryData) { try { foreach ($binaryData as $idx => $binary) { $grid = $this->db->getGridFS(); $grid->getMongoCollection()->storeBytes($binary, array('path' => $path, 'w_id' => $this->workspaceId, 'idx' => $idx)); } } catch (\Exception $e) { throw $e; } } return $data; }
/** * Remove the given property, or the value which references the node (when * multi-valued). * * @param NodeInterface $node * @param PropertyInterface $property */ private function dereferenceProperty(NodeInterface $node, PropertyInterface $property) { if (false === $property->isMultiple()) { $property->remove(); return; } // dereference from multi-valued referring properties $values = $property->getValue(); foreach ($values as $i => $referencedNode) { if ($referencedNode->getIdentifier() === $node->getIdentifier()) { unset($values[$i]); } } $property->getParent()->setProperty($property->getName(), $values); }
/** * Validation if all the data is correct before writing it into the database. * * @param PropertyInterface $property * * @throws RepositoryException * @throws ValueFormatException */ private function assertValidProperty(PropertyInterface $property) { $type = $property->getType(); switch ($type) { case PropertyType::NAME: $values = $property->getValue(); if (!$property->isMultiple()) { $values = array($values); } foreach ($values as $value) { $pos = strpos($value, ':'); if (false !== $pos) { $prefix = substr($value, 0, $pos); if (!isset($this->namespaces[$prefix])) { throw new ValueFormatException(sprintf('Invalid value for NAME property type at "%s", the namespace prefix "%s" does not exist.");', $property->getPath(), $prefix)); } } } break; case PropertyType::PATH: $values = $property->getValue(); if (!$property->isMultiple()) { $values = array($values); } foreach ($values as $value) { try { // making the path absolute also validates the result to be a valid path PathHelper::absolutizePath($value, $property->getPath()); } catch (RepositoryException $e) { throw new ValueFormatException(sprintf('Value "%s" for PATH property at "%s" is invalid', $value, $property->getPath()), 0, $e); } } break; case PropertyType::URI: $values = $property->getValue(); if (!$property->isMultiple()) { $values = array($values); } foreach ($values as $value) { if (!preg_match(self::VALIDATE_URI_RFC3986, $value)) { throw new ValueFormatException(sprintf('Invalid value "%s" for URI property at "%s". Value has to comply with RFC 3986.', $value, $property->getPath())); } } break; case PropertyType::DECIMAL: case PropertyType::STRING: $values = (array) $property->getValue(); foreach ($values as $value) { if (0 !== preg_match(self::VALIDATE_STRING, $value)) { throw new ValueFormatException(sprintf('Invalid character detected in value %s for STRING property at "%s".', json_encode($value), $property->getPath())); } } break; } }