Skip to content

Commit 94900e2

Browse files
committed
[TASK] Add and implement CSSElement interface
Also add tests to confirm that the supplanted types in the DocBlock actually implement the new interface. And correct a DocBlock type to also allow `string`, which is currently possible. cf. #1230
1 parent 4e107ac commit 94900e2

File tree

15 files changed

+129
-10
lines changed

15 files changed

+129
-10
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ Please also have a look at our
1010

1111
### Added
1212

13+
- Interface `CSSElement` (#1231)
1314
- Methods `getLineNumber` and `getColumnNumber` which return a nullable `int`
1415
for the following classes:
1516
`Comment`, `CSSList`, `SourceException`, `Charset`, `CSSNamespace`, `Import`,

README.md

+8-2
Original file line numberDiff line numberDiff line change
@@ -624,6 +624,9 @@ classDiagram
624624
625625
%% Start of the part originally generated from the PHP code using tasuku43/mermaid-class-diagram
626626
627+
class CSSElement {
628+
<<interface>>
629+
}
627630
class Renderable {
628631
<<interface>>
629632
}
@@ -721,9 +724,11 @@ classDiagram
721724
}
722725
723726
RuleSet <|-- DeclarationBlock: inheritance
727+
Renderable <|-- CSSElement: inheritance
724728
Renderable <|-- CSSListItem: inheritance
725729
Commentable <|-- CSSListItem: inheritance
726730
Positionable <|.. RuleSet: realization
731+
CSSElement <|.. RuleSet: realization
727732
CSSListItem <|.. RuleSet: realization
728733
RuleSet <|-- AtRuleSet: inheritance
729734
AtRule <|.. AtRuleSet: realization
@@ -736,7 +741,7 @@ classDiagram
736741
AtRule <|.. Import: realization
737742
Positionable <|.. CSSNamespace: realization
738743
AtRule <|.. CSSNamespace: realization
739-
Renderable <|.. Rule: realization
744+
CSSElement <|.. Rule: realization
740745
Positionable <|.. Rule: realization
741746
Commentable <|.. Rule: realization
742747
SourceException <|-- OutputException: inheritance
@@ -746,6 +751,7 @@ classDiagram
746751
SourceException <|-- UnexpectedTokenException: inheritance
747752
CSSList <|-- CSSBlockList: inheritance
748753
CSSBlockList <|-- Document: inheritance
754+
CSSElement <|.. CSSList: realization
749755
Positionable <|.. CSSList: realization
750756
CSSListItem <|.. CSSList: realization
751757
CSSList <|-- KeyFrame: inheritance
@@ -758,7 +764,7 @@ classDiagram
758764
Value <|-- ValueList: inheritance
759765
CSSFunction <|-- CalcFunction: inheritance
760766
ValueList <|-- LineName: inheritance
761-
Renderable <|.. Value: realization
767+
CSSElement <|.. Value: realization
762768
Positionable <|.. Value: realization
763769
PrimitiveValue <|-- Size: inheritance
764770
PrimitiveValue <|-- CSSString: inheritance

src/CSSElement.php

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Sabberworm\CSS;
6+
7+
/**
8+
* Represents any entity in the CSS that is encapsulated by a class.
9+
*
10+
* Its primary purpose is to provide a type for use with `Document::getAllValues()`
11+
* when a subset of values from a particular part of the document is required.
12+
*
13+
* Thus, elements which don't contain `Value`s (such as statement at-rules) don't need to implement this.
14+
*
15+
* It extends `Renderable` because every element is renderable.
16+
*/
17+
interface CSSElement extends Renderable {}

src/CSSList/CSSBlockList.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace Sabberworm\CSS\CSSList;
66

7+
use Sabberworm\CSS\CSSElement;
78
use Sabberworm\CSS\Property\Selector;
89
use Sabberworm\CSS\Rule\Rule;
910
use Sabberworm\CSS\RuleSet\DeclarationBlock;
@@ -75,7 +76,7 @@ public function getAllRuleSets(): array
7576
}
7677

7778
/**
78-
* @param CSSList|Rule|RuleSet|Value $element
79+
* @param CSSElement|string $element
7980
* @param list<Value> $result
8081
*/
8182
protected function allValues(

src/CSSList/CSSList.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace Sabberworm\CSS\CSSList;
66

77
use Sabberworm\CSS\Comment\CommentContainer;
8+
use Sabberworm\CSS\CSSElement;
89
use Sabberworm\CSS\OutputFormat;
910
use Sabberworm\CSS\Parsing\ParserState;
1011
use Sabberworm\CSS\Parsing\SourceException;
@@ -34,7 +35,7 @@
3435
* Note that `CSSListItem` extends both `Commentable` and `Renderable`,
3536
* so those interfaces must also be implemented by concrete subclasses.
3637
*/
37-
abstract class CSSList implements CSSListItem, Positionable
38+
abstract class CSSList implements CSSElement, CSSListItem, Positionable
3839
{
3940
use CommentContainer;
4041
use Position;

src/CSSList/Document.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace Sabberworm\CSS\CSSList;
66

7+
use Sabberworm\CSS\CSSElement;
78
use Sabberworm\CSS\OutputFormat;
89
use Sabberworm\CSS\Parsing\ParserState;
910
use Sabberworm\CSS\Parsing\SourceException;
@@ -33,7 +34,7 @@ public static function parse(ParserState $parserState): Document
3334
/**
3435
* Returns all `Value` objects found recursively in `Rule`s in the tree.
3536
*
36-
* @param CSSList|RuleSet|string $element
37+
* @param CSSElement|string $element
3738
* the `CSSList` or `RuleSet` to start the search from (defaults to the whole document).
3839
* If a string is given, it is used as rule name filter.
3940
* @param bool $searchInFunctionArguments whether to also return Value objects used as Function arguments.

src/Rule/Rule.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@
77
use Sabberworm\CSS\Comment\Comment;
88
use Sabberworm\CSS\Comment\Commentable;
99
use Sabberworm\CSS\Comment\CommentContainer;
10+
use Sabberworm\CSS\CSSElement;
1011
use Sabberworm\CSS\OutputFormat;
1112
use Sabberworm\CSS\Parsing\ParserState;
1213
use Sabberworm\CSS\Parsing\UnexpectedEOFException;
1314
use Sabberworm\CSS\Parsing\UnexpectedTokenException;
1415
use Sabberworm\CSS\Position\Position;
1516
use Sabberworm\CSS\Position\Positionable;
16-
use Sabberworm\CSS\Renderable;
1717
use Sabberworm\CSS\Value\RuleValueList;
1818
use Sabberworm\CSS\Value\Value;
1919

@@ -22,7 +22,7 @@
2222
*
2323
* In CSS, `Rule`s are expressed as follows: “key: value[0][0] value[0][1], value[1][0] value[1][1];”
2424
*/
25-
class Rule implements Commentable, Positionable, Renderable
25+
class Rule implements Commentable, CSSElement, Positionable
2626
{
2727
use CommentContainer;
2828
use Position;

src/RuleSet/RuleSet.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace Sabberworm\CSS\RuleSet;
66

77
use Sabberworm\CSS\Comment\CommentContainer;
8+
use Sabberworm\CSS\CSSElement;
89
use Sabberworm\CSS\CSSList\CSSListItem;
910
use Sabberworm\CSS\OutputFormat;
1011
use Sabberworm\CSS\Parsing\ParserState;
@@ -26,7 +27,7 @@
2627
* Note that `CSSListItem` extends both `Commentable` and `Renderable`,
2728
* so those interfaces must also be implemented by concrete subclasses.
2829
*/
29-
abstract class RuleSet implements CSSListItem, Positionable
30+
abstract class RuleSet implements CSSElement, CSSListItem, Positionable
3031
{
3132
use CommentContainer;
3233
use Position;

src/Value/Value.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,19 @@
44

55
namespace Sabberworm\CSS\Value;
66

7+
use Sabberworm\CSS\CSSElement;
78
use Sabberworm\CSS\Parsing\ParserState;
89
use Sabberworm\CSS\Parsing\SourceException;
910
use Sabberworm\CSS\Parsing\UnexpectedEOFException;
1011
use Sabberworm\CSS\Parsing\UnexpectedTokenException;
1112
use Sabberworm\CSS\Position\Position;
1213
use Sabberworm\CSS\Position\Positionable;
13-
use Sabberworm\CSS\Renderable;
1414

1515
/**
1616
* Abstract base class for specific classes of CSS values: `Size`, `Color`, `CSSString` and `URL`, and another
1717
* abstract subclass `ValueList`.
1818
*/
19-
abstract class Value implements Positionable, Renderable
19+
abstract class Value implements CSSElement, Positionable
2020
{
2121
use Position;
2222

tests/Unit/CSSList/CSSListTest.php

+11
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use PHPUnit\Framework\TestCase;
88
use Sabberworm\CSS\Comment\Commentable;
9+
use Sabberworm\CSS\CSSElement;
910
use Sabberworm\CSS\Renderable;
1011
use Sabberworm\CSS\RuleSet\DeclarationBlock;
1112
use Sabberworm\CSS\Tests\Unit\CSSList\Fixtures\ConcreteCSSList;
@@ -15,6 +16,16 @@
1516
*/
1617
final class CSSListTest extends TestCase
1718
{
19+
/**
20+
* @test
21+
*/
22+
public function implementsCSSElement(): void
23+
{
24+
$subject = new ConcreteCSSList();
25+
26+
self::assertInstanceOf(CSSElement::class, $subject);
27+
}
28+
1829
/**
1930
* @test
2031
*/

tests/Unit/Rule/RuleTest.php

+11
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace Sabberworm\CSS\Tests\Unit\Rule;
66

77
use PHPUnit\Framework\TestCase;
8+
use Sabberworm\CSS\CSSElement;
89
use Sabberworm\CSS\Parsing\ParserState;
910
use Sabberworm\CSS\Rule\Rule;
1011
use Sabberworm\CSS\Settings;
@@ -17,6 +18,16 @@
1718
*/
1819
final class RuleTest extends TestCase
1920
{
21+
/**
22+
* @test
23+
*/
24+
public function implementsCSSElement(): void
25+
{
26+
$subject = new Rule('beverage-container');
27+
28+
self::assertInstanceOf(CSSElement::class, $subject);
29+
}
30+
2031
/**
2132
* @return array<string, array{0: string, 1: list<class-string>}>
2233
*/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Sabberworm\CSS\Tests\Unit\RuleSet\Fixtures;
6+
7+
use Sabberworm\CSS\OutputFormat;
8+
use Sabberworm\CSS\RuleSet\RuleSet;
9+
10+
final class ConcreteRuleSet extends RuleSet
11+
{
12+
public function render(OutputFormat $outputFormat): string
13+
{
14+
throw new \BadMethodCallException('Nothing to see here :/', 1744067015);
15+
}
16+
}

tests/Unit/RuleSet/RuleSetTest.php

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Sabberworm\CSS\Tests\Unit\RuleSet;
6+
7+
use PHPUnit\Framework\TestCase;
8+
use Sabberworm\CSS\CSSElement;
9+
use Sabberworm\CSS\Tests\Unit\RuleSet\Fixtures\ConcreteRuleSet;
10+
11+
/**
12+
* @covers \Sabberworm\CSS\RuleSet\RuleSet
13+
*/
14+
final class RuleSetTest extends TestCase
15+
{
16+
/**
17+
* @test
18+
*/
19+
public function implementsCSSElement(): void
20+
{
21+
$subject = new ConcreteRuleSet();
22+
23+
self::assertInstanceOf(CSSElement::class, $subject);
24+
}
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Sabberworm\CSS\Tests\Unit\Value\Fixtures;
6+
7+
use Sabberworm\CSS\OutputFormat;
8+
use Sabberworm\CSS\Value\Value;
9+
10+
final class ConcreteValue extends Value
11+
{
12+
public function render(OutputFormat $outputFormat): string
13+
{
14+
throw new \BadMethodCallException('Nothing to see here :/', 1744067015);
15+
}
16+
}

tests/Unit/Value/ValueTest.php

+12
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@
55
namespace Sabberworm\CSS\Tests\Unit\Value;
66

77
use PHPUnit\Framework\TestCase;
8+
use Sabberworm\CSS\CSSElement;
89
use Sabberworm\CSS\OutputFormat;
910
use Sabberworm\CSS\Parsing\ParserState;
1011
use Sabberworm\CSS\Settings;
12+
use Sabberworm\CSS\Tests\Unit\Value\Fixtures\ConcreteValue;
1113
use Sabberworm\CSS\Value\CSSFunction;
1214
use Sabberworm\CSS\Value\Value;
1315

@@ -25,6 +27,16 @@ final class ValueTest extends TestCase
2527
*/
2628
private const DEFAULT_DELIMITERS = [',', ' ', '/'];
2729

30+
/**
31+
* @test
32+
*/
33+
public function implementsCSSElement(): void
34+
{
35+
$subject = new ConcreteValue();
36+
37+
self::assertInstanceOf(CSSElement::class, $subject);
38+
}
39+
2840
/**
2941
* @return array<string, array{0: string}>
3042
*/

0 commit comments

Comments
 (0)