1<?php
2/**
3 * @package tikiwiki
4 */
5// (c) Copyright by authors of the Tiki Wiki CMS Groupware Project
6//
7// All Rights Reserved. See copyright.txt for details and a complete list of authors.
8// Licensed under the GNU LESSER GENERAL PUBLIC LICENSE. See license.txt for details.
9// $Id$
10
11$section = 'trackers';
12require_once('tiki-setup.php');
13
14$access->check_feature('feature_trackers');
15
16$trklib = TikiLib::lib('trk');
17if ($prefs['feature_categories'] == 'y') {
18	$categlib = TikiLib::lib('categ');
19}
20$filegallib = TikiLib::lib('filegal');
21$notificationlib = TikiLib::lib('notification');
22if ($prefs['feature_groupalert'] == 'y') {
23	$groupalertlib = TikiLib::lib('groupalert');
24}
25$auto_query_args = [
26	'offset',
27	'trackerId',
28	'reloff',
29	'itemId',
30	'maxRecords',
31	'status',
32	'sort_mode',
33	'initial',
34	'filterfield',
35	'filtervalue',
36	'view',
37	'exactvalue'
38];
39if (isset($_REQUEST['trackerId'])) {
40	$trackerId = $_REQUEST['trackerId'];
41}
42if (isset($_REQUEST['itemId'])) {
43	$itemId = $_REQUEST['itemId'];
44}
45$special = false;
46if (! isset($trackerId) && $prefs['userTracker'] == 'y' && ! isset($_REQUEST['user'])) {
47	if (isset($_REQUEST['view']) and $_REQUEST['view'] == ' user') {
48		if (empty($user)) {
49			$smarty->assign('msg', tra("You are not logged in"));
50			$smarty->assign('errortype', '402');
51			$smarty->display("error.tpl");
52			die;
53		}
54		$utid = $userlib->get_tracker_usergroup($user);
55		if (isset($utid['usersTrackerId'])) {
56			$trackerId = $utid['usersTrackerId'];
57			$itemId = $trklib->get_item_id($trackerId, $utid['usersFieldId'], $user);
58			if ($itemId == null) {
59				$addit = [];
60				$addit[] = [
61					'fieldId' => $utid['usersFieldId'],
62					'type' => 'u',
63					'value' => $user,
64				];
65				$definition = Tracker_Definition::get($trackerId);
66				if ($definition && $f = $definition->getUserField()) {
67					if ($f != $utid['usersFieldId']) {
68						$addit[] = [
69							'fieldId' => $f,
70							'type' => 'u',
71							'value' => $user,
72						];
73					}
74				}
75				if ($definition && $f = $definition->getWriterGroupField()) {
76					$addit[] = [
77						'fieldId' => $f,
78						'type' => 'g',
79						'value' => $group,
80					];
81				}
82				$itemId = $trklib->replace_item($trackerId, 0, ['data' => $addit], 'o');
83			}
84			$special = 'user';
85		}
86	} elseif (isset($_REQUEST["usertracker"]) and $tiki_p_admin == 'y') {
87		$utid = $userlib->get_tracker_usergroup($_REQUEST['usertracker']);
88		if (isset($utid['usersTrackerId'])) {
89			$trackerId = $utid['usersTrackerId'];
90			$itemId = $trklib->get_item_id($trackerId, $utid['usersFieldId'], $_REQUEST["usertracker"]);
91		}
92	}
93}
94if (! isset($trackerId) && $prefs['groupTracker'] == 'y') {
95	if (isset($_REQUEST['view']) and $_REQUEST['view'] == ' group') {
96		$gtid = $userlib->get_grouptrackerid($group);
97		if (isset($gtid['groupTrackerId'])) {
98			$trackerId = $gtid['groupTrackerId'];
99			$itemId = $trklib->get_item_id($trackerId, $gtid['groupFieldId'], $group);
100			if ($itemId == null) {
101				$addit = ['data' => [
102					'fieldId' => $gtid['groupFieldId'],
103					'type' => 'g',
104					'value' => $group,
105				]];
106				$itemId = $trklib->replace_item($trackerId, 0, $addit, 'o');
107			}
108			$special = 'group';
109		}
110	} elseif (isset($_REQUEST["grouptracker"]) and $tiki_p_admin == 'y') {
111		$gtid = $userlib->get_grouptrackerid($_REQUEST["grouptracker"]);
112		if (isset($gtid['groupTrackerId'])) {
113			$trackerId = $gtid['groupTrackerId'];
114			$itemId = $trklib->get_item_id($trackerId, $gtid['groupFieldId'], $_REQUEST["grouptracker"]);
115		}
116	}
117}
118$smarty->assign_by_ref('special', $special);
119//url to a user user tracker tiki-view_tracker_item.php?user=yyyyy&view=+user or tiki-view_tracker_item.php?greoup=yyy&user=yyyyy&view=+user or tiki-view_tracker_item.php?trackerId=xxx&user=yyyyy&view=+user
120if ($prefs['userTracker'] == 'y' && isset($_REQUEST['view']) && $_REQUEST['view'] = ' user' && ! empty($_REQUEST['user'])) {
121	if (empty($trackerId)) {
122		if (empty($_REQUEST['group'])) {
123			$_REQUEST['group'] = $userlib->get_user_default_group($_REQUEST['user']);
124		}
125		if (! empty($_REQUEST['group'])) {
126			$utid = $userlib->get_usertrackerid($_REQUEST['group']);
127			if (! empty($utid['usersTrackerId']) && ! empty($utid['usersFieldId'])) {
128				$trackerId = $utid['usersTrackerId'];
129				$fieldId = $utid['usersFieldId'];
130			}
131		}
132	}
133	if (! empty($trackerId)) {
134		if (empty($fieldId)) {
135			$definition = Tracker_Definition::get($trackerId);
136			if ($definition) {
137				$fieldId = $definition->getUserField();
138			}
139		}
140		if (! empty($fieldId)) {
141			$itemId = $trklib->get_item_id($trackerId, $fieldId, $_REQUEST['user']);
142			if (! $itemId) {
143				$smarty->assign(
144					'msg',
145					tra("You don't have a personal tracker item yet. Click here to make one:") . '<br /><a href="tiki-view_tracker.php?trackerId=' . $trackerId . '&cookietab=2">' . tra('Create tracker item') . '</a>'
146				);
147				$smarty->display("error.tpl");
148				die;
149			}
150		}
151	}
152}
153if ((! isset($trackerId) || ! $trackerId) && isset($itemId)) {
154	$item_info = $trklib->get_tracker_item($itemId);
155	$trackerId = $item_info['trackerId'];
156}
157if (! isset($trackerId) || ! $trackerId) {
158	$smarty->assign('msg', tra("No tracker indicated"));
159	$smarty->display("error.tpl");
160	die;
161}
162if (! isset($utid) and ! isset($gtid) and (! isset($itemId) or ! $itemId) and ! isset($_REQUEST["offset"])) {
163	$smarty->assign('msg', tra("No item indicated"));
164	$smarty->display("error.tpl");
165	die;
166}
167
168if (isset($itemId)) {
169	$item_info = $trklib->get_tracker_item($itemId);
170
171	TikiLib::events()->trigger(
172		'tiki.trackeritem.view',
173		[
174			'type' => 'trackeritem',
175			'object' => $itemId,
176			'owner' => $item_info['createdBy'],
177			'user' => $GLOBALS['user'],
178		]
179	);
180}
181
182$definition = Tracker_Definition::get($trackerId);
183$fieldDefinitions = $definition->getFields();
184$smarty->assign('tracker_is_multilingual', $prefs['feature_multilingual'] == 'y' && $definition->getLanguageField());
185
186if ($prefs['feature_groupalert'] == 'y') {
187	$groupforalert = $groupalertlib->GetGroup('tracker', $trackerId);
188	if ($groupforalert != "") {
189		$showeachuser = $groupalertlib->GetShowEachUser('tracker', $trackerId, $groupforalert);
190		$listusertoalert = $userlib->get_users(0, -1, 'login_asc', '', '', false, $groupforalert, '');
191		$smarty->assign_by_ref('listusertoalert', $listusertoalert['data']);
192	}
193	$smarty->assign_by_ref('groupforalert', $groupforalert);
194	$smarty->assign_by_ref('showeachuser', $showeachuser);
195}
196if (! isset($_REQUEST["sort_mode"])) {
197	$sort_mode = 'created_desc';
198} else {
199	$sort_mode = $_REQUEST["sort_mode"];
200}
201$smarty->assign_by_ref('sort_mode', $sort_mode);
202if (! isset($_REQUEST["offset"])) {
203	$offset = 0;
204} else {
205	$offset = $_REQUEST["offset"];
206}
207$smarty->assign_by_ref('offset', $offset);
208if (isset($_REQUEST["find"])) {
209	$find = $_REQUEST["find"];
210} else {
211	$find = '';
212}
213$smarty->assign('find', $find);
214// ************* previous/next **************
215foreach ([
216	'status',
217	'filterfield',
218	'filtervalue',
219	'initial',
220	'exactvalue',
221	'reloff'
222] as $reqfld) {
223	$trynam = 'try' . $reqfld;
224	if (isset($_REQUEST[$reqfld])) {
225		$$trynam = $_REQUEST[$reqfld];
226	} else {
227		$$trynam = '';
228	}
229}
230if (isset($_REQUEST['filterfield'])) {
231	if (is_array($_REQUEST['filtervalue']) and isset($_REQUEST['filtervalue'][$tryfilterfield])) {
232		$tryfiltervalue = $_REQUEST['filtervalue'][$tryfilterfield];
233	} else {
234		$tryfilterfield = preg_split('/\s*:\s*/', $_REQUEST['filterfield']);
235		$tryfiltervalue = preg_split('/\s*:\s*/', $_REQUEST['filtervalue']);
236		$tryexactvalue = preg_split('/\s*:\s*/', $_REQUEST['exactvalue']);
237	}
238}
239
240//*********** handle prev/next links *****************
241if (isset($_REQUEST['reloff'])) {
242	if (isset($_REQUEST['move'])) {
243		switch ($_REQUEST['move']) {
244			case 'prev':
245				$tryreloff += - 1;
246				break;
247
248			case 'next':
249				$tryreloff += 1;
250				break;
251
252			default:
253				$tryreloff = (int)$_REQUEST['move'];
254		}
255	}
256	$cant = 0;
257	$listfields = [];
258	if (substr($sort_mode, 0, 2) == 'f_') { //look at the field in case the field needs some processing to find the sort
259		list($a, $i, $o) = explode('_', $sort_mode);
260		foreach ($fieldDefinitions as $f) {
261			if ($f['fieldId'] == $i) {
262				$listfields = [
263					$i => $f
264				];
265				break;
266			}
267		}
268	}
269	if (isset($_REQUEST['cant'])) {
270		$cant = $_REQUEST['cant'];
271	} else {
272		if (is_array($tryfiltervalue)) {
273			$tryfiltervalue = array_values($tryfiltervalue);
274		}
275		$trymove = $trklib->list_items($trackerId, $offset + $tryreloff, 1, $sort_mode, $listfields, $tryfilterfield, $tryfiltervalue, $trystatus, $tryinitial, $tryexactvalue);
276		if (isset($trymove['data'][0]['itemId'])) {
277			// Autodetect itemId if not specified
278			if (! isset($itemId)) {
279				$itemId = $trymove['data'][0]['itemId'];
280				unset($item_info);
281			}
282			$cant = $trymove['cant'];
283		}
284	}
285	$smarty->assign('cant', $cant);
286}
287//*********** that's all for prev/next *****************
288$smarty->assign('itemId', $itemId);
289if (! isset($item_info)) {
290	$item_info = $trklib->get_tracker_item($itemId);
291	if (empty($item_info)) {
292		$smarty->assign('msg', tra("No item indicated"));
293		$smarty->display("error.tpl");
294		die;
295	}
296}
297$item_info['logs'] = ['cant' => $trklib->item_has_history($item_info['itemId'])];	// only used to show history links, no need to load everything
298$smarty->assign_by_ref('item_info', $item_info);
299$smarty->assign('item', ['itemId' => $itemId, 'trackerId' => $trackerId]);
300$cat_objid = $itemId;
301$cat_type = 'trackeritem';
302
303$tracker_info = $definition->getInformation();
304$itemObject = Tracker_Item::fromInfo($item_info);
305
306if (! isset($tracker_info["writerCanModify"]) or (isset($utid) and ($trackerId != $utid['usersTrackerId']))) {
307	$tracker_info["writerCanModify"] = 'n';
308}
309if (! isset($tracker_info["userCanSeeOwn"]) or (isset($utid) and ($trackerId != $utid['usersTrackerId']))) {
310	$tracker_info["userCanSeeOwn"] = 'n';
311}
312if (! isset($tracker_info["writerGroupCanModify"]) or (isset($gtid) and ($trackerId != $gtid['groupTrackerId']))) {
313	$tracker_info["writerGroupCanModify"] = 'n';
314}
315if (! isset($tracker_info["groupCanSeeOwn"]) or (isset($gtid) and ($trackerId != $gtid['groupTrackerId']))) {
316	$tracker_info["groupCanSeeOwn"] = 'n';
317}
318$tikilib->get_perm_object($trackerId, 'tracker', $tracker_info);
319if (! $itemObject->canView()) {
320	$smarty->assign('errortype', 403);
321	$smarty->assign('msg', tra("Permission denied"));
322	$smarty->display("error.tpl");
323	die;
324}
325if (isset($tracker_info['adminOnlyViewEditItem']) && $tracker_info['adminOnlyViewEditItem'] === 'y') {
326	$access->check_permission('tiki_p_admin_trackers', tra('This tracker restricts access to the built-in tracker interfaces. You need admin tracker permission'), 'tracker', $tracker_info['trackerId']);
327}
328
329include_once('tiki-sefurl.php');
330
331if (isset($_REQUEST["remove"]) && $itemObject->canRemove()) {
332	$access->check_authenticity(tr('Are you sure you want to permanently delete this item?'));
333	$trklib->remove_tracker_item($_REQUEST["remove"]);
334	$access->redirect(filter_out_sefurl('tiki-view_tracker.php?trackerId=' . $trackerId));
335}
336if (! empty($_REQUEST['moveto'])) {
337	$perms = Perms::get('tracker', $_REQUEST['moveto']);
338	if ($tiki_p_admin_trackers == 'y' && $perms->create_tracker_items) {
339		// Move item to another tracker. This assumes certain similarities between the 2 trackers.
340		$trklib->move_item($trackerId, $itemId, $_REQUEST['moveto']);
341		header('Location: ' . filter_out_sefurl('tiki-view_tracker_item.php?itemId=' . $itemId));
342		exit;
343	} else {
344		$smarty->assign('errortype', 403);
345		$smarty->assign('msg', tra("Permission denied"));
346		$smarty->display("error.tpl");
347		die;
348	}
349}
350if (isset($_REQUEST["removeattach"])) {
351	$owner = $trklib->get_item_attachment_owner($_REQUEST["removeattach"]);
352	if (($user && ($owner == $user)) || ($tiki_p_admin_trackers == 'y')) {
353		$access->check_authenticity(tra('Are you sure you want to remove this attachment?'));
354		$trklib->remove_item_attachment($_REQUEST["removeattach"]);
355	}
356}
357
358
359$status_types = $trklib->status_types();
360$smarty->assign('status_types', $status_types);
361$fields = [];
362$ins_fields = [];
363$usecategs = false;
364$cookietab = 1;
365$itemUsers = $trklib->get_item_creators($trackerId, $itemId);
366$smarty->assign_by_ref('itemUsers', $itemUsers);
367$plugins_loaded = false;
368
369if (empty($tracker_info)) {
370	$item_info = [];
371}
372$fieldFactory = $definition->getFieldFactory();
373
374$rateFieldId = $definition->getRateField();
375if (isset($tracker_info['useRatings']) and $tracker_info['useRatings'] == 'y' and $tiki_p_tracker_vote_ratings == 'y') {
376	if ($user and $tiki_p_tracker_vote_ratings == 'y' and isset($rateFieldId) and isset($_REQUEST['ins_' . $rateFieldId])) {
377		$trklib->replace_rating($trackerId, $itemId, $rateFieldId, $user, $_REQUEST['ins_' . $rateFieldId]);
378		header('Location: tiki-view_tracker_item.php?trackerId=' . $trackerId . '&itemId=' . $itemId);
379		die;
380	}
381}
382
383// Why do we need to define these array elements? Can users not just consult fieldId? Chealer 2017-05-23
384foreach ($fieldDefinitions as &$fieldDefinition) {
385	$fid = $fieldDefinition["fieldId"];
386
387	$fieldDefinition["ins_id"] = 'ins_' . $fid;
388	$fieldDefinition["filter_id"] = 'filter_' . $fid;
389}
390unset($fieldDefinition);
391
392if (isset($_REQUEST["save"]) || isset($_REQUEST["save_return"]) || isset($_REQUEST['save_and_comment'])) {
393	foreach ($fieldDefinitions as $i => $current_field) {
394		$fid = $current_field["fieldId"];
395		$fieldIsVisible = $itemObject->canViewField($fid);
396		$fieldIsEditable = $itemObject->canModifyField($fid);
397
398		$current_field_ins = null;
399		if ($fieldIsVisible || $fieldIsEditable) {
400			$current_field_ins = $current_field;
401
402			$handler = $fieldFactory->getHandler($current_field, $item_info);
403
404			if ($handler) {
405				$insert_values = $handler->getFieldData($_REQUEST);
406
407				if ($insert_values) {
408					$current_field_ins = array_merge($current_field_ins, $insert_values);
409				}
410			}
411		}
412
413		if (! empty($current_field_ins)) {
414			if ($fieldIsEditable) {
415				$ins_fields['data'][$i] = $current_field_ins;
416			}
417			if ($fieldIsVisible) {
418				$fields['data'][$i] = $current_field_ins;
419			}
420		}
421	}
422
423	if ($itemObject->canModify()) {
424		$captchalib = TikiLib::lib('captcha');
425		if (empty($user) && $prefs['feature_antibot'] == 'y' && ! $captchalib->validate()) {
426			$smarty->assign('msg', $captchalib->getErrors());
427			$smarty->assign('errortype', 'no_redirect_login');
428			$smarty->display("error.tpl");
429			die;
430		}
431		// Check field values for each type and presence of mandatory ones
432		$mandatory_missing = [];
433		$err_fields = [];
434		$categorized_fields = $definition->getCategorizedFields();
435		$field_errors = $trklib->check_field_values($ins_fields, $categorized_fields, $trackerId, empty($itemId) ? '' : $itemId);
436		$smarty->assign('err_mandatory', $field_errors['err_mandatory']);
437		$smarty->assign('err_value', $field_errors['err_value']);
438		// values are OK, then lets save the item
439		if (count($field_errors['err_mandatory']) == 0 && count($field_errors['err_value']) == 0) {
440			$smarty->assign('input_err', '0'); // no warning to display
441			if ($prefs['feature_groupalert'] == 'y') {
442				$groupalertlib->Notify(isset($_REQUEST['listtoalert']) ? $_REQUEST['listtoalert'] : '', "tiki-view_tracker_item.php?itemId=" . $itemId);
443			}
444			check_ticket('view-trackers-items');
445			if (! isset($_REQUEST["edstatus"]) or ($tracker_info["showStatus"] != 'y' and $tiki_p_admin_trackers != 'y')) {
446				$_REQUEST["edstatus"] = $tracker_info["modItemStatus"];
447			}
448			$trklib->replace_item($trackerId, $itemId, $ins_fields, $_REQUEST["edstatus"]);
449			if (isset($rateFieldId) && isset($_REQUEST["ins_$rateFieldId"])) {
450				$trklib->replace_rating($trackerId, $itemId, $rateFieldId, $user, $_REQUEST["ins_$rateFieldId"]);
451			}
452			$_REQUEST['show'] = 'view';
453
454			// What is this loop for? The value is overriden later for editable fields. Chealer 2017-05-25
455			foreach ($fields["data"] as $i => $array) {
456				if (isset($fields["data"][$i])) {
457					$ins_fields["data"][$i]["value"] = '';
458				}
459			}
460
461			$item_info = $trklib->get_tracker_item($itemId);
462			$item_info['logs'] = $trklib->get_item_history($item_info, 0, '', 0, 1);
463			$smarty->assign('item_info', $item_info);
464		} else {
465			$error = $ins_fields;
466			$cookietab = "2";
467			if ($tracker_info['useAttachments'] == 'y') {
468				++$cookietab;
469			}
470			if ($tracker_info['useComments'] == 'y') {
471				++$cookietab;
472			}
473			$smarty->assign('input_err', '1'); // warning to display
474			// can't go back if there are errors
475			if (isset($_REQUEST['save_return'])) {
476				$_REQUEST['save'] = 'save';
477				unset($_REQUEST['save_return']);
478			}
479			if (isset($_REQUEST['save_and_comment'])) {
480				$_REQUEST['save'] = 'save';
481				unset($_REQUEST['save_and_comment']);
482			}
483		}
484		if (isset($_REQUEST['save_return']) && isset($_REQUEST['from'])) {
485			$fromUrl = filter_out_sefurl('tiki-index.php?page=' . urlencode($_REQUEST['from']));
486			header("Location: {$fromUrl}");
487			exit;
488		}
489
490		if (isset($_REQUEST['save_and_comment'])) {
491			$version = $trklib->last_log_version($itemId);
492			$smarty->assign('version', $version);
493
494			$modalUrl = TikiLib::lib('service')->getUrl([
495				'controller' => 'comment',
496				'action' => 'post',
497				'type' => 'trackeritem',
498				'objectId' => $itemId,
499				'parentId' => 0,
500				'version' => $version,
501				'return_url' => '',
502				'title' => tr('Comment for edit #%0', $version),
503				]);
504
505			$headerlib->add_jq_onready('$.openModal({ remote:"' . $modalUrl . '"});');
506			}
507
508	}
509}
510// remove image from an image field
511if (isset($_REQUEST["removeImage"])) {
512	$img_field = [
513		'data' => []
514	];
515	$img_field['data'][] = [
516		'fieldId' => $_REQUEST["fieldId"],
517		'type' => 'i',
518		'name' => $_REQUEST["fieldName"],
519		'value' => 'blank'
520	];
521	$trklib->replace_item($trackerId, $itemId, $img_field);
522	$_REQUEST['show'] = "mod";
523}
524// ************* return to list ***************************
525if (isset($_REQUEST["returntracker"]) || isset($_REQUEST["save_return"])) {
526	require_once('lib/smarty_tiki/block.self_link.php');
527	header(
528		'Location: ' . smarty_block_self_link(
529			[
530				'_script' => 'tiki-view_tracker.php',
531				'_tag' => 'n',
532				'_urlencode' => 'n',
533				'itemId' => 'NULL',
534				'trackerId' => $trackerId
535			],
536			'',
537			$smarty
538		)
539	);
540	die;
541}
542// ********************************************************
543$info = $trklib->get_tracker_item($itemId);
544$itemObject = Tracker_Item::fromInfo($info);
545if (! isset($info['trackerId'])) {
546	$info['trackerId'] = $trackerId;
547}
548if (! $itemObject->canView()) {
549	$smarty->assign('errortype', 403);
550	$smarty->assign('msg', tra('Permission denied'));
551	$smarty->display('error.tpl');
552	die;
553}
554
555$fieldFactory = $definition->getFieldFactory();
556
557foreach ($fieldDefinitions as $i => $current_field) {
558	$current_field_ins = null;
559	$fid = $current_field['fieldId'];
560
561	$handler = $fieldFactory->getHandler($current_field, $info);
562
563	$fieldIsVisible = $itemObject->canViewField($fid);
564	$fieldIsEditable = $itemObject->canModifyField($fid);
565
566	if ($fieldIsVisible || $fieldIsEditable) {
567		$current_field_ins = $current_field;
568
569		if ($handler) {
570			$insert_values = $handler->getFieldData();
571
572			if ($insert_values) {
573				$current_field_ins = array_merge($current_field_ins, $insert_values);
574			}
575		}
576	}
577
578	if (! empty($current_field_ins)) {
579		if ($fieldIsVisible) {
580			$fields['data'][$i] = $current_field_ins;
581		}
582		if ($fieldIsEditable) {
583			$ins_fields['data'][$i] = $current_field_ins;
584		}
585	}
586}
587$smarty->assign('tracker_item_main_value', $trklib->get_isMain_value($trackerId, $itemId));
588
589//restore types values if there is an error
590if (isset($error)) {
591	foreach ($ins_fields["data"] as $i => $current_field) {
592		if (isset($error["data"][$i]["value"])) {
593			$ins_fields["data"][$i]["value"] = $error["data"][$i]["value"];
594		}
595	}
596}
597
598$authorfield = $definition->getAuthorField();
599if ($authorfield) {
600	$tracker_info['authorindiv'] = $trklib->get_item_value($trackerId, $itemId, $authorfield);
601}
602
603// Pull realname for user.
604$info["createdByReal"] = $tikilib->get_user_preference($info["createdBy"], 'realName', '');
605$info["lastModifByReal"] = $tikilib->get_user_preference($info["lastModifBy"], 'realName', '');
606
607if ($tracker_info['doNotShowEmptyField'] == 'y') {
608	$trackerlib = TikiLib::lib('trk');
609	$fields['data'] = $trackerlib->mark_fields_as_empty($fields['data']);
610}
611
612$smarty->assign('trackerId', $trackerId);
613$smarty->assign('tracker_info', $tracker_info);
614$smarty->assign_by_ref('info', $info);
615$smarty->assign_by_ref('fields', $fields["data"]);
616$smarty->assign_by_ref('ins_fields', $ins_fields["data"]);
617if ($prefs['feature_user_watches'] == 'y' and $tiki_p_watch_trackers == 'y') {
618	if ($user and isset($_REQUEST['watch'])) {
619		check_ticket('view-trackers-items');
620		if ($_REQUEST['watch'] == 'add') {
621			$tikilib->add_user_watch($user, 'tracker_item_modified', $itemId, 'tracker ' . $trackerId, $tracker_info['name'], "tiki-view_tracker_item.php?trackerId=" . $trackerId . "&amp;itemId=" . $itemId);
622		} else {
623			$remove_watch_tracker_type = 'tracker ' . $trackerId;
624			$tikilib->remove_user_watch($user, 'tracker_item_modified', $itemId, $remove_watch_tracker_type);
625		}
626	}
627	$smarty->assign('user_watching_tracker', 'n');
628	$it = $tikilib->user_watches($user, 'tracker_item_modified', $itemId, 'tracker ' . $trackerId);
629	if ($user and $tikilib->user_watches($user, 'tracker_item_modified', $itemId, 'tracker ' . $trackerId)) {
630		$smarty->assign('user_watching_tracker', 'y');
631	}
632	// Check, if the user is watching this trackers' item by a category.
633	if ($prefs['feature_categories'] == 'y') {
634		$watching_categories_temp = $categlib->get_watching_categories($trackerId, 'tracker', $user);
635		$smarty->assign('category_watched', 'n');
636		if (count($watching_categories_temp) > 0) {
637			$smarty->assign('category_watched', 'y');
638			$watching_categories = [];
639			foreach ($watching_categories_temp as $wct) {
640				$watching_categories[] = [
641					"categId" => $wct,
642					"name" => $categlib->get_category_name($wct)
643				];
644			}
645			$smarty->assign('watching_categories', $watching_categories);
646		}
647	}
648}
649
650if ($tracker_info['useComments'] == 'y') {
651	$comCount = $trklib->get_item_nb_comments($itemId);
652	$smarty->assign("comCount", $comCount);
653	$smarty->assign("canViewCommentsAsItemOwner", $itemObject->canViewComments());
654
655	$saveAndComment = $definition->getConfiguration('saveAndComment');
656	if ($saveAndComment !== 'n') {
657		if (! $itemObject->canPostComments()) {
658			$saveAndComment = 'n';
659		}
660	}
661	$smarty->assign("saveAndComment", $saveAndComment);
662}
663
664if ($tracker_info["useAttachments"] == 'y') {
665	if (isset($_REQUEST["removeattach"])) {
666		$_REQUEST["show"] = "att";
667	}
668	if (isset($_REQUEST["editattach"])) {
669		$att = $trklib->get_item_attachment($_REQUEST["editattach"]);
670		$smarty->assign("attach_comment", $att['comment']);
671		$smarty->assign("attach_version", $att['version']);
672		$smarty->assign("attach_longdesc", $att['longdesc']);
673		$smarty->assign("attach_file", $att["filename"]);
674		$smarty->assign("attId", $att["attId"]);
675		$_REQUEST["show"] = "att";
676	}
677	if (isset($_REQUEST['attach']) && $tiki_p_attach_trackers == 'y' && isset($_FILES['userfile1'])) {
678		// Process an attachment here
679		if (is_uploaded_file($_FILES['userfile1']['tmp_name'])) {
680			$fp = fopen($_FILES['userfile1']['tmp_name'], "rb");
681			$data = '';
682			$fhash = '';
683			if ($prefs['t_use_db'] == 'n') {
684				$fhash = md5($_FILES['userfile1']['name'] . $tikilib->now);
685				$fw = fopen($prefs['t_use_dir'] . $fhash, "wb");
686				if (! $fw) {
687					$smarty->assign('msg', tra('Cannot write to this file:') . $fhash);
688					$smarty->display("error.tpl");
689					die;
690				}
691			}
692			while (! feof($fp)) {
693				if ($prefs['t_use_db'] == 'n') {
694					$data = fread($fp, 8192 * 16);
695					fwrite($fw, $data);
696				} else {
697					$data .= fread($fp, 8192 * 16);
698				}
699			}
700			fclose($fp);
701			if ($prefs['t_use_db'] == 'n') {
702				fclose($fw);
703				$data = '';
704			}
705			try {
706				if ($prefs['t_use_db'] == 'n') {
707					$filegallib->assertUploadedFileIsSafe($prefs['t_use_dir'] . $fhash, $_FILES['userfile1']['name']);
708				} else {
709					$filegallib->assertUploadedContentIsSafe($data, $_FILES['userfile1']['name']);
710				}
711			} catch (Exception $e) {
712				$smarty->assign('msg', $_FILES['userfile1']['name'] . ': ' . $e->getMessage());
713				$smarty->display("error.tpl");
714				die;
715			}
716			$size = $_FILES['userfile1']['size'];
717			$name = $_FILES['userfile1']['name'];
718			$type = $_FILES['userfile1']['type'];
719		} else {
720			$smarty->assign('msg', $_FILES['userfile1']['name'] . ': ' . tra('Upload was not successful') . ': ' . $tikilib->uploaded_file_error($_FILES['userfile1']['error']));
721			$smarty->display("error.tpl");
722			die;
723		}
724		$trklib->replace_item_attachment($_REQUEST["attId"], $name, $type, $size, $data, $_REQUEST["attach_comment"], $user, $fhash, $_REQUEST["attach_version"], $_REQUEST["attach_longdesc"], $trackerId, $itemId, $tracker_info);
725		$_REQUEST["attId"] = 0;
726		$_REQUEST['show'] = "att";
727	}
728	// If anything below here is changed, please change lib/wiki-plugins/wikiplugin_attach.php as well.
729	$attextra = 'n';
730	if (strstr($tracker_info["orderAttachments"], '|')) {
731		$attextra = 'y';
732	}
733	$attfields = explode(',', strtok($tracker_info["orderAttachments"], '|'));
734	$atts = $trklib->list_item_attachments($itemId, 0, -1, 'comment_asc', '');
735	$smarty->assign('atts', $atts["data"]);
736	$smarty->assign('attCount', $atts["cant"]);
737	$smarty->assign('attfields', $attfields);
738	$smarty->assign('attextra', $attextra);
739}
740if (isset($_REQUEST['moveto']) && empty($_REQUEST['moveto'])) {
741	$trackers = $trklib->list_trackers();
742	$smarty->assign_by_ref('trackers', $trackers['data']);
743	$_REQUEST['show'] = 'mod';
744}
745if (isset($_REQUEST['show'])) {
746	if ($_REQUEST['show'] == 'view') {
747		$cookietab = 1;
748		// for legacy edit mode after saving
749		setCookieSection('tabs_view_tracker_item', '', 'tabs');
750	} elseif ($tracker_info["useComments"] == 'y' and $_REQUEST['show'] == 'com') {
751		$cookietab = 2;
752	} elseif ($_REQUEST['show'] == "mod") {
753		$cookietab = 2;
754		if ($tracker_info["useAttachments"] == 'y') {
755			$cookietab++;
756		}
757		if ($tracker_info["useComments"] == 'y' && $tiki_p_tracker_view_comments == 'y') {
758			$cookietab++;
759		}
760	} elseif ($_REQUEST['show'] == "att") {
761		$cookietab = 2;
762		if ($tracker_info["useComments"] == 'y' && $tiki_p_tracker_view_comments == 'y') {
763			$cookietab = 3;
764		}
765	}
766}
767if (isset($_REQUEST['from'])) {
768	$from = $_REQUEST['from'];
769} else {
770	$from = false;
771}
772$smarty->assign('from', $from);
773if (isset($_REQUEST['status'])) {
774	$smarty->assign_by_ref('status', $_REQUEST['status']);
775}
776include_once('tiki-section_options.php');
777
778ask_ticket('view-trackers-items');
779if ($prefs['feature_actionlog'] == 'y') {
780	$logslib = TikiLib::lib('logs');
781	$logslib->add_action('Viewed', $itemId, 'trackeritem');
782}
783
784// Generate validation js
785if ($prefs['feature_jquery'] == 'y' && $prefs['feature_jquery_validation'] == 'y') {
786	$validatorslib = TikiLib::lib('validators');
787	$validationjs = $validatorslib->generateTrackerValidateJS($fields['data']);
788	$smarty->assign('validationjs', $validationjs);
789}
790
791if ($itemObject->canRemove()) {
792	$smarty->assign('editTitle', tr('Edit/Delete'));
793} else {
794	$smarty->assign('editTitle', tr('Edit'));
795}
796if (! empty($path)) {
797	$smarty->assign('formAction', $path);
798}
799$smarty->assign('pdf_export', ($prefs['print_pdf_from_url'] != 'none') ? 'y' : 'n');
800$smarty->assign('canView', $itemObject->canView());
801$smarty->assign('canModify', $itemObject->canModify());
802$smarty->assign('canRemove', $itemObject->canRemove());
803
804
805// Add view/edit template. Override an optional template defined in the tracker by a template passed via request
806// Note: Override is only allowed if a default template was set already in the tracker.
807
808// View
809$viewItemPretty = [
810		'override' => false,
811		'value' => $tracker_info['viewItemPretty'],
812		'type' => 'wiki'
813];
814if (! empty($tracker_info['viewItemPretty'])) {
815	if (isset($_REQUEST['vi_tpl'])) {
816		$viewItemPretty['override'] = true;
817		$viewItemPretty['value'] = $_REQUEST['vi_tpl'];
818	}
819	// Need to check wether this is a wiki: or tpl: template, bc the smarty template needs to take care of this
820	if (strpos(strtolower($viewItemPretty['value']), 'wiki:') === false) {
821		$viewItemPretty['type'] = 'tpl';
822	}
823}
824$smarty->assign('viewItemPretty', $viewItemPretty);
825
826// Edit
827$editItemPretty = [
828	'override' => false,
829	'value' => $tracker_info['editItemPretty'],
830	'type' => 'wiki'
831];
832if (! empty($tracker_info['editItemPretty'])) {
833	if (isset($_REQUEST['ei_tpl'])) {
834		$editItemPretty['override'] = true;
835		$editItemPretty['value'] = $_REQUEST['ei_tpl'];
836	}
837	if (strpos(strtolower($editItemPretty['value']), 'wiki:') === false) {
838		$editItemPretty['type'] = 'tpl';
839	}
840}
841$smarty->assign('editItemPretty', $editItemPretty);
842
843// add referer url to setup the back button in tpl
844// check wether we have been called from a different page than ourselfs to save a link to the referer for a back buttom.
845// this can be a wikipage with the trackerlist item and and view item temlate set using vi_tpl=wiki:mytemplate
846// if we do anything on the current page (i.e. adding a comment) we need to keep that saved link.
847$referer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '';
848$temp = strtolower($referer);
849if (strpos($temp, 'vi_tpl=') || strpos($temp, 'ei_tpl=')) {
850	$referer = $_SESSION['item_tpl_referer'];
851} else {
852	$_SESSION['item_tpl_referer'] = $referer;
853}
854unset($temp);
855$smarty->assign('referer', $referer);
856
857// Display the template
858$smarty->assign('mid', 'tiki-view_tracker_item.tpl');
859
860try {
861	if (isset($_REQUEST['print'])) {
862		$smarty->assign('print_page', 'y');
863		$smarty->display('tiki-print.tpl');
864	} elseif (isset($_REQUEST['pdf'])) {
865		$smarty->assign('print_page', 'y');
866		$trackerData = $smarty->fetch('tiki-print.tpl');
867		//getting comments associated with tracker item
868		$broker = TikiLib::lib('service')->getBroker();
869		$comments = $broker->internalRender("comment", "list", $jitRequest = new JitFilter(["controller" => "comment","action" => "list","type" => "trackeritem","objectId" => $itemId]));
870		require_once 'lib/pdflib.php';
871		$generator = new PdfGenerator();
872		if (! empty($generator->error)) {
873			Feedback::error($generator->error);
874			$access->redirect($page);
875		} else {
876			$pdf = $generator->getPdf('tiki-print.php', ['page' => $tracker_info['name']], str_ireplace("</dl>", "</dl><h3>Comments</h3>" . $comments . "<br />", $trackerData));
877			$length = strlen($pdf);
878			header('Cache-Control: private, must-revalidate');
879			header('Pragma: private');
880			header("Content-Description: File Transfer");
881			header('Content-disposition: attachment; filename="' . TikiLib::lib('tiki')->remove_non_word_characters_and_accents($trklib->get_isMain_value($trackerId, $itemId)) . '.pdf"');
882			header("Content-Type: application/pdf");
883			header("Content-Transfer-Encoding: binary");
884			header('Content-Length: ' . $length);
885			echo $pdf;
886		}
887		 //end of pdf
888	} else {
889		$smarty->display('tiki.tpl');
890	}
891} catch (SmartyException $e) {
892	$message = tr('The requested element cannot be displayed. One of the view/edit templates is missing or has errors: %0', $e->getMessage());
893	trigger_error($e->getMessage(), E_USER_ERROR);
894	$smarty->loadPlugin('smarty_modifier_sefurl');
895	$access->redirect(smarty_modifier_sefurl($info['trackerId'], 'tracker'), $message, 302, 'error');
896}
897