Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
30 / 30
100.00% covered (success)
100.00%
11 / 11
CRAP
100.00% covered (success)
100.00%
1 / 1
Declaration
100.00% covered (success)
100.00%
30 / 30
100.00% covered (success)
100.00%
11 / 11
16
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
2
 __clone
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getPosition
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getName
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getValue
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getImportant
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setImportant
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 toTokenOrCVArray
100.00% covered (success)
100.00%
14 / 14
100.00% covered (success)
100.00%
1 / 1
5
 toTokenArray
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 toComponentValueArray
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 __toString
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
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\Objects;
10
11use InvalidArgumentException;
12use Wikimedia\CSS\Util;
13
14/**
15 * Represent a CSS declaration, eg. `margin: 10px 20px;`
16 */
17class Declaration implements DeclarationOrAtRule {
18
19    /** @var int Line in the input where this declaration starts */
20    protected $line = -1;
21
22    /** @var int Position in the input where this declaration starts */
23    protected $pos = -1;
24
25    /** @var string */
26    protected $name;
27
28    /** @var ComponentValueList */
29    protected $value;
30
31    /** @var bool */
32    protected $important = false;
33
34    /**
35     * @param Token $token Token starting the declaration
36     */
37    public function __construct( Token $token ) {
38        if ( $token->type() !== Token::T_IDENT ) {
39            throw new InvalidArgumentException(
40                "Declaration must begin with an ident token, got {$token->type()}"
41            );
42        }
43
44        [ $this->line, $this->pos ] = $token->getPosition();
45        $this->name = $token->value();
46        $this->value = new ComponentValueList();
47    }
48
49    public function __clone() {
50        $this->value = clone $this->value;
51    }
52
53    /**
54     * Get the position of this Declaration in the input stream
55     * @return array [ $line, $pos ]
56     */
57    public function getPosition() {
58        return [ $this->line, $this->pos ];
59    }
60
61    /**
62     * Return the declaration's name
63     * @return string
64     */
65    public function getName() {
66        return $this->name;
67    }
68
69    /**
70     * Return the declaration's value
71     * @return ComponentValueList
72     */
73    public function getValue() {
74        return $this->value;
75    }
76
77    /**
78     * Return the declaration's 'important' flag
79     * @return bool
80     */
81    public function getImportant() {
82        return $this->important;
83    }
84
85    /**
86     * Set the 'important' flag
87     * @param bool $flag
88     */
89    public function setImportant( $flag ) {
90        $this->important = (bool)$flag;
91    }
92
93    /**
94     * @param string $function Function to call, toTokenArray() or toComponentValueArray()
95     * @return Token[]|ComponentValue[]
96     */
97    private function toTokenOrCVArray( $function ) {
98        $ret = [];
99
100        $ret[] = new Token(
101            Token::T_IDENT,
102            [ 'value' => $this->name, 'position' => [ $this->line, $this->pos ] ]
103        );
104        $ret[] = $v = new Token( Token::T_COLON );
105        // Manually looping and appending turns out to be noticeably faster than array_merge.
106        foreach ( $this->value->$function() as $v ) {
107            $ret[] = $v;
108        }
109        if ( $this->important ) {
110            if ( !$v instanceof Token || $v->type() !== Token::T_WHITESPACE ) {
111                $ret[] = new Token( Token::T_WHITESPACE, [ 'significant' => false ] );
112            }
113            $ret[] = new Token( Token::T_DELIM, '!' );
114            $ret[] = new Token( Token::T_IDENT, 'important' );
115        }
116        return $ret;
117    }
118
119    /** @inheritDoc */
120    public function toTokenArray() {
121        return $this->toTokenOrCVArray( __FUNCTION__ );
122    }
123
124    /** @inheritDoc */
125    public function toComponentValueArray() {
126        return $this->toTokenOrCVArray( __FUNCTION__ );
127    }
128
129    public function __toString() {
130        return Util::stringify( $this );
131    }
132}