dolibarr 23.0.3
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 );
130
134 public $rowid;
135
139 public $ref;
143 public $fk_recruitmentjobposition;
147 public $description;
151 public $fk_user_creat;
155 public $fk_user_modif;
159 public $fk_user;
163 public $lastname;
167 public $firstname;
171 public $email;
175 public $phone;
179 public $date_birth;
183 public $email_msgid;
187 public $email_date;
191 public $remuneration_requested;
195 public $remuneration_proposed;
199 public $fk_recruitment_origin;
203 public $import_key;
207 public $model_pdf;
211 public $status;
215 public $ip;
216 // END MODULEBUILDER PROPERTIES
217
223 public function __construct(DoliDB $db)
224 {
225 global $langs;
226
227 $this->db = $db;
228
229 $this->ismultientitymanaged = 1;
230 $this->isextrafieldmanaged = 1;
231
232 if (!getDolGlobalString('MAIN_SHOW_TECHNICAL_ID') && isset($this->fields['rowid'])) {
233 $this->fields['rowid']['visible'] = 0;
234 }
235 if (!isModEnabled('multicompany') && isset($this->fields['entity'])) {
236 $this->fields['entity']['enabled'] = 0;
237 }
238
239 // Example to show how to set values of fields definition dynamically
240 /*if ($user->rights->recruitment->recruitmentcandidature->read) {
241 $this->fields['myfield']['visible'] = 1;
242 $this->fields['myfield']['noteditable'] = 0;
243 }*/
244
245 // Unset fields that are disabled
246 foreach ($this->fields as $key => $val) {
247 if (isset($val['enabled']) && empty($val['enabled'])) {
248 unset($this->fields[$key]);
249 }
250 }
251
252 // Translate some data of arrayofkeyval
253 if (is_object($langs)) {
254 foreach ($this->fields as $key => $val) {
255 if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) {
256 foreach ($val['arrayofkeyval'] as $key2 => $val2) {
257 $this->fields[$key]['arrayofkeyval'][$key2] = $langs->trans($val2);
258 }
259 }
260 }
261 }
262 }
263
271 public function create(User $user, $notrigger = 0)
272 {
273 return $this->createCommon($user, $notrigger);
274 }
275
283 public function createFromClone(User $user, $fromid)
284 {
285 global $langs, $extrafields;
286 $error = 0;
287
288 dol_syslog(__METHOD__, LOG_DEBUG);
289
290 $object = new self($this->db);
291
292 $this->db->begin();
293
294 // Load source object
295 $result = $object->fetchCommon($fromid);
296 if ($result > 0 && !empty($object->table_element_line)) {
297 $object->fetchLines();
298 }
299
300 // get lines so they will be clone
301 //foreach($this->lines as $line)
302 // $line->fetch_optionals();
303
304 // Reset some properties
305 unset($object->id);
306 unset($object->fk_user_creat);
307 unset($object->import_key);
308
309 // Clear fields
310 if (property_exists($object, 'ref')) {
311 // @phan-suppress-next-line PhanTypeMismatchProperty
312 $object->ref = empty($this->fields['ref']['default']) ? "Copy_Of_".$object->ref : $this->fields['ref']['default'];
313 }
314
315 $object->status = self::STATUS_DRAFT;
316 $object->date_creation = dol_now();
317 $object->date_modification = null;
318
319 // Clear extrafields that are unique
320 if (is_array($object->array_options) && count($object->array_options) > 0) {
321 $extrafields->fetch_name_optionals_label($this->table_element);
322 foreach ($object->array_options as $key => $option) {
323 $shortkey = preg_replace('/options_/', '', $key);
324 if (!empty($extrafields->attributes[$this->table_element]['unique'][$shortkey])) {
325 unset($object->array_options[$key]);
326 }
327 }
328 }
329
330 // Create clone
331 $object->context['createfromclone'] = 'createfromclone';
332 $result = $object->createCommon($user);
333 if ($result < 0) {
334 $error++;
336 }
337
338 if (!$error) {
339 // copy internal contacts
340 if ($this->copy_linked_contact($object, 'internal') < 0) {
341 $error++;
342 }
343 }
344
345 if (!$error) {
346 // copy external contacts if same company
347 if (property_exists($this, 'socid') && $this->socid == $object->socid) {
348 if ($this->copy_linked_contact($object, 'external') < 0) {
349 $error++;
350 }
351 }
352 }
353
354 unset($object->context['createfromclone']);
355
356 // End
357 if (!$error) {
358 $this->db->commit();
359 return $object;
360 } else {
361 $this->db->rollback();
362 return -1;
363 }
364 }
365
374 public function fetch($id, $ref = null, $email_msgid = '')
375 {
376 $morewhere = '';
377 if ($email_msgid) {
378 $morewhere = " AND email_msgid = '".$this->db->escape($email_msgid)."'";
379 }
380 $result = $this->fetchCommon($id, $ref, $morewhere);
381 if ($result > 0 && !empty($this->table_element_line)) {
382 $this->fetchLines();
383 }
384 return $result;
385 }
386
392 public function fetchLines()
393 {
394 $this->lines = array();
395
396 $result = $this->fetchLinesCommon();
397 return $result;
398 }
399
400
413 public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, $filter = '', $filtermode = 'AND')
414 {
415 dol_syslog(__METHOD__, LOG_DEBUG);
416
417 $records = array();
418
419 $sql = 'SELECT ';
420 $sql .= $this->getFieldList();
421 $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t';
422 if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) {
423 $sql .= ' WHERE t.entity IN ('.getEntity($this->element).')';
424 } else {
425 $sql .= ' WHERE 1 = 1';
426 }
427
428 // Manage filter
429 $errormessage = '';
430 $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage);
431 if ($errormessage) {
432 $this->errors[] = $errormessage;
433 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
434 return -1;
435 }
436
437 if (!empty($sortfield)) {
438 $sql .= $this->db->order($sortfield, $sortorder);
439 }
440 if (!empty($limit)) {
441 $sql .= $this->db->plimit($limit, $offset);
442 }
443
444 $resql = $this->db->query($sql);
445 if ($resql) {
446 $num = $this->db->num_rows($resql);
447 $i = 0;
448 while ($i < ($limit ? min($limit, $num) : $num)) {
449 $obj = $this->db->fetch_object($resql);
450
451 $record = new self($this->db);
452 $record->setVarsFromFetchObj($obj);
453
454 $records[$record->id] = $record;
455
456 $i++;
457 }
458 $this->db->free($resql);
459
460 return $records;
461 } else {
462 $this->errors[] = 'Error '.$this->db->lasterror();
463 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
464
465 return -1;
466 }
467 }
468
476 public function update(User $user, $notrigger = 0)
477 {
478 return $this->updateCommon($user, $notrigger);
479 }
480
488 public function delete(User $user, $notrigger = 0)
489 {
490 return $this->deleteCommon($user, $notrigger);
491 //return $this->deleteCommon($user, $notrigger, 1);
492 }
493
502 public function deleteLine(User $user, $idline, $notrigger = 0)
503 {
504 if ($this->status < 0) {
505 $this->error = 'ErrorDeleteLineNotAllowedByObjectStatus';
506 return -2;
507 }
508
509 return $this->deleteLineCommon($user, $idline, $notrigger);
510 }
511
512
520 public function validate($user, $notrigger = 0)
521 {
522 global $conf, $langs;
523
524 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
525
526 $error = 0;
527
528 // Protection
529 if ($this->status == self::STATUS_VALIDATED) {
530 dol_syslog(get_class($this)."::validate action abandoned: already validated", LOG_WARNING);
531 return 0;
532 }
533
534 /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->recruitment->recruitmentcandidature->write))
535 || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->recruitment->recruitmentcandidature->recruitmentcandidature_advance->validate))))
536 {
537 $this->error='NotEnoughPermissions';
538 dol_syslog(get_class($this)."::valid ".$this->error, LOG_ERR);
539 return -1;
540 }*/
541
542 $now = dol_now();
543
544 $this->db->begin();
545
546 // Define new ref
547 if (/* !$error && */ (preg_match('/^[\‍(]?PROV/i', $this->ref) || empty($this->ref))) { // empty should not happened, but when it occurs, the test save life
548 $num = $this->getNextNumRef();
549 } else {
550 $num = (string) $this->ref;
551 }
552 $this->newref = $num;
553
554 if (!empty($num)) {
555 // Validate
556 $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element;
557 $sql .= " SET ref = '".$this->db->escape($num)."',";
558 $sql .= " status = ".self::STATUS_VALIDATED;
559 if (!empty($this->fields['date_validation'])) {
560 $sql .= ", date_validation = '".$this->db->idate($now)."',";
561 }
562 if (!empty($this->fields['fk_user_valid'])) { // @phan-suppress-current-line PhanTypeMismatchProperty
563 $sql .= ", fk_user_valid = ".((int) $user->id);
564 }
565 $sql .= " WHERE rowid = ".((int) $this->id);
566
567 dol_syslog(get_class($this)."::validate()", LOG_DEBUG);
568 $resql = $this->db->query($sql);
569 if (!$resql) {
570 dol_print_error($this->db);
571 $this->error = $this->db->lasterror();
572 $error++;
573 }
574
575 if (!$error && !$notrigger) {
576 // Call trigger
577 $result = $this->call_trigger('RECRUITMENTCANDIDATURE_VALIDATE', $user);
578 if ($result < 0) {
579 $error++;
580 }
581 // End call triggers
582 }
583 }
584
585 if (!$error) {
586 $this->oldref = $this->ref;
587
588 // Rename directory if dir was a temporary ref
589 if (preg_match('/^[\‍(]?PROV/i', $this->ref)) {
590 // Now we rename also files into index
591 $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)."'";
592 $sql .= " WHERE filename LIKE '".$this->db->escape($this->ref)."%' AND filepath = 'recruitmentcandidature/".$this->db->escape($this->ref)."' and entity = ".$conf->entity;
593 $resql = $this->db->query($sql);
594 if (!$resql) {
595 $error++;
596 $this->error = $this->db->lasterror();
597 }
598 $sql = 'UPDATE '.MAIN_DB_PREFIX."ecm_files set filepath = 'recruitmentcandidature/".$this->db->escape($this->newref)."'";
599 $sql .= " WHERE filepath = 'recruitmentcandidature/".$this->db->escape($this->ref)."' and entity = ".$conf->entity;
600 $resql = $this->db->query($sql);
601 if (!$resql) {
602 $error++;
603 $this->error = $this->db->lasterror();
604 }
605
606 // We rename directory ($this->ref = old ref, $num = new ref) in order not to lose the attachments
607 $oldref = dol_sanitizeFileName($this->ref);
608 $newref = dol_sanitizeFileName($num);
609 $dirsource = $conf->recruitment->dir_output.'/recruitmentcandidature/'.$oldref;
610 $dirdest = $conf->recruitment->dir_output.'/recruitmentcandidature/'.$newref;
611 if (!$error && file_exists($dirsource)) {
612 dol_syslog(get_class($this)."::validate() rename dir ".$dirsource." into ".$dirdest);
613
614 if (@rename($dirsource, $dirdest)) {
615 dol_syslog("Rename ok");
616 // Rename docs starting with $oldref with $newref
617 $listoffiles = dol_dir_list($conf->recruitment->dir_output.'/recruitmentcandidature/'.$newref, 'files', 1, '^'.preg_quote($oldref, '/'));
618 foreach ($listoffiles as $fileentry) {
619 $dirsource = $fileentry['name'];
620 $dirdest = preg_replace('/^'.preg_quote($oldref, '/').'/', $newref, $dirsource);
621 $dirsource = $fileentry['path'].'/'.$dirsource;
622 $dirdest = $fileentry['path'].'/'.$dirdest;
623 @rename($dirsource, $dirdest);
624 }
625 }
626 }
627 }
628 }
629
630 // Set new ref and current status
631 if (!$error) {
632 $this->ref = $num;
633 $this->status = self::STATUS_VALIDATED;
634 }
635
636 if (!$error) {
637 $this->db->commit();
638 return 1;
639 } else {
640 $this->db->rollback();
641 return -1;
642 }
643 }
644
645
653 public function setDraft($user, $notrigger = 0)
654 {
655 // Protection
656 if ($this->status <= self::STATUS_DRAFT) {
657 return 0;
658 }
659
660 /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->recruitment->write))
661 || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->recruitment->recruitment_advance->validate))))
662 {
663 $this->error='Permission denied';
664 return -1;
665 }*/
666
667 return $this->setStatusCommon($user, self::STATUS_DRAFT, $notrigger, 'RECRUITMENTCANDIDATURE_UNVALIDATE');
668 }
669
677 public function cancel($user, $notrigger = 0)
678 {
679 // Protection
680 if ($this->status != self::STATUS_VALIDATED) {
681 return 0;
682 }
683
684 /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->recruitment->write))
685 || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->recruitment->recruitment_advance->validate))))
686 {
687 $this->error='Permission denied';
688 return -1;
689 }*/
690
691 return $this->setStatusCommon($user, self::STATUS_CANCELED, $notrigger, 'RECRUITMENTCANDIDATURE_CLOSE');
692 }
693
701 public function reopen($user, $notrigger = 0)
702 {
703 // Protection
704 if ($this->status != self::STATUS_REFUSED && $this->status != self::STATUS_CANCELED && $this->status != self::STATUS_CONTRACT_REFUSED) {
705 return 0;
706 }
707
708 /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->recruitment->write))
709 || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->recruitment->recruitment_advance->validate))))
710 {
711 $this->error='Permission denied';
712 return -1;
713 }*/
714
715 return $this->setStatusCommon($user, self::STATUS_VALIDATED, $notrigger, 'RECRUITMENTCANDIDATURE_REOPEN');
716 }
717
727 public function getFullName($langs, $option = 0, $nameorder = -1, $maxlen = 0)
728 {
729 $lastname = $this->lastname;
730 $firstname = $this->firstname;
731 if (empty($lastname)) {
732 $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 : '')))));
733 }
734
735 $ret = '';
736
737 $ret .= dolGetFirstLastname((string) $firstname, (string) $lastname, $nameorder);
738
739 return dol_trunc($ret, $maxlen);
740 }
741
749 public function getTooltipContentArray($params)
750 {
751 global $langs;
752
753 $langs->load('recruitment');
754
755 $datas = [];
756
757 if (getDolGlobalInt('MAIN_OPTIMIZEFORTEXTBROWSER')) {
758 return ['optimize' => $langs->trans("ShowRecruitmentCandidature")];
759 }
760 $datas['picto'] = img_picto('', $this->picto) . ' <u class="paddingrightonly">' . $langs->trans("RecruitmentCandidature") . '</u>';
761 if (isset($this->status)) {
762 $datas['picto'] .= ' ' . $this->getLibStatut(5);
763 }
764 if (!empty($this->ref)) {
765 $datas['ref'] = '<br><b>' . $langs->trans('Ref') . ':</b> ' . $this->ref;
766 }
767 if (!empty($this->email)) {
768 $datas['email'] = '<br>' . $langs->trans('Email') . ':</b> ' . $this->email;
769 }
770 $datas['name'] = '<br>' . $langs->trans('Email') . ':</b> ' . $this->getFullName($langs);
771
772 return $datas;
773 }
774
785 public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
786 {
787 global $conf, $langs, $hookmanager;
788
789 if (!empty($conf->dol_no_mouse_hover)) {
790 $notooltip = 1; // Force disable tooltips
791 }
792
793 $result = '';
794 $params = [
795 'id' => (string) $this->id,
796 'objecttype' => $this->element.($this->module ? '@'.$this->module : ''),
797 'option' => $option,
798 ];
799 $classfortooltip = 'classfortooltip';
800 $dataparams = '';
801 if (getDolGlobalInt('MAIN_ENABLE_AJAX_TOOLTIP')) {
802 $classfortooltip = 'classforajaxtooltip';
803 $dataparams = ' data-params="'.dol_escape_htmltag(json_encode($params)).'"';
804 $label = '';
805 } else {
806 $label = implode($this->getTooltipContentArray($params));
807 }
808
809 $baseurl = DOL_URL_ROOT . '/recruitment/recruitmentcandidature_card.php';
810 $query = ['id' => $this->id];
811 if ($option !== 'nolink') {
812 // Add param to save lastsearch_values or not
813 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
814 if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
815 $add_save_lastsearch_values = 1;
816 }
817 if ($add_save_lastsearch_values) {
818 $query += ['save_lastsearch_values' => 1];
819 }
820 }
821 $url = dolBuildUrl($baseurl, $query);
822
823 $linkclose = '';
824 if (empty($notooltip)) {
825 if (getDolGlobalInt('MAIN_OPTIMIZEFORTEXTBROWSER')) {
826 $label = $langs->trans("ShowRecruitmentCandidature");
827 $linkclose .= ' alt="'.dolPrintHTMLForAttribute($label).'"';
828 }
829 $linkclose .= ($label ? ' title="'.dolPrintHTMLForAttribute($label).'"' : ' title="tocomplete"');
830 $linkclose .= $dataparams.' class="'.$classfortooltip.($morecss ? ' '.$morecss : '').'"';
831 } else {
832 $linkclose = ($morecss ? ' class="'.$morecss.'"' : '');
833 }
834
835 $linkstart = '<a href="'.$url.'"';
836 $linkstart .= $linkclose.'>';
837 $linkend = '</a>';
838
839 $result .= $linkstart;
840
841 if (empty($this->showphoto_on_popup)) {
842 if ($withpicto) {
843 $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);
844 }
845 } else {
846 if ($withpicto) {
847 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
848
849 list($class, $module) = explode('@', $this->picto);
850 $upload_dir = $conf->$module->multidir_output[$conf->entity]."/$class/".dol_sanitizeFileName($this->ref);
851 $filearray = dol_dir_list($upload_dir, "files");
852 $filename = $filearray[0]['name'];
853 if (!empty($filename)) {
854 $pospoint = strpos($filearray[0]['name'], '.');
855
856 $pathtophoto = $class.'/'.$this->ref.'/thumbs/'.substr($filename, 0, $pospoint).'_mini'.substr($filename, $pospoint);
857 if (!getDolGlobalString(strtoupper($module.'_'.$class).'_FORMATLISTPHOTOSASUSERS')) {
858 $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>';
859 } else {
860 $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>';
861 }
862
863 $result .= '</div>';
864 } else {
865 $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);
866 }
867 }
868 }
869
870 if ($withpicto != 2) {
871 $result .= $this->ref;
872 }
873
874 $result .= $linkend;
875 //if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : '');
876
877 global $action, $hookmanager;
878 $hookmanager->initHooks(array('recruitmentcandidaturedao'));
879 $parameters = array('id' => $this->id, 'getnomurl' => &$result);
880 $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
881 if ($reshook > 0) {
882 $result = $hookmanager->resPrint;
883 } else {
884 $result .= $hookmanager->resPrint;
885 }
886
887 return $result;
888 }
889
896 public function getLibStatut($mode = 0)
897 {
898 return $this->LibStatut($this->status, $mode);
899 }
900
901 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
909 public function LibStatut($status, $mode = 0)
910 {
911 // phpcs:enable
912 if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
913 global $langs;
914 //$langs->load("recruitment@recruitment");
915 $this->labelStatus[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft');
916 $this->labelStatus[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Received').' ('.$langs->transnoentitiesnoconv("InterviewToDo").')';
917 $this->labelStatus[self::STATUS_CONTRACT_PROPOSED] = $langs->transnoentitiesnoconv('ContractProposed');
918 $this->labelStatus[self::STATUS_CONTRACT_SIGNED] = $langs->transnoentitiesnoconv('ContractSigned');
919 $this->labelStatus[self::STATUS_CONTRACT_REFUSED] = $langs->transnoentitiesnoconv('ContractRefused');
920 $this->labelStatus[self::STATUS_REFUSED] = $langs->transnoentitiesnoconv('Refused');
921 $this->labelStatus[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('Canceled');
922 $this->labelStatusShort[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft');
923 $this->labelStatusShort[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Received');
924 $this->labelStatusShort[self::STATUS_CONTRACT_PROPOSED] = $langs->transnoentitiesnoconv('ContractProposed');
925 $this->labelStatusShort[self::STATUS_CONTRACT_SIGNED] = $langs->transnoentitiesnoconv('ContractSigned');
926 $this->labelStatusShort[self::STATUS_CONTRACT_REFUSED] = $langs->transnoentitiesnoconv('ContractRefused');
927 $this->labelStatusShort[self::STATUS_REFUSED] = $langs->transnoentitiesnoconv('Refused');
928 $this->labelStatusShort[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('Canceled');
929 }
930
931 $statusType = 'status'.$status;
932 //if ($status == self::STATUS_VALIDATED) $statusType = 'status1';
933 if ($status == self::STATUS_CANCELED) {
934 $statusType = 'status9';
935 }
936 if ($status == self::STATUS_CONTRACT_PROPOSED) {
937 $statusType = 'status4';
938 }
939 if ($status == self::STATUS_CONTRACT_SIGNED) {
940 $statusType = 'status6';
941 }
942 if ($status == self::STATUS_REFUSED) {
943 $statusType = 'status10';
944 }
945
946 return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode);
947 }
948
955 public function info($id)
956 {
957 $sql = 'SELECT rowid, date_creation as datec, tms as datem,';
958 $sql .= ' fk_user_creat, fk_user_modif';
959 $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t';
960 $sql .= ' WHERE t.rowid = '.((int) $id);
961 $result = $this->db->query($sql);
962 if ($result) {
963 if ($this->db->num_rows($result)) {
964 $obj = $this->db->fetch_object($result);
965
966 $this->id = $obj->rowid;
967
968 $this->user_creation_id = $obj->fk_user_creat;
969 $this->user_modification_id = $obj->fk_user_modif;
970 $this->date_creation = $this->db->jdate($obj->datec);
971 $this->date_modification = empty($obj->datem) ? '' : $this->db->jdate($obj->datem);
972 }
973
974 $this->db->free($result);
975 } else {
976 dol_print_error($this->db);
977 }
978 }
979
986 public function initAsSpecimen()
987 {
988 return $this->initAsSpecimenCommon();
989 }
990
996 public function getLinesArray()
997 {
998 $this->lines = array();
999
1000 $objectline = new RecruitmentCandidatureLine($this->db);
1001 $result = $objectline->fetchAll('ASC', 'position', 0, 0, '(fk_recruitmentcandidature:=:'.((int) $this->id).')');
1002
1003 if (is_numeric($result)) {
1004 $this->setErrorsFromObject($objectline);
1005 return $result;
1006 } else {
1007 $this->lines = $result;
1008 // @phpstan-ignore-next-line
1009 return $result; // @phan-suppress-current-line PhanTypeMismatchReturn
1010 }
1011 }
1012
1018 public function getNextNumRef()
1019 {
1020 global $langs, $conf;
1021 $langs->load("recruitment@recruitment");
1022
1023 if (!getDolGlobalString('RECRUITMENT_RECRUITMENTCANDIDATURE_ADDON')) {
1024 $conf->global->RECRUITMENT_RECRUITMENTCANDIDATURE_ADDON = 'mod_recruitmentcandidature_standard';
1025 }
1026
1027 if (getDolGlobalString('RECRUITMENT_RECRUITMENTCANDIDATURE_ADDON')) {
1028 $mybool = false;
1029
1030 $file = getDolGlobalString('RECRUITMENT_RECRUITMENTCANDIDATURE_ADDON') . ".php";
1031 $classname = getDolGlobalString('RECRUITMENT_RECRUITMENTCANDIDATURE_ADDON');
1032
1033 // Include file with class
1034 $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
1035 foreach ($dirmodels as $reldir) {
1036 $dir = dol_buildpath($reldir."core/modules/recruitment/");
1037
1038 // Load file with numbering class (if found)
1039 $mybool = ((bool) @include_once $dir.$file) || $mybool;
1040 }
1041
1042 if (!$mybool) {
1043 dol_print_error(null, "Failed to include file ".$file);
1044 return '';
1045 }
1046
1047 if (class_exists($classname)) {
1048 $obj = new $classname();
1049 '@phan-var-force ModeleNumRefRecruitmentCandidature $obj';
1051 $numref = $obj->getNextValue($this);
1052
1053 if ($numref != '' && $numref != '-1') {
1054 return $numref;
1055 } else {
1056 $this->error = $obj->error;
1057 //dol_print_error($this->db,get_class($this)."::getNextNumRef ".$obj->error);
1058 return "";
1059 }
1060 } else {
1061 print $langs->trans("Error")." ".$langs->trans("ClassNotFound").' '.$classname;
1062 return "";
1063 }
1064 } else {
1065 print $langs->trans("ErrorNumberingModuleNotSetup", $this->element);
1066 return "";
1067 }
1068 }
1069
1081 public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams = null)
1082 {
1083 global $conf, $langs;
1084
1085 $result = 0;
1086 $includedocgeneration = 0;
1087
1088 $langs->load("recruitment@recruitment");
1089
1090 if (!dol_strlen($modele)) {
1091 if (getDolGlobalString('RECRUITMENTCANDIDATURE_ADDON_PDF')) {
1092 $modele = getDolGlobalString('RECRUITMENTCANDIDATURE_ADDON_PDF');
1093 } else {
1094 $modele = ''; // No default value. For job application, we allow to disable all PDF generation
1095 }
1096 }
1097
1098 $modelpath = "core/modules/recruitment/doc/";
1099
1100 if ($includedocgeneration && !empty($modele)) {
1101 $result = $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
1102 }
1103
1104 return $result;
1105 }
1106
1114 public function doScheduledJob()
1115 {
1116 global $conf, $langs;
1117
1118 //$conf->global->SYSLOG_FILE = 'DOL_DATA_ROOT/dolibarr_mydedicatedlofile.log';
1119
1120 $error = 0;
1121 $this->output = '';
1122 $this->error = '';
1123
1124 dol_syslog(__METHOD__, LOG_DEBUG);
1125
1126 $now = dol_now();
1127
1128 $this->db->begin();
1129
1130 // ...
1131
1132 $this->db->commit();
1133
1134 return $error;
1135 }
1136
1144 public function getKanbanView($option = '', $arraydata = null)
1145 {
1146 global $mysoc;
1147
1148 $selected = (empty($arraydata['selected']) ? 0 : $arraydata['selected']);
1149
1150 $return = '<div class="box-flex-item box-flex-grow-zero">';
1151 $return .= '<div class="info-box info-box-sm">';
1152 $return .= '<span class="info-box-icon bg-infobox-action">';
1153 $return .= img_picto('', $this->picto);
1154 $return .= '</span>';
1155 $return .= '<div class="info-box-content">';
1156 $return .= '<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">'.(method_exists($this, 'getNomUrl') ? $this->getNomUrl(1) : $this->ref).'</span>';
1157 if ($selected >= 0) {
1158 $return .= '<input id="cb'.$this->id.'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->id.'"'.($selected ? ' checked="checked"' : '').'>';
1159 }
1160 if (property_exists($this, 'fk_recruitmentjobposition')) {
1161 $return .= '<br>';
1162 //$return .= '<span class="opacitymedium">';
1163 //$return .= $langs->trans('Job').'</span> : ';
1164 $return .= '<div class="info-box-label tdoverflowmax150">';
1165 $tmpjob = new RecruitmentJobPosition($this->db);
1166 $tmpjob->fetch($this->fk_recruitmentjobposition);
1167 //$return .= $this->fk_recruitmentjobposition;
1168 $return .= dolPrintHTML($tmpjob->label);
1169 $return .= '</div>';
1170 }
1171 if (property_exists($this, 'phone') && $this->phone) {
1172 $return .= '<div class="info-box-label small">'.dol_print_phone($this->phone, $mysoc->country_code, 0, 0, 'AC_TEL', '&nbsp;', 'phone').'</div>';
1173 }
1174 if (property_exists($this, 'email') && $this->email) {
1175 $return .= '<div class="info-box-label small">'.dol_print_email($this->email, 0, 0, 1, 64, 1, 1).'</div>';
1176 }
1177 if (method_exists($this, 'getLibStatut')) {
1178 $return .= '<div class="info-box-status">'.$this->getLibStatut(3).'</div>';
1179 }
1180 $return .= '</div>';
1181 $return .= '</div>';
1182 $return .= '</div>';
1183 return $return;
1184 }
1185}
1186
1187
1188require_once DOL_DOCUMENT_ROOT.'/core/class/commonobjectline.class.php';
1189
1194{
1195 // To complete with content of an object RecruitmentCandidatureLine
1196 // We should have a field rowid, fk_recruitmentcandidature and position
1197
1203 public function __construct(DoliDB $db)
1204 {
1205 $this->db = $db;
1206 }
1207}
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
$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.
setErrorsFromObject($object)
setErrorsFromObject
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.
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)
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.
getTooltipContentArray($params)
getTooltipContentArray
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
global $mysoc
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:64
dol_now($mode='gmt')
Return date for now.
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)
dolBuildUrl($url, $params=[], $addtoken=false)
Return path of url.
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_sanitizeFileName($str, $newstr='_', $unaccent=1, $includequotes=0, $allowdash=0)
Clean a string to use it as a file name.
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
forgeSQLFromUniversalSearchCriteria($filter, &$errorstr='', $noand=0, $nopar=0, $noerror=0)
forgeSQLFromUniversalSearchCriteria
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
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.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
$conf db name
Only used if Module[ID]Name translation string is not found.
Definition repair.php:128