111 * |
136 * |
112 * @param string $line HTML-escape the value. |
137 * @param string $line HTML-escape the value. |
113 * @return string |
138 * @return string |
114 */ |
139 */ |
115 public function addedLine( $line ) { |
140 public function addedLine( $line ) { |
116 return "<td class='diff-addedline'><span aria-hidden='true' class='dashicons dashicons-plus'></span><span class='screen-reader-text'>" . __( 'Added:' ) . " </span>{$line}</td>"; |
141 return "<td class='diff-addedline'><span aria-hidden='true' class='dashicons dashicons-plus'></span><span class='screen-reader-text'>" . |
117 |
142 /* translators: Hidden accessibility text. */ |
|
143 __( 'Added:' ) . |
|
144 " </span>{$line}</td>"; |
118 } |
145 } |
119 |
146 |
120 /** |
147 /** |
121 * @ignore |
148 * @ignore |
122 * |
149 * |
123 * @param string $line HTML-escape the value. |
150 * @param string $line HTML-escape the value. |
124 * @return string |
151 * @return string |
125 */ |
152 */ |
126 public function deletedLine( $line ) { |
153 public function deletedLine( $line ) { |
127 return "<td class='diff-deletedline'><span aria-hidden='true' class='dashicons dashicons-minus'></span><span class='screen-reader-text'>" . __( 'Deleted:' ) . " </span>{$line}</td>"; |
154 return "<td class='diff-deletedline'><span aria-hidden='true' class='dashicons dashicons-minus'></span><span class='screen-reader-text'>" . |
|
155 /* translators: Hidden accessibility text. */ |
|
156 __( 'Deleted:' ) . |
|
157 " </span>{$line}</td>"; |
128 } |
158 } |
129 |
159 |
130 /** |
160 /** |
131 * @ignore |
161 * @ignore |
132 * |
162 * |
133 * @param string $line HTML-escape the value. |
163 * @param string $line HTML-escape the value. |
134 * @return string |
164 * @return string |
135 */ |
165 */ |
136 public function contextLine( $line ) { |
166 public function contextLine( $line ) { |
137 return "<td class='diff-context'><span class='screen-reader-text'>" . __( 'Unchanged:' ) . " </span>{$line}</td>"; |
167 return "<td class='diff-context'><span class='screen-reader-text'>" . |
|
168 /* translators: Hidden accessibility text. */ |
|
169 __( 'Unchanged:' ) . |
|
170 " </span>{$line}</td>"; |
138 } |
171 } |
139 |
172 |
140 /** |
173 /** |
141 * @ignore |
174 * @ignore |
142 * |
175 * |
266 |
299 |
267 // Compute word diffs for each matched pair using the inline diff. |
300 // Compute word diffs for each matched pair using the inline diff. |
268 foreach ( $orig_matches as $o => $f ) { |
301 foreach ( $orig_matches as $o => $f ) { |
269 if ( is_numeric( $o ) && is_numeric( $f ) ) { |
302 if ( is_numeric( $o ) && is_numeric( $f ) ) { |
270 $text_diff = new Text_Diff( 'auto', array( array( $orig[ $o ] ), array( $final[ $f ] ) ) ); |
303 $text_diff = new Text_Diff( 'auto', array( array( $orig[ $o ] ), array( $final[ $f ] ) ) ); |
271 $renderer = new $this->inline_diff_renderer; |
304 $renderer = new $this->inline_diff_renderer(); |
272 $diff = $renderer->render( $text_diff ); |
305 $diff = $renderer->render( $text_diff ); |
273 |
306 |
274 // If they're too different, don't include any <ins> or <del>'s. |
307 // If they're too different, don't include any <ins> or <del>'s. |
275 if ( preg_match_all( '!(<ins>.*?</ins>|<del>.*?</del>)!', $diff, $diff_matches ) ) { |
308 if ( preg_match_all( '!(<ins>.*?</ins>|<del>.*?</del>)!', $diff, $diff_matches ) ) { |
276 // Length of all text between <ins> or <del>. |
309 // Length of all text between <ins> or <del>. |
277 $stripped_matches = strlen( strip_tags( implode( ' ', $diff_matches[0] ) ) ); |
310 $stripped_matches = strlen( strip_tags( implode( ' ', $diff_matches[0] ) ) ); |
278 // Since we count length of text between <ins> or <del> (instead of picking just one), |
311 /* |
279 // we double the length of chars not in those tags. |
312 * Since we count length of text between <ins> or <del> (instead of picking just one), |
|
313 * we double the length of chars not in those tags. |
|
314 */ |
280 $stripped_diff = strlen( strip_tags( $diff ) ) * 2 - $stripped_matches; |
315 $stripped_diff = strlen( strip_tags( $diff ) ) * 2 - $stripped_matches; |
281 $diff_ratio = $stripped_matches / $stripped_diff; |
316 $diff_ratio = $stripped_matches / $stripped_diff; |
282 if ( $diff_ratio > $this->_diff_threshold ) { |
317 if ( $diff_ratio > $this->_diff_threshold ) { |
283 continue; // Too different. Don't save diffs. |
318 continue; // Too different. Don't save diffs. |
284 } |
319 } |
355 * blanks to keep matches aligned with side-by-side diff |
390 * blanks to keep matches aligned with side-by-side diff |
356 * of `$orig`. A value >= 0 corresponds to index of `$final`. |
391 * of `$orig`. A value >= 0 corresponds to index of `$final`. |
357 * Value < 0 indicates a blank row. |
392 * Value < 0 indicates a blank row. |
358 * } |
393 * } |
359 */ |
394 */ |
360 public function interleave_changed_lines( $orig, $final ) { |
395 public function interleave_changed_lines( $orig, $final ) { // phpcs:ignore Universal.NamingConventions.NoReservedKeywordParameterNames.finalFound |
361 |
396 |
362 // Contains all pairwise string comparisons. Keys are such that this need only be a one dimensional array. |
397 // Contains all pairwise string comparisons. Keys are such that this need only be a one dimensional array. |
363 $matches = array(); |
398 $matches = array(); |
364 foreach ( array_keys( $orig ) as $o ) { |
399 foreach ( array_keys( $orig ) as $o ) { |
365 foreach ( array_keys( $final ) as $f ) { |
400 foreach ( array_keys( $final ) as $f ) { |
404 // Stores rows and blanks for each column. |
439 // Stores rows and blanks for each column. |
405 $orig_rows = array_keys( $orig_matches ); |
440 $orig_rows = array_keys( $orig_matches ); |
406 $orig_rows_copy = $orig_rows; |
441 $orig_rows_copy = $orig_rows; |
407 $final_rows = array_keys( $final_matches ); |
442 $final_rows = array_keys( $final_matches ); |
408 |
443 |
409 // Interleaves rows with blanks to keep matches aligned. |
444 /* |
410 // We may end up with some extraneous blank rows, but we'll just ignore them later. |
445 * Interleaves rows with blanks to keep matches aligned. |
|
446 * We may end up with some extraneous blank rows, but we'll just ignore them later. |
|
447 */ |
411 foreach ( $orig_rows_copy as $orig_row ) { |
448 foreach ( $orig_rows_copy as $orig_row ) { |
412 $final_pos = array_search( $orig_matches[ $orig_row ], $final_rows, true ); |
449 $final_pos = array_search( $orig_matches[ $orig_row ], $final_rows, true ); |
413 $orig_pos = (int) array_search( $orig_row, $orig_rows, true ); |
450 $orig_pos = (int) array_search( $orig_row, $orig_rows, true ); |
414 |
451 |
415 if ( false === $final_pos ) { // This orig is paired with a blank final. |
452 if ( false === $final_pos ) { // This orig is paired with a blank final. |
495 |
532 |
496 /** |
533 /** |
497 * Make private properties readable for backward compatibility. |
534 * Make private properties readable for backward compatibility. |
498 * |
535 * |
499 * @since 4.0.0 |
536 * @since 4.0.0 |
|
537 * @since 6.4.0 Getting a dynamic property is deprecated. |
500 * |
538 * |
501 * @param string $name Property to get. |
539 * @param string $name Property to get. |
502 * @return mixed Property. |
540 * @return mixed A declared property's value, else null. |
503 */ |
541 */ |
504 public function __get( $name ) { |
542 public function __get( $name ) { |
505 if ( in_array( $name, $this->compat_fields, true ) ) { |
543 if ( in_array( $name, $this->compat_fields, true ) ) { |
506 return $this->$name; |
544 return $this->$name; |
507 } |
545 } |
|
546 |
|
547 wp_trigger_error( |
|
548 __METHOD__, |
|
549 "The property `{$name}` is not declared. Getting a dynamic property is " . |
|
550 'deprecated since version 6.4.0! Instead, declare the property on the class.', |
|
551 E_USER_DEPRECATED |
|
552 ); |
|
553 return null; |
508 } |
554 } |
509 |
555 |
510 /** |
556 /** |
511 * Make private properties settable for backward compatibility. |
557 * Make private properties settable for backward compatibility. |
512 * |
558 * |
513 * @since 4.0.0 |
559 * @since 4.0.0 |
|
560 * @since 6.4.0 Setting a dynamic property is deprecated. |
514 * |
561 * |
515 * @param string $name Property to check if set. |
562 * @param string $name Property to check if set. |
516 * @param mixed $value Property value. |
563 * @param mixed $value Property value. |
517 * @return mixed Newly-set property. |
|
518 */ |
564 */ |
519 public function __set( $name, $value ) { |
565 public function __set( $name, $value ) { |
520 if ( in_array( $name, $this->compat_fields, true ) ) { |
566 if ( in_array( $name, $this->compat_fields, true ) ) { |
521 return $this->$name = $value; |
567 $this->$name = $value; |
522 } |
568 return; |
|
569 } |
|
570 |
|
571 wp_trigger_error( |
|
572 __METHOD__, |
|
573 "The property `{$name}` is not declared. Setting a dynamic property is " . |
|
574 'deprecated since version 6.4.0! Instead, declare the property on the class.', |
|
575 E_USER_DEPRECATED |
|
576 ); |
523 } |
577 } |
524 |
578 |
525 /** |
579 /** |
526 * Make private properties checkable for backward compatibility. |
580 * Make private properties checkable for backward compatibility. |
527 * |
581 * |
528 * @since 4.0.0 |
582 * @since 4.0.0 |
|
583 * @since 6.4.0 Checking a dynamic property is deprecated. |
529 * |
584 * |
530 * @param string $name Property to check if set. |
585 * @param string $name Property to check if set. |
531 * @return bool Whether the property is set. |
586 * @return bool Whether the property is set. |
532 */ |
587 */ |
533 public function __isset( $name ) { |
588 public function __isset( $name ) { |
534 if ( in_array( $name, $this->compat_fields, true ) ) { |
589 if ( in_array( $name, $this->compat_fields, true ) ) { |
535 return isset( $this->$name ); |
590 return isset( $this->$name ); |
536 } |
591 } |
|
592 |
|
593 wp_trigger_error( |
|
594 __METHOD__, |
|
595 "The property `{$name}` is not declared. Checking `isset()` on a dynamic property " . |
|
596 'is deprecated since version 6.4.0! Instead, declare the property on the class.', |
|
597 E_USER_DEPRECATED |
|
598 ); |
|
599 return false; |
537 } |
600 } |
538 |
601 |
539 /** |
602 /** |
540 * Make private properties un-settable for backward compatibility. |
603 * Make private properties un-settable for backward compatibility. |
541 * |
604 * |
542 * @since 4.0.0 |
605 * @since 4.0.0 |
|
606 * @since 6.4.0 Unsetting a dynamic property is deprecated. |
543 * |
607 * |
544 * @param string $name Property to unset. |
608 * @param string $name Property to unset. |
545 */ |
609 */ |
546 public function __unset( $name ) { |
610 public function __unset( $name ) { |
547 if ( in_array( $name, $this->compat_fields, true ) ) { |
611 if ( in_array( $name, $this->compat_fields, true ) ) { |
548 unset( $this->$name ); |
612 unset( $this->$name ); |
549 } |
613 return; |
|
614 } |
|
615 |
|
616 wp_trigger_error( |
|
617 __METHOD__, |
|
618 "A property `{$name}` is not declared. Unsetting a dynamic property is " . |
|
619 'deprecated since version 6.4.0! Instead, declare the property on the class.', |
|
620 E_USER_DEPRECATED |
|
621 ); |
550 } |
622 } |
551 } |
623 } |