dolibarr 22.0.5
recruitmentcandidature.class.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2020 Laurent Destailleur <eldy@users.sourceforge.net>
3 * Copyright (C) 2024-2025 Frédéric France <frederic.france@free.fr>
4 * Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
26// Put here all includes required by your class file
27require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
28require_once DOL_DOCUMENT_ROOT.'/core/class/commonpeople.class.php';
29
34{
35 use CommonPeople;
36
40 public $module = 'recruitment';
41
45 public $element = 'recruitmentcandidature';
46
50 public $table_element = 'recruitment_recruitmentcandidature';
51
55 public $picto = 'recruitmentcandidature';
56
60 public $email_fields_no_propagate_in_actioncomm;
61
62
63 const STATUS_DRAFT = 0;
64 const STATUS_VALIDATED = 1;
65 //const STATUS_INTERVIEW_SCHEDULED = 2;
66 const STATUS_CONTRACT_PROPOSED = 3;
67 const STATUS_CONTRACT_SIGNED = 5;
68 const STATUS_CONTRACT_REFUSED = 6;
69 const STATUS_REFUSED = 8;
70 const STATUS_CANCELED = 9;
71
72
98 // BEGIN MODULEBUILDER PROPERTIES
102 public $fields = array(
103 'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'position' => 1, 'notnull' => 1, 'visible' => 0, 'noteditable' => 1, 'index' => 1, 'comment' => "Id"),
104 'entity' => array('type' => 'integer', 'label' => 'Entity', 'enabled' => 1, 'visible' => 0, 'position' => 5, 'notnull' => 1, 'default' => '1', 'index' => 1),
105 'ref' => array('type' => 'varchar(128)', 'label' => 'Ref', 'enabled' => 1, 'position' => 10, 'notnull' => 1, 'visible' => 4, 'noteditable' => 1, 'default' => '(PROV)', 'index' => 1, 'searchall' => 1, 'showoncombobox' => 1, 'comment' => "Reference of candidature", 'csslist' => 'nowraponall'),
106 'fk_recruitmentjobposition' => array('type' => 'integer:RecruitmentJobPosition:recruitment/class/recruitmentjobposition.class.php:0', 'label' => 'Job', 'enabled' => '1', 'position' => 15, 'notnull' => 0, 'visible' => 1, 'index' => 1, 'picto' => 'recruitmentjobposition', 'css' => 'minwidth300 maxwidth500 widthcentpercentminusx', 'csslist' => 'minwidth100 nowraponall'),
107 'note_public' => array('type' => 'html', 'label' => 'NotePublic', 'enabled' => 1, 'position' => 61, 'notnull' => 0, 'visible' => 0,),
108 'note_private' => array('type' => 'html', 'label' => 'NotePrivate', 'enabled' => 1, 'position' => 62, 'notnull' => 0, 'visible' => 0,),
109 'fk_user_creat' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserAuthor', 'enabled' => 1, 'position' => 510, 'notnull' => -1, 'visible' => -2, 'foreignkey' => 'user.rowid', 'csslist' => 'tdoverflowmax100'),
110 'fk_user_modif' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserModif', 'enabled' => 1, 'position' => 511, 'notnull' => -1, 'visible' => -2, 'csslist' => 'tdoverflowmax100'),
111 'lastname' => array('type' => 'varchar(128)', 'label' => 'Lastname', 'enabled' => 1, 'position' => 20, 'notnull' => 0, 'visible' => 1, 'csslist' => 'tdoverflowmax150'),
112 'firstname' => array('type' => 'varchar(128)', 'label' => 'Firstname', 'enabled' => 1, 'position' => 21, 'notnull' => 0, 'visible' => 1, 'csslist' => 'tdoverflowmax150'),
113 'email' => array('type' => 'email', 'label' => 'EMail', 'enabled' => 1, 'position' => 30, 'notnull' => 1, 'visible' => 1, 'picto' => 'email', 'csslist' => 'tdoverflowmax150'),
114 'phone' => array('type' => 'phone', 'label' => 'Phone', 'enabled' => 1, 'position' => 31, 'notnull' => 0, 'visible' => 1, 'picto' => 'phone', 'csslist' => 'tdoverflowmax150'),
115 'date_birth' => array('type' => 'date', 'label' => 'DateOfBirth', 'enabled' => 1, 'position' => 70, 'visible' => -1,),
116 'email_msgid' => array('type' => 'varchar(255)', 'label' => 'EmailMsgID', 'visible' => -2, 'enabled' => 1, 'position' => 540, 'notnull' => -1, 'help' => 'EmailMsgIDDesc'),
117 'email_date' => array('type' => 'datetime', 'label' => 'EmailDate', 'visible' => -2, 'enabled' => 1, 'position' => 541),
118 //'fk_recruitment_origin' => array('type'=>'integer:CRecruitmentOrigin:recruitment/class/crecruitmentorigin.class.php', 'label'=>'Origin', 'enabled'=>1, 'position'=>45, 'visible'=>1, 'index'=>1),
119 'remuneration_requested' => array('type' => 'integer', 'label' => 'RequestedRemuneration', 'enabled' => 1, 'position' => 80, 'notnull' => 0, 'visible' => -1,),
120 'remuneration_proposed' => array('type' => 'integer', 'label' => 'ProposedRemuneration', 'enabled' => 1, 'position' => 81, 'notnull' => 0, 'visible' => -1,),
121 'description' => array('type' => 'html', 'label' => 'Description', 'enabled' => 1, 'position' => 300, 'notnull' => 0, 'visible' => 3, 'cssview' => 'wordbreak'),
122 'date_creation' => array('type' => 'datetime', 'label' => 'DateCreation', 'enabled' => 1, 'position' => 500, 'notnull' => 1, 'visible' => -4, 'csslist' => 'nowraponall'),
123 'tms' => array('type' => 'timestamp', 'label' => 'DateModification', 'enabled' => 1, 'position' => 501, 'notnull' => 0, 'visible' => -2, 'csslist' => 'nowraponall'),
124 'fk_user' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'Employee', 'picto' => 'user', 'help' => 'LinkToUserCreated', 'enabled' => 1, 'position' => 600, 'notnull' => 0, 'visible' => -1, 'css' => 'minwidth300 maxwidth500 widthcentpercentminusx', 'csslist' => 'tdoverflowmax100'),
125 'import_key' => array('type' => 'varchar(14)', 'label' => 'ImportId', 'enabled' => 1, 'position' => 1000, 'notnull' => -1, 'visible' => -2,),
126 'model_pdf' => array('type' => 'varchar(255)', 'label' => 'Model pdf', 'enabled' => 1, 'position' => 1010, 'notnull' => -1, 'visible' => 0,),
127 'status' => array('type' => 'smallint', 'label' => 'Status', 'enabled' => 1, 'position' => 1000, 'notnull' => 1, 'visible' => 2, 'index' => 1, 'default' => '0', 'arrayofkeyval' => array(0 => 'Draft', 1 => 'Received', 3 => 'ContractProposed', 5 => 'ContractSigned', 8 => 'Refused', 9 => 'Canceled')),
128 "ip" => array("type" => "varchar(250)", "label" => "Ip", "enabled" => 1, 'position' => 700, 'notnull' => 0, "visible" => 0, "comment" => "ip used to create record (for public submission page)"),
129 );
133 public $rowid;
137 public $entity;
141 public $ref;
145 public $fk_recruitmentjobposition;
149 public $description;
153 public $fk_user_creat;
157 public $fk_user_modif;
161 public $fk_user;
165 public $lastname;
169 public $firstname;
173 public $email;
177 public $phone;
181 public $date_birth;
185 public $email_msgid;
189 public $email_date;
193 public $remuneration_requested;
197 public $remuneration_proposed;
201 public $fk_recruitment_origin;
205 public $import_key;
209 public $model_pdf;
213 public $status;
217 public $ip;
218 // END MODULEBUILDER PROPERTIES
219
225 public function __construct(DoliDB $db)
226 {
227 global $langs;
228
229 $this->db = $db;
230
231 $this->ismultientitymanaged = 1;
232 $this->isextrafieldmanaged = 1;
233
234 if (!getDolGlobalString('MAIN_SHOW_TECHNICAL_ID') && isset($this->fields['rowid'])) {
235 $this->fields['rowid']['visible'] = 0;
236 }
237 if (!isModEnabled('multicompany') && isset($this->fields['entity'])) {
238 $this->fields['entity']['enabled'] = 0;
239 }
240
241 // Example to show how to set values of fields definition dynamically
242 /*if ($user->rights->recruitment->recruitmentcandidature->read) {
243 $this->fields['myfield']['visible'] = 1;
244 $this->fields['myfield']['noteditable'] = 0;
245 }*/
246
247 // Unset fields that are disabled
248 foreach ($this->fields as $key => $val) {
249 if (isset($val['enabled']) && empty($val['enabled'])) {
250 unset($this->fields[$key]);
251 }
252 }
253
254 // Translate some data of arrayofkeyval
255 if (is_object($langs)) {
256 foreach ($this->fields as $key => $val) {
257 if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) {
258 foreach ($val['arrayofkeyval'] as $key2 => $val2) {
259 $this->fields[$key]['arrayofkeyval'][$key2] = $langs->trans($val2);
260 }
261 }
262 }
263 }
264 }
265
273 public function create(User $user, $notrigger = 0)
274 {
275 return $this->createCommon($user, $notrigger);
276 }
277
285 public function createFromClone(User $user, $fromid)
286 {
287 global $langs, $extrafields;
288 $error = 0;
289
290 dol_syslog(__METHOD__, LOG_DEBUG);
291
292 $object = new self($this->db);
293
294 $this->db->begin();
295
296 // Load source object
297 $result = $object->fetchCommon($fromid);
298 if ($result > 0 && !empty($object->table_element_line)) {
299 $object->fetchLines();
300 }
301
302 // get lines so they will be clone
303 //foreach($this->lines as $line)
304 // $line->fetch_optionals();
305
306 // Reset some properties
307 unset($object->id);
308 unset($object->fk_user_creat);
309 unset($object->import_key);
310
311 // Clear fields
312 if (property_exists($object, 'ref')) {
313 // @phan-suppress-next-line PhanTypeMismatchProperty
314 $object->ref = empty($this->fields['ref']['default']) ? "Copy_Of_".$object->ref : $this->fields['ref']['default'];
315 }
316
317 $object->status = self::STATUS_DRAFT;
318 $object->date_creation = dol_now();
319 $object->date_modification = null;
320
321 // Clear extrafields that are unique
322 if (is_array($object->array_options) && count($object->array_options) > 0) {
323 $extrafields->fetch_name_optionals_label($this->table_element);
324 foreach ($object->array_options as $key => $option) {
325 $shortkey = preg_replace('/options_/', '', $key);
326 if (!empty($extrafields->attributes[$this->table_element]['unique'][$shortkey])) {
327 //var_dump($key);
328 //var_dump($clonedObj->array_options[$key]); exit;
329 unset($object->array_options[$key]);
330 }
331 }
332 }
333
334 // Create clone
335 $object->context['createfromclone'] = 'createfromclone';
336 $result = $object->createCommon($user);
337 if ($result < 0) {
338 $error++;
339 $this->error = $object->error;
340 $this->errors = $object->errors;
341 }
342
343 if (!$error) {
344 // copy internal contacts
345 if ($this->copy_linked_contact($object, 'internal') < 0) {
346 $error++;
347 }
348 }
349
350 if (!$error) {
351 // copy external contacts if same company
352 if (property_exists($this, 'socid') && $this->socid == $object->socid) {
353 if ($this->copy_linked_contact($object, 'external') < 0) {
354 $error++;
355 }
356 }
357 }
358
359 unset($object->context['createfromclone']);
360
361 // End
362 if (!$error) {
363 $this->db->commit();
364 return $object;
365 } else {
366 $this->db->rollback();
367 return -1;
368 }
369 }
370
379 public function fetch($id, $ref = null, $email_msgid = '')
380 {
381 $morewhere = '';
382 if ($email_msgid) {
383 $morewhere = " AND email_msgid = '".$this->db->escape($email_msgid)."'";
384 }
385 $result = $this->fetchCommon($id, $ref, $morewhere);
386 if ($result > 0 && !empty($this->table_element_line)) {
387 $this->fetchLines();
388 }
389 return $result;
390 }
391
397 public function fetchLines()
398 {
399 $this->lines = array();
400
401 $result = $this->fetchLinesCommon();
402 return $result;
403 }
404
405
418 public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, $filter = '', $filtermode = 'AND')
419 {
420 dol_syslog(__METHOD__, LOG_DEBUG);
421
422 $records = array();
423
424 $sql = 'SELECT ';
425 $sql .= $this->getFieldList();
426 $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t';
427 if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) {
428 $sql .= ' WHERE t.entity IN ('.getEntity($this->element).')';
429 } else {
430 $sql .= ' WHERE 1 = 1';
431 }
432
433 // Manage filter
434 $errormessage = '';
435 $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage);
436 if ($errormessage) {
437 $this->errors[] = $errormessage;
438 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
439 return -1;
440 }
441
442 if (!empty($sortfield)) {
443 $sql .= $this->db->order($sortfield, $sortorder);
444 }
445 if (!empty($limit)) {
446 $sql .= $this->db->plimit($limit, $offset);
447 }
448
449 $resql = $this->db->query($sql);
450 if ($resql) {
451 $num = $this->db->num_rows($resql);
452 $i = 0;
453 while ($i < ($limit ? min($limit, $num) : $num)) {
454 $obj = $this->db->fetch_object($resql);
455
456 $record = new self($this->db);
457 $record->setVarsFromFetchObj($obj);
458
459 $records[$record->id] = $record;
460
461 $i++;
462 }
463 $this->db->free($resql);
464
465 return $records;
466 } else {
467 $this->errors[] = 'Error '.$this->db->lasterror();
468 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
469
470 return -1;
471 }
472 }
473
481 public function update(User $user, $notrigger = 0)
482 {
483 return $this->updateCommon($user, $notrigger);
484 }
485
493 public function delete(User $user, $notrigger = 0)
494 {
495 return $this->deleteCommon($user, $notrigger);
496 //return $this->deleteCommon($user, $notrigger, 1);
497 }
498
507 public function deleteLine(User $user, $idline, $notrigger = 0)
508 {
509 if ($this->status < 0) {
510 $this->error = 'ErrorDeleteLineNotAllowedByObjectStatus';
511 return -2;
512 }
513
514 return $this->deleteLineCommon($user, $idline, $notrigger);
515 }
516
517
525 public function validate($user, $notrigger = 0)
526 {
527 global $conf, $langs;
528
529 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
530
531 $error = 0;
532
533 // Protection
534 if ($this->status == self::STATUS_VALIDATED) {
535 dol_syslog(get_class($this)."::validate action abandoned: already validated", LOG_WARNING);
536 return 0;
537 }
538
539 /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->recruitment->recruitmentcandidature->write))
540 || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->recruitment->recruitmentcandidature->recruitmentcandidature_advance->validate))))
541 {
542 $this->error='NotEnoughPermissions';
543 dol_syslog(get_class($this)."::valid ".$this->error, LOG_ERR);
544 return -1;
545 }*/
546
547 $now = dol_now();
548
549 $this->db->begin();
550
551 // Define new ref
552 if (!$error && (preg_match('/^[\‍(]?PROV/i', $this->ref) || empty($this->ref))) { // empty should not happened, but when it occurs, the test save life
553 $num = $this->getNextNumRef();
554 } else {
555 $num = $this->ref;
556 }
557 $this->newref = $num;
558
559 if (!empty($num)) {
560 // Validate
561 $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element;
562 $sql .= " SET ref = '".$this->db->escape($num)."',";
563 $sql .= " status = ".self::STATUS_VALIDATED;
564 if (!empty($this->fields['date_validation'])) {
565 $sql .= ", date_validation = '".$this->db->idate($now)."',";
566 }
567 if (!empty($this->fields['fk_user_valid'])) { // @phan-suppress-current-line PhanTypeMismatchProperty
568 $sql .= ", fk_user_valid = ".((int) $user->id);
569 }
570 $sql .= " WHERE rowid = ".((int) $this->id);
571
572 dol_syslog(get_class($this)."::validate()", LOG_DEBUG);
573 $resql = $this->db->query($sql);
574 if (!$resql) {
575 dol_print_error($this->db);
576 $this->error = $this->db->lasterror();
577 $error++;
578 }
579
580 if (!$error && !$notrigger) {
581 // Call trigger
582 $result = $this->call_trigger('RECRUITMENTCANDIDATURE_VALIDATE', $user);
583 if ($result < 0) {
584 $error++;
585 }
586 // End call triggers
587 }
588 }
589
590 if (!$error) {
591 $this->oldref = $this->ref;
592
593 // Rename directory if dir was a temporary ref
594 if (preg_match('/^[\‍(]?PROV/i', $this->ref)) {
595 // Now we rename also files into index
596 $sql = 'UPDATE '.MAIN_DB_PREFIX."ecm_files set filename = CONCAT('".$this->db->escape($this->newref)."', SUBSTR(filename, ".(strlen($this->ref) + 1).")), filepath = 'recruitmentcandidature/".$this->db->escape($this->newref)."'";
597 $sql .= " WHERE filename LIKE '".$this->db->escape($this->ref)."%' AND filepath = 'recruitmentcandidature/".$this->db->escape($this->ref)."' and entity = ".$conf->entity;
598 $resql = $this->db->query($sql);
599 if (!$resql) {
600 $error++;
601 $this->error = $this->db->lasterror();
602 }
603 $sql = 'UPDATE '.MAIN_DB_PREFIX."ecm_files set filepath = 'recruitmentcandidature/".$this->db->escape($this->newref)."'";
604 $sql .= " WHERE filepath = 'recruitmentcandidature/".$this->db->escape($this->ref)."' and entity = ".$conf->entity;
605 $resql = $this->db->query($sql);
606 if (!$resql) {
607 $error++;
608 $this->error = $this->db->lasterror();
609 }
610
611 // We rename directory ($this->ref = old ref, $num = new ref) in order not to lose the attachments
612 $oldref = dol_sanitizeFileName($this->ref);
613 $newref = dol_sanitizeFileName($num);
614 $dirsource = $conf->recruitment->dir_output.'/recruitmentcandidature/'.$oldref;
615 $dirdest = $conf->recruitment->dir_output.'/recruitmentcandidature/'.$newref;
616 if (!$error && file_exists($dirsource)) {
617 dol_syslog(get_class($this)."::validate() rename dir ".$dirsource." into ".$dirdest);
618
619 if (@rename($dirsource, $dirdest)) {
620 dol_syslog("Rename ok");
621 // Rename docs starting with $oldref with $newref
622 $listoffiles = dol_dir_list($conf->recruitment->dir_output.'/recruitmentcandidature/'.$newref, 'files', 1, '^'.preg_quote($oldref, '/'));
623 foreach ($listoffiles as $fileentry) {
624 $dirsource = $fileentry['name'];
625 $dirdest = preg_replace('/^'.preg_quote($oldref, '/').'/', $newref, $dirsource);
626 $dirsource = $fileentry['path'].'/'.$dirsource;
627 $dirdest = $fileentry['path'].'/'.$dirdest;
628 @rename($dirsource, $dirdest);
629 }
630 }
631 }
632 }
633 }
634
635 // Set new ref and current status
636 if (!$error) {
637 $this->ref = $num;
638 $this->status = self::STATUS_VALIDATED;
639 }
640
641 if (!$error) {
642 $this->db->commit();
643 return 1;
644 } else {
645 $this->db->rollback();
646 return -1;
647 }
648 }
649
650
658 public function setDraft($user, $notrigger = 0)
659 {
660 // Protection
661 if ($this->status <= self::STATUS_DRAFT) {
662 return 0;
663 }
664
665 /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->recruitment->write))
666 || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->recruitment->recruitment_advance->validate))))
667 {
668 $this->error='Permission denied';
669 return -1;
670 }*/
671
672 return $this->setStatusCommon($user, self::STATUS_DRAFT, $notrigger, 'RECRUITMENTCANDIDATURE_UNVALIDATE');
673 }
674
682 public function cancel($user, $notrigger = 0)
683 {
684 // Protection
685 if ($this->status != self::STATUS_VALIDATED) {
686 return 0;
687 }
688
689 /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->recruitment->write))
690 || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->recruitment->recruitment_advance->validate))))
691 {
692 $this->error='Permission denied';
693 return -1;
694 }*/
695
696 return $this->setStatusCommon($user, self::STATUS_CANCELED, $notrigger, 'RECRUITMENTCANDIDATURE_CLOSE');
697 }
698
706 public function reopen($user, $notrigger = 0)
707 {
708 // Protection
709 if ($this->status != self::STATUS_REFUSED && $this->status != self::STATUS_CANCELED && $this->status != self::STATUS_CONTRACT_REFUSED) {
710 return 0;
711 }
712
713 /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->recruitment->write))
714 || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->recruitment->recruitment_advance->validate))))
715 {
716 $this->error='Permission denied';
717 return -1;
718 }*/
719
720 return $this->setStatusCommon($user, self::STATUS_VALIDATED, $notrigger, 'RECRUITMENTCANDIDATURE_REOPEN');
721 }
722
732 public function getFullName($langs, $option = 0, $nameorder = -1, $maxlen = 0)
733 {
734 $lastname = $this->lastname;
735 $firstname = $this->firstname;
736 if (empty($lastname)) {
737 $lastname = (isset($this->lastname) ? $this->lastname : (isset($this->name) ? $this->name : (isset($this->nom) ? $this->nom : (isset($this->societe) ? $this->societe : (isset($this->company) ? $this->company : '')))));
738 }
739
740 $ret = '';
741
742 $ret .= dolGetFirstLastname($firstname, $lastname, $nameorder);
743
744 return dol_trunc($ret, $maxlen);
745 }
746
757 public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
758 {
759 global $conf, $langs, $hookmanager;
760
761 if (!empty($conf->dol_no_mouse_hover)) {
762 $notooltip = 1; // Force disable tooltips
763 }
764
765 $result = '';
766
767 $label = img_picto('', $this->picto).' <u class="paddingrightonly">'.$langs->trans("RecruitmentCandidature").'</u>';
768 if (isset($this->status)) {
769 $label .= ' '.$this->getLibStatut(5);
770 }
771 $label .= '<br>';
772 $label .= '<b>'.$langs->trans('Ref').':</b> '.$this->ref;
773 $label .= '<br><b>'.$langs->trans('Email').':</b> '.$this->email;
774 $label .= '<br><b>'.$langs->trans('Name').':</b> '.$this->getFullName($langs);
775
776 $url = dol_buildpath('/recruitment/recruitmentcandidature_card.php', 1).'?id='.$this->id;
777
778 if ($option != 'nolink') {
779 // Add param to save lastsearch_values or not
780 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
781 if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
782 $add_save_lastsearch_values = 1;
783 }
784 if ($add_save_lastsearch_values) {
785 $url .= '&save_lastsearch_values=1';
786 }
787 }
788
789 $linkclose = '';
790 if (empty($notooltip)) {
791 if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
792 $label = $langs->trans("ShowRecruitmentCandidature");
793 $linkclose .= ' alt="'.dolPrintHTMLForAttribute($label).'"';
794 }
795 $linkclose .= ' title="'.dolPrintHTMLForAttribute($label).'"';
796 $linkclose .= ' class="classfortooltip'.($morecss ? ' '.$morecss : '').'"';
797 } else {
798 $linkclose = ($morecss ? ' class="'.$morecss.'"' : '');
799 }
800
801 $linkstart = '<a href="'.$url.'"';
802 $linkstart .= $linkclose.'>';
803 $linkend = '</a>';
804
805 $result .= $linkstart;
806
807 if (empty($this->showphoto_on_popup)) {
808 if ($withpicto) {
809 $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip ? 0 : 1);
810 }
811 } else {
812 if ($withpicto) {
813 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
814
815 list($class, $module) = explode('@', $this->picto);
816 $upload_dir = $conf->$module->multidir_output[$conf->entity]."/$class/".dol_sanitizeFileName($this->ref);
817 $filearray = dol_dir_list($upload_dir, "files");
818 $filename = $filearray[0]['name'];
819 if (!empty($filename)) {
820 $pospoint = strpos($filearray[0]['name'], '.');
821
822 $pathtophoto = $class.'/'.$this->ref.'/thumbs/'.substr($filename, 0, $pospoint).'_mini'.substr($filename, $pospoint);
823 if (!getDolGlobalString(strtoupper($module.'_'.$class).'_FORMATLISTPHOTOSASUSERS')) {
824 $result .= '<div class="floatleft inline-block valignmiddle divphotoref"><div class="photoref"><img class="photo'.$module.'" alt="No photo" border="0" src="'.DOL_URL_ROOT.'/viewimage.php?modulepart='.$module.'&entity='.$conf->entity.'&file='.urlencode($pathtophoto).'"></div></div>';
825 } else {
826 $result .= '<div class="floatleft inline-block valignmiddle divphotoref"><img class="photouserphoto userphoto" alt="No photo" border="0" src="'.DOL_URL_ROOT.'/viewimage.php?modulepart='.$module.'&entity='.$conf->entity.'&file='.urlencode($pathtophoto).'"></div>';
827 }
828
829 $result .= '</div>';
830 } else {
831 $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip ? 0 : 1);
832 }
833 }
834 }
835
836 if ($withpicto != 2) {
837 $result .= $this->ref;
838 }
839
840 $result .= $linkend;
841 //if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : '');
842
843 global $action, $hookmanager;
844 $hookmanager->initHooks(array('recruitmentcandidaturedao'));
845 $parameters = array('id' => $this->id, 'getnomurl' => &$result);
846 $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
847 if ($reshook > 0) {
848 $result = $hookmanager->resPrint;
849 } else {
850 $result .= $hookmanager->resPrint;
851 }
852
853 return $result;
854 }
855
862 public function getLibStatut($mode = 0)
863 {
864 return $this->LibStatut($this->status, $mode);
865 }
866
867 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
875 public function LibStatut($status, $mode = 0)
876 {
877 // phpcs:enable
878 if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
879 global $langs;
880 //$langs->load("recruitment@recruitment");
881 $this->labelStatus[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft');
882 $this->labelStatus[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Received').' ('.$langs->transnoentitiesnoconv("InterviewToDo").')';
883 $this->labelStatus[self::STATUS_CONTRACT_PROPOSED] = $langs->transnoentitiesnoconv('ContractProposed');
884 $this->labelStatus[self::STATUS_CONTRACT_SIGNED] = $langs->transnoentitiesnoconv('ContractSigned');
885 $this->labelStatus[self::STATUS_CONTRACT_REFUSED] = $langs->transnoentitiesnoconv('ContractRefused');
886 $this->labelStatus[self::STATUS_REFUSED] = $langs->transnoentitiesnoconv('Refused');
887 $this->labelStatus[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('Canceled');
888 $this->labelStatusShort[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft');
889 $this->labelStatusShort[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Received');
890 $this->labelStatusShort[self::STATUS_CONTRACT_PROPOSED] = $langs->transnoentitiesnoconv('ContractProposed');
891 $this->labelStatusShort[self::STATUS_CONTRACT_SIGNED] = $langs->transnoentitiesnoconv('ContractSigned');
892 $this->labelStatusShort[self::STATUS_CONTRACT_REFUSED] = $langs->transnoentitiesnoconv('ContractRefused');
893 $this->labelStatusShort[self::STATUS_REFUSED] = $langs->transnoentitiesnoconv('Refused');
894 $this->labelStatusShort[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('Canceled');
895 }
896
897 $statusType = 'status'.$status;
898 //if ($status == self::STATUS_VALIDATED) $statusType = 'status1';
899 if ($status == self::STATUS_CANCELED) {
900 $statusType = 'status9';
901 }
902 if ($status == self::STATUS_CONTRACT_PROPOSED) {
903 $statusType = 'status4';
904 }
905 if ($status == self::STATUS_CONTRACT_SIGNED) {
906 $statusType = 'status6';
907 }
908 if ($status == self::STATUS_REFUSED) {
909 $statusType = 'status10';
910 }
911
912 return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode);
913 }
914
921 public function info($id)
922 {
923 $sql = 'SELECT rowid, date_creation as datec, tms as datem,';
924 $sql .= ' fk_user_creat, fk_user_modif';
925 $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t';
926 $sql .= ' WHERE t.rowid = '.((int) $id);
927 $result = $this->db->query($sql);
928 if ($result) {
929 if ($this->db->num_rows($result)) {
930 $obj = $this->db->fetch_object($result);
931
932 $this->id = $obj->rowid;
933
934 $this->user_creation_id = $obj->fk_user_creat;
935 $this->user_modification_id = $obj->fk_user_modif;
936 $this->date_creation = $this->db->jdate($obj->datec);
937 $this->date_modification = empty($obj->datem) ? '' : $this->db->jdate($obj->datem);
938 }
939
940 $this->db->free($result);
941 } else {
942 dol_print_error($this->db);
943 }
944 }
945
952 public function initAsSpecimen()
953 {
954 return $this->initAsSpecimenCommon();
955 }
956
962 public function getLinesArray()
963 {
964 $this->lines = array();
965
966 $objectline = new RecruitmentCandidatureLine($this->db);
967 $result = $objectline->fetchAll('ASC', 'position', 0, 0, '(fk_recruitmentcandidature:=:'.((int) $this->id).')');
968
969 if (is_numeric($result)) {
970 $this->error = $objectline->error;
971 $this->errors = $objectline->errors;
972 return $result;
973 } else {
974 $this->lines = $result;
975 // @phpstan-ignore-next-line
976 return $result; // @phan-suppress-current-line PhanTypeMismatchReturn
977 }
978 }
979
985 public function getNextNumRef()
986 {
987 global $langs, $conf;
988 $langs->load("recruitment@recruitment");
989
990 if (!getDolGlobalString('RECRUITMENT_RECRUITMENTCANDIDATURE_ADDON')) {
991 $conf->global->RECRUITMENT_RECRUITMENTCANDIDATURE_ADDON = 'mod_recruitmentcandidature_standard';
992 }
993
994 if (getDolGlobalString('RECRUITMENT_RECRUITMENTCANDIDATURE_ADDON')) {
995 $mybool = false;
996
997 $file = getDolGlobalString('RECRUITMENT_RECRUITMENTCANDIDATURE_ADDON') . ".php";
998 $classname = getDolGlobalString('RECRUITMENT_RECRUITMENTCANDIDATURE_ADDON');
999
1000 // Include file with class
1001 $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
1002 foreach ($dirmodels as $reldir) {
1003 $dir = dol_buildpath($reldir."core/modules/recruitment/");
1004
1005 // Load file with numbering class (if found)
1006 $mybool = ((bool) @include_once $dir.$file) || $mybool;
1007 }
1008
1009 if (!$mybool) {
1010 dol_print_error(null, "Failed to include file ".$file);
1011 return '';
1012 }
1013
1014 if (class_exists($classname)) {
1015 $obj = new $classname();
1016 '@phan-var-force ModeleNumRefRecruitmentCandidature $obj';
1017 $numref = $obj->getNextValue($this);
1018
1019 if ($numref != '' && $numref != '-1') {
1020 return $numref;
1021 } else {
1022 $this->error = $obj->error;
1023 //dol_print_error($this->db,get_class($this)."::getNextNumRef ".$obj->error);
1024 return "";
1025 }
1026 } else {
1027 print $langs->trans("Error")." ".$langs->trans("ClassNotFound").' '.$classname;
1028 return "";
1029 }
1030 } else {
1031 print $langs->trans("ErrorNumberingModuleNotSetup", $this->element);
1032 return "";
1033 }
1034 }
1035
1047 public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams = null)
1048 {
1049 global $conf, $langs;
1050
1051 $result = 0;
1052 $includedocgeneration = 0;
1053
1054 $langs->load("recruitment@recruitment");
1055
1056 if (!dol_strlen($modele)) {
1057 if (getDolGlobalString('RECRUITMENTCANDIDATURE_ADDON_PDF')) {
1058 $modele = getDolGlobalString('RECRUITMENTCANDIDATURE_ADDON_PDF');
1059 } else {
1060 $modele = ''; // No default value. For job application, we allow to disable all PDF generation
1061 }
1062 }
1063
1064 $modelpath = "core/modules/recruitment/doc/";
1065
1066 if ($includedocgeneration && !empty($modele)) {
1067 $result = $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
1068 }
1069
1070 return $result;
1071 }
1072
1080 public function doScheduledJob()
1081 {
1082 global $conf, $langs;
1083
1084 //$conf->global->SYSLOG_FILE = 'DOL_DATA_ROOT/dolibarr_mydedicatedlofile.log';
1085
1086 $error = 0;
1087 $this->output = '';
1088 $this->error = '';
1089
1090 dol_syslog(__METHOD__, LOG_DEBUG);
1091
1092 $now = dol_now();
1093
1094 $this->db->begin();
1095
1096 // ...
1097
1098 $this->db->commit();
1099
1100 return $error;
1101 }
1102
1110 public function getKanbanView($option = '', $arraydata = null)
1111 {
1112 global $mysoc;
1113
1114 $selected = (empty($arraydata['selected']) ? 0 : $arraydata['selected']);
1115
1116 $return = '<div class="box-flex-item box-flex-grow-zero">';
1117 $return .= '<div class="info-box info-box-sm">';
1118 $return .= '<span class="info-box-icon bg-infobox-action">';
1119 $return .= img_picto('', $this->picto);
1120 $return .= '</span>';
1121 $return .= '<div class="info-box-content">';
1122 $return .= '<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">'.(method_exists($this, 'getNomUrl') ? $this->getNomUrl(1) : $this->ref).'</span>';
1123 if ($selected >= 0) {
1124 $return .= '<input id="cb'.$this->id.'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->id.'"'.($selected ? ' checked="checked"' : '').'>';
1125 }
1126 if (property_exists($this, 'fk_recruitmentjobposition')) {
1127 $return .= '<br>';
1128 //$return .= '<span class="opacitymedium">';
1129 //$return .= $langs->trans('Job').'</span> : ';
1130 $return .= '<div class="info-box-label tdoverflowmax150">';
1131 $tmpjob = new RecruitmentJobPosition($this->db);
1132 $tmpjob->fetch($this->fk_recruitmentjobposition);
1133 //$return .= $this->fk_recruitmentjobposition;
1134 $return .= dolPrintHTML($tmpjob->label);
1135 $return .= '</div>';
1136 }
1137 if (property_exists($this, 'phone') && $this->phone) {
1138 $return .= '<div class="info-box-label small">'.dol_print_phone($this->phone, $mysoc->country_code, 0, 0, 'AC_TEL', '&nbsp;', 'phone').'</div>';
1139 }
1140 if (property_exists($this, 'email') && $this->email) {
1141 $return .= '<div class="info-box-label small">'.dol_print_email($this->email, 0, 0, 1, 64, 1, 1).'</div>';
1142 }
1143 if (method_exists($this, 'getLibStatut')) {
1144 $return .= '<div class="info-box-status">'.$this->getLibStatut(3).'</div>';
1145 }
1146 $return .= '</div>';
1147 $return .= '</div>';
1148 $return .= '</div>';
1149 return $return;
1150 }
1151}
1152
1153
1154require_once DOL_DOCUMENT_ROOT.'/core/class/commonobjectline.class.php';
1155
1160{
1161 // To complete with content of an object RecruitmentCandidatureLine
1162 // We should have a field rowid, fk_recruitmentcandidature and position
1163
1169 public function __construct(DoliDB $db)
1170 {
1171 $this->db = $db;
1172 }
1173}
if( $user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
Definition card.php:67
$object ref
Definition info.php:90
Parent class of all other business classes (invoices, contracts, proposals, orders,...
deleteLineCommon(User $user, $idline, $notrigger=0)
Delete a line of object in database.
commonGenerateDocument($modelspath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams=null)
Common function for all objects extending CommonObject for generating documents.
createCommon(User $user, $notrigger=0)
Create object in the database.
getFieldList($alias='', $excludefields=array())
Function to concat keys of fields.
updateCommon(User $user, $notrigger=0)
Update object into database.
setStatusCommon($user, $status, $notrigger=0, $triggercode='')
Set to a status.
initAsSpecimenCommon()
Initialise object with example values Id must be 0 if object instance is a specimen.
copy_linked_contact($objFrom, $source='internal')
Copy contact from one element to current.
fetchLinesCommon($morewhere='', $noextrafields=0)
Load object in memory from the database.
fetchCommon($id, $ref=null, $morewhere='', $noextrafields=0)
Load object in memory from the database.
deleteCommon(User $user, $notrigger=0, $forcechilddeletion=0)
Delete object in database.
call_trigger($triggerName, $user)
Call trigger based on this instance.
Parent class for class inheritance lines of business objects This class is useless for the moment so ...
Class to manage Dolibarr database access.
Class for RecruitmentCandidature.
getLinesArray()
Create an array of lines.
createFromClone(User $user, $fromid)
Clone an object into another one.
cancel($user, $notrigger=0)
Set cancel status.
doScheduledJob()
Action executed by scheduler CAN BE A CRON TASK.
getKanbanView($option='', $arraydata=null)
Return clickable link of object (with eventually picto)
getNomUrl($withpicto=0, $option='', $notooltip=0, $morecss='', $save_lastsearch_value=-1)
Return a link to the object card (with optionally the picto)
getNextNumRef()
Returns the reference to the following non used object depending on the active numbering module.
reopen($user, $notrigger=0)
Set back to validated status.
initAsSpecimen()
Initialise object with example values Id must be 0 if object instance is a specimen.
getLibStatut($mode=0)
Return label of the status.
fetch($id, $ref=null, $email_msgid='')
Load object in memory from the database.
fetchLines()
Load object lines in memory from the database.
generateDocument($modele, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0, $moreparams=null)
Create a document onto disk according to template module.
update(User $user, $notrigger=0)
Update object into database.
validate($user, $notrigger=0)
Validate object.
deleteLine(User $user, $idline, $notrigger=0)
Delete a line of object in database.
LibStatut($status, $mode=0)
Return the status.
fetchAll($sortorder='', $sortfield='', $limit=0, $offset=0, $filter='', $filtermode='AND')
Load list of objects in memory from the database.
getFullName($langs, $option=0, $nameorder=-1, $maxlen=0)
Return full name ('name+' '+lastname)
setDraft($user, $notrigger=0)
Set draft status.
create(User $user, $notrigger=0)
Create object into database.
info($id)
Load the info information in the object.
Class RecruitmentCandidatureLine.
Class for RecruitmentJobPosition.
Class to manage Dolibarr users.
print $langs trans("Ref").' m titre as m m statut as status
Or an array listing all the potential status of the object: array: int of the status => translated la...
Definition index.php:171
print $script_file $mode $langs defaultlang(is_numeric($duration_value) ? " delay=". $duration_value :"").(is_numeric($duration_value2) ? " after cd cd cd description as p label as s rowid as s nom as s email
Sender: Who sends the email ("Sender" has sent emails on behalf of "From").
dol_dir_list($utf8_path, $types="all", $recursive=0, $filter="", $excludefilter=null, $sortcriteria="name", $sortorder=SORT_ASC, $mode=0, $nohook=0, $relativename="", $donotfollowsymlinks=0, $nbsecondsold=0)
Scan a directory and return a list of files/directories.
Definition files.lib.php:63
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2, $allowothertags=array())
Show picto whatever it's its name (generic function)
dolPrintHTML($s, $allowiframe=0)
Return a string (that can be on several lines) ready to be output on a HTML page.
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $allowothertags=array())
Show a picto called object_picto (generic function)
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
forgeSQLFromUniversalSearchCriteria($filter, &$errorstr='', $noand=0, $nopar=0, $noerror=0)
forgeSQLFromUniversalSearchCriteria
dol_now($mode='auto')
Return date for now.
dolGetFirstLastname($firstname, $lastname, $nameorder=-1)
Return firstname and lastname in correct order.
dolGetStatus($statusLabel='', $statusLabelShort='', $html='', $statusType='status0', $displayMode=0, $url='', $params=array())
Output the badge of a status.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
dol_trunc($string, $size=40, $trunc='right', $stringencoding='UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding '…' if string larger than length.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1, $includequotes=0)
Clean a string to use it as a file name.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
global $conf
The following vars must be defined: $type2label $form $conf, $lang, The following vars may also be de...
Definition member.php:79
$conf db name
Only used if Module[ID]Name translation string is not found.
Definition repair.php:161