Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 22
0.00% covered (danger)
0.00%
0 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
BatchModifyElements
0.00% covered (danger)
0.00%
0 / 22
0.00% covered (danger)
0.00%
0 / 2
72
0.00% covered (danger)
0.00%
0 / 1
 add
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 apply
0.00% covered (danger)
0.00%
0 / 21
0.00% covered (danger)
0.00%
0 / 1
56
1<?php
2
3namespace MediaWiki\Extension\DiscussionTools;
4
5use LogicException;
6use MediaWiki\Html\HtmlHelper;
7use Wikimedia\RemexHtml\Serializer\SerializerNode;
8
9class BatchModifyElements {
10    /** @var array<array{callable, callable}> */
11    private array $modifications = [];
12
13    /**
14     * Add a modification to the queue.
15     */
16    public function add( callable $shouldModifyCallback, callable $modifyCallback ): void {
17        $this->modifications[] = [ $shouldModifyCallback, $modifyCallback ];
18    }
19
20    /**
21     * Apply all modifications to a fragment.
22     */
23    public function apply( string $htmlFragment, bool $html5format = true ): string {
24        if ( !count( $this->modifications ) ) {
25            return $htmlFragment;
26        }
27
28        return HtmlHelper::modifyElements(
29            $htmlFragment,
30            function ( SerializerNode $node ) {
31                foreach ( $this->modifications as [ $shouldModify, $modify ] ) {
32                    if ( $shouldModify( $node ) ) {
33                        return true;
34                    }
35                }
36                return false;
37            },
38            function ( SerializerNode $node ) {
39                $modified = null;
40                foreach ( $this->modifications as [ $shouldModify, $modify ] ) {
41                    if ( $shouldModify( $node ) ) {
42                        if ( !$modified ) {
43                            $modified = $modify( $node );
44                        } else {
45                            // Ideally we would support matching mulitple modifiers, but as a modifier
46                            // can return a string but has to be passed a SerizliazerNode, this is
47                            // not trivial.
48                            throw new LogicException( 'Node matches multiple modifiers.' );
49                        }
50                    }
51                }
52                return $modified ?? $node;
53            },
54            $html5format
55        );
56    }
57}