Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
22 / 22
100.00% covered (success)
100.00%
4 / 4
CRAP
100.00% covered (success)
100.00%
1 / 1
NamespaceAtRuleSanitizer
100.00% covered (success)
100.00%
22 / 22
100.00% covered (success)
100.00%
4 / 4
10
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
1
 getIndex
100.00% covered (success)
100.00%
1 / 1
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%
13 / 13
100.00% covered (success)
100.00%
1 / 1
6
1<?php
2/**
3 * @file
4 * @license https://opensource.org/licenses/Apache-2.0 Apache-2.0
5 */
6
7namespace Wikimedia\CSS\Sanitizer;
8
9use Wikimedia\CSS\Grammar\Alternative;
10use Wikimedia\CSS\Grammar\Juxtaposition;
11use Wikimedia\CSS\Grammar\Matcher;
12use Wikimedia\CSS\Grammar\MatcherFactory;
13use Wikimedia\CSS\Grammar\Quantifier;
14use Wikimedia\CSS\Objects\AtRule;
15use Wikimedia\CSS\Objects\CSSObject;
16use Wikimedia\CSS\Objects\Rule;
17use Wikimedia\CSS\Util;
18
19/**
20 * Sanitizes a CSS \@namespace rule
21 * @see https://www.w3.org/TR/2014/REC-css-namespaces-3-20140320/
22 */
23class NamespaceAtRuleSanitizer extends RuleSanitizer {
24
25    /** @var Matcher */
26    protected $matcher;
27
28    /**
29     * @param MatcherFactory $matcherFactory
30     */
31    public function __construct( MatcherFactory $matcherFactory ) {
32        $this->matcher = new Juxtaposition( [
33            Quantifier::optional( $matcherFactory->ident() ),
34            new Alternative( [
35                $matcherFactory->urlstring( 'namespace' ),
36                $matcherFactory->url( 'namespace' ),
37            ] ),
38        ] );
39    }
40
41    /** @inheritDoc */
42    public function getIndex() {
43        return -900;
44    }
45
46    /** @inheritDoc */
47    public function handlesRule( Rule $rule ) {
48        return $rule instanceof AtRule && !strcasecmp( $rule->getName(), 'namespace' );
49    }
50
51    /** @inheritDoc */
52    protected function doSanitize( CSSObject $object ) {
53        if ( !$object instanceof AtRule || !$this->handlesRule( $object ) ) {
54            $this->sanitizationError( 'expected-at-rule', $object, [ 'namespace' ] );
55            return null;
56        }
57
58        if ( $object->getBlock() !== null ) {
59            $this->sanitizationError( 'at-rule-block-not-allowed', $object->getBlock(), [ 'namespace' ] );
60            return null;
61        }
62        if ( !$this->matcher->matchAgainst( $object->getPrelude(), [ 'mark-significance' => true ] ) ) {
63            $cv = Util::findFirstNonWhitespace( $object->getPrelude() );
64            if ( $cv ) {
65                $this->sanitizationError( 'invalid-namespace-value', $cv );
66            } else {
67                $this->sanitizationError( 'missing-namespace-value', $object );
68            }
69            return null;
70        }
71        return $this->fixPreludeWhitespace( $object, true );
72    }
73}