Completed
Pull Request — master (#5408)
by Damian
23:40 queued 12:41
created

DataExtensionTest_AllMethodNames   A

Complexity

Total Complexity 1

Size/Duplication

Total Lines 10
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2
Metric Value
wmc 1
lcom 1
cbo 2
dl 0
loc 10
rs 10

1 Method

Rating   Name   Duplication   Size   Complexity  
A allMethodNames() 0 6 1
1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 3 and the first side effect is on line 337.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
3
class DataExtensionTest extends SapphireTest {
4
	protected static $fixture_file = 'DataExtensionTest.yml';
5
6
	protected $extraDataObjects = array(
7
		'DataExtensionTest_Member',
8
		'DataExtensionTest_Player',
9
		'DataExtensionTest_RelatedObject',
10
		'DataExtensionTest_MyObject',
11
		'DataExtensionTest_CMSFieldsBase',
12
		'DataExtensionTest_CMSFieldsChild',
13
		'DataExtensionTest_CMSFieldsGrandchild'
14
	);
15
16
	protected $requiredExtensions = array(
17
		'DataObject' => array( 'DataExtensionTest_AppliedToDO' ),
18
	);
19
20
	public function testOneToManyAssociationWithExtension() {
21
		$contact = new DataExtensionTest_Member();
22
		$contact->Website = "http://www.example.com";
0 ignored issues
show
Documentation introduced by
The property Website does not exist on object<DataExtensionTest_Member>. 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...
23
24
		$object = new DataExtensionTest_RelatedObject();
25
		$object->FieldOne = "Lorem ipsum dolor";
0 ignored issues
show
Documentation introduced by
The property FieldOne does not exist on object<DataExtensionTest_RelatedObject>. 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...
26
		$object->FieldTwo = "Random notes";
0 ignored issues
show
Documentation introduced by
The property FieldTwo does not exist on object<DataExtensionTest_RelatedObject>. 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...
27
28
		// The following code doesn't currently work:
29
		// $contact->RelatedObjects()->add($object);
0 ignored issues
show
Unused Code Comprehensibility introduced by
75% of this comment could be valid code. Did you maybe forget this after debugging?

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

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

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

Loading history...
30
		// $contact->write();
0 ignored issues
show
Unused Code Comprehensibility introduced by
72% of this comment could be valid code. Did you maybe forget this after debugging?

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

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

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

Loading history...
31
32
		// Instead we have to do the following
33
		$contact->write();
34
		$object->ContactID = $contact->ID;
0 ignored issues
show
Documentation introduced by
The property ContactID does not exist on object<DataExtensionTest_RelatedObject>. 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...
35
		$object->write();
36
37
		$contactID = $contact->ID;
38
		unset($contact);
39
		unset($object);
40
41
		$contact = DataObject::get_one("DataExtensionTest_Member", array(
42
			'"DataExtensionTest_Member"."Website"' => 'http://www.example.com'
43
		));
44
		$object = DataObject::get_one('DataExtensionTest_RelatedObject', array(
45
			'"DataExtensionTest_RelatedObject"."ContactID"' => $contactID
46
		));
47
48
		$this->assertNotNull($object, 'Related object not null');
49
		$this->assertInstanceOf('DataExtensionTest_Member', $object->Contact(),
50
			'Related contact is a member dataobject');
51
		$this->assertInstanceOf('DataExtensionTest_Member', $object->getComponent('Contact'),
52
			'getComponent does the same thing as Contact()');
53
54
		$this->assertInstanceOf('DataExtensionTest_RelatedObject', $contact->RelatedObjects()->First());
55
		$this->assertEquals("Lorem ipsum dolor", $contact->RelatedObjects()->First()->FieldOne);
56
		$this->assertEquals("Random notes", $contact->RelatedObjects()->First()->FieldTwo);
57
		$contact->delete();
58
	}
59
60
	public function testManyManyAssociationWithExtension() {
61
		$parent = new DataExtensionTest_MyObject();
62
		$parent->Title = 'My Title';
0 ignored issues
show
Documentation introduced by
The property Title does not exist on object<DataExtensionTest_MyObject>. 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...
63
		$parent->write();
64
65
		$this->assertEquals(0, $parent->Faves()->Count());
66
67
		$obj1 = $this->objFromFixture('DataExtensionTest_RelatedObject', 'obj1');
68
		$obj2 = $this->objFromFixture('DataExtensionTest_RelatedObject', 'obj2');
69
70
		$parent->Faves()->add($obj1->ID);
71
		$this->assertEquals(1, $parent->Faves()->Count());
72
73
		$parent->Faves()->add($obj2->ID);
74
		$this->assertEquals(2, $parent->Faves()->Count());
75
76
		$parent->Faves()->removeByID($obj2->ID);
77
		$this->assertEquals(1, $parent->Faves()->Count());
78
	}
79
80
	/**
81
	 * Test {@link Object::add_extension()} has loaded DataExtension statics correctly.
82
	 */
83
	public function testAddExtensionLoadsStatics() {
84
		// Object::add_extension() will load DOD statics directly, so let's try adding a extension on the fly
85
		DataExtensionTest_Player::add_extension('DataExtensionTest_PlayerExtension');
86
87
		// Now that we've just added the extension, we need to rebuild the database
88
		$this->resetDBSchema(true);
89
90
		// Create a test record with extended fields, writing to the DB
91
		$player = new DataExtensionTest_Player();
92
		$player->setField('Name', 'Joe');
93
		$player->setField('DateBirth', '1990-5-10');
94
		$player->Address = '123 somewhere street';
0 ignored issues
show
Documentation introduced by
The property Address does not exist on object<DataExtensionTest_Player>. 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...
95
		$player->write();
96
97
		unset($player);
98
99
		// Pull the record out of the DB and examine the extended fields
100
		$player = DataObject::get_one('DataExtensionTest_Player', array(
101
			'"DataExtensionTest_Player"."Name"' => 'Joe'
102
		));
103
		$this->assertEquals($player->DateBirth, '1990-05-10');
104
		$this->assertEquals($player->Address, '123 somewhere street');
105
		$this->assertEquals($player->Status, 'Goalie');
106
	}
107
108
	/**
109
	 * Test that DataObject::$api_access can be set to true via a extension
110
	 */
111
	public function testApiAccessCanBeExtended() {
112
		$this->assertTrue(Config::inst()->get('DataExtensionTest_Member', 'api_access', Config::FIRST_SET));
113
	}
114
115
	public function testPermissionExtension() {
116
		// testing behaviour in isolation, too many sideeffects and other checks
117
		// in SiteTree->can*() methods to test one single feature reliably with them
118
119
		$obj = $this->objFromFixture('DataExtensionTest_MyObject', 'object1');
120
		$websiteuser = $this->objFromFixture('Member', 'websiteuser');
121
		$admin = $this->objFromFixture('Member', 'admin');
122
123
		$this->assertFalse(
124
			$obj->canOne($websiteuser),
125
			'Both extensions return true, but original method returns false'
126
		);
127
128
		$this->assertFalse(
129
			$obj->canTwo($websiteuser),
130
			'One extension returns false, original returns true, but extension takes precedence'
131
		);
132
133
		$this->assertTrue(
134
			$obj->canThree($admin),
135
			'Undefined extension methods returning NULL dont influence the original method'
136
		);
137
138
	}
139
140
	public function testPopulateDefaults() {
141
		$obj = new DataExtensionTest_Member();
142
		$this->assertEquals(
143
			$obj->Phone,
144
			'123',
145
			'Defaults can be populated through extension'
146
		);
147
	}
148
149
	/**
150
	 * Test that DataObject::dbObject() works for fields applied by a extension
151
	 */
152
	public function testDbObjectOnExtendedFields() {
153
		$member = $this->objFromFixture('DataExtensionTest_Member', 'member1');
154
		$this->assertNotNull($member->dbObject('Website'));
155
		$this->assertInstanceOf('SilverStripe\Model\FieldType\DBVarchar', $member->dbObject('Website'));
156
	}
157
158
	public function testExtensionCanBeAppliedToDataObject() {
159
		$do = new DataObject();
160
		$mo = new DataExtensionTest_MyObject();
161
162
		$this->assertTrue($do->hasMethod('testMethodApplied'));
163
		$this->assertTrue($mo->hasMethod('testMethodApplied'));
164
165
		$this->assertEquals("hello world", $mo->testMethodApplied());
166
		$this->assertEquals("hello world", $do->testMethodApplied());
167
	}
168
169
	public function testExtensionAllMethodNamesHasOwner() {
170
		/** @var DataExtensionTest_MyObject $do */
171
		$do = DataExtensionTest_MyObject::create();
172
173
		$this->assertTrue($do->hasMethod('getTestValueWithDataExtensionTest_MyObject'));
174
	}
175
176
	public function testPageFieldGeneration() {
177
		$page = new DataExtensionTest_CMSFieldsBase();
178
		$fields = $page->getCMSFields();
179
		$this->assertNotEmpty($fields);
180
181
		// Check basic field exists
182
		$this->assertNotEmpty($fields->dataFieldByName('PageField'));
183
	}
184
185
	public function testPageExtensionsFieldGeneration() {
186
		$page = new DataExtensionTest_CMSFieldsBase();
187
		$fields = $page->getCMSFields();
188
		$this->assertNotEmpty($fields);
189
190
		// Check extending fields exist
191
		$this->assertNotEmpty($fields->dataFieldByName('ExtendedFieldRemove')); // Not removed yet!
192
		$this->assertNotEmpty($fields->dataFieldByName('ExtendedFieldKeep'));
193
	}
194
195
	public function testSubpageFieldGeneration() {
196
		$page = new DataExtensionTest_CMSFieldsChild();
197
		$fields = $page->getCMSFields();
198
		$this->assertNotEmpty($fields);
199
200
		// Check extending fields exist
201
		$this->assertEmpty($fields->dataFieldByName('ExtendedFieldRemove')); // Removed by child class
202
		$this->assertNotEmpty($fields->dataFieldByName('ExtendedFieldKeep'));
203
		$this->assertNotEmpty($preExtendedField = $fields->dataFieldByName('ChildFieldBeforeExtension'));
204
		$this->assertEquals($preExtendedField->Title(), 'ChildFieldBeforeExtension: Modified Title');
205
206
		// Post-extension fields
207
		$this->assertNotEmpty($fields->dataFieldByName('ChildField'));
208
	}
209
210
	public function testSubSubpageFieldGeneration() {
211
		$page = new DataExtensionTest_CMSFieldsGrandchild();
212
		$fields = $page->getCMSFields();
213
		$this->assertNotEmpty($fields);
214
215
		// Check extending fields exist
216
		$this->assertEmpty($fields->dataFieldByName('ExtendedFieldRemove')); // Removed by child class
217
		$this->assertNotEmpty($fields->dataFieldByName('ExtendedFieldKeep'));
218
219
		// Check child fields removed by grandchild in beforeUpdateCMSFields
220
		$this->assertEmpty($fields->dataFieldByName('ChildFieldBeforeExtension')); // Removed by grandchild class
221
222
		// Check grandchild field modified by extension
223
		$this->assertNotEmpty($preExtendedField = $fields->dataFieldByName('GrandchildFieldBeforeExtension'));
224
		$this->assertEquals($preExtendedField->Title(), 'GrandchildFieldBeforeExtension: Modified Title');
225
226
		// Post-extension fields
227
		$this->assertNotEmpty($fields->dataFieldByName('ChildField'));
228
		$this->assertNotEmpty($fields->dataFieldByName('GrandchildField'));
229
	}
230
231
	/**
232
	 * Test setOwner behaviour
233
	 */
234
	public function testSetOwner() {
235
		$extension = new DataExtensionTest_Ext1();
236
		$obj1 = $this->objFromFixture('DataExtensionTest_RelatedObject', 'obj1');
237
		$obj2 = $this->objFromFixture('DataExtensionTest_RelatedObject', 'obj1');
238
239
		$extension->setOwner(null);
240
		$this->assertNull($extension->getOwner());
241
242
		// Set original owner
243
		$extension->setOwner($obj1);
0 ignored issues
show
Bug introduced by
It seems like $obj1 defined by $this->objFromFixture('D...RelatedObject', 'obj1') on line 236 can be null; however, Extension::setOwner() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
244
		$this->assertEquals($obj1, $extension->getOwner());
245
246
		// Set nested owner
247
		$extension->setOwner($obj2);
0 ignored issues
show
Bug introduced by
It seems like $obj2 defined by $this->objFromFixture('D...RelatedObject', 'obj1') on line 237 can be null; however, Extension::setOwner() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
248
		$this->assertEquals($obj2, $extension->getOwner());
249
250
		// Clear nested owner
251
		$extension->clearOwner();
252
		$this->assertEquals($obj1, $extension->getOwner());
253
254
		// Clear original owner
255
		$extension->clearOwner();
256
		$this->assertNull($extension->getOwner());
257
258
		// Another clearOwner should error
259
		$this->setExpectedException("BadMethodCallException", "clearOwner() called more than setOwner()");
260
		$extension->clearOwner();
261
	}
262
263
}
264
265
class DataExtensionTest_Member extends DataObject implements TestOnly {
266
267
	private static $db = array(
268
		"Name" => "Varchar",
269
		"Email" => "Varchar"
270
	);
271
272
}
273
274
class DataExtensionTest_Player extends DataObject implements TestOnly {
275
276
	private static $db = array(
277
		'Name' => 'Varchar'
278
	);
279
280
}
281
282
class DataExtensionTest_PlayerExtension extends DataExtension implements TestOnly {
283
284
	public static function get_extra_config($class = null, $extensionClass = null, $args = null) {
0 ignored issues
show
Unused Code introduced by
The parameter $extensionClass 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...
Unused Code introduced by
The parameter $args 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...
285
		$config = array();
286
287
		// Only add these extensions if the $class is set to DataExtensionTest_Player, to
288
		// test that the argument works.
289
		if($class == 'DataExtensionTest_Player') {
290
			$config['db'] = array(
291
				'Address' => 'Text',
292
				'DateBirth' => 'Date',
293
				'Status' => "Enum('Shooter,Goalie')"
294
			);
295
			$config['defaults'] = array(
296
				'Status' => 'Goalie'
297
			);
298
		}
299
300
		return $config;
301
	}
302
303
}
304
305
class DataExtensionTest_ContactRole extends DataExtension implements TestOnly {
306
307
	private static $db = array(
308
		'Website' => 'Varchar',
309
		'Phone' => 'Varchar(255)',
310
	);
311
312
	private static $has_many = array(
313
		'RelatedObjects' => 'DataExtensionTest_RelatedObject'
314
	);
315
316
	private static $defaults = array(
317
		'Phone' => '123'
318
	);
319
320
	private static $api_access = true;
321
322
}
323
324
class DataExtensionTest_RelatedObject extends DataObject implements TestOnly {
325
326
	private static $db = array(
327
		"FieldOne" => "Varchar",
328
		"FieldTwo" => "Varchar"
329
	);
330
331
	private static $has_one = array(
332
		"Contact" => "DataExtensionTest_Member"
333
	);
334
335
}
336
337
DataExtensionTest_Member::add_extension('DataExtensionTest_ContactRole');
338
339
class DataExtensionTest_MyObject extends DataObject implements TestOnly {
340
341
	private static $db = array(
342
		'Title' => 'Varchar',
343
	);
344
345
	public function canOne($member = null) {
346
		// extended access checks
347
		$results = $this->extend('canOne', $member);
348
		if($results && is_array($results)) if(!min($results)) return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression $results of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
349
350
		return false;
351
	}
352
353
	public function canTwo($member = null) {
354
		// extended access checks
355
		$results = $this->extend('canTwo', $member);
356
		if($results && is_array($results)) if(!min($results)) return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression $results of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
357
358
		return true;
359
	}
360
361
	public function canThree($member = null) {
362
		// extended access checks
363
		$results = $this->extend('canThree', $member);
364
		if($results && is_array($results)) if(!min($results)) return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression $results of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
365
366
		return true;
367
	}
368
}
369
370
class DataExtensionTest_Ext1 extends DataExtension implements TestOnly {
371
372
	public function canOne($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...
373
		return true;
374
	}
375
376
	public function canTwo($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...
377
		return false;
378
	}
379
380
	public function canThree($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...
381
	}
382
383
}
384
385
class DataExtensionTest_Ext2 extends DataExtension implements TestOnly {
386
387
	public function canOne($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...
388
		return true;
389
	}
390
391
	public function canTwo($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...
392
		return true;
393
	}
394
395
	public function canThree($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...
396
	}
397
398
}
399
400
class DataExtensionTest_Faves extends DataExtension implements TestOnly {
401
402
	private static $many_many = array(
403
		'Faves' => 'DataExtensionTest_RelatedObject'
404
	);
405
406
}
407
408
class DataExtensionTest_AppliedToDO extends DataExtension implements TestOnly
409
{
410
411
	public function testMethodApplied()
412
	{
413
		return "hello world";
414
	}
415
416
}
417
418
class DataExtensionTest_AllMethodNames extends DataExtension implements TestOnly
419
{
420
	public function allMethodNames()
421
	{
422
		return array(
423
			strtolower('getTestValueWith'.$this->owner->ClassName)
424
		);
425
	}
426
427
}
428
429
DataExtensionTest_MyObject::add_extension('DataExtensionTest_Ext1');
430
DataExtensionTest_MyObject::add_extension('DataExtensionTest_Ext2');
431
DataExtensionTest_MyObject::add_extension('DataExtensionTest_Faves');
432
DataExtensionTest_MyObject::add_extension('DataExtensionTest_AllMethodNames');
433
434
/**
435
 * Base class for CMS fields
436
 */
437
class DataExtensionTest_CMSFieldsBase extends DataObject implements TestOnly {
438
439
	private static $db = array(
440
		'PageField' => 'Varchar(255)'
441
	);
442
443
	private static $extensions = array(
444
		'DataExtensionTest_CMSFieldsBaseExtension'
445
	);
446
447
	public function getCMSFields() {
448
		$fields = parent::getCMSFields();
449
		$fields->addFieldToTab('Root.Test', new TextField('PageField'));
450
		return $fields;
451
	}
452
}
453
454
/**
455
 * Extension to top level test class, tests that updateCMSFields work
456
 */
457
class DataExtensionTest_CMSFieldsBaseExtension extends DataExtension implements TestOnly {
458
	private static $db = array(
459
		'ExtendedFieldKeep' => 'Varchar(255)',
460
		'ExtendedFieldRemove' => 'Varchar(255)'
461
	);
462
463
	public function updateCMSFields(FieldList $fields) {
464
		$fields->addFieldToTab('Root.Test', new TextField('ExtendedFieldRemove'));
465
		$fields->addFieldToTab('Root.Test', new TextField('ExtendedFieldKeep'));
466
467
		if($childField = $fields->dataFieldByName('ChildFieldBeforeExtension')) {
468
			$childField->setTitle('ChildFieldBeforeExtension: Modified Title');
469
		}
470
471
		if($grandchildField = $fields->dataFieldByName('GrandchildFieldBeforeExtension')) {
472
			$grandchildField->setTitle('GrandchildFieldBeforeExtension: Modified Title');
473
		}
474
	}
475
}
476
477
/**
478
 * Second level test class.
479
 * Tests usage of beforeExtendingCMSFields
480
 */
481
class DataExtensionTest_CMSFieldsChild extends DataExtensionTest_CMSFieldsBase implements TestOnly {
482
	private static $db = array(
483
		'ChildField' => 'Varchar(255)',
484
		'ChildFieldBeforeExtension' => 'Varchar(255)'
485
	);
486
487
	public function getCMSFields() {
488
		$this->beforeExtending('updateCMSFields', function(FieldList $fields) {
489
			$fields->addFieldToTab('Root.Test', new TextField('ChildFieldBeforeExtension'));
490
		});
491
492
		$this->afterExtending('updateCMSFields', function(FieldList $fields){
493
			$fields->removeByName('ExtendedFieldRemove', true);
494
		});
495
496
		$fields = parent::getCMSFields();
497
		$fields->addFieldToTab('Root.Test', new TextField('ChildField'));
498
		return $fields;
499
	}
500
}
501
502
/**
503
 * Third level test class, testing that beforeExtendingCMSFields can be nested
504
 */
505
class DataExtensionTest_CMSFieldsGrandchild extends DataExtensionTest_CMSFieldsChild implements TestOnly {
506
	private static $db = array(
507
		'GrandchildField' => 'Varchar(255)'
508
	);
509
510
	public function getCMSFields() {
511
		$this->beforeUpdateCMSFields(function(FieldList $fields) {
512
			// Remove field from parent's beforeExtendingCMSFields
513
			$fields->removeByName('ChildFieldBeforeExtension', true);
514
515
			// Adds own pre-extension field
516
			$fields->addFieldToTab('Root.Test', new TextField('GrandchildFieldBeforeExtension'));
517
		});
518
519
		$fields = parent::getCMSFields();
520
		$fields->addFieldToTab('Root.Test', new TextField('GrandchildField'));
521
		return $fields;
522
	}
523
}
524