dolibarr 20.0.0
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) 2024 MDW <mdeweerd@users.noreply.github.com>
5 * Copyright (C) ---Put here your own copyright and developer email---
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
27// Put here all includes required by your class file
28require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
29//require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php';
30//require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php';
31
36{
40 public $module = 'mymodule';
41
45 public $element = 'myobject';
46
50 public $table_element = 'mymodule_myobject';
51
55 //public $element_for_permission = 'mymodule';
56
60 public $picto = 'fa-file';
61
62
63 const STATUS_DRAFT = 0;
64 const STATUS_VALIDATED = 1;
65 const STATUS_CANCELED = 9;
66
107 // BEGIN MODULEBUILDER PROPERTIES
111 public $fields = array(
112 'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'visible' => -2, 'noteditable' => 1, 'notnull' => 1, 'index' => 1, 'position' => 1, 'comment' => 'Id', 'css' => 'left'),
113 'entity' => array('type' => 'integer', 'label' => 'Entity', 'enabled' => 1, 'visible' => 0, 'notnull' => 1, 'default' => 1, 'index' => 1, 'position' => 10),
114 'ref' => array('type' => 'varchar(128)', 'label' => 'Ref', 'enabled' => 1, 'visible' => 1, 'noteditable' => 0, 'default' => '', 'notnull' => 1, 'showoncombobox' => 1, 'index' => 1, 'position' => 20, 'searchall' => 1, 'comment' => 'Reference of object', 'validate' => 1),
115 'label' => array('type' => 'varchar(255)', 'label' => 'Label', 'enabled' => 1, 'visible' => 1, 'position' => 30, 'searchall' => 1, 'css' => 'minwidth300', 'cssview' => 'wordbreak', 'help' => 'Help text', 'showoncombobox' => 2, 'validate' => 1, 'alwayseditable' => 1),
116 'amount' => array('type' => 'price', 'label' => 'Amount', 'enabled' => 1, 'visible' => 1, 'default' => 'null', 'position' => 40, 'searchall' => 0, 'isameasure' => 1, 'help' => 'Help text for amount', 'validate' => 1),
117 'qty' => array('type' => 'real', 'label' => 'Qty', 'enabled' => 1, 'visible' => 1, 'default' => '0', 'position' => 45, 'searchall' => 0, 'isameasure' => 1, 'help' => 'Help text for quantity', 'css' => 'maxwidth75imp', 'validate' => 1),
118 'fk_soc' => array('type' => 'integer:Societe:societe/class/societe.class.php:1:((status:=:1) AND (entity:IN:__SHARED_ENTITIES__))', 'picto' => 'company', 'label' => 'ThirdParty', 'visible' => 1, 'enabled' => 'isModEnabled("societe")', 'position' => 50, 'notnull' => -1, 'index' => 1, 'help' => 'OrganizationEventLinkToThirdParty', 'validate' => 1, 'css' => 'maxwidth500 widthcentpercentminusxx', 'csslist' => 'tdoverflowmax150'),
119 'fk_project' => array('type' => 'integer:Project:projet/class/project.class.php:1', 'label' => 'Project', 'picto' => 'project', 'enabled' => 'isModEnabled("project")', 'visible' => -1, 'position' => 52, 'notnull' => -1, 'index' => 1, 'validate' => 1, 'css' => 'maxwidth500 widthcentpercentminusxx', 'csslist' => 'tdoverflowmax150'),
120 'description' => array('type' => 'text', 'label' => 'Description', 'enabled' => 1, 'visible' => 3, 'position' => 60, 'validate' => 1),
121 'note_public' => array('type' => 'html', 'label' => 'NotePublic', 'enabled' => 1, 'visible' => 0, 'position' => 61, 'validate' => 1, 'cssview' => 'wordbreak'),
122 'note_private' => array('type' => 'html', 'label' => 'NotePrivate', 'enabled' => 1, 'visible' => 0, 'position' => 62, 'validate' => 1, 'cssview' => 'wordbreak'),
123 'date_creation' => array('type' => 'datetime', 'label' => 'DateCreation', 'enabled' => 1, 'visible' => -2, 'notnull' => 1, 'position' => 500),
124 'tms' => array('type' => 'timestamp', 'label' => 'DateModification', 'enabled' => 1, 'visible' => -2, 'notnull' => 0, 'position' => 501),
125 //'date_validation ' =>array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>1, 'visible'=>-2, 'position'=>502),
126 'fk_user_creat' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserAuthor', 'picto' => 'user', 'enabled' => 1, 'visible' => -2, 'notnull' => 1, 'position' => 510, 'foreignkey' => 'user.rowid', 'csslist' => 'tdoverflowmax150'),
127 'fk_user_modif' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserModif', 'picto' => 'user', 'enabled' => 1, 'visible' => -2, 'notnull' => -1, 'position' => 511, 'csslist' => 'tdoverflowmax150'),
128 //'fk_user_valid' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'UserValidation', 'enabled'=>1, 'visible'=>-1, 'position'=>512),
129 'last_main_doc' => array('type' => 'varchar(255)', 'label' => 'LastMainDoc', 'enabled' => 1, 'visible' => 0, 'notnull' => 0, 'position' => 600),
130 'import_key' => array('type' => 'varchar(14)', 'label' => 'ImportId', 'enabled' => 1, 'visible' => -2, 'notnull' => -1, 'index' => 0, 'position' => 1000),
131 'model_pdf' => array('type' => 'varchar(255)', 'label' => 'Model pdf', 'enabled' => 1, 'visible' => 0, 'notnull' => -1, 'position' => 1010),
132 'status' => array('type' => 'integer', 'label' => 'Status', 'enabled' => 1, 'visible' => 1, 'notnull' => 1, 'default' => 0, 'index' => 1, 'position' => 2000, 'arrayofkeyval' => array(0 => 'Draft', 1 => 'Validated', 9 => 'Canceled'), 'validate' => 1),
133 );
134
138 public $rowid;
139
143 public $ref;
144
148 public $entity;
149
153 public $label;
154
158 public $amount;
159
163 public $socid; // both socid and fk_soc are used
164 public $fk_soc; // both socid and fk_soc are used
165
169 public $status;
170
174 public $date_creation;
175
179 public $fk_user_creat;
180
184 public $fk_user_modif;
185
189 public $last_main_doc;
190
194 public $import_key;
195 // END MODULEBUILDER PROPERTIES
196
197
198 // If this object has a subtable with lines
199
200 // /**
201 // * @var string Name of subtable line
202 // */
203 // public $table_element_line = 'mymodule_myobjectline';
204
205 // /**
206 // * @var string Field with ID of parent key if this object has a parent
207 // */
208 // public $fk_element = 'fk_myobject';
209
210 // /**
211 // * @var string Name of subtable class that manage subtable lines
212 // */
213 // public $class_element_line = 'MyObjectline';
214
215 // /**
216 // * @var array List of child tables. To test if we can delete object.
217 // */
218 // protected $childtables = array('mychildtable' => array('name'=>'MyObject', 'fk_element'=>'fk_myobject'));
219
220 // /**
221 // * @var array List of child tables. To know object to delete on cascade.
222 // * If name matches '@ClassNAme:FilePathClass;ParentFkFieldName' it will
223 // * call method deleteByParentField(parentId, ParentFkFieldName) to fetch and delete child object
224 // */
225 // protected $childtablesoncascade = array('mymodule_myobjectdet');
226
227 // /**
228 // * @var MyObjectLine[] Array of subtable lines
229 // */
230 // public $lines = array();
231
232
233
239 public function __construct(DoliDB $db)
240 {
241 global $langs;
242
243 $this->db = $db;
244 $this->ismultientitymanaged = 0;
245 $this->isextrafieldmanaged = 1;
246
247 if (!getDolGlobalInt('MAIN_SHOW_TECHNICAL_ID') && isset($this->fields['rowid']) && !empty($this->fields['ref'])) {
248 $this->fields['rowid']['visible'] = 0;
249 }
250 if (!isModEnabled('multicompany') && isset($this->fields['entity'])) {
251 $this->fields['entity']['enabled'] = 0;
252 }
253
254 // Example to show how to set values of fields definition dynamically
255 /*if ($user->hasRight('mymodule', 'myobject', 'read')) {
256 $this->fields['myfield']['visible'] = 1;
257 $this->fields['myfield']['noteditable'] = 0;
258 }*/
259
260 // Unset fields that are disabled
261 foreach ($this->fields as $key => $val) {
262 if (isset($val['enabled']) && empty($val['enabled'])) {
263 unset($this->fields[$key]);
264 }
265 }
266
267 // Translate some data of arrayofkeyval
268 if (is_object($langs)) {
269 foreach ($this->fields as $key => $val) {
270 if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) {
271 foreach ($val['arrayofkeyval'] as $key2 => $val2) {
272 $this->fields[$key]['arrayofkeyval'][$key2] = $langs->trans($val2);
273 }
274 }
275 }
276 }
277 }
278
286 public function create(User $user, $notrigger = 0)
287 {
288 $resultcreate = $this->createCommon($user, $notrigger);
289
290 //$resultvalidate = $this->validate($user, $notrigger);
291
292 return $resultcreate;
293 }
294
302 public function createFromClone(User $user, $fromid)
303 {
304 global $langs, $extrafields;
305 $error = 0;
306
307 dol_syslog(__METHOD__, LOG_DEBUG);
308
309 $object = new self($this->db);
310
311 $this->db->begin();
312
313 // Load source object
314 $result = $object->fetchCommon($fromid);
315 if ($result > 0 && !empty($object->table_element_line)) {
316 $object->fetchLines();
317 }
318
319 // get lines so they will be clone
320 //foreach($this->lines as $line)
321 // $line->fetch_optionals();
322
323 // Reset some properties
324 unset($object->id);
325 unset($object->fk_user_creat);
326 unset($object->import_key);
327
328 // Clear fields
329 if (property_exists($object, 'ref')) {
330 $object->ref = empty($this->fields['ref']['default']) ? "Copy_Of_".$object->ref : $this->fields['ref']['default'];
331 }
332 if (property_exists($object, 'label')) {
333 $object->label = empty($this->fields['label']['default']) ? $langs->trans("CopyOf")." ".$object->label : $this->fields['label']['default'];
334 }
335 if (property_exists($object, 'status')) {
336 $object->status = self::STATUS_DRAFT;
337 }
338 if (property_exists($object, 'date_creation')) {
339 $object->date_creation = dol_now();
340 }
341 if (property_exists($object, 'date_modification')) {
342 $object->date_modification = null;
343 }
344 // ...
345 // Clear extrafields that are unique
346 if (is_array($object->array_options) && count($object->array_options) > 0) {
347 $extrafields->fetch_name_optionals_label($this->table_element);
348 foreach ($object->array_options as $key => $option) {
349 $shortkey = preg_replace('/options_/', '', $key);
350 if (!empty($extrafields->attributes[$this->table_element]['unique'][$shortkey])) {
351 //var_dump($key);
352 //var_dump($clonedObj->array_options[$key]); exit;
353 unset($object->array_options[$key]);
354 }
355 }
356 }
357
358 // Create clone
359 $object->context['createfromclone'] = 'createfromclone';
360 $result = $object->createCommon($user);
361 if ($result < 0) {
362 $error++;
364 }
365
366 if (!$error) {
367 // copy internal contacts
368 if ($this->copy_linked_contact($object, 'internal') < 0) {
369 $error++;
370 }
371 }
372
373 if (!$error) {
374 // copy external contacts if same company
375 if (!empty($object->socid) && property_exists($this, 'fk_soc') && $this->fk_soc == $object->socid) {
376 if ($this->copy_linked_contact($object, 'external') < 0) {
377 $error++;
378 }
379 }
380 }
381
382 unset($object->context['createfromclone']);
383
384 // End
385 if (!$error) {
386 $this->db->commit();
387 return $object;
388 } else {
389 $this->db->rollback();
390 return -1;
391 }
392 }
393
403 public function fetch($id, $ref = null, $noextrafields = 0, $nolines = 0)
404 {
405 $result = $this->fetchCommon($id, $ref, '', $noextrafields);
406 if ($result > 0 && !empty($this->table_element_line) && empty($nolines)) {
407 $this->fetchLines($noextrafields);
408 }
409 return $result;
410 }
411
418 public function fetchLines($noextrafields = 0)
419 {
420 $this->lines = array();
421
422 $result = $this->fetchLinesCommon('', $noextrafields);
423 return $result;
424 }
425
426
441 public function fetchAll($sortorder = '', $sortfield = '', $limit = 1000, $offset = 0, string $filter = '', $filtermode = 'AND')
442 {
443 dol_syslog(__METHOD__, LOG_DEBUG);
444
445 $records = array();
446
447 $sql = "SELECT ";
448 $sql .= $this->getFieldList('t');
449 $sql .= " FROM ".$this->db->prefix().$this->table_element." as t";
450 if (isset($this->isextrafieldmanaged) && $this->isextrafieldmanaged == 1) {
451 $sql .= " LEFT JOIN ".$this->db->prefix().$this->table_element."_extrafields as te ON te.fk_object = t.rowid";
452 }
453 if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) {
454 $sql .= " WHERE t.entity IN (".getEntity($this->element).")";
455 } else {
456 $sql .= " WHERE 1 = 1";
457 }
458
459 // Manage filter
460 $errormessage = '';
461 $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage);
462 if ($errormessage) {
463 $this->errors[] = $errormessage;
464 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
465 return -1;
466 }
467
468 if (!empty($sortfield)) {
469 $sql .= $this->db->order($sortfield, $sortorder);
470 }
471 if (!empty($limit)) {
472 $sql .= $this->db->plimit($limit, $offset);
473 }
474
475 $resql = $this->db->query($sql);
476 if ($resql) {
477 $num = $this->db->num_rows($resql);
478 $i = 0;
479 while ($i < ($limit ? min($limit, $num) : $num)) {
480 $obj = $this->db->fetch_object($resql);
481
482 $record = new self($this->db);
483 $record->setVarsFromFetchObj($obj);
484
485 if (!empty($record->isextrafieldmanaged)) {
486 $record->fetch_optionals();
487 }
488
489 $records[$record->id] = $record;
490
491 $i++;
492 }
493 $this->db->free($resql);
494
495 return $records;
496 } else {
497 $this->errors[] = 'Error '.$this->db->lasterror();
498 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
499
500 return -1;
501 }
502 }
503
511 public function update(User $user, $notrigger = 0)
512 {
513 return $this->updateCommon($user, $notrigger);
514 }
515
523 public function delete(User $user, $notrigger = 0)
524 {
525 return $this->deleteCommon($user, $notrigger);
526 //return $this->deleteCommon($user, $notrigger, 1);
527 }
528
537 public function deleteLine(User $user, $idline, $notrigger = 0)
538 {
539 if ($this->status < 0) {
540 $this->error = 'ErrorDeleteLineNotAllowedByObjectStatus';
541 return -2;
542 }
543
544 return $this->deleteLineCommon($user, $idline, $notrigger);
545 }
546
547
555 public function validate($user, $notrigger = 0)
556 {
557 global $conf;
558
559 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
560
561 $error = 0;
562
563 // Protection
564 if ($this->status == self::STATUS_VALIDATED) {
565 dol_syslog(get_class($this)."::validate action abandoned: already validated", LOG_WARNING);
566 return 0;
567 }
568
569 /* if (! ((!getDolGlobalInt('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('mymodule', 'myobject', 'write'))
570 || (getDolGlobalInt('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('mymodule', 'myobject_advance', 'validate')))
571 {
572 $this->error='NotEnoughPermissions';
573 dol_syslog(get_class($this)."::valid ".$this->error, LOG_ERR);
574 return -1;
575 }*/
576
577 $now = dol_now();
578
579 $this->db->begin();
580
581 // Define new ref
582 if (!$error && (preg_match('/^[\‍(]?PROV/i', $this->ref) || empty($this->ref))) { // empty should not happened, but when it occurs, the test save life
583 $num = $this->getNextNumRef();
584 } else {
585 $num = $this->ref;
586 }
587 $this->newref = $num;
588
589 if (!empty($num)) {
590 // Validate
591 $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element;
592 $sql .= " SET ";
593 if (!empty($this->fields['ref'])) {
594 $sql .= " ref = '".$this->db->escape($num)."',";
595 }
596 $sql .= " status = ".self::STATUS_VALIDATED;
597 if (!empty($this->fields['date_validation'])) {
598 $sql .= ", date_validation = '".$this->db->idate($now)."'";
599 }
600 if (!empty($this->fields['fk_user_valid'])) {
601 $sql .= ", fk_user_valid = ".((int) $user->id);
602 }
603 $sql .= " WHERE rowid = ".((int) $this->id);
604
605 dol_syslog(get_class($this)."::validate()", LOG_DEBUG);
606 $resql = $this->db->query($sql);
607 if (!$resql) {
608 dol_print_error($this->db);
609 $this->error = $this->db->lasterror();
610 $error++;
611 }
612
613 if (!$error && !$notrigger) {
614 // Call trigger
615 $result = $this->call_trigger('MYOBJECT_VALIDATE', $user);
616 if ($result < 0) {
617 $error++;
618 }
619 // End call triggers
620 }
621 }
622
623 if (!$error) {
624 $this->oldref = $this->ref;
625
626 // Rename directory if dir was a temporary ref
627 if (preg_match('/^[\‍(]?PROV/i', $this->ref)) {
628 // Now we rename also files into index
629 $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)."'";
630 $sql .= " WHERE filename LIKE '".$this->db->escape($this->ref)."%' AND filepath = 'myobject/".$this->db->escape($this->ref)."' and entity = ".$conf->entity;
631 $resql = $this->db->query($sql);
632 if (!$resql) {
633 $error++;
634 $this->error = $this->db->lasterror();
635 }
636 $sql = 'UPDATE '.MAIN_DB_PREFIX."ecm_files set filepath = 'myobject/".$this->db->escape($this->newref)."'";
637 $sql .= " WHERE filepath = 'myobject/".$this->db->escape($this->ref)."' and entity = ".$conf->entity;
638 $resql = $this->db->query($sql);
639 if (!$resql) {
640 $error++;
641 $this->error = $this->db->lasterror();
642 }
643
644 // We rename directory ($this->ref = old ref, $num = new ref) in order not to lose the attachments
645 $oldref = dol_sanitizeFileName($this->ref);
646 $newref = dol_sanitizeFileName($num);
647 $dirsource = $conf->mymodule->dir_output.'/myobject/'.$oldref;
648 $dirdest = $conf->mymodule->dir_output.'/myobject/'.$newref;
649 if (!$error && file_exists($dirsource)) {
650 dol_syslog(get_class($this)."::validate() rename dir ".$dirsource." into ".$dirdest);
651
652 if (@rename($dirsource, $dirdest)) {
653 dol_syslog("Rename ok");
654 // Rename docs starting with $oldref with $newref
655 $listoffiles = dol_dir_list($conf->mymodule->dir_output.'/myobject/'.$newref, 'files', 1, '^'.preg_quote($oldref, '/'));
656 foreach ($listoffiles as $fileentry) {
657 $dirsource = $fileentry['name'];
658 $dirdest = preg_replace('/^'.preg_quote($oldref, '/').'/', $newref, $dirsource);
659 $dirsource = $fileentry['path'].'/'.$dirsource;
660 $dirdest = $fileentry['path'].'/'.$dirdest;
661 @rename($dirsource, $dirdest);
662 }
663 }
664 }
665 }
666 }
667
668 // Set new ref and current status
669 if (!$error) {
670 $this->ref = $num;
671 $this->status = self::STATUS_VALIDATED;
672 }
673
674 if (!$error) {
675 $this->db->commit();
676 return 1;
677 } else {
678 $this->db->rollback();
679 return -1;
680 }
681 }
682
683
691 public function setDraft($user, $notrigger = 0)
692 {
693 // Protection
694 if ($this->status <= self::STATUS_DRAFT) {
695 return 0;
696 }
697
698 /* if (! ((!getDolGlobalInt('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('mymodule','write'))
699 || (getDolGlobalInt('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('mymodule','mymodule_advance','validate'))))
700 {
701 $this->error='Permission denied';
702 return -1;
703 }*/
704
705 return $this->setStatusCommon($user, self::STATUS_DRAFT, $notrigger, 'MYMODULE_MYOBJECT_UNVALIDATE');
706 }
707
715 public function cancel($user, $notrigger = 0)
716 {
717 // Protection
718 if ($this->status != self::STATUS_VALIDATED) {
719 return 0;
720 }
721
722 /* if (! ((!getDolGlobalInt('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('mymodule','write'))
723 || (getDolGlobalInt('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('mymodule','mymodule_advance','validate'))))
724 {
725 $this->error='Permission denied';
726 return -1;
727 }*/
728
729 return $this->setStatusCommon($user, self::STATUS_CANCELED, $notrigger, 'MYMODULE_MYOBJECT_CANCEL');
730 }
731
739 public function reopen($user, $notrigger = 0)
740 {
741 // Protection
742 if ($this->status == self::STATUS_VALIDATED) {
743 return 0;
744 }
745
746 /*if (! ((!getDolGlobalInt('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('mymodule','write'))
747 || (getDolGlobalInt('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('mymodule','mymodule_advance','validate'))))
748 {
749 $this->error='Permission denied';
750 return -1;
751 }*/
752
753 return $this->setStatusCommon($user, self::STATUS_VALIDATED, $notrigger, 'MYMODULE_MYOBJECT_REOPEN');
754 }
755
763 public function getTooltipContentArray($params)
764 {
765 global $langs;
766
767 $datas = [];
768
769 if (getDolGlobalInt('MAIN_OPTIMIZEFORTEXTBROWSER')) {
770 return ['optimize' => $langs->trans("ShowMyObject")];
771 }
772 $datas['picto'] = img_picto('', $this->picto).' <u>'.$langs->trans("MyObject").'</u>';
773 if (isset($this->status)) {
774 $datas['picto'] .= ' '.$this->getLibStatut(5);
775 }
776 if (property_exists($this, 'ref')) {
777 $datas['ref'] = '<br><b>'.$langs->trans('Ref').':</b> '.$this->ref;
778 }
779 if (property_exists($this, 'label')) {
780 $datas['ref'] = '<br>'.$langs->trans('Label').':</b> '.$this->label;
781 }
782
783 return $datas;
784 }
785
796 public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
797 {
798 global $conf, $langs, $hookmanager;
799
800 if (!empty($conf->dol_no_mouse_hover)) {
801 $notooltip = 1; // Force disable tooltips
802 }
803
804 $result = '';
805 $params = [
806 'id' => $this->id,
807 'objecttype' => $this->element.($this->module ? '@'.$this->module : ''),
808 'option' => $option,
809 ];
810 $classfortooltip = 'classfortooltip';
811 $dataparams = '';
812 if (getDolGlobalInt('MAIN_ENABLE_AJAX_TOOLTIP')) {
813 $classfortooltip = 'classforajaxtooltip';
814 $dataparams = ' data-params="'.dol_escape_htmltag(json_encode($params)).'"';
815 $label = '';
816 } else {
817 $label = implode($this->getTooltipContentArray($params));
818 }
819
820 $url = dol_buildpath('/mymodule/myobject_card.php', 1).'?id='.$this->id;
821
822 if ($option !== 'nolink') {
823 // Add param to save lastsearch_values or not
824 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
825 if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
826 $add_save_lastsearch_values = 1;
827 }
828 if ($url && $add_save_lastsearch_values) {
829 $url .= '&save_lastsearch_values=1';
830 }
831 }
832
833 $linkclose = '';
834 if (empty($notooltip)) {
835 if (getDolGlobalInt('MAIN_OPTIMIZEFORTEXTBROWSER')) {
836 $label = $langs->trans("ShowMyObject");
837 $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"';
838 }
839 $linkclose .= ($label ? ' title="'.dol_escape_htmltag($label, 1).'"' : ' title="tocomplete"');
840 $linkclose .= $dataparams.' class="'.$classfortooltip.($morecss ? ' '.$morecss : '').'"';
841 } else {
842 $linkclose = ($morecss ? ' class="'.$morecss.'"' : '');
843 }
844
845 if ($option == 'nolink' || empty($url)) {
846 $linkstart = '<span';
847 } else {
848 $linkstart = '<a href="'.$url.'"';
849 }
850 $linkstart .= $linkclose.'>';
851 if ($option == 'nolink' || empty($url)) {
852 $linkend = '</span>';
853 } else {
854 $linkend = '</a>';
855 }
856
857 $result .= $linkstart;
858
859 if (empty($this->showphoto_on_popup)) {
860 if ($withpicto) {
861 $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), (($withpicto != 2) ? 'class="paddingright"' : ''), 0, 0, $notooltip ? 0 : 1);
862 }
863 } else {
864 if ($withpicto) {
865 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
866
867 list($class, $module) = explode('@', $this->picto);
868 $upload_dir = $conf->$module->multidir_output[$conf->entity]."/$class/".dol_sanitizeFileName($this->ref);
869 $filearray = dol_dir_list($upload_dir, "files");
870 $filename = $filearray[0]['name'];
871 if (!empty($filename)) {
872 $pospoint = strpos($filearray[0]['name'], '.');
873
874 $pathtophoto = $class.'/'.$this->ref.'/thumbs/'.substr($filename, 0, $pospoint).'_mini'.substr($filename, $pospoint);
875 if (!getDolGlobalString(strtoupper($module.'_'.$class).'_FORMATLISTPHOTOSASUSERS')) {
876 $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>';
877 } else {
878 $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>';
879 }
880
881 $result .= '</div>';
882 } else {
883 $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'"'), 0, 0, $notooltip ? 0 : 1);
884 }
885 }
886 }
887
888 if ($withpicto != 2) {
889 $result .= $this->ref;
890 }
891
892 $result .= $linkend;
893 //if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : '');
894
895 global $action, $hookmanager;
896 $hookmanager->initHooks(array($this->element.'dao'));
897 $parameters = array('id' => $this->id, 'getnomurl' => &$result);
898 $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
899 if ($reshook > 0) {
900 $result = $hookmanager->resPrint;
901 } else {
902 $result .= $hookmanager->resPrint;
903 }
904
905 return $result;
906 }
907
915 public function getKanbanView($option = '', $arraydata = null)
916 {
917 global $conf, $langs;
918
919 $selected = (empty($arraydata['selected']) ? 0 : $arraydata['selected']);
920
921 $return = '<div class="box-flex-item box-flex-grow-zero">';
922 $return .= '<div class="info-box info-box-sm">';
923 $return .= '<span class="info-box-icon bg-infobox-action">';
924 $return .= img_picto('', $this->picto);
925 $return .= '</span>';
926 $return .= '<div class="info-box-content">';
927 $return .= '<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">'.(method_exists($this, 'getNomUrl') ? $this->getNomUrl() : $this->ref).'</span>';
928 if ($selected >= 0) {
929 $return .= '<input id="cb'.$this->id.'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->id.'"'.($selected ? ' checked="checked"' : '').'>';
930 }
931 if (property_exists($this, 'label')) {
932 $return .= ' <div class="inline-block opacitymedium valignmiddle tdoverflowmax100">'.$this->label.'</div>';
933 }
934 if (property_exists($this, 'thirdparty') && is_object($this->thirdparty)) {
935 $return .= '<br><div class="info-box-ref tdoverflowmax150">'.$this->thirdparty->getNomUrl(1).'</div>';
936 }
937 if (property_exists($this, 'amount')) {
938 $return .= '<br>';
939 $return .= '<span class="info-box-label amount">'.price($this->amount, 0, $langs, 1, -1, -1, $conf->currency).'</span>';
940 }
941 if (method_exists($this, 'getLibStatut')) {
942 $return .= '<br><div class="info-box-status">'.$this->getLibStatut(3).'</div>';
943 }
944 $return .= '</div>';
945 $return .= '</div>';
946 $return .= '</div>';
947
948 return $return;
949 }
950
957 public function getLabelStatus($mode = 0)
958 {
959 return $this->LibStatut($this->status, $mode);
960 }
961
968 public function getLibStatut($mode = 0)
969 {
970 return $this->LibStatut($this->status, $mode);
971 }
972
973 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
981 public function LibStatut($status, $mode = 0)
982 {
983 // phpcs:enable
984 if (is_null($status)) {
985 return '';
986 }
987
988 if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
989 global $langs;
990 //$langs->load("mymodule@mymodule");
991 $this->labelStatus[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft');
992 $this->labelStatus[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Enabled');
993 $this->labelStatus[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('Disabled');
994 $this->labelStatusShort[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft');
995 $this->labelStatusShort[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Enabled');
996 $this->labelStatusShort[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('Disabled');
997 }
998
999 $statusType = 'status'.$status;
1000 //if ($status == self::STATUS_VALIDATED) $statusType = 'status1';
1001 if ($status == self::STATUS_CANCELED) {
1002 $statusType = 'status6';
1003 }
1004
1005 return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode);
1006 }
1007
1014 public function info($id)
1015 {
1016 $sql = "SELECT rowid,";
1017 $sql .= " date_creation as datec, tms as datem";
1018 if (!empty($this->fields['date_validation'])) {
1019 $sql .= ", date_validation as datev";
1020 }
1021 if (!empty($this->fields['fk_user_creat'])) {
1022 $sql .= ", fk_user_creat";
1023 }
1024 if (!empty($this->fields['fk_user_modif'])) {
1025 $sql .= ", fk_user_modif";
1026 }
1027 if (!empty($this->fields['fk_user_valid'])) {
1028 $sql .= ", fk_user_valid";
1029 }
1030 $sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element." as t";
1031 $sql .= " WHERE t.rowid = ".((int) $id);
1032
1033 $result = $this->db->query($sql);
1034 if ($result) {
1035 if ($this->db->num_rows($result)) {
1036 $obj = $this->db->fetch_object($result);
1037
1038 $this->id = $obj->rowid;
1039
1040 if (!empty($this->fields['fk_user_creat'])) {
1041 $this->user_creation_id = $obj->fk_user_creat;
1042 }
1043 if (!empty($this->fields['fk_user_modif'])) {
1044 $this->user_modification_id = $obj->fk_user_modif;
1045 }
1046 if (!empty($this->fields['fk_user_valid'])) {
1047 $this->user_validation_id = $obj->fk_user_valid;
1048 }
1049 $this->date_creation = $this->db->jdate($obj->datec);
1050 $this->date_modification = empty($obj->datem) ? '' : $this->db->jdate($obj->datem);
1051 if (!empty($obj->datev)) {
1052 $this->date_validation = empty($obj->datev) ? '' : $this->db->jdate($obj->datev);
1053 }
1054 }
1055
1056 $this->db->free($result);
1057 } else {
1058 dol_print_error($this->db);
1059 }
1060 }
1061
1068 public function initAsSpecimen()
1069 {
1070 // Set here init that are not commonf fields
1071 // $this->property1 = ...
1072 // $this->property2 = ...
1073
1074 return $this->initAsSpecimenCommon();
1075 }
1076
1082 public function getLinesArray()
1083 {
1084 $this->lines = array();
1085
1086 $objectline = new MyObjectLine($this->db);
1087 $result = $objectline->fetchAll('ASC', 'position', 0, 0, '(fk_myobject:=:'.((int) $this->id).')');
1088
1089 if (is_numeric($result)) {
1090 $this->setErrorsFromObject($objectline);
1091 return $result;
1092 } else {
1093 $this->lines = $result;
1094 return $this->lines;
1095 }
1096 }
1097
1103 public function getNextNumRef()
1104 {
1105 global $langs, $conf;
1106 $langs->load("mymodule@mymodule");
1107
1108 if (!getDolGlobalString('MYMODULE_MYOBJECT_ADDON')) {
1109 $conf->global->MYMODULE_MYOBJECT_ADDON = 'mod_myobject_standard';
1110 }
1111
1112 if (getDolGlobalString('MYMODULE_MYOBJECT_ADDON')) {
1113 $mybool = false;
1114
1115 $file = getDolGlobalString('MYMODULE_MYOBJECT_ADDON').".php";
1116 $classname = getDolGlobalString('MYMODULE_MYOBJECT_ADDON');
1117
1118 // Include file with class
1119 $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
1120 foreach ($dirmodels as $reldir) {
1121 $dir = dol_buildpath($reldir."core/modules/mymodule/");
1122
1123 // Load file with numbering class (if found)
1124 $mybool |= @include_once $dir.$file;
1125 }
1126
1127 if ($mybool === false) {
1128 dol_print_error(null, "Failed to include file ".$file);
1129 return '';
1130 }
1131
1132 if (class_exists($classname)) {
1133 $obj = new $classname();
1134 $numref = $obj->getNextValue($this);
1135
1136 if ($numref != '' && $numref != '-1') {
1137 return $numref;
1138 } else {
1139 $this->error = $obj->error;
1140 //dol_print_error($this->db,get_class($this)."::getNextNumRef ".$obj->error);
1141 return "";
1142 }
1143 } else {
1144 print $langs->trans("Error")." ".$langs->trans("ClassNotFound").' '.$classname;
1145 return "";
1146 }
1147 } else {
1148 print $langs->trans("ErrorNumberingModuleNotSetup", $this->element);
1149 return "";
1150 }
1151 }
1152
1164 public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams = null)
1165 {
1166 global $langs;
1167
1168 $result = 0;
1169 $includedocgeneration = 0;
1170
1171 $langs->load("mymodule@mymodule");
1172
1173 if (!dol_strlen($modele)) {
1174 $modele = 'standard_myobject';
1175
1176 if (!empty($this->model_pdf)) {
1177 $modele = $this->model_pdf;
1178 } elseif (getDolGlobalString('MYOBJECT_ADDON_PDF')) {
1179 $modele = getDolGlobalString('MYOBJECT_ADDON_PDF');
1180 }
1181 }
1182
1183 $modelpath = "core/modules/mymodule/doc/";
1184
1185 if ($includedocgeneration && !empty($modele)) {
1186 $result = $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
1187 }
1188
1189 return $result;
1190 }
1191
1201 public function validateField($fields, $fieldKey, $fieldValue)
1202 {
1203 // Add your own validation rules here.
1204 // ...
1205
1206 return parent::validateField($fields, $fieldKey, $fieldValue);
1207 }
1208
1216 public function doScheduledJob()
1217 {
1218 //global $conf, $langs;
1219
1220 //$conf->global->SYSLOG_FILE = 'DOL_DATA_ROOT/dolibarr_mydedicatedlogfile.log';
1221
1222 $error = 0;
1223 $this->output = '';
1224 $this->error = '';
1225
1226 dol_syslog(__METHOD__." start", LOG_INFO);
1227
1228 $now = dol_now();
1229
1230 $this->db->begin();
1231
1232 // ...
1233
1234 $this->db->commit();
1235
1236 dol_syslog(__METHOD__." end", LOG_INFO);
1237
1238 return $error;
1239 }
1240}
1241
1242
1243require_once DOL_DOCUMENT_ROOT.'/core/class/commonobjectline.class.php';
1244
1249{
1250 // To complete with content of an object MyObjectLine
1251 // We should have a field rowid, fk_myobject and position
1252
1257 public $parent_element = ''; // Example: '' or 'myobject'
1258
1263 public $fk_parent_attribute = ''; // Example: '' or 'fk_myobject'
1264
1270 public function __construct(DoliDB $db)
1271 {
1272 $this->db = $db;
1273
1274 $this->isextrafieldmanaged = 0;
1275 }
1276}
if( $user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
Definition card.php:58
print $langs trans("AuditedSecurityEvents").'</strong >< span class="opacitymedium"></span >< br > status
Or an array listing all the potential status of the object: array: int of the status => translated la...
Definition security.php:636
$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()
Initialise 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.
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.
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 dolibarr global constant string value.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.