Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
Total | |
0.00% |
0 / 1 |
|
0.00% |
0 / 6 |
CRAP | |
0.00% |
0 / 55 |
ChildNode | |
0.00% |
0 / 1 |
|
0.00% |
0 / 6 |
650 | |
0.00% |
0 / 55 |
_fragment_from_arguments | |
0.00% |
0 / 1 |
12 | |
0.00% |
0 / 6 |
|||
after | |
0.00% |
0 / 1 |
20 | |
0.00% |
0 / 9 |
|||
before | |
0.00% |
0 / 1 |
30 | |
0.00% |
0 / 10 |
|||
remove | |
0.00% |
0 / 1 |
20 | |
0.00% |
0 / 10 |
|||
_remove | |
0.00% |
0 / 1 |
20 | |
0.00% |
0 / 9 |
|||
replaceWith | |
0.00% |
0 / 1 |
30 | |
0.00% |
0 / 11 |
<?php | |
declare( strict_types = 1 ); | |
// @phan-file-suppress PhanTypeMismatchArgument | |
// @phan-file-suppress PhanUndeclaredMethod | |
// @phan-file-suppress PhanUndeclaredProperty | |
// phpcs:disable Generic.NamingConventions.CamelCapsFunctionName.ScopeNotCamelCaps | |
// phpcs:disable MediaWiki.Commenting.FunctionComment.WrongStyle | |
namespace Wikimedia\Dodo; | |
/****************************************************************************** | |
* ChildNode.php | |
* ------------- | |
*/ | |
/** | |
* DOM-LS | |
* Node objects that can have a parent must | |
* implement the ChildNode class. These include: | |
* | |
* Element | |
* CharacterData | |
* DocumentType | |
* | |
* The additional methods defined by this class | |
* are practical conveniences, but are not really | |
* required to get full DOM functionality. | |
*/ | |
trait ChildNode /* implements \Wikimedia\IDLeDOM\ChildNode */ { | |
use \Wikimedia\IDLeDOM\Stub\ChildNode; | |
/** | |
* @param Document $document | |
* @param array $args | |
* @return DocumentFragment | |
*/ | |
private static function _fragment_from_arguments( $document, array $args ) { | |
$fragment = $document->createDocumentFragment(); | |
foreach ( $args as $item ) { | |
if ( !( $item instanceof Node ) ) { | |
/* In particular, you can't have NULLs */ | |
$item = $document->createTextNode( strval( $item ) ); | |
} | |
$fragment->appendChild( $item ); | |
} | |
return $fragment; | |
} | |
/** | |
* Insert any number of Nodes or | |
* DOMStrings after $this. | |
* | |
* NOTE | |
* DOMStrings are inserted as | |
* equivalent Text nodes. | |
* | |
* TODO: after and before() | |
* are very very similar and | |
* could probably be factored | |
* nicely.. | |
* | |
* @inheritDoc | |
*/ | |
public function after( ...$args /* DOMStrings and/or Nodes */ ) : void { | |
$parentNode = $this->_parentNode; | |
$nextSibling = $this->getNextSibling(); | |
if ( $parentNode === null ) { | |
/* | |
* If $this has no parent, | |
* then it is not actually | |
* part of a document, and | |
* according to DOM-LS, | |
* this method has no effect. | |
*/ | |
return; | |
} | |
// Find "viable next sibling"; that is, next one not in $args | |
while ( $nextSibling !== null && in_array( $nextSibling, $args, true ) ) { | |
$nextSibling = $nextSibling->getNextSibling(); | |
} | |
// ok, parent and sibling are saved away since this node could itself | |
// appear in $args and we're about to move $args to a document fragment. | |
/* | |
* Turn the arguments into | |
* a DocumentFragment. | |
*/ | |
$frag = self::_fragment_from_arguments( $this->__node_document(), $args ); | |
/* | |
* Insert the DocumentFragment | |
* at the determined location. | |
*/ | |
$parentNode->insertBefore( $frag, $nextSibling ); | |
} | |
/** | |
* Insert any number of Nodes or | |
* DOMStrings after $this. | |
* | |
* NOTE | |
* DOMStrings are inserted as | |
* equivalent Text nodes. | |
* | |
* @inheritDoc | |
*/ | |
public function before( ...$args /* DOMStrings and/or Nodes */ ) : void { | |
$parentNode = $this->_parentNode; | |
$prevSibling = $this->previousSibling(); | |
if ( $this->_parentNode === null ) { | |
/* | |
* If $this has no parent, | |
* then it is not actually | |
* part of a document, and | |
* according to DOM-LS, | |
* this method has no effect. | |
*/ | |
return; | |
} | |
// Find "viable prev sibling"; that is, prev one not in $args | |
while ( $prevSibling !== null && in_array( $prevSibling, $args, true ) ) { | |
$prevSibling = $prevSibling->previousSibling(); | |
} | |
// ok, parent and sibling are saved away since this node could itself | |
// appear in $args and we're about to move $args to a document fragment. | |
/* | |
* Turn the arguments into | |
* a DocumentFragment. | |
*/ | |
$frag = self::_fragment_from_arguments( $this->__node_document(), $args ); | |
$nextSibling = $prevSibling ? $prevSibling->getNextSibling() : $parentNode->firstChild(); | |
/* | |
* Insert the DocumentFragment | |
* at the determined location. | |
*/ | |
$parentNode->insertBefore( $frag, $nextSibling ); | |
} | |
/* | |
* Remove $this from its parent. | |
* @inheritDoc | |
*/ | |
public function remove() : void { | |
if ( $this->_parentNode === null ) { | |
/* | |
* If $this has no parent, | |
* according to DOM-LS, | |
* this method has no effect. | |
*/ | |
return; | |
} | |
$doc = $this->__node_document(); | |
if ( $doc ) { | |
/* | |
* Un-associate $this | |
* with its document, | |
* if it has one. | |
*/ | |
if ( $this->__is_rooted() ) { | |
$doc->__mutate_remove( $this ); | |
$doc->__uproot(); | |
} | |
} | |
/* | |
* Remove this node from its parents array of children | |
* and update the structure id for all ancestors | |
*/ | |
$this->_remove(); | |
/* Forget this node's parent */ | |
$this->_parentNode = null; | |
} | |
/** | |
* Remove this node w/o uprooting or sending mutation events | |
* This is like a 'soft remove' - it's used in whatwg stuff. | |
*/ | |
protected function _remove() { | |
if ( $this->_parentNode === null ) { | |
return; | |
} | |
$parent = $this->_parentNode; | |
if ( $parent->_childNodes !== null ) { | |
array_splice( $parent->_childNodes, $this->__sibling_index(), 1 ); | |
} elseif ( $parent->_firstChild === $this ) { | |
$parent->_firstChild = $this->getNextSibling(); | |
} | |
LinkedList::ll_remove( $this ); | |
} | |
/** | |
* Replace this node with the nodes or strings provided as arguments. | |
* @inheritDoc | |
*/ | |
public function replaceWith( ...$args /* Nodes or DOMStrings */ ) : void { | |
$parentNode = $this->getParentNode(); | |
$nextSibling = $this->getNextSibling(); | |
if ( $this->getParentNode() === null ) { | |
return; | |
} | |
/* | |
* Find "viable next sibling"; that is, next one | |
* not in $arguments | |
*/ | |
while ( $nextSibling !== null && in_array( $nextSibling, $args, true ) ) { | |
$nextSibling = $nextSibling->getNextSibling(); | |
} | |
/* | |
* ok, parent and sibling are saved away since this node | |
* could itself appear in $arguments and we're about to | |
* move $arguments to a document fragment. | |
*/ | |
$frag = self::_fragment_from_arguments( $this->__node_document(), $args ); | |
if ( $this->_parentNode === $parentNode ) { | |
$parentNode->replaceChild( $frag, $this ); | |
} else { | |
/* `this` was inserted into docFrag */ | |
$parentNode->insertBefore( $frag, $nextSibling ); | |
} | |
} | |
} |