Completed
Push — 16.1 ( c4b782...6c2a65 )
by Hadi
16:11
created

calendar_owner_etemplate_widget   B

Complexity

Total Complexity 36

Size/Duplication

Total Lines 254
Duplicated Lines 1.57 %

Coupling/Cohesion

Components 1
Dependencies 8

Importance

Changes 0
Metric Value
dl 4
loc 254
rs 8.8
c 0
b 0
f 0
wmc 36
lcom 1
cbo 8

4 Methods

Rating   Name   Duplication   Size   Complexity  
C beforeSendToClient() 4 75 11
A validate() 0 16 4
D ajax_owner() 0 110 17
B get_owner_label() 0 24 4

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
/**
3
 * EGroupware - eTemplate serverside of owner list widget
4
 *
5
 * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
6
 * @package etemplate
7
 * @subpackage api
8
 * @link http://www.egroupware.org
9
 * @author Nathan Gray
10
 * @copyright 2016 Nathan Gray
11
 * @version $Id$
12
 */
13
14
use EGroupware\Api;
15
use EGroupware\Api\Link;
16
use EGroupware\Api\Framework;
17
use EGroupware\Api\Etemplate;
18
19
/**
20
 * eTemplate tag list widget
21
 *
22
 * The naming convention is <appname>_<subtype>_etemplate_widget
23
 */
24
class calendar_owner_etemplate_widget extends Etemplate\Widget\Taglist
25
{
26
27
	/**
28
	 *  Make sure all the needed select options are there
29
	 *
30
	 * @param string $cname
31
	 * @param array $expand values for keys 'c', 'row', 'c_', 'row_', 'cont'
32
	 */
33
	public function beforeSendToClient($cname, array $expand=null)
34
	{
35
36
		Framework::includeJS('.','et2_widget_owner','calendar');
37
		Framework::includeCSS('calendar','calendar');
38
39
		$bo = new calendar_bo();
40
41
		$form_name = self::form_name($cname, $this->id, $expand);
42
43
		$value =& self::get_array(self::$request->content, $form_name);
44
45 View Code Duplication
		if (!is_array(self::$request->sel_options[$form_name]))
46
		{
47
			self::$request->sel_options[$form_name] = array();
48
		}
49
		$sel_options =& self::$request->sel_options[$form_name];
50
51
		// Get user accounts, formatted nicely for grouping and matching
52
		// the ajax call calendar_uiforms->ajax_owner() - users first
53
		$accounts = array();
54
		$list = array('accounts', 'owngroups');
55
		foreach($list as $type)
56
		{
57
			$account_options = array('account_type' => $type);
58
			$accounts_type = Api\Accounts::link_query('',$account_options);
59
			if($type == 'accounts')
60
			{
61
				$accounts_type = array_intersect_key($accounts_type, $GLOBALS['egw']->acl->get_grants('calendar'));
62
			}
63
			$accounts += $accounts_type;
64
		}
65
		$sel_options += array_map(
66
			function($account_id, $account_name) {
67
				return array(
68
					'value' => ''.$account_id,
69
					'label' => $account_name,
70
					'app' => lang('api-accounts')
71
				);
72
			},
73
			array_keys($accounts), $accounts
74
		);
75
76
		if(!is_array($value))
77
		{
78
			// set value with an empty string only if sel options are not
79
			// loaded, for example: setting calendar owner via URL when
80
			// calendar app is not yet loaded.
81
			$value = !empty($sel_options) ? array(): explode(',', $value);
82
		}
83
		
84
		// Add external owners that a select account widget will not find
85
		foreach($value as &$owner)
86
		{
87
			$label = self::get_owner_label($owner);
88
			$info = array();
89
			if(!is_numeric($owner))
90
			{
91
				$resource = $bo->resources[substr($owner, 0,1)];
92
				if($resource['info'] && !($info = $bo->resource_info($owner)))
93
				{
94
					continue;	// ignore that resource, we would get a PHP Fatal: Unsupported operand types
95
				}
96
			}
97
			else if (!in_array($owner, array_keys($accounts)))
98
			{
99
				$resource = array('app'=> 'api-accounts');
100
			}
101
			else
102
			{
103
				continue;
104
			}
105
			$sel_options[] = array('value' => $owner, 'label' => $label, 'app' => lang($resource['app'])) + $info;
106
		}
107
	}
108
109
	/**
110
	 * Validate input
111
	 *
112
	 * @param string $cname current namespace
113
	 * @param array $expand values for keys 'c', 'row', 'c_', 'row_', 'cont'
114
	 * @param array $content
115
	 * @param array &$validated=array() validated content
116
	 */
117
	public function validate($cname, array $expand, array $content, &$validated=array())
118
	{
119
		$form_name = self::form_name($cname, $this->id, $expand);
120
121
		if (!$this->is_readonly($cname, $form_name))
122
		{
123
			$value = $value_in =& self::get_array($content, $form_name);
124
			if(!is_array($value))
125
			{
126
				$value = Array($value);
127
			}
128
129
			$valid =& self::get_array($validated, $form_name, true);
130
			if (true) $valid = $value;
131
		}
132
	}
133
	/**
134
	 * Handle ajax searches for owner across all supported resources
135
	 *
136
	 * @return Array List of matching results
137
	 */
138
	public static function ajax_owner($id = null)
139
	{
140
		// Handle a request for a single ID
141
		if($id)
142
		{
143
			$label = self::get_owner_label($id);
144
			Api\Json\Response::get()->data($label);
145
			return $label;
146
		}
147
148
		$bo = new calendar_bo();
149
		$query = $_REQUEST['query'];
150
151
		// Arbitrarily limited to 50 / resource
152
		$options = array('start' => 0, 'num_rows' => 50,
153
			// Filter accounts out of addressbook
154
			'filter' => array('account_id' => null)) +
155
			array_diff_key($_REQUEST, array_flip(array('menuaction','query')));
156
		$results = array();
157
158
		// Contacts matching accounts the user does not have permission for cause
159
		// confusion as user selects the contact and there's nothing there, so
160
		// we remove those contacts
161
		$remove_contacts = array();
162
163
		$resources = array_merge(array('' => $bo->resources['']),$bo->resources);
164
		foreach($resources as $type => $data)
165
		{
166
			$mapped = array();
167
			$_results = array();
168
169
			// Handle Api\Accounts seperately
170
			if($type == '')
171
			{
172
				$account_options = $options + array('account_type' => 'both');
173
				$_results += $remove_contacts = Api\Accounts::link_query($query, $account_options);
174
				if (!empty($_REQUEST['checkgrants']))
175
				{
176
					$grants = $GLOBALS['egw']->acl->get_grants('calendar');
177
					$_results = array_intersect_key($_results, $grants);
178
				}
179
			}
180
			// App provides a custom search function
181
			else if ($data['app'] && $data['search'])
182
			{
183
				$_results = call_user_func_array($data['search'], array($query, $options));
184
			}
185
			// Use standard link registry
186
			else if ($data['app'] && Link::get_registry($data['app'], 'query'))
187
			{
188
				$_results = Link::query($data['app'], $query,$options);
189
			}
190
191
			// There are always special cases
192
			switch ($type)
193
			{
194
				case 'l':
195
					// Include mailing lists
196
					$contacts_obj = new Api\Contacts();
197
					$lists = array_filter(
198
						$contacts_obj->get_lists(Api\Acl::READ),
199
						function($element) use($query) {
200
							return (stripos($element, $query) !== false);
201
						}
202
					);
203
					foreach($lists as $list_id => $list)
204
					{
205
						$_results[$list_id] = array(
206
							'label' => $list,
207
							'resources' => $bo->enum_mailing_list($type.$list_id)
208
						);
209
					}
210
					break;
211
			}
212
			if(!$_results)
213
			{
214
				continue;
215
			}
216
217
			foreach(array_unique($_results, SORT_REGULAR) as $id => $title)
218
			{
219
				if($id && $title)
220
				{
221
					// Magicsuggest uses id, not value.
222
					$value = array(
223
						'id' => $type.$id,
224
						'value'=> $type.$id,
225
						'label' => $title,
226
						'app'	=> lang($data['app'])
227
					);
228
					if(is_array($value['label']))
229
					{
230
						$value = array_merge($value, $value['label']);
231
					}
232
					$mapped[] = $value;
233
				}
234
			}
235
			if(count($mapped))
236
			{
237
				$results = array_merge($results, $mapped);
238
			}
239
		}
240
241
		// switch regular JSON response handling off
242
		Api\Json\Request::isJSONRequest(false);
243
244
		header('Content-Type: application/json; charset=utf-8');
245
		echo json_encode($results);
246
		exit();
247
	}
248
249
	/**
250
	 * Get just the label for a single owner
251
	 * @param string $id
252
	 */
253
	public static function get_owner_label($id)
254
	{
255
		static $bo;
256
		if(!$bo) $bo = new calendar_bo();
257
258
		$id = ''.$id;
259
		if(!is_numeric($id))
260
		{
261
			$resource = $bo->resources[substr($id, 0,1)];
262
			$label = Link::title($resource['app'], substr($id,1));
263
264
			// Could not get via link, try via resources info
265
			if($label === false)
266
			{
267
				$info = ExecMethod($resource['info'], substr($id,1));
0 ignored issues
show
Deprecated Code introduced by
The function ExecMethod() has been deprecated with message: use autoloadable class-names, instanciate and call method or use static methods

This function has been deprecated. The supplier of the file has supplied an explanatory message.

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

Loading history...
268
				$label = $info[0]['name'];
269
			}
270
		}
271
		else
272
		{
273
			$label = Link::title('api-accounts',$id);
274
		}
275
		return $label;
276
	}
277
}
278