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