/** * Append to content nodes to the target nodes. * * @param array|\Traversable $contentNodes * @return array new nodes */ public function appendChildren($contentNodes) { $result = array(); if ($this->_node instanceof \DOMElement) { foreach ($contentNodes as $contentNode) { /** @var \DOMNode $contentNode */ if (Constraints::isNode($contentNode)) { $result[] = $this->_node->appendChild($contentNode->cloneNode(TRUE)); } } } return $result; }
/** * Convert a given content string into and array of nodes * * @param string $xml * @param string $contentType * @param boolean $includeTextNodes * @param integer $limit * @throws \UnexpectedValueException * @return array */ public function getFragment($xml, $contentType = 'text/xml', $includeTextNodes = TRUE, $limit = -1) { $xml = $this->getContentAsString($xml); $loader = $this->getOwner()->loaders(); if (!$loader->supports($contentType)) { throw new Exceptions\InvalidFragmentLoader(get_class($loader)); } if (!$xml) { return array(); } $result = array(); $fragment = $loader->loadFragment($xml, $contentType, $this->getOwner()->getLoadingOptions($contentType)); if ($fragment) { $fragment = $this->getOwner()->document->importNode($fragment, TRUE); for ($i = $fragment->childNodes->length - 1; $i >= 0; $i--) { $element = $fragment->childNodes->item($i); if ($element instanceof \DOMElement || $includeTextNodes && Constraints::isNode($element)) { array_unshift($result, $element); $element->parentNode->removeChild($element); } } } return $this->getLimitedArray($result, $limit); }
/** * 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; }
/** * @param array $nodes * @param callable $filter * @param callable $stopAt * @param int $options * @return array */ private function filterNodes(array $nodes, callable $filter = NULL, callable $stopAt = NULL, $options = 0) { $result = array(); foreach ($nodes as $index => $node) { list($isFilter, $isStopAt) = $this->getNodeStatus($node, $index, $filter, $stopAt); if ($isStopAt) { if ($isFilter && Constraints::hasOption($options, self::INCLUDE_STOP)) { $result[] = $node; } return $result; } elseif ($isFilter) { $result[] = $node; } } return $result; }
/** * Adds the specified classes if the switch is TRUE, * removes the specified classes if the switch is FALSE, * toggles the specified classes if the switch is NULL. * * @example toggleClass.php Usage Example: FluentDOM\Query::toggleClass() * @param string|callable $class * @param NULL|boolean $switch toggle if NULL, add if TRUE, remove if FALSE * @return Query */ public function toggleClass($class, $switch = NULL) { $callback = Constraints::isCallable($class); $this->each(function (\DOMElement $node, $index) use($class, $switch, $callback) { if ($callback) { $classString = $callback($node, $index, $node->getAttribute('class')); } else { $classString = $class; } if (empty($classString) && !(bool) $switch) { if ($node->hasAttribute('class')) { $node->removeAttribute('class'); } } else { $modified = $this->changeClassString($node->getAttribute('class'), $classString, $switch); if (FALSE !== $modified) { if (empty($modified)) { $node->removeAttribute('class'); } else { $node->setAttribute('class', $modified); } } } }, TRUE); return $this; }