Code Coverage Lines Functions and Methods Classes and Traits Total 0.00% covered (danger) 0.00% 0 / 60 0.00% covered (danger) 0.00% 0 / 12 CRAP 0.00% covered (danger) 0.00% 0 / 1 DiffDOMUtils 0.00% covered (danger) 0.00% 0 / 60 0.00% covered (danger) 0.00% 0 / 12 1892 0.00% covered (danger) 0.00% 0 / 1 hasNChildren 0.00% covered (danger) 0.00% 0 / 7 0.00% covered (danger) 0.00% 0 / 1 30 isContentNode 0.00% covered (danger) 0.00% 0 / 3 0.00% covered (danger) 0.00% 0 / 1 12 firstNonSepChild 0.00% covered (danger) 0.00% 0 / 4 0.00% covered (danger) 0.00% 0 / 1 12 lastNonSepChild 0.00% covered (danger) 0.00% 0 / 4 0.00% covered (danger) 0.00% 0 / 1 12 previousNonSepSibling 0.00% covered (danger) 0.00% 0 / 4 0.00% covered (danger) 0.00% 0 / 1 12 nextNonSepSibling 0.00% covered (danger) 0.00% 0 / 4 0.00% covered (danger) 0.00% 0 / 1 12 numNonDeletedChildNodes 0.00% covered (danger) 0.00% 0 / 7 0.00% covered (danger) 0.00% 0 / 1 12 firstNonDeletedChild 0.00% covered (danger) 0.00% 0 / 4 0.00% covered (danger) 0.00% 0 / 1 12 lastNonDeletedChild 0.00% covered (danger) 0.00% 0 / 4 0.00% covered (danger) 0.00% 0 / 1 12 nextNonDeletedSibling 0.00% covered (danger) 0.00% 0 / 4 0.00% covered (danger) 0.00% 0 / 1 12 previousNonDeletedSibling 0.00% covered (danger) 0.00% 0 / 4 0.00% covered (danger) 0.00% 0 / 1 12 nodeEssentiallyEmpty 0.00% covered (danger) 0.00% 0 / 11 0.00% covered (danger) 0.00% 0 / 1 72
 1 count()`.  This walks the sibling list and so 20 * takes O(`nchildren`) time -- so `nchildren` is expected to be small 21 * (say: 0, 1, or 2). 22 * 23 * Skips all diff markers by default. 24 * @param Node \$node 25 * @param int \$nchildren 26 * @param bool \$countDiffMarkers 27 * @return bool 28 */ 29 public static function hasNChildren( 30 Node \$node, int \$nchildren, bool \$countDiffMarkers = false 31 ): bool { 32 for ( \$child = \$node->firstChild; \$child; \$child = \$child->nextSibling ) { 33 if ( !\$countDiffMarkers && DiffUtils::isDiffMarker( \$child ) ) { 34 continue; 35 } 36 if ( \$nchildren <= 0 ) { 37 return false; 38 } 39 \$nchildren -= 1; 40 } 41 return ( \$nchildren === 0 ); 42 } 43 44 /** 45 * Is a node a content node? 46 * 47 * @param ?Node \$node 48 * @return bool 49 */ 50 public static function isContentNode( ?Node \$node ): bool { 51 return !( \$node instanceof Comment ) && 52 !DOMUtils::isIEW( \$node ) && 53 !DiffUtils::isDiffMarker( \$node ); 54 } 55 56 /** 57 * Get the first child element or non-IEW text node, ignoring 58 * whitespace-only text nodes, comments, and deleted nodes. 59 * 60 * @param Node \$node 61 * @return Node|null 62 */ 63 public static function firstNonSepChild( Node \$node ): ?Node { 64 \$child = \$node->firstChild; 65 while ( \$child && !self::isContentNode( \$child ) ) { 66 \$child = \$child->nextSibling; 67 } 68 return \$child; 69 } 70 71 /** 72 * Get the last child element or non-IEW text node, ignoring 73 * whitespace-only text nodes, comments, and deleted nodes. 74 * 75 * @param Node \$node 76 * @return Node|null 77 */ 78 public static function lastNonSepChild( Node \$node ): ?Node { 79 \$child = \$node->lastChild; 80 while ( \$child && !self::isContentNode( \$child ) ) { 81 \$child = \$child->previousSibling; 82 } 83 return \$child; 84 } 85 86 /** 87 * Get the previous non separator sibling node. 88 * 89 * @param Node \$node 90 * @return Node|null 91 */ 92 public static function previousNonSepSibling( Node \$node ): ?Node { 93 \$prev = \$node->previousSibling; 94 while ( \$prev && !self::isContentNode( \$prev ) ) { 95 \$prev = \$prev->previousSibling; 96 } 97 return \$prev; 98 } 99 100 /** 101 * Get the next non separator sibling node. 102 * 103 * @param Node \$node 104 * @return Node|null 105 */ 106 public static function nextNonSepSibling( Node \$node ): ?Node { 107 \$next = \$node->nextSibling; 108 while ( \$next && !self::isContentNode( \$next ) ) { 109 \$next = \$next->nextSibling; 110 } 111 return \$next; 112 } 113 114 /** 115 * Return the numbler of non deleted child nodes. 116 * 117 * @param Node \$node 118 * @return int 119 */ 120 public static function numNonDeletedChildNodes( Node \$node ): int { 121 \$n = 0; 122 \$child = \$node->firstChild; 123 while ( \$child ) { 124 if ( !DiffUtils::isDiffMarker( \$child ) ) { // FIXME: This is ignoring both inserted/deleted 125 \$n++; 126 } 127 \$child = \$child->nextSibling; 128 } 129 return \$n; 130 } 131 132 /** 133 * Get the first non-deleted child of node. 134 * 135 * @param Node \$node 136 * @return Node|null 137 */ 138 public static function firstNonDeletedChild( Node \$node ): ?Node { 139 \$child = \$node->firstChild; 140 // FIXME: This is ignoring both inserted/deleted 141 while ( \$child && DiffUtils::isDiffMarker( \$child ) ) { 142 \$child = \$child->nextSibling; 143 } 144 return \$child; 145 } 146 147 /** 148 * Get the last non-deleted child of node. 149 * 150 * @param Node \$node 151 * @return Node|null 152 */ 153 public static function lastNonDeletedChild( Node \$node ): ?Node { 154 \$child = \$node->lastChild; 155 // FIXME: This is ignoring both inserted/deleted 156 while ( \$child && DiffUtils::isDiffMarker( \$child ) ) { 157 \$child = \$child->previousSibling; 158 } 159 return \$child; 160 } 161 162 /** 163 * Get the next non deleted sibling. 164 * 165 * @param Node \$node 166 * @return Node|null 167 */ 168 public static function nextNonDeletedSibling( Node \$node ): ?Node { 169 \$node = \$node->nextSibling; 170 while ( \$node && DiffUtils::isDiffMarker( \$node ) ) { // FIXME: This is ignoring both inserted/deleted 171 \$node = \$node->nextSibling; 172 } 173 return \$node; 174 } 175 176 /** 177 * Get the previous non deleted sibling. 178 * 179 * @param Node \$node 180 * @return Node|null 181 */ 182 public static function previousNonDeletedSibling( Node \$node ): ?Node { 183 \$node = \$node->previousSibling; 184 while ( \$node && DiffUtils::isDiffMarker( \$node ) ) { // FIXME: This is ignoring both inserted/deleted 185 \$node = \$node->previousSibling; 186 } 187 return \$node; 188 } 189 190 /** 191 * Does `node` contain nothing or just non-newline whitespace? 192 * `strict` adds the condition that all whitespace is forbidden. 193 * 194 * @param Node \$node 195 * @param bool \$strict 196 * @return bool 197 */ 198 public static function nodeEssentiallyEmpty( Node \$node, bool \$strict = false ): bool { 199 \$n = \$node->firstChild; 200 while ( \$n ) { 201 if ( \$n instanceof Element && !DiffUtils::isDiffMarker( \$n ) ) { 202 return false; 203 } elseif ( \$n instanceof Text && 204 ( \$strict || !preg_match( '/^[ \t]*\$/D', \$n->nodeValue ) ) 205 ) { 206 return false; 207 } elseif ( \$n instanceof Comment ) { 208 return false; 209 } 210 \$n = \$n->nextSibling; 211 } 212 return true; 213 } 214 215 }