Completed
Push — 3.2 ( 88f8ac...cd42d0 )
by Daniel
28:57 queued 28:57
created

testHasOwnTableDatabaseFieldWithVersioned()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 30
Code Lines 23

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 30
rs 8.8571
cc 1
eloc 23
nc 1
nop 0
1
<?php
2
3
/**
4
 * @package framework
5
 * @subpackage tests
6
 */
7
class VersionedTest extends SapphireTest {
8
9
	protected static $fixture_file = 'VersionedTest.yml';
10
11
	protected $extraDataObjects = array(
12
		'VersionedTest_DataObject',
13
		'VersionedTest_Subclass',
14
		'VersionedTest_AnotherSubclass',
15
		'VersionedTest_RelatedWithoutVersion',
16
		'VersionedTest_SingleStage',
17
		'VersionedTest_WithIndexes',
18
	);
19
20
	protected $requiredExtensions = array(
21
		"VersionedTest_DataObject" => array('Versioned'),
22
		"VersionedTest_WithIndexes" => array('Versioned'),
23
	);
24
25
	public function testUniqueIndexes() {
26
		$tableExpectations = array(
27
			'VersionedTest_WithIndexes' =>
28
				array('value' => true, 'message' => 'Unique indexes are unique in main table'),
29
			'VersionedTest_WithIndexes_versions' =>
30
				array('value' => false, 'message' => 'Unique indexes are no longer unique in _versions table'),
31
			'VersionedTest_WithIndexes_Live' =>
32
				array('value' => false, 'message' => 'Unique indexes are no longer unique in _Live table'),
33
		);
34
	
35
		// Test each table's performance
36
		foreach ($tableExpectations as $tableName => $expectation) {
37
			$indexes = DB::get_schema()->indexList($tableName);
38
39
			// Check for presence of all unique indexes
40
			$indexColumns = array_map(function($index) {
41
				return $index['value'];
42
			}, $indexes);
43
			sort($indexColumns);
44
			$expectedColumns = array('"UniqA"', '"UniqS"');
45
			$this->assertEquals(
46
					array_values($expectedColumns),
47
					array_values(array_intersect($indexColumns, $expectedColumns)),
48
					"$tableName has both indexes");
49
50
			// Check unique -> non-unique conversion
51
			foreach ($indexes as $indexKey => $indexSpec) {
52
				if (in_array($indexSpec['value'], $expectedColumns)) {
53
					$isUnique = $indexSpec['type'] === 'unique';
54
					$this->assertEquals($isUnique, $expectation['value'], $expectation['message']);
55
}
56
			}
57
		}
58
	}
59
60
	public function testDeletingOrphanedVersions() {
61
		$obj = new VersionedTest_Subclass();
62
		$obj->ExtraField = 'Foo'; // ensure that child version table gets written
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...
63
		$obj->write();
64
		$obj->publish('Stage', 'Live');
65
66
		$obj->ExtraField = 'Bar'; // ensure that child version table gets written
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...
67
		$obj->write();
68
		$obj->publish('Stage', 'Live');
69
70
		$versions = DB::query("SELECT COUNT(*) FROM \"VersionedTest_Subclass_versions\""
71
			. " WHERE \"RecordID\" = '$obj->ID'")->value();
72
73
		$this->assertGreaterThan(0, $versions, 'At least 1 version exists in the history of the page');
74
75
		// Force orphaning of all versions created earlier, only on parent record.
76
		// The child versiones table should still have the correct relationship
77
		DB::query("DELETE FROM \"VersionedTest_DataObject_versions\" WHERE \"RecordID\" = $obj->ID");
78
79
		// insert a record with no primary key (ID)
80
		DB::query("INSERT INTO \"VersionedTest_DataObject_versions\" (\"RecordID\") VALUES ($obj->ID)");
81
82
		// run the script which should clean that up
83
		$obj->augmentDatabase();
84
85
		$versions = DB::query("SELECT COUNT(*) FROM \"VersionedTest_Subclass_versions\""
86
			. " WHERE \"RecordID\" = '$obj->ID'")->value();
87
		$this->assertEquals(0, $versions, 'Orphaned versions on child tables are removed');
88
89
		// test that it doesn't delete records that we need
90
		$obj->write();
91
		$obj->publish('Stage', 'Live');
92
93
		$count = DB::query("SELECT COUNT(*) FROM \"VersionedTest_Subclass_versions\""
94
			. " WHERE \"RecordID\" = '$obj->ID'")->value();
95
		$obj->augmentDatabase();
96
97
		$count2 = DB::query("SELECT COUNT(*) FROM \"VersionedTest_Subclass_versions\""
98
			. " WHERE \"RecordID\" = '$obj->ID'")->value();
99
100
		$this->assertEquals($count, $count2);
101
	}
102
103
	public function testDuplicate() {
104
		$obj1 = new VersionedTest_Subclass();
105
		$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...
106
		$obj1->write(); // version 1
107
		$obj1->publish('Stage', 'Live');
108
		$obj1->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...
109
		$obj1->write(); // version 2
110
111
		// Make duplicate
112
		$obj2 = $obj1->duplicate();
113
114
		// Check records differ
115
		$this->assertNotEquals($obj1->ID, $obj2->ID);
116
		$this->assertEquals(2, $obj1->Version);
117
		$this->assertEquals(1, $obj2->Version);
118
	}
119
120
	public function testForceChangeUpdatesVersion() {
121
		$obj = new VersionedTest_DataObject();
122
		$obj->Name = "test";
0 ignored issues
show
Documentation introduced by
The property Name does not exist on object<VersionedTest_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...
123
		$obj->write();
124
125
		$oldVersion = $obj->Version;
0 ignored issues
show
Documentation introduced by
The property Version does not exist on object<VersionedTest_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...
126
		$obj->forceChange();
127
		$obj->write();
128
129
		$this->assertTrue(
130
			($obj->Version > $oldVersion),
131
			"A object Version is increased when just calling forceChange() without any other changes"
132
		);
133
	}
134
135
	/**
136
	 * Test Versioned::get_including_deleted()
137
	 */
138
	public function testGetIncludingDeleted() {
139
		// Get all ids of pages
140
		$allPageIDs = DataObject::get(
141
			'VersionedTest_DataObject',
142
			"\"ParentID\" = 0", "\"VersionedTest_DataObject\".\"ID\" ASC"
143
		)->column('ID');
144
145
		// Modify a page, ensuring that the Version ID and Record ID will differ,
146
		// and then subsequently delete it
147
		$targetPage = $this->objFromFixture('VersionedTest_DataObject', 'page3');
148
		$targetPage->Content = 'To be deleted';
0 ignored issues
show
Documentation introduced by
The property Content does not exist on object<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...
149
		$targetPage->write();
150
		$targetPage->delete();
151
152
		// Get all items, ignoring deleted
153
		$remainingPages = DataObject::get("VersionedTest_DataObject", "\"ParentID\" = 0",
154
			"\"VersionedTest_DataObject\".\"ID\" ASC");
155
		// Check that page 3 has gone
156
		$this->assertNotNull($remainingPages);
157
		$this->assertEquals(array("Page 1", "Page 2", "Subclass Page 1"), $remainingPages->column('Title'));
158
159
		// Get all including deleted
160
		$allPages = Versioned::get_including_deleted("VersionedTest_DataObject", "\"ParentID\" = 0",
161
			"\"VersionedTest_DataObject\".\"ID\" ASC");
162
		// Check that page 3 is still there
163
		$this->assertEquals(array("Page 1", "Page 2", "Page 3", "Subclass Page 1"), $allPages->column('Title'));
164
165
		// Check that the returned pages have the correct IDs
166
		$this->assertEquals($allPageIDs, $allPages->column('ID'));
167
168
		// Check that this still works if we switch to reading the other stage
169
		Versioned::reading_stage("Live");
170
		$allPages = Versioned::get_including_deleted("VersionedTest_DataObject", "\"ParentID\" = 0",
171
			"\"VersionedTest_DataObject\".\"ID\" ASC");
172
		$this->assertEquals(array("Page 1", "Page 2", "Page 3", "Subclass Page 1"), $allPages->column('Title'));
173
174
		// Check that the returned pages still have the correct IDs
175
		$this->assertEquals($allPageIDs, $allPages->column('ID'));
176
	}
177
178
	public function testVersionedFieldsAdded() {
179
		$obj = new VersionedTest_DataObject();
180
		// Check that the Version column is added as a full-fledged column
181
		$this->assertInstanceOf('Int', $obj->dbObject('Version'));
182
183
		$obj2 = new VersionedTest_Subclass();
184
		// Check that the Version column is added as a full-fledged column
185
		$this->assertInstanceOf('Int', $obj2->dbObject('Version'));
186
	}
187
188
	public function testVersionedFieldsNotInCMS() {
189
		$obj = new VersionedTest_DataObject();
190
191
		// the version field in cms causes issues with Versioned::augmentWrite()
192
		$this->assertNull($obj->getCMSFields()->dataFieldByName('Version'));
193
	}
194
195
	public function testPublishCreateNewVersion() {
196
		$page1 = $this->objFromFixture('VersionedTest_DataObject', 'page1');
197
		$page1->Content = 'orig';
0 ignored issues
show
Documentation introduced by
The property Content does not exist on object<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
		$page1->write();
199
		$oldVersion = $page1->Version;
0 ignored issues
show
Documentation introduced by
The property Version does not exist on object<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...
200
		$page1->publish('Stage', 'Live', false);
201
		$this->assertEquals($oldVersion, $page1->Version, 'publish() with $createNewVersion=FALSE');
202
203
		$page1->Content = 'changed';
0 ignored issues
show
Documentation introduced by
The property Content does not exist on object<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...
204
		$page1->write();
205
		$oldVersion = $page1->Version;
0 ignored issues
show
Documentation introduced by
The property Version does not exist on object<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...
206
		$page1->publish('Stage', 'Live', true);
207
		$this->assertTrue($oldVersion < $page1->Version, 'publish() with $createNewVersion=TRUE');
208
	}
209
210
	public function testRollbackTo() {
211
		$page1 = $this->objFromFixture('VersionedTest_AnotherSubclass', 'subclass1');
212
		$page1->Content = 'orig';
0 ignored issues
show
Documentation introduced by
The property Content does not exist on object<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...
213
		$page1->write();
214
		$page1->publish('Stage', 'Live');
215
		$origVersion = $page1->Version;
0 ignored issues
show
Documentation introduced by
The property Version does not exist on object<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...
216
217
		$page1->Content = 'changed';
0 ignored issues
show
Documentation introduced by
The property Content does not exist on object<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...
218
		$page1->write();
219
		$page1->publish('Stage', 'Live');
220
		$changedVersion = $page1->Version;
0 ignored issues
show
Documentation introduced by
The property Version does not exist on object<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...
221
222
		$page1->doRollbackTo($origVersion);
223
		$page1 = Versioned::get_one_by_stage('VersionedTest_DataObject', 'Stage',
224
			sprintf('"VersionedTest_DataObject"."ID" = %d', $page1->ID));
225
226
		$this->assertTrue($page1->Version > $changedVersion, 'Create a new higher version number');
227
		$this->assertEquals('orig', $page1->Content, 'Copies the content from the old version');
228
229
		// check db entries
230
		$version = DB::prepared_query("SELECT MAX(\"Version\") FROM \"VersionedTest_DataObject_versions\" WHERE \"RecordID\" = ?",
231
			array($page1->ID)
232
		)->value();
233
		$this->assertEquals($page1->Version, $version, 'Correct entry in VersionedTest_DataObject_versions');
234
235
		$version = DB::prepared_query("SELECT MAX(\"Version\") FROM \"VersionedTest_AnotherSubclass_versions\" WHERE \"RecordID\" = ?",
236
			array($page1->ID)
237
		)->value();
238
		$this->assertEquals($page1->Version, $version, 'Correct entry in VersionedTest_AnotherSubclass_versions');
239
	}
240
241
	public function testDeleteFromStage() {
242
		$page1 = $this->objFromFixture('VersionedTest_DataObject', 'page1');
243
		$pageID = $page1->ID;
244
245
		$page1->Content = 'orig';
0 ignored issues
show
Documentation introduced by
The property Content does not exist on object<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...
246
		$page1->write();
247
		$page1->publish('Stage', 'Live');
248
249
		$this->assertEquals(1,
250
			DB::query('SELECT COUNT(*) FROM "VersionedTest_DataObject" WHERE "ID" = '.$pageID)->value());
251
		$this->assertEquals(1,
252
			DB::query('SELECT COUNT(*) FROM "VersionedTest_DataObject_Live" WHERE "ID" = '.$pageID)->value());
253
254
		$page1->deleteFromStage('Live');
255
256
		// Confirm that deleteFromStage() doesn't manipulate the original record
257
		$this->assertEquals($pageID, $page1->ID);
258
259
		$this->assertEquals(1,
260
			DB::query('SELECT COUNT(*) FROM "VersionedTest_DataObject" WHERE "ID" = '.$pageID)->value());
261
		$this->assertEquals(0,
262
			DB::query('SELECT COUNT(*) FROM "VersionedTest_DataObject_Live" WHERE "ID" = '.$pageID)->value());
263
264
		$page1->delete();
265
266
		$this->assertEquals(0, $page1->ID);
267
		$this->assertEquals(0,
268
			DB::query('SELECT COUNT(*) FROM "VersionedTest_DataObject" WHERE "ID" = '.$pageID)->value());
269
		$this->assertEquals(0,
270
			DB::query('SELECT COUNT(*) FROM "VersionedTest_DataObject_Live" WHERE "ID" = '.$pageID)->value());
271
	}
272
273
	public function testWritingNewToStage() {
274
		$origStage = Versioned::current_stage();
275
276
		Versioned::reading_stage("Stage");
277
		$page = new VersionedTest_DataObject();
278
		$page->Title = "testWritingNewToStage";
0 ignored issues
show
Documentation introduced by
The property Title does not exist on object<VersionedTest_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
		$page->URLSegment = "testWritingNewToStage";
0 ignored issues
show
Documentation introduced by
The property URLSegment does not exist on object<VersionedTest_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
		$page->write();
281
282
		$live = Versioned::get_by_stage('VersionedTest_DataObject', 'Live', array(
283
			'"VersionedTest_DataObject_Live"."ID"' => $page->ID
284
		));
285
		$this->assertEquals(0, $live->count());
286
287
		$stage = Versioned::get_by_stage('VersionedTest_DataObject', 'Stage',array(
288
			'"VersionedTest_DataObject"."ID"' => $page->ID
289
		));
290
		$this->assertEquals(1, $stage->count());
291
		$this->assertEquals($stage->First()->Title, 'testWritingNewToStage');
292
293
		Versioned::reading_stage($origStage);
294
	}
295
296
	/**
297
	 * This tests for the situation described in the ticket #5596.
298
	 * Writing new Page to live first creates a row in VersionedTest_DataObject table (to get the new ID),
299
	 * then "changes it's mind" in Versioned and writes VersionedTest_DataObject_Live. It does not remove
300
	 * the VersionedTest_DataObject record though.
301
	 */
302
	public function testWritingNewToLive() {
303
		$origStage = Versioned::current_stage();
304
305
		Versioned::reading_stage("Live");
306
		$page = new VersionedTest_DataObject();
307
		$page->Title = "testWritingNewToLive";
0 ignored issues
show
Documentation introduced by
The property Title does not exist on object<VersionedTest_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...
308
		$page->URLSegment = "testWritingNewToLive";
0 ignored issues
show
Documentation introduced by
The property URLSegment does not exist on object<VersionedTest_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...
309
		$page->write();
310
311
		$live = Versioned::get_by_stage('VersionedTest_DataObject', 'Live',array(
312
			'"VersionedTest_DataObject_Live"."ID"' => $page->ID
313
		));
314
		$this->assertEquals(1, $live->count());
315
		$this->assertEquals($live->First()->Title, 'testWritingNewToLive');
316
317
		$stage = Versioned::get_by_stage('VersionedTest_DataObject', 'Stage',array(
318
			'"VersionedTest_DataObject"."ID"' => $page->ID
319
		));
320
		$this->assertEquals(0, $stage->count());
321
322
		Versioned::reading_stage($origStage);
323
	}
324
325
	/**
326
	 * Tests DataObject::hasOwnTableDatabaseField
327
	 */
328
	public function testHasOwnTableDatabaseFieldWithVersioned() {
329
		$noversion    = new DataObject();
330
		$versioned    = new VersionedTest_DataObject();
331
		$versionedSub = new VersionedTest_Subclass();
332
		$versionedAno = new VersionedTest_AnotherSubclass();
333
		$versionField = new VersionedTest_UnversionedWithField();
334
335
		$this->assertFalse(
336
			(bool) $noversion->hasOwnTableDatabaseField('Version'),
337
			'Plain models have no version field.'
338
		);
339
		$this->assertEquals(
340
			'Int', $versioned->hasOwnTableDatabaseField('Version'),
341
			'The versioned ext adds an Int version field.'
342
		);
343
		$this->assertEquals(
344
			null,
345
			$versionedSub->hasOwnTableDatabaseField('Version'),
346
			'Sub-classes of a versioned model don\'t have a Version field.'
347
		);
348
		$this->assertEquals(
349
			null,
350
			$versionedAno->hasOwnTableDatabaseField('Version'),
351
			'Sub-classes of a versioned model don\'t have a Version field.'
352
		);
353
		$this->assertEquals(
354
			'Varchar', $versionField->hasOwnTableDatabaseField('Version'),
355
			'Models w/o Versioned can have their own Version field.'
356
		);
357
	}
358
359
	/**
360
	 * Test that SQLQuery::queriedTables() applies the version-suffixes properly.
361
	 */
362
	public function testQueriedTables() {
363
		Versioned::reading_stage('Live');
364
365
		$this->assertEquals(array(
366
			'VersionedTest_DataObject_Live',
367
			'VersionedTest_Subclass_Live',
368
		), DataObject::get('VersionedTest_Subclass')->dataQuery()->query()->queriedTables());
369
	}
370
371
	public function testGetVersionWhenClassnameChanged() {
372
		$obj = new VersionedTest_DataObject;
373
		$obj->Name = "test";
0 ignored issues
show
Documentation introduced by
The property Name does not exist on object<VersionedTest_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...
374
		$obj->write();
375
		$obj->Name = "test2";
0 ignored issues
show
Documentation introduced by
The property Name does not exist on object<VersionedTest_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...
376
		$obj->ClassName = "VersionedTest_Subclass";
377
		$obj->write();
378
		$subclassVersion = $obj->Version;
0 ignored issues
show
Documentation introduced by
The property Version does not exist on object<VersionedTest_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...
379
380
		$obj->Name = "test3";
0 ignored issues
show
Documentation introduced by
The property Name does not exist on object<VersionedTest_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...
381
		$obj->ClassName = "VersionedTest_DataObject";
382
		$obj->write();
383
384
		// We should be able to pass the subclass and still get the correct class back
385
		$obj2 = Versioned::get_version("VersionedTest_Subclass", $obj->ID, $subclassVersion);
386
		$this->assertInstanceOf("VersionedTest_Subclass", $obj2);
387
		$this->assertEquals("test2", $obj2->Name);
388
389
		$obj3 = Versioned::get_latest_version("VersionedTest_Subclass", $obj->ID);
390
		$this->assertEquals("test3", $obj3->Name);
391
		$this->assertInstanceOf("VersionedTest_DataObject", $obj3);
392
393
	}
394
395
	public function testArchiveVersion() {
396
397
		// In 2005 this file was created
398
		SS_Datetime::set_mock_now('2005-01-01 00:00:00');
399
		$testPage = new VersionedTest_Subclass();
400
		$testPage->Title = 'Archived page';
0 ignored issues
show
Documentation introduced by
The property Title does not exist on object<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...
401
		$testPage->Content = 'This is the content from 2005';
0 ignored issues
show
Documentation introduced by
The property Content does not exist on object<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...
402
		$testPage->ExtraField = '2005';
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...
403
		$testPage->write();
404
405
		// In 2007 we updated it
406
		SS_Datetime::set_mock_now('2007-01-01 00:00:00');
407
		$testPage->Content = "It's 2007 already!";
0 ignored issues
show
Documentation introduced by
The property Content does not exist on object<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...
408
		$testPage->ExtraField = '2007';
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...
409
		$testPage->write();
410
411
		// In 2009 we updated it again
412
		SS_Datetime::set_mock_now('2009-01-01 00:00:00');
413
		$testPage->Content = "I'm enjoying 2009";
0 ignored issues
show
Documentation introduced by
The property Content does not exist on object<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...
414
		$testPage->ExtraField = '2009';
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...
415
		$testPage->write();
416
417
		// End mock, back to the present day:)
418
		SS_Datetime::clear_mock_now();
419
420
		// Test 1 - 2006 Content
421
		singleton('VersionedTest_Subclass')->flushCache(true);
422
		Versioned::set_reading_mode('Archive.2006-01-01 00:00:00');
423
		$testPage2006 = DataObject::get('VersionedTest_Subclass')->filter(array('Title' => 'Archived page'))->first();
424
		$this->assertInstanceOf("VersionedTest_Subclass", $testPage2006);
425
		$this->assertEquals("2005", $testPage2006->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...
426
		$this->assertEquals("This is the content from 2005", $testPage2006->Content);
427
428
		// Test 2 - 2008 Content
429
		singleton('VersionedTest_Subclass')->flushCache(true);
430
		Versioned::set_reading_mode('Archive.2008-01-01 00:00:00');
431
		$testPage2008 = DataObject::get('VersionedTest_Subclass')->filter(array('Title' => 'Archived page'))->first();
432
		$this->assertInstanceOf("VersionedTest_Subclass", $testPage2008);
433
		$this->assertEquals("2007", $testPage2008->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...
434
		$this->assertEquals("It's 2007 already!", $testPage2008->Content);
435
436
		// Test 3 - Today
437
		singleton('VersionedTest_Subclass')->flushCache(true);
438
		Versioned::set_reading_mode('Stage.Stage');
439
		$testPageCurrent = DataObject::get('VersionedTest_Subclass')->filter(array('Title' => 'Archived page'))
440
			->first();
441
		$this->assertInstanceOf("VersionedTest_Subclass", $testPageCurrent);
442
		$this->assertEquals("2009", $testPageCurrent->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...
443
		$this->assertEquals("I'm enjoying 2009", $testPageCurrent->Content);
444
	}
445
446
	public function testAllVersions()
447
	{
448
		// In 2005 this file was created
449
		SS_Datetime::set_mock_now('2005-01-01 00:00:00');
450
		$testPage = new VersionedTest_Subclass();
451
		$testPage->Title = 'Archived page';
0 ignored issues
show
Documentation introduced by
The property Title does not exist on object<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...
452
		$testPage->Content = 'This is the content from 2005';
0 ignored issues
show
Documentation introduced by
The property Content does not exist on object<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...
453
		$testPage->ExtraField = '2005';
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...
454
		$testPage->write();
455
456
		// In 2007 we updated it
457
		SS_Datetime::set_mock_now('2007-01-01 00:00:00');
458
		$testPage->Content = "It's 2007 already!";
0 ignored issues
show
Documentation introduced by
The property Content does not exist on object<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...
459
		$testPage->ExtraField = '2007';
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...
460
		$testPage->write();
461
462
		// Check both versions are returned
463
		$versions = Versioned::get_all_versions('VersionedTest_Subclass', $testPage->ID);
464
		$content = array();
465
		$extraFields = array();
466
		foreach($versions as $version)
467
		{
468
			$content[] = $version->Content;
469
			$extraFields[] = $version->ExtraField;
470
		}
471
472
		$this->assertEquals($versions->Count(), 2, 'All versions returned');
473
		$this->assertEquals($content, array('This is the content from 2005', "It's 2007 already!"),
474
			'Version fields returned');
475
		$this->assertEquals($extraFields, array('2005', '2007'), 'Version fields returned');
476
477
		// In 2009 we updated it again
478
		SS_Datetime::set_mock_now('2009-01-01 00:00:00');
479
		$testPage->Content = "I'm enjoying 2009";
0 ignored issues
show
Documentation introduced by
The property Content does not exist on object<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...
480
		$testPage->ExtraField = '2009';
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...
481
		$testPage->write();
482
483
		// End mock, back to the present day:)
484
		SS_Datetime::clear_mock_now();
485
486
		$versions = Versioned::get_all_versions('VersionedTest_Subclass', $testPage->ID);
487
		$content = array();
488
		$extraFields = array();
489
		foreach($versions as $version)
490
		{
491
			$content[] = $version->Content;
492
			$extraFields[] = $version->ExtraField;
493
		}
494
495
		$this->assertEquals($versions->Count(), 3, 'Additional all versions returned');
496
		$this->assertEquals($content,
497
			array('This is the content from 2005', "It's 2007 already!", "I'm enjoying 2009"),
498
			'Additional version fields returned');
499
		$this->assertEquals($extraFields, array('2005', '2007', '2009'), 'Additional version fields returned');
500
	}
501
502
	public function testArchiveRelatedDataWithoutVersioned() {
503
		SS_Datetime::set_mock_now('2009-01-01 00:00:00');
504
505
		$relatedData = new VersionedTest_RelatedWithoutVersion();
506
		$relatedData->Name = 'Related Data';
0 ignored issues
show
Documentation introduced by
The property Name does not exist on object<VersionedTest_RelatedWithoutVersion>. 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...
507
		$relatedDataId = $relatedData->write();
508
509
		$testData = new VersionedTest_DataObject();
510
		$testData->Title = 'Test';
0 ignored issues
show
Documentation introduced by
The property Title does not exist on object<VersionedTest_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...
511
		$testData->Content = 'Before Content';
0 ignored issues
show
Documentation introduced by
The property Content does not exist on object<VersionedTest_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...
512
		$testData->Related()->add($relatedData);
513
		$id = $testData->write();
514
515
		SS_Datetime::set_mock_now('2010-01-01 00:00:00');
516
		$testData->Content = 'After Content';
0 ignored issues
show
Documentation introduced by
The property Content does not exist on object<VersionedTest_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...
517
		$testData->write();
518
519
		Versioned::reading_archived_date('2009-01-01 19:00:00');
520
521
		$fetchedData = VersionedTest_DataObject::get()->byId($id);
522
		$this->assertEquals('Before Content', $fetchedData->Content, 'We see the correct content of the older version');
523
524
		$relatedData = VersionedTest_RelatedWithoutVersion::get()->byId($relatedDataId);
525
		$this->assertEquals(
526
			1,
527
			$relatedData->Related()->count(),
528
			'We have a relation, with no version table, querying it still works'
529
		);
530
	}
531
532
	public function testVersionedWithSingleStage() {
533
		$tables = DB::table_list();
534
		$this->assertContains(
535
			'versionedtest_singlestage',
536
			array_keys($tables),
537
			'Contains base table'
538
		);
539
		$this->assertContains(
540
			'versionedtest_singlestage_versions',
541
			array_keys($tables),
542
			'Contains versions table'
543
		);
544
		$this->assertNotContains(
545
			'versionedtest_singlestage_live',
546
			array_keys($tables),
547
			'Does not contain separate table with _Live suffix'
548
		);
549
		$this->assertNotContains(
550
			'versionedtest_singlestage_stage',
551
			array_keys($tables),
552
			'Does not contain separate table with _Stage suffix'
553
		);
554
555
		Versioned::reading_stage("Stage");
556
		$obj = new VersionedTest_SingleStage(array('Name' => 'MyObj'));
557
		$obj->write();
558
		$this->assertNotNull(
559
			VersionedTest_SingleStage::get()->byID($obj->ID),
560
			'Writes to and reads from default stage if its set explicitly'
561
		);
562
563
		Versioned::reading_stage("Live");
564
		$obj = new VersionedTest_SingleStage(array('Name' => 'MyObj'));
565
		$obj->write();
566
		$this->assertNotNull(
567
			VersionedTest_SingleStage::get()->byID($obj->ID),
568
			'Writes to and reads from default stage even if a non-matching stage is set'
569
		);
570
	}
571
572
	/**
573
	 * Test that publishing processes respects lazy loaded fields
574
	 */
575
	public function testLazyLoadFields() {
576
		$originalMode = Versioned::get_reading_mode();
577
578
		// Generate staging record and retrieve it from stage in live mode
579
		Versioned::reading_stage('Stage');
580
		$obj = new VersionedTest_Subclass();
581
		$obj->Name = 'bob';
0 ignored issues
show
Documentation introduced by
The property Name does not exist on object<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...
582
		$obj->ExtraField = 'Field 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...
583
		$obj->write();
584
		$objID = $obj->ID;
585
		$filter = sprintf('"VersionedTest_DataObject"."ID" = \'%d\'', Convert::raw2sql($objID));
586
		Versioned::reading_stage('Live');
587
588
		// Check fields are unloaded prior to access
589
		$objLazy = Versioned::get_one_by_stage('VersionedTest_DataObject', 'Stage', $filter, false);
590
		$lazyFields = $objLazy->getQueriedDatabaseFields();
591
		$this->assertTrue(isset($lazyFields['ExtraField_Lazy']));
592
		$this->assertEquals('VersionedTest_Subclass', $lazyFields['ExtraField_Lazy']);
593
594
		// Check lazy loading works when viewing a Stage object in Live mode
595
		$this->assertEquals('Field Value', $objLazy->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...
596
597
		// Test that writeToStage respects lazy loaded fields
598
		$objLazy = Versioned::get_one_by_stage('VersionedTest_DataObject', 'Stage', $filter, false);
599
		$objLazy->writeToStage('Live');
600
		$objLive = Versioned::get_one_by_stage('VersionedTest_DataObject', 'Live', $filter, false);
601
		$liveLazyFields = $objLive->getQueriedDatabaseFields();
602
603
		// Check fields are unloaded prior to access
604
		$this->assertTrue(isset($liveLazyFields['ExtraField_Lazy']));
605
		$this->assertEquals('VersionedTest_Subclass', $liveLazyFields['ExtraField_Lazy']);
606
607
		// Check that live record has original value
608
		$this->assertEquals('Field Value', $objLive->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...
609
610
		Versioned::set_reading_mode($originalMode);
611
	}
612
613
	/**
614
	 * Tests that reading mode persists between requests
615
	 */
616
	public function testReadingPersistent() {
617
		$session = Injector::inst()->create('Session', array());
618
619
		// Set to stage
620
		Director::test('/?stage=Stage', null, $session);
621
		$this->assertEquals(
622
			'Stage.Stage',
623
			$session->inst_get('readingMode'),
624
			'Check querystring changes reading mode to Stage'
625
		);
626
		Director::test('/', null, $session);
627
		$this->assertEquals(
628
			'Stage.Stage',
629
			$session->inst_get('readingMode'),
630
			'Check that subsequent requests in the same session remain in Stage mode'
631
		);
632
633
		// Test live persists
634
		Director::test('/?stage=Live', null, $session);
635
		$this->assertEquals(
636
			'Stage.Live',
637
			$session->inst_get('readingMode'),
638
			'Check querystring changes reading mode to Live'
639
		);
640
		Director::test('/', null, $session);
641
		$this->assertEquals(
642
			'Stage.Live',
643
			$session->inst_get('readingMode'),
644
			'Check that subsequent requests in the same session remain in Live mode'
645
		);
646
647
		// Test that session doesn't redundantly store the default stage if it doesn't need to
648
		$session2 = Injector::inst()->create('Session', array());
649
		Director::test('/', null, $session2);
650
		$this->assertEmpty($session2->inst_changedData());
651
		Director::test('/?stage=Live', null, $session2);
652
		$this->assertEmpty($session2->inst_changedData());
653
654
		// Test choose_site_stage
655
		Session::set('readingMode', 'Stage.Stage');
656
		Versioned::choose_site_stage();
657
		$this->assertEquals('Stage.Stage', Versioned::get_reading_mode());
658
		Session::set('readingMode', 'Archive.2014-01-01');
659
		Versioned::choose_site_stage();
660
		$this->assertEquals('Archive.2014-01-01', Versioned::get_reading_mode());
661
		Session::clear('readingMode');
662
		Versioned::choose_site_stage();
663
		$this->assertEquals('Stage.Live', Versioned::get_reading_mode());
664
	}
665
666
	/**
667
	 * Ensures that the latest version of a record is the expected value
668
	 *
669
	 * @param type $record
670
	 * @param type $version
671
	 */
672
	protected function assertRecordHasLatestVersion($record, $version) {
673
		foreach(ClassInfo::ancestry(get_class($record), true) as $table) {
674
			$versionForClass = DB::prepared_query(
675
				$sql = "SELECT MAX(\"Version\") FROM \"{$table}_versions\" WHERE \"RecordID\" = ?",
676
				array($record->ID)
677
			)->value();
678
			$this->assertEquals($version, $versionForClass, "That the table $table has the latest version $version");
679
		}
680
	}
681
682
	/**
683
	 * Tests that multi-table dataobjects are correctly versioned
684
	 */
685
	public function testWriteToStage() {
686
		// Test subclass with versioned extension directly added
687
		$record = VersionedTest_Subclass::create();
688
		$record->Title = "Test A";
0 ignored issues
show
Documentation introduced by
The property Title does not exist on object<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...
689
		$record->ExtraField = "Test A";
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...
690
		$record->writeToStage("Stage");
691
		$this->assertRecordHasLatestVersion($record, 1);
692
		$record->publish("Stage", "Live");
693
		$this->assertRecordHasLatestVersion($record, 1);
694
		$record->Title = "Test A2";
0 ignored issues
show
Documentation introduced by
The property Title does not exist on object<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...
695
		$record->ExtraField = "Test A2";
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...
696
		$record->writeToStage("Stage");
697
		$this->assertRecordHasLatestVersion($record, 2);
698
699
		// Test subclass without changes to base class
700
		$record = VersionedTest_Subclass::create();
701
		$record->ExtraField = "Test B";
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...
702
		$record->writeToStage("Stage");
703
		$this->assertRecordHasLatestVersion($record, 1);
704
		$record->publish("Stage", "Live");
705
		$this->assertRecordHasLatestVersion($record, 1);
706
		$record->ExtraField = "Test B2";
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...
707
		$record->writeToStage("Stage");
708
		$this->assertRecordHasLatestVersion($record, 2);
709
710
		// Test subclass without changes to sub class
711
		$record = VersionedTest_Subclass::create();
712
		$record->Title = "Test C";
0 ignored issues
show
Documentation introduced by
The property Title does not exist on object<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...
713
		$record->writeToStage("Stage");
714
		$this->assertRecordHasLatestVersion($record, 1);
715
		$record->publish("Stage", "Live");
716
		$this->assertRecordHasLatestVersion($record, 1);
717
		$record->Title = "Test C2";
0 ignored issues
show
Documentation introduced by
The property Title does not exist on object<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...
718
		$record->writeToStage("Stage");
719
		$this->assertRecordHasLatestVersion($record, 2);
720
721
		// Test subclass with versioned extension only added to the base clases
722
		$record = VersionedTest_AnotherSubclass::create();
723
		$record->Title = "Test A";
0 ignored issues
show
Documentation introduced by
The property Title does not exist on object<VersionedTest_AnotherSubclass>. 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...
724
		$record->AnotherField = "Test A";
0 ignored issues
show
Documentation introduced by
The property AnotherField does not exist on object<VersionedTest_AnotherSubclass>. 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...
725
		$record->writeToStage("Stage");
726
		$this->assertRecordHasLatestVersion($record, 1);
727
		$record->publish("Stage", "Live");
728
		$this->assertRecordHasLatestVersion($record, 1);
729
		$record->Title = "Test A2";
0 ignored issues
show
Documentation introduced by
The property Title does not exist on object<VersionedTest_AnotherSubclass>. 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...
730
		$record->AnotherField = "Test A2";
0 ignored issues
show
Documentation introduced by
The property AnotherField does not exist on object<VersionedTest_AnotherSubclass>. 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...
731
		$record->writeToStage("Stage");
732
		$this->assertRecordHasLatestVersion($record, 2);
733
734
735
		// Test subclass without changes to base class
736
		$record = VersionedTest_AnotherSubclass::create();
737
		$record->AnotherField = "Test B";
0 ignored issues
show
Documentation introduced by
The property AnotherField does not exist on object<VersionedTest_AnotherSubclass>. 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...
738
		$record->writeToStage("Stage");
739
		$this->assertRecordHasLatestVersion($record, 1);
740
		$record->publish("Stage", "Live");
741
		$this->assertRecordHasLatestVersion($record, 1);
742
		$record->AnotherField = "Test B2";
0 ignored issues
show
Documentation introduced by
The property AnotherField does not exist on object<VersionedTest_AnotherSubclass>. 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...
743
		$record->writeToStage("Stage");
744
		$this->assertRecordHasLatestVersion($record, 2);
745
746
		// Test subclass without changes to sub class
747
		$record = VersionedTest_AnotherSubclass::create();
748
		$record->Title = "Test C";
0 ignored issues
show
Documentation introduced by
The property Title does not exist on object<VersionedTest_AnotherSubclass>. 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...
749
		$record->writeToStage("Stage");
750
		$this->assertRecordHasLatestVersion($record, 1);
751
		$record->publish("Stage", "Live");
752
		$this->assertRecordHasLatestVersion($record, 1);
753
		$record->Title = "Test C2";
0 ignored issues
show
Documentation introduced by
The property Title does not exist on object<VersionedTest_AnotherSubclass>. 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...
754
		$record->writeToStage("Stage");
755
		$this->assertRecordHasLatestVersion($record, 2);
756
	}
757
758
	public function testVersionedHandlesRenamedDataObjectFields(){
759
		Config::inst()->remove('VersionedTest_RelatedWithoutVersion','db','Name','Varchar');
760
761
		Config::inst()->update('VersionedTest_RelatedWithoutVersion','db',array(
762
			"NewField" => "Varchar",
763
		));
764
765
		VersionedTest_RelatedWithoutVersion::add_extension("Versioned('Stage', 'Live')");
766
		$this->resetDBSchema(true);
767
		$testData = new VersionedTest_RelatedWithoutVersion();
768
		$testData->NewField = 'Test';
0 ignored issues
show
Documentation introduced by
The property NewField does not exist on object<VersionedTest_RelatedWithoutVersion>. 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...
769
		$testData->write();
770
	}
771
}
772
773
774
/**
775
 * @package framework
776
 * @subpackage tests
777
 */
778
class VersionedTest_DataObject extends DataObject implements TestOnly {
779
	private static $db = array(
780
		"Name" => "Varchar",
781
		'Title' => 'Varchar',
782
		'Content' => 'HTMLText'
783
	);
784
785
	private static $extensions = array(
786
		"Versioned('Stage', 'Live')"
787
	);
788
789
	private static $has_one = array(
790
		'Parent' => 'VersionedTest_DataObject'
791
	);
792
793
	private static $many_many = array(
794
		'Related' => 'VersionedTest_RelatedWithoutVersion'
795
	);
796
797
}
798
799
class VersionedTest_WithIndexes extends DataObject implements TestOnly {
800
801
	private static $db = array(
802
		'UniqA' => 'Int',
803
		'UniqS' => 'Int',
804
	);
805
	private static $extensions = array(
806
		"Versioned('Stage', 'Live')"
807
	);
808
	private static $indexes = array(
809
		'UniqS_idx' => 'unique ("UniqS")',
810
		'UniqA_idx' => array('type' => 'unique', 'name' => 'UniqA_idx', 'value' => '"UniqA"',),
811
	);
812
813
}
814
815
/**
816
 * @package framework
817
 * @subpackage tests
818
 */
819
class VersionedTest_RelatedWithoutVersion extends DataObject implements TestOnly {
820
821
	private static $db = array(
822
		'Name' => 'Varchar'
823
	);
824
825
	private static $belongs_many_many = array(
826
		'Related' => 'VersionedTest_DataObject'
827
	);
828
829
}
830
831
/**
832
 * @package framework
833
 * @subpackage tests
834
 */
835
class VersionedTest_Subclass extends VersionedTest_DataObject implements TestOnly {
836
	private static $db = array(
837
		"ExtraField" => "Varchar",
838
	);
839
}
840
841
/**
842
 * @package framework
843
 * @subpackage tests
844
 */
845
class VersionedTest_AnotherSubclass extends VersionedTest_DataObject implements TestOnly {
846
	private static $db = array(
847
		"AnotherField" => "Varchar"
848
	);
849
}
850
851
/**
852
 * @package framework
853
 * @subpackage tests
854
 */
855
class VersionedTest_UnversionedWithField extends DataObject implements TestOnly {
856
	private static $db = array('Version' => 'Varchar(255)');
857
}
858
859
class VersionedTest_SingleStage extends DataObject implements TestOnly {
860
	private static $db = array(
861
		'Name' => 'Varchar'
862
	);
863
864
	private static $extensions = array(
865
		'Versioned("Stage")'
866
	);
867
}
868