Completed
Push — fix-for-add-folder ( c1d355...a17c5c )
by Sam
07:30
created

CampaignAdmin::getChangeSetResource()   B

Complexity

Conditions 3
Paths 3

Size

Total Lines 25
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 1
Metric Value
c 2
b 0
f 1
dl 0
loc 25
rs 8.8571
cc 3
eloc 17
nc 3
nop 1
1
<?php
2
3
/**
4
 * Campaign section of the CMS
5
 *
6
 * @package framework
7
 * @subpackage admin
8
 */
9
class CampaignAdmin extends LeftAndMain implements PermissionProvider {
10
11
	private static $allowed_actions = [
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
12
		'set',
13
		'sets',
14
		'schema',
15
		'DetailEditForm',
16
		'readCampaigns',
17
		'createCampaign',
18
		'readCampaign',
19
		'updateCampaign',
20
		'deleteCampaign',
21
	];
22
23
	private static $menu_priority = 11;
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
24
25
	private static $menu_title = 'Campaigns';
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
26
27
	private static $url_handlers = [
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
28
		'GET sets' => 'readCampaigns',
29
		'POST set/$ID' => 'createCampaign',
30
		'GET set/$ID' => 'readCampaign',
31
		'PUT set/$ID' => 'updateCampaign',
32
		'DELETE set/$ID' => 'deleteCampaign',
33
	];
34
35
	private static $url_segment = 'campaigns';
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
36
37
	public function getClientConfig() {
38
		return array_merge(parent::getClientConfig(), [
39
			'forms' => [
40
				// TODO Use schemaUrl instead
41
				'editForm' => [
42
					'schemaUrl' => $this->Link('schema/EditForm')
43
				]
44
			]
45
		]);
46
	}
47
48
	public function schema($request) {
49
		// TODO Hardcoding schema until we can get GridField to generate a schema dynamically
50
		$json = <<<JSON
51
{
52
	"id": "EditForm",
53
	"schema": {
54
		"name": "EditForm",
55
		"id": "EditForm",
56
		"action": "schema",
57
		"method": "GET",
58
		"schema_url": "admin\/campaigns\/schema\/EditForm",
59
		"attributes": {
60
			"id": "Form_EditForm",
61
			"action": "admin\/campaigns\/EditForm",
62
			"method": "POST",
63
			"enctype": "multipart\/form-data",
64
			"target": null,
65
			"class": "cms-edit-form CampaignAdmin LeftAndMain"
66
		},
67
		"data": [],
68
		"fields": [{
69
			"name": "ID",
70
			"id": "Form_EditForm_ID",
71
			"type": "Hidden",
72
			"component": null,
73
			"holder_id": null,
74
			"title": false,
75
			"source": null,
76
			"extraClass": "hidden nolabel",
77
			"description": null,
78
			"rightTitle": null,
79
			"leftTitle": null,
80
			"readOnly": false,
81
			"disabled": false,
82
			"customValidationMessage": "",
83
			"attributes": [],
84
			"data": []
85
		}, {
86
			"name": "ChangeSets",
87
			"id": "Form_EditForm_ChangeSets",
88
			"type": "Custom",
89
			"component": "GridField",
90
			"holder_id": null,
91
			"title": "Campaigns",
92
			"source": null,
93
			"extraClass": null,
94
			"description": null,
95
			"rightTitle": null,
96
			"leftTitle": null,
97
			"readOnly": false,
98
			"disabled": false,
99
			"customValidationMessage": "",
100
			"attributes": [],
101
			"data": {
102
				"recordType": "ChangeSet",
103
				"collectionReadEndpoint": {
104
					"url": "admin\/campaigns\/sets",
105
					"method": "GET"
106
				},
107
				"itemReadEndpoint": {
108
					"url": "admin\/campaigns\/set\/:id",
109
					"method": "GET"
110
				},
111
				"itemUpdateEndpoint": {
112
					"url": "admin\/campaigns\/set\/:id",
113
					"method": "PUT"
114
				},
115
				"itemCreateEndpoint": {
116
					"url": "admin\/campaigns\/set\/:id",
117
					"method": "POST"
118
				},
119
				"itemDeleteEndpoint": {
120
					"url": "admin\/campaigns\/set\/:id",
121
					"method": "DELETE"
122
				},
123
				"editFormSchemaEndpoint": "admin\/campaigns\/schema\/DetailEditForm",
124
				"columns": [
125
					{"name": "Title", "field": "Name"},
126
					{"name": "Changes", "field": "_embedded.ChangeSetItems.length"},
127
					{"name": "Description", "field": "Description"}
128
				]
129
			}
130
		}, {
131
			"name": "SecurityID",
132
			"id": "Form_EditForm_SecurityID",
133
			"type": "Hidden",
134
			"component": null,
135
			"holder_id": null,
136
			"title": "Security ID",
137
			"source": null,
138
			"extraClass": "hidden",
139
			"description": null,
140
			"rightTitle": null,
141
			"leftTitle": null,
142
			"readOnly": false,
143
			"disabled": false,
144
			"customValidationMessage": "",
145
			"attributes": [],
146
			"data": []
147
		}],
148
		"actions": []
149
	}
150
}
151
JSON;
152
153
		$formName = $request->param('ID');
154
		if($formName == 'EditForm') {
155
			$response = $this->getResponse();
156
			$response->addHeader('Content-Type', 'application/json');
157
			$response->setBody($json);
158
			return $response;
159
		} else {
160
			return parent::schema($request);
161
		}
162
	}
163
164
	/**
165
	 * REST endpoint to create a campaign.
166
	 *
167
	 * @param SS_HTTPRequest $request
168
	 *
169
	 * @return SS_HTTPResponse
170
	 */
171 View Code Duplication
	public function createCampaign(SS_HTTPRequest $request) {
0 ignored issues
show
Unused Code introduced by
The parameter $request 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...
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...
172
		$response = new SS_HTTPResponse();
173
		$response->addHeader('Content-Type', 'application/json');
174
		$response->setBody(Convert::raw2json(['campaign' => 'create']));
175
176
		// TODO Implement permission check and data creation
177
178
		return $response;
179
	}
180
181
	/**
182
	 * REST endpoint to get a list of campaigns.
183
	 *
184
	 * @param SS_HTTPRequest $request
185
	 *
186
	 * @return SS_HTTPResponse
187
	 */
188
	public function readCampaigns(SS_HTTPRequest $request) {
0 ignored issues
show
Unused Code introduced by
The parameter $request 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...
189
		$response = new SS_HTTPResponse();
190
		$response->addHeader('Content-Type', 'application/json');
191
		$hal = $this->getListResource();
192
		$response->setBody(Convert::array2json($hal));
193
		return $response;
194
		}
195
196
	/**
197
	 * Get list contained as a hal wrapper
198
	 *
199
	 * @return array
200
	 */
201
	protected function getListResource() {
202
		$items = $this->getListItems();
203
		$count = $items->count();
204
		$hal = [
205
			'count' => $count,
206
			'total' => $count,
207
			'_links' => [
208
				'self' => [
209
					'href' => $this->Link('items')
210
				]
211
			],
212
			'_embedded' => ['ChangeSets' => []]
213
		];
214
		foreach($items as $item) {
215
			/** @var ChangeSet $item */
216
			$resource = $this->getChangeSetResource($item);
217
			$hal['_embedded']['ChangeSets'][] = $resource;
218
		}
219
		return $hal;
220
	}
221
222
	/**
223
	 * Build item resource from a changeset
224
	 *
225
	 * @param ChangeSet $changeSet
226
	 * @return array
227
	 */
228
	protected function getChangeSetResource(ChangeSet $changeSet) {
229
		$hal = [
230
			'_links' => [
231
				'self' => [
232
					'href' => $this->SetLink($changeSet->ID)
233
				]
234
			],
235
			'ID' => $changeSet->ID,
236
			'Name' => $changeSet->Name,
237
			'Created' => $changeSet->Created,
238
			'LastEdited' => $changeSet->LastEdited,
239
			'State' => $changeSet->State,
240
			'_embedded' => ['ChangeSetItems' => []]
241
		];
242
		foreach($changeSet->Changes() as $changeSetItem) {
243
			if(!$changeSetItem) {
244
				continue;
245
			}
246
247
			/** @var ChangesetItem $changeSetItem */
248
			$resource = $this->getChangeSetItemResource($changeSetItem);
249
			$hal['_embedded']['ChangeSetItems'][] = $resource;
250
		}
251
		return $hal;
252
	}
253
254
	/**
255
	 * Build item resource from a changesetitem
256
	 *
257
	 * @param ChangeSetItem $changeSetItem
258
	 * @return array
259
	 */
260
	protected function getChangeSetItemResource(ChangeSetItem $changeSetItem) {
261
		$hal = [
262
			'_links' => [
263
				'self' => [
264
					'href' => $this->ItemLink($changeSetItem->ID)
265
				]
266
			],
267
			'ID' => $changeSetItem->ID,
268
			'Created' => $changeSetItem->Created,
269
			'LastEdited' => $changeSetItem->LastEdited,
270
			'Title' => $changeSetItem->getTitle(),
271
			'ChangeType' => $changeSetItem->getChangeType(),
272
			'Added' => $changeSetItem->Added,
273
		];
274
		// Depending on whether the object was added implicitly or explicitly, set
275
		// other related objects.
276
		if($changeSetItem->Added === ChangeSetItem::IMPLICITLY) {
277
			$referencedItems = $changeSetItem->ReferencedBy();
278
			$referencedBy = [];
279
			foreach($referencedItems as $referencedItem) {
280
				$referencedBy[] = [
281
					'href' => $this->SetLink($referencedItem->ID)
282
				];
283
			}
284
			if($referencedBy) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $referencedBy 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...
285
				$hal['_links']['referenced_by'] = $referencedBy;
286
			}
287
		}
288
289
		return $hal;
290
	}
291
292
293
294
	/**
295
	 * Gets viewable list of campaigns
296
	 *
297
	 * @return SS_List
298
	 */
299
	protected function getListItems() {
300
		return ChangeSet::get()
301
			->filter('State', ChangeSet::STATE_OPEN)
302
			->filterByCallback(function($item) {
303
				return ($item->canView());
304
			});
305
	}
306
307
308
	/**
309
	 * REST endpoint to get a campaign.
310
	 *
311
	 * @param SS_HTTPRequest $request
312
	 *
313
	 * @return SS_HTTPResponse
314
	 */
315
	public function readCampaign(SS_HTTPRequest $request) {
0 ignored issues
show
Unused Code introduced by
The parameter $request 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...
316
		$response = new SS_HTTPResponse();
317
		$response->addHeader('Content-Type', 'application/json');
318
		$response->setBody('');
319
320
		// TODO Implement data retrieval and serialisation
321
322
		return $response;
323
	}
324
325
	/**
326
	 * REST endpoint to update a campaign.
327
	 *
328
	 * @param SS_HTTPRequest $request
329
	 *
330
	 * @return SS_HTTPResponse
331
	 */
332 View Code Duplication
	public function updateCampaign(SS_HTTPRequest $request) {
0 ignored issues
show
Unused Code introduced by
The parameter $request 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...
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...
333
		$response = new SS_HTTPResponse();
334
		$response->addHeader('Content-Type', 'application/json');
335
		$response->setBody(Convert::raw2json(['campaign' => 'update']));
336
337
		// TODO Implement data update and permission checks
338
339
		return $response;
340
	}
341
342
	/**
343
	 * REST endpoint to delete a campaign.
344
	 *
345
	 * @param SS_HTTPRequest $request
346
	 *
347
	 * @return SS_HTTPResponse
348
	 */
349
	public function deleteCampaign(SS_HTTPRequest $request) {
350
		$id = $request->param('ID');
351 View Code Duplication
		if (!$id || !is_numeric($id)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
352
            return (new SS_HTTPResponse(json_encode(['status' => 'error']), 400))
353
                ->addHeader('Content-Type', 'application/json');
354
        }
355
356
		$record = ChangeSet::get()->byID($id);
357 View Code Duplication
		if(!$record) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
358
			return (new SS_HTTPResponse(json_encode(['status' => 'error']), 404))
359
                ->addHeader('Content-Type', 'application/json');
360
		}
361
362 View Code Duplication
		if(!$record->canDelete()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
363
			return (new SS_HTTPResponse(json_encode(['status' => 'error']), 401))
364
                ->addHeader('Content-Type', 'application/json');
365
		}
366
367
		$record->delete();
368
369
		return (new SS_HTTPResponse('', 204));
370
	}
371
372
	/**
373
	 * @todo Use GridFieldDetailForm once it can handle structured data and form schemas
374
	 *
375
	 * @return Form
376
	 */
377
	public function getDetailEditForm() {
378
		return Form::create(
379
			$this,
380
			'DetailEditForm',
381
			ChangeSet::singleton()->getCMSFields(),
382
			FieldList::create(
383
				FormAction::create('save', 'Save')
384
			)
385
		);
386
	}
387
388
	/**
389
	 * Gets user-visible url to edit a specific {@see ChangeSet}
390
	 *
391
	 * @param $itemID
392
	 * @return string
393
	 */
394
	public function SetLink($itemID) {
395
		return Controller::join_links(
396
			$this->Link('set'),
397
			$itemID
398
		);
399
	}
400
401
	/**
402
	 * Gets user-visible url to edit a specific {@see ChangeSetItem}
403
	 *
404
	 * @param int $itemID
405
	 * @return string
406
	 */
407
	public function ItemLink($itemID) {
408
		return Controller::join_links(
409
			$this->Link('item'),
410
			$itemID
411
		);
412
	}
413
414
	/**
415
	 *
416
	 */
417
	public function FindReferencedChanges() {
418
419
	}
420
421
}
422