resources_reserve::ajax_update_planner()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 5
nc 1
nop 2
dl 0
loc 7
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * eGroupWare - resources
4
 * Book a single resource through sitemgr module, not the normal method
5
 *
6
 * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
7
 * @package resources
8
 * @link http://www.egroupware.org
9
 * @author Nathan Gray
10
 * @version $Id$
11
 */
12
13
use EGroupware\Api;
14
use EGroupware\Api\Link;
15
use EGroupware\Api\Framework;
16
17
class resources_reserve {
18
19
	public function __construct() {
20
		$this->tmpl = new etemplate();
0 ignored issues
show
Bug introduced by
The type etemplate 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...
Bug Best Practice introduced by
The property tmpl does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
21
		$this->bo = new resources_bo();
0 ignored issues
show
Bug Best Practice introduced by
The property bo does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
22
	}
23
24
	/**
25
	 * Book a resource
26
	 */
27
	public function book($content = array(), $arguments = array())
28
	{
29
		Framework::includeJS('jscalendar','calendar');
30
		$data = array();
31
		$readonlys = array();
32
		$display_days = $_GET['planner_days'] ? $_GET['planner_days'] : 3;
33
		$planner_date = $_GET['date'] ? $_GET['date'] : strtotime('yesterday',$content['date'] ? $content['date'] : time());
34
35
		if($_GET['confirm']) {
36
			$register_code = ($_GET['confirm'] && preg_match('/^[0-9a-f]{32}$/',$_GET['confirm'])) ? $_GET['confirm'] : false;
37
			if($register_code && $registration = registration_bo::confirm($register_code)) {
0 ignored issues
show
Bug introduced by
The type registration_bo 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...
38
				// Get calendar through link
39
				$links = Link::get_links('registration', $registration['reg_id'],'calendar');
40
				$bo = new calendar_boupdate();
41
				$data = $bo->read(current($links));
42
43
				$addressbook = new Api\Contacts();
44
				$data += $addressbook->read(key($data['participant_types']['c']));
45
46
				// Show date of reservation, so they can see it blocked off
47
				$display_days = 1;
48
				$planner_date = mktime(0,0,0,date('m',$data['start']),date('d',$data['start']),date('Y',$data['start']));
49
				$readonlys['__ALL__'] = true;
50
				$content = array(
51
					'resource' => key($data['participant_types']['r']),
52
					'date' => $data['start'],
53
					'time' => $data['start'] - mktime(0,0,0,date('m',$data['start']),date('d',$data['start']),date('Y',$data['start'])),
54
					'quantity' => 0
55
				);
56
				calendar_so::split_status($data['participant_types']['r'][$content['resource']], $content['quantity'],$role);
57
				$data['msg']= '<div class="confirm">'.lang('Registration confirmed %1', Api\DateTime::to($data['start'])) .'</div>';
0 ignored issues
show
Unused Code introduced by
The call to lang() has too many arguments starting with EGroupware\Api\DateTime::to($data['start']). ( Ignorable by Annotation )

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

57
				$data['msg']= '<div class="confirm">'./** @scrutinizer ignore-call */ lang('Registration confirmed %1', Api\DateTime::to($data['start'])) .'</div>';

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...
58
			} else {
59
				$data['msg']= '<div class="confirm">'.lang('Unable to process confirmation.').'</div>';
60
			}
61
                }
62
63
		$this->tmpl->read('resources.sitemgr_book');
64
65
		if(!$arguments['resource'] && !($arguments['resource'] = $content['resource'])) return false;
66
		$data += $this->bo->read($arguments['resource']);
67
68
		$data['quantity'] = $content['quantity'] ? $content['quantity'] : 2;
69
70
		$data['date'] = $arguments['date'] ? $arguments['date'] : $content['date'];
71
		$data['time'] = $content['time'];
72
73
		$preserve = array(
74
			'resource' => $data['res_id'],
75
		);
76
		$preserve['sitemgr_version'] = $arguments['sitemgr_version'] ? $arguments['sitemgr_version'] : $content['sitemgr_version'];
77
		$preserve['confirmation'] = $arguments['confirmation'] || $content['confirmation'];
78
		$preserve['contact_form'] = $arguments['contact_form'] ? $arguments['contact_form'] : $content['contact_form'];
79
		$preserve['link'] = $arguments['link'] ? $arguments['link'] : $content['link'];
80
		$preserve['email_message'] = $arguments['email_message'] ? $arguments['email_message'] : $content['email_message'];
81
		$preserve['include_group'] = $arguments['include_group'] ? $arguments['include_group'] : $content['include_group'];
82
83
		// Check for valid time
84
		if($data['date'] && $content['book'])
85
		{
86
			$start_time = $data['date'] + (is_array($data['time']) ? $data['time']['hour']*3600 + $data['time']['minute']*60 : $data['time']);
87
			// Use sitemgr's default appointment length
88
			if($GLOBALS['egw_info']['user']['account_lid'] != $GLOBALS['sitemgr_info']['anonymous_user'])
89
			{
90
				$preferences = new Api\Preferences($GLOBALS['egw']->accounts->name2id($GLOBALS['sitemgr_info']['anonymous_user']));
91
				$preferences = $preferences->read_repository();
92
				$duration = $preferences['calendar']['defaultlength'] * 60;
93
			}
94
			else
95
			{
96
				$duration = ($GLOBALS['egw_info']['user']['preferences']['calendar']['defaultlength'] * 60);
97
			}
98
			$end_time = $start_time + $duration;
99
100
			$config = Api\Config::read('registration');
101
102
			// Not a user, need contact
103
			if($GLOBALS['egw_info']['user']['account_lid'] == $GLOBALS['sitemgr_info']['anonymous_user'] && !$content['contact_id'])
104
			{
105
				if ($config['pending_addressbook'])   // save the contact in the addressbook
106
				{
107
					$content['owner'] = $config['pending_addressbook'];
108
					$content['private'] = 0;        // in case default_private is set
109
				}
110
111
				$addressbook = new Api\Contacts();
112
				$contact_fields = $addressbook->contact_fields;
113
				unset($contact_fields['email']); // Always present
114
				unset($contact_fields['id']); // Address already there
115
				if(array_intersect_key($contact_fields,$content)) {
116
					$result = $addressbook->save($content);
117
					if(!$result) {
118
						throw new Api\Exception\NoPermission($addressbook->error);
119
						return False;
0 ignored issues
show
Unused Code introduced by
return False is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
120
					}
121
122
123
					$contact_id = $result;
124
					$contact = 'c'.$contact_id;
125
				}
126
			}
127
			else
128
			{
129
				$contact = $GLOBALS['egw_info']['user']['account_id'];
130
				$contact_id = $GLOBALS['egw_info']['user']['person_id'];
131
			}
132
133
			if($contact) {
134
				// Make event
135
				$event = array(
136
					'title' =>	Link::title('addressbook', $contact_id),
137
					'start' =>	$start_time,
138
					'end' =>	$end_time,
139
					'participants' => array(
140
						'r'.$data['res_id'] => calendar_so::combine_status('U', $data['quantity'], 'REQ-PARTICIPANT'),
141
						$contact => calendar_so::combine_status('U', $data['quantity'], 'REQ-PARTICIPANT')
142
					)
143
				);
144
				if($preserve['include_group'])
145
				{
146
					$event['participants'][$preserve['include_group']] = calendar_so::combine_status('U', 1, 'REQ-PARTICIPANT');
147
				}
148
				$cal_bo = new calendar_boupdate();
149
				$result = $cal_bo->update($event);
150
151
				// Show date of reservation, so they can see it blocked off
152
				$display_days = 1;
153
				$planner_date = mktime(0,0,0,date('m',$event['start']),date('d',$event['start']),date('Y',$event['start']));
154
155
				// Free time search
156
				if(!is_numeric($result))
157
				{
158
					$form = new calendar_uiforms();
159
					$freetime = $form->freetime('r'.$data['res_id'],
160
						strtotime($GLOBALS['egw_info']['user']['preferences']['calendar']['workdaystarts'] . ':00',$start_time),
161
						strtotime($GLOBALS['egw_info']['user']['preferences']['calendar']['workdayends'] . ':00 ',$end_time),
162
						$duration
163
					);
164
					$data += $content;
165
					$data['msg'] = lang('Please choose a different time:')."\n";
166
					foreach($freetime as $slot) {
167
						$data['msg'] .= Api\DateTime::to($slot['start']) . ' - ' . Api\DateTime::to($slot['end'])."<br />\n";
168
					}
169
				}
170
				elseif ($preserve['confirmation'] && $contact_id && $result)
171
				{
172
					// Confirmation required - send registration email
173
					$reg_id = registration_bo::save(array(
174
						'contact_id' => $contact_id,
175
						'timestamp' => time() + ($config['expiry'] * 3600),
176
						'post_confirm_hook' => 'resources.resources_reserve.confirm',
177
						'sitemgr_version' => $preserve['sitemgr_version']
178
					), false);
179
					if(is_numeric($reg_id))
180
					{
181
						// Link to event
182
						Link::link('registration', $reg_id, 'calendar', $result);
183
						$reg = registration_bo::read($reg_id);
184
185
						// Send email
186
						$email_info = $config + array(
187
							'title' => $data['name'],
188
							'subject' => $data['name'] . ' ' . Api\DateTime::to($start_time),
189
							'link' => $preserve['link'],
190
						);
191
						if($preserve['email_message'])
192
						{
193
							$email_info['message'] = lang($preserve['email_message'],
194
								Api\DateTime::to($start_time),
195
								$preserve['link'].'&confirm='.$reg['register_code'],
196
								Api\DateTime::to($reg['timestamp'])
197
							);
198
						}
199
						$data['msg'] .= registration_bo::send_confirmation($email_info, $reg);
200
					}
201
				}
202
			}
203
		}
204
205
		$data['picture'] = $this->bo->get_picture($data);
206
207
		// Not a user, need contact
208
		if($GLOBALS['egw_info']['user']['account_lid'] == $GLOBALS['sitemgr_info']['anonymous_user'] && !$content['contact_id'])
209
		{
210
			$data['contact_form'] = $preserve['contact_form'];
211
			$data['show_contact'] = !$preserve['contact_form'];
212
		}
213
214
		$cal_user = array('r'.$arguments['resource']);
215
		foreach($this->bo->get_acc_list($data['res_id']) as $acc_id => $name)
216
		{
217
			$cal_user[] = 'r'.$acc_id;
218
		}
219
220
		if(!$data['date']) $data['date'] = strtotime('tomorrow');
221
		if(!$data['time']) $data['time']['hour'] = $GLOBALS['egw_info']['user']['preferences']['calendar']['workdaystarts'];
222
223
		// Use sitemgr's default appointment length
224
		if($GLOBALS['egw_info']['user']['account_lid'] != $GLOBALS['sitemgr_info']['anonymous_user'])
225
		{
226
			$preferences = new Api\Preferences($GLOBALS['egw']->accounts->name2id($GLOBALS['sitemgr_info']['anonymous_user']));
227
			$preferences = $preferences->read_repository();
228
			$data['duration'] = $preferences['calendar']['defaultlength'];
229
		}
230
		else
231
		{
232
			$data['duration'] = $GLOBALS['egw_info']['user']['preferences']['calendar']['defaultlength'];
233
		}
234
		// Leading 0
235
		$data['duration'] = '0'.$data['duration'];
236
237
		if(!$GLOBALS['egw_info']['user']['apps']['resources'] || !$this->bo->get_calendar_info($data['res_id']) || // Needed for booking
238
			!$GLOBALS['egw_info']['user']['apps']['calendar'] // Needed for updating schedule
239
		)
240
		{
241
			$data['planner'] = 'Permission error - site not configured properly.  Need ' . lang('resources') . ' & ' . lang('calendar');
242
		}
243
		else
244
		{
245
			$data['planner'] = $this->get_planner(
246
				$arguments['resource'],
247
				$planner_date ? $planner_date : strtotime('yesterday',$date), // Show day before, too
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $date seems to be never defined.
Loading history...
248
				$display_days,
249
				$preserve['link']
250
			);
251
		}
252
253
		// Restrict times to working hours
254
		for($i = $GLOBALS['egw_info']['user']['preferences']['calendar']['workdaystarts']; $i < $GLOBALS['egw_info']['user']['preferences']['calendar']['workdayends']; $i++)
255
		{
256
			if($GLOBALS['egw_info']['user']['preferences']['common']['timeformat'] == '12')
257
			{
258
				$sel_options['hour'][$i] = ($i < '12' ? $i .' am' : ($i > 12 ? $i -12 : $i).' pm');
259
			}
260
			else
261
			{
262
				$sel_options['hour'][$i] = ($i < '10' ? '0'.$i : $i);
263
			}
264
		}
265
266
		return $this->tmpl->exec('resources.resources_reserve.book',$data,$sel_options,$readonlys,$preserve);
267
	}
268
269
	public function ajax_update_planner($resource_id, $date) {
270
		$response = Api\Json\Response::get();
271
		$response->assign('exec[planner_div]','innerHTML',$this->get_planner(
272
			$resource_id,
273
			strtotime('yesterday',$date),
274
			3,
275
			$_SERVER['HTTP_REFERER']
276
		));
277
	}
278
279
	/**
280
	 * Get HTML for the planner to show when its busy
281
	 *
282
	 * @param resource_id
283
	 *
284
	 * @return String - HTML
285
	 */
286
	protected function get_planner($resource_id, $date, $days = 3, $link)
0 ignored issues
show
Coding Style introduced by
Parameters which have default values should be placed at the end.

If you place a parameter with a default value before a parameter with a default value, the default value of the first parameter will never be used as it will always need to be passed anyway:

// $a must always be passed; it's default value is never used.
function someFunction($a = 5, $b) { }
Loading history...
287
	{
288
//echo "get_planner($resource_id, $date, $days, $link)";
289
		$calendar = new calendar_uiviews(array(
290
			'owner'		=> 'r'.$resource_id,
291
			//'owner'		=> implode(',',$cal_user),
292
			'planner_days'	=> $days,
293
			'view'		=> 'date_advance',
294
			'date'		=> $date
295
		));
296
		// Need to add this in explicitly, or it may be lost if use clicks a day
297
		$calendar->search_params['users'][] = 'r'.$resource_id;
298
		$calendar->search_params['users'][] = $GLOBALS['egw_info']['user']['account_id'];
299
		$calendar->allowEdit = false;    // switches off all edit popups
300
301
		$planner = '<style type="text/css">'."\n".
302
			'@import url('.$GLOBALS['egw_info']['server']['webserver_url'].'/calendar/templates/default/app.css'.");\n".
303
			'</style>'."\n";
304
305
		// replacing egw-urls with sitemgr ones, allows to use navigation links
306
		$planner .= str_replace($GLOBALS['egw_info']['server']['webserver_url'].'/index.php?',
307
			$link.'&',
308
			$calendar->planner(true));
0 ignored issues
show
Bug introduced by
Are you sure the usage of $calendar->planner(true) targeting calendar_uiviews::planner() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
309
310
		return $planner;
311
	}
312
313
	/**
314
	 * Confirm a registration done through sitemgr
315
	 *
316
	 * @param registration - registration information
0 ignored issues
show
Documentation Bug introduced by
The doc comment - at position 0 could not be parsed: Unknown type name '-' at position 0 in -.
Loading history...
317
	 */
318
	public function confirm($registration)
319
	{
320
		// Get calendar through link
321
		$links = Link::get_links('registration', $registration['reg_id'],'calendar');
322
		$bo = new calendar_boupdate();
323
		$event = $bo->read(current($links));
0 ignored issues
show
Unused Code introduced by
The assignment to $event is dead and can be removed.
Loading history...
324
		if($registration['status'] == registration_bo::CONFIRMED)
325
		{
326
			$bo->set_status(current($links), 'c'.$registration['contact_id'], 'A');
327
		}
328
		else
329
		{
330
			$bo->delete(current($links));
331
			// Remove contact ID, or registration will try to purge the account
332
			if($registration['account_id'])
333
			{
334
				unset($registration['contact_id']);
335
			}
336
		}
337
		return $registration;
338
	}
339
}
340
341