smarty_function_appForm()   F
last analyzed

Complexity

Conditions 39
Paths > 20000

Size

Total Lines 124
Code Lines 86

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 1560

Importance

Changes 0
Metric Value
cc 39
eloc 86
nc 157810689
nop 2
dl 0
loc 124
ccs 0
cts 97
cp 0
crap 1560
rs 0
c 0
b 0
f 0

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
 *     'cssClass' => set additional css classes for the form
63
 *     'formData' => any injected form data that the form needs to
64
 *       draw itself regardless of new or old
65
 *     'submitLabel' => a submit label or 'Save'
66
 *     'buttons' => an array of buttons as [
67
 *         ['name'=>'abc', 'label'=>'Abc', 'class'=>'additional classes'],...]
68
 *       ]. These will override the default submit button.
69
 *     'assignForm' => set this to change the name of the assigned form parameter
70
 *       (default 'form')
71
 *     'assignSubmitted' => set this to use a different submitted parameter
72
 *       (default 'submitted')
73
 *     'action' => url to go to if you don't want to handle the form in the same page
74
 *     [NOT YET AVAILABLE] 'fieldDefaults' => set default values for fields as
75
 *       ['field'=>'default']
76
 *     [NOT YET AVAILABLE] 'mapFilters' => a set of ['formField' => ['tableField'=>'value',...]] to filter
77
 *       dynamic maps extracted from other tables
78
 *     [NOT YET AVAILABLE] 'mapFields' => a set of form field = ['tableField's] that you want returned
79
 *       in a dynamic map if not the default mapped field. You can add a 'format'
80
 *       key with sub array ['concat', 'prefix', 'postfix'] to format how the
81
 *       fields will be combined into the map
82
 *     'enableAjaxValidation' => bool  whether or not to use ajax validation
83
 *     'enableAjaxSubmission' => bool  whether or not to use ajax submission
84
 *     'ajaxValidationUrl' => set to the URL for AJAX validation if not the default
85
 *     'dataSources' => set of sourceKey sourceUuid pairs for all required data sources
86
 *       These would have been defined in the application form builder
87
 *     'initialiseFromDds' => set of classKey=>ddsUuid pairs for any classes that need
88
 *       to point to a preexisting Daedalus table row rather than create a new one
89
 *     'readOnly' => set to true if you want the form to be read only
90
 *     'printOnly' => set to true if you want to print the form
91
 *     'name' => the name of the form if not the default
92
 *
93
 * @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...
94
 * @return null
95
 * @throws
96
 */
97
function smarty_function_appForm($params, $template)
98
{
99
	// As this can be called multiple times within the rendering of pages we
100
	// need to ensure we don't fetch items from the database more than necessary
101
	// or handle the form more than once otherwise we can create additional entries
102
	static $handledObjects = [];
103
	static $forms = [];
104
	static $appFormClasses = [];
105
	static $appFormObjects = [];
106
107
	$appForm = 'applicationForm';
108
	// process the parameters
109
	if (!isset($params['classType']))
110
		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

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