/** * Sorts an array of DOM nodes based on document position, in place, with the duplicates removed. * Note that this only works on arrays of DOM nodes, not strings or numbers. * * @param \DOMNode[] $array array of DOM nodes * @throws \InvalidArgumentException * @return array */ public function unique(array $array) { $count = count($array); if ($count <= 1) { if ($count == 1) { Constraints::assertNode(reset($array), 'Array must only contain dom nodes, found "%s".'); } return $array; } $sortable = array(); $unsortable = array(); foreach ($array as $node) { Constraints::assertNode($node, 'Array must only contain dom nodes, found "%s".'); $hash = spl_object_hash($node); if ($node->parentNode instanceof \DOMNode || $node === $node->ownerDocument->documentElement) { /* use the document position as index, ignore duplicates */ if (!isset($sortable[$hash])) { $sortable[$hash] = $node; } } else { /* use the object hash as index, ignore duplicates */ if (!isset($unsortable[$hash])) { $unsortable[$hash] = $node; } } } uasort($sortable, new Nodes\Compare($this->xpath)); $result = array_values($sortable); array_splice($result, count($result), 0, array_values($unsortable)); return $result; }