Code Coverage
 
Classes and Traits
Functions and Methods
Lines
Total
0.00% covered (danger)
0.00%
0 / 1
84.21% covered (warning)
84.21%
16 / 19
CRAP
89.47% covered (warning)
89.47%
68 / 76
Parsoid\Config\Api\PageConfig
0.00% covered (danger)
0.00%
0 / 1
84.21% covered (warning)
84.21%
16 / 19
39.68
89.47% covered (warning)
89.47%
68 / 76
 __construct
0.00% covered (danger)
0.00%
0 / 1
6.92
70.59% covered (warning)
70.59%
12 / 17
 mockPageContent
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
8 / 8
 loadData
0.00% covered (danger)
0.00%
0 / 1
5.01
93.75% covered (success)
93.75%
15 / 16
 getContentModel
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
2 / 2
 hasLintableContentModel
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
3 / 3
 getTitle
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
2 / 2
 getNs
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
2 / 2
 getPageId
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
2 / 2
 getPageLanguage
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
2 / 2
 getPageLanguageDir
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
2 / 2
 getRevisionId
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
2 / 2
 getParentRevisionId
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
2 / 2
 getRevisionTimestamp
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
2 / 2
 getRevisionUser
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
2 / 2
 getRevisionUserId
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
2 / 2
 getRevisionSha1
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
2 / 2
 getRevisionSize
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
2 / 2
 getRevisionContent
100.00% covered (success)
100.00%
1 / 1
3
100.00% covered (success)
100.00%
4 / 4
 fromSettings
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 2
<?php
declare( strict_types = 1 );
namespace Parsoid\Config\Api;
use Parsoid\Config\PageConfig as IPageConfig;
use Parsoid\Config\PageContent;
use Parsoid\Tests\MockPageContent;
use Wikimedia\Assert\Assert;
/**
 * PageConfig via MediaWiki's Action API
 *
 * Note this is intended for testing, not performance.
 */
class PageConfig extends IPageConfig {
    /** @var ApiHelper */
    private $api;
    /** @var string */
    private $title;
    /** @var string|null */
    private $revid;
    /** @phan-var array<string,mixed>|null */
    private $page;
    /** @phan-var array<string,mixed>|null */
    private $rev;
    /** @var PageContent|null */
    private $content;
    /** @var string|null */
    private $pagelanguage;
    /** @var string|null */
    private $pagelanguageDir;
    /**
     * @param ApiHelper|null $api (only needed if $opts doesn't provide page info)
     * @param array $opts
     */
    public function __construct( ?ApiHelper $api, array $opts ) {
        $this->api = $api;
        if ( !isset( $opts['title'] ) ) {
            throw new \InvalidArgumentException( '$opts[\'title\'] must be set' );
        }
        $this->title = $opts['title'];
        $this->revid = $opts['revid'] ?? null;
        $this->pagelanguage = $opts['pageLanguage'] ?? null;
        $this->pagelanguageDir = $opts['pageLanguageDir'] ?? null;
        // This option is primarily used to mock the page content.
        if ( isset( $opts['pageContent'] ) && empty( $opts['loadData'] ) ) {
            $this->mockPageContent( $opts );
        } else {
            Assert::invariant( $api !== null, 'Cannot load page info without an API' );
            # Lazily load later
            $this->page = null;
            $this->rev = null;
            if ( isset( $opts['pageContent'] ) ) {
                $this->loadData();
                $this->rev = [
                    'slots' => [ 'main' => $opts['pageContent'] ],
                ];
            }
        }
    }
    private function mockPageContent( array $opts ) {
        $this->page = [
            'title' => $this->title,
            'ns' => $opts['pagens'] ?? 0,
            'pageid' => -1,
            'pagelanguage' => $opts['pageLanguage'] ?? 'en',
            'pagelanguagedir' => $opts['pageLanguageDir'] ?? 'ltr',
        ];
        $this->rev = [
            'slots' => [ 'main' => $opts['pageContent'] ],
        ];
    }
    private function loadData() {
        if ( $this->page !== null ) {
            return;
        }
        $params = [
            'action' => 'query',
            'prop' => 'info|revisions',
            'rvprop' => 'ids|timestamp|user|userid|sha1|size|content',
            'rvslots' => '*',
        ];
        if ( !empty( $this->revid ) ) {
            $params['revids'] = $this->revid;
        } else {
            $params['titles'] = $this->title;
            $params['rvlimit'] = 1;
        }
        $this->page = $this->api->makeRequest( $params )['query']['pages'][0];
        $this->rev = $this->page['revisions'][0] ?? [];
        unset( $this->page['revisions'] );
        if ( isset( $this->rev['timestamp'] ) ) {
            $this->rev['timestamp'] = preg_replace( '/\D/', '', $this->rev['timestamp'] );
        }
        // Well, we tried but the page probably doesn't exist
        if ( !$this->rev ) {
            $this->mockPageContent( [
                'pageContent' => '',  // FIXME: T234549
            ] );
        }
    }
    /** @inheritDoc */
    public function getContentModel(): string {
        $this->loadData();
        return $this->rev['slots']['main']['contentmodel'] ?? 'wikitext';
    }
    public function hasLintableContentModel(): bool {
        $contentmodel = $this->getContentModel();
        return $contentmodel === 'wikitext' ||
            $contentmodel === 'proofread-page';
    }
    /** @inheritDoc */
    public function getTitle(): string {
        $this->loadData();
        return $this->page['title']; // normalized
    }
    /** @inheritDoc */
    public function getNs(): int {
        $this->loadData();
        return $this->page['ns'];
    }
    /** @inheritDoc */
    public function getPageId(): int {
        $this->loadData();
        return $this->page['pageid'] ?? 0;
    }
    /** @inheritDoc */
    public function getPageLanguage(): string {
        $this->loadData();
        return $this->pagelanguage ?? $this->page['pagelanguage'];
    }
    /** @inheritDoc */
    public function getPageLanguageDir(): string {
        $this->loadData();
        return $this->pagelanguageDir ?? $this->page['pagelanguagedir'];
    }
    /** @inheritDoc */
    public function getRevisionId(): ?int {
        $this->loadData();
        return $this->rev['revid'] ?? null;
    }
    /** @inheritDoc */
    public function getParentRevisionId(): ?int {
        $this->loadData();
        return $this->rev['parentid'] ?? null;
    }
    /** @inheritDoc */
    public function getRevisionTimestamp(): ?string {
        $this->loadData();
        return $this->rev['timestamp'] ?? null;
    }
    /** @inheritDoc */
    public function getRevisionUser(): ?string {
        $this->loadData();
        return $this->rev['user'] ?? null;
    }
    /** @inheritDoc */
    public function getRevisionUserId(): ?int {
        $this->loadData();
        return $this->rev['userid'] ?? null;
    }
    /** @inheritDoc */
    public function getRevisionSha1(): ?string {
        $this->loadData();
        return $this->rev['sha1'] ?? null;
    }
    /** @inheritDoc */
    public function getRevisionSize(): ?int {
        $this->loadData();
        return $this->rev['size'] ?? null;
    }
    /** @inheritDoc */
    public function getRevisionContent(): ?PageContent {
        $this->loadData();
        if ( !$this->content ) {
            $this->content = new MockPageContent( $this->rev['slots'] );
        }
        return $this->content;
    }
    /**
     * @param array $parsoidSettings
     * @param array $opts
     * @return PageConfig
     */
    public static function fromSettings(
        array $parsoidSettings, array $opts
    ): PageConfig {
        $api = ApiHelper::fromSettings( $parsoidSettings );
        return new PageConfig( $api, $opts );
    }
}