/** * {@inheritDoc} * * Overwritten to validate that unpersisted nodes are not referenced. * * This is needed because of this jackrabbit issue: * https://issues.apache.org/jira/browse/JCR-1614 */ public function convertType($value, $type, $srctype = PropertyType::UNDEFINED) { if (is_array($value)) { return parent::convertType($value, $type, $srctype); } if (PropertyType::UNDEFINED == $srctype) { $srctype = $this->determineType($value); } if ((PropertyType::REFERENCE == $srctype || PropertyType::WEAKREFERENCE == $srctype) && $value instanceof NodeInterface) { if ($value->isNew()) { throw new ValueFormatException('Node ' . $value->getPath() . ' must be persisted before being referenceable'); } } return parent::convertType($value, $type, $srctype); }
/** * Literal ::= CastLiteral | UncastLiteral * * @param mixed $literal * * @return string */ public function evalLiteral($literal) { if ($literal instanceof \DateTime) { $string = $this->valueConverter->convertType($literal, PropertyType::STRING); return $this->evalCastLiteral($string, 'DATE'); } if (is_bool($literal)) { $string = $literal ? 'true' : 'false'; return $this->evalCastLiteral($string, 'BOOLEAN'); } if (is_int($literal)) { $string = $this->valueConverter->convertType($literal, PropertyType::STRING); return $this->evalCastLiteral($string, 'LONG'); } if (is_float($literal)) { $string = $this->valueConverter->convertType($literal, PropertyType::STRING); return $this->evalCastLiteral($string, 'DOUBLE'); } return "'{$literal}'"; }
/** * Seperate properties array into an xml and binary data. * * @param array $properties * * @return array ( * 'stringDom' => $stringDom, * 'numericalDom' => $numericalDom', * 'binaryData' => streams, * 'references' => array('type' => INT, 'values' => array(UUIDs))) */ private function propsToXML($properties) { $namespaces = array('mix' => "http://www.jcp.org/jcr/mix/1.0", 'nt' => "http://www.jcp.org/jcr/nt/1.0", 'xs' => "http://www.w3.org/2001/XMLSchema", 'jcr' => "http://www.jcp.org/jcr/1.0", 'sv' => "http://www.jcp.org/jcr/sv/1.0", 'rep' => "internal"); $doms = array('stringDom' => array(), 'numericalDom' => array()); $binaryData = $references = array(); foreach ($properties as $property) { $targetDoms = array('stringDom'); switch ($property->getType()) { case PropertyType::WEAKREFERENCE: case PropertyType::REFERENCE: $references[$property->getName()] = array('type' => $property->getType(), 'values' => $property->isMultiple() ? $property->getString() : array($property->getString())); case PropertyType::NAME: case PropertyType::URI: case PropertyType::PATH: case PropertyType::STRING: $values = $property->getString(); break; case PropertyType::DECIMAL: $values = $property->getDecimal(); $targetDoms[] = 'numericalDom'; break; case PropertyType::BOOLEAN: $values = array_map('intval', (array) $property->getBoolean()); break; case PropertyType::LONG: $values = $property->getLong(); $targetDoms[] = 'numericalDom'; break; case PropertyType::BINARY: if ($property->isNew() || $property->isModified()) { $values = array(); foreach ((array) $property->getValueForStorage() as $stream) { if (null === $stream) { $binary = ''; } else { $binary = stream_get_contents($stream); fclose($stream); } $binaryData[$property->getName()][] = $binary; $length = strlen($binary); $values[] = $length; } } else { $values = $property->getLength(); if (!$property->isMultiple() && empty($values)) { $values = array(0); } } break; case PropertyType::DATE: $values = $property->getDate(); if ($values instanceof \DateTime) { $values = array($values); } foreach ((array) $values as $key => $date) { if ($date instanceof \DateTime) { // do not modify the instance which is associated with the node. $date = clone $date; // normalize to UTC for storage. $date->setTimezone(new \DateTimeZone('UTC')); } $values[$key] = $date; } $values = $this->valueConverter->convertType($values, PropertyType::STRING); break; case PropertyType::DOUBLE: $values = $property->getDouble(); $targetDoms[] = 'numericalDom'; break; default: throw new RepositoryException('unknown type ' . $property->getType()); } foreach ($targetDoms as $targetDom) { $doms[$targetDom][] = array('name' => $property->getName(), 'type' => PropertyType::nameFromValue($property->getType()), 'multiple' => $property->isMultiple(), 'lengths' => (array) $property->getLength(), 'values' => $values); } } $ret = array('stringDom' => null, 'numericalDom' => null, 'binaryData' => $binaryData, 'references' => $references); foreach ($doms as $targetDom => $properties) { $dom = new \DOMDocument('1.0', 'UTF-8'); $rootNode = $dom->createElement('sv:node'); foreach ($namespaces as $namespace => $uri) { $rootNode->setAttribute('xmlns:' . $namespace, $uri); } $dom->appendChild($rootNode); foreach ($properties as $property) { /* @var $property Property */ $propertyNode = $dom->createElement('sv:property'); $propertyNode->setAttribute('sv:name', $property['name']); $propertyNode->setAttribute('sv:type', $property['type']); $propertyNode->setAttribute('sv:multi-valued', $property['multiple'] ? '1' : '0'); $lengths = (array) $property['lengths']; foreach ((array) $property['values'] as $key => $value) { $element = $propertyNode->appendChild($dom->createElement('sv:value')); $element->appendChild($dom->createTextNode($value)); if (isset($lengths[$key])) { $lengthAttribute = $dom->createAttribute('length'); $lengthAttribute->value = $lengths[$key]; $element->appendChild($lengthAttribute); } } $rootNode->appendChild($propertyNode); } if (count($properties)) { $ret[$targetDom] = $dom; } } return $ret; }
/** * @expectedException \PHPCR\ValueFormatException */ public function testConvertTypeInvalidTarget() { $this->valueConverter->convertType('test', PropertyType::UNDEFINED); }
protected function getMimePart($name, $value, $mime_boundary) { $data = ''; $eol = "\r\n"; if (is_array($value)) { if (is_array($value[0])) { foreach ($value[0] as $v) { $data .= $this->getMimePart($name, array($v, $value[1]), $mime_boundary); } return $data; } $data .= '--' . $mime_boundary . $eol; if (is_resource($value[0])) { $data .= 'Content-Disposition: form-data; name="' . $name . '"; filename="' . $name . '"' . $eol; $data .= 'Content-Type: jcr-value/' . strtolower(PropertyType::nameFromValue($value[1])) . '; charset=UTF-8' . $eol; $data .= 'Content-Transfer-Encoding: binary' . $eol . $eol; $data .= stream_get_contents($value[0]) . $eol; fclose($value[0]); } else { $data .= 'Content-Disposition: form-data; name="' . $name . '"' . $eol; $data .= 'Content-Type: jcr-value/' . strtolower(PropertyType::nameFromValue($value[1])) . '; charset=UTF-8' . $eol; $data .= 'Content-Transfer-Encoding: 8bit' . $eol . $eol; switch ($value[1]) { case PropertyType::DATE: $data .= $this->valueConverter->convertType($value[0], PropertyType::STRING); break; default: $data .= $value[0]; } $data .= $eol; } } else { if (is_array($value)) { foreach ($value as $v) { $data .= $this->getMimePart($name, $v, $mime_boundary); } return $data; } $data .= '--' . $mime_boundary . $eol; $data .= 'Content-Disposition: form-data; name="' . $name . '"' . $eol; $data .= 'Content-Type: text/plain; charset=UTF-8' . $eol; $data .= 'Content-Transfer-Encoding: 8bit' . $eol . $eol; //$data .= '--' . $mime_boundary . $eol; $data .= $value . $eol; } return $data; }