Completed
Push — master ( 4daa1b...d5c9ed )
by Daniel
13:53
created

testDBObjectLazyLoadedFields()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 14
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 9
nc 1
nop 0
dl 0
loc 14
rs 9.4285
c 1
b 0
f 0
1
<?php
2
3
namespace SilverStripe\ORM\Tests;
4
5
use SilverStripe\ORM\DB;
6
use SilverStripe\ORM\DataList;
7
use SilverStripe\ORM\DataObject;
8
use SilverStripe\ORM\Tests\DataObjectLazyLoadingTest\VersionedObject;
9
use SilverStripe\ORM\Tests\DataObjectLazyLoadingTest\VersionedSubObject;
10
use SilverStripe\ORM\Tests\DataObjectTest\SubTeam;
11
use SilverStripe\ORM\Tests\DataObjectTest\Team;
12
use SilverStripe\ORM\Tests\VersionedTest\Subclass;
13
use SilverStripe\ORM\Versioning\Versioned;
14
use SilverStripe\Dev\SapphireTest;
15
16
class DataObjectLazyLoadingTest extends SapphireTest
17
{
18
19
    protected static $fixture_file = array(
20
        'DataObjectTest.yml',
21
        'VersionedTest.yml'
22
    );
23
24
    protected function getExtraDataObjects()
25
    {
26
        return array_merge(
27
            DataObjectTest::$extra_data_objects,
28
            ManyManyListTest::$extra_data_objects,
29
            VersionedTest::$extra_data_objects,
30
            [
31
                VersionedObject::class,
32
                VersionedSubObject::class,
33
            ]
34
        );
35
    }
36
37
    public function testQueriedColumnsID()
38
    {
39
        $db = DB::get_conn();
40
        $playerList = new DataList(SubTeam::class);
41
        $playerList = $playerList->setQueriedColumns(array('ID'));
42
        $expected = 'SELECT DISTINCT "DataObjectTest_Team"."ClassName", "DataObjectTest_Team"."LastEdited", ' .
43
            '"DataObjectTest_Team"."Created", "DataObjectTest_Team"."ID", CASE WHEN '.
44
            '"DataObjectTest_Team"."ClassName" IS NOT NULL THEN "DataObjectTest_Team"."ClassName" ELSE ' .
45
            $db->quoteString(Team::class).' END AS "RecordClassName", "DataObjectTest_Team"."Title" '.
46
            'FROM "DataObjectTest_Team" ' .
47
            'LEFT JOIN "DataObjectTest_SubTeam" ON "DataObjectTest_SubTeam"."ID" = "DataObjectTest_Team"."ID" ' .
48
            'WHERE ("DataObjectTest_Team"."ClassName" IN (?))' .
49
            ' ORDER BY "DataObjectTest_Team"."Title" ASC';
50
        $this->assertSQLEquals($expected, $playerList->sql($parameters));
51
    }
52
53
    public function testQueriedColumnsFromBaseTableAndSubTable()
54
    {
55
        $db = DB::get_conn();
56
        $playerList = new DataList(SubTeam::class);
57
        $playerList = $playerList->setQueriedColumns(array('Title', 'SubclassDatabaseField'));
58
        $expected = 'SELECT DISTINCT "DataObjectTest_Team"."ClassName", "DataObjectTest_Team"."LastEdited", ' .
59
            '"DataObjectTest_Team"."Created", "DataObjectTest_Team"."Title", ' .
60
            '"DataObjectTest_SubTeam"."SubclassDatabaseField", "DataObjectTest_Team"."ID", CASE WHEN ' .
61
            '"DataObjectTest_Team"."ClassName" IS NOT NULL THEN "DataObjectTest_Team"."ClassName" ELSE ' .
62
            $db->quoteString(Team::class).' END AS "RecordClassName" FROM "DataObjectTest_Team" ' .
63
            'LEFT JOIN "DataObjectTest_SubTeam" ON "DataObjectTest_SubTeam"."ID" = "DataObjectTest_Team"."ID" WHERE ' .
64
            '("DataObjectTest_Team"."ClassName" IN (?)) ' .
65
            'ORDER BY "DataObjectTest_Team"."Title" ASC';
66
        $this->assertSQLEquals($expected, $playerList->sql($parameters));
67
    }
68
69
    public function testQueriedColumnsFromBaseTable()
70
    {
71
        $db = DB::get_conn();
72
        $playerList = new DataList(SubTeam::class);
73
        $playerList = $playerList->setQueriedColumns(array('Title'));
74
        $expected = 'SELECT DISTINCT "DataObjectTest_Team"."ClassName", "DataObjectTest_Team"."LastEdited", ' .
75
            '"DataObjectTest_Team"."Created", "DataObjectTest_Team"."Title", "DataObjectTest_Team"."ID", ' .
76
            'CASE WHEN "DataObjectTest_Team"."ClassName" IS NOT NULL THEN "DataObjectTest_Team"."ClassName" ELSE ' .
77
            $db->quoteString(Team::class).' END AS "RecordClassName" FROM "DataObjectTest_Team" ' .
78
            'LEFT JOIN "DataObjectTest_SubTeam" ON "DataObjectTest_SubTeam"."ID" = "DataObjectTest_Team"."ID" WHERE ' .
79
            '("DataObjectTest_Team"."ClassName" IN (?)) ' .
80
            'ORDER BY "DataObjectTest_Team"."Title" ASC';
81
        $this->assertSQLEquals($expected, $playerList->sql($parameters));
82
    }
83
84
    public function testQueriedColumnsFromSubTable()
85
    {
86
        $db = DB::get_conn();
87
        $playerList = new DataList(SubTeam::class);
88
        $playerList = $playerList->setQueriedColumns(array('SubclassDatabaseField'));
89
        $expected = 'SELECT DISTINCT "DataObjectTest_Team"."ClassName", "DataObjectTest_Team"."LastEdited", ' .
90
            '"DataObjectTest_Team"."Created", "DataObjectTest_SubTeam"."SubclassDatabaseField", ' .
91
            '"DataObjectTest_Team"."ID", CASE WHEN "DataObjectTest_Team"."ClassName" IS NOT NULL THEN ' .
92
            '"DataObjectTest_Team"."ClassName" ELSE '.$db->quoteString(Team::class).' END ' .
93
            'AS "RecordClassName", "DataObjectTest_Team"."Title" ' .
94
            'FROM "DataObjectTest_Team" LEFT JOIN "DataObjectTest_SubTeam" ON "DataObjectTest_SubTeam"."ID" = ' .
95
            '"DataObjectTest_Team"."ID" WHERE ("DataObjectTest_Team"."ClassName" IN (?)) ' .
96
            'ORDER BY "DataObjectTest_Team"."Title" ASC';
97
        $this->assertSQLEquals($expected, $playerList->sql($parameters));
98
    }
99
100
    public function testNoSpecificColumnNamesBaseDataObjectQuery()
101
    {
102
        // This queries all columns from base table
103
        $playerList = new DataList(Team::class);
104
        // Shouldn't be a left join in here.
105
        $this->assertEquals(
106
            0,
107
            preg_match(
108
                $this->normaliseSQL(
109
                    '/SELECT DISTINCT "DataObjectTest_Team"."ID" .* LEFT JOIN .* FROM "DataObjectTest_Team"/'
110
                ),
111
                $this->normaliseSQL($playerList->sql($parameters))
112
            )
113
        );
114
    }
115
116
    public function testNoSpecificColumnNamesSubclassDataObjectQuery()
117
    {
118
        // This queries all columns from base table and subtable
119
        $playerList = new DataList(SubTeam::class);
120
        // Should be a left join.
121
        $this->assertEquals(
122
            1,
123
            preg_match(
124
                $this->normaliseSQL('/SELECT DISTINCT .* LEFT JOIN .* /'),
125
                $this->normaliseSQL($playerList->sql($parameters))
126
            )
127
        );
128
    }
129
130
    public function testLazyLoadedFieldsHasField()
131
    {
132
        $subteam1 = $this->objFromFixture(SubTeam::class, 'subteam1');
133
        $teams = DataObject::get(Team::class); // query parent class
134
        $subteam1Lazy = $teams->find('ID', $subteam1->ID);
135
136
        // TODO Fix hasField() to exclude *_Lazy
137
        // $this->assertFalse($subteam1Lazy->hasField('SubclassDatabaseField_Lazy'));
0 ignored issues
show
Unused Code Comprehensibility introduced by
77% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
138
        $this->assertTrue($subteam1Lazy->hasField('SubclassDatabaseField'));
139
    }
140
141
    public function testLazyLoadedFieldsGetField()
142
    {
143
        $subteam1 = $this->objFromFixture(SubTeam::class, 'subteam1');
144
        $teams = DataObject::get(Team::class); // query parent class
145
        $subteam1Lazy = $teams->find('ID', $subteam1->ID);
146
147
        $this->assertEquals(
148
            $subteam1->getField('SubclassDatabaseField'),
149
            $subteam1Lazy->getField('SubclassDatabaseField')
150
        );
151
    }
152
153
    public function testDBObjectLazyLoadedFields()
154
    {
155
        $subteam1 = $this->objFromFixture(SubTeam::class, 'subteam1');
156
        $teams = DataObject::get(Team::class); // query parent class
157
        $subteam1Lazy = $teams->find('ID', $subteam1->ID);
158
159
        $subteam1DO = $subteam1->dbObject('SubclassDatabaseField');
160
        $subteam1LazyDO = $subteam1Lazy->dbObject('SubclassDatabaseField');
161
162
        $this->assertEquals(
163
            $subteam1DO->getValue(),
164
            $subteam1LazyDO->getValue()
165
        );
166
    }
167
168
    public function testLazyLoadedFieldsSetField()
169
    {
170
        $subteam1 = $this->objFromFixture(SubTeam::class, 'subteam1');
171
        $subteam1ID = $subteam1->ID;
172
        $teams = DataObject::get(Team::class); // query parent class
173
        $subteam1Lazy = $teams->find('ID', $subteam1->ID);
174
175
        // Updated lazyloaded field
176
        $subteam1Lazy->SubclassDatabaseField = 'Changed';
0 ignored issues
show
Documentation introduced by
The property SubclassDatabaseField does not exist on object<SilverStripe\ORM\DataObject>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
177
        $subteam1Lazy->write();
178
179
        // Reload from database
180
        DataObject::flush_and_destroy_cache();
181
        $subteam1Reloaded = DataObject::get_by_id(SubTeam::class, $subteam1ID);
182
183
        $this->assertEquals(
184
            'Changed',
185
            $subteam1Reloaded->getField('SubclassDatabaseField')
186
        );
187
    }
188
189
    public function testLazyLoadedFieldsWriteWithUnloadedFields()
190
    {
191
        $subteam1 = $this->objFromFixture(SubTeam::class, 'subteam1');
192
        $subteam1ID = $subteam1->ID;
193
        $teams = DataObject::get(Team::class); // query parent class
194
        $subteam1Lazy = $teams->find('ID', $subteam1->ID);
195
196
        // Updated lazyloaded field
197
        $subteam1Lazy->Title = 'Changed';
0 ignored issues
show
Documentation introduced by
The property Title does not exist on object<SilverStripe\ORM\DataObject>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
198
        $subteam1Lazy->write();
199
200
        // Reload from database
201
        DataObject::flush_and_destroy_cache();
202
        $subteam1Reloaded = DataObject::get_by_id(SubTeam::class, $subteam1ID);
203
204
        $this->assertEquals(
205
            'Subclassed 1',
206
            $subteam1Reloaded->getField('SubclassDatabaseField')
207
        );
208
    }
209
210
    public function testLazyLoadedFieldsWriteNullFields()
211
    {
212
        $subteam1 = $this->objFromFixture(SubTeam::class, 'subteam1');
213
        $subteam1ID = $subteam1->ID;
214
        $teams = DataObject::get(Team::class); // query parent class
215
        $subteam1Lazy = $teams->find('ID', $subteam1->ID);
216
217
        // Updated lazyloaded field
218
        $subteam1Lazy->SubclassDatabaseField = null;
0 ignored issues
show
Documentation introduced by
The property SubclassDatabaseField does not exist on object<SilverStripe\ORM\DataObject>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
219
        $subteam1Lazy->write();
220
221
        // Reload from database
222
        DataObject::flush_and_destroy_cache();
223
        $subteam1Reloaded = DataObject::get_by_id(SubTeam::class, $subteam1ID);
224
225
        $this->assertEquals(
226
            null,
227
            $subteam1Reloaded->getField('SubclassDatabaseField')
228
        );
229
    }
230
231
    public function testLazyLoadedFieldsGetChangedFields()
232
    {
233
        $subteam1 = $this->objFromFixture(SubTeam::class, 'subteam1');
234
        $teams = DataObject::get(Team::class); // query parent class
235
        $subteam1Lazy = $teams->find('ID', $subteam1->ID);
236
237
        // Updated lazyloaded field
238
        $subteam1Lazy->SubclassDatabaseField = 'Changed';
0 ignored issues
show
Documentation introduced by
The property SubclassDatabaseField does not exist on object<SilverStripe\ORM\DataObject>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
239
        $this->assertEquals(
240
            array('SubclassDatabaseField' => array(
241
                'before' => 'Subclassed 1',
242
                'after' => 'Changed',
243
                'level' => 2
244
            )),
245
            $subteam1Lazy->getChangedFields()
246
        );
247
    }
248
249
    public function testLazyLoadedFieldsHasOneRelation()
250
    {
251
        $subteam1 = $this->objFromFixture(SubTeam::class, 'subteam1');
252
        $parentTeam = $this->objFromFixture(Team::class, 'team1');
253
        $teams = DataObject::get(Team::class); // query parent class
254
        $subteam1Lazy = $teams->find('ID', $subteam1->ID);
255
256
        $parentTeamLazy = $subteam1Lazy->ParentTeam();
257
        $this->assertInstanceOf(Team::class, $parentTeamLazy);
258
        $this->assertEquals($parentTeam->ID, $parentTeamLazy->ID);
259
    }
260
261
    public function testLazyLoadedFieldsToMap()
262
    {
263
        $subteam1 = $this->objFromFixture(SubTeam::class, 'subteam1');
264
        $parentTeam = $this->objFromFixture(Team::class, 'team1');
265
        $teams = DataObject::get(Team::class); // query parent class
266
        $subteam1Lazy = $teams->find('ID', $subteam1->ID);
267
        $mapLazy = $subteam1Lazy->toMap();
268
        $this->assertArrayHasKey('SubclassDatabaseField', $mapLazy);
269
        $this->assertEquals('Subclassed 1', $mapLazy['SubclassDatabaseField']);
270
    }
271
272
    public function testLazyLoadedFieldsIsEmpty()
273
    {
274
        $subteam1 = $this->objFromFixture(SubTeam::class, 'subteam1');
275
        $parentTeam = $this->objFromFixture(Team::class, 'team1');
276
        $teams = DataObject::get(Team::class); // query parent class
277
        $subteam1Lazy = $teams->find('ID', $subteam1->ID);
278
        $subteam1Lazy->Title = '';
0 ignored issues
show
Documentation introduced by
The property Title does not exist on object<SilverStripe\ORM\DataObject>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
279
        $subteam1Lazy->DecoratedDatabaseField = '';
0 ignored issues
show
Documentation introduced by
The property DecoratedDatabaseField does not exist on object<SilverStripe\ORM\DataObject>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
280
        $subteam1Lazy->ParentTeamID = 0;
0 ignored issues
show
Documentation introduced by
The property ParentTeamID does not exist on object<SilverStripe\ORM\DataObject>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
281
        // Leave $subteam1Lazy->SubclassDatabaseField intact
282
        $this->assertFalse($subteam1Lazy->isEmpty());
283
    }
284
285
    public function testLazyLoadedFieldsDuplicate()
286
    {
287
        $subteam1 = $this->objFromFixture(SubTeam::class, 'subteam1');
288
        $parentTeam = $this->objFromFixture(Team::class, 'team1');
289
        $teams = DataObject::get(Team::class); // query parent class
290
        $subteam1Lazy = $teams->find('ID', $subteam1->ID);
291
        $subteam1LazyDup = $subteam1Lazy->duplicate();
292
293
        $this->assertEquals('Subclassed 1', $subteam1LazyDup->SubclassDatabaseField);
294
    }
295
296
    public function testLazyLoadedFieldsGetAllFields()
297
    {
298
        $subteam1 = $this->objFromFixture(SubTeam::class, 'subteam1');
299
        $parentTeam = $this->objFromFixture(Team::class, 'team1');
300
        $teams = DataObject::get(Team::class); // query parent class
301
        $subteam1Lazy = $teams->find('ID', $subteam1->ID);
302
        $this->assertArrayNotHasKey('SubclassDatabaseField_Lazy', $subteam1Lazy->toMap());
303
        $this->assertArrayHasKey('SubclassDatabaseField', $subteam1Lazy->toMap());
304
    }
305
306
    public function testLazyLoadedFieldsOnVersionedRecords()
307
    {
308
        // Save another record, sanity check that we're getting the right one
309
        $obj2 = new Subclass();
310
        $obj2->Name = "test2";
0 ignored issues
show
Documentation introduced by
The property Name does not exist on object<SilverStripe\ORM\...VersionedTest\Subclass>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
311
        $obj2->ExtraField = "foo2";
0 ignored issues
show
Bug introduced by
The property ExtraField does not seem to exist. Did you mean many_many_extraFields?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
312
        $obj2->write();
313
314
        // Save the actual inspected record
315
        $obj1 = new Subclass();
316
        $obj1->Name = "test";
0 ignored issues
show
Documentation introduced by
The property Name does not exist on object<SilverStripe\ORM\...VersionedTest\Subclass>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
317
        $obj1->ExtraField = "foo";
0 ignored issues
show
Bug introduced by
The property ExtraField does not seem to exist. Did you mean many_many_extraFields?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
318
        $obj1->write();
319
        $version1 = $obj1->Version;
0 ignored issues
show
Documentation introduced by
The property Version does not exist on object<SilverStripe\ORM\...VersionedTest\Subclass>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
320
        $obj1->Name = "test2";
0 ignored issues
show
Documentation introduced by
The property Name does not exist on object<SilverStripe\ORM\...VersionedTest\Subclass>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
321
        $obj1->ExtraField = "baz";
0 ignored issues
show
Bug introduced by
The property ExtraField does not seem to exist. Did you mean many_many_extraFields?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
322
        $obj1->write();
323
        $version2 = $obj1->Version;
0 ignored issues
show
Documentation introduced by
The property Version does not exist on object<SilverStripe\ORM\...VersionedTest\Subclass>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
324
325
326
        $reloaded = Versioned::get_version(VersionedTest\Subclass::class, $obj1->ID, $version1);
327
        $this->assertEquals($reloaded->Name, 'test');
328
        $this->assertEquals($reloaded->ExtraField, 'foo');
0 ignored issues
show
Bug introduced by
The property ExtraField does not seem to exist. Did you mean many_many_extraFields?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
329
330
        $reloaded = Versioned::get_version(VersionedTest\Subclass::class, $obj1->ID, $version2);
331
        $this->assertEquals($reloaded->Name, 'test2');
332
        $this->assertEquals($reloaded->ExtraField, 'baz');
0 ignored issues
show
Bug introduced by
The property ExtraField does not seem to exist. Did you mean many_many_extraFields?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
333
334
        $reloaded = Versioned::get_latest_version(VersionedTest\Subclass::class, $obj1->ID);
335
        $this->assertEquals($reloaded->Version, $version2);
336
        $this->assertEquals($reloaded->Name, 'test2');
337
        $this->assertEquals($reloaded->ExtraField, 'baz');
0 ignored issues
show
Bug introduced by
The property ExtraField does not seem to exist. Did you mean many_many_extraFields?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
338
339
        $allVersions = Versioned::get_all_versions(VersionedTest\Subclass::class, $obj1->ID);
340
        $this->assertEquals(2, $allVersions->count());
341
        $this->assertEquals($allVersions->first()->Version, $version1);
342
        $this->assertEquals($allVersions->first()->Name, 'test');
343
        $this->assertEquals($allVersions->first()->ExtraField, 'foo');
0 ignored issues
show
Bug introduced by
The property ExtraField does not seem to exist. Did you mean many_many_extraFields?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
344
        $this->assertEquals($allVersions->last()->Version, $version2);
345
        $this->assertEquals($allVersions->last()->Name, 'test2');
346
        $this->assertEquals($allVersions->last()->ExtraField, 'baz');
0 ignored issues
show
Bug introduced by
The property ExtraField does not seem to exist. Did you mean many_many_extraFields?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
347
348
        $obj1->delete();
349
    }
350
351
    public function testLazyLoadedFieldsDoNotReferenceVersionsTable()
352
    {
353
        // Save another record, sanity check that we're getting the right one
354
        $obj2 = new Subclass();
355
        $obj2->Name = "test2";
0 ignored issues
show
Documentation introduced by
The property Name does not exist on object<SilverStripe\ORM\...VersionedTest\Subclass>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
356
        $obj2->ExtraField = "foo2";
0 ignored issues
show
Bug introduced by
The property ExtraField does not seem to exist. Did you mean many_many_extraFields?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
357
        $obj2->write();
358
359
        $obj1 = new VersionedSubObject();
360
        $obj1->PageName = "old-value";
0 ignored issues
show
Documentation introduced by
The property PageName does not exist on object<SilverStripe\ORM\...est\VersionedSubObject>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
361
        $obj1->ExtraField = "old-value";
0 ignored issues
show
Bug introduced by
The property ExtraField does not seem to exist. Did you mean many_many_extraFields?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
362
        $obj1ID = $obj1->write();
363
        $obj1->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE);
364
365
        $obj1 = VersionedSubObject::get()->byID($obj1ID);
366
        $this->assertEquals(
367
            'old-value',
368
            $obj1->PageName,
369
            "Correct value on base table when fetching base class"
370
        );
371
        $this->assertEquals(
372
            'old-value',
373
            $obj1->ExtraField,
0 ignored issues
show
Bug introduced by
The property ExtraField does not seem to exist. Did you mean many_many_extraFields?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
374
            "Correct value on sub table when fetching base class"
375
        );
376
377
        $obj1 = VersionedObject::get()->byID($obj1ID);
378
        $this->assertEquals(
379
            'old-value',
380
            $obj1->PageName,
381
            "Correct value on base table when fetching sub class"
382
        );
383
        $this->assertEquals(
384
            'old-value',
385
            $obj1->ExtraField,
0 ignored issues
show
Bug introduced by
The property ExtraField does not seem to exist. Did you mean many_many_extraFields?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
386
            "Correct value on sub table when fetching sub class"
387
        );
388
389
        // Force inconsistent state to test behaviour (shouldn't select from *_versions)
390
        DB::query(
391
            sprintf(
392
                "UPDATE \"VersionedLazy_DataObject_Versions\" SET \"PageName\" = 'versioned-value' " .
393
                "WHERE \"RecordID\" = %d",
394
                $obj1ID
395
            )
396
        );
397
        DB::query(
398
            sprintf(
399
                "UPDATE \"VersionedLazySub_DataObject_Versions\" SET \"ExtraField\" = 'versioned-value' " .
400
                "WHERE \"RecordID\" = %d",
401
                $obj1ID
402
            )
403
        );
404
405
        $obj1 = VersionedSubObject::get()->byID($obj1ID);
406
        $this->assertEquals(
407
            'old-value',
408
            $obj1->PageName,
409
            "Correct value on base table when fetching base class"
410
        );
411
        $this->assertEquals(
412
            'old-value',
413
            $obj1->ExtraField,
0 ignored issues
show
Bug introduced by
The property ExtraField does not seem to exist. Did you mean many_many_extraFields?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
414
            "Correct value on sub table when fetching base class"
415
        );
416
        $obj1 = VersionedObject::get()->byID($obj1ID);
417
        $this->assertEquals(
418
            'old-value',
419
            $obj1->PageName,
420
            "Correct value on base table when fetching sub class"
421
        );
422
        $this->assertEquals(
423
            'old-value',
424
            $obj1->ExtraField,
0 ignored issues
show
Bug introduced by
The property ExtraField does not seem to exist. Did you mean many_many_extraFields?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
425
            "Correct value on sub table when fetching sub class"
426
        );
427
428
        // Update live table only to test behaviour (shouldn't select from *_versions or stage)
429
        DB::query(
430
            sprintf(
431
                'UPDATE "VersionedLazy_DataObject_Live" SET "PageName" = \'live-value\' WHERE "ID" = %d',
432
                $obj1ID
433
            )
434
        );
435
        DB::query(
436
            sprintf(
437
                'UPDATE "VersionedLazySub_DataObject_Live" SET "ExtraField" = \'live-value\' WHERE "ID" = %d',
438
                $obj1ID
439
            )
440
        );
441
442
        Versioned::set_stage(Versioned::LIVE);
443
        $obj1 = VersionedObject::get()->byID($obj1ID);
444
        $this->assertEquals(
445
            'live-value',
446
            $obj1->PageName,
447
            "Correct value from base table when fetching base class on live stage"
448
        );
449
        $this->assertEquals(
450
            'live-value',
451
            $obj1->ExtraField,
0 ignored issues
show
Bug introduced by
The property ExtraField does not seem to exist. Did you mean many_many_extraFields?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
452
            "Correct value from sub table when fetching base class on live stage"
453
        );
454
    }
455
}
456