Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
33 / 33
100.00% covered (success)
100.00%
9 / 9
CRAP
100.00% covered (success)
100.00%
1 / 1
SimpleBlock
100.00% covered (success)
100.00%
33 / 33
100.00% covered (success)
100.00%
9 / 9
20
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
8 / 8
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
 newFromDelimiter
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 matchingDelimiter
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
5
 getStartTokenType
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getEndTokenType
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
 toTokenArray
100.00% covered (success)
100.00%
15 / 15
100.00% covered (success)
100.00%
1 / 1
7
 __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 simple block, eg. `{ color: red }`
16 */
17class SimpleBlock extends ComponentValue {
18
19    /** @var string */
20    protected $startTokenType;
21
22    /** @var string */
23    protected $endTokenType;
24
25    /** @var ComponentValueList */
26    protected $value;
27
28    /**
29     * @param Token $token Associated token
30     */
31    public function __construct( Token $token ) {
32        $this->endTokenType = static::matchingDelimiter( $token->type() );
33        if ( $this->endTokenType === null ) {
34            throw new InvalidArgumentException(
35                'A SimpleBlock is delimited by either {}, [], or ().'
36            );
37        }
38
39        [ $this->line, $this->pos ] = $token->getPosition();
40        $this->startTokenType = $token->type();
41        $this->value = new ComponentValueList();
42    }
43
44    public function __clone() {
45        $this->value = clone $this->value;
46    }
47
48    /**
49     * Create simple block by token type
50     * @param string $delimiter Token::T_LEFT_PAREN, Token::T_LEFT_BRACE, or
51     *  Token::T_LEFT_BRACKET
52     * @return SimpleBlock
53     */
54    public static function newFromDelimiter( $delimiter ) {
55        return new static( new Token( $delimiter ) );
56    }
57
58    /**
59     * Return the ending delimiter for a starting delimiter
60     * @param string $delim Token::T_* constant
61     * @return string|null Matching Token::T_* constant, if any
62     */
63    public static function matchingDelimiter( $delim ) {
64        switch ( $delim ) {
65            case Token::T_LEFT_BRACE:
66                return Token::T_RIGHT_BRACE;
67            case Token::T_LEFT_BRACKET:
68                return Token::T_RIGHT_BRACKET;
69            case Token::T_LEFT_PAREN:
70                return Token::T_RIGHT_PAREN;
71            default:
72                return null;
73        }
74    }
75
76    /**
77     * Get the start token type
78     * @return string
79     */
80    public function getStartTokenType() {
81        return $this->startTokenType;
82    }
83
84    /**
85     * Get the end token type
86     * @return string
87     */
88    public function getEndTokenType() {
89        return $this->endTokenType;
90    }
91
92    /**
93     * Return the block's value
94     * @return ComponentValueList
95     */
96    public function getValue() {
97        return $this->value;
98    }
99
100    /** @inheritDoc */
101    public function toTokenArray() {
102        $ret = [
103            new Token( $this->startTokenType, [ 'position' => [ $this->line, $this->pos ] ] ),
104        ];
105
106        // Manually looping and appending turns out to be noticeably faster than array_merge.
107        $tokens = $this->value->toTokenArray();
108        if ( $tokens && $this->startTokenType === Token::T_LEFT_BRACE ) {
109            if ( $tokens[0]->type() !== Token::T_WHITESPACE ) {
110                $ret[] = new Token( Token::T_WHITESPACE, [ 'significant' => false ] );
111            }
112            foreach ( $tokens as $v ) {
113                $ret[] = $v;
114            }
115            if ( $tokens[count( $tokens ) - 1]->type() !== Token::T_WHITESPACE ) {
116                $ret[] = new Token( Token::T_WHITESPACE, [ 'significant' => false ] );
117            }
118        } else {
119            foreach ( $tokens as $v ) {
120                $ret[] = $v;
121            }
122        }
123
124        $ret[] = new Token( $this->endTokenType );
125
126        return $ret;
127    }
128
129    public function __toString() {
130        return Util::stringify( $this );
131    }
132}