dolibarr 19.0.3
contact.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2010 Regis Houssin <regis.houssin@inodbox.com>
3 * Copyright (C) 2012-2015 Laurent Destailleur <eldy@users.sourceforge.net>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <https://www.gnu.org/licenses/>.
17 */
18
25// Load Dolibarr environment
26require '../main.inc.php';
27require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
28require_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php';
29require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php';
30require_once DOL_DOCUMENT_ROOT.'/core/lib/project.lib.php';
31require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php';
32if (isModEnabled('categorie')) {
33 require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
34}
35
36// Load translation files required by the page
37$langsLoad=array('projects', 'companies');
38if (isModEnabled('eventorganization')) {
39 $langsLoad[]='eventorganization';
40}
41
42$langs->loadLangs($langsLoad);
43
44$id = GETPOST('id', 'int');
45$ref = GETPOST('ref', 'alpha');
46$lineid = GETPOST('lineid', 'int');
47$socid = GETPOST('socid', 'int');
48$action = GETPOST('action', 'aZ09');
49
50$mine = GETPOST('mode') == 'mine' ? 1 : 0;
51//if (! $user->rights->projet->all->lire) $mine=1; // Special for projects
52
53$object = new Project($db);
54
55include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be include, not include_once
56if (getDolGlobalString('PROJECT_ALLOW_COMMENT_ON_PROJECT') && method_exists($object, 'fetchComments') && empty($object->comments)) {
57 $object->fetchComments();
58}
59
60// Security check
61$socid = 0;
62//if ($user->socid > 0) $socid = $user->socid; // For external user, no check is done on company because readability is managed by public status of project and assignement.
63$result = restrictedArea($user, 'projet', $id, 'projet&project');
64
65$hookmanager->initHooks(array('projectcontactcard', 'globalcard'));
66
67
68/*
69 * Actions
70 */
71
72$parameters = array('id'=>$id);
73$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action);
74if ($reshook < 0) {
75 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
76}
77
78if (empty($reshook)) {
79 // Test if we can add contact to the tasks at the same times, if not or not required, make a redirect
80 $formconfirmtoaddtasks = '';
81 if ($action == 'addcontact') {
82 $form = new Form($db);
83
84 $source=GETPOST("source", 'aZ09');
85
86 $taskstatic = new Task($db);
87 $task_array = $taskstatic->getTasksArray(0, 0, $object->id, 0, 0);
88 $nbTasks = count($task_array);
89
90 //If no task avaiblable, redirec to to add confirm
91 $type_to = (GETPOST('typecontact') ? 'typecontact='.GETPOST('typecontact') : 'type='.GETPOST('type'));
92 $personToAffect = (GETPOST('userid') ? GETPOST('userid', 'int') : GETPOST('contactid', 'int'));
93 $affect_to = (GETPOST('userid') ? 'userid='.$personToAffect : 'contactid='.$personToAffect);
94 $url_redirect='?id='.$object->id.'&'.$affect_to.'&'.$type_to.'&source='.$source;
95
96 if ($personToAffect > 0 && (!getDolGlobalString('PROJECT_HIDE_TASKS') || $nbTasks > 0)) {
97 $text = $langs->trans('AddPersonToTask');
98 $textbody = $text.' (<a href="#" class="selectall">'.$langs->trans("SelectAll").'</a>)';
99 $formquestion = array('text' => $textbody);
100
101 $task_to_affect = array();
102 foreach ($task_array as $task) {
103 $task_already_affected=false;
104 $personsLinked = $task->liste_contact(-1, $source);
105 if (!is_array($personsLinked) && count($personsLinked) < 0) {
106 setEventMessage($object->error, 'errors');
107 } else {
108 foreach ($personsLinked as $person) {
109 if ($person['id']==$personToAffect) {
110 $task_already_affected = true;
111 break;
112 }
113 }
114 if (!$task_already_affected) {
115 $task_to_affect[$task->id] = $task->id;
116 }
117 }
118 }
119
120 if (empty($task_to_affect)) {
121 $action = 'addcontact_confirm';
122 } else {
123 $formcompany = new FormCompany($db);
124 foreach ($task_array as $task) {
125 $key = $task->id;
126 $val = $task->ref . ' '.dol_trunc($task->label);
127 $formquestion[] = array(
128 'type' => 'other',
129 'name' => 'person_'.$key.',person_role_'.$key,
130 'label' => '<input type="checkbox" class="flat'.(in_array($key, $task_to_affect) ? ' taskcheckboxes"' : '" checked disabled').' id="person_'.$key.'" name="person_'.$key.'" value="1"> <label for="person_'.$key.'">'.$val.'<label>',
131 'value' => $formcompany->selectTypeContact($taskstatic, '', 'person_role_'.$key, $source, 'position', 0, 'minwidth100imp', 0, 1)
132 );
133 }
134 $formquestion[] = array('type'=> 'other', 'name'=>'tasksavailable', 'label'=>'', 'value' => '<input type="hidden" id="tasksavailable" name="tasksavailable" value="'.implode(',', array_keys($task_to_affect)).'">');
135 }
136
137 $formconfirmtoaddtasks = $form->formconfirm($_SERVER['PHP_SELF'] . $url_redirect, $text, '', 'addcontact_confirm', $formquestion, '', 1, 300, 590);
138 $formconfirmtoaddtasks .='
139 <script>
140 $(document).ready(function() {
141 var saveprop = false;
142 $(".selectall").click(function(){
143 console.log("We click on select all with "+saveprop);
144 if (!saveprop) {
145 $(".taskcheckboxes").prop("checked", true);
146 saveprop = true;
147 } else {
148 $(".taskcheckboxes").prop("checked", false);
149 saveprop = false;
150 }
151 });
152 });
153 </script>';
154 } else {
155 $action = 'addcontact_confirm';
156 }
157 }
158
159 // Add new contact
160 if ($action == 'addcontact_confirm' && $user->hasRight('projet', 'creer')) {
161 if (GETPOST('confirm', 'alpha') == 'no') {
162 header("Location: ".$_SERVER['PHP_SELF']."?id=".$object->id);
163 exit;
164 }
165
166 $contactid = (GETPOST('userid') ? GETPOST('userid', 'int') : GETPOST('contactid', 'int'));
167 $typeid = (GETPOST('typecontact') ? GETPOST('typecontact') : GETPOST('type'));
168
169 if (! ($contactid > 0)) {
170 $error++;
171 $langs->load("errors");
172 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Contact")), null, 'errors');
173 }
174
175 $result = 0;
176 $result = $object->fetch($id);
177
178 if (!$error && $result > 0 && $id > 0) {
179 $result = $object->add_contact($contactid, $typeid, GETPOST("source", 'aZ09'));
180
181 if ($result == 0) {
182 $langs->load("errors");
183 setEventMessages($langs->trans("ErrorThisContactIsAlreadyDefinedAsThisType"), null, 'errors');
184 } elseif ($result < 0) {
185 if ($object->error == 'DB_ERROR_RECORD_ALREADY_EXISTS') {
186 $langs->load("errors");
187 setEventMessages($langs->trans("ErrorThisContactIsAlreadyDefinedAsThisType"), null, 'errors');
188 } else {
189 setEventMessages($object->error, $object->errors, 'errors');
190 }
191 }
192
193 $affecttotask=GETPOST('tasksavailable', 'intcomma');
194 if (!empty($affecttotask)) {
195 require_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php';
196 $task_to_affect = explode(',', $affecttotask);
197 if (!empty($task_to_affect)) {
198 foreach ($task_to_affect as $task_id) {
199 if (GETPOSTISSET('person_'.$task_id) && GETPOST('person_'.$task_id, 'san_alpha')) {
200 $tasksToAffect = new Task($db);
201 $result=$tasksToAffect->fetch($task_id);
202 if ($result < 0) {
203 setEventMessages($tasksToAffect->error, null, 'errors');
204 } else {
205 $result = $tasksToAffect->add_contact($contactid, GETPOST('person_role_'.$task_id), GETPOST("source", 'aZ09'));
206 if ($result < 0) {
207 if ($tasksToAffect->error == 'DB_ERROR_RECORD_ALREADY_EXISTS') {
208 $langs->load("errors");
209 setEventMessages($langs->trans("ErrorThisContactIsAlreadyDefinedAsThisType"), null, 'errors');
210 } else {
211 setEventMessages($tasksToAffect->error, $tasksToAffect->errors, 'errors');
212 }
213 }
214 }
215 }
216 }
217 }
218 }
219 }
220
221 if ($result >= 0) {
222 header("Location: ".$_SERVER['PHP_SELF']."?id=".$object->id);
223 exit;
224 }
225 }
226
227 // Change contact's status
228 if ($action == 'swapstatut' && $user->hasRight('projet', 'creer')) {
229 if ($object->fetch($id)) {
230 $result = $object->swapContactStatus(GETPOST('ligne', 'int'));
231 } else {
232 dol_print_error($db);
233 }
234 }
235
236 // Delete a contact
237 if (($action == 'deleteline' || $action == 'deletecontact') && $user->hasRight('projet', 'creer')) {
238 $object->fetch($id);
239 $result = $object->delete_contact(GETPOST("lineid", 'int'));
240
241 if ($result >= 0) {
242 header("Location: contact.php?id=".$object->id);
243 exit;
244 } else {
245 dol_print_error($db);
246 }
247 }
248}
249
250
251/*
252 * View
253 */
254
255$form = new Form($db);
256$contactstatic = new Contact($db);
257$userstatic = new User($db);
258
259$title = $langs->trans('ProjectContact').' - '.$object->ref.' '.$object->name;
260if (getDolGlobalString('MAIN_HTML_TITLE') && preg_match('/projectnameonly/', $conf->global->MAIN_HTML_TITLE) && $object->name) {
261 $title = $object->ref.' '.$object->name.' - '.$langs->trans('ProjectContact');
262}
263
264$help_url = 'EN:Module_Projects|FR:Module_Projets|ES:M&oacute;dulo_Proyectos|DE:Modul_Projekte';
265
266llxHeader('', $title, $help_url);
267
268
269
270if ($id > 0 || !empty($ref)) {
271 /*
272 * View
273 */
274 if (getDolGlobalString('PROJECT_ALLOW_COMMENT_ON_PROJECT') && method_exists($object, 'fetchComments') && empty($object->comments)) {
275 $object->fetchComments();
276 }
277 // To verify role of users
278 //$userAccess = $object->restrictedProjectArea($user,'read');
279 $userWrite = $object->restrictedProjectArea($user, 'write');
280 //$userDelete = $object->restrictedProjectArea($user,'delete');
281 //print "userAccess=".$userAccess." userWrite=".$userWrite." userDelete=".$userDelete;
282
283 $head = project_prepare_head($object);
284 print dol_get_fiche_head($head, 'contact', $langs->trans("Project"), -1, ($object->public ? 'projectpub' : 'project'));
285
286 $formconfirm = $formconfirmtoaddtasks;
287
288 // Call Hook formConfirm
289 $parameters = array('formConfirm' => $formconfirm);
290 $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
291 if (empty($reshook)) {
292 $formconfirm .= $hookmanager->resPrint;
293 } elseif ($reshook > 0) {
294 $formconfirm = $hookmanager->resPrint;
295 }
296
297 // Print form confirm
298 print $formconfirm;
299
300 // Project card
301
302 if (!empty($_SESSION['pageforbacktolist']) && !empty($_SESSION['pageforbacktolist']['project'])) {
303 $tmpurl = $_SESSION['pageforbacktolist']['project'];
304 $tmpurl = preg_replace('/__SOCID__/', $object->socid, $tmpurl);
305 $linkback = '<a href="'.$tmpurl.(preg_match('/\?/', $tmpurl) ? '&' : '?'). 'restore_lastsearch_values=1">'.$langs->trans("BackToList").'</a>';
306 } else {
307 $linkback = '<a href="'.DOL_URL_ROOT.'/projet/list.php?restore_lastsearch_values=1">'.$langs->trans("BackToList").'</a>';
308 }
309
310 $morehtmlref = '<div class="refidno">';
311 // Title
312 $morehtmlref .= dol_escape_htmltag($object->title);
313 $morehtmlref .= '<br>';
314 // Thirdparty
315 if (!empty($object->thirdparty->id) && $object->thirdparty->id > 0) {
316 $morehtmlref .= $object->thirdparty->getNomUrl(1, 'project');
317 }
318 $morehtmlref .= '</div>';
319
320 // Define a complementary filter for search of next/prev ref.
321 if (!$user->hasRight('projet', 'all', 'lire')) {
322 $objectsListId = $object->getProjectsAuthorizedForUser($user, 0, 0);
323 $object->next_prev_filter = "rowid IN (".$db->sanitize(count($objectsListId) ? join(',', array_keys($objectsListId)) : '0').")";
324 }
325
326 dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref);
327
328
329 print '<div class="fichecenter">';
330 print '<div class="fichehalfleft">';
331 print '<div class="underbanner clearboth"></div>';
332
333 print '<table class="border tableforfield centpercent">';
334
335 // Usage
336 if (getDolGlobalString('PROJECT_USE_OPPORTUNITIES') || !getDolGlobalString('PROJECT_HIDE_TASKS') || isModEnabled('eventorganization')) {
337 print '<tr><td class="tdtop">';
338 print $langs->trans("Usage");
339 print '</td>';
340 print '<td>';
341 if (getDolGlobalString('PROJECT_USE_OPPORTUNITIES')) {
342 print '<input type="checkbox" disabled name="usage_opportunity"'.(GETPOSTISSET('usage_opportunity') ? (GETPOST('usage_opportunity', 'alpha') != '' ? ' checked="checked"' : '') : ($object->usage_opportunity ? ' checked="checked"' : '')).'"> ';
343 $htmltext = $langs->trans("ProjectFollowOpportunity");
344 print $form->textwithpicto($langs->trans("ProjectFollowOpportunity"), $htmltext);
345 print '<br>';
346 }
347 if (!getDolGlobalString('PROJECT_HIDE_TASKS')) {
348 print '<input type="checkbox" disabled name="usage_task"'.(GETPOSTISSET('usage_task') ? (GETPOST('usage_task', 'alpha') != '' ? ' checked="checked"' : '') : ($object->usage_task ? ' checked="checked"' : '')).'"> ';
349 $htmltext = $langs->trans("ProjectFollowTasks");
350 print $form->textwithpicto($langs->trans("ProjectFollowTasks"), $htmltext);
351 print '<br>';
352 }
353 if (!getDolGlobalString('PROJECT_HIDE_TASKS') && getDolGlobalString('PROJECT_BILL_TIME_SPENT')) {
354 print '<input type="checkbox" disabled name="usage_bill_time"'.(GETPOSTISSET('usage_bill_time') ? (GETPOST('usage_bill_time', 'alpha') != '' ? ' checked="checked"' : '') : ($object->usage_bill_time ? ' checked="checked"' : '')).'"> ';
355 $htmltext = $langs->trans("ProjectBillTimeDescription");
356 print $form->textwithpicto($langs->trans("BillTime"), $htmltext);
357 print '<br>';
358 }
359 if (isModEnabled('eventorganization')) {
360 print '<input type="checkbox" disabled name="usage_organize_event"'.(GETPOSTISSET('usage_organize_event') ? (GETPOST('usage_organize_event', 'alpha') != '' ? ' checked="checked"' : '') : ($object->usage_organize_event ? ' checked="checked"' : '')).'"> ';
361 $htmltext = $langs->trans("EventOrganizationDescriptionLong");
362 print $form->textwithpicto($langs->trans("ManageOrganizeEvent"), $htmltext);
363 }
364 print '</td></tr>';
365 }
366
367 // Visibility
368 print '<tr><td class="titlefield">'.$langs->trans("Visibility").'</td><td>';
369 if ($object->public) {
370 print img_picto($langs->trans('SharedProject'), 'world', 'class="paddingrightonly"');
371 print $langs->trans('SharedProject');
372 } else {
373 print img_picto($langs->trans('PrivateProject'), 'private', 'class="paddingrightonly"');
374 print $langs->trans('PrivateProject');
375 }
376 print '</td></tr>';
377
378 if (getDolGlobalString('PROJECT_USE_OPPORTUNITIES') && !empty($object->usage_opportunity)) {
379 // Opportunity status
380 print '<tr><td>'.$langs->trans("OpportunityStatus").'</td><td>';
381 $code = dol_getIdFromCode($db, $object->opp_status, 'c_lead_status', 'rowid', 'code');
382 if ($code) {
383 print $langs->trans("OppStatus".$code);
384 }
385
386 // Opportunity percent
387 print ' <span title="'.$langs->trans("OpportunityProbability").'"> / ';
388 if (strcmp($object->opp_percent, '')) {
389 print price($object->opp_percent, 0, $langs, 1, 0).' %';
390 }
391 print '</span></td></tr>';
392
393 // Opportunity Amount
394 print '<tr><td>'.$langs->trans("OpportunityAmount").'</td><td>';
395 if (strcmp($object->opp_amount, '')) {
396 print '<span class="amount">'.price($object->opp_amount, 0, $langs, 1, 0, -1, $conf->currency).'</span>';
397 if (strcmp($object->opp_percent, '')) {
398 print ' &nbsp; &nbsp; &nbsp; <span title="'.dol_escape_htmltag($langs->trans('OpportunityWeightedAmount')).'"><span class="opacitymedium">'.$langs->trans("Weighted").'</span>: <span class="amount">'.price($object->opp_amount * $object->opp_percent / 100, 0, $langs, 1, 0, -1, $conf->currency).'</span></span>';
399 }
400 }
401 print '</td></tr>';
402 }
403
404 // Budget
405 print '<tr><td>'.$langs->trans("Budget").'</td><td>';
406 if (!is_null($object->budget_amount) && strcmp($object->budget_amount, '')) {
407 print '<span class="amount">'.price($object->budget_amount, 0, $langs, 1, 0, 0, $conf->currency).'</span>';
408 }
409 print '</td></tr>';
410
411 // Date start - end project
412 print '<tr><td>'.$langs->trans("Dates").'</td><td>';
413 $start = dol_print_date($object->date_start, 'day');
414 print($start ? $start : '?');
415 $end = dol_print_date($object->date_end, 'day');
416 print ' <span class="opacitymedium">-</span> ';
417 print($end ? $end : '?');
418 if ($object->hasDelay()) {
419 print img_warning("Late");
420 }
421 print '</td></tr>';
422
423 // Other attributes
424 $cols = 2;
425 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php';
426
427 print "</table>";
428
429 print '</div>';
430 print '<div class="fichehalfright">';
431 print '<div class="underbanner clearboth"></div>';
432
433 print '<table class="border tableforfield centpercent">';
434
435 // Description
436 print '<td class="titlefield tdtop">'.$langs->trans("Description").'</td><td>';
437 print dol_htmlentitiesbr($object->description);
438 print '</td></tr>';
439
440 // Categories
441 if (isModEnabled('categorie')) {
442 print '<tr><td class="valignmiddle">'.$langs->trans("Categories").'</td><td>';
443 print $form->showCategories($object->id, Categorie::TYPE_PROJECT, 1);
444 print "</td></tr>";
445 }
446
447 print '</table>';
448
449 print '</div>';
450 print '</div>';
451
452 print '<div class="clearboth"></div>';
453
454 print dol_get_fiche_end();
455
456 print '<br>';
457
458 // Contacts lines (modules that overwrite templates must declare this into descriptor)
459 $dirtpls = array_merge($conf->modules_parts['tpl'], array('/core/tpl'));
460 foreach ($dirtpls as $reldir) {
461 $res = @include dol_buildpath($reldir.'/contacts.tpl.php');
462 if ($res) {
463 break;
464 }
465 }
466}
467
468// End of page
469llxFooter();
470$db->close();
if(!defined('NOREQUIRESOC')) if(!defined( 'NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined( 'NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined( 'NOREQUIREAJAX')) llxHeader()
Empty header.
Definition wrapper.php:55
llxFooter()
Empty footer.
Definition wrapper.php:69
Class to build HTML component for third parties management Only common components are here.
Class to manage generation of HTML components Only common components must be here.
Class to manage projects.
Class to manage tasks.
Class to manage Dolibarr users.
dol_banner_tab($object, $paramid, $morehtml='', $shownav=1, $fieldid='rowid', $fieldref='ref', $morehtmlref='', $moreparam='', $nodbprefix=0, $morehtmlleft='', $morehtmlstatus='', $onlybanner=0, $morehtmlright='')
Show tab footer of a card.
img_warning($titlealt='default', $moreatt='', $morecss='pictowarning')
Show warning logo.
dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limittoshow=0, $moretabssuffix='', $dragdropfile=0)
Show tabs of a record.
dol_print_error($db='', $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
dol_get_fiche_end($notab=0)
Return tab footer of a card.
setEventMessage($mesgs, $style='mesgs', $noduplicate=0)
Set event message in dol_events session object.
price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code='')
Function to format a value into an amount for visual output Function used into PDF and HTML pages.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
dol_getIdFromCode($db, $key, $tablename, $fieldkey='code', $fieldid='id', $entityfilter=0, $filters='')
Return an id or code from a code or id.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0)
Set event messages in dol_events session object.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
dol_htmlentitiesbr($stringtoencode, $nl2brmode=0, $pagecodefrom='UTF-8', $removelasteolbr=1)
This function is called to encode a string into a HTML string but differs from htmlentities because a...
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
project_prepare_head(Project $project, $moreparam='')
Prepare array with list of tabs.
restrictedArea(User $user, $features, $object=0, $tableandshare='', $feature2='', $dbt_keyfield='fk_soc', $dbt_select='rowid', $isdraft=0, $mode=0)
Check permissions of a user to show a page and an object.
Contact()
Old copy.
Definition index.php:572