Skip to content

Commit 941b684

Browse files
committed
POC allow sorting on numerical columns
1 parent 31cca1d commit 941b684

File tree

3 files changed

+184
-107
lines changed

3 files changed

+184
-107
lines changed

src/Jackalope/Transport/DoctrineDBAL/Client.php

+156-81
Original file line numberDiff line numberDiff line change
@@ -662,7 +662,9 @@ private function syncNode($uuid, $path, $type, $isNewNode, $props = array(), $pr
662662
'namespace' => $namespace,
663663
'parent' => PathHelper::getParentPath($path),
664664
'workspace_name' => $this->workspaceName,
665-
'props' => $propsData['dom']->saveXML(),
665+
'props' => $propsData['stringDom'] ? $propsData['stringDom']->saveXML() : null,
666+
'long_props' => $propsData['longDom'] ? $propsData['longDom']->saveXML() : null,
667+
'decimal_props' => $propsData['decimalDom'] ? $propsData['decimalDom']->saveXML() : null,
666668
'depth' => PathHelper::getPathDepth($path),
667669
'parent_a' => PathHelper::getParentPath($path),
668670
));
@@ -684,7 +686,13 @@ private function syncNode($uuid, $path, $type, $isNewNode, $props = array(), $pr
684686
if (!$nodeId) {
685687
throw new RepositoryException("nodeId for $path not found");
686688
}
687-
$this->conn->update('phpcr_nodes', array('props' => $propsData['dom']->saveXML()), array('id' => $nodeId));
689+
$this->conn->update('phpcr_nodes', array(
690+
'props' => $propsData['stringDom'] ? $propsData['stringDom']->saveXML() : null,
691+
'long_props' => $propsData['longDom'] ? $propsData['longDom']->saveXML() : null,
692+
'decimal_props' => $propsData['decimalDom'] ? $propsData['decimalDom']->saveXML() : null,
693+
),
694+
array('id' => $nodeId)
695+
);
688696
}
689697

690698
$this->nodeIdentifiers[$path] = $uuid;
@@ -837,70 +845,85 @@ private function syncReferences()
837845
}
838846
}
839847

840-
public static function xmlToProps($xml, ValueConverter $valueConverter, $filter = null)
848+
public static function xmlToProps($xmlData, ValueConverter $valueConverter, $filter = null)
841849
{
842850
$data = new \stdClass();
843851

844-
$dom = new \DOMDocument('1.0', 'UTF-8');
845-
$dom->loadXML($xml);
852+
$xmlFields = array();
846853

847-
foreach ($dom->getElementsByTagNameNS('http://www.jcp.org/jcr/sv/1.0', 'property') as $propertyNode) {
848-
$name = $propertyNode->getAttribute('sv:name');
854+
if (!empty($xmlData['props'])) {
855+
$xmlFields[] = $xmlData['props'];
856+
}
857+
if (!empty($xmlData['long_props'])) {
858+
$xmlFields[] = $xmlData['long_props'];
859+
}
860+
if (!empty($xmlData['decimal_props'])) {
861+
$xmlFields[] = $xmlData['decimal_props'];
862+
}
849863

850-
// only return the properties that pass through the filter callback
851-
if (null !== $filter && is_callable($filter) && false === $filter($name)) {
852-
continue;
853-
}
864+
foreach ($xmlFields as $xml) {
865+
866+
$dom = new \DOMDocument('1.0', 'UTF-8');
867+
$dom->loadXML($xml);
868+
869+
foreach ($dom->getElementsByTagNameNS('http://www.jcp.org/jcr/sv/1.0', 'property') as $propertyNode) {
870+
$name = $propertyNode->getAttribute('sv:name');
871+
872+
// only return the properties that pass through the filter callback
873+
if (null !== $filter && is_callable($filter) && false === $filter($name)) {
874+
continue;
875+
}
876+
877+
$values = array();
878+
$type = PropertyType::valueFromName($propertyNode->getAttribute('sv:type'));
879+
foreach ($propertyNode->childNodes as $valueNode) {
880+
switch ($type) {
881+
case PropertyType::NAME:
882+
case PropertyType::URI:
883+
case PropertyType::WEAKREFERENCE:
884+
case PropertyType::REFERENCE:
885+
case PropertyType::PATH:
886+
case PropertyType::DECIMAL:
887+
case PropertyType::STRING:
888+
$values[] = $valueNode->nodeValue;
889+
break;
890+
case PropertyType::BOOLEAN:
891+
$values[] = (bool) $valueNode->nodeValue;
892+
break;
893+
case PropertyType::LONG:
894+
$values[] = (int) $valueNode->nodeValue;
895+
break;
896+
case PropertyType::BINARY:
897+
$values[] = (int) $valueNode->nodeValue;
898+
break;
899+
case PropertyType::DATE:
900+
$date = $valueNode->nodeValue;
901+
if ($date) {
902+
$date = new \DateTime($date);
903+
$date->setTimezone(new \DateTimeZone(date_default_timezone_get()));
904+
// Jackalope expects a string, might make sense to refactor to allow \DateTime instances too
905+
$date = $valueConverter->convertType($date, PropertyType::STRING);
906+
}
907+
$values[] = $date;
908+
break;
909+
case PropertyType::DOUBLE:
910+
$values[] = (double) $valueNode->nodeValue;
911+
break;
912+
default:
913+
throw new \InvalidArgumentException("Type with constant $type not found.");
914+
}
915+
}
854916

855-
$values = array();
856-
$type = PropertyType::valueFromName($propertyNode->getAttribute('sv:type'));
857-
foreach ($propertyNode->childNodes as $valueNode) {
858917
switch ($type) {
859-
case PropertyType::NAME:
860-
case PropertyType::URI:
861-
case PropertyType::WEAKREFERENCE:
862-
case PropertyType::REFERENCE:
863-
case PropertyType::PATH:
864-
case PropertyType::DECIMAL:
865-
case PropertyType::STRING:
866-
$values[] = $valueNode->nodeValue;
867-
break;
868-
case PropertyType::BOOLEAN:
869-
$values[] = (bool) $valueNode->nodeValue;
870-
break;
871-
case PropertyType::LONG:
872-
$values[] = (int) $valueNode->nodeValue;
873-
break;
874918
case PropertyType::BINARY:
875-
$values[] = (int) $valueNode->nodeValue;
876-
break;
877-
case PropertyType::DATE:
878-
$date = $valueNode->nodeValue;
879-
if ($date) {
880-
$date = new \DateTime($date);
881-
$date->setTimezone(new \DateTimeZone(date_default_timezone_get()));
882-
// Jackalope expects a string, might make sense to refactor to allow \DateTime instances too
883-
$date = $valueConverter->convertType($date, PropertyType::STRING);
884-
}
885-
$values[] = $date;
886-
break;
887-
case PropertyType::DOUBLE:
888-
$values[] = (double) $valueNode->nodeValue;
919+
$data->{':' . $name} = $propertyNode->getAttribute('sv:multi-valued') ? $values : $values[0];
889920
break;
890921
default:
891-
throw new \InvalidArgumentException("Type with constant $type not found.");
922+
$data->{$name} = $propertyNode->getAttribute('sv:multi-valued') ? $values : $values[0];
923+
$data->{':' . $name} = $type;
924+
break;
892925
}
893926
}
894-
895-
switch ($type) {
896-
case PropertyType::BINARY:
897-
$data->{':' . $name} = $propertyNode->getAttribute('sv:multi-valued') ? $values : $values[0];
898-
break;
899-
default:
900-
$data->{$name} = $propertyNode->getAttribute('sv:multi-valued') ? $values : $values[0];
901-
$data->{':' . $name} = $type;
902-
break;
903-
}
904927
}
905928

906929
return $data;
@@ -912,7 +935,11 @@ public static function xmlToProps($xml, ValueConverter $valueConverter, $filter
912935
* @param array $properties
913936
* @param boolean $inlineBinaries
914937
*
915-
* @return array ('dom' => $dom, 'binaryData' => streams, 'references' => array('type' => INT, 'values' => array(UUIDs)))
938+
* @return array (
939+
* 'stringDom' => $stringDom,
940+
* 'integerDom' => $integerDom',
941+
* 'binaryData' => streams,
942+
* 'references' => array('type' => INT, 'values' => array(UUIDs)))
916943
*/
917944
private function propsToXML($properties, $inlineBinaries = false)
918945
{
@@ -925,20 +952,17 @@ private function propsToXML($properties, $inlineBinaries = false)
925952
'rep' => "internal",
926953
);
927954

928-
$dom = new \DOMDocument('1.0', 'UTF-8');
929-
$rootNode = $dom->createElement('sv:node');
930-
foreach ($namespaces as $namespace => $uri) {
931-
$rootNode->setAttribute('xmlns:' . $namespace, $uri);
932-
}
933-
$dom->appendChild($rootNode);
955+
$propertyMap = array(
956+
'longDom' => array(),
957+
'stringDom' => array(),
958+
'decimalDom' => array(),
959+
);
934960

935961
$binaryData = $references = array();
962+
936963
foreach ($properties as $property) {
937-
/* @var $property Property */
938-
$propertyNode = $dom->createElement('sv:property');
939-
$propertyNode->setAttribute('sv:name', $property->getName());
940-
$propertyNode->setAttribute('sv:type', PropertyType::nameFromValue($property->getType()));
941-
$propertyNode->setAttribute('sv:multi-valued', $property->isMultiple() ? '1' : '0');
964+
965+
$column = 'stringDom';
942966

943967
switch ($property->getType()) {
944968
case PropertyType::WEAKREFERENCE:
@@ -955,12 +979,14 @@ private function propsToXML($properties, $inlineBinaries = false)
955979
break;
956980
case PropertyType::DECIMAL:
957981
$values = $property->getDecimal();
982+
$column = 'decimalDom';
958983
break;
959984
case PropertyType::BOOLEAN:
960985
$values = array_map('intval', (array) $property->getBoolean());
961986
break;
962987
case PropertyType::LONG:
963988
$values = $property->getLong();
989+
$column = 'longDom';
964990
break;
965991
case PropertyType::BINARY:
966992
if ($property->isNew() || $property->isModified()) {
@@ -998,26 +1024,65 @@ private function propsToXML($properties, $inlineBinaries = false)
9981024
break;
9991025
case PropertyType::DOUBLE:
10001026
$values = $property->getDouble();
1027+
$column = 'decimalDom';
10011028
break;
10021029
default:
10031030
throw new RepositoryException('unknown type '.$property->getType());
10041031
}
10051032

1006-
$lengths = (array) $property->getLength();
1007-
foreach ((array) $values as $key => $value) {
1008-
$element = $propertyNode->appendChild($dom->createElement('sv:value'));
1009-
$element->appendChild($dom->createTextNode($value));
1010-
if (isset($lengths[$key])) {
1011-
$lengthAttribute = $dom->createAttribute('length');
1012-
$lengthAttribute->value = $lengths[$key];
1013-
$element->appendChild($lengthAttribute);
1033+
$propertyMap[$column][] = array(
1034+
'name' => $property->getName(),
1035+
'type' => PropertyType::nameFromValue($property->getType()),
1036+
'multiple' => $property->isMultiple(),
1037+
'lengths' => (array) $property->getLength(),
1038+
'values' => $values,
1039+
);
1040+
}
1041+
1042+
$ret = array(
1043+
'stringDom' => null,
1044+
'longDom' => null,
1045+
'decimalDom' => null,
1046+
'binaryData' => $binaryData,
1047+
'references' => $references
1048+
);
1049+
1050+
foreach ($propertyMap as $column => $properties) {
1051+
1052+
$dom = new \DOMDocument('1.0', 'UTF-8');
1053+
$rootNode = $dom->createElement('sv:node');
1054+
foreach ($namespaces as $namespace => $uri) {
1055+
$rootNode->setAttribute('xmlns:' . $namespace, $uri);
1056+
}
1057+
$dom->appendChild($rootNode);
1058+
1059+
foreach ($properties as $property) {
1060+
1061+
/* @var $property Property */
1062+
$propertyNode = $dom->createElement('sv:property');
1063+
$propertyNode->setAttribute('sv:name', $property['name']);
1064+
$propertyNode->setAttribute('sv:type', $property['type']);
1065+
$propertyNode->setAttribute('sv:multi-valued', $property['multiple'] ? '1' : '0');
1066+
$lengths = (array) $property['lengths'];
1067+
foreach ((array) $values as $key => $value) {
1068+
$element = $propertyNode->appendChild($dom->createElement('sv:value'));
1069+
$element->appendChild($dom->createTextNode($value));
1070+
if (isset($lengths[$key])) {
1071+
$lengthAttribute = $dom->createAttribute('length');
1072+
$lengthAttribute->value = $lengths[$key];
1073+
$element->appendChild($lengthAttribute);
1074+
}
10141075
}
1076+
1077+
$rootNode->appendChild($propertyNode);
10151078
}
10161079

1017-
$rootNode->appendChild($propertyNode);
1080+
if (count($properties)) {
1081+
$ret[$column] = $dom;
1082+
}
10181083
}
10191084

1020-
return array('dom' => $dom, 'binaryData' => $binaryData, 'references' => $references);
1085+
return $ret;
10211086
}
10221087

10231088
/**
@@ -1123,7 +1188,7 @@ private function getNodesData($rows)
11231188

11241189
foreach ($rows as $row) {
11251190
$this->nodeIdentifiers[$row['path']] = $row['identifier'];
1126-
$data[$row['path']] = self::xmlToProps($row['props'], $this->valueConverter);
1191+
$data[$row['path']] = self::xmlToProps($row, $this->valueConverter);
11271192
$data[$row['path']]->{'jcr:primaryType'} = $row['type'];
11281193
$paths[] = $row['path'];
11291194
}
@@ -1190,7 +1255,7 @@ public function getNodes($paths)
11901255
$params[':fetchDepth'] = $this->fetchDepth;
11911256

11921257
$query = '
1193-
SELECT path AS arraykey, id, path, parent, local_name, namespace, workspace_name, identifier, type, props, depth, sort_order
1258+
SELECT path AS arraykey, id, path, parent, local_name, namespace, workspace_name, identifier, type, props, long_props, decimal_props, depth, sort_order
11941259
FROM phpcr_nodes
11951260
WHERE workspace_name = :workspace
11961261
AND (';
@@ -1204,7 +1269,7 @@ public function getNodes($paths)
12041269
$i++;
12051270
}
12061271
} else {
1207-
$query = 'SELECT path AS arraykey, id, path, parent, local_name, namespace, workspace_name, identifier, type, props, depth, sort_order
1272+
$query = 'SELECT path AS arraykey, id, path, parent, local_name, namespace, workspace_name, identifier, type, props, long_props, decimal_props, depth, sort_order
12081273
FROM phpcr_nodes WHERE workspace_name = :workspace AND (';
12091274

12101275
$i = 0;
@@ -1278,7 +1343,7 @@ public function getNodesByIdentifier($identifiers)
12781343
return array();
12791344
}
12801345

1281-
$query = 'SELECT id, path, parent, local_name, namespace, workspace_name, identifier, type, props, depth, sort_order
1346+
$query = 'SELECT id, path, parent, local_name, namespace, workspace_name, identifier, type, props, long_props, decimal_props, depth, sort_order
12821347
FROM phpcr_nodes WHERE workspace_name = ? AND identifier IN (?)';
12831348
if ($this->conn->getDatabasePlatform() instanceof SqlitePlatform) {
12841349
$all = array();
@@ -2178,6 +2243,7 @@ public function query(Query $query)
21782243

21792244
$primarySource = reset($selectors);
21802245
$primaryType = $primarySource->getSelectorName() ?: $primarySource->getNodeTypeName();
2246+
error_log($sql);
21812247
$data = $this->conn->fetchAll($sql, array($this->workspaceName));
21822248

21832249
$results = $properties = $standardColumns = array();
@@ -2202,7 +2268,11 @@ public function query(Query $query)
22022268

22032269
if (isset($row[$columnPrefix . 'props'])) {
22042270
$properties[$selectorName] = (array) static::xmlToProps(
2205-
$row[$columnPrefix . 'props'],
2271+
array(
2272+
'props' => $row[$columnPrefix . 'props'],
2273+
'decimal_props' => $row[$columnPrefix . 'decimal_props'],
2274+
'long_props' => $row[$columnPrefix . 'long_props'],
2275+
),
22062276
$this->valueConverter
22072277
);
22082278
} else {
@@ -2223,6 +2293,11 @@ public function query(Query $query)
22232293
$columnName = $column->getPropertyName();
22242294
$columnPrefix = isset($selectorAliases[$selectorName]) ? $selectorAliases[$selectorName] . '_' : $selectorAliases[''] . '_';
22252295

2296+
// do not overwrite jcr:path and jcr:score
2297+
if (in_array($columnName, array('jcr:path', 'jcr:score'))) {
2298+
continue;
2299+
}
2300+
22262301
$dcrValue = 'jcr:uuid' === $columnName
22272302
? $row[$columnPrefix . 'identifier']
22282303
: (isset($properties[$selectorName][$columnName]) ? $properties[$selectorName][$columnName] : '')

0 commit comments

Comments
 (0)