admin_config::index()   F
last analyzed

Complexity

Conditions 45
Paths > 20000

Size

Total Lines 200
Code Lines 112

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 2 Features 0
Metric Value
cc 45
eloc 112
c 3
b 2
f 0
nc 1766017
nop 1
dl 0
loc 200
rs 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
 * EGgroupware admin - New et2 site configuration
4
 *
5
 * @link http://www.egroupware.org
6
 * @author Ralf Becker <[email protected]>
7
 * @package admin
8
 * @copyright (c) 2016-18 by Ralf Becker <[email protected]>
9
 * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
10
 */
11
12
use EGroupware\Api;
13
14
/**
15
 * New site configuration for all apps using eTemplate2 $app/templates/default/config.xet
16
 */
17
class admin_config
18
{
19
	var $public_functions = array('index' => True);
20
21
	/**
22
	 * Upload function to store anonymous images into instance files_dir/anon_images
23
	 *
24
	 * @param array $file file info array
25
	 * @param array|string $value current value of login_background_file
26
	 *
27
	 */
28
	function ajax_upload_anon_images ($file, $value)
29
	{
30
		if (!isset($GLOBALS['egw_info']['user']['apps']['admin'])) die('no rights to be here!');
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
31
		$path = $GLOBALS['egw_info']['server']['files_dir'].'/anon-images';
32
		$success = false;
33
		$response = Api\Json\Response::get();
34
		if (is_array($file) && is_writable(dirname($path)))
35
		{
36
			if (!is_dir($path)) mkdir ($path);
37
			$tmp_file = array_keys($file);
38
			$destination = $path.'/'.$file[$tmp_file[0]]['name'];
39
			$success = rename($GLOBALS['egw_info']['server']['temp_dir'].'/'.$tmp_file[0],$destination);
40
		}
41
		if ($success)
42
		{
43
			$value = array_merge($value, array(
44
				$GLOBALS['egw_info']['server']['webserver_url'].'/api/anon_images.php?src='.urlencode($file[$tmp_file[0]]['name']).'&'.filemtime($destination),
45
			));
46
			$response->data($value);
47
		}
48
		else
49
		{
50
			$response->error(lang('Failed to upload %1',$destination));
0 ignored issues
show
Unused Code introduced by
The call to lang() has too many arguments starting with $destination. ( Ignorable by Annotation )

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

50
			$response->error(/** @scrutinizer ignore-call */ lang('Failed to upload %1',$destination));

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
51
		}
52
	}
53
54
	/**
55
	 * Removes images from anon-images directory
56
	 *
57
	 * @param type $files
58
	 */
59
	function remove_anon_images ($files)
60
	{
61
		if (!isset($GLOBALS['egw_info']['user']['apps']['admin'])) die('no rights to be here!');
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
62
		if ($files)
0 ignored issues
show
introduced by
$files is of type type, thus it always evaluated to true.
Loading history...
63
		{
64
			$base = $GLOBALS['egw_info']['server']['files_dir'].'/anon-images';
65
			foreach ($files as $file)
66
			{
67
				$parts2 = explode('anon_images.php?src=', $file);
68
				$parts = explode('&', $parts2[1]);
69
				$path = $base.'/'.urldecode($parts[0]);
70
				if (is_writable(dirname($base)) && file_exists($path))
71
				{
72
					unlink($path);
73
				}
74
			}
75
		}
76
	}
77
78
	/**
79
	 * List of configs
80
	 *
81
	 * @param type $_content
82
	 * @throws Api\Exception\WrongParameter
83
	 */
84
	function index($_content=null)
85
	{
86
		if (is_array($_content))
0 ignored issues
show
introduced by
The condition is_array($_content) is always false.
Loading history...
87
		{
88
			$_appname = $_content['appname'];
89
		}
90
		elseif (!empty($_GET['appname']) && isset($GLOBALS['egw_info']['apps'][$_GET['appname']]))
91
		{
92
			$_appname = $_GET['appname'];
93
		}
94
		else
95
		{
96
			throw new Api\Exception\WrongParameter("Wrong or missing appname parameter!");
97
		}
98
		if ($GLOBALS['egw']->acl->check('site_config_acce',1,'admin'))
99
		{
100
			Api\Framework::redirect_link('/index.php');
101
		}
102
103
		// load the translations of the app we show too, so they dont need to be in admin!
104
		if ($_appname != 'admin')
105
		{
106
			Api\Translation::add_app($_appname);
107
		}
108
109
		switch($_appname)
110
		{
111
			case 'admin':
112
			case 'addressbook':
113
			case 'calendar':
114
			case 'preferences':
115
				$appname = $_appname;
116
				$config_appname = 'phpgwapi';
117
				break;
118
			case 'phpgwapi':
119
			case '':
120
				/* This keeps the admin from getting into what is a setup-only config */
121
				Api\Framework::redirect_link('/admin/index.php?ajax=true');
122
				break;
123
			default:
124
				$appname = $_appname;
125
				$config_appname = $appname;
126
				break;
127
		}
128
129
		$c = new Api\Config($config_appname);
130
		$old = (array)$c->read_repository();
131
		if ($_content['cancel'] || ($_content['save'] || $_content['apply']) && $GLOBALS['egw']->acl->check('site_config_acce',2,'admin'))
132
		{
133
			Api\Framework::redirect_link('/admin/index.php?ajax=true');
134
		}
135
136
		if ($_content['save'] || $_content['apply'])
137
		{
138
			// support old validation hooks
139
			$_POST = array('newsettings' => &$_content['newsettings']);
140
141
			// Remove actual files (cleanup) of deselected urls from login_background_file
142
			if (!empty($c->config_data['login_background_file']))
0 ignored issues
show
Deprecated Code introduced by
The property EGroupware\Api\Config::$config_data has been deprecated: dont use direct ( Ignorable by Annotation )

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

142
			if (!empty(/** @scrutinizer ignore-deprecated */ $c->config_data['login_background_file']))

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
143
			{
144
				$this->remove_anon_images(array_diff((array)$c->config_data['login_background_file'], (array)$_content['newsettings']['login_background_file']));
0 ignored issues
show
Deprecated Code introduced by
The property EGroupware\Api\Config::$config_data has been deprecated: dont use direct ( Ignorable by Annotation )

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

144
				$this->remove_anon_images(array_diff((array)/** @scrutinizer ignore-deprecated */ $c->config_data['login_background_file'], (array)$_content['newsettings']['login_background_file']));

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
145
			}
146
147
			/* Load hook file with functions to validate each config (one/none/all) */
148
			$errors = Api\Hooks::single(array(
149
				'location' => 'config_validate',
150
			)+(array)$_content['newsettings'], $appname);
151
			if (!is_string($errors)) $errors = '';	// old hooks allways return true
152
153
			foreach($_content['newsettings'] as $key => $config)
154
			{
155
				if ($config)
156
				{
157
					$c->config_data[$key] = $config;
0 ignored issues
show
Deprecated Code introduced by
The property EGroupware\Api\Config::$config_data has been deprecated: dont use direct ( Ignorable by Annotation )

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

157
					/** @scrutinizer ignore-deprecated */ $c->config_data[$key] = $config;

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
158
					if (in_array($key, (array)$GLOBALS['egw_info']['server']['found_validation_hook'], true) && function_exists($key))
159
					{
160
						call_user_func($key, $config, $c);
161
						if($GLOBALS['config_error'])
162
						{
163
							$errors .= lang($GLOBALS['config_error']) . "\n";
164
							$GLOBALS['config_error'] = False;
165
						}
166
					}
167
				}
168
				// don't erase passwords, since we also don't print them
169
				elseif(strpos($key,'passwd') === false && strpos($key,'password') === false && strpos($key,'root_pw') === false)
170
				{
171
					unset($c->config_data[$key]);
0 ignored issues
show
Deprecated Code introduced by
The property EGroupware\Api\Config::$config_data has been deprecated: dont use direct ( Ignorable by Annotation )

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

171
					unset(/** @scrutinizer ignore-deprecated */ $c->config_data[$key]);

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
172
				}
173
			}
174
			if(in_array('final_validation', (array)$GLOBALS['egw_info']['server']['found_validation_hook']) &&
175
				function_exists('final_validation'))
176
			{
177
				final_validation($_content['newsettings']);
178
				if($GLOBALS['config_error'])
179
				{
180
					$errors .= lang($GLOBALS['config_error']) . "\n";
181
					$GLOBALS['config_error'] = False;
182
				}
183
				unset($GLOBALS['egw_info']['server']['found_validation_hook']);
184
			}
185
186
			// do not allow to save config, if there are errors
187
			if (!$errors)
188
			{
189
				// compute real changes and their old values (null for removals)
190
				$modifications = array_udiff_assoc($c->config_data, $old, function($a, $b)
0 ignored issues
show
Deprecated Code introduced by
The property EGroupware\Api\Config::$config_data has been deprecated: dont use direct ( Ignorable by Annotation )

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

190
				$modifications = array_udiff_assoc(/** @scrutinizer ignore-deprecated */ $c->config_data, $old, function($a, $b)

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
191
				{
192
					return (int)($a != $b);	// necessary to kope with arrays
193
				});
194
				$removals = array_diff(array_udiff_assoc($old, $c->config_data, function($a, $b)
0 ignored issues
show
Deprecated Code introduced by
The property EGroupware\Api\Config::$config_data has been deprecated: dont use direct ( Ignorable by Annotation )

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

194
				$removals = array_diff(array_udiff_assoc($old, /** @scrutinizer ignore-deprecated */ $c->config_data, function($a, $b)

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
195
				{
196
					return (int)(!empty($a) && $a != $b);
197
				}), array(null, ''));
198
				$set = array_merge(array_fill_keys(array_keys($removals), null), $modifications);
199
				$old = array_filter($old, function($key) use ($set)
200
				{
201
					return array_key_exists($key, $set);
202
				}, ARRAY_FILTER_USE_KEY);
203
				if ($set)
0 ignored issues
show
Bug Best Practice introduced by
The expression $set 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...
204
				{
205
					$cmd = new admin_cmd_config($_appname, $set, $old,
206
						(array)$_content['admin_cmd'], $config_appname === 'phpgwapi');
207
					$msg = $cmd->run();
208
				}
209
				else
210
				{
211
					$msg = lang('Nothing to save.');
212
				}
213
				// allow apps to hook into configuration dialog to eg. save some stuff outside configuration
214
				$_content['location'] = 'config_after_save';
215
				Api\Hooks::single($_content, $_appname);
216
			}
217
			if(!$errors && !$_content['apply'])
218
			{
219
				Api\Framework::message($msg, 'success');
220
				Api\Framework::redirect_link('/index.php', array(
221
					'menuaction' => 'admin.admin_ui.index',
222
					'ajax' => 'true'
223
				), 'admin');
224
			}
225
		}
226
227
		if($errors)
228
		{
229
			Api\Framework::message(lang('Error') . ': ' . $errors, 'error');
230
			unset($errors);
231
			unset($GLOBALS['config_error']);
232
233
			// keep old content on error
234
			$config = $_content['newsettings'];
235
		}
236
		else
237
		{
238
			if ($_content['apply'])
239
			{
240
				Api\Framework::message($msg, 'success');
241
			}
242
			$config = $c->read_repository();
243
		}
244
		$sel_options = $readonlys = array();
245
		// call "config" hook, allowing apps to overwrite config, eg. set default values,
246
		// or return options in "sel_options" keys
247
		$config['location'] = 'config';
248
		// let config hook know, this is an inital call and not one after user hits [Apply] button
249
		$config['initial-call'] = is_null($_content);
250
		$ret = Api\Hooks::single($config, $appname);
251
		if (is_array($ret))
252
		{
253
			if (isset($ret['sel_options'])) $sel_options = $ret['sel_options'];
254
			$config = array_merge($config, $ret);
255
		}
256
257
		$tmpl = new Api\Etemplate($appname.'.config');
258
		$path = (parse_url($tmpl->rel_path, PHP_URL_SCHEME) !== 'vfs' ? EGW_SERVER_ROOT : '').$tmpl->rel_path;
259
		$content = array(
260
			'tabs' => $_content['tabs'],
261
			'tabs2' => $_content['tabs2'],
262
			'template' => $appname.'.config',
263
			'newsettings' => array(),
264
		);
265
266
		// for security reasons we do not send all config to client-side, but only ones mentioned in templates
267
		$matches = null;
268
		preg_match_all('/id="newsettings\[([^]]+)\]/', file_get_contents($path), $matches, PREG_PATTERN_ORDER);
269
		foreach($matches[1] as $name)
270
		{
271
			$content['newsettings'][$name] = isset($config[$name]) ? $config[$name] : '';
272
		}
273
274
		// make everything readonly and remove save/apply button, if user has not rights to store config
275
		if ($GLOBALS['egw']->acl->check('site_config_acce',2,'admin'))
276
		{
277
			$readonlys[__ALL__] = true;
0 ignored issues
show
Bug introduced by
The constant __ALL__ was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
278
			$readonlys['cancel'] = false;
279
		}
280
281
		$tmpl->read('admin.site-config');
282
		$method = (get_called_class() == __CLASS__) ? 'admin.admin_config.index' : "$appname.".get_called_class().'.'.__FUNCTION__;
283
		$tmpl->exec($method, $content, $sel_options, $readonlys, array('appname' => $appname));
284
	}
285
}
286