AdvancedWorkflowExtension   A
last analyzed

Complexity

Total Complexity 23

Size/Duplication

Total Lines 141
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 6

Importance

Changes 1
Bugs 0 Features 1
Metric Value
wmc 23
lcom 1
cbo 6
dl 0
loc 141
rs 10
c 1
b 0
f 1

6 Methods

Rating   Name   Duplication   Size   Complexity  
A startworkflow() 0 16 4
B updateEditForm() 0 33 4
A updateItemEditForm() 0 8 3
B updateworkflow() 0 29 6
B returnResponse() 0 11 5
A saveAsDraftWithAction() 0 4 1
1
<?php
2
/**
3
 * Handles interactions triggered by users in the backend of the CMS. Replicate this
4
 * type of functionality wherever you need UI interaction with workflow. 
5
 *
6
 * @author  [email protected]
7
 * @license BSD License (http://silverstripe.org/bsd-license/)
8
 * @package advancedworkflow
9
 */
10
class AdvancedWorkflowExtension extends LeftAndMainExtension {
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...
11
	
12
	private static $allowed_actions = array(
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...
Unused Code introduced by
The property $allowed_actions is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
13
		'updateworkflow',
14
		'startworkflow'
15
	);
16
17
	public function startworkflow($data, $form, $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...
18
		$item = $form->getRecord();
19
		$workflowID = isset($data['TriggeredWorkflowID']) ? intval($data['TriggeredWorkflowID']) : 0;
20
21
		if (!$item || !$item->canEdit()) {
22
			return;
23
		}
24
		
25
		// Save a draft, if the user forgets to do so
26
		$this->saveAsDraftWithAction($form, $item);
27
28
		$svc = singleton('WorkflowService');
29
		$svc->startWorkflow($item, $workflowID);
30
		
31
		return $this->returnResponse($form);
32
	}
33
34
	/**
35
	 * Need to update the edit form AFTER it's been transformed to read only so that the workflow stuff is still
36
	 * allowed to be added with 'write' permissions
37
	 *
38
	 * @param Form $form
39
	 */
40
	public function updateEditForm(Form $form) {
41
		Requirements::javascript(ADVANCED_WORKFLOW_DIR . '/javascript/advanced-workflow-cms.js');
42
		$svc    = singleton('WorkflowService');
43
		$p      = $form->getRecord();
44
		$active = $svc->getWorkflowFor($p);
45
46
		if ($active) {
47
48
			$fields = $form->Fields();
49
			$current = $active->CurrentAction();
50
			$wfFields = $active->getWorkflowFields();
51
52
			$allowed = array_keys($wfFields->saveableFields());
53
			$data = array();
54
			foreach ($allowed as $fieldName) {
55
				$data[$fieldName] = $current->$fieldName;
56
			}
57
58
			$fields->findOrMakeTab(
59
				'Root.WorkflowActions',
60
				_t('Workflow.WorkflowActionsTabTitle', 'Workflow Actions')
61
			);
62
			$fields->addFieldsToTab('Root.WorkflowActions', $wfFields);
63
64
			$form->loadDataFrom($data);
65
66
			if (!$p->canEditWorkflow()) {
67
				$form->makeReadonly();
68
			}
69
70
			$this->owner->extend('updateWorkflowEditForm', $form);
71
		}
72
	}
73
	
74
	public function updateItemEditForm($form) {
75
		$record = $form->getRecord();
76
		if ($record && $record->hasExtension('WorkflowApplicable')) {
77
			$actions = $form->Actions();
78
			$record->extend('updateCMSActions', $actions);
79
			$this->updateEditForm($form);
80
		}
81
	}
82
83
	/**
84
	 * Update a workflow based on user input. 
85
	 *
86
	 * @todo refactor with WorkflowInstance::updateWorkflow
87
	 * 
88
	 * @param array $data
89
	 * @param Form $form
90
	 * @param SS_HTTPRequest $request
91
	 * @return String
92
	 */
93
	public function updateworkflow($data, Form $form, $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...
94
		$svc = singleton('WorkflowService');
95
		$p = $form->getRecord();
96
		$workflow = $svc->getWorkflowFor($p);
97
		$action = $workflow->CurrentAction();
98
99
		if (!$p || !$p->canEditWorkflow()) {
100
			return;
101
		}
102
103
		$allowedFields = $workflow->getWorkflowFields()->saveableFields();
104
		unset($allowedFields['TransitionID']);
105
106
		$allowed = array_keys($allowedFields);
107
		if (count($allowed)) {
108
			$form->saveInto($action, $allowed);
0 ignored issues
show
Documentation introduced by
$allowed is of type array, but the function expects a object<FieldList>|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
109
			$action->write();
110
		}
111
112
		if (isset($data['TransitionID']) && $data['TransitionID']) {
113
			$svc->executeTransition($p, $data['TransitionID']);
114
		} else {
115
			// otherwise, just try to execute the current workflow to see if it
116
			// can now proceed based on user input
117
			$workflow->execute();
118
		}
119
120
		return $this->returnResponse($form);
121
	}
122
	
123
	protected function returnResponse($form) {
124
		if ($this->owner instanceof GridFieldDetailForm_ItemRequest) {
125
			$record = $form->getRecord();
126
			if ($record && $record->exists()) {
127
				return $this->owner->edit($this->owner->getRequest());
128
			}
129
		} 
130
		
131
		$negotiator = method_exists($this->owner, 'getResponseNegotiator') ? $this->owner->getResponseNegotiator() : Controller::curr()->getResponseNegotiator();
132
		return $negotiator->respond($this->owner->getRequest());
133
	}
134
	
135
	/**
136
	 * Ocassionally users forget to apply their changes via the standard CMS "Save Draft" button,
137
	 * and select the action button instead - losing their changes.
138
	 * Calling this from a controller method saves a draft automatically for the user, whenever a workflow action is run.
139
	 * See: #72 and #77
140
	 * 
141
	 * @param \Form $form
142
	 * @param \DataObject $item
143
	 * @return void
144
	 */
145
	protected function saveAsDraftWithAction(Form $form, DataObject $item) {
146
		$form->saveInto($item);
147
		$item->write();
148
	}	
149
150
}
151