dolibarr 21.0.0-beta
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
108 // BEGIN MODULEBUILDER PROPERTIES
113 public $fields = array(
114 'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'position' => 1, 'notnull' => 1, 'visible' => 0, 'noteditable' => 1, 'index' => 1, 'css' => 'left', 'comment' => 'Id'),
115 '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'),
116 '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,),
117 '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,),
118 '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,),
119 '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,),
120 '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,),
121 'description' => array('type' => 'text', 'label' => 'Description', 'enabled' => 1, 'position' => 60, 'notnull' => 0, 'visible' => 3, 'validate' => 1,),
122 'note_public' => array('type' => 'html', 'label' => 'NotePublic', 'enabled' => 1, 'position' => 61, 'notnull' => 0, 'visible' => 0, 'cssview' => 'wordbreak', 'validate' => 1,),
123 'note_private' => array('type' => 'html', 'label' => 'NotePrivate', 'enabled' => 1, 'position' => 62, 'notnull' => 0, 'visible' => 0, 'cssview' => 'wordbreak', 'validate' => 1,),
124 'date_creation' => array('type' => 'datetime', 'label' => 'DateCreation', 'enabled' => 1, 'position' => 500, 'notnull' => 1, 'visible' => -2,),
125 'tms' => array('type' => 'timestamp', 'label' => 'DateModification', 'enabled' => 1, 'position' => 501, 'notnull' => 0, 'visible' => -2,),
126 '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',),
127 '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',),
128 'last_main_doc' => array('type' => 'varchar(255)', 'label' => 'LastMainDoc', 'enabled' => 1, 'position' => 600, 'notnull' => 0, 'visible' => 0,),
129 'import_key' => array('type' => 'varchar(14)', 'label' => 'ImportId', 'enabled' => 1, 'position' => 1000, 'notnull' => -1, 'visible' => -2,),
130 'model_pdf' => array('type' => 'varchar(255)', 'label' => 'Model pdf', 'enabled' => 1, 'position' => 1010, 'notnull' => -1, 'visible' => 0,),
131 '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,),
132 );
133
137 public $rowid;
138
142 public $ref;
143
147 public $entity;
148
152 public $label;
153
157 public $amount;
158
162 public $socid; // both socid and fk_soc are used
166 public $fk_soc; // both socid and fk_soc are used
167
171 public $status;
172
176 public $fk_user_creat;
177
181 public $fk_user_modif;
182
186 public $last_main_doc;
187
191 public $import_key;
192 // END MODULEBUILDER PROPERTIES
193
194
195 // If this object has a subtable with lines
196
197 // /**
198 // * @var string Name of subtable line
199 // */
200 // public $table_element_line = 'mymodule_myobjectline';
201
202 // /**
203 // * @var string Field with ID of parent key if this object has a parent
204 // */
205 // public $fk_element = 'fk_myobject';
206
207 // /**
208 // * @var string Name of subtable class that manage subtable lines
209 // */
210 // public $class_element_line = 'MyObjectline';
211
212 // /**
213 // * @var array List of child tables. To test if we can delete object.
214 // */
215 // protected $childtables = array('mychildtable' => array('name'=>'MyObject', 'fk_element'=>'fk_myobject'));
216
217 // /**
218 // * @var array List of child tables. To know object to delete on cascade.
219 // * If name matches '@ClassNAme:FilePathClass;ParentFkFieldName' it will
220 // * call method deleteByParentField(parentId, ParentFkFieldName) to fetch and delete child object
221 // */
222 // protected $childtablesoncascade = array('mymodule_myobjectdet');
223
224 // /**
225 // * @var MyObjectLine[] Array of subtable lines
226 // */
227 // public $lines = array();
228
229
230
236 public function __construct(DoliDB $db)
237 {
238 global $langs;
239
240 $this->db = $db;
241 $this->ismultientitymanaged = 0;
242 $this->isextrafieldmanaged = 1;
243
244 if (!getDolGlobalInt('MAIN_SHOW_TECHNICAL_ID') && isset($this->fields['rowid']) && !empty($this->fields['ref'])) {
245 $this->fields['rowid']['visible'] = 0;
246 }
247 if (!isModEnabled('multicompany') && isset($this->fields['entity'])) {
248 $this->fields['entity']['enabled'] = 0;
249 }
250
251 // Example to show how to set values of fields definition dynamically
252 /*if ($user->hasRight('mymodule', 'myobject', 'read')) {
253 $this->fields['myfield']['visible'] = 1;
254 $this->fields['myfield']['noteditable'] = 0;
255 }*/
256
257 // Unset fields that are disabled
258 foreach ($this->fields as $key => $val) {
259 if (isset($val['enabled']) && empty($val['enabled'])) {
260 unset($this->fields[$key]);
261 }
262 }
263
264 // Translate some data of arrayofkeyval
265 if (is_object($langs)) {
266 foreach ($this->fields as $key => $val) {
267 if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) {
268 foreach ($val['arrayofkeyval'] as $key2 => $val2) {
269 $this->fields[$key]['arrayofkeyval'][$key2] = $langs->trans($val2);
270 }
271 }
272 }
273 }
274 }
275
283 public function create(User $user, $notrigger = 0)
284 {
285 $resultcreate = $this->createCommon($user, $notrigger);
286
287 // uncomment lines below if you want to validate object after creation
288 // $this->fetch($this->id); // needed to retrieve some fields (ie date_creation for masked ref)
289 // $resultcreate = $this->validate($user, $notrigger);
290
291 return $resultcreate;
292 }
293
301 public function createFromClone(User $user, $fromid)
302 {
303 global $langs, $extrafields;
304 $error = 0;
305
306 dol_syslog(__METHOD__, LOG_DEBUG);
307
308 $object = new self($this->db);
309
310 $this->db->begin();
311
312 // Load source object
313 $result = $object->fetchCommon($fromid);
314 if ($result > 0 && !empty($object->table_element_line)) {
315 $object->fetchLines();
316 }
317
318 // get lines so they will be clone
319 //foreach($this->lines as $line)
320 // $line->fetch_optionals();
321
322 // Reset some properties
323 unset($object->id);
324 unset($object->fk_user_creat);
325 unset($object->import_key);
326
327 // Clear fields
328 if (property_exists($object, 'ref')) {
329 $object->ref = empty($this->fields['ref']['default']) ? "Copy_Of_".$object->ref : $this->fields['ref']['default'];
330 }
331 if (property_exists($object, 'label')) {
332 $object->label = empty($this->fields['label']['default']) ? $langs->trans("CopyOf")." ".$object->label : $this->fields['label']['default'];
333 }
334 if (property_exists($object, 'status')) {
335 $object->status = self::STATUS_DRAFT;
336 }
337 if (property_exists($object, 'date_creation')) {
338 $object->date_creation = dol_now();
339 }
340 if (property_exists($object, 'date_modification')) {
341 $object->date_modification = null;
342 }
343 // ...
344 // Clear extrafields that are unique
345 if (is_array($object->array_options) && count($object->array_options) > 0) {
346 $extrafields->fetch_name_optionals_label($this->table_element);
347 foreach ($object->array_options as $key => $option) {
348 $shortkey = preg_replace('/options_/', '', $key);
349 if (!empty($extrafields->attributes[$this->table_element]['unique'][$shortkey])) {
350 //var_dump($key);
351 //var_dump($clonedObj->array_options[$key]); exit;
352 unset($object->array_options[$key]);
353 }
354 }
355 }
356
357 // Create clone
358 $object->context['createfromclone'] = 'createfromclone';
359 $result = $object->createCommon($user);
360 if ($result < 0) {
361 $error++;
363 }
364
365 if (!$error) {
366 // copy internal contacts
367 if ($this->copy_linked_contact($object, 'internal') < 0) {
368 $error++;
369 }
370 }
371
372 if (!$error) {
373 // copy external contacts if same company
374 if (!empty($object->socid) && property_exists($this, 'fk_soc') && $this->fk_soc == $object->socid) {
375 if ($this->copy_linked_contact($object, 'external') < 0) {
376 $error++;
377 }
378 }
379 }
380
381 unset($object->context['createfromclone']);
382
383 // End
384 if (!$error) {
385 $this->db->commit();
386 return $object;
387 } else {
388 $this->db->rollback();
389 return -1;
390 }
391 }
392
402 public function fetch($id, $ref = null, $noextrafields = 0, $nolines = 0)
403 {
404 $result = $this->fetchCommon($id, $ref, '', $noextrafields);
405 if ($result > 0 && !empty($this->table_element_line) && empty($nolines)) {
406 $this->fetchLines($noextrafields);
407 }
408 return $result;
409 }
410
417 public function fetchLines($noextrafields = 0)
418 {
419 $this->lines = array();
420
421 $result = $this->fetchLinesCommon('', $noextrafields);
422 return $result;
423 }
424
425
440 public function fetchAll($sortorder = '', $sortfield = '', $limit = 1000, $offset = 0, string $filter = '', $filtermode = 'AND')
441 {
442 dol_syslog(__METHOD__, LOG_DEBUG);
443
444 $records = array();
445
446 $sql = "SELECT ";
447 $sql .= $this->getFieldList('t');
448 $sql .= " FROM ".$this->db->prefix().$this->table_element." as t";
449 if (isset($this->isextrafieldmanaged) && $this->isextrafieldmanaged == 1) {
450 $sql .= " LEFT JOIN ".$this->db->prefix().$this->table_element."_extrafields as te ON te.fk_object = t.rowid";
451 }
452 if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) {
453 $sql .= " WHERE t.entity IN (".getEntity($this->element).")";
454 } else {
455 $sql .= " WHERE 1 = 1";
456 }
457
458 // Manage filter
459 $errormessage = '';
460 $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage);
461 if ($errormessage) {
462 $this->errors[] = $errormessage;
463 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
464 return -1;
465 }
466
467 if (!empty($sortfield)) {
468 $sql .= $this->db->order($sortfield, $sortorder);
469 }
470 if (!empty($limit)) {
471 $sql .= $this->db->plimit($limit, $offset);
472 }
473
474 $resql = $this->db->query($sql);
475 if ($resql) {
476 $num = $this->db->num_rows($resql);
477 $i = 0;
478 while ($i < ($limit ? min($limit, $num) : $num)) {
479 $obj = $this->db->fetch_object($resql);
480
481 $record = new self($this->db);
482 $record->setVarsFromFetchObj($obj);
483
484 if (!empty($record->isextrafieldmanaged)) {
485 $record->fetch_optionals();
486 }
487
488 $records[$record->id] = $record;
489
490 $i++;
491 }
492 $this->db->free($resql);
493
494 return $records;
495 } else {
496 $this->errors[] = 'Error '.$this->db->lasterror();
497 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
498
499 return -1;
500 }
501 }
502
510 public function update(User $user, $notrigger = 0)
511 {
512 return $this->updateCommon($user, $notrigger);
513 }
514
522 public function delete(User $user, $notrigger = 0)
523 {
524 return $this->deleteCommon($user, $notrigger);
525 //return $this->deleteCommon($user, $notrigger, 1);
526 }
527
536 public function deleteLine(User $user, $idline, $notrigger = 0)
537 {
538 if ($this->status < 0) {
539 $this->error = 'ErrorDeleteLineNotAllowedByObjectStatus';
540 return -2;
541 }
542
543 return $this->deleteLineCommon($user, $idline, $notrigger);
544 }
545
546
554 public function validate($user, $notrigger = 0)
555 {
556 global $conf;
557
558 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
559
560 $error = 0;
561
562 // Protection
563 if ($this->status == self::STATUS_VALIDATED) {
564 dol_syslog(get_class($this)."::validate action abandoned: already validated", LOG_WARNING);
565 return 0;
566 }
567
568 /* if (! ((!getDolGlobalInt('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('mymodule', 'myobject', 'write'))
569 || (getDolGlobalInt('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('mymodule', 'myobject_advance', 'validate')))
570 {
571 $this->error='NotEnoughPermissions';
572 dol_syslog(get_class($this)."::valid ".$this->error, LOG_ERR);
573 return -1;
574 }*/
575
576 $now = dol_now();
577
578 $this->db->begin();
579
580 // Define new ref
581 if (!$error && (preg_match('/^[\‍(]?PROV/i', $this->ref) || empty($this->ref))) { // empty should not happened, but when it occurs, the test save life
582 $num = $this->getNextNumRef();
583 } else {
584 $num = $this->ref;
585 }
586 $this->newref = $num;
587
588 if (!empty($num)) {
589 // Validate
590 $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element;
591 $sql .= " SET ";
592 if (!empty($this->fields['ref'])) {
593 $sql .= " ref = '".$this->db->escape($num)."',";
594 }
595 $sql .= " status = ".self::STATUS_VALIDATED;
596 if (!empty($this->fields['date_validation'])) {
597 $sql .= ", date_validation = '".$this->db->idate($now)."'";
598 }
599 if (!empty($this->fields['fk_user_valid'])) {
600 $sql .= ", fk_user_valid = ".((int) $user->id);
601 }
602 $sql .= " WHERE rowid = ".((int) $this->id);
603
604 dol_syslog(get_class($this)."::validate()", LOG_DEBUG);
605 $resql = $this->db->query($sql);
606 if (!$resql) {
607 dol_print_error($this->db);
608 $this->error = $this->db->lasterror();
609 $error++;
610 }
611
612 if (!$error && !$notrigger) {
613 // Call trigger
614 $result = $this->call_trigger('MYOBJECT_VALIDATE', $user);
615 if ($result < 0) {
616 $error++;
617 }
618 // End call triggers
619 }
620 }
621
622 if (!$error) {
623 $this->oldref = $this->ref;
624
625 // Rename directory if dir was a temporary ref
626 if (preg_match('/^[\‍(]?PROV/i', $this->ref)) {
627 // Now we rename also files into index
628 $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)."'";
629 $sql .= " WHERE filename LIKE '".$this->db->escape($this->ref)."%' AND filepath = 'myobject/".$this->db->escape($this->ref)."' and entity = ".$conf->entity;
630 $resql = $this->db->query($sql);
631 if (!$resql) {
632 $error++;
633 $this->error = $this->db->lasterror();
634 }
635 $sql = 'UPDATE '.MAIN_DB_PREFIX."ecm_files set filepath = 'myobject/".$this->db->escape($this->newref)."'";
636 $sql .= " WHERE filepath = 'myobject/".$this->db->escape($this->ref)."' and entity = ".$conf->entity;
637 $resql = $this->db->query($sql);
638 if (!$resql) {
639 $error++;
640 $this->error = $this->db->lasterror();
641 }
642
643 // We rename directory ($this->ref = old ref, $num = new ref) in order not to lose the attachments
644 $oldref = dol_sanitizeFileName($this->ref);
645 $newref = dol_sanitizeFileName($num);
646 $dirsource = $conf->mymodule->dir_output.'/myobject/'.$oldref;
647 $dirdest = $conf->mymodule->dir_output.'/myobject/'.$newref;
648 if (!$error && file_exists($dirsource)) {
649 dol_syslog(get_class($this)."::validate() rename dir ".$dirsource." into ".$dirdest);
650
651 if (@rename($dirsource, $dirdest)) {
652 dol_syslog("Rename ok");
653 // Rename docs starting with $oldref with $newref
654 $listoffiles = dol_dir_list($conf->mymodule->dir_output.'/myobject/'.$newref, 'files', 1, '^'.preg_quote($oldref, '/'));
655 foreach ($listoffiles as $fileentry) {
656 $dirsource = $fileentry['name'];
657 $dirdest = preg_replace('/^'.preg_quote($oldref, '/').'/', $newref, $dirsource);
658 $dirsource = $fileentry['path'].'/'.$dirsource;
659 $dirdest = $fileentry['path'].'/'.$dirdest;
660 @rename($dirsource, $dirdest);
661 }
662 }
663 }
664 }
665 }
666
667 // Set new ref and current status
668 if (!$error) {
669 $this->ref = $num;
670 $this->status = self::STATUS_VALIDATED;
671 }
672
673 if (!$error) {
674 $this->db->commit();
675 return 1;
676 } else {
677 $this->db->rollback();
678 return -1;
679 }
680 }
681
682
690 public function setDraft($user, $notrigger = 0)
691 {
692 // Protection
693 if ($this->status <= self::STATUS_DRAFT) {
694 return 0;
695 }
696
697 /* if (! ((!getDolGlobalInt('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('mymodule','write'))
698 || (getDolGlobalInt('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('mymodule','mymodule_advance','validate'))))
699 {
700 $this->error='Permission denied';
701 return -1;
702 }*/
703
704 return $this->setStatusCommon($user, self::STATUS_DRAFT, $notrigger, 'MYMODULE_MYOBJECT_UNVALIDATE');
705 }
706
714 public function cancel($user, $notrigger = 0)
715 {
716 // Protection
717 if ($this->status != self::STATUS_VALIDATED) {
718 return 0;
719 }
720
721 /* if (! ((!getDolGlobalInt('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('mymodule','write'))
722 || (getDolGlobalInt('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('mymodule','mymodule_advance','validate'))))
723 {
724 $this->error='Permission denied';
725 return -1;
726 }*/
727
728 return $this->setStatusCommon($user, self::STATUS_CANCELED, $notrigger, 'MYMODULE_MYOBJECT_CANCEL');
729 }
730
738 public function reopen($user, $notrigger = 0)
739 {
740 // Protection
741 if ($this->status == self::STATUS_VALIDATED) {
742 return 0;
743 }
744
745 /*if (! ((!getDolGlobalInt('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('mymodule','write'))
746 || (getDolGlobalInt('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('mymodule','mymodule_advance','validate'))))
747 {
748 $this->error='Permission denied';
749 return -1;
750 }*/
751
752 return $this->setStatusCommon($user, self::STATUS_VALIDATED, $notrigger, 'MYMODULE_MYOBJECT_REOPEN');
753 }
754
762 public function getTooltipContentArray($params)
763 {
764 global $langs;
765
766 $datas = [];
767
768 if (getDolGlobalInt('MAIN_OPTIMIZEFORTEXTBROWSER')) {
769 return ['optimize' => $langs->trans("ShowMyObject")];
770 }
771 $datas['picto'] = img_picto('', $this->picto).' <u>'.$langs->trans("MyObject").'</u>';
772 if (isset($this->status)) {
773 $datas['picto'] .= ' '.$this->getLibStatut(5);
774 }
775 if (property_exists($this, 'ref')) {
776 $datas['ref'] = '<br><b>'.$langs->trans('Ref').':</b> '.$this->ref;
777 }
778 if (property_exists($this, 'label')) {
779 $datas['ref'] = '<br>'.$langs->trans('Label').':</b> '.$this->label;
780 }
781
782 return $datas;
783 }
784
795 public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
796 {
797 global $conf, $langs, $hookmanager;
798
799 if (!empty($conf->dol_no_mouse_hover)) {
800 $notooltip = 1; // Force disable tooltips
801 }
802
803 $result = '';
804 $params = [
805 'id' => $this->id,
806 'objecttype' => $this->element.($this->module ? '@'.$this->module : ''),
807 'option' => $option,
808 ];
809 $classfortooltip = 'classfortooltip';
810 $dataparams = '';
811 if (getDolGlobalInt('MAIN_ENABLE_AJAX_TOOLTIP')) {
812 $classfortooltip = 'classforajaxtooltip';
813 $dataparams = ' data-params="'.dol_escape_htmltag(json_encode($params)).'"';
814 $label = '';
815 } else {
816 $label = implode($this->getTooltipContentArray($params));
817 }
818
819 $url = dol_buildpath('/mymodule/myobject_card.php', 1).'?id='.$this->id;
820
821 if ($option !== 'nolink') {
822 // Add param to save lastsearch_values or not
823 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
824 if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
825 $add_save_lastsearch_values = 1;
826 }
827 if ($url && $add_save_lastsearch_values) {
828 $url .= '&save_lastsearch_values=1';
829 }
830 }
831
832 $linkclose = '';
833 if (empty($notooltip)) {
834 if (getDolGlobalInt('MAIN_OPTIMIZEFORTEXTBROWSER')) {
835 $label = $langs->trans("ShowMyObject");
836 $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"';
837 }
838 $linkclose .= ($label ? ' title="'.dol_escape_htmltag($label, 1).'"' : ' title="tocomplete"');
839 $linkclose .= $dataparams.' class="'.$classfortooltip.($morecss ? ' '.$morecss : '').'"';
840 } else {
841 $linkclose = ($morecss ? ' class="'.$morecss.'"' : '');
842 }
843
844 if ($option == 'nolink' || empty($url)) {
845 $linkstart = '<span';
846 } else {
847 $linkstart = '<a href="'.$url.'"';
848 }
849 $linkstart .= $linkclose.'>';
850 if ($option == 'nolink' || empty($url)) {
851 $linkend = '</span>';
852 } else {
853 $linkend = '</a>';
854 }
855
856 $result .= $linkstart;
857
858 if (empty($this->showphoto_on_popup)) {
859 if ($withpicto) {
860 $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), (($withpicto != 2) ? 'class="paddingright"' : ''), 0, 0, $notooltip ? 0 : 1);
861 }
862 } else {
863 if ($withpicto) {
864 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
865
866 list($class, $module) = explode('@', $this->picto);
867 $upload_dir = $conf->$module->multidir_output[$conf->entity]."/$class/".dol_sanitizeFileName($this->ref);
868 $filearray = dol_dir_list($upload_dir, "files");
869 $filename = $filearray[0]['name'];
870 if (!empty($filename)) {
871 $pospoint = strpos($filearray[0]['name'], '.');
872
873 $pathtophoto = $class.'/'.$this->ref.'/thumbs/'.substr($filename, 0, $pospoint).'_mini'.substr($filename, $pospoint);
874 if (!getDolGlobalString(strtoupper($module.'_'.$class).'_FORMATLISTPHOTOSASUSERS')) {
875 $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>';
876 } else {
877 $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>';
878 }
879
880 $result .= '</div>';
881 } else {
882 $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'"'), 0, 0, $notooltip ? 0 : 1);
883 }
884 }
885 }
886
887 if ($withpicto != 2) {
888 $result .= $this->ref;
889 }
890
891 $result .= $linkend;
892 //if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : '');
893
894 global $action, $hookmanager;
895 $hookmanager->initHooks(array($this->element.'dao'));
896 $parameters = array('id' => $this->id, 'getnomurl' => &$result);
897 $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
898 if ($reshook > 0) {
899 $result = $hookmanager->resPrint;
900 } else {
901 $result .= $hookmanager->resPrint;
902 }
903
904 return $result;
905 }
906
914 public function getKanbanView($option = '', $arraydata = null)
915 {
916 global $conf, $langs;
917
918 $selected = (empty($arraydata['selected']) ? 0 : $arraydata['selected']);
919
920 $return = '<div class="box-flex-item box-flex-grow-zero">';
921 $return .= '<div class="info-box info-box-sm">';
922 $return .= '<span class="info-box-icon bg-infobox-action">';
923 $return .= img_picto('', $this->picto);
924 $return .= '</span>';
925 $return .= '<div class="info-box-content">';
926 $return .= '<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">'.(method_exists($this, 'getNomUrl') ? $this->getNomUrl() : $this->ref).'</span>';
927 if ($selected >= 0) {
928 $return .= '<input id="cb'.$this->id.'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->id.'"'.($selected ? ' checked="checked"' : '').'>';
929 }
930 if (property_exists($this, 'label')) {
931 $return .= ' <div class="inline-block opacitymedium valignmiddle tdoverflowmax100">'.$this->label.'</div>';
932 }
933 if (property_exists($this, 'thirdparty') && is_object($this->thirdparty)) {
934 $return .= '<br><div class="info-box-ref tdoverflowmax150">'.$this->thirdparty->getNomUrl(1).'</div>';
935 }
936 if (property_exists($this, 'amount')) {
937 $return .= '<br>';
938 $return .= '<span class="info-box-label amount">'.price($this->amount, 0, $langs, 1, -1, -1, $conf->currency).'</span>';
939 }
940 if (method_exists($this, 'getLibStatut')) {
941 $return .= '<br><div class="info-box-status">'.$this->getLibStatut(3).'</div>';
942 }
943 $return .= '</div>';
944 $return .= '</div>';
945 $return .= '</div>';
946
947 return $return;
948 }
949
956 public function getLabelStatus($mode = 0)
957 {
958 return $this->LibStatut($this->status, $mode);
959 }
960
967 public function getLibStatut($mode = 0)
968 {
969 return $this->LibStatut($this->status, $mode);
970 }
971
972 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
980 public function LibStatut($status, $mode = 0)
981 {
982 // phpcs:enable
983 if (is_null($status)) {
984 return '';
985 }
986
987 if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
988 global $langs;
989 //$langs->load("mymodule@mymodule");
990 $this->labelStatus[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft');
991 $this->labelStatus[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Enabled');
992 $this->labelStatus[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('Disabled');
993 $this->labelStatusShort[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft');
994 $this->labelStatusShort[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Enabled');
995 $this->labelStatusShort[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('Disabled');
996 }
997
998 $statusType = 'status'.$status;
999 //if ($status == self::STATUS_VALIDATED) $statusType = 'status1';
1000 if ($status == self::STATUS_CANCELED) {
1001 $statusType = 'status6';
1002 }
1003
1004 return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode);
1005 }
1006
1013 public function info($id)
1014 {
1015 $sql = "SELECT rowid,";
1016 $sql .= " date_creation as datec, tms as datem";
1017 if (!empty($this->fields['date_validation'])) {
1018 $sql .= ", date_validation as datev";
1019 }
1020 if (!empty($this->fields['fk_user_creat'])) {
1021 $sql .= ", fk_user_creat";
1022 }
1023 if (!empty($this->fields['fk_user_modif'])) {
1024 $sql .= ", fk_user_modif";
1025 }
1026 if (!empty($this->fields['fk_user_valid'])) {
1027 $sql .= ", fk_user_valid";
1028 }
1029 $sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element." as t";
1030 $sql .= " WHERE t.rowid = ".((int) $id);
1031
1032 $result = $this->db->query($sql);
1033 if ($result) {
1034 if ($this->db->num_rows($result)) {
1035 $obj = $this->db->fetch_object($result);
1036
1037 $this->id = $obj->rowid;
1038
1039 if (!empty($this->fields['fk_user_creat'])) {
1040 $this->user_creation_id = $obj->fk_user_creat;
1041 }
1042 if (!empty($this->fields['fk_user_modif'])) {
1043 $this->user_modification_id = $obj->fk_user_modif;
1044 }
1045 if (!empty($this->fields['fk_user_valid'])) {
1046 $this->user_validation_id = $obj->fk_user_valid;
1047 }
1048 $this->date_creation = $this->db->jdate($obj->datec);
1049 $this->date_modification = empty($obj->datem) ? '' : $this->db->jdate($obj->datem);
1050 if (!empty($obj->datev)) {
1051 $this->date_validation = empty($obj->datev) ? '' : $this->db->jdate($obj->datev);
1052 }
1053 }
1054
1055 $this->db->free($result);
1056 } else {
1057 dol_print_error($this->db);
1058 }
1059 }
1060
1067 public function initAsSpecimen()
1068 {
1069 // Set here init that are not commonf fields
1070 // $this->property1 = ...
1071 // $this->property2 = ...
1072
1073 return $this->initAsSpecimenCommon();
1074 }
1075
1081 public function getLinesArray()
1082 {
1083 $this->lines = array();
1084
1085 $objectline = new MyObjectLine($this->db);
1086 $result = $objectline->fetchAll('ASC', 'position', 0, 0, '(fk_myobject:=:'.((int) $this->id).')');
1087
1088 if (is_numeric($result)) {
1089 $this->setErrorsFromObject($objectline);
1090 return $result;
1091 } else {
1092 $this->lines = $result;
1093 return $this->lines;
1094 }
1095 }
1096
1102 public function getNextNumRef()
1103 {
1104 global $langs, $conf;
1105 $langs->load("mymodule@mymodule");
1106
1107 if (!getDolGlobalString('MYMODULE_MYOBJECT_ADDON')) {
1108 $conf->global->MYMODULE_MYOBJECT_ADDON = 'mod_myobject_standard';
1109 }
1110
1111 if (getDolGlobalString('MYMODULE_MYOBJECT_ADDON')) {
1112 $mybool = false;
1113
1114 $file = getDolGlobalString('MYMODULE_MYOBJECT_ADDON').".php";
1115 $classname = getDolGlobalString('MYMODULE_MYOBJECT_ADDON');
1116
1117 // Include file with class
1118 $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
1119 foreach ($dirmodels as $reldir) {
1120 $dir = dol_buildpath($reldir."core/modules/mymodule/");
1121
1122 // Load file with numbering class (if found)
1123 $mybool = $mybool || @include_once $dir.$file;
1124 }
1125
1126 if (!$mybool) {
1127 dol_print_error(null, "Failed to include file ".$file);
1128 return '';
1129 }
1130
1131 if (class_exists($classname)) {
1132 $obj = new $classname();
1133 '@phan-var-force ModeleNumRefMyObject $obj';
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:66
$object ref
Definition info.php:89
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:171
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.
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_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.
global $conf
The following vars must be defined: $type2label $form $conf, $lang, The following vars may also be de...
Definition member.php:79