Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
79.17% covered (warning)
79.17%
19 / 24
50.00% covered (danger)
50.00%
2 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
MobileFormatter
79.17% covered (warning)
79.17%
19 / 24
50.00% covered (danger)
50.00%
2 / 4
10.90
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 applyTransforms
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 parseItemsToRemove
91.67% covered (success)
91.67%
11 / 12
0.00% covered (danger)
0.00%
0 / 1
5.01
 canApply
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2
3use HtmlFormatter\HtmlFormatter;
4use MediaWiki\Config\Config;
5use MediaWiki\Title\Title;
6use MobileFrontend\Transforms\IMobileTransform;
7use Wikimedia\Parsoid\Utils\DOMCompat;
8
9/**
10 * Converts HTML into a mobile-friendly version
11 */
12class MobileFormatter extends HtmlFormatter {
13    /**
14     * Class name for collapsible section wrappers
15     */
16    public const STYLE_COLLAPSIBLE_SECTION_CLASS = 'collapsible-block';
17
18    /**
19     * @var Title
20     */
21    protected $title;
22
23    /**
24     * @var Config
25     */
26    private $config;
27
28    /**
29     * @var MobileContext
30     */
31    private $context;
32
33    /**
34     * @param string $html Text to process
35     * @param Title $title Title to which $html belongs
36     * @param Config $config
37     * @param MobileContext $context
38     */
39    public function __construct(
40        $html, Title $title, Config $config, MobileContext $context
41    ) {
42        parent::__construct( $html );
43
44        $this->title = $title;
45        $this->context = $context;
46        $this->config = $config;
47    }
48
49    /**
50     * Performs various transformations to the content to make it appropriate for mobile devices.
51     * @param array<IMobileTransform> $transforms lit of transforms to be sequentually applied
52     *   to html DOM
53     */
54    public function applyTransforms( array $transforms ) {
55        // Apply all removals before continuing with transforms (see T185040 for example)
56        $this->filterContent();
57
58        $doc = $this->getDoc();
59        $body = DOMCompat::querySelector( $doc, 'body' );
60
61        foreach ( $transforms as $transform ) {
62            $transform->apply( $body );
63        }
64    }
65
66    /**
67     * @inheritDoc
68     */
69    protected function parseItemsToRemove(): array {
70        $removals = parent::parseItemsToRemove();
71
72        // Remove specified content in content namespaces
73        if ( in_array( $this->title->getNamespace(), $this->config->get( 'ContentNamespaces' ), true ) ) {
74            $mfRemovableClasses = $this->config->get( 'MFRemovableClasses' );
75            $removableClasses = $mfRemovableClasses['base'];
76            if ( $this->context->isBetaGroupMember() ) {
77                $removableClasses = array_merge( $removableClasses, $mfRemovableClasses['beta'] );
78            }
79
80            foreach ( $removableClasses as $itemToRemove ) {
81                $type = '';
82                $rawName = '';
83                if ( $this->parseSelector( $itemToRemove, $type, $rawName ) ) {
84                    $removals[$type][] = $rawName;
85                }
86            }
87        }
88
89        return $removals;
90    }
91
92    /**
93     * Check whether the MobileFormatter can be applied to the text of a page.
94     * @param string $text
95     * @param array $options with 'maxHeadings' and 'maxImages' keys that limit the MobileFormatter
96     *  to pages with less than or equal to that number of headings and images.
97     * @return bool
98     */
99    public static function canApply( $text, $options ) {
100        $headings = preg_match_all( '/<[hH][1-6]/', $text );
101        $imgs = preg_match_all( '/<img/', $text );
102        return $headings <= $options['maxHeadings'] && $imgs <= $options['maxImages'];
103    }
104}