1 | <?php |
||||
2 | |||||
3 | namespace DNADesign\Elemental\Tests\TopPage; |
||||
4 | |||||
5 | use DNADesign\Elemental\Extensions\ElementalAreasExtension; |
||||
6 | use DNADesign\Elemental\Extensions\ElementalPageExtension; |
||||
7 | use DNADesign\Elemental\Models\BaseElement; |
||||
8 | use DNADesign\Elemental\Models\ElementalArea; |
||||
9 | use DNADesign\Elemental\TopPage; |
||||
10 | use Page; |
||||
11 | use SilverStripe\Dev\SapphireTest; |
||||
12 | use SilverStripe\ORM\DataObject; |
||||
13 | |||||
14 | class TopPageTest extends SapphireTest |
||||
15 | { |
||||
16 | /** |
||||
17 | * @var string |
||||
18 | */ |
||||
19 | protected static $fixture_file = 'TopPageTest.yml'; |
||||
20 | |||||
21 | /** |
||||
22 | * @var array |
||||
23 | */ |
||||
24 | protected static $required_extensions = [ |
||||
25 | TestBlockPage::class => [ |
||||
26 | ElementalPageExtension::class, |
||||
27 | ], |
||||
28 | TestChildPage::class => [ |
||||
29 | ElementalPageExtension::class, |
||||
30 | ], |
||||
31 | Page::class => [ |
||||
32 | TopPage\SiteTreeExtension::class, |
||||
33 | ], |
||||
34 | ElementalArea::class => [ |
||||
35 | TopPage\DataExtension::class, |
||||
36 | ], |
||||
37 | BaseElement::class => [ |
||||
38 | TopPage\DataExtension::class, |
||||
39 | ], |
||||
40 | TestList::class => [ |
||||
41 | ElementalAreasExtension::class, |
||||
42 | ], |
||||
43 | ]; |
||||
44 | |||||
45 | /** |
||||
46 | * @var array |
||||
47 | */ |
||||
48 | protected static $extra_dataobjects = [ |
||||
49 | TestContent::class, |
||||
50 | TestList::class, |
||||
51 | TestBlockPage::class, |
||||
52 | TestChildPage::class, |
||||
53 | ]; |
||||
54 | |||||
55 | /** |
||||
56 | * @param string $pageIdentifier |
||||
57 | * @param string $pageClass |
||||
58 | * @param string $objectIdentifier |
||||
59 | * @param string $objectClass |
||||
60 | * @dataProvider objectsProvider |
||||
61 | */ |
||||
62 | public function testTestGetTopPage( |
||||
63 | string $pageIdentifier, |
||||
64 | string $pageClass, |
||||
65 | string $objectIdentifier, |
||||
66 | string $objectClass |
||||
67 | ): void { |
||||
68 | /** @var Page|TopPage\SiteTreeExtension $content */ |
||||
69 | $page = $this->objFromFixture($pageClass, $pageIdentifier); |
||||
70 | |||||
71 | /** @var DataObject|TopPage\DataExtension $object */ |
||||
72 | $object = $this->objFromFixture($objectClass, $objectIdentifier); |
||||
73 | |||||
74 | $topPage = $object->getTopPage(); |
||||
75 | |||||
76 | $this->assertNotNull($topPage); |
||||
77 | $this->assertEquals((int) $page->ID, (int) $topPage->ID); |
||||
78 | } |
||||
79 | |||||
80 | /** |
||||
81 | * @param string $pageIdentifier |
||||
82 | * @param string $pageClass |
||||
83 | * @param string $objectIdentifier |
||||
84 | * @param string $objectClass |
||||
85 | * @dataProvider objectsProvider |
||||
86 | */ |
||||
87 | public function testTestUpdateTopPageEmptyCache( |
||||
88 | string $pageIdentifier, |
||||
89 | string $pageClass, |
||||
90 | string $objectIdentifier, |
||||
91 | string $objectClass |
||||
92 | ): void { |
||||
93 | /** @var TopPage\DataExtension $extension */ |
||||
94 | $extension = singleton(TopPage\DataExtension::class); |
||||
95 | $extension->withTopPageUpdate( |
||||
96 | true, |
||||
97 | function () use ($pageIdentifier, $pageClass, $objectIdentifier, $objectClass): void { |
||||
98 | /** @var Page|TopPage\SiteTreeExtension $content */ |
||||
99 | $page = $this->objFromFixture($pageClass, $pageIdentifier); |
||||
100 | |||||
101 | /** @var DataObject|TopPage\DataExtension $object */ |
||||
102 | $object = $this->objFromFixture($objectClass, $objectIdentifier); |
||||
103 | |||||
104 | $this->assertEquals(0, (int) $object->TopPageID); |
||||
105 | |||||
106 | $object->forceChange(); |
||||
107 | $id = $object->write(); |
||||
108 | $object = DataObject::get($object->ClassName)->byID($id); |
||||
109 | |||||
110 | $this->assertEquals((int) $page->ID, (int) $object->TopPageID); |
||||
111 | |||||
112 | // do a second write to make sure that we won't override existing top page |
||||
113 | $object->forceChange(); |
||||
114 | $id = $object->write(); |
||||
115 | $object = DataObject::get($object->ClassName)->byID($id); |
||||
116 | |||||
117 | $this->assertEquals((int) $page->ID, (int) $object->TopPageID); |
||||
118 | } |
||||
119 | ); |
||||
120 | } |
||||
121 | |||||
122 | public function testNewPage(): void |
||||
123 | { |
||||
124 | /** @var TopPage\DataExtension $extension */ |
||||
125 | $extension = singleton(TopPage\DataExtension::class); |
||||
126 | $extension->withTopPageUpdate( |
||||
127 | true, |
||||
128 | function (): void { |
||||
129 | $page = TestBlockPage::create(); |
||||
130 | $page->Title = 'New page test'; |
||||
131 | $page->write(); |
||||
132 | |||||
133 | /** @var ElementalArea|TopPage\DataExtension $area */ |
||||
134 | $area = $page->ElementalArea(); |
||||
135 | $this->assertEquals((int) $page->ID, (int) $area->TopPageID); |
||||
0 ignored issues
–
show
Bug
Best Practice
introduced
by
![]() |
|||||
136 | } |
||||
137 | ); |
||||
138 | } |
||||
139 | |||||
140 | /** |
||||
141 | * @param bool $populateTopPage |
||||
142 | * @dataProvider populateTopPageProvider |
||||
143 | */ |
||||
144 | public function testNewBlock(bool $populateTopPage): void |
||||
145 | { |
||||
146 | /** @var TopPage\DataExtension $extension */ |
||||
147 | $extension = singleton(TopPage\DataExtension::class); |
||||
148 | $extension->withTopPageUpdate( |
||||
149 | true, |
||||
150 | function () use ($populateTopPage): void { |
||||
151 | if ($populateTopPage) { |
||||
152 | $this->populateTopPageForAllObjects(); |
||||
153 | } |
||||
154 | |||||
155 | /** @var TestBlockPage $page */ |
||||
156 | $page = $this->objFromFixture(TestBlockPage::class, 'block-page1'); |
||||
157 | |||||
158 | /** @var ElementalArea $area */ |
||||
159 | $area = $this->objFromFixture(ElementalArea::class, 'area3'); |
||||
160 | |||||
161 | /** @var TestContent|TopPage\DataExtension $content */ |
||||
162 | $content = TestContent::create(); |
||||
163 | $content->Title = 'Fresh block'; |
||||
0 ignored issues
–
show
|
|||||
164 | |||||
165 | $area->Elements()->add($content); |
||||
0 ignored issues
–
show
It seems like
$content can also be of type DNADesign\Elemental\TopPage\DataExtension ; however, parameter $item of SilverStripe\ORM\HasManyList::add() does only seem to accept SilverStripe\ORM\DataObject|integer , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
166 | $content = DataObject::get($content->ClassName)->byID($content->ID); |
||||
0 ignored issues
–
show
|
|||||
167 | |||||
168 | $this->assertEquals((int) $page->ID, (int) $content->TopPageID); |
||||
169 | } |
||||
170 | ); |
||||
171 | } |
||||
172 | |||||
173 | /** |
||||
174 | * This test is checking for page duplication in two cases |
||||
175 | * Case 1: standard duplication |
||||
176 | * Case 2: duplication with a fixed page setting |
||||
177 | * The seconds case shows that it's possible to use the withFixedTopPage to set the top page to arbitrary value |
||||
178 | * and completely bypass page determination logic |
||||
179 | * This is needed in some edge cases were automatic determination is not possible due to the object not being |
||||
180 | * assigned to the parent object at the time of duplication but rather later |
||||
181 | * |
||||
182 | * @param int $fixedPageID |
||||
183 | * @dataProvider fixedPagesProvider |
||||
184 | */ |
||||
185 | public function testPageDuplication(int $fixedPageID): void |
||||
186 | { |
||||
187 | /** @var TopPage\DataExtension $extension */ |
||||
188 | $extension = singleton(TopPage\DataExtension::class); |
||||
189 | $extension->withFixedTopPage($fixedPageID, function () use ($extension, $fixedPageID) { |
||||
190 | $extension->withTopPageUpdate( |
||||
191 | true, |
||||
192 | function () use ($fixedPageID): void { |
||||
193 | $this->populateTopPageForAllObjects(); |
||||
194 | |||||
195 | /** @var TestBlockPage $page */ |
||||
196 | $page = $this->objFromFixture(TestBlockPage::class, 'block-page1'); |
||||
197 | |||||
198 | /** @var TestChildPage $childPage */ |
||||
199 | $childPage = $this->objFromFixture(TestChildPage::class, 'child-page1'); |
||||
200 | |||||
201 | $page->duplicate(); |
||||
202 | $pages = TestBlockPage::get()->filter(['Title' => 'BlockPage1'])->sort('ID', 'DESC'); |
||||
203 | |||||
204 | $this->assertCount(2, $pages); |
||||
205 | |||||
206 | $pageClone = $pages->first(); |
||||
207 | $childPages = TestChildPage::get()->filter(['Title' => 'ChildPage1'])->sort('ID', 'DESC'); |
||||
208 | |||||
209 | $this->assertCount(2, $childPages); |
||||
210 | |||||
211 | $childClone = $childPages->first(); |
||||
212 | |||||
213 | $this->assertNotEquals((int) $childPage->ID, (int) $childClone->ID); |
||||
214 | |||||
215 | $objects = [ |
||||
216 | [TestList::class, 'List1', $pageClone], |
||||
217 | [TestContent::class, 'Content1', $pageClone], |
||||
218 | [TestList::class, 'List2', $childClone], |
||||
219 | [TestContent::class, 'Content2', $childClone], |
||||
220 | ]; |
||||
221 | |||||
222 | foreach ($objects as $objectData) { |
||||
223 | $class = array_shift($objectData); |
||||
224 | $title = array_shift($objectData); |
||||
225 | $page = array_shift($objectData); |
||||
226 | |||||
227 | $items = DataObject::get($class)->filter(['Title' => $title])->sort('ID', 'DESC'); |
||||
228 | |||||
229 | $this->assertCount(2, $items); |
||||
230 | |||||
231 | /** @var DataObject|TopPage\DataExtension $objectClone */ |
||||
232 | $objectClone = $items->first(); |
||||
233 | |||||
234 | $expected = $fixedPageID ?: (int) $page->ID; |
||||
235 | $this->assertEquals($expected, (int) $objectClone->TopPageID); |
||||
236 | |||||
237 | /** @var ElementalArea|TopPage\DataExtension $area */ |
||||
238 | $area = $objectClone->Parent(); |
||||
239 | |||||
240 | $this->assertEquals($expected, (int) $area->TopPageID); |
||||
0 ignored issues
–
show
The property
TopPageID does not exist on DNADesign\Elemental\Models\ElementalArea . Since you implemented __get , consider adding a @property annotation.
![]() |
|||||
241 | } |
||||
242 | } |
||||
243 | ); |
||||
244 | }); |
||||
245 | } |
||||
246 | |||||
247 | public function objectsProvider(): array |
||||
248 | { |
||||
249 | return [ |
||||
250 | [ |
||||
251 | 'block-page1', |
||||
252 | TestBlockPage::class, |
||||
253 | 'content1', |
||||
254 | TestContent::class, |
||||
255 | ], |
||||
256 | [ |
||||
257 | 'block-page1', |
||||
258 | TestBlockPage::class, |
||||
259 | 'list1', |
||||
260 | TestList::class, |
||||
261 | ], |
||||
262 | [ |
||||
263 | 'block-page1', |
||||
264 | TestBlockPage::class, |
||||
265 | 'area1', |
||||
266 | ElementalArea::class, |
||||
267 | ], |
||||
268 | [ |
||||
269 | 'block-page1', |
||||
270 | TestBlockPage::class, |
||||
271 | 'area3', |
||||
272 | ElementalArea::class, |
||||
273 | ], |
||||
274 | [ |
||||
275 | 'child-page1', |
||||
276 | TestChildPage::class, |
||||
277 | 'content2', |
||||
278 | TestContent::class, |
||||
279 | ], |
||||
280 | [ |
||||
281 | 'child-page1', |
||||
282 | TestChildPage::class, |
||||
283 | 'list2', |
||||
284 | TestList::class, |
||||
285 | ], |
||||
286 | [ |
||||
287 | 'child-page1', |
||||
288 | TestChildPage::class, |
||||
289 | 'area2', |
||||
290 | ElementalArea::class, |
||||
291 | ], |
||||
292 | [ |
||||
293 | 'child-page1', |
||||
294 | TestChildPage::class, |
||||
295 | 'area4', |
||||
296 | ElementalArea::class, |
||||
297 | ], |
||||
298 | ]; |
||||
299 | } |
||||
300 | |||||
301 | public function populateTopPageProvider(): array |
||||
302 | { |
||||
303 | return [ |
||||
304 | [true], |
||||
305 | [false], |
||||
306 | ]; |
||||
307 | } |
||||
308 | |||||
309 | public function fixedPagesProvider(): array |
||||
310 | { |
||||
311 | return [ |
||||
312 | [0], // feature is disabled |
||||
313 | [99], // obviously non-existent page |
||||
314 | ]; |
||||
315 | } |
||||
316 | |||||
317 | private function populateTopPageForAllObjects(): void |
||||
318 | { |
||||
319 | $list = $this->objectsProvider(); |
||||
320 | |||||
321 | foreach ($list as $objects) { |
||||
322 | array_shift($objects); |
||||
323 | array_shift($objects); |
||||
324 | $identifier = array_shift($objects); |
||||
325 | $class = array_shift($objects); |
||||
326 | |||||
327 | $object = $this->objFromFixture($class, $identifier); |
||||
328 | $object->forceChange(); |
||||
329 | $object->write(); |
||||
330 | } |
||||
331 | } |
||||
332 | } |
||||
333 |