Passed
Push — 4 ( eae0ff...3ed7c8 )
by Steve
64:51 queued 12s
created

TopPageTest::fixedPagesProvider()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 5
rs 10
c 1
b 0
f 0
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;
0 ignored issues
show
Bug introduced by
The type Page was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
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
The property TopPageID does not exist on DNADesign\Elemental\Models\ElementalArea. Since you implemented __get, consider adding a @property annotation.
Loading history...
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
Bug introduced by
The property Title does not seem to exist on DNADesign\Elemental\TopPage\DataExtension.
Loading history...
164
165
                $area->Elements()->add($content);
0 ignored issues
show
Bug introduced by
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 ignore-type  annotation

165
                $area->Elements()->add(/** @scrutinizer ignore-type */ $content);
Loading history...
166
                $content = DataObject::get($content->ClassName)->byID($content->ID);
0 ignored issues
show
Bug introduced by
The property ClassName does not seem to exist on DNADesign\Elemental\TopPage\DataExtension.
Loading history...
Bug introduced by
The property ID does not seem to exist on DNADesign\Elemental\TopPage\DataExtension.
Loading history...
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();
0 ignored issues
show
Bug introduced by
The method first() does not exist on Traversable. It seems like you code against a sub-type of Traversable such as IntlCodePointBreakIterator or IntlRuleBasedBreakIterator or SilverStripe\ORM\SS_List or SilverStripe\View\ViewableData or League\Csv\Reader or Symfony\Component\DomCrawler\Crawler or IntlBreakIterator or Ds\Map or Ds\Set or Ds\Sequence or SilverStripe\ORM\Connect\Query or Cassandra\Rows. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

206
                    /** @scrutinizer ignore-call */ 
207
                    $pageClone = $pages->first();
Loading history...
Bug introduced by
The method first() does not exist on Countable. It seems like you code against a sub-type of Countable such as SilverStripe\ORM\SS_List or League\Csv\Reader or Symfony\Component\DomCrawler\Crawler or Ds\Map or Ds\Set or Ds\Sequence. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

206
                    /** @scrutinizer ignore-call */ 
207
                    $pageClone = $pages->first();
Loading history...
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
Bug Best Practice introduced by
The property TopPageID does not exist on DNADesign\Elemental\Models\ElementalArea. Since you implemented __get, consider adding a @property annotation.
Loading history...
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