Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
22 / 22
100.00% covered (success)
100.00%
5 / 5
CRAP
100.00% covered (success)
100.00%
1 / 1
MediaAtRuleSanitizer
100.00% covered (success)
100.00%
22 / 22
100.00% covered (success)
100.00%
5 / 5
11
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getRuleSanitizers
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setRuleSanitizers
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 handlesRule
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
2
 doSanitize
100.00% covered (success)
100.00%
17 / 17
100.00% covered (success)
100.00%
1 / 1
6
1<?php
2declare( strict_types = 1 );
3
4/**
5 * @file
6 * @license https://opensource.org/licenses/Apache-2.0 Apache-2.0
7 */
8
9namespace Wikimedia\CSS\Sanitizer;
10
11use Wikimedia\CSS\Grammar\Matcher;
12use Wikimedia\CSS\Objects\AtRule;
13use Wikimedia\CSS\Objects\CSSObject;
14use Wikimedia\CSS\Objects\Rule;
15use Wikimedia\CSS\Util;
16
17/**
18 * Sanitizes a CSS \@media rule
19 * @see https://www.w3.org/TR/2013/CR-css3-conditional-20130404/#at-media
20 */
21class MediaAtRuleSanitizer extends RuleSanitizer {
22
23    /** @var Matcher */
24    protected $mediaQueryListMatcher;
25
26    /** @var RuleSanitizer[] */
27    protected $ruleSanitizers = [];
28
29    /**
30     * @param Matcher $mediaQueryListMatcher Matcher for media query lists.
31     *  Probably from MatcherFactory::cssMediaQueryList().
32     */
33    public function __construct( Matcher $mediaQueryListMatcher ) {
34        $this->mediaQueryListMatcher = $mediaQueryListMatcher;
35    }
36
37    /**
38     * Access the list of rule sanitizers
39     * @return RuleSanitizer[]
40     */
41    public function getRuleSanitizers() {
42        return $this->ruleSanitizers;
43    }
44
45    /**
46     * Set the list of rule sanitizers
47     * @param RuleSanitizer[] $ruleSanitizers
48     */
49    public function setRuleSanitizers( array $ruleSanitizers ) {
50        Util::assertAllInstanceOf( $ruleSanitizers, RuleSanitizer::class, '$ruleSanitizers' );
51        $this->ruleSanitizers = $ruleSanitizers;
52    }
53
54    /** @inheritDoc */
55    public function handlesRule( Rule $rule ) {
56        return $rule instanceof AtRule && !strcasecmp( $rule->getName(), 'media' );
57    }
58
59    /** @inheritDoc */
60    protected function doSanitize( CSSObject $object ) {
61        if ( !$object instanceof AtRule || !$this->handlesRule( $object ) ) {
62            $this->sanitizationError( 'expected-at-rule', $object, [ 'media' ] );
63            return null;
64        }
65
66        if ( $object->getBlock() === null ) {
67            $this->sanitizationError( 'at-rule-block-required', $object, [ 'media' ] );
68            return null;
69        }
70
71        // Test the media query
72        $match = $this->mediaQueryListMatcher->matchAgainst(
73            $object->getPrelude(), [ 'mark-significance' => true ]
74        );
75        if ( !$match ) {
76            $cv = Util::findFirstNonWhitespace( $object->getPrelude() ) ?: $object->getPrelude();
77            $this->sanitizationError( 'invalid-media-query', $cv );
78            return null;
79        }
80
81        $ret = clone $object;
82        $this->fixPreludeWhitespace( $ret, false );
83        $this->sanitizeRuleBlock( $ret->getBlock(), $this->ruleSanitizers );
84
85        // @phan-suppress-next-line PhanTypeMismatchReturn generics weakness
86        return $ret;
87    }
88}