Passed
Push — dougall-pheobe-database-map-fi... ( ...2d7731 )
by
unknown
22:10
created

smarty_function_appForm()   F

Complexity

Conditions 38
Paths > 20000

Size

Total Lines 122
Code Lines 84

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 1482

Importance

Changes 0
Metric Value
eloc 84
dl 0
loc 122
rs 0
c 0
b 0
f 0
cc 38
nc 78905345
nop 2
ccs 0
cts 95
cp 0
crap 1482

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * Manage an application form
5
 *
6
 * Usage:
7
 * a) creating a new form of type abc which will set a $form and $submitted
8
 * parameter for use in the template
9
 *
10
 * ```
11
 *    {appForm classType='abc' }
12
 *    {if ($submitted)}
13
 *        // do something
14
 *    {else}
15
 *        {$form->run()}
16
 *    {/if}
17
 * ```
18
 * You can change the form and submitted parameter names using assignForm
19
 * and assignSubmitted respectively.
20
 *
21
 * b) editing an existing form of type 'abc' and uuid of $uuid
22
 *
23
 * ```
24
 *    {appForm classType='abc' uuid=$uuid}
25
 * ```
26
 *
27
 * c) changing the name of the assigned form parameter and submitted results
28
 *
29
 * ```
30
 *    {appForm classType='abc' assignForm='myForm' assignSubmitted='myFormSubmitted'}
31
 *    {if ($myFormSubmitted)}
32
 *        // do something
33
 *    {else}
34
 *        {$myForm->run()}
35
 *    {/if}
36
 * ```
37
 *
38
 * d) Assign required data sources to a form. If sources are required, this will
39
 * complain if they are not set.
40
 *
41
 * ```
42
 *    {appForm classType='abc' dataSources=['sourceKey'=>'soureUuid',...]}
43
 * ```
44
 *
45
 * e) You can set whether or not the form can be edited by passing in readOnly. This
46
 * defaults to false.
47
 * ```
48
 *    {appForm classType='abc' readOnly=true}
49
 * ````
50
 *
51
 * @param $params
52
 *   Required parameters
53
 *   -------------------
54
 *     'classType'  => the class type of the form in Phoebe
55
 *
56
 *   Optional Parameters
57
 *   -------------------
58
 *     'uuid' => the form uuid if this is not a new form
59
 *     'id' => an html id for the form. If not set the uuid is used, or failing
60
 *       that the form type.
61
 *     'label' => the form label if not using the default
62
 *     'formData' => any injected form data that the form needs to
63
 *       draw itself regardless of new or old
64
 *     'submitLabel' => a submit label or 'Save'
65
 *     'buttons' => an array of buttons as [
66
 *         ['name'=>'abc', 'label'=>'Abc', 'class'=>'additional classes'],...]
67
 *       ]. These will override the default submit button.
68
 *     'assignForm' => set this to change the name of the assigned form parameter
69
 *       (default 'form')
70
 *     'assignSubmitted' => set this to use a different submitted parameter
71
 *       (default 'submitted')
72
 *     'action' => url to go to if you don't want to handle the form in the same page
73
 *     [NOT YET AVAILABLE] 'fieldDefaults' => set default values for fields as
74
 *       ['field'=>'default']
75
 *     [NOT YET AVAILABLE] 'mapFilters' => a set of ['formField' => ['tableField'=>'value',...]] to filter
76
 *       dynamic maps extracted from other tables
77
 *     [NOT YET AVAILABLE] 'mapFields' => a set of form field = ['tableField's] that you want returned
78
 *       in a dynamic map if not the default mapped field. You can add a 'format'
79
 *       key with sub array ['concat', 'prefix', 'postfix'] to format how the
80
 *       fields will be combined into the map
81
 *     'enableAjaxValidation' => bool  whether or not to use ajax validation
82
 *     'enableAjaxSubmission' => bool  whether or not to use ajax submission
83
 *     'ajaxValidationUrl' => set to the URL for AJAX validation if not the default
84
 *     'dataSources' => set of sourceKey sourceUuid pairs for all required data sources
85
 *       These would have been defined in the application form builder
86
 *     'initialiseFromDds' => set of classKey=>ddsUuid pairs for any classes that need
87
 *       to point to a preexisting Daedalus table row rather than create a new one
88
 *     'readOnly' => set to true if you want the form to be read only
89
 *     'printOnly' => set to true if you want to print the form
90
 *     'name' => the name of the form if not the default
91
 *
92
 * @param $template  the smarty template
0 ignored issues
show
Bug introduced by
The type the was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
93
 * @return null
94
 * @throws
95
 */
96
function smarty_function_appForm($params, $template)
97
{
98
	// As this can be called multiple times within the rendering of pages we
99
	// need to ensure we don't fetch items from the database more than necessary
100
	// or handle the form more than once otherwise we can create additional entries
101
	static $handledObjects = [];
102
	static $forms = [];
103
	static $appFormClasses = [];
104
	static $appFormObjects = [];
105
106
	$appForm = 'applicationForm';
107
	// process the parameters
108
	if (!isset($params['classType']))
109
		throw new \RuntimeException("You must pass in the form's classType otherwise we don't which form it is. You passed in: ".print_r($params,true));
0 ignored issues
show
Bug introduced by
Are you sure print_r($params, true) of type string|true can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

109
		throw new \RuntimeException("You must pass in the form's classType otherwise we don't which form it is. You passed in: "./** @scrutinizer ignore-type */ print_r($params,true));
Loading history...
110
	$classType = $params['classType'];
111
	$uuid = !empty($params['uuid']) ? $params['uuid'] : null;
112
	$id = !empty($params['id']) ? $params['id'] : null;
113
	$formName = !empty($params['name']) ? $params['name'] : null;
114
	$saveOptions = !empty($params['submitLabel']) ? ['label'=>$params['submitLabel']] : [];
115
	$buttons = !empty($params['buttons']) ? $params['buttons'] : null;
116
	$label = !empty($params['label']) ? $params['label'] : null;
117
	$action = !empty($params['action']) ? $params['action'] : null;
118
	$assignForm = !empty($params['assignForm']) ? $params['assignForm'] : 'form';
119
	$assignSubmitted = !empty($params['assignSubmitted']) ? $params['assignSubmitted'] : 'submitted';
120
	$dataSources = !empty($params['dataSources']) ? $params['dataSources'] : [];
121
	$readOnly = isset($params['readOnly']) ? (bool)$params['readOnly'] : false;
122
	$printOnly = isset($params['printOnly']) ? (bool)$params['printOnly'] : false;
123
	$enableAjaxValidation = isset($params['enableAjaxValidation']) ? (bool)$params['enableAjaxValidation'] : true;
124
	$enableAjaxSubmission = isset($params['enableAjaxSubmission']) ? (bool)$params['enableAjaxSubmission'] : false;
125
	$ajaxValidationUrl = !empty($params['ajaxValidationUrl']) ? $params['ajaxValidationUrl'] : '/phoebe/appforms/index/validate-form';
126
	$initialiseFromDds = !empty($params['initialiseFromDds']) ? $params['initialiseFromDds'] : null;
127
	//$mapFilters = !empty($params['mapFilters']) ? $params['mapFilters'] : [];
128
	//$mapFields = !empty($params['mapFields']) ? $params['mapFields'] : [];
129
130
	// get hold of the form class
131
	$phoebe = neon('phoebe')->getIPhoebeType('applicationForm');
132
	if (array_key_exists($classType, $appFormClasses)) {
133
		$class = $appFormClasses[$classType];
134
	} else {
135
		$class = $phoebe->getClass($classType);
136
		$appFormClasses[$classType] = $class;
137
	}
138
	if (!$class)
139
		throw new \RuntimeException('Error - cannot get hold of the form class '.$classType);
140
141
	$requiredDataSources = array_keys($class->getRequiredDataSources());
142
	$missingDataSources = array_diff($requiredDataSources, array_keys($dataSources));
143
	if (count($missingDataSources)) {
144
		throw new \RuntimeException('Error - you need to provide uuids for the following classes: '.implode(', ',$missingDataSources));
145
	}
146
147
	// prefix invalid (HTML5) ids with a letter
148
	$id = ($id ? $id : ($uuid ? $uuid : null));
149
	if ($id) {
150
		if (is_numeric($id[0]) || $id[0] == '-' || $id[0] == '_')
151
			$id = 'z' . $id;
152
	}
153
154
	// get hold of the form definition
155
	$formKey = md5(serialize($params));
156
	if (array_key_exists($formKey, $forms)) {
157
		$form = $forms[$formKey];
158
	} else {
159
		// creating a form is expensive so do it only once during a render
160
		$form = neon('phoebe')->getForm($appForm, $classType, [
161
			'id' => $id,
162
			'name' => $formName,
163
			'uuid' => $uuid,
164
			'label'=>$label,
165
			'save'=>$saveOptions,
166
			'buttons' => $buttons,
167
			'readOnly' => $readOnly,
168
			'printOnly' => $printOnly,
169
			'action'=>$action,
170
			'enableAjaxValidation' => $enableAjaxValidation,
171
			'enableAjaxSubmission' => $enableAjaxSubmission,
172
			'ajaxValidationUrl' => url([$ajaxValidationUrl, 'name'=>$formName, 'classType' => $classType]),
173
			'initialiseFromDds' => $initialiseFromDds,
174
			//'mapFilters'=>$mapFilters,
175
			//'mapFields'=>$mapFields
176
		]);
177
178
		$forms[$formKey] = $form;
179
	}
180
181
	// handle the form processing saving or displaying
182
	$object = null;
183
	if (array_key_exists($uuid, $appFormObjects)) {
184
		$object = $appFormObjects[$uuid];
185
	} else if ($uuid) {
186
		$phoebe = neon('phoebe')->getIPhoebeType($appForm);
187
		$object = $phoebe->getObject($uuid);
188
		if (!$object)
189
			throw new \yii\web\NotFoundHttpException('The requested form was not found. Uuid='.$uuid);
190
		$appFormObjects[$uuid] = $object;
191
	}
192
	$template->assign($assignSubmitted, false);
193
194
	// is this a submitted form ready for saving
195
	if (!$readOnly) {
196
		$request = neon()->request;
197
		if ($request->isPost && !in_array($uuid, $handledObjects) && $form->processRequest()) {
198
			if (!$object && !$uuid) {
199
				$object = $phoebe->addObject($classType);
200
				$uuid = $object->_uuid;
201
			}
202
			$object->setDataSources($dataSources);
203
			$object->editObject($form->getData());
204
			// load the data back again as it will have changed
205
			$object = $phoebe->getObject($uuid);
206
			$appFormObjects[$uuid] = $object;
207
			$template->assign($assignSubmitted, true);
208
			$handledObjects[] = $uuid;
209
		}
210
	}
211
	// is this a form we should load from the database
212
	if ($object) {
213
		$form->loadFromDb($object->data);
214
	}
215
216
	// assign the resulting form
217
	$template->assign($assignForm, $form);
218
}
219
220