@@ -230,8 +230,7 @@ private function validateUniqueColumnIndex(): void {
230230 * Validates that all data rows have data-row-id attributes when unique-column-index is not provided
231231 */
232232 private function validateDataRowIds (): bool {
233- $ xpath = new DOMXPath ( $ this ->dom );
234- $ dataRows = $ xpath ->query ( './/tr[not(th)] ' , $ this ->table );
233+ $ dataRows = $ this ->getDataRows ();
235234
236235 foreach ( $ dataRows as $ row ) {
237236 $ rowId = $ this ->extractDataRowId ( $ row );
@@ -258,7 +257,7 @@ private function extractDataRowId( DOMElement $row ): ?string {
258257
259258 // Check cells for data-row-id (using the last one found)
260259 // this allows us to handle the case where a user passes a data-row-id on more than one column
261- $ cells = $ row -> getElementsByTagName ( ' td ' );
260+ $ cells = $ this -> getRowCells ( $ row );
262261 $ lastRowId = null ;
263262
264263 foreach ( $ cells as $ cell ) {
@@ -341,13 +340,10 @@ private function addProgressHeader(): void {
341340 }
342341
343342 /**
344- * Iterates over all data rows (tr without th) and adds the checkbox cell to each.
343+ * Iterates over all data rows and adds the checkbox cell to each.
345344 */
346345 private function processDataRows (): void {
347- $ xpath = new DOMXPath ( $ this ->dom );
348- // this is fucked, but this should be better than just trying to get the tr element with
349- // ->getElementByTagName('tr') as that will return all tr elements, including the header ones
350- $ dataRows = $ xpath ->query ( './/tr[not(th)] ' , $ this ->table );
346+ $ dataRows = $ this ->getDataRows ();
351347 $ rowIndex = 0 ;
352348
353349 foreach ( $ dataRows as $ r ) {
@@ -465,9 +461,9 @@ private function getUniqueRowId( DOMElement $row, int $rowIndex ): string {
465461
466462 // Wasn't found, use the unique-column-index if it is set
467463 if ( $ this ->uniqueColumnIndex !== null ) {
468- $ tdElements = $ row -> getElementsByTagName ( ' td ' );
469- if ( $ tdElements -> length > $ this ->uniqueColumnIndex ) {
470- $ uniqueCell = $ tdElements -> item ( $ this ->uniqueColumnIndex ) ;
464+ $ rowCells = $ this -> getRowCells ( $ row );
465+ if ( count ( $ rowCells ) > $ this ->uniqueColumnIndex ) {
466+ $ uniqueCell = $ rowCells [ $ this ->uniqueColumnIndex ] ;
471467 if ( $ uniqueCell ) {
472468 $ rowIdContent = trim ( $ uniqueCell ->textContent );
473469 if ( !empty ( $ rowIdContent ) ) {
@@ -546,4 +542,33 @@ public function hasError(): bool {
546542 public function getErrorMessage (): ?string {
547543 return $ this ->errorMessage ;
548544 }
545+
546+ /**
547+ * Get the cell elements from a row including the headers
548+ * @param DOMElement $row
549+ * @return array
550+ */
551+ private function getRowCells ( DOMElement $ row ): array {
552+ $ cells = [];
553+
554+ foreach ( $ row ->childNodes as $ child ) {
555+ if (
556+ $ child instanceof DOMElement &&
557+ ( $ child ->tagName === 'th ' || $ child ->tagName === 'td ' )
558+ ) {
559+ $ cells [] = $ child ;
560+ }
561+ }
562+
563+ return $ cells ;
564+ }
565+
566+ /**
567+ * Returns all the rows which we consider to hold "data"
568+ * @return iterable
569+ */
570+ private function getDataRows (): iterable {
571+ $ xpath = new DOMXPath ( $ this ->dom );
572+ return $ xpath ->query ( './/tr[td] ' , $ this ->table );
573+ }
549574}
0 commit comments