Code Coverage
 
Classes and Traits
Functions and Methods
Lines
Total
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 43
PageBundle
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 5
462
0.00% covered (danger)
0.00%
0 / 43
 __construct
0.00% covered (danger)
0.00%
0 / 1
42
0.00% covered (danger)
0.00%
0 / 7
 toHtml
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 3
 validate
0.00% covered (danger)
0.00%
0 / 1
56
0.00% covered (danger)
0.00%
0 / 8
 responseData
0.00% covered (danger)
0.00%
0 / 1
6
0.00% covered (danger)
0.00%
0 / 12
 apply
0.00% covered (danger)
0.00%
0 / 1
30
0.00% covered (danger)
0.00%
0 / 13
<?php
declare( strict_types = 1 );
namespace Wikimedia\Parsoid\Core;
use Composer\Semver\Semver;
use Wikimedia\Parsoid\DOM\Document;
use Wikimedia\Parsoid\DOM\Element;
use Wikimedia\Parsoid\DOM\Node;
use Wikimedia\Parsoid\Utils\ContentUtils;
use Wikimedia\Parsoid\Utils\DOMCompat;
use Wikimedia\Parsoid\Utils\DOMDataUtils;
use Wikimedia\Parsoid\Utils\DOMUtils;
/**
 * PORT-FIXME: This is just a placeholder for data that was previously passed
 * to entrypoint in JavaScript.  Who will construct these objects and whether
 * this is the correct interface is yet to be determined.
 */
class PageBundle {
    /** @var string */
    public $html;
    /** @var ?array */
    public $parsoid;
    /** @var ?array */
    public $mw;
    /** @var ?string */
    public $version;
    /** @var ?array */
    public $headers;
    /** @var string|null */
    public $contentmodel;
    /**
     * @param string $html
     * @param ?array $parsoid
     * @param ?array $mw
     * @param ?string $version
     * @param ?array $headers
     * @param ?string $contentmodel
     */
    public function __construct(
        string $html, ?array $parsoid = null, ?array $mw = null,
        ?string $version = null, ?array $headers = null,
        ?string $contentmodel = null
    ) {
        $this->html = $html;
        $this->parsoid = $parsoid;
        $this->mw = $mw;
        $this->version = $version;
        $this->headers = $headers;
        $this->contentmodel = $contentmodel;
    }
    public function toHtml(): string {
        $doc = DOMUtils::parseHTML( $this->html );
        self::apply( $doc, $this );
        return ContentUtils::toXML( $doc );
    }
    /**
     * Check if this pagebundle is valid.
     * @param string $contentVersion Document content version to validate against.
     * @param ?string &$errorMessage Error message will be returned here.
     * @return bool
     */
    public function validate(
        string $contentVersion, ?string &$errorMessage = null
    ) {
        if ( !$this->parsoid || !isset( $this->parsoid['ids'] ) ) {
            $errorMessage = 'Invalid data-parsoid was provided.';
            return false;
        } elseif ( Semver::satisfies( $contentVersion, '^999.0.0' )
            && ( !$this->mw || !isset( $this->mw['ids'] ) )
        ) {
            $errorMessage = 'Invalid data-mw was provided.';
            return false;
        }
        return true;
    }
    /**
     * @return array
     */
    public function responseData() {
        $responseData = [
            'contentmodel' => $this->contentmodel ?? '',
            'html' => [
                'headers' => array_merge( [
                    'content-type' => 'text/html; charset=utf-8; '
                        . 'profile="https://www.mediawiki.org/wiki/Specs/HTML/'
                        . $this->version . '"',
                ], $this->headers ?? [] ),
                'body' => $this->html,
            ],
            'data-parsoid' => [
                'headers' => [
                    'content-type' => 'application/json; charset=utf-8; '
                        . 'profile="https://www.mediawiki.org/wiki/Specs/data-parsoid/'
                        . $this->version . '"',
                ],
                'body' => $this->parsoid,
            ],
        ];
        if ( Semver::satisfies( $this->version, '^999.0.0' ) ) {
            $responseData['data-mw'] = [
                'headers' => [
                    'content-type' => 'application/json; charset=utf-8; ' .
                        'profile="https://www.mediawiki.org/wiki/Specs/data-mw/' .
                        $this->version . '"',
                ],
                'body' => $this->mw,
            ];
        }
        return $responseData;
    }
    /**
     * Applies the `data-*` attributes JSON structure to the document.
     * Leaves `id` attributes behind -- they are used by citation code to
     * extract `<ref>` body from the DOM.
     *
     * @param Document $doc doc
     * @param PageBundle $pb page bundle
     */
    public static function apply( Document $doc, PageBundle $pb ): void {
        DOMUtils::visitDOM(
            DOMCompat::getBody( $doc ),
            static function ( Node $node ) use ( &$pb ): void {
                if ( $node instanceof Element ) {
                    $id = $node->getAttribute( 'id' ) ?? '';
                    if ( isset( $pb->parsoid['ids'][$id] ) ) {
                        DOMDataUtils::setJSONAttribute(
                            $node, 'data-parsoid', $pb->parsoid['ids'][$id]
                        );
                    }
                    if ( isset( $pb->mw['ids'][$id] ) ) {
                        // Only apply if it isn't already set.  This means
                        // earlier applications of the pagebundle have higher
                        // precedence, inline data being the highest.
                        if ( !$node->hasAttribute( 'data-mw' ) ) {
                            DOMDataUtils::setJSONAttribute(
                                $node, 'data-mw', $pb->mw['ids'][$id]
                            );
                        }
                    }
                }
            }
        );
    }
}