dolibarr 21.0.0-alpha
myobject.class.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2017 Laurent Destailleur <eldy@users.sourceforge.net>
3 * Copyright (C) 2023-2024 Frédéric France <frederic.france@free.fr>
4 * Copyright (C) ---Replace with your own copyright and developer email---
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';
28//require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php';
29//require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php';
30
35{
39 public $module = 'mymodule';
40
44 public $element = 'myobject';
45
49 public $table_element = 'mymodule_myobject';
50
54 //public $element_for_permission = 'mymodule';
55
59 public $picto = 'fa-file';
60
61
62 const STATUS_DRAFT = 0;
63 const STATUS_VALIDATED = 1;
64 const STATUS_CANCELED = 9;
65
107 // BEGIN MODULEBUILDER PROPERTIES
112 public $fields = array(
113 "rowid" => array("type" => "integer", "label" => "TechnicalID", "enabled" => 1, 'position' => 1, 'notnull' => 1, "visible" => 0, "noteditable" => 1, "index" => 1, "css" => "left", "comment" => "Id"),
114 "ref" => array("type" => "varchar(128)", "label" => "Ref", "enabled" => 1, 'position' => 20, 'notnull' => 1, "visible" => 1, "index" => 1, "searchall" => 1, "showoncombobox" => 1, "validate" => 1, "comment" => "Reference of object"),
115 "label" => array("type" => "varchar(255)", "label" => "Label", "enabled" => 1, 'position' => 30, 'notnull' => 0, "visible" => 1, "alwayseditable" => "1", "searchall" => 1, "css" => "minwidth300", "cssview" => "wordbreak", "help" => "Help text", "showoncombobox" => "2", "validate" => 1,),
116 "amount" => array("type" => "price", "label" => "Amount", "enabled" => 1, 'position' => 40, 'notnull' => 0, "visible" => 1, "default" => "null", "isameasure" => 1, "help" => "Help text for amount", "validate" => 1,),
117 "qty" => array("type" => "real", "label" => "Qty", "enabled" => 1, 'position' => 45, 'notnull' => 0, "visible" => 1, "default" => "0", "isameasure" => 1, "css" => "maxwidth75imp", "help" => "Help text for quantity", "validate" => 1,),
118 "fk_soc" => array("type" => "integer:Societe:societe/class/societe.class.php:1:((status:=:1) AND (entity:IN:__SHARED_ENTITIES__))", "label" => "ThirdParty", "picto" => "company", "enabled" => "isModEnabled('societe')", 'position' => 50, 'notnull' => -1, "visible" => 1, "index" => 1, "css" => "maxwidth500 widthcentpercentminusxx", "csslist" => "tdoverflowmax150", "help" => "OrganizationEventLinkToThirdParty", "validate" => 1,),
119 "fk_project" => array("type" => "integer:Project:projet/class/project.class.php:1", "label" => "Project", "picto" => "project", "enabled" => "isModEnabled('project')", 'position' => 52, 'notnull' => -1, "visible" => "-1", "index" => 1, "css" => "maxwidth500 widthcentpercentminusxx", "csslist" => "tdoverflowmax150", "validate" => 1,),
120 "description" => array("type" => "text", "label" => "Description", "enabled" => 1, 'position' => 60, 'notnull' => 0, "visible" => "3", "validate" => 1,),
121 "note_public" => array("type" => "html", "label" => "NotePublic", "enabled" => 1, 'position' => 61, 'notnull' => 0, "visible" => 0, "cssview" => "wordbreak", "validate" => 1,),
122 "note_private" => array("type" => "html", "label" => "NotePrivate", "enabled" => 1, 'position' => 62, 'notnull' => 0, "visible" => 0, "cssview" => "wordbreak", "validate" => 1,),
123 "date_creation" => array("type" => "datetime", "label" => "DateCreation", "enabled" => 1, 'position' => 500, 'notnull' => 1, "visible" => -2,),
124 "tms" => array("type" => "timestamp", "label" => "DateModification", "enabled" => 1, 'position' => 501, 'notnull' => 0, "visible" => -2,),
125 "fk_user_creat" => array("type" => "integer:User:user/class/user.class.php", "label" => "UserAuthor", "picto" => "user", "enabled" => 1, 'position' => 510, 'notnull' => 1, "visible" => -2, "foreignkey" => "0", "csslist" => "tdoverflowmax150",),
126 "fk_user_modif" => array("type" => "integer:User:user/class/user.class.php", "label" => "UserModif", "picto" => "user", "enabled" => 1, 'position' => 511, 'notnull' => -1, "visible" => -2, "csslist" => "tdoverflowmax150",),
127 "last_main_doc" => array("type" => "varchar(255)", "label" => "LastMainDoc", "enabled" => 1, 'position' => 600, 'notnull' => 0, "visible" => 0,),
128 "import_key" => array("type" => "varchar(14)", "label" => "ImportId", "enabled" => 1, 'position' => 1000, 'notnull' => -1, "visible" => -2,),
129 "model_pdf" => array("type" => "varchar(255)", "label" => "Model pdf", "enabled" => 1, 'position' => 1010, 'notnull' => -1, "visible" => 0,),
130 "status" => array("type" => "integer", "label" => "Status", "enabled" => 1, 'position' => 2000, 'notnull' => 1, "visible" => 1, "index" => 1, "arrayofkeyval" => array("0" => "Draft", "1" => "Validated", "9" => "Canceled"), "validate" => 1,),
131 );
132
136 public $rowid;
137
141 public $ref;
142
146 public $entity;
147
151 public $label;
152
156 public $amount;
157
161 public $socid; // both socid and fk_soc are used
165 public $fk_soc; // both socid and fk_soc are used
166
170 public $status;
171
175 public $fk_user_creat;
176
180 public $fk_user_modif;
181
185 public $last_main_doc;
186
190 public $import_key;
191 // END MODULEBUILDER PROPERTIES
192
193
194 // If this object has a subtable with lines
195
196 // /**
197 // * @var string Name of subtable line
198 // */
199 // public $table_element_line = 'mymodule_myobjectline';
200
201 // /**
202 // * @var string Field with ID of parent key if this object has a parent
203 // */
204 // public $fk_element = 'fk_myobject';
205
206 // /**
207 // * @var string Name of subtable class that manage subtable lines
208 // */
209 // public $class_element_line = 'MyObjectline';
210
211 // /**
212 // * @var array List of child tables. To test if we can delete object.
213 // */
214 // protected $childtables = array('mychildtable' => array('name'=>'MyObject', 'fk_element'=>'fk_myobject'));
215
216 // /**
217 // * @var array List of child tables. To know object to delete on cascade.
218 // * If name matches '@ClassNAme:FilePathClass;ParentFkFieldName' it will
219 // * call method deleteByParentField(parentId, ParentFkFieldName) to fetch and delete child object
220 // */
221 // protected $childtablesoncascade = array('mymodule_myobjectdet');
222
223 // /**
224 // * @var MyObjectLine[] Array of subtable lines
225 // */
226 // public $lines = array();
227
228
229
235 public function __construct(DoliDB $db)
236 {
237 global $langs;
238
239 $this->db = $db;
240 $this->ismultientitymanaged = 0;
241 $this->isextrafieldmanaged = 1;
242
243 if (!getDolGlobalInt('MAIN_SHOW_TECHNICAL_ID') && isset($this->fields['rowid']) && !empty($this->fields['ref'])) {
244 $this->fields['rowid']['visible'] = 0;
245 }
246 if (!isModEnabled('multicompany') && isset($this->fields['entity'])) {
247 $this->fields['entity']['enabled'] = 0;
248 }
249
250 // Example to show how to set values of fields definition dynamically
251 /*if ($user->hasRight('mymodule', 'myobject', 'read')) {
252 $this->fields['myfield']['visible'] = 1;
253 $this->fields['myfield']['noteditable'] = 0;
254 }*/
255
256 // Unset fields that are disabled
257 foreach ($this->fields as $key => $val) {
258 if (isset($val['enabled']) && empty($val['enabled'])) {
259 unset($this->fields[$key]);
260 }
261 }
262
263 // Translate some data of arrayofkeyval
264 if (is_object($langs)) {
265 foreach ($this->fields as $key => $val) {
266 if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) {
267 foreach ($val['arrayofkeyval'] as $key2 => $val2) {
268 $this->fields[$key]['arrayofkeyval'][$key2] = $langs->trans($val2);
269 }
270 }
271 }
272 }
273 }
274
282 public function create(User $user, $notrigger = 0)
283 {
284 $resultcreate = $this->createCommon($user, $notrigger);
285
286 //$resultvalidate = $this->validate($user, $notrigger);
287
288 return $resultcreate;
289 }
290
298 public function createFromClone(User $user, $fromid)
299 {
300 global $langs, $extrafields;
301 $error = 0;
302
303 dol_syslog(__METHOD__, LOG_DEBUG);
304
305 $object = new self($this->db);
306
307 $this->db->begin();
308
309 // Load source object
310 $result = $object->fetchCommon($fromid);
311 if ($result > 0 && !empty($object->table_element_line)) {
312 $object->fetchLines();
313 }
314
315 // get lines so they will be clone
316 //foreach($this->lines as $line)
317 // $line->fetch_optionals();
318
319 // Reset some properties
320 unset($object->id);
321 unset($object->fk_user_creat);
322 unset($object->import_key);
323
324 // Clear fields
325 if (property_exists($object, 'ref')) {
326 $object->ref = empty($this->fields['ref']['default']) ? "Copy_Of_".$object->ref : $this->fields['ref']['default'];
327 }
328 if (property_exists($object, 'label')) {
329 $object->label = empty($this->fields['label']['default']) ? $langs->trans("CopyOf")." ".$object->label : $this->fields['label']['default'];
330 }
331 if (property_exists($object, 'status')) {
332 $object->status = self::STATUS_DRAFT;
333 }
334 if (property_exists($object, 'date_creation')) {
335 $object->date_creation = dol_now();
336 }
337 if (property_exists($object, 'date_modification')) {
338 $object->date_modification = null;
339 }
340 // ...
341 // Clear extrafields that are unique
342 if (is_array($object->array_options) && count($object->array_options) > 0) {
343 $extrafields->fetch_name_optionals_label($this->table_element);
344 foreach ($object->array_options as $key => $option) {
345 $shortkey = preg_replace('/options_/', '', $key);
346 if (!empty($extrafields->attributes[$this->table_element]['unique'][$shortkey])) {
347 //var_dump($key);
348 //var_dump($clonedObj->array_options[$key]); exit;
349 unset($object->array_options[$key]);
350 }
351 }
352 }
353
354 // Create clone
355 $object->context['createfromclone'] = 'createfromclone';
356 $result = $object->createCommon($user);
357 if ($result < 0) {
358 $error++;
360 }
361
362 if (!$error) {
363 // copy internal contacts
364 if ($this->copy_linked_contact($object, 'internal') < 0) {
365 $error++;
366 }
367 }
368
369 if (!$error) {
370 // copy external contacts if same company
371 if (!empty($object->socid) && property_exists($this, 'fk_soc') && $this->fk_soc == $object->socid) {
372 if ($this->copy_linked_contact($object, 'external') < 0) {
373 $error++;
374 }
375 }
376 }
377
378 unset($object->context['createfromclone']);
379
380 // End
381 if (!$error) {
382 $this->db->commit();
383 return $object;
384 } else {
385 $this->db->rollback();
386 return -1;
387 }
388 }
389
399 public function fetch($id, $ref = null, $noextrafields = 0, $nolines = 0)
400 {
401 $result = $this->fetchCommon($id, $ref, '', $noextrafields);
402 if ($result > 0 && !empty($this->table_element_line) && empty($nolines)) {
403 $this->fetchLines($noextrafields);
404 }
405 return $result;
406 }
407
414 public function fetchLines($noextrafields = 0)
415 {
416 $this->lines = array();
417
418 $result = $this->fetchLinesCommon('', $noextrafields);
419 return $result;
420 }
421
422
437 public function fetchAll($sortorder = '', $sortfield = '', $limit = 1000, $offset = 0, string $filter = '', $filtermode = 'AND')
438 {
439 dol_syslog(__METHOD__, LOG_DEBUG);
440
441 $records = array();
442
443 $sql = "SELECT ";
444 $sql .= $this->getFieldList('t');
445 $sql .= " FROM ".$this->db->prefix().$this->table_element." as t";
446 if (isset($this->isextrafieldmanaged) && $this->isextrafieldmanaged == 1) {
447 $sql .= " LEFT JOIN ".$this->db->prefix().$this->table_element."_extrafields as te ON te.fk_object = t.rowid";
448 }
449 if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) {
450 $sql .= " WHERE t.entity IN (".getEntity($this->element).")";
451 } else {
452 $sql .= " WHERE 1 = 1";
453 }
454
455 // Manage filter
456 $errormessage = '';
457 $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage);
458 if ($errormessage) {
459 $this->errors[] = $errormessage;
460 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
461 return -1;
462 }
463
464 if (!empty($sortfield)) {
465 $sql .= $this->db->order($sortfield, $sortorder);
466 }
467 if (!empty($limit)) {
468 $sql .= $this->db->plimit($limit, $offset);
469 }
470
471 $resql = $this->db->query($sql);
472 if ($resql) {
473 $num = $this->db->num_rows($resql);
474 $i = 0;
475 while ($i < ($limit ? min($limit, $num) : $num)) {
476 $obj = $this->db->fetch_object($resql);
477
478 $record = new self($this->db);
479 $record->setVarsFromFetchObj($obj);
480
481 if (!empty($record->isextrafieldmanaged)) {
482 $record->fetch_optionals();
483 }
484
485 $records[$record->id] = $record;
486
487 $i++;
488 }
489 $this->db->free($resql);
490
491 return $records;
492 } else {
493 $this->errors[] = 'Error '.$this->db->lasterror();
494 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
495
496 return -1;
497 }
498 }
499
507 public function update(User $user, $notrigger = 0)
508 {
509 return $this->updateCommon($user, $notrigger);
510 }
511
519 public function delete(User $user, $notrigger = 0)
520 {
521 return $this->deleteCommon($user, $notrigger);
522 //return $this->deleteCommon($user, $notrigger, 1);
523 }
524
533 public function deleteLine(User $user, $idline, $notrigger = 0)
534 {
535 if ($this->status < 0) {
536 $this->error = 'ErrorDeleteLineNotAllowedByObjectStatus';
537 return -2;
538 }
539
540 return $this->deleteLineCommon($user, $idline, $notrigger);
541 }
542
543
551 public function validate($user, $notrigger = 0)
552 {
553 global $conf;
554
555 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
556
557 $error = 0;
558
559 // Protection
560 if ($this->status == self::STATUS_VALIDATED) {
561 dol_syslog(get_class($this)."::validate action abandoned: already validated", LOG_WARNING);
562 return 0;
563 }
564
565 /* if (! ((!getDolGlobalInt('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('mymodule', 'myobject', 'write'))
566 || (getDolGlobalInt('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('mymodule', 'myobject_advance', 'validate')))
567 {
568 $this->error='NotEnoughPermissions';
569 dol_syslog(get_class($this)."::valid ".$this->error, LOG_ERR);
570 return -1;
571 }*/
572
573 $now = dol_now();
574
575 $this->db->begin();
576
577 // Define new ref
578 if (!$error && (preg_match('/^[\‍(]?PROV/i', $this->ref) || empty($this->ref))) { // empty should not happened, but when it occurs, the test save life
579 $num = $this->getNextNumRef();
580 } else {
581 $num = $this->ref;
582 }
583 $this->newref = $num;
584
585 if (!empty($num)) {
586 // Validate
587 $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element;
588 $sql .= " SET ";
589 if (!empty($this->fields['ref'])) {
590 $sql .= " ref = '".$this->db->escape($num)."',";
591 }
592 $sql .= " status = ".self::STATUS_VALIDATED;
593 if (!empty($this->fields['date_validation'])) {
594 $sql .= ", date_validation = '".$this->db->idate($now)."'";
595 }
596 if (!empty($this->fields['fk_user_valid'])) {
597 $sql .= ", fk_user_valid = ".((int) $user->id);
598 }
599 $sql .= " WHERE rowid = ".((int) $this->id);
600
601 dol_syslog(get_class($this)."::validate()", LOG_DEBUG);
602 $resql = $this->db->query($sql);
603 if (!$resql) {
604 dol_print_error($this->db);
605 $this->error = $this->db->lasterror();
606 $error++;
607 }
608
609 if (!$error && !$notrigger) {
610 // Call trigger
611 $result = $this->call_trigger('MYOBJECT_VALIDATE', $user);
612 if ($result < 0) {
613 $error++;
614 }
615 // End call triggers
616 }
617 }
618
619 if (!$error) {
620 $this->oldref = $this->ref;
621
622 // Rename directory if dir was a temporary ref
623 if (preg_match('/^[\‍(]?PROV/i', $this->ref)) {
624 // Now we rename also files into index
625 $sql = 'UPDATE '.MAIN_DB_PREFIX."ecm_files set filename = CONCAT('".$this->db->escape($this->newref)."', SUBSTR(filename, ".(strlen($this->ref) + 1).")), filepath = 'myobject/".$this->db->escape($this->newref)."'";
626 $sql .= " WHERE filename LIKE '".$this->db->escape($this->ref)."%' AND filepath = 'myobject/".$this->db->escape($this->ref)."' and entity = ".$conf->entity;
627 $resql = $this->db->query($sql);
628 if (!$resql) {
629 $error++;
630 $this->error = $this->db->lasterror();
631 }
632 $sql = 'UPDATE '.MAIN_DB_PREFIX."ecm_files set filepath = 'myobject/".$this->db->escape($this->newref)."'";
633 $sql .= " WHERE filepath = 'myobject/".$this->db->escape($this->ref)."' and entity = ".$conf->entity;
634 $resql = $this->db->query($sql);
635 if (!$resql) {
636 $error++;
637 $this->error = $this->db->lasterror();
638 }
639
640 // We rename directory ($this->ref = old ref, $num = new ref) in order not to lose the attachments
641 $oldref = dol_sanitizeFileName($this->ref);
642 $newref = dol_sanitizeFileName($num);
643 $dirsource = $conf->mymodule->dir_output.'/myobject/'.$oldref;
644 $dirdest = $conf->mymodule->dir_output.'/myobject/'.$newref;
645 if (!$error && file_exists($dirsource)) {
646 dol_syslog(get_class($this)."::validate() rename dir ".$dirsource." into ".$dirdest);
647
648 if (@rename($dirsource, $dirdest)) {
649 dol_syslog("Rename ok");
650 // Rename docs starting with $oldref with $newref
651 $listoffiles = dol_dir_list($conf->mymodule->dir_output.'/myobject/'.$newref, 'files', 1, '^'.preg_quote($oldref, '/'));
652 foreach ($listoffiles as $fileentry) {
653 $dirsource = $fileentry['name'];
654 $dirdest = preg_replace('/^'.preg_quote($oldref, '/').'/', $newref, $dirsource);
655 $dirsource = $fileentry['path'].'/'.$dirsource;
656 $dirdest = $fileentry['path'].'/'.$dirdest;
657 @rename($dirsource, $dirdest);
658 }
659 }
660 }
661 }
662 }
663
664 // Set new ref and current status
665 if (!$error) {
666 $this->ref = $num;
667 $this->status = self::STATUS_VALIDATED;
668 }
669
670 if (!$error) {
671 $this->db->commit();
672 return 1;
673 } else {
674 $this->db->rollback();
675 return -1;
676 }
677 }
678
679
687 public function setDraft($user, $notrigger = 0)
688 {
689 // Protection
690 if ($this->status <= self::STATUS_DRAFT) {
691 return 0;
692 }
693
694 /* if (! ((!getDolGlobalInt('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('mymodule','write'))
695 || (getDolGlobalInt('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('mymodule','mymodule_advance','validate'))))
696 {
697 $this->error='Permission denied';
698 return -1;
699 }*/
700
701 return $this->setStatusCommon($user, self::STATUS_DRAFT, $notrigger, 'MYMODULE_MYOBJECT_UNVALIDATE');
702 }
703
711 public function cancel($user, $notrigger = 0)
712 {
713 // Protection
714 if ($this->status != self::STATUS_VALIDATED) {
715 return 0;
716 }
717
718 /* if (! ((!getDolGlobalInt('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('mymodule','write'))
719 || (getDolGlobalInt('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('mymodule','mymodule_advance','validate'))))
720 {
721 $this->error='Permission denied';
722 return -1;
723 }*/
724
725 return $this->setStatusCommon($user, self::STATUS_CANCELED, $notrigger, 'MYMODULE_MYOBJECT_CANCEL');
726 }
727
735 public function reopen($user, $notrigger = 0)
736 {
737 // Protection
738 if ($this->status == self::STATUS_VALIDATED) {
739 return 0;
740 }
741
742 /*if (! ((!getDolGlobalInt('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('mymodule','write'))
743 || (getDolGlobalInt('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('mymodule','mymodule_advance','validate'))))
744 {
745 $this->error='Permission denied';
746 return -1;
747 }*/
748
749 return $this->setStatusCommon($user, self::STATUS_VALIDATED, $notrigger, 'MYMODULE_MYOBJECT_REOPEN');
750 }
751
759 public function getTooltipContentArray($params)
760 {
761 global $langs;
762
763 $datas = [];
764
765 if (getDolGlobalInt('MAIN_OPTIMIZEFORTEXTBROWSER')) {
766 return ['optimize' => $langs->trans("ShowMyObject")];
767 }
768 $datas['picto'] = img_picto('', $this->picto).' <u>'.$langs->trans("MyObject").'</u>';
769 if (isset($this->status)) {
770 $datas['picto'] .= ' '.$this->getLibStatut(5);
771 }
772 if (property_exists($this, 'ref')) {
773 $datas['ref'] = '<br><b>'.$langs->trans('Ref').':</b> '.$this->ref;
774 }
775 if (property_exists($this, 'label')) {
776 $datas['ref'] = '<br>'.$langs->trans('Label').':</b> '.$this->label;
777 }
778
779 return $datas;
780 }
781
792 public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
793 {
794 global $conf, $langs, $hookmanager;
795
796 if (!empty($conf->dol_no_mouse_hover)) {
797 $notooltip = 1; // Force disable tooltips
798 }
799
800 $result = '';
801 $params = [
802 'id' => $this->id,
803 'objecttype' => $this->element.($this->module ? '@'.$this->module : ''),
804 'option' => $option,
805 ];
806 $classfortooltip = 'classfortooltip';
807 $dataparams = '';
808 if (getDolGlobalInt('MAIN_ENABLE_AJAX_TOOLTIP')) {
809 $classfortooltip = 'classforajaxtooltip';
810 $dataparams = ' data-params="'.dol_escape_htmltag(json_encode($params)).'"';
811 $label = '';
812 } else {
813 $label = implode($this->getTooltipContentArray($params));
814 }
815
816 $url = dol_buildpath('/mymodule/myobject_card.php', 1).'?id='.$this->id;
817
818 if ($option !== 'nolink') {
819 // Add param to save lastsearch_values or not
820 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
821 if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
822 $add_save_lastsearch_values = 1;
823 }
824 if ($url && $add_save_lastsearch_values) {
825 $url .= '&save_lastsearch_values=1';
826 }
827 }
828
829 $linkclose = '';
830 if (empty($notooltip)) {
831 if (getDolGlobalInt('MAIN_OPTIMIZEFORTEXTBROWSER')) {
832 $label = $langs->trans("ShowMyObject");
833 $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"';
834 }
835 $linkclose .= ($label ? ' title="'.dol_escape_htmltag($label, 1).'"' : ' title="tocomplete"');
836 $linkclose .= $dataparams.' class="'.$classfortooltip.($morecss ? ' '.$morecss : '').'"';
837 } else {
838 $linkclose = ($morecss ? ' class="'.$morecss.'"' : '');
839 }
840
841 if ($option == 'nolink' || empty($url)) {
842 $linkstart = '<span';
843 } else {
844 $linkstart = '<a href="'.$url.'"';
845 }
846 $linkstart .= $linkclose.'>';
847 if ($option == 'nolink' || empty($url)) {
848 $linkend = '</span>';
849 } else {
850 $linkend = '</a>';
851 }
852
853 $result .= $linkstart;
854
855 if (empty($this->showphoto_on_popup)) {
856 if ($withpicto) {
857 $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), (($withpicto != 2) ? 'class="paddingright"' : ''), 0, 0, $notooltip ? 0 : 1);
858 }
859 } else {
860 if ($withpicto) {
861 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
862
863 list($class, $module) = explode('@', $this->picto);
864 $upload_dir = $conf->$module->multidir_output[$conf->entity]."/$class/".dol_sanitizeFileName($this->ref);
865 $filearray = dol_dir_list($upload_dir, "files");
866 $filename = $filearray[0]['name'];
867 if (!empty($filename)) {
868 $pospoint = strpos($filearray[0]['name'], '.');
869
870 $pathtophoto = $class.'/'.$this->ref.'/thumbs/'.substr($filename, 0, $pospoint).'_mini'.substr($filename, $pospoint);
871 if (!getDolGlobalString(strtoupper($module.'_'.$class).'_FORMATLISTPHOTOSASUSERS')) {
872 $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>';
873 } else {
874 $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>';
875 }
876
877 $result .= '</div>';
878 } else {
879 $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'"'), 0, 0, $notooltip ? 0 : 1);
880 }
881 }
882 }
883
884 if ($withpicto != 2) {
885 $result .= $this->ref;
886 }
887
888 $result .= $linkend;
889 //if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : '');
890
891 global $action, $hookmanager;
892 $hookmanager->initHooks(array($this->element.'dao'));
893 $parameters = array('id' => $this->id, 'getnomurl' => &$result);
894 $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
895 if ($reshook > 0) {
896 $result = $hookmanager->resPrint;
897 } else {
898 $result .= $hookmanager->resPrint;
899 }
900
901 return $result;
902 }
903
911 public function getKanbanView($option = '', $arraydata = null)
912 {
913 global $conf, $langs;
914
915 $selected = (empty($arraydata['selected']) ? 0 : $arraydata['selected']);
916
917 $return = '<div class="box-flex-item box-flex-grow-zero">';
918 $return .= '<div class="info-box info-box-sm">';
919 $return .= '<span class="info-box-icon bg-infobox-action">';
920 $return .= img_picto('', $this->picto);
921 $return .= '</span>';
922 $return .= '<div class="info-box-content">';
923 $return .= '<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">'.(method_exists($this, 'getNomUrl') ? $this->getNomUrl() : $this->ref).'</span>';
924 if ($selected >= 0) {
925 $return .= '<input id="cb'.$this->id.'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->id.'"'.($selected ? ' checked="checked"' : '').'>';
926 }
927 if (property_exists($this, 'label')) {
928 $return .= ' <div class="inline-block opacitymedium valignmiddle tdoverflowmax100">'.$this->label.'</div>';
929 }
930 if (property_exists($this, 'thirdparty') && is_object($this->thirdparty)) {
931 $return .= '<br><div class="info-box-ref tdoverflowmax150">'.$this->thirdparty->getNomUrl(1).'</div>';
932 }
933 if (property_exists($this, 'amount')) {
934 $return .= '<br>';
935 $return .= '<span class="info-box-label amount">'.price($this->amount, 0, $langs, 1, -1, -1, $conf->currency).'</span>';
936 }
937 if (method_exists($this, 'getLibStatut')) {
938 $return .= '<br><div class="info-box-status">'.$this->getLibStatut(3).'</div>';
939 }
940 $return .= '</div>';
941 $return .= '</div>';
942 $return .= '</div>';
943
944 return $return;
945 }
946
953 public function getLabelStatus($mode = 0)
954 {
955 return $this->LibStatut($this->status, $mode);
956 }
957
964 public function getLibStatut($mode = 0)
965 {
966 return $this->LibStatut($this->status, $mode);
967 }
968
969 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
977 public function LibStatut($status, $mode = 0)
978 {
979 // phpcs:enable
980 if (is_null($status)) {
981 return '';
982 }
983
984 if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
985 global $langs;
986 //$langs->load("mymodule@mymodule");
987 $this->labelStatus[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft');
988 $this->labelStatus[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Enabled');
989 $this->labelStatus[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('Disabled');
990 $this->labelStatusShort[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft');
991 $this->labelStatusShort[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Enabled');
992 $this->labelStatusShort[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('Disabled');
993 }
994
995 $statusType = 'status'.$status;
996 //if ($status == self::STATUS_VALIDATED) $statusType = 'status1';
997 if ($status == self::STATUS_CANCELED) {
998 $statusType = 'status6';
999 }
1000
1001 return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode);
1002 }
1003
1010 public function info($id)
1011 {
1012 $sql = "SELECT rowid,";
1013 $sql .= " date_creation as datec, tms as datem";
1014 if (!empty($this->fields['date_validation'])) {
1015 $sql .= ", date_validation as datev";
1016 }
1017 if (!empty($this->fields['fk_user_creat'])) {
1018 $sql .= ", fk_user_creat";
1019 }
1020 if (!empty($this->fields['fk_user_modif'])) {
1021 $sql .= ", fk_user_modif";
1022 }
1023 if (!empty($this->fields['fk_user_valid'])) {
1024 $sql .= ", fk_user_valid";
1025 }
1026 $sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element." as t";
1027 $sql .= " WHERE t.rowid = ".((int) $id);
1028
1029 $result = $this->db->query($sql);
1030 if ($result) {
1031 if ($this->db->num_rows($result)) {
1032 $obj = $this->db->fetch_object($result);
1033
1034 $this->id = $obj->rowid;
1035
1036 if (!empty($this->fields['fk_user_creat'])) {
1037 $this->user_creation_id = $obj->fk_user_creat;
1038 }
1039 if (!empty($this->fields['fk_user_modif'])) {
1040 $this->user_modification_id = $obj->fk_user_modif;
1041 }
1042 if (!empty($this->fields['fk_user_valid'])) {
1043 $this->user_validation_id = $obj->fk_user_valid;
1044 }
1045 $this->date_creation = $this->db->jdate($obj->datec);
1046 $this->date_modification = empty($obj->datem) ? '' : $this->db->jdate($obj->datem);
1047 if (!empty($obj->datev)) {
1048 $this->date_validation = empty($obj->datev) ? '' : $this->db->jdate($obj->datev);
1049 }
1050 }
1051
1052 $this->db->free($result);
1053 } else {
1054 dol_print_error($this->db);
1055 }
1056 }
1057
1064 public function initAsSpecimen()
1065 {
1066 // Set here init that are not commonf fields
1067 // $this->property1 = ...
1068 // $this->property2 = ...
1069
1070 return $this->initAsSpecimenCommon();
1071 }
1072
1078 public function getLinesArray()
1079 {
1080 $this->lines = array();
1081
1082 $objectline = new MyObjectLine($this->db);
1083 $result = $objectline->fetchAll('ASC', 'position', 0, 0, '(fk_myobject:=:'.((int) $this->id).')');
1084
1085 if (is_numeric($result)) {
1086 $this->setErrorsFromObject($objectline);
1087 return $result;
1088 } else {
1089 $this->lines = $result;
1090 return $this->lines;
1091 }
1092 }
1093
1099 public function getNextNumRef()
1100 {
1101 global $langs, $conf;
1102 $langs->load("mymodule@mymodule");
1103
1104 if (!getDolGlobalString('MYMODULE_MYOBJECT_ADDON')) {
1105 $conf->global->MYMODULE_MYOBJECT_ADDON = 'mod_myobject_standard';
1106 }
1107
1108 if (getDolGlobalString('MYMODULE_MYOBJECT_ADDON')) {
1109 $mybool = false;
1110
1111 $file = getDolGlobalString('MYMODULE_MYOBJECT_ADDON').".php";
1112 $classname = getDolGlobalString('MYMODULE_MYOBJECT_ADDON');
1113
1114 // Include file with class
1115 $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
1116 foreach ($dirmodels as $reldir) {
1117 $dir = dol_buildpath($reldir."core/modules/mymodule/");
1118
1119 // Load file with numbering class (if found)
1120 $mybool = $mybool || @include_once $dir.$file;
1121 }
1122
1123 if (!$mybool) {
1124 dol_print_error(null, "Failed to include file ".$file);
1125 return '';
1126 }
1127
1128 if (class_exists($classname)) {
1129 $obj = new $classname();
1130 '@phan-var-force ModeleNumRefMyObject $obj';
1131 $numref = $obj->getNextValue($this);
1132
1133 if ($numref != '' && $numref != '-1') {
1134 return $numref;
1135 } else {
1136 $this->error = $obj->error;
1137 //dol_print_error($this->db,get_class($this)."::getNextNumRef ".$obj->error);
1138 return "";
1139 }
1140 } else {
1141 print $langs->trans("Error")." ".$langs->trans("ClassNotFound").' '.$classname;
1142 return "";
1143 }
1144 } else {
1145 print $langs->trans("ErrorNumberingModuleNotSetup", $this->element);
1146 return "";
1147 }
1148 }
1149
1161 public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams = null)
1162 {
1163 global $langs;
1164
1165 $result = 0;
1166 $includedocgeneration = 0;
1167
1168 $langs->load("mymodule@mymodule");
1169
1170 if (!dol_strlen($modele)) {
1171 $modele = 'standard_myobject';
1172
1173 if (!empty($this->model_pdf)) {
1174 $modele = $this->model_pdf;
1175 } elseif (getDolGlobalString('MYOBJECT_ADDON_PDF')) {
1176 $modele = getDolGlobalString('MYOBJECT_ADDON_PDF');
1177 }
1178 }
1179
1180 $modelpath = "core/modules/mymodule/doc/";
1181
1182 if ($includedocgeneration && !empty($modele)) {
1183 $result = $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
1184 }
1185
1186 return $result;
1187 }
1188
1198 public function validateField($fields, $fieldKey, $fieldValue)
1199 {
1200 // Add your own validation rules here.
1201 // ...
1202
1203 return parent::validateField($fields, $fieldKey, $fieldValue);
1204 }
1205
1213 public function doScheduledJob()
1214 {
1215 //global $conf, $langs;
1216
1217 //$conf->global->SYSLOG_FILE = 'DOL_DATA_ROOT/dolibarr_mydedicatedlogfile.log';
1218
1219 $error = 0;
1220 $this->output = '';
1221 $this->error = '';
1222
1223 dol_syslog(__METHOD__." start", LOG_INFO);
1224
1225 $now = dol_now();
1226
1227 $this->db->begin();
1228
1229 // ...
1230
1231 $this->db->commit();
1232
1233 dol_syslog(__METHOD__." end", LOG_INFO);
1234
1235 return $error;
1236 }
1237}
1238
1239
1240require_once DOL_DOCUMENT_ROOT.'/core/class/commonobjectline.class.php';
1241
1246{
1247 // To complete with content of an object MyObjectLine
1248 // We should have a field rowid, fk_myobject and position
1249
1254 public $parent_element = ''; // Example: '' or 'myobject'
1255
1260 public $fk_parent_attribute = ''; // Example: '' or 'fk_myobject'
1261
1267 public function __construct(DoliDB $db)
1268 {
1269 $this->db = $db;
1270
1271 $this->isextrafieldmanaged = 0;
1272 }
1273}
if( $user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
Definition card.php:58
$object ref
Definition info.php:79
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.
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 MyObject.
generateDocument($modele, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0, $moreparams=null)
Create a document onto disk according to template module.
createFromClone(User $user, $fromid)
Clone an object into another one.
getKanbanView($option='', $arraydata=null)
Return a thumb for kanban views.
getLibStatut($mode=0)
Return the label of the status.
create(User $user, $notrigger=0)
Create object into database.
update(User $user, $notrigger=0)
Update object into database.
getTooltipContentArray($params)
getTooltipContentArray
reopen($user, $notrigger=0)
Set back to validated status.
setDraft($user, $notrigger=0)
Set draft status.
getNomUrl($withpicto=0, $option='', $notooltip=0, $morecss='', $save_lastsearch_value=-1)
Return a link to the object card (with optionally the picto)
LibStatut($status, $mode=0)
Return the label of a given status.
validateField($fields, $fieldKey, $fieldValue)
Return validation test result for a field.
getNextNumRef()
Returns the reference to the following non used object depending on the active numbering module.
fetchAll($sortorder='', $sortfield='', $limit=1000, $offset=0, string $filter='', $filtermode='AND')
Load list of objects in memory from the database.
initAsSpecimen()
Initialize object with example values Id must be 0 if object instance is a specimen.
__construct(DoliDB $db)
Constructor.
deleteLine(User $user, $idline, $notrigger=0)
Delete a line of object in database.
cancel($user, $notrigger=0)
Set cancel status.
fetchLines($noextrafields=0)
Load object lines in memory from the database.
info($id)
Load the info information in the object.
doScheduledJob()
Action executed by scheduler CAN BE A CRON TASK.
fetch($id, $ref=null, $noextrafields=0, $nolines=0)
Load object in memory from the database.
getLabelStatus($mode=0)
Return the label of the status.
validate($user, $notrigger=0)
Validate object.
$fields
'type' field format: 'integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter[:Sortf...
getLinesArray()
Create an array of lines.
Class MyObjectLine.
$parent_element
To overload.
$fk_parent_attribute
To overload.
__construct(DoliDB $db)
Constructor.
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:162
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_object($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0)
Show a picto called object_picto (generic function)
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (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.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1)
Clean a string to use it as a file name.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
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.