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     * @param callable $shouldModifyCallback
17     * @param callable $modifyCallback
18     */
19    public function add( callable $shouldModifyCallback, callable $modifyCallback ): void {
20        $this->modifications[] = [ $shouldModifyCallback, $modifyCallback ];
21    }
22
23    /**
24     * Apply all modifications to a fragment.
25     *
26     * @param string $htmlFragment
27     * @param bool $html5format
28     * @return string
29     */
30    public function apply( string $htmlFragment, bool $html5format = true ): string {
31        if ( !count( $this->modifications ) ) {
32            return $htmlFragment;
33        }
34
35        return HtmlHelper::modifyElements(
36            $htmlFragment,
37            function ( SerializerNode $node ) {
38                foreach ( $this->modifications as [ $shouldModify, $modify ] ) {
39                    if ( $shouldModify( $node ) ) {
40                        return true;
41                    }
42                }
43                return false;
44            },
45            function ( SerializerNode $node ) {
46                $modified = null;
47                foreach ( $this->modifications as [ $shouldModify, $modify ] ) {
48                    if ( $shouldModify( $node ) ) {
49                        if ( !$modified ) {
50                            $modified = $modify( $node );
51                        } else {
52                            // Ideally we would support matching mulitple modifiers, but as a modifier
53                            // can return a string but has to be passed a SerizliazerNode, this is
54                            // not trivial.
55                            throw new LogicException( 'Node matches multiple modifiers.' );
56                        }
57                    }
58                }
59                return $modified ?? $node;
60            },
61            $html5format
62        );
63    }
64}