Skip to content

Commit 8b7a2b8

Browse files
committed
[TASK] Deconflate getAllValues() parameters
This is the backport of #1231, #1240 and #1241. cf. #1230
1 parent e100b80 commit 8b7a2b8

File tree

14 files changed

+432
-8
lines changed

14 files changed

+432
-8
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ This project adheres to [Semantic Versioning](https://semver.org/).
77

88
### Added
99

10+
- Add Interface `CSSElement` (#1231)
1011
- Methods `getLineNumber` and `getColumnNumber` which return a nullable `int`
1112
for the following classes:
1213
`Comment`, `CSSList`, `SourceException`, `Charset`, `CSSNamespace`, `Import`,

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
@@ -2,6 +2,7 @@
22

33
namespace Sabberworm\CSS\CSSList;
44

5+
use Sabberworm\CSS\CSSElement;
56
use Sabberworm\CSS\Property\Selector;
67
use Sabberworm\CSS\Rule\Rule;
78
use Sabberworm\CSS\RuleSet\DeclarationBlock;
@@ -59,7 +60,7 @@ protected function allRuleSets(array &$aResult)
5960
}
6061

6162
/**
62-
* @param CSSList|Rule|RuleSet|Value $oElement
63+
* @param CSSElement|string $oElement
6364
* @param array<int, Value> $aResult
6465
* @param string|null $sSearchString
6566
* @param bool $bSearchInFunctionArguments

src/CSSList/CSSList.php

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

55
use Sabberworm\CSS\Comment\Comment;
66
use Sabberworm\CSS\Comment\Commentable;
7+
use Sabberworm\CSS\CSSElement;
78
use Sabberworm\CSS\OutputFormat;
89
use Sabberworm\CSS\Parsing\ParserState;
910
use Sabberworm\CSS\Parsing\SourceException;
@@ -31,7 +32,7 @@
3132
*
3233
* It can also contain `Import` and `Charset` objects stemming from at-rules.
3334
*/
34-
abstract class CSSList implements Commentable, Positionable, Renderable
35+
abstract class CSSList implements Commentable, CSSElement, Positionable
3536
{
3637
use Position;
3738

src/CSSList/Document.php

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

33
namespace Sabberworm\CSS\CSSList;
44

5+
use Sabberworm\CSS\CSSElement;
56
use Sabberworm\CSS\OutputFormat;
67
use Sabberworm\CSS\Parsing\ParserState;
78
use Sabberworm\CSS\Parsing\SourceException;
@@ -80,7 +81,7 @@ public function getAllRuleSets()
8081
/**
8182
* Returns all `Value` objects found recursively in `Rule`s in the tree.
8283
*
83-
* @param CSSList|RuleSet|string $mElement
84+
* @param CSSElement|string $mElement
8485
* the `CSSList` or `RuleSet` to start the search from (defaults to the whole document).
8586
* If a string is given, it is used as rule name filter.
8687
* @param bool $bSearchInFunctionArguments whether to also return Value objects used as Function arguments.

src/Rule/Rule.php

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

55
use Sabberworm\CSS\Comment\Comment;
66
use Sabberworm\CSS\Comment\Commentable;
7+
use Sabberworm\CSS\CSSElement;
78
use Sabberworm\CSS\OutputFormat;
89
use Sabberworm\CSS\Parsing\ParserState;
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
use Sabberworm\CSS\Value\RuleValueList;
1515
use Sabberworm\CSS\Value\Value;
1616

@@ -19,7 +19,7 @@
1919
*
2020
* In CSS, `Rule`s are expressed as follows: “key: value[0][0] value[0][1], value[1][0] value[1][1];”
2121
*/
22-
class Rule implements Commentable, Positionable, Renderable
22+
class Rule implements Commentable, CSSElement, Positionable
2323
{
2424
use Position;
2525

src/RuleSet/RuleSet.php

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

55
use Sabberworm\CSS\Comment\Comment;
66
use Sabberworm\CSS\Comment\Commentable;
7+
use Sabberworm\CSS\CSSElement;
78
use Sabberworm\CSS\OutputFormat;
89
use Sabberworm\CSS\Parsing\ParserState;
910
use Sabberworm\CSS\Parsing\UnexpectedEOFException;
@@ -22,7 +23,7 @@
2223
* If you want to manipulate a `RuleSet`, use the methods `addRule(Rule $rule)`, `getRules()` and `removeRule($rule)`
2324
* (which accepts either a `Rule` or a rule name; optionally suffixed by a dash to remove all related rules).
2425
*/
25-
abstract class RuleSet implements Commentable, Positionable, Renderable
26+
abstract class RuleSet implements CSSElement, Commentable, Positionable
2627
{
2728
use Position;
2829

src/Value/Value.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,19 @@
22

33
namespace Sabberworm\CSS\Value;
44

5+
use Sabberworm\CSS\CSSElement;
56
use Sabberworm\CSS\Parsing\ParserState;
67
use Sabberworm\CSS\Parsing\SourceException;
78
use Sabberworm\CSS\Parsing\UnexpectedEOFException;
89
use Sabberworm\CSS\Parsing\UnexpectedTokenException;
910
use Sabberworm\CSS\Position\Position;
1011
use Sabberworm\CSS\Position\Positionable;
11-
use Sabberworm\CSS\Renderable;
1212

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

tests/Unit/CSSList/CSSListTest.php

+182
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Sabberworm\CSS\Tests\Unit\CSSList;
6+
7+
use PHPUnit\Framework\TestCase;
8+
use Sabberworm\CSS\Comment\Commentable;
9+
use Sabberworm\CSS\CSSElement;
10+
use Sabberworm\CSS\Renderable;
11+
use Sabberworm\CSS\RuleSet\DeclarationBlock;
12+
use Sabberworm\CSS\Tests\Unit\CSSList\Fixtures\ConcreteCSSList;
13+
14+
/**
15+
* @covers \Sabberworm\CSS\CSSList\CSSList
16+
*/
17+
final class CSSListTest extends TestCase
18+
{
19+
/**
20+
* @test
21+
*/
22+
public function implementsCSSElement(): void
23+
{
24+
$subject = new ConcreteCSSList();
25+
26+
self::assertInstanceOf(CSSElement::class, $subject);
27+
}
28+
29+
/**
30+
* @test
31+
*/
32+
public function implementsRenderable(): void
33+
{
34+
$subject = new ConcreteCSSList();
35+
36+
self::assertInstanceOf(Renderable::class, $subject);
37+
}
38+
39+
/**
40+
* @test
41+
*/
42+
public function implementsCommentable(): void
43+
{
44+
$subject = new ConcreteCSSList();
45+
46+
self::assertInstanceOf(Commentable::class, $subject);
47+
}
48+
49+
/**
50+
* @test
51+
*/
52+
public function getLineNoByDefaultReturnsZero(): void
53+
{
54+
$subject = new ConcreteCSSList();
55+
56+
self::assertSame(0, $subject->getLineNo());
57+
}
58+
59+
/**
60+
* @test
61+
*/
62+
public function getLineNoReturnsLineNumberProvidedToConstructor(): void
63+
{
64+
$lineNumber = 42;
65+
66+
$subject = new ConcreteCSSList($lineNumber);
67+
68+
self::assertSame($lineNumber, $subject->getLineNo());
69+
}
70+
71+
/**
72+
* @test
73+
*/
74+
public function getContentsInitiallyReturnsEmptyArray(): void
75+
{
76+
$subject = new ConcreteCSSList();
77+
78+
self::assertSame([], $subject->getContents());
79+
}
80+
81+
/**
82+
* @return array<string, array{0: list<DeclarationBlock>}>
83+
*/
84+
public static function contentsDataProvider(): array
85+
{
86+
return [
87+
'empty array' => [[]],
88+
'1 item' => [[new DeclarationBlock()]],
89+
'2 items' => [[new DeclarationBlock(), new DeclarationBlock()]],
90+
];
91+
}
92+
93+
/**
94+
* @test
95+
*
96+
* @param list<DeclarationBlock> $contents
97+
*
98+
* @dataProvider contentsDataProvider
99+
*/
100+
public function setContentsSetsContents(array $contents): void
101+
{
102+
$subject = new ConcreteCSSList();
103+
104+
$subject->setContents($contents);
105+
106+
self::assertSame($contents, $subject->getContents());
107+
}
108+
109+
/**
110+
* @test
111+
*/
112+
public function setContentsReplacesContentsSetInPreviousCall(): void
113+
{
114+
$subject = new ConcreteCSSList();
115+
116+
$contents2 = [new DeclarationBlock()];
117+
118+
$subject->setContents([new DeclarationBlock()]);
119+
$subject->setContents($contents2);
120+
121+
self::assertSame($contents2, $subject->getContents());
122+
}
123+
124+
/**
125+
* @test
126+
*/
127+
public function insertBeforeInsertsContentBeforeSibling(): void
128+
{
129+
$subject = new ConcreteCSSList();
130+
131+
$bogusOne = new DeclarationBlock();
132+
$bogusOne->setSelectors('.bogus-one');
133+
$bogusTwo = new DeclarationBlock();
134+
$bogusTwo->setSelectors('.bogus-two');
135+
136+
$item = new DeclarationBlock();
137+
$item->setSelectors('.item');
138+
139+
$sibling = new DeclarationBlock();
140+
$sibling->setSelectors('.sibling');
141+
142+
$subject->setContents([$bogusOne, $sibling, $bogusTwo]);
143+
144+
self::assertCount(3, $subject->getContents());
145+
146+
$subject->insertBefore($item, $sibling);
147+
148+
self::assertCount(4, $subject->getContents());
149+
self::assertSame([$bogusOne, $item, $sibling, $bogusTwo], $subject->getContents());
150+
}
151+
152+
/**
153+
* @test
154+
*/
155+
public function insertBeforeAppendsIfSiblingNotFound(): void
156+
{
157+
$subject = new ConcreteCSSList();
158+
159+
$bogusOne = new DeclarationBlock();
160+
$bogusOne->setSelectors('.bogus-one');
161+
$bogusTwo = new DeclarationBlock();
162+
$bogusTwo->setSelectors('.bogus-two');
163+
164+
$item = new DeclarationBlock();
165+
$item->setSelectors('.item');
166+
167+
$sibling = new DeclarationBlock();
168+
$sibling->setSelectors('.sibling');
169+
170+
$orphan = new DeclarationBlock();
171+
$orphan->setSelectors('.forever-alone');
172+
173+
$subject->setContents([$bogusOne, $sibling, $bogusTwo]);
174+
175+
self::assertCount(3, $subject->getContents());
176+
177+
$subject->insertBefore($item, $orphan);
178+
179+
self::assertCount(4, $subject->getContents());
180+
self::assertSame([$bogusOne, $sibling, $bogusTwo, $item], $subject->getContents());
181+
}
182+
}

tests/Unit/Rule/RuleTest.php

+11
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Sabberworm\CSS\Tests\Unit\Rule;
44

55
use PHPUnit\Framework\TestCase;
6+
use Sabberworm\CSS\CSSElement;
67
use Sabberworm\CSS\Parsing\ParserState;
78
use Sabberworm\CSS\Settings;
89
use Sabberworm\CSS\Rule\Rule;
@@ -15,6 +16,16 @@
1516
*/
1617
final class RuleTest extends TestCase
1718
{
19+
/**
20+
* @test
21+
*/
22+
public function implementsCSSElement(): void
23+
{
24+
$subject = new Rule('beverage-container');
25+
26+
self::assertInstanceOf(CSSElement::class, $subject);
27+
}
28+
1829
/**
1930
* @return array<string, array{0: string, 1: list<class-string>}>
2031
*/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
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+
/**
13+
* @return never
14+
*/
15+
public function render(OutputFormat $outputFormat): string
16+
{
17+
throw new \BadMethodCallException('Nothing to see here :/', 1744067015);
18+
}
19+
}

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+
}

0 commit comments

Comments
 (0)