Completed
Push — master ( 75905b...69c9ad )
by Damian
14:56 queued 02:22
created

VersionedTest::testRollbackTo()   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
		'VersionedTest_PublicStage',
19
		'VersionedTest_PublicViaExtension',
20
	);
21
22
	protected $requiredExtensions = array(
23
		"VersionedTest_DataObject" => array('Versioned'),
24
		"VersionedTest_WithIndexes" => array('Versioned'),
25
	);
26
27
	public function testUniqueIndexes() {
28
		$tableExpectations = array(
29
			'VersionedTest_WithIndexes' =>
30
				array('value' => true, 'message' => 'Unique indexes are unique in main table'),
31
			'VersionedTest_WithIndexes_versions' =>
32
				array('value' => false, 'message' => 'Unique indexes are no longer unique in _versions table'),
33
			'VersionedTest_WithIndexes_Live' =>
34
				array('value' => false, 'message' => 'Unique indexes are no longer unique in _Live table'),
35
		);
36
37
		// Test each table's performance
38
		foreach ($tableExpectations as $tableName => $expectation) {
39
			$indexes = DB::get_schema()->indexList($tableName);
40
41
			// Check for presence of all unique indexes
42
			$indexColumns = array_map(function($index) {
43
				return $index['value'];
44
			}, $indexes);
45
			sort($indexColumns);
46
			$expectedColumns = array('"UniqA"', '"UniqS"');
47
			$this->assertEquals(
48
					array_values($expectedColumns),
49
					array_values(array_intersect($indexColumns, $expectedColumns)),
50
					"$tableName has both indexes");
51
52
			// Check unique -> non-unique conversion
53
			foreach ($indexes as $indexKey => $indexSpec) {
54
				if (in_array($indexSpec['value'], $expectedColumns)) {
55
					$isUnique = $indexSpec['type'] === 'unique';
56
					$this->assertEquals($isUnique, $expectation['value'], $expectation['message']);
57
}
58
			}
59
		}
60
	}
61
62
	public function testDeletingOrphanedVersions() {
63
		$obj = new VersionedTest_Subclass();
64
		$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...
65
		$obj->write();
66
		$obj->publish('Stage', 'Live');
67
68
		$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...
69
		$obj->write();
70
		$obj->publish('Stage', 'Live');
71
72
		$versions = DB::query("SELECT COUNT(*) FROM \"VersionedTest_Subclass_versions\""
73
			. " WHERE \"RecordID\" = '$obj->ID'")->value();
74
75
		$this->assertGreaterThan(0, $versions, 'At least 1 version exists in the history of the page');
76
77
		// Force orphaning of all versions created earlier, only on parent record.
78
		// The child versiones table should still have the correct relationship
79
		DB::query("DELETE FROM \"VersionedTest_DataObject_versions\" WHERE \"RecordID\" = $obj->ID");
80
81
		// insert a record with no primary key (ID)
82
		DB::query("INSERT INTO \"VersionedTest_DataObject_versions\" (\"RecordID\") VALUES ($obj->ID)");
83
84
		// run the script which should clean that up
85
		$obj->augmentDatabase();
86
87
		$versions = DB::query("SELECT COUNT(*) FROM \"VersionedTest_Subclass_versions\""
88
			. " WHERE \"RecordID\" = '$obj->ID'")->value();
89
		$this->assertEquals(0, $versions, 'Orphaned versions on child tables are removed');
90
91
		// test that it doesn't delete records that we need
92
		$obj->write();
93
		$obj->publish('Stage', 'Live');
94
95
		$count = DB::query("SELECT COUNT(*) FROM \"VersionedTest_Subclass_versions\""
96
			. " WHERE \"RecordID\" = '$obj->ID'")->value();
97
		$obj->augmentDatabase();
98
99
		$count2 = DB::query("SELECT COUNT(*) FROM \"VersionedTest_Subclass_versions\""
100
			. " WHERE \"RecordID\" = '$obj->ID'")->value();
101
102
		$this->assertEquals($count, $count2);
103
	}
104
105
	public function testDuplicate() {
106
		$obj1 = new VersionedTest_Subclass();
107
		$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...
108
		$obj1->write(); // version 1
109
		$obj1->publish('Stage', 'Live');
110
		$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...
111
		$obj1->write(); // version 2
112
113
		// Make duplicate
114
		$obj2 = $obj1->duplicate();
115
116
		// Check records differ
117
		$this->assertNotEquals($obj1->ID, $obj2->ID);
118
		$this->assertEquals(2, $obj1->Version);
119
		$this->assertEquals(1, $obj2->Version);
120
	}
121
122
	public function testForceChangeUpdatesVersion() {
123
		$obj = new VersionedTest_DataObject();
124
		$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...
125
		$obj->write();
126
127
		$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...
128
		$obj->forceChange();
129
		$obj->write();
130
131
		$this->assertTrue(
132
			($obj->Version > $oldVersion),
133
			"A object Version is increased when just calling forceChange() without any other changes"
134
		);
135
	}
136
137
	/**
138
	 * Test Versioned::get_including_deleted()
139
	 */
140
	public function testGetIncludingDeleted() {
141
		// Get all ids of pages
142
		$allPageIDs = DataObject::get(
143
			'VersionedTest_DataObject',
144
			"\"ParentID\" = 0", "\"VersionedTest_DataObject\".\"ID\" ASC"
145
		)->column('ID');
146
147
		// Modify a page, ensuring that the Version ID and Record ID will differ,
148
		// and then subsequently delete it
149
		$targetPage = $this->objFromFixture('VersionedTest_DataObject', 'page3');
150
		$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...
151
		$targetPage->write();
152
		$targetPage->delete();
153
154
		// Get all items, ignoring deleted
155
		$remainingPages = DataObject::get("VersionedTest_DataObject", "\"ParentID\" = 0",
156
			"\"VersionedTest_DataObject\".\"ID\" ASC");
157
		// Check that page 3 has gone
158
		$this->assertNotNull($remainingPages);
159
		$this->assertEquals(array("Page 1", "Page 2", "Subclass Page 1"), $remainingPages->column('Title'));
160
161
		// Get all including deleted
162
		$allPages = Versioned::get_including_deleted("VersionedTest_DataObject", "\"ParentID\" = 0",
163
			"\"VersionedTest_DataObject\".\"ID\" ASC");
164
		// Check that page 3 is still there
165
		$this->assertEquals(array("Page 1", "Page 2", "Page 3", "Subclass Page 1"), $allPages->column('Title'));
166
167
		// Check that the returned pages have the correct IDs
168
		$this->assertEquals($allPageIDs, $allPages->column('ID'));
169
170
		// Check that this still works if we switch to reading the other stage
171
		Versioned::reading_stage("Live");
172
		$allPages = Versioned::get_including_deleted("VersionedTest_DataObject", "\"ParentID\" = 0",
173
			"\"VersionedTest_DataObject\".\"ID\" ASC");
174
		$this->assertEquals(array("Page 1", "Page 2", "Page 3", "Subclass Page 1"), $allPages->column('Title'));
175
176
		// Check that the returned pages still have the correct IDs
177
		$this->assertEquals($allPageIDs, $allPages->column('ID'));
178
	}
179
180
	public function testVersionedFieldsAdded() {
181
		$obj = new VersionedTest_DataObject();
182
		// Check that the Version column is added as a full-fledged column
183
		$this->assertInstanceOf('Int', $obj->dbObject('Version'));
184
185
		$obj2 = new VersionedTest_Subclass();
186
		// Check that the Version column is added as a full-fledged column
187
		$this->assertInstanceOf('Int', $obj2->dbObject('Version'));
188
	}
189
190
	public function testVersionedFieldsNotInCMS() {
191
		$obj = new VersionedTest_DataObject();
192
193
		// the version field in cms causes issues with Versioned::augmentWrite()
194
		$this->assertNull($obj->getCMSFields()->dataFieldByName('Version'));
195
	}
196
197
	public function testPublishCreateNewVersion() {
198
		$page1 = $this->objFromFixture('VersionedTest_DataObject', 'page1');
199
		$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...
200
		$page1->write();
201
		$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...
202
		$page1->publish('Stage', 'Live', false);
203
		$this->assertEquals($oldVersion, $page1->Version, 'publish() with $createNewVersion=FALSE');
204
205
		$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...
206
		$page1->write();
207
		$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...
208
		$page1->publish('Stage', 'Live', true);
209
		$this->assertTrue($oldVersion < $page1->Version, 'publish() with $createNewVersion=TRUE');
210
	}
211
212
	public function testRollbackTo() {
213
		$page1 = $this->objFromFixture('VersionedTest_AnotherSubclass', 'subclass1');
214
		$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...
215
		$page1->write();
216
		$page1->publish('Stage', 'Live');
217
		$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...
218
219
		$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...
220
		$page1->write();
221
		$page1->publish('Stage', 'Live');
222
		$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...
223
224
		$page1->doRollbackTo($origVersion);
225
		$page1 = Versioned::get_one_by_stage('VersionedTest_DataObject', 'Stage',
226
			sprintf('"VersionedTest_DataObject"."ID" = %d', $page1->ID));
227
228
		$this->assertTrue($page1->Version > $changedVersion, 'Create a new higher version number');
229
		$this->assertEquals('orig', $page1->Content, 'Copies the content from the old version');
230
231
		// check db entries
232
		$version = DB::prepared_query("SELECT MAX(\"Version\") FROM \"VersionedTest_DataObject_versions\" WHERE \"RecordID\" = ?",
233
			array($page1->ID)
234
		)->value();
235
		$this->assertEquals($page1->Version, $version, 'Correct entry in VersionedTest_DataObject_versions');
236
237
		$version = DB::prepared_query("SELECT MAX(\"Version\") FROM \"VersionedTest_AnotherSubclass_versions\" WHERE \"RecordID\" = ?",
238
			array($page1->ID)
239
		)->value();
240
		$this->assertEquals($page1->Version, $version, 'Correct entry in VersionedTest_AnotherSubclass_versions');
241
	}
242
243
	public function testDeleteFromStage() {
244
		$page1 = $this->objFromFixture('VersionedTest_DataObject', 'page1');
245
		$pageID = $page1->ID;
246
247
		$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...
248
		$page1->write();
249
		$page1->publish('Stage', 'Live');
250
251
		$this->assertEquals(1,
252
			DB::query('SELECT COUNT(*) FROM "VersionedTest_DataObject" WHERE "ID" = '.$pageID)->value());
253
		$this->assertEquals(1,
254
			DB::query('SELECT COUNT(*) FROM "VersionedTest_DataObject_Live" WHERE "ID" = '.$pageID)->value());
255
256
		$page1->deleteFromStage('Live');
257
258
		// Confirm that deleteFromStage() doesn't manipulate the original record
259
		$this->assertEquals($pageID, $page1->ID);
260
261
		$this->assertEquals(1,
262
			DB::query('SELECT COUNT(*) FROM "VersionedTest_DataObject" WHERE "ID" = '.$pageID)->value());
263
		$this->assertEquals(0,
264
			DB::query('SELECT COUNT(*) FROM "VersionedTest_DataObject_Live" WHERE "ID" = '.$pageID)->value());
265
266
		$page1->delete();
267
268
		$this->assertEquals(0, $page1->ID);
269
		$this->assertEquals(0,
270
			DB::query('SELECT COUNT(*) FROM "VersionedTest_DataObject" WHERE "ID" = '.$pageID)->value());
271
		$this->assertEquals(0,
272
			DB::query('SELECT COUNT(*) FROM "VersionedTest_DataObject_Live" WHERE "ID" = '.$pageID)->value());
273
	}
274
275
	public function testWritingNewToStage() {
276
		$origStage = Versioned::current_stage();
277
278
		Versioned::reading_stage("Stage");
279
		$page = new VersionedTest_DataObject();
280
		$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...
281
		$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...
282
		$page->write();
283
284
		$live = Versioned::get_by_stage('VersionedTest_DataObject', 'Live', array(
285
			'"VersionedTest_DataObject_Live"."ID"' => $page->ID
286
		));
287
		$this->assertEquals(0, $live->count());
288
289
		$stage = Versioned::get_by_stage('VersionedTest_DataObject', 'Stage',array(
290
			'"VersionedTest_DataObject"."ID"' => $page->ID
291
		));
292
		$this->assertEquals(1, $stage->count());
293
		$this->assertEquals($stage->First()->Title, 'testWritingNewToStage');
294
295
		Versioned::reading_stage($origStage);
296
	}
297
298
	/**
299
	 * This tests for the situation described in the ticket #5596.
300
	 * Writing new Page to live first creates a row in VersionedTest_DataObject table (to get the new ID),
301
	 * then "changes it's mind" in Versioned and writes VersionedTest_DataObject_Live. It does not remove
302
	 * the VersionedTest_DataObject record though.
303
	 */
304
	public function testWritingNewToLive() {
305
		$origStage = Versioned::current_stage();
306
307
		Versioned::reading_stage("Live");
308
		$page = new VersionedTest_DataObject();
309
		$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...
310
		$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...
311
		$page->write();
312
313
		$live = Versioned::get_by_stage('VersionedTest_DataObject', 'Live',array(
314
			'"VersionedTest_DataObject_Live"."ID"' => $page->ID
315
		));
316
		$this->assertEquals(1, $live->count());
317
		$this->assertEquals($live->First()->Title, 'testWritingNewToLive');
318
319
		$stage = Versioned::get_by_stage('VersionedTest_DataObject', 'Stage',array(
320
			'"VersionedTest_DataObject"."ID"' => $page->ID
321
		));
322
		$this->assertEquals(0, $stage->count());
323
324
		Versioned::reading_stage($origStage);
325
	}
326
327
	/**
328
	 * Tests DataObject::hasOwnTableDatabaseField
329
	 */
330
	public function testHasOwnTableDatabaseFieldWithVersioned() {
331
		$noversion    = new DataObject();
332
		$versioned    = new VersionedTest_DataObject();
333
		$versionedSub = new VersionedTest_Subclass();
334
		$versionedAno = new VersionedTest_AnotherSubclass();
335
		$versionField = new VersionedTest_UnversionedWithField();
336
337
		$this->assertFalse(
338
			(bool) $noversion->hasOwnTableDatabaseField('Version'),
339
			'Plain models have no version field.'
340
		);
341
		$this->assertEquals(
342
			'Int', $versioned->hasOwnTableDatabaseField('Version'),
343
			'The versioned ext adds an Int version field.'
344
		);
345
		$this->assertEquals(
346
			null,
347
			$versionedSub->hasOwnTableDatabaseField('Version'),
348
			'Sub-classes of a versioned model don\'t have a Version field.'
349
		);
350
		$this->assertEquals(
351
			null,
352
			$versionedAno->hasOwnTableDatabaseField('Version'),
353
			'Sub-classes of a versioned model don\'t have a Version field.'
354
		);
355
		$this->assertEquals(
356
			'Varchar', $versionField->hasOwnTableDatabaseField('Version'),
357
			'Models w/o Versioned can have their own Version field.'
358
		);
359
	}
360
361
	/**
362
	 * Test that SQLSelect::queriedTables() applies the version-suffixes properly.
363
	 */
364
	public function testQueriedTables() {
365
		Versioned::reading_stage('Live');
366
367
		$this->assertEquals(array(
368
			'VersionedTest_DataObject_Live',
369
			'VersionedTest_Subclass_Live',
370
		), DataObject::get('VersionedTest_Subclass')->dataQuery()->query()->queriedTables());
371
	}
372
373
	public function testGetVersionWhenClassnameChanged() {
374
		$obj = new VersionedTest_DataObject;
375
		$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...
376
		$obj->write();
377
		$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...
378
		$obj->ClassName = "VersionedTest_Subclass";
379
		$obj->write();
380
		$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...
381
382
		$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...
383
		$obj->ClassName = "VersionedTest_DataObject";
384
		$obj->write();
385
386
		// We should be able to pass the subclass and still get the correct class back
387
		$obj2 = Versioned::get_version("VersionedTest_Subclass", $obj->ID, $subclassVersion);
388
		$this->assertInstanceOf("VersionedTest_Subclass", $obj2);
389
		$this->assertEquals("test2", $obj2->Name);
390
391
		$obj3 = Versioned::get_latest_version("VersionedTest_Subclass", $obj->ID);
392
		$this->assertEquals("test3", $obj3->Name);
393
		$this->assertInstanceOf("VersionedTest_DataObject", $obj3);
394
395
	}
396
397
	public function testArchiveVersion() {
398
399
		// In 2005 this file was created
400
		SS_Datetime::set_mock_now('2005-01-01 00:00:00');
401
		$testPage = new VersionedTest_Subclass();
402
		$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...
403
		$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...
404
		$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...
405
		$testPage->write();
406
407
		// In 2007 we updated it
408
		SS_Datetime::set_mock_now('2007-01-01 00:00:00');
409
		$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...
410
		$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...
411
		$testPage->write();
412
413
		// In 2009 we updated it again
414
		SS_Datetime::set_mock_now('2009-01-01 00:00:00');
415
		$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...
416
		$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...
417
		$testPage->write();
418
419
		// End mock, back to the present day:)
420
		SS_Datetime::clear_mock_now();
421
422
		// Test 1 - 2006 Content
423
		singleton('VersionedTest_Subclass')->flushCache(true);
424
		Versioned::set_reading_mode('Archive.2006-01-01 00:00:00');
425
		$testPage2006 = DataObject::get('VersionedTest_Subclass')->filter(array('Title' => 'Archived page'))->first();
426
		$this->assertInstanceOf("VersionedTest_Subclass", $testPage2006);
427
		$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...
428
		$this->assertEquals("This is the content from 2005", $testPage2006->Content);
429
430
		// Test 2 - 2008 Content
431
		singleton('VersionedTest_Subclass')->flushCache(true);
432
		Versioned::set_reading_mode('Archive.2008-01-01 00:00:00');
433
		$testPage2008 = DataObject::get('VersionedTest_Subclass')->filter(array('Title' => 'Archived page'))->first();
434
		$this->assertInstanceOf("VersionedTest_Subclass", $testPage2008);
435
		$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...
436
		$this->assertEquals("It's 2007 already!", $testPage2008->Content);
437
438
		// Test 3 - Today
439
		singleton('VersionedTest_Subclass')->flushCache(true);
440
		Versioned::set_reading_mode('Stage.Stage');
441
		$testPageCurrent = DataObject::get('VersionedTest_Subclass')->filter(array('Title' => 'Archived page'))
442
			->first();
443
		$this->assertInstanceOf("VersionedTest_Subclass", $testPageCurrent);
444
		$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...
445
		$this->assertEquals("I'm enjoying 2009", $testPageCurrent->Content);
446
	}
447
448
	public function testAllVersions()
449
	{
450
		// In 2005 this file was created
451
		SS_Datetime::set_mock_now('2005-01-01 00:00:00');
452
		$testPage = new VersionedTest_Subclass();
453
		$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...
454
		$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...
455
		$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...
456
		$testPage->write();
457
458
		// In 2007 we updated it
459
		SS_Datetime::set_mock_now('2007-01-01 00:00:00');
460
		$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...
461
		$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...
462
		$testPage->write();
463
464
		// Check both versions are returned
465
		$versions = Versioned::get_all_versions('VersionedTest_Subclass', $testPage->ID);
466
		$content = array();
467
		$extraFields = array();
468
		foreach($versions as $version)
469
		{
470
			$content[] = $version->Content;
471
			$extraFields[] = $version->ExtraField;
472
		}
473
474
		$this->assertEquals($versions->Count(), 2, 'All versions returned');
475
		$this->assertEquals($content, array('This is the content from 2005', "It's 2007 already!"),
476
			'Version fields returned');
477
		$this->assertEquals($extraFields, array('2005', '2007'), 'Version fields returned');
478
479
		// In 2009 we updated it again
480
		SS_Datetime::set_mock_now('2009-01-01 00:00:00');
481
		$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...
482
		$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...
483
		$testPage->write();
484
485
		// End mock, back to the present day:)
486
		SS_Datetime::clear_mock_now();
487
488
		$versions = Versioned::get_all_versions('VersionedTest_Subclass', $testPage->ID);
489
		$content = array();
490
		$extraFields = array();
491
		foreach($versions as $version)
492
		{
493
			$content[] = $version->Content;
494
			$extraFields[] = $version->ExtraField;
495
		}
496
497
		$this->assertEquals($versions->Count(), 3, 'Additional all versions returned');
498
		$this->assertEquals($content,
499
			array('This is the content from 2005', "It's 2007 already!", "I'm enjoying 2009"),
500
			'Additional version fields returned');
501
		$this->assertEquals($extraFields, array('2005', '2007', '2009'), 'Additional version fields returned');
502
	}
503
504
	public function testArchiveRelatedDataWithoutVersioned() {
505
		SS_Datetime::set_mock_now('2009-01-01 00:00:00');
506
507
		$relatedData = new VersionedTest_RelatedWithoutVersion();
508
		$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...
509
		$relatedDataId = $relatedData->write();
510
511
		$testData = new VersionedTest_DataObject();
512
		$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...
513
		$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...
514
		$testData->Related()->add($relatedData);
515
		$id = $testData->write();
516
517
		SS_Datetime::set_mock_now('2010-01-01 00:00:00');
518
		$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...
519
		$testData->write();
520
521
		Versioned::reading_archived_date('2009-01-01 19:00:00');
522
523
		$fetchedData = VersionedTest_DataObject::get()->byId($id);
524
		$this->assertEquals('Before Content', $fetchedData->Content, 'We see the correct content of the older version');
525
526
		$relatedData = VersionedTest_RelatedWithoutVersion::get()->byId($relatedDataId);
527
		$this->assertEquals(
528
			1,
529
			$relatedData->Related()->count(),
530
			'We have a relation, with no version table, querying it still works'
531
		);
532
	}
533
534
	public function testVersionedWithSingleStage() {
535
		$tables = DB::table_list();
536
		$this->assertContains(
537
			'versionedtest_singlestage',
538
			array_keys($tables),
539
			'Contains base table'
540
		);
541
		$this->assertContains(
542
			'versionedtest_singlestage_versions',
543
			array_keys($tables),
544
			'Contains versions table'
545
		);
546
		$this->assertNotContains(
547
			'versionedtest_singlestage_live',
548
			array_keys($tables),
549
			'Does not contain separate table with _Live suffix'
550
		);
551
		$this->assertNotContains(
552
			'versionedtest_singlestage_stage',
553
			array_keys($tables),
554
			'Does not contain separate table with _Stage suffix'
555
		);
556
557
		Versioned::reading_stage("Stage");
558
		$obj = new VersionedTest_SingleStage(array('Name' => 'MyObj'));
559
		$obj->write();
560
		$this->assertNotNull(
561
			VersionedTest_SingleStage::get()->byID($obj->ID),
562
			'Writes to and reads from default stage if its set explicitly'
563
		);
564
565
		Versioned::reading_stage("Live");
566
		$obj = new VersionedTest_SingleStage(array('Name' => 'MyObj'));
567
		$obj->write();
568
		$this->assertNotNull(
569
			VersionedTest_SingleStage::get()->byID($obj->ID),
570
			'Writes to and reads from default stage even if a non-matching stage is set'
571
		);
572
	}
573
574
	/**
575
	 * Test that publishing processes respects lazy loaded fields
576
	 */
577
	public function testLazyLoadFields() {
578
		$originalMode = Versioned::get_reading_mode();
579
580
		// Generate staging record and retrieve it from stage in live mode
581
		Versioned::reading_stage('Stage');
582
		$obj = new VersionedTest_Subclass();
583
		$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...
584
		$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...
585
		$obj->write();
586
		$objID = $obj->ID;
587
		$filter = sprintf('"VersionedTest_DataObject"."ID" = \'%d\'', Convert::raw2sql($objID));
588
		Versioned::reading_stage('Live');
589
590
		// Check fields are unloaded prior to access
591
		$objLazy = Versioned::get_one_by_stage('VersionedTest_DataObject', 'Stage', $filter, false);
592
		$lazyFields = $objLazy->getQueriedDatabaseFields();
593
		$this->assertTrue(isset($lazyFields['ExtraField_Lazy']));
594
		$this->assertEquals('VersionedTest_Subclass', $lazyFields['ExtraField_Lazy']);
595
596
		// Check lazy loading works when viewing a Stage object in Live mode
597
		$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...
598
599
		// Test that writeToStage respects lazy loaded fields
600
		$objLazy = Versioned::get_one_by_stage('VersionedTest_DataObject', 'Stage', $filter, false);
601
		$objLazy->writeToStage('Live');
602
		$objLive = Versioned::get_one_by_stage('VersionedTest_DataObject', 'Live', $filter, false);
603
		$liveLazyFields = $objLive->getQueriedDatabaseFields();
604
605
		// Check fields are unloaded prior to access
606
		$this->assertTrue(isset($liveLazyFields['ExtraField_Lazy']));
607
		$this->assertEquals('VersionedTest_Subclass', $liveLazyFields['ExtraField_Lazy']);
608
609
		// Check that live record has original value
610
		$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...
611
612
		Versioned::set_reading_mode($originalMode);
613
	}
614
615
	/**
616
	 * Tests that reading mode persists between requests
617
	 */
618
	public function testReadingPersistent() {
0 ignored issues
show
Coding Style introduced by
testReadingPersistent uses the super-global variable $_GET which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
619
		$session = Injector::inst()->create('Session', array());
620
		$adminID = $this->logInWithPermission('ADMIN');
621
		$session->inst_set('loggedInAs', $adminID);
622
623
		// Set to stage
624
		Director::test('/?stage=Stage', null, $session);
625
		$this->assertEquals(
626
				'Stage.Stage',
627
				$session->inst_get('readingMode'),
628
				'Check querystring changes reading mode to Stage'
629
		);
630
		Director::test('/', null, $session);
631
		$this->assertEquals(
632
				'Stage.Stage',
633
				$session->inst_get('readingMode'),
634
				'Check that subsequent requests in the same session remain in Stage mode'
635
		);
636
637
		// Test live persists
638
		Director::test('/?stage=Live', null, $session);
639
		$this->assertEquals(
640
				'Stage.Live',
641
				$session->inst_get('readingMode'),
642
				'Check querystring changes reading mode to Live'
643
		);
644
		Director::test('/', null, $session);
645
		$this->assertEquals(
646
				'Stage.Live',
647
				$session->inst_get('readingMode'),
648
				'Check that subsequent requests in the same session remain in Live mode'
649
		);
650
651
		// Test that session doesn't redundantly store the default stage if it doesn't need to
652
		$session2 = Injector::inst()->create('Session', array());
653
		$session2->inst_set('loggedInAs', $adminID);
654
		Director::test('/', null, $session2);
655
		$this->assertArrayNotHasKey('readingMode', $session2->inst_changedData());
656
		Director::test('/?stage=Live', null, $session2);
657
		$this->assertArrayNotHasKey('readingMode', $session2->inst_changedData());
658
659
		// Test choose_site_stage
660
		unset($_GET['stage']);
661
		unset($_GET['archiveDate']);
662
		Session::set('readingMode', 'Stage.Stage');
663
		Versioned::choose_site_stage();
664
		$this->assertEquals('Stage.Stage', Versioned::get_reading_mode());
665
		Session::set('readingMode', 'Archive.2014-01-01');
666
		Versioned::choose_site_stage();
667
		$this->assertEquals('Archive.2014-01-01', Versioned::get_reading_mode());
668
		Session::clear('readingMode');
669
		Versioned::choose_site_stage();
670
		$this->assertEquals('Stage.Live', Versioned::get_reading_mode());
671
	}
672
673
	/**
674
	 * Test that stage parameter is blocked by non-administrative users
675
	 */
676
	public function testReadingModeSecurity() {
677
		$this->setExpectedException('SS_HTTPResponse_Exception');
678
		$session = Injector::inst()->create('Session', array());
679
		$result = Director::test('/?stage=Stage', null, $session);
680
	}
681
682
	/**
683
	 * Ensures that the latest version of a record is the expected value
684
	 *
685
	 * @param DataObject $record
686
	 * @param int $version
687
	 */
688
	protected function assertRecordHasLatestVersion($record, $version) {
689
		foreach(ClassInfo::ancestry(get_class($record), true) as $table) {
690
			$versionForClass = DB::prepared_query(
691
				$sql = "SELECT MAX(\"Version\") FROM \"{$table}_versions\" WHERE \"RecordID\" = ?",
692
				array($record->ID)
693
			)->value();
694
			$this->assertEquals($version, $versionForClass, "That the table $table has the latest version $version");
695
		}
696
	}
697
698
	/**
699
	 * Tests that multi-table dataobjects are correctly versioned
700
	 */
701
	public function testWriteToStage() {
702
		// Test subclass with versioned extension directly added
703
		$record = VersionedTest_Subclass::create();
704
		$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...
705
		$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...
706
		$record->writeToStage("Stage");
707
		$this->assertRecordHasLatestVersion($record, 1);
708
		$record->publish("Stage", "Live");
709
		$this->assertRecordHasLatestVersion($record, 1);
710
		$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...
711
		$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...
712
		$record->writeToStage("Stage");
713
		$this->assertRecordHasLatestVersion($record, 2);
714
715
		// Test subclass without changes to base class
716
		$record = VersionedTest_Subclass::create();
717
		$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...
718
		$record->writeToStage("Stage");
719
		$this->assertRecordHasLatestVersion($record, 1);
720
		$record->publish("Stage", "Live");
721
		$this->assertRecordHasLatestVersion($record, 1);
722
		$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...
723
		$record->writeToStage("Stage");
724
		$this->assertRecordHasLatestVersion($record, 2);
725
726
		// Test subclass without changes to sub class
727
		$record = VersionedTest_Subclass::create();
728
		$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...
729
		$record->writeToStage("Stage");
730
		$this->assertRecordHasLatestVersion($record, 1);
731
		$record->publish("Stage", "Live");
732
		$this->assertRecordHasLatestVersion($record, 1);
733
		$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...
734
		$record->writeToStage("Stage");
735
		$this->assertRecordHasLatestVersion($record, 2);
736
737
		// Test subclass with versioned extension only added to the base clases
738
		$record = VersionedTest_AnotherSubclass::create();
739
		$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...
740
		$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...
741
		$record->writeToStage("Stage");
742
		$this->assertRecordHasLatestVersion($record, 1);
743
		$record->publish("Stage", "Live");
744
		$this->assertRecordHasLatestVersion($record, 1);
745
		$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...
746
		$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...
747
		$record->writeToStage("Stage");
748
		$this->assertRecordHasLatestVersion($record, 2);
749
750
751
		// Test subclass without changes to base class
752
		$record = VersionedTest_AnotherSubclass::create();
753
		$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...
754
		$record->writeToStage("Stage");
755
		$this->assertRecordHasLatestVersion($record, 1);
756
		$record->publish("Stage", "Live");
757
		$this->assertRecordHasLatestVersion($record, 1);
758
		$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...
759
		$record->writeToStage("Stage");
760
		$this->assertRecordHasLatestVersion($record, 2);
761
762
		// Test subclass without changes to sub class
763
		$record = VersionedTest_AnotherSubclass::create();
764
		$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...
765
		$record->writeToStage("Stage");
766
		$this->assertRecordHasLatestVersion($record, 1);
767
		$record->publish("Stage", "Live");
768
		$this->assertRecordHasLatestVersion($record, 1);
769
		$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...
770
		$record->writeToStage("Stage");
771
		$this->assertRecordHasLatestVersion($record, 2);
772
	}
773
774
	public function testVersionedHandlesRenamedDataObjectFields(){
775
		Config::inst()->remove('VersionedTest_RelatedWithoutVersion','db','Name','Varchar');
776
777
		Config::inst()->update('VersionedTest_RelatedWithoutVersion','db',array(
778
			"NewField" => "Varchar",
779
		));
780
781
		VersionedTest_RelatedWithoutVersion::add_extension("Versioned('Stage', 'Live')");
782
		$this->resetDBSchema(true);
783
		$testData = new VersionedTest_RelatedWithoutVersion();
784
		$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...
785
		$testData->write();
786
	}
787
788
	public function testCanView() {
789
		$public1ID = $this->idFromFixture('VersionedTest_PublicStage', 'public1');
790
		$public2ID = $this->idFromFixture('VersionedTest_PublicViaExtension', 'public2');
791
		$privateID = $this->idFromFixture('VersionedTest_DataObject', 'page1');
792
793
		// Test that all (and only) public pages are viewable in stage mode
794
		Session::clear("loggedInAs");
795
		Versioned::reading_stage('Stage');
796
		$public1 = Versioned::get_one_by_stage('VersionedTest_PublicStage', 'Stage', array('"ID"' => $public1ID));
797
		$public2 = Versioned::get_one_by_stage('VersionedTest_PublicViaExtension', 'Stage', array('"ID"' => $public2ID));
798
		$private = Versioned::get_one_by_stage('VersionedTest_DataObject', 'Stage', array('"ID"' => $privateID));
799
800
		$this->assertTrue($public1->canView());
801
		$this->assertTrue($public2->canView());
802
		$this->assertFalse($private->canView());
803
804
		// Adjusting the current stage should not allow objects loaded in stage to be viewable
805
		Versioned::reading_stage('Live');
806
		$this->assertTrue($public1->canView());
807
		$this->assertTrue($public2->canView());
808
		$this->assertFalse($private->canView());
809
810
		// Writing the private page to live should be fine though
811
		$private->publish("Stage", "Live");
812
		$privateLive = Versioned::get_one_by_stage('VersionedTest_DataObject', 'Live', array('"ID"' => $privateID));
813
		$this->assertTrue($private->canView());
814
		$this->assertTrue($privateLive->canView());
815
816
		// But if the private version becomes different to the live version, it's once again disallowed
817
		Versioned::reading_stage('Stage');
818
		$private->Title = 'Secret Title';
0 ignored issues
show
Documentation introduced by
The property Title 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...
819
		$private->write();
820
		$this->assertFalse($private->canView());
821
		$this->assertTrue($privateLive->canView());
822
823
		// And likewise, viewing a live page (when mode is draft) should be ok
824
		Versioned::reading_stage('Stage');
825
		$this->assertFalse($private->canView());
826
		$this->assertTrue($privateLive->canView());
827
828
		// Logging in as admin should allow all permissions
829
		$this->logInWithPermission('ADMIN');
830
		Versioned::reading_stage('Stage');
831
		$this->assertTrue($public1->canView());
832
		$this->assertTrue($public2->canView());
833
		$this->assertTrue($private->canView());
834
	}
835
836
837
	public function testCanViewStage() {
838
		$public = $this->objFromFixture('VersionedTest_PublicStage', 'public1');
839
		$private = $this->objFromFixture('VersionedTest_DataObject', 'page1');
840
		Session::clear("loggedInAs");
841
		Versioned::reading_stage('Stage');
842
843
		// Test that all (and only) public pages are viewable in stage mode
844
		// Unpublished records are not viewable in live regardless of permissions
845
		$this->assertTrue($public->canViewStage('Stage'));
846
		$this->assertFalse($private->canViewStage('Stage'));
847
		$this->assertFalse($public->canViewStage('Live'));
848
		$this->assertFalse($private->canViewStage('Live'));
849
850
		// Writing records to live should make both stage and live modes viewable
851
		$private->publish("Stage", "Live");
852
		$public->publish("Stage", "Live");
853
		$this->assertTrue($public->canViewStage('Stage'));
854
		$this->assertTrue($private->canViewStage('Stage'));
855
		$this->assertTrue($public->canViewStage('Live'));
856
		$this->assertTrue($private->canViewStage('Live'));
857
858
		// If the draft mode changes, the live mode remains public, although the updated
859
		// draft mode is secured for non-public records.
860
		$private->Title = 'Secret Title';
0 ignored issues
show
Documentation introduced by
The property Title 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...
861
		$private->write();
862
		$public->Title = 'Public Title';
0 ignored issues
show
Documentation introduced by
The property Title 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...
863
		$public->write();
864
		$this->assertTrue($public->canViewStage('Stage'));
865
		$this->assertFalse($private->canViewStage('Stage'));
866
		$this->assertTrue($public->canViewStage('Live'));
867
		$this->assertTrue($private->canViewStage('Live'));
868
	}
869
}
870
871
872
/**
873
 * @package framework
874
 * @subpackage tests
875
 */
876
class VersionedTest_DataObject extends DataObject implements TestOnly {
877
	private static $db = array(
878
		"Name" => "Varchar",
879
		'Title' => 'Varchar',
880
		'Content' => 'HTMLText'
881
	);
882
883
	private static $extensions = array(
884
		"Versioned('Stage', 'Live')"
885
	);
886
887
	private static $has_one = array(
888
		'Parent' => 'VersionedTest_DataObject'
889
	);
890
891
	private static $many_many = array(
892
		'Related' => 'VersionedTest_RelatedWithoutVersion'
893
	);
894
895
896
	public function canView($member = null) {
897
		$extended = $this->extendedCan(__FUNCTION__, $member);
898
		if($extended !== null) {
899
			return $extended;
900
		}
901
		return true;
902
	}
903
}
904
905
class VersionedTest_WithIndexes extends DataObject implements TestOnly {
906
907
	private static $db = array(
908
		'UniqA' => 'Int',
909
		'UniqS' => 'Int',
910
	);
911
	private static $extensions = array(
912
		"Versioned('Stage', 'Live')"
913
	);
914
	private static $indexes = array(
915
		'UniqS_idx' => 'unique ("UniqS")',
916
		'UniqA_idx' => array('type' => 'unique', 'name' => 'UniqA_idx', 'value' => '"UniqA"',),
917
	);
918
919
}
920
921
/**
922
 * @package framework
923
 * @subpackage tests
924
 */
925
class VersionedTest_RelatedWithoutVersion extends DataObject implements TestOnly {
926
927
	private static $db = array(
928
		'Name' => 'Varchar'
929
	);
930
931
	private static $belongs_many_many = array(
932
		'Related' => 'VersionedTest_DataObject'
933
	);
934
935
}
936
937
/**
938
 * @package framework
939
 * @subpackage tests
940
 */
941
class VersionedTest_Subclass extends VersionedTest_DataObject implements TestOnly {
942
	private static $db = array(
943
		"ExtraField" => "Varchar",
944
	);
945
}
946
947
/**
948
 * @package framework
949
 * @subpackage tests
950
 */
951
class VersionedTest_AnotherSubclass extends VersionedTest_DataObject implements TestOnly {
952
	private static $db = array(
953
		"AnotherField" => "Varchar"
954
	);
955
}
956
957
/**
958
 * @package framework
959
 * @subpackage tests
960
 */
961
class VersionedTest_UnversionedWithField extends DataObject implements TestOnly {
962
	private static $db = array('Version' => 'Varchar(255)');
963
}
964
965
class VersionedTest_SingleStage extends DataObject implements TestOnly {
966
	private static $db = array(
967
		'Name' => 'Varchar'
968
	);
969
970
	private static $extensions = array(
971
		'Versioned("Stage")'
972
	);
973
}
974
975
/**
976
 * Versioned dataobject with public stage mode
977
 */
978
class VersionedTest_PublicStage extends DataObject implements TestOnly {
979
	private static $db = array(
980
		'Title' => 'Varchar'
981
	);
982
983
	private static $extensions = array(
984
		"Versioned('Stage', 'Live')"
985
	);
986
987
	public function canView($member = null) {
988
		$extended = $this->extendedCan(__FUNCTION__, $member);
989
		if($extended !== null) {
990
			return $extended;
991
		}
992
		return true;
993
	}
994
995
	public function canViewVersioned($member = null) {
0 ignored issues
show
Unused Code introduced by
The parameter $member is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
996
		// All non-live modes are public
997
		return true;
998
	}
999
}
1000
1001
/**
1002
 * Public access is provided via extension rather than overriding canViewVersioned
1003
 */
1004
class VersionedTest_PublicViaExtension extends DataObject implements TestOnly {
1005
1006
	public function canView($member = null) {
1007
		$extended = $this->extendedCan(__FUNCTION__, $member);
1008
		if($extended !== null) {
1009
			return $extended;
1010
		}
1011
		return true;
1012
	}
1013
1014
	private static $db = array(
1015
		'Title' => 'Varchar'
1016
	);
1017
1018
	private static $extensions = array(
1019
		"Versioned('Stage', 'Live')",
1020
		"VersionedTest_PublicExtension"
1021
	);
1022
}
1023
1024
/**
1025
 * Alters stage mode of extended object to be public
1026
 */
1027
class VersionedTest_PublicExtension extends DataExtension implements TestOnly {
1028
	public function canViewNonLive($member = null) {
0 ignored issues
show
Unused Code introduced by
The parameter $member is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1029
		return true;
1030
	}
1031
}
1032