Completed
Pull Request — master (#53)
by Helpful
02:20
created

getClassName()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 3
rs 10
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
3
class SiteTreePublishingEngineTest extends SapphireTest {
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
4
5
	protected $requiredExtensions = array(
6
		'SiteTreePublishingEngineTest_StaticallyPublishable' => array(
7
			'SiteTreePublishingEngine',
8
			'FilesystemPublisher'
9
		),
10
		'SiteTreePublishingEngineTest_StaticPublishingTrigger' => array(
11
			'SiteTreePublishingEngine',
12
			'FilesystemPublisher'
13
		)
14
	);
15
16
	public function setUp() {
17
		parent::setUp();
18
		Config::inst()->nest();
19
		Config::inst()->update('StaticPagesQueue', 'realtime', true);
20
	}
21
22
	public function tearDown() {
23
		Config::inst()->unnest();
24
		parent::tearDown();
25
	}
26
	
27 View Code Duplication
	function testCollectChangesForPublishing() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
28
29
		$obj = Object::create('SiteTreePublishingEngineTest_StaticPublishingTrigger');
30
		$obj->collectChanges(array('action'=>'publish'));
31
32
		$this->assertEquals(
33
			$obj->getToUpdate(),
34
			array('/updateOnPublish?_ID=1&_ClassName=StaticallyPublishableTest'=>10)
35
		);
36
		$this->assertEquals(
37
			$obj->getToDelete(),
38
			array('/deleteOnPublish?_ID=1&_ClassName=StaticallyPublishableTest'=>10)
39
		);
40
41
	}
42
43 View Code Duplication
	function testCollectChangesForUnpublishing() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
44
45
		$obj = Object::create('SiteTreePublishingEngineTest_StaticPublishingTrigger');
46
		$obj->collectChanges(array('action'=>'unpublish'));
47
48
		$this->assertEquals(
49
			$obj->getToUpdate(),
50
			array('/updateOnUnpublish?_ID=1&_ClassName=StaticallyPublishableTest'=>10)
51
		);
52
		$this->assertEquals(
53
			$obj->getToDelete(),
54
			array('/deleteOnUnpublish?_ID=1&_ClassName=StaticallyPublishableTest'=>10)
55
		);
56
57
	}
58
59
	function testFlushChangesToUpdateEnqueuesAndDeletesRegular() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
60
61
		$toUpdate = array('/toUpdate?_ID=1&_ClassName=StaticallyPublishableTest'=>10);
62
63
		$stub = $this->getMock(
64
			'SiteTreePublishingEngineTest_StaticPublishingTrigger',
65
			array('convertUrlsToPathMap', 'deleteRegularFiles', 'deleteStaleFiles')
66
		);
67
		$stub->expects($this->once())
68
			->method('convertUrlsToPathMap')
69
			->will($this->returnValue(array('url'=>'file')));
70
71
		// Test: enqueues the updated URLs
72
		$stub->setUrlArrayObject($this->getMock('URLArrayObject', array('addUrls')));
73
		$stub->getUrlArrayObject()->expects($this->once())
74
			->method('addUrls')
75
			->with($this->equalTo($toUpdate));
76
77
		// Test: deletes just the regular files
78
		$stub->expects($this->never())
79
			->method('deleteStaleFiles');
80
		$stub->expects($this->once())
81
			->method('deleteRegularFiles')
82
			->with($this->equalTo(array('file')));
83
84
		// Test: clears the update queue
85
		$stub->setToUpdate($toUpdate);
86
		$stub->flushChanges();
87
		$this->assertEquals($stub->getToUpdate(), array(), 'The update cache has been flushed.');
88
89
	}
90
91
	function testFlushChangesToDeleteDeletesRegularAndStale() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
92
93
		$toDelete = array('/toDelete?_ID=1&_ClassName=StaticallyPublishableTest'=>10);
94
95
		$stub = $this->getMock(
96
			'SiteTreePublishingEngineTest_StaticPublishingTrigger',
97
			array('convertUrlsToPathMap', 'deleteRegularFiles', 'deleteStaleFiles')
98
		);
99
		$stub->expects($this->once())
100
			->method('convertUrlsToPathMap')
101
			->will($this->returnValue(array('url'=>'file')));
102
103
		// Test: deletes both regular and stale files
104
		$stub->expects($this->once())
105
			->method('deleteRegularFiles')
106
			->with($this->equalTo(array('file')));
107
		$stub->expects($this->once())
108
			->method('deleteStaleFiles')
109
			->with($this->equalTo(array('file')));
110
111
		// Test: clears the queue
112
		$stub->setToDelete($toDelete);
113
		$stub->flushChanges();
114
		$this->assertEquals($stub->getToDelete(), array(), 'The delete cache has been flushed.');
115
116
	}
117
118
	function testConvertUrlsToPathMapNoObject() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
119
		Config::inst()->nest();
120
		Config::inst()->update('FilesystemPublisher', 'static_base_url', 'http://foo');
121
		Config::inst()->update('Director', 'alternate_base_url', '/');
122
123
		$urls = array('/xyzzy');
124
125
		$stub = Object::create('SiteTreePublishingEngineTest_StaticPublishingTrigger');
126
127
		// Test (inclusively with urlsToPaths, these interfaces should be refactored together)
128
		$result = $stub->convertUrlsToPathMap($urls);
129
		$this->assertEquals($result, array(
130
			'/xyzzy' => './xyzzy.html'
131
		));
132
133
		Config::inst()->unnest();
134
	}
135
136
	function testConvertUrlsToPathMapMainSite() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
137
		Config::inst()->nest();
138
		Config::inst()->update('FilesystemPublisher', 'static_base_url', 'http://foo');
139
		Config::inst()->update('Director', 'alternate_base_url', '/');
140
		$urls = array('/xyzzy?_ID=1&_ClassName=SiteTreePublishingEngineTest_StaticallyPublishable');
141
142
		// Pretend this object supports subsites, and is from the main site.
143
		$page = $this->getMock('SiteTreePublishingEngineTest_StaticallyPublishable', array('Subsite', 'hasExtension'));
144
		$page->expects($this->any())
145
			->method('Subsite')
146
			->will($this->returnValue(null));
147
		$page->expects($this->any())
148
			->method('hasExtension')
149
			->will($this->returnValue(true));
150
151
		$stub = Object::create('SiteTreePublishingEngineTest_StaticPublishingTrigger');
152
153
		$stub->setUrlArrayObject($this->getMock('URLArrayObject', array('getObject')));
154
		$stub->getUrlArrayObject()->expects($this->any())
155
			->method('getObject')
156
			->will($this->returnValue(
157
				$page
158
			));
159
160
		// Test (inclusively with urlsToPaths, these interfaces should be refactored together)
161
		$result = $stub->convertUrlsToPathMap($urls);
162
		$this->assertEquals(
163
			$result,
164
			array('http://foo/xyzzy?_ID=1&_ClassName=SiteTreePublishingEngineTest_StaticallyPublishable' =>
165
				'foo/xyzzy.html')
166
		);
167
168
		Config::inst()->unnest();
169
	}
170
171
	function testConvertUrlsToPathMapSubsite() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
172
		Config::inst()->nest();
173
		Config::inst()->update('FilesystemPublisher', 'static_base_url', 'http://foo');
174
		Config::inst()->update('Director', 'alternate_base_url', '/');
175
		$urls = array('/xyzzy?_ID=1&_ClassName=SiteTreePublishingEngineTest_StaticallyPublishable');
176
177
		// Mock a set of objects pretending to support Subsites. Subsites might not be installed.
178
		$domain1 = $this->getMock('SubsiteDomain_mock', array('Domain'));
179
		$domain1->Domain = 'subiste1.domain.org';
180
		$domain2 = $this->getMock('SubsiteDomain_mock', array('Domain'));
181
		$domain2->Domain = 'subiste2.domain.org';
182
183
		$domains = Object::create('ArrayList', array($domain1, $domain2));
184
185
		$subsite = $this->getMock('Subsite_mock', array('Domains', 'ID'));
186
		$subsite->expects($this->any())
187
			->method('Domains')
188
			->will($this->returnValue($domains));
189
		$subsite->ID = 1;
190
191
		$stub = $this->getMock('SiteTreePublishingEngineTest_StaticallyPublishable', array('Subsite', 'hasExtension'));
192
		$stub->expects($this->any())
193
			->method('Subsite')
194
			->will($this->returnValue($subsite));
195
		$stub->expects($this->any())
196
			->method('hasExtension')
197
			->will($this->returnValue(true));
198
199
		// Prepare static mocks.
200
		$stub->setUrlArrayObject($this->getMock('URLArrayObject', array('getObject')));
201
		$stub->getUrlArrayObject()->expects($this->any())
202
			->method('getObject')
203
			->will($this->returnValue($stub));
204
205
		// Test (inclusively with urlsToPaths, these interfaces should be refactored together)
206
		$result = $stub->convertUrlsToPathMap($urls);
207
		$this->assertEquals(
208
			$result,
209
			array(
210
				'http://subiste1.domain.org/xyzzy?_ID=1&_ClassName=SiteTreePublishingEngineTest_StaticallyPublishable' =>
211
				"subiste1.domain.org/xyzzy.html",
212
				'http://subiste2.domain.org/xyzzy?_ID=1&_ClassName=SiteTreePublishingEngineTest_StaticallyPublishable' =>
213
				"subiste2.domain.org/xyzzy.html"
214
			)
215
		);
216
217
		Config::inst()->unnest();
218
219
	}
220
221
	function testDeleteStaleFiles() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
222
223
		$stub = $this->getMock(
224
			'SiteTreePublishingEngineTest_StaticPublishingTrigger',
225
			array('deleteFromCacheDir')
226
		);
227
		$stub->expects($this->at(0))
228
			->method('deleteFromCacheDir')
229
			->with($this->equalTo('xyzzy.stale.html'));
230
		$stub->expects($this->at(1))
231
			->method('deleteFromCacheDir')
232
			->with($this->equalTo('foo/bar/baz.stale.html'));
233
234
		$stub->deleteStaleFiles(array('xyzzy.html', 'foo/bar/baz.html'));
235
236
	}
237
}
238
239
class SiteTreePublishingEngineTest_StaticallyPublishable extends SiteTree implements TestOnly, StaticallyPublishable {
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
240
241
	public $url;
242
	public $prio;
243
244
	public function getClassName() {
245
		return 'StaticallyPublishableTest';
246
	}
247
248
	public function getID() {
249
		return '1';
250
	}
251
252
	public function urlsToCache() {
253
		return array($this->url => $this->prio);
254
	}
255
256
}
257
258
class SiteTreePublishingEngineTest_StaticPublishingTrigger extends SiteTree implements TestOnly, StaticPublishingTrigger {
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
259
260
	public function generatePublishable($url, $prio) {
261
		$obj = Object::create('SiteTreePublishingEngineTest_StaticallyPublishable');
262
		$obj->url = $url;
0 ignored issues
show
Documentation introduced by
The property url does not exist on object<SiteTreePublishin...taticPublishingTrigger>. 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...
263
		$obj->prio = $prio;
0 ignored issues
show
Documentation introduced by
The property prio does not exist on object<SiteTreePublishin...taticPublishingTrigger>. 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...
264
265
		return $obj;
266
	}
267
268 View Code Duplication
	public function objectsToUpdate($context) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
269
270
		switch ($context['action']) {
271
			case 'publish':
272
				return new ArrayList(array($this->generatePublishable('/updateOnPublish', 10)));
273
			case 'unpublish':
274
				return new ArrayList(array($this->generatePublishable('/updateOnUnpublish', 10)));
275
		}
276
277
	}
278
279
	/**
280
	 * Remove the object on unpublishing (the parent will get updated via objectsToUpdate).
281
	 */
282 View Code Duplication
	public function objectsToDelete($context) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
283
284
		switch ($context['action']) {
285
			case 'publish':
286
				return new ArrayList(array($this->generatePublishable('/deleteOnPublish', 10)));
287
			case 'unpublish':
288
				return new ArrayList(array($this->generatePublishable('/deleteOnUnpublish', 10)));
289
		}
290
291
	}
292
293
}
294