dolibarr 25.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-2025 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';
28require_once DOL_DOCUMENT_ROOT . '/core/lib/functions.lib.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
51 public $TRIGGER_PREFIX = 'MYMODULE_MYOBJECT'; // Will be used to build trigger keys 'MYMODULE_MYOBJECT_MODIFY', ...
52
56 public $table_element = 'mymodule_myobject';
57
61 //public $element_for_permission = 'mymodule';
62
66 public $picto = 'fa-file';
67
71 public $isextrafieldmanaged = 0;
72
77 public $ismultientitymanaged = 0;
78
79
80 const STATUS_DRAFT = 0;
81 const STATUS_VALIDATED = 1;
82 const STATUS_CANCELED = 9;
83
128 // BEGIN MODULEBUILDER PROPERTIES
133 public $fields = array(
134 'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'position' => 1, 'notnull' => 1, 'visible' => -1, 'noteditable' => 1, 'index' => 1, 'css' => 'left', 'comment' => 'Id', 'lang' => 'mymodule@mymodule'),
135 'ref' => array('type' => 'varchar(128)', 'label' => 'Ref', 'enabled' => 1, 'position' => 15, 'notnull' => 1, 'visible' => 1, 'index' => 1, 'searchall' => 1, 'showoncombobox' => 1, 'validate' => 1, 'comment' => 'Reference of object', 'lang' => 'mymodule@mymodule'),
136 'entity' => array('type' => 'integer', 'label' => 'Entity', 'default' => '1', 'enabled' => 1, 'visible' => 0, 'notnull' => 1, 'position' => 20, 'index' => 1),
137 '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, 'lang' => 'mymodule@mymodule'),
138 '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, 'lang' => 'mymodule@mymodule'),
139 '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, 'lang' => 'mymodule@mymodule'),
140 '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, 'lang' => 'mymodule@mymodule'),
141 '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, 'lang' => 'mymodule@mymodule'),
142 'description' => array('type' => 'text', 'label' => 'Description', 'enabled' => 1, 'position' => 60, 'notnull' => 0, 'visible' => 3, 'validate' => 1, 'lang' => 'mymodule@mymodule'),
143 'note_public' => array('type' => 'html', 'label' => 'NotePublic', 'enabled' => 1, 'position' => 61, 'notnull' => 0, 'visible' => 0, 'cssview' => 'wordbreak', 'validate' => 1, 'lang' => 'mymodule@mymodule'),
144 'note_private' => array('type' => 'html', 'label' => 'NotePrivate', 'enabled' => 1, 'position' => 62, 'notnull' => 0, 'visible' => 0, 'cssview' => 'wordbreak', 'validate' => 1, 'lang' => 'mymodule@mymodule'),
145 'date_creation' => array('type' => 'datetime', 'label' => 'DateCreation', 'enabled' => 1, 'position' => 500, 'notnull' => 1, 'visible' => -2, 'lang' => 'mymodule@mymodule'),
146 'tms' => array('type' => 'timestamp', 'label' => 'DateModification', 'enabled' => 1, 'position' => 501, 'notnull' => 0, 'visible' => -2, 'lang' => 'mymodule@mymodule'),
147 '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', 'lang' => 'mymodule@mymodule'),
148 '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', 'lang' => 'mymodule@mymodule'),
149 'last_main_doc' => array('type' => 'varchar(255)', 'label' => 'LastMainDoc', 'enabled' => 1, 'position' => 600, 'notnull' => 0, 'visible' => 0, 'lang' => 'mymodule@mymodule'),
150 'import_key' => array('type' => 'varchar(14)', 'label' => 'ImportId', 'enabled' => 1, 'position' => 1000, 'notnull' => -1, 'visible' => -2, 'lang' => 'mymodule@mymodule'),
151 'model_pdf' => array('type' => 'varchar(255)', 'label' => 'Model pdf', 'enabled' => 1, 'position' => 1010, 'notnull' => -1, 'visible' => 0, 'lang' => 'mymodule@mymodule'),
152 '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, 'lang' => 'mymodule@mymodule'),
153 );
154
158 public $rowid;
159
163 public $ref;
164
168 public $label;
169
173 public $amount;
174
178 public $socid; // both socid and fk_soc are used
182 public $fk_soc; // both socid and fk_soc are used
183
187 public $status;
188
192 public $fk_user_creat;
193
197 public $fk_user_modif;
198
202 public $last_main_doc;
203
207 public $import_key;
208 // END MODULEBUILDER PROPERTIES
209
210 //BEGIN MODULEBUILDER LINES
211 // If this object has a subtable with lines
212
216 public $table_element_line = 'mymodule_myobjectline';
217
221 public $fk_element = 'fk_myobject';
222
226 public $class_element_line = 'MyObjectline';
227
231 protected $childtables = array('mychildtable' => array('name' => 'MyObject', 'fk_element' => 'fk_myobject'));
232
238 protected $childtablesoncascade = array('mymodule_myobjectdet');
239
243 public $lines = array();
244
245 //END MODULEBUILDER LINES
246
252 public function __construct(DoliDB $db)
253 {
254 global $langs;
255
256 $this->db = $db;
257
258 if (!getDolGlobalInt('MAIN_SHOW_TECHNICAL_ID') && isset($this->fields['rowid']) && !empty($this->fields['ref'])) {
259 $this->fields['rowid']['visible'] = 0;
260 }
261 if (!isModEnabled('multicompany') && isset($this->fields['entity'])) {
262 $this->fields['entity']['enabled'] = 0;
263 }
264
265 // Example to show how to set values of fields definition dynamically
266 /*if ($user->hasRight('mymodule', 'myobject', 'read')) {
267 $this->fields['myfield']['visible'] = 1;
268 $this->fields['myfield']['noteditable'] = 0;
269 }*/
270
271 // Unset fields that are disabled
272 foreach ($this->fields as $key => $val) {
273 if (isset($val['enabled']) && empty($val['enabled'])) {
274 unset($this->fields[$key]);
275 }
276 }
277
278 // Translate some data of arrayofkeyval
279 if (is_object($langs)) {
280 foreach ($this->fields as $key => $val) {
281 if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) {
282 foreach ($val['arrayofkeyval'] as $key2 => $val2) {
283 $this->fields[$key]['arrayofkeyval'][$key2] = $langs->trans($val2);
284 }
285 }
286 }
287 }
288 }
289
297 public function create(User $user, $notrigger = 0)
298 {
299 $result = $this->createCommon($user, $notrigger);
300
301 // uncomment lines below if you want to validate object after creation
302 // if ($result > 0) {
303 // $this->fetch($this->id); // needed to retrieve some fields (ie date_creation for masked ref)
304 // $resultupdate = $this->validate($user, $notrigger);
305 // if ($resultupdate < 0) { return $resultupdate; }
306 // }
307
308 return $result;
309 }
310
318 public function createFromClone(User $user, $fromid)
319 {
320 global $langs, $extrafields;
321 $error = 0;
322
323 dol_syslog(__METHOD__, LOG_DEBUG);
324
325 $object = new self($this->db);
326
327 $this->db->begin();
328
329 // Load source object
330 $result = $object->fetchCommon($fromid);
331 //BEGIN MODULEBUILDER LINES
332 if ($result > 0 && !empty($object->table_element_line)) {
333 $object->fetchLines();
334 }
335
336 // get lines so they will be clone
337 foreach ($this->lines as $line) {
338 $line->fetch_optionals();
339 }
340 //END MODULEBUILDER LINES
341 // Reset some properties
342 unset($object->id);
343 unset($object->fk_user_creat);
344 unset($object->import_key);
345
346 // Clear fields
347 if (property_exists($object, 'ref')) {
348 $object->ref = empty($this->fields['ref']['default']) ? "Copy_Of_".$object->ref : $this->fields['ref']['default'];
349 }
350 if (property_exists($object, 'label')) {
351 $object->label = empty($this->fields['label']['default']) ? $langs->trans("CopyOf")." ".$object->label : $this->fields['label']['default'];
352 }
353 if (property_exists($object, 'status')) {
354 $object->status = self::STATUS_DRAFT;
355 }
356 if (property_exists($object, 'date_creation')) {
357 $object->date_creation = dol_now();
358 }
359 if (property_exists($object, 'date_modification')) {
360 $object->date_modification = null;
361 }
362 // ...
363 // Clear extrafields that are unique
364 if (is_array($object->array_options) && count($object->array_options) > 0) {
365 $extrafields->fetch_name_optionals_label($this->table_element);
366 foreach ($object->array_options as $key => $option) {
367 $shortkey = preg_replace('/options_/', '', $key);
368 if (!empty($extrafields->attributes[$this->table_element]['unique'][$shortkey])) {
369 //var_dump($key);
370 //var_dump($clonedObj->array_options[$key]); exit;
371 unset($object->array_options[$key]);
372 }
373 }
374 }
375
376 // Create clone
377 $object->context['createfromclone'] = 'createfromclone';
378 $result = $object->createCommon($user);
379 if ($result < 0) {
380 $error++;
382 }
383
384 if (!$error) {
385 // copy internal contacts
386 if ($this->copy_linked_contact($object, 'internal') < 0) {
387 $error++;
388 }
389 }
390
391 if (!$error) {
392 // copy external contacts if same company
393 if (!empty($object->socid) && ((property_exists($this, 'fk_soc') && ($this->fk_soc == $object->socid)) || (property_exists($this, 'socid') && ($this->socid == $object->socid)))) { // @phpstan-ignore-line
394 if ($this->copy_linked_contact($object, 'external') < 0) {
395 $error++;
396 }
397 }
398 }
399
400 unset($object->context['createfromclone']);
401
402 // End
403 if (!$error) {
404 $this->db->commit();
405 return $object;
406 } else {
407 $this->db->rollback();
408 return -1;
409 }
410 }
411
421 public function fetch($id, $ref = null, $noextrafields = 0, $nolines = 0)
422 {
423 $result = $this->fetchCommon($id, $ref, '', $noextrafields);
424 //BEGIN MODULEBUILDER LINES
425 if ($result > 0 && !empty($this->table_element_line) && empty($nolines)) {
426 $this->fetchLines($noextrafields);
427 }
428 //END MODULEBUILDER LINES
429 return $result;
430 }
431
432 //BEGIN MODULEBUILDER LINES
439 public function fetchLines($noextrafields = 0)
440 {
441 $this->lines = array();
442
443 $result = $this->fetchLinesCommon('', $noextrafields);
444 return $result;
445 }
446 //END MODULEBUILDER LINES
461 public function fetchAll($sortorder = '', $sortfield = '', $limit = 1000, $offset = 0, string $filter = '', $filtermode = 'AND')
462 {
463 dol_syslog(__METHOD__, LOG_DEBUG);
464
465 $records = array();
466
467 $sql = "SELECT ";
468 $sql .= $this->getFieldList('t');
469 $sql .= " FROM ".$this->db->prefix().$this->table_element." as t";
470 if (!empty($this->isextrafieldmanaged) && $this->isextrafieldmanaged == 1) {
471 $sql .= " LEFT JOIN ".$this->db->prefix().$this->table_element."_extrafields as te ON te.fk_object = t.rowid";
472 }
473 if (!empty($this->ismultientitymanaged) && (int) $this->ismultientitymanaged == 1) {
474 $sql .= " WHERE t.entity IN (".getEntity($this->element).")";
475 } elseif (preg_match('/^\w+@\w+$/', (string) $this->ismultientitymanaged)) {
476 $tmparray = explode('@', (string) $this->ismultientitymanaged);
477 $sql .= " LEFT JOIN ".$this->db->prefix().$this->db->sanitize($tmparray[1])." as pt ON t.".$this->db->sanitize($tmparray[0])." = pt.rowid";
478 $sql .= " WHERE pt.entity IN (".getEntity($this->element).")";
479 } else {
480 $sql .= " WHERE 1 = 1";
481 }
482
483 // Manage filter
484 $errormessage = '';
485 $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage);
486 if ($errormessage) {
487 $this->errors[] = $errormessage;
488 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
489 return -1;
490 }
491
492 if (!empty($sortfield)) {
493 $sql .= $this->db->order($sortfield, $sortorder);
494 }
495 if (!empty($limit)) {
496 $sql .= $this->db->plimit($limit, $offset);
497 }
498
499 $resql = $this->db->query($sql);
500 if ($resql) {
501 $num = $this->db->num_rows($resql);
502 $i = 0;
503 while ($i < ($limit ? min($limit, $num) : $num)) {
504 $obj = $this->db->fetch_object($resql);
505
506 $record = new self($this->db);
507 $record->setVarsFromFetchObj($obj);
508
509 if (!empty($record->isextrafieldmanaged)) {
510 $record->fetch_optionals();
511 }
512
513 $records[$record->id] = $record;
514
515 $i++;
516 }
517 $this->db->free($resql);
518
519 return $records;
520 } else {
521 $this->errors[] = 'Error '.$this->db->lasterror();
522 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
523
524 return -1;
525 }
526 }
527
535 public function update(User $user, $notrigger = 0)
536 {
537 return $this->updateCommon($user, $notrigger);
538 }
539
547 public function delete(User $user, $notrigger = 0)
548 {
549 return $this->deleteCommon($user, $notrigger);
550 //return $this->deleteCommon($user, $notrigger, 1);
551 }
552
553 //BEGIN MODULEBUILDER LINES
562 public function deleteLine(User $user, $idline, $notrigger = 0)
563 {
564 if ($this->status < 0) {
565 $this->error = 'ErrorDeleteLineNotAllowedByObjectStatus';
566 return -2;
567 }
568
569 return $this->deleteLineCommon($user, $idline, $notrigger);
570 }
571 //END MODULEBUILDER LINES
572
573
581 public function validate($user, $notrigger = 0)
582 {
583 global $conf;
584
585 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
586
587 $error = 0;
588
589 // Protection
590 if ($this->status == self::STATUS_VALIDATED) {
591 dol_syslog(get_class($this)."::validate action abandoned: already validated", LOG_WARNING);
592 return 0;
593 }
594
595 /* if (! ((!getDolGlobalInt('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('mymodule', 'myobject', 'write'))
596 || (getDolGlobalInt('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('mymodule', 'myobject_advance', 'validate')))
597 {
598 $this->error='NotEnoughPermissions';
599 dol_syslog(get_class($this)."::valid ".$this->error, LOG_ERR);
600 return -1;
601 }*/
602
603 $now = dol_now();
604
605 $this->db->begin();
606
607 // Define new ref
608 if (preg_match('/^[\‍(]?PROV/i', $this->ref) || empty($this->ref)) { // empty should not happened, but when it occurs, the test save life
609 $num = $this->getNextNumRef();
610 } else {
611 $num = (string) $this->ref;
612 }
613 $this->newref = $num;
614
615 if (!empty($num)) {
616 // Validate
617 $sql = "UPDATE ".$this->db->prefix().$this->table_element;
618 $sql .= " SET ";
619 if (!empty($this->fields['ref'])) {
620 $sql .= " ref = '".$this->db->escape($num)."',";
621 }
622 $sql .= " status = ".self::STATUS_VALIDATED;
623 if (!empty($this->fields['date_validation'])) {
624 $sql .= ", date_validation = '".$this->db->idate($now)."'";
625 }
626 if (!empty($this->fields['fk_user_valid'])) {
627 $sql .= ", fk_user_valid = ".((int) $user->id);
628 }
629 $sql .= " WHERE rowid = ".((int) $this->id);
630
631 dol_syslog(get_class($this)."::validate()", LOG_DEBUG);
632 $resql = $this->db->query($sql);
633 if (!$resql) {
634 dol_print_error($this->db);
635 $this->error = $this->db->lasterror();
636 $error++;
637 }
638
639 if (!$error && !$notrigger) {
640 // Call trigger
641 $result = $this->call_trigger('MYMODULE_MYOBJECT_VALIDATE', $user);
642 if ($result < 0) {
643 $error++;
644 }
645 // End call triggers
646 }
647 }
648
649 if (!$error) {
650 $this->oldref = $this->ref;
651
652 // Rename directory if dir was a temporary ref
653 if (preg_match('/^[\‍(]?PROV/i', $this->ref)) {
654 // Now we rename also files into index
655 $sql = 'UPDATE '.$this->db->prefix()."ecm_files set filename = CONCAT('".$this->db->escape($this->newref)."', SUBSTR(filename, ".(dol_strlen($this->ref) + 1).")), filepath = 'myobject/".$this->db->escape($this->newref)."'";
656 $sql .= " WHERE filename LIKE '".$this->db->escape($this->ref)."%' AND filepath = 'myobject/".$this->db->escape($this->ref)."' and entity = ".((int) $conf->entity);
657 $resql = $this->db->query($sql);
658 if (!$resql) {
659 $error++;
660 $this->error = $this->db->lasterror();
661 }
662 $sql = 'UPDATE '.$this->db->prefix()."ecm_files set filepath = 'myobject/".$this->db->escape($this->newref)."'";
663 $sql .= " WHERE filepath = 'myobject/".$this->db->escape($this->ref)."' and entity = ".((int) $conf->entity);
664 $resql = $this->db->query($sql);
665 if (!$resql) {
666 $error++;
667 $this->error = $this->db->lasterror();
668 }
669
670 // We rename directory ($this->ref = old ref, $num = new ref) in order not to lose the attachments
671 $oldref = dol_sanitizeFileName($this->ref);
672 $newref = dol_sanitizeFileName($num);
673 $dirsource = $conf->mymodule->dir_output.'/myobject/'.$oldref;
674 $dirdest = $conf->mymodule->dir_output.'/myobject/'.$newref;
675 if (!$error && file_exists($dirsource)) {
676 dol_syslog(get_class($this)."::validate() rename dir ".$dirsource." into ".$dirdest);
677
678 if (@rename($dirsource, $dirdest)) {
679 dol_syslog("Rename ok");
680 // Rename docs starting with $oldref with $newref
681 $listoffiles = dol_dir_list($conf->mymodule->dir_output.'/myobject/'.$newref, 'files', 1, '^'.preg_quote($oldref, '/'));
682 foreach ($listoffiles as $fileentry) {
683 $dirsource = $fileentry['name'];
684 $dirdest = preg_replace('/^'.preg_quote($oldref, '/').'/', $newref, $dirsource);
685 $dirsource = $fileentry['path'].'/'.$dirsource;
686 $dirdest = $fileentry['path'].'/'.$dirdest;
687 @rename($dirsource, $dirdest);
688 }
689 }
690 }
691 }
692 }
693
694 // Set new ref and current status
695 if (!$error) {
696 $this->ref = $num;
697 $this->status = self::STATUS_VALIDATED;
698 }
699
700 if (!$error) {
701 $this->db->commit();
702 return 1;
703 } else {
704 $this->db->rollback();
705 return -1;
706 }
707 }
708
709
717 public function setDraft($user, $notrigger = 0)
718 {
719 // Protection
720 if ($this->status <= self::STATUS_DRAFT) {
721 return 0;
722 }
723
724 /* if (! ((!getDolGlobalInt('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('mymodule','write'))
725 || (getDolGlobalInt('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('mymodule','mymodule_advance','validate'))))
726 {
727 $this->error='Permission denied';
728 return -1;
729 }*/
730
731 return $this->setStatusCommon($user, self::STATUS_DRAFT, $notrigger, 'MYMODULE_MYOBJECT_UNVALIDATE');
732 }
733
741 public function cancel($user, $notrigger = 0)
742 {
743 // Protection
744 if ($this->status != self::STATUS_VALIDATED) {
745 return 0;
746 }
747
748 /* if (! ((!getDolGlobalInt('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('mymodule','write'))
749 || (getDolGlobalInt('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('mymodule','mymodule_advance','validate'))))
750 {
751 $this->error='Permission denied';
752 return -1;
753 }*/
754
755 return $this->setStatusCommon($user, self::STATUS_CANCELED, $notrigger, 'MYMODULE_MYOBJECT_CANCEL');
756 }
757
765 public function reopen($user, $notrigger = 0)
766 {
767 // Protection
768 if ($this->status == self::STATUS_VALIDATED) {
769 return 0;
770 }
771
772 /*if (! ((!getDolGlobalInt('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('mymodule','write'))
773 || (getDolGlobalInt('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('mymodule','mymodule_advance','validate'))))
774 {
775 $this->error='Permission denied';
776 return -1;
777 }*/
778
779 return $this->setStatusCommon($user, self::STATUS_VALIDATED, $notrigger, 'MYMODULE_MYOBJECT_REOPEN');
780 }
781
789 public function getTooltipContentArray($params)
790 {
791 global $langs;
792
793 $datas = [];
794
795 if (getDolGlobalInt('MAIN_OPTIMIZEFORTEXTBROWSER')) {
796 return ['optimize' => $langs->trans("ShowMyObject")];
797 }
798 $datas['picto'] = img_picto('', $this->picto).' <u>'.$langs->trans("MyObject").'</u>';
799 if (isset($this->status)) {
800 $datas['picto'] .= ' '.$this->getLibStatut(5);
801 }
802 if (property_exists($this, 'ref')) {
803 $datas['ref'] = '<br><b>'.$langs->trans('Ref').':</b> '.$this->ref;
804 }
805 if (property_exists($this, 'label')) {
806 $datas['label'] = '<br>'.$langs->trans('Label').':</b> '.$this->label;
807 }
808
809 return $datas;
810 }
811
822 public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
823 {
824 global $conf, $langs, $hookmanager;
825
826 if (!empty($conf->dol_no_mouse_hover)) {
827 $notooltip = 1; // Force disable tooltips
828 }
829
830 $result = '';
831 $params = [
832 'id' => (string) $this->id,
833 'objecttype' => $this->element.($this->module ? '@'.$this->module : ''),
834 'option' => $option,
835 ];
836 $classfortooltip = 'classfortooltip';
837 $dataparams = '';
838 if (getDolGlobalInt('MAIN_ENABLE_AJAX_TOOLTIP')) {
839 $classfortooltip = 'classforajaxtooltip';
840 $dataparams = ' data-params="'.dol_escape_htmltag(json_encode($params)).'"';
841 $label = '';
842 } else {
843 $label = implode($this->getTooltipContentArray($params));
844 }
845
846 $baseurl = dol_buildpath('/mymodule/myobject_card.php', 1);
847 $query = ['id' => $this->id];
848 if ($option !== 'nolink') {
849 // Add param to save lastsearch_values or not
850 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
851 if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
852 $add_save_lastsearch_values = 1;
853 }
854 if ($add_save_lastsearch_values) {
855 $query = array_merge($query, ['save_lastsearch_values' => 1]);
856 }
857 }
858 $url = dolBuildUrl($baseurl, $query);
859
860 $linkclose = '';
861 if (empty($notooltip)) {
862 if (getDolGlobalInt('MAIN_OPTIMIZEFORTEXTBROWSER')) {
863 $label = $langs->trans("ShowMyObject");
864 $linkclose .= ' alt="'.dolPrintHTMLForAttribute($label).'"';
865 }
866 $linkclose .= ($label ? ' title="'.dolPrintHTMLForAttribute($label).'"' : ' title="tocomplete"');
867 $linkclose .= $dataparams.' class="'.$classfortooltip.($morecss ? ' '.$morecss : '').'"';
868 } else {
869 $linkclose = ($morecss ? ' class="'.$morecss.'"' : '');
870 }
871
872 if ($option == 'nolink') {
873 $linkstart = '<span';
874 } else {
875 $linkstart = '<a href="'.$url.'"';
876 }
877 $linkstart .= $linkclose.'>';
878 if ($option == 'nolink') {
879 $linkend = '</span>';
880 } else {
881 $linkend = '</a>';
882 }
883
884 $result .= $linkstart;
885
886 if (empty($this->showphoto_on_popup)) {
887 if ($withpicto) {
888 $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), (($withpicto != 2) ? 'class="paddingright"' : ''), 0, 0, $notooltip ? 0 : 1);
889 }
890 } else {
891 if ($withpicto) {
892 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
893
894 list($class, $module) = explode('@', $this->picto);
895 $upload_dir = $conf->$module->multidir_output[$conf->entity]."/$class/".dol_sanitizeFileName($this->ref);
896 $filearray = dol_dir_list($upload_dir, "files");
897 $filename = $filearray[0]['name'];
898 if (!empty($filename)) {
899 $pospoint = strpos($filearray[0]['name'], '.');
900
901 $pathtophoto = $class.'/'.$this->ref.'/thumbs/'.dol_substr($filename, 0, $pospoint).'_mini'.dol_substr($filename, $pospoint);
902 if (!getDolGlobalString(dol_strtoupper($module.'_'.$class).'_FORMATLISTPHOTOSASUSERS')) {
903 $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>';
904 } else {
905 $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>';
906 }
907
908 $result .= '</div>';
909 } else {
910 $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'"'), 0, 0, $notooltip ? 0 : 1);
911 }
912 }
913 }
914
915 if ($withpicto != 2) {
916 $result .= $this->ref;
917 }
918
919 $result .= $linkend;
920 //if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : '');
921
922 global $action, $hookmanager;
923 $hookmanager->initHooks(array($this->element.'dao'));
924 $parameters = array('id' => $this->id, 'getnomurl' => &$result);
925 $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
926 if ($reshook > 0) {
927 $result = $hookmanager->resPrint;
928 } else {
929 $result .= $hookmanager->resPrint;
930 }
931
932 return $result;
933 }
934
942 public function getKanbanView($option = '', $arraydata = null)
943 {
944 global $conf, $langs;
945
946 $selected = (empty($arraydata['selected']) ? 0 : $arraydata['selected']);
947
948 $return = '<div class="box-flex-item box-flex-grow-zero">';
949 $return .= '<div class="info-box info-box-sm">';
950 $return .= '<span class="info-box-icon bg-infobox-action">';
951 $return .= img_picto('', $this->picto);
952 $return .= '</span>';
953 $return .= '<div class="info-box-content">';
954 $return .= '<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">'.(method_exists($this, 'getNomUrl') ? $this->getNomUrl() : $this->ref).'</span>';
955 if ($selected >= 0) {
956 $return .= '<input id="cb'.$this->id.'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->id.'"'.($selected ? ' checked="checked"' : '').'>';
957 }
958 if (property_exists($this, 'label')) {
959 $return .= ' <div class="inline-block opacitymedium valignmiddle tdoverflowmax100">'.$this->label.'</div>';
960 }
961 if (property_exists($this, 'thirdparty') && is_object($this->thirdparty)) {
962 $return .= '<br><div class="info-box-ref tdoverflowmax150">'.$this->thirdparty->getNomUrl(1).'</div>';
963 }
964 if (property_exists($this, 'amount')) {
965 $return .= '<br>';
966 $return .= '<span class="info-box-label amount">'.price($this->amount, 0, $langs, 1, -1, -1, $conf->currency).'</span>';
967 }
968 if (method_exists($this, 'getLibStatut')) {
969 $return .= '<br><div class="info-box-status">'.$this->getLibStatut(3).'</div>';
970 }
971 $return .= '</div>';
972 $return .= '</div>';
973 $return .= '</div>';
974
975 return $return;
976 }
977
984 public function getLabelStatus($mode = 0)
985 {
986 return $this->LibStatut($this->status, $mode);
987 }
988
995 public function getLibStatut($mode = 0)
996 {
997 return $this->LibStatut($this->status, $mode);
998 }
999
1000 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1008 public function LibStatut($status, $mode = 0)
1009 {
1010 // phpcs:enable
1011 if (is_null($status)) {
1012 return '';
1013 }
1014
1015 $paramsBadge = array('badgeParams' => array('attr' => array(
1016 'data-status-element' => $this->element,
1017 'data-status' => (int) $status
1018 )));
1019
1020
1021 if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
1022 global $langs;
1023 //$langs->load("mymodule@mymodule");
1024 // Build status labels from the 'status' field arrayofkeyval so that the badge (LibStatut),
1025 // the list filter and the select all show the same, configurable labels.
1026 if (!empty($this->fields['status']['arrayofkeyval']) && is_array($this->fields['status']['arrayofkeyval'])) {
1027 foreach ($this->fields['status']['arrayofkeyval'] as $statuskey => $statuslabel) {
1028 $this->labelStatus[$statuskey] = $langs->transnoentitiesnoconv($statuslabel);
1029 $this->labelStatusShort[$statuskey] = $langs->transnoentitiesnoconv($statuslabel);
1030 }
1031 }
1032 }
1033
1034 $statusType = 'status'.$status;
1035 //if ($status == self::STATUS_VALIDATED) $statusType = 'status1';
1036 if ($status == self::STATUS_CANCELED) {
1037 $statusType = 'status6';
1038 }
1039
1040 return dolGetStatus($this->labelStatus[$status] ?? '', $this->labelStatusShort[$status] ?? '', '', $statusType, $mode, '', $paramsBadge);
1041 }
1042
1049 public function info($id)
1050 {
1051 $sql = "SELECT t.rowid, t.date_creation as datec";
1052 if (!empty($this->isextrafieldmanaged) && $this->isextrafieldmanaged == 1) {
1053 $sql .= ", GREATEST(t.tms, COALESCE(te.tms, t.tms)) as datem";
1054 } else {
1055 $sql .= ", t.tms as datem";
1056 }
1057 if (!empty($this->fields['date_validation'])) {
1058 $sql .= ", t.date_validation as datev";
1059 }
1060 if (!empty($this->fields['fk_user_creat'])) {
1061 $sql .= ", t.fk_user_creat";
1062 }
1063 if (!empty($this->fields['fk_user_modif'])) {
1064 $sql .= ", t.fk_user_modif";
1065 }
1066 if (!empty($this->fields['fk_user_valid'])) {
1067 $sql .= ", t.fk_user_valid";
1068 }
1069 $sql .= " FROM ".$this->db->prefix().$this->table_element." as t";
1070 if (!empty($this->isextrafieldmanaged) && $this->isextrafieldmanaged == 1) {
1071 $sql .= " LEFT JOIN ".$this->db->prefix().$this->table_element."_extrafields as te ON te.fk_object = t.rowid";
1072 }
1073 $sql .= " WHERE t.rowid = ".((int) $id);
1074
1075 $result = $this->db->query($sql);
1076 if ($result) {
1077 if ($this->db->num_rows($result)) {
1078 $obj = $this->db->fetch_object($result);
1079
1080 $this->id = $obj->rowid;
1081
1082 if (!empty($this->fields['fk_user_creat'])) {
1083 $this->user_creation_id = $obj->fk_user_creat;
1084 }
1085 if (!empty($this->fields['fk_user_modif'])) {
1086 $this->user_modification_id = $obj->fk_user_modif;
1087 }
1088 if (!empty($this->fields['fk_user_valid'])) {
1089 $this->user_validation_id = $obj->fk_user_valid;
1090 }
1091 $this->date_creation = $this->db->jdate($obj->datec);
1092 $this->date_modification = empty($obj->datem) ? '' : $this->db->jdate($obj->datem);
1093 if (!empty($obj->datev)) {
1094 $this->date_validation = empty($obj->datev) ? '' : $this->db->jdate($obj->datev);
1095 }
1096 }
1097
1098 $this->db->free($result);
1099 } else {
1100 dol_print_error($this->db);
1101 }
1102 }
1103
1110 public function initAsSpecimen()
1111 {
1112 // Set here init that are not commonf fields
1113 // $this->property1 = ...
1114 // $this->property2 = ...
1115
1116 return $this->initAsSpecimenCommon();
1117 }
1118
1119 //BEGIN MODULEBUILDER LINES
1125 public function getLinesArray()
1126 {
1127 $this->lines = array();
1128
1129 $objectline = new MyObjectLine($this->db);
1130 $result = $objectline->fetchAll('ASC', 'position', 0, 0, '(fk_myobject:=:'.((int) $this->id).')');
1131
1132 if (is_numeric($result)) {
1133 $this->setErrorsFromObject($objectline);
1134 return $result;
1135 } else {
1137 $this->lines = $result;
1138 return $this->lines;
1139 }
1140 }
1141 //END MODULEBUILDER LINES
1142
1148 public function getNextNumRef()
1149 {
1150 global $langs, $conf;
1151 $langs->load("mymodule@mymodule");
1152
1153 if (!getDolGlobalString('MYMODULE_MYOBJECT_ADDON')) {
1154 $conf->global->MYMODULE_MYOBJECT_ADDON = 'mod_myobject_standard';
1155 }
1156
1157 if (getDolGlobalString('MYMODULE_MYOBJECT_ADDON')) {
1158 $mybool = false;
1159
1160 $file = getDolGlobalString('MYMODULE_MYOBJECT_ADDON').".php";
1161 $classname = getDolGlobalString('MYMODULE_MYOBJECT_ADDON');
1162
1163 // Include file with class
1164 $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
1165 foreach ($dirmodels as $reldir) {
1166 $dir = dol_buildpath($reldir."core/modules/mymodule/");
1167
1168 // Load file with numbering class (if found)
1169 $mybool = $mybool || @include_once $dir.$file;
1170 }
1171
1172 if (!$mybool) {
1173 dol_print_error(null, "Failed to include file ".$file);
1174 return '';
1175 }
1176
1177 if (class_exists($classname)) {
1178 $obj = new $classname();
1179 '@phan-var-force ModeleNumRefMyObject $obj';
1180 $numref = $obj->getNextValue($this);
1181
1182 if ($numref != '' && $numref != '-1') {
1183 return $numref;
1184 } else {
1185 $this->error = $obj->error;
1186 //dol_print_error($this->db,get_class($this)."::getNextNumRef ".$obj->error);
1187 return "";
1188 }
1189 } else {
1190 print $langs->trans("Error")." ".$langs->trans("ClassNotFound").' '.$classname;
1191 return "";
1192 }
1193 } else {
1194 print $langs->trans("ErrorNumberingModuleNotSetup", $this->element);
1195 return "";
1196 }
1197 }
1198
1210 public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams = null)
1211 {
1212 global $langs;
1213
1214 $result = 0;
1215 $includedocgeneration = 0;
1216
1217 $langs->load("mymodule@mymodule");
1218
1219 if (!dol_strlen($modele)) {
1220 if (!empty($this->model_pdf)) {
1221 $modele = $this->model_pdf;
1222 } else {
1223 $modele = getDolGlobalString('MYOBJECT_ADDON_PDF', 'standard_myobject');
1224 }
1225 }
1226
1227 $modelpath = "core/modules/mymodule/doc/";
1228
1229 if ($includedocgeneration && !empty($modele)) {
1230 $result = $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
1231 }
1232
1233 return $result;
1234 }
1235
1245 public function validateField($fields, $fieldKey, $fieldValue)
1246 {
1247 // Add your own validation rules here.
1248 // ...
1249
1250 return parent::validateField($fields, $fieldKey, $fieldValue);
1251 }
1252
1260 public function doScheduledJob()
1261 {
1262 //global $conf, $langs;
1263
1264 //$conf->global->SYSLOG_FILE = 'DOL_DATA_ROOT/dolibarr_mydedicatedlogfile.log';
1265
1266 $error = 0;
1267 $this->output = '';
1268 $this->error = '';
1269
1270 dol_syslog(__METHOD__." start", LOG_INFO);
1271
1272 //$now = dol_now();
1273
1274 $this->db->begin();
1275
1276 // ...
1277
1278 $this->db->commit();
1279
1280 dol_syslog(__METHOD__." end", LOG_INFO);
1281
1282 return $error;
1283 }
1284}
1285
1286
1287require_once DOL_DOCUMENT_ROOT.'/core/class/commonobjectline.class.php';
1288//BEGIN MODULEBUILDER LINES
1293{
1294 // To complete with content of an object MyObjectLine
1295 // We should have a field rowid, fk_myobject and position
1296
1301 public $parent_element = ''; // Example: '' or 'myobject'
1302
1307 public $fk_parent_attribute = ''; // Example: '' or 'fk_myobject'
1308
1312 public $isextrafieldmanaged = 0;
1313
1318 public $ismultientitymanaged = 0;
1319
1320
1326 public function __construct(DoliDB $db)
1327 {
1328 $this->db = $db;
1329 }
1330}
1331//END MODULEBUILDER LINES
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
$object ref
Definition info.php:90
deleteLineCommon(User $user, $idline, $notrigger=0)
Delete a line of object in database.
commonGenerateDocument($modelspath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams=null)
Common function for all objects extending CommonObject for generating documents.
setErrorsFromObject($object)
setErrorsFromObject
createCommon(User $user, $notrigger=0)
Create object in the database.
getFieldList($alias='', $excludefields=array())
Function to concat keys of fields.
updateCommon(User $user, $notrigger=0)
Update object into database.
setStatusCommon($user, $status, $notrigger=0, $triggercode='')
Set to a status.
initAsSpecimenCommon()
Initialise object with example values Id must be 0 if object instance is a specimen.
copy_linked_contact($objFrom, $source='internal')
Copy contact from one element to current.
fetchLinesCommon($morewhere='', $noextrafields=0)
Load object in memory from the database.
fetchCommon($id, $ref=null, $morewhere='', $noextrafields=0)
Load object in memory from the database.
deleteCommon(User $user, $notrigger=0, $forcechilddeletion=0)
Delete object in database.
Parent class for class inheritance lines of business objects This class is useless for the moment so ...
Class to manage Dolibarr database access.
Class for 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:169
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $conf
The main.inc.php has been included so the following variable are now defined:
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:65
dol_now($mode='gmt')
Return date for now.
dolBuildUrl($url, $params=[], $addtoken=false, $anchor='')
Return path of url.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1, $includequotes=0, $allowdash=0)
Clean a string to use it as a file name.
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
forgeSQLFromUniversalSearchCriteria($filter, &$errorstr='', $noand=0, $nopar=0, $noerror=0, $forbiddenfields=array())
forgeSQLFromUniversalSearchCriteria
dol_strtoupper($string, $encoding="UTF-8")
Convert a string to upper.
dol_substr($string, $start, $length=null, $stringencoding='', $trunconbytes=0)
Make a substring.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
print $langs trans('Date')." left Ref Label right Qty right Price right TotalHT right TotalTTC right right right right right right right right right centpercent right TotalHT right n right VAT right n right TotalVAT right n No sujeto a RE IRPF right TotalLT1 right n right TotalLT2 right n right TotalTTC right n takeposcustomercurrency takeposcustomercurrency takeposcustomercurrency takeposcustomercurrency right TotalTTC takeposcustomercurrency right takeposcustomercurrency n right Paid right PaymentTypeShortLIQ right SELECT p pos_change as p datep as p p num_paiement as f pf amount as amount
Definition receipt.php:494