Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
2.04% covered (danger)
2.04%
1 / 49
33.33% covered (danger)
33.33%
1 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
RefGroup
2.04% covered (danger)
2.04%
1 / 49
33.33% covered (danger)
33.33%
1 / 3
85.14
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 createLinkback
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
6
 renderLine
0.00% covered (danger)
0.00%
0 / 39
0.00% covered (danger)
0.00%
0 / 1
42
1<?php
2declare( strict_types = 1 );
3
4namespace Cite\Parsoid;
5
6use Wikimedia\Parsoid\DOM\Document;
7use Wikimedia\Parsoid\DOM\Element;
8use Wikimedia\Parsoid\Ext\DOMUtils;
9use Wikimedia\Parsoid\Ext\ParsoidExtensionAPI;
10use Wikimedia\Parsoid\Utils\DOMCompat;
11
12/**
13 * Helper class used by `<references>` implementation.
14 * @license GPL-2.0-or-later
15 */
16class RefGroup {
17
18    public string $name;
19    /** @var RefGroupItem[] */
20    public array $refs = [];
21    /** @var array<string,RefGroupItem> Lookup map only for named refs */
22    public array $indexByName = [];
23
24    public function __construct( string $group = '' ) {
25        $this->name = $group;
26    }
27
28    /**
29     * Generate leading linkbacks
30     */
31    private static function createLinkback(
32        ParsoidExtensionAPI $extApi, string $target, ?string $group,
33        string $text, Document $ownerDoc
34    ): Element {
35        $a = $ownerDoc->createElement( 'a' );
36        $span = $ownerDoc->createElement( 'span' );
37        $a->setAttribute( 'href', $extApi->getPageUri() . '#' . $target );
38        $span->setAttribute( 'class', 'mw-linkback-text' );
39        if ( $group ) {
40            $a->setAttribute( 'data-mw-group', $group );
41        }
42        $span->appendChild( $ownerDoc->createTextNode( $text . ' ' ) );
43        $a->appendChild( $span );
44        return $a;
45    }
46
47    public function renderLine(
48        ParsoidExtensionAPI $extApi, Element $refsList, RefGroupItem $ref
49    ): void {
50        $ownerDoc = $refsList->ownerDocument;
51
52        // Generate the li and set ref content first, so the HTML gets parsed.
53        // We then append the rest of the ref nodes before the first node
54        $li = $ownerDoc->createElement( 'li' );
55        $refDir = $ref->dir;
56        $refTarget = $ref->target;
57        $refContentId = $ref->contentId;
58        $refGroup = $ref->group;
59        DOMUtils::addAttributes( $li, [
60                'about' => '#' . $refTarget,
61                'id' => $refTarget,
62                'class' => ( $refDir === 'rtl' || $refDir === 'ltr' ) ? 'mw-cite-dir-' . $refDir : null
63            ]
64        );
65        $reftextSpan = $ownerDoc->createElement( 'span' );
66        DOMUtils::addAttributes(
67            $reftextSpan,
68            [
69                'id' => 'mw-reference-text-' . $refTarget,
70                'class' => 'mw-reference-text',
71            ]
72        );
73        if ( $refContentId ) {
74            // `sup` is the wrapper created by Ref::sourceToDom()'s call to
75            // `extApi->extTagToDOM()`.  Only its contents are relevant.
76            $sup = $extApi->getContentDOM( $refContentId )->firstChild;
77            DOMUtils::migrateChildren( $sup, $reftextSpan );
78            '@phan-var Element $sup';  /** @var Element $sup */
79            DOMCompat::remove( $sup );
80            $extApi->clearContentDOM( $refContentId );
81        }
82        $li->appendChild( $reftextSpan );
83
84        if ( count( $ref->linkbacks ) === 1 ) {
85            $linkback = self::createLinkback( $extApi, $ref->id, $refGroup, "↑", $ownerDoc );
86            DOMUtils::addRel( $linkback, 'mw:referencedBy' );
87            $li->insertBefore( $linkback, $reftextSpan );
88        } else {
89            // 'mw:referencedBy' span wrapper
90            $span = $ownerDoc->createElement( 'span' );
91            DOMUtils::addRel( $span, 'mw:referencedBy' );
92            $li->insertBefore( $span, $reftextSpan );
93
94            foreach ( $ref->linkbacks as $i => $lb ) {
95                $span->appendChild(
96                    self::createLinkback( $extApi, $lb, $refGroup, (string)( $i + 1 ), $ownerDoc )
97                );
98            }
99        }
100
101        // Space before content node
102        $li->insertBefore( $ownerDoc->createTextNode( ' ' ), $reftextSpan );
103
104        // Add it to the ref list
105        $refsList->appendChild( $li );
106    }
107}