dolibarr 23.0.3
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';
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
50 public $TRIGGER_PREFIX = 'MYMODULE_MYOBJECT'; // Will be used to build trgiger keys 'MYMODULE_MYOBJECT_MODIFY', ...
51
55 public $table_element = 'mymodule_myobject';
56
60 //public $element_for_permission = 'mymodule';
61
65 public $picto = 'fa-file';
66
70 public $isextrafieldmanaged = 0;
71
76 public $ismultientitymanaged = 0;
77
78
79 const STATUS_DRAFT = 0;
80 const STATUS_VALIDATED = 1;
81 const STATUS_CANCELED = 9;
82
126 // BEGIN MODULEBUILDER PROPERTIES
131 public $fields = array(
132 'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'position' => 1, 'notnull' => 1, 'visible' => 0, 'noteditable' => 1, 'index' => 1, 'css' => 'left', 'comment' => 'Id', 'lang' => 'mymodule@mymodule'),
133 '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', 'lang' => 'mymodule@mymodule'),
134 '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'),
135 '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'),
136 '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'),
137 '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'),
138 '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'),
139 'description' => array('type' => 'text', 'label' => 'Description', 'enabled' => 1, 'position' => 60, 'notnull' => 0, 'visible' => 3, 'validate' => 1, 'lang' => 'mymodule@mymodule'),
140 'note_public' => array('type' => 'html', 'label' => 'NotePublic', 'enabled' => 1, 'position' => 61, 'notnull' => 0, 'visible' => 0, 'cssview' => 'wordbreak', 'validate' => 1, 'lang' => 'mymodule@mymodule'),
141 'note_private' => array('type' => 'html', 'label' => 'NotePrivate', 'enabled' => 1, 'position' => 62, 'notnull' => 0, 'visible' => 0, 'cssview' => 'wordbreak', 'validate' => 1, 'lang' => 'mymodule@mymodule'),
142 'date_creation' => array('type' => 'datetime', 'label' => 'DateCreation', 'enabled' => 1, 'position' => 500, 'notnull' => 1, 'visible' => -2, 'lang' => 'mymodule@mymodule'),
143 'tms' => array('type' => 'timestamp', 'label' => 'DateModification', 'enabled' => 1, 'position' => 501, 'notnull' => 0, 'visible' => -2, 'lang' => 'mymodule@mymodule'),
144 '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'),
145 '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'),
146 'last_main_doc' => array('type' => 'varchar(255)', 'label' => 'LastMainDoc', 'enabled' => 1, 'position' => 600, 'notnull' => 0, 'visible' => 0, 'lang' => 'mymodule@mymodule'),
147 'import_key' => array('type' => 'varchar(14)', 'label' => 'ImportId', 'enabled' => 1, 'position' => 1000, 'notnull' => -1, 'visible' => -2, 'lang' => 'mymodule@mymodule'),
148 'model_pdf' => array('type' => 'varchar(255)', 'label' => 'Model pdf', 'enabled' => 1, 'position' => 1010, 'notnull' => -1, 'visible' => 0, 'lang' => 'mymodule@mymodule'),
149 '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'),
150 );
151
155 public $rowid;
156
160 public $ref;
161
165 public $label;
166
170 public $amount;
171
175 public $socid; // both socid and fk_soc are used
179 public $fk_soc; // both socid and fk_soc are used
180
184 public $status;
185
189 public $fk_user_creat;
190
194 public $fk_user_modif;
195
199 public $last_main_doc;
200
204 public $import_key;
205 // END MODULEBUILDER PROPERTIES
206
207
208 // If this object has a subtable with lines
209
210 // /**
211 // * @var string Name of subtable line
212 // */
213 // public $table_element_line = 'mymodule_myobjectline';
214
215 // /**
216 // * @var string Field name with ID of parent key if this object has a parent, Or Field name of in child tables to link to this record.
217 // */
218 // public $fk_element = 'fk_myobject';
219
220 // /**
221 // * @var string Name of subtable class that manage subtable lines
222 // */
223 // public $class_element_line = 'MyObjectline';
224
225 // /**
226 // * @var array List of child tables. To test if we can delete object.
227 // */
228 // protected $childtables = array('mychildtable' => array('name'=>'MyObject', 'fk_element'=>'fk_myobject'));
229
230 // /**
231 // * @var array List of child tables. To know object to delete on cascade.
232 // * If name matches '@ClassName:FilePathClass:ParentFkFieldName' (the recommended mode) it will
233 // * call method ClassName->deleteByParentField(parentId, 'ParentFkFieldName') to fetch and delete child object.
234 // * Using an array like childtables should not be implemented because a child may have other child, so we must only use the method that call deleteByParentField().
235 // */
236 // protected $childtablesoncascade = array('mymodule_myobjectdet');
237
238 // /**
239 // * @var MyObjectLine[] Array of subtable lines
240 // */
241 // public $lines = array();
242
243
244
250 public function __construct(DoliDB $db)
251 {
252 global $langs;
253
254 $this->db = $db;
255
256 if (!getDolGlobalInt('MAIN_SHOW_TECHNICAL_ID') && isset($this->fields['rowid']) && !empty($this->fields['ref'])) {
257 $this->fields['rowid']['visible'] = 0;
258 }
259 if (!isModEnabled('multicompany') && isset($this->fields['entity'])) {
260 $this->fields['entity']['enabled'] = 0;
261 }
262
263 // Example to show how to set values of fields definition dynamically
264 /*if ($user->hasRight('mymodule', 'myobject', 'read')) {
265 $this->fields['myfield']['visible'] = 1;
266 $this->fields['myfield']['noteditable'] = 0;
267 }*/
268
269 // Unset fields that are disabled
270 foreach ($this->fields as $key => $val) {
271 if (isset($val['enabled']) && empty($val['enabled'])) {
272 unset($this->fields[$key]);
273 }
274 }
275
276 // Translate some data of arrayofkeyval
277 if (is_object($langs)) {
278 foreach ($this->fields as $key => $val) {
279 if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) {
280 foreach ($val['arrayofkeyval'] as $key2 => $val2) {
281 $this->fields[$key]['arrayofkeyval'][$key2] = $langs->trans($val2);
282 }
283 }
284 }
285 }
286 }
287
295 public function create(User $user, $notrigger = 0)
296 {
297 $result = $this->createCommon($user, $notrigger);
298
299 // uncomment lines below if you want to validate object after creation
300 // if ($result > 0) {
301 // $this->fetch($this->id); // needed to retrieve some fields (ie date_creation for masked ref)
302 // $resultupdate = $this->validate($user, $notrigger);
303 // if ($resultupdate < 0) { return $resultupdate; }
304 // }
305
306 return $result;
307 }
308
316 public function createFromClone(User $user, $fromid)
317 {
318 global $langs, $extrafields;
319 $error = 0;
320
321 dol_syslog(__METHOD__, LOG_DEBUG);
322
323 $object = new self($this->db);
324
325 $this->db->begin();
326
327 // Load source object
328 $result = $object->fetchCommon($fromid);
329 if ($result > 0 && !empty($object->table_element_line)) {
330 $object->fetchLines();
331 }
332
333 // get lines so they will be clone
334 //foreach($this->lines as $line)
335 // $line->fetch_optionals();
336
337 // Reset some properties
338 unset($object->id);
339 unset($object->fk_user_creat);
340 unset($object->import_key);
341
342 // Clear fields
343 if (property_exists($object, 'ref')) {
344 $object->ref = empty($this->fields['ref']['default']) ? "Copy_Of_".$object->ref : $this->fields['ref']['default'];
345 }
346 if (property_exists($object, 'label')) {
347 $object->label = empty($this->fields['label']['default']) ? $langs->trans("CopyOf")." ".$object->label : $this->fields['label']['default'];
348 }
349 if (property_exists($object, 'status')) {
350 $object->status = self::STATUS_DRAFT;
351 }
352 if (property_exists($object, 'date_creation')) {
353 $object->date_creation = dol_now();
354 }
355 if (property_exists($object, 'date_modification')) {
356 $object->date_modification = null;
357 }
358 // ...
359 // Clear extrafields that are unique
360 if (is_array($object->array_options) && count($object->array_options) > 0) {
361 $extrafields->fetch_name_optionals_label($this->table_element);
362 foreach ($object->array_options as $key => $option) {
363 $shortkey = preg_replace('/options_/', '', $key);
364 if (!empty($extrafields->attributes[$this->table_element]['unique'][$shortkey])) {
365 //var_dump($key);
366 //var_dump($clonedObj->array_options[$key]); exit;
367 unset($object->array_options[$key]);
368 }
369 }
370 }
371
372 // Create clone
373 $object->context['createfromclone'] = 'createfromclone';
374 $result = $object->createCommon($user);
375 if ($result < 0) {
376 $error++;
378 }
379
380 if (!$error) {
381 // copy internal contacts
382 if ($this->copy_linked_contact($object, 'internal') < 0) {
383 $error++;
384 }
385 }
386
387 if (!$error) {
388 // copy external contacts if same company
389 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
390 if ($this->copy_linked_contact($object, 'external') < 0) {
391 $error++;
392 }
393 }
394 }
395
396 unset($object->context['createfromclone']);
397
398 // End
399 if (!$error) {
400 $this->db->commit();
401 return $object;
402 } else {
403 $this->db->rollback();
404 return -1;
405 }
406 }
407
417 public function fetch($id, $ref = null, $noextrafields = 0, $nolines = 0)
418 {
419 $result = $this->fetchCommon($id, $ref, '', $noextrafields);
420 if ($result > 0 && !empty($this->table_element_line) && empty($nolines)) {
421 $this->fetchLines($noextrafields);
422 }
423 return $result;
424 }
425
432 public function fetchLines($noextrafields = 0)
433 {
434 $this->lines = array();
435
436 $result = $this->fetchLinesCommon('', $noextrafields);
437 return $result;
438 }
439
440
455 public function fetchAll($sortorder = '', $sortfield = '', $limit = 1000, $offset = 0, string $filter = '', $filtermode = 'AND')
456 {
457 dol_syslog(__METHOD__, LOG_DEBUG);
458
459 $records = array();
460
461 $sql = "SELECT ";
462 $sql .= $this->getFieldList('t');
463 $sql .= " FROM ".$this->db->prefix().$this->table_element." as t";
464 if (!empty($this->isextrafieldmanaged) && $this->isextrafieldmanaged == 1) {
465 $sql .= " LEFT JOIN ".$this->db->prefix().$this->table_element."_extrafields as te ON te.fk_object = t.rowid";
466 }
467 if (!empty($this->ismultientitymanaged) && (int) $this->ismultientitymanaged == 1) {
468 $sql .= " WHERE t.entity IN (".getEntity($this->element).")";
469 } elseif (preg_match('/^\w+@\w+$/', (string) $this->ismultientitymanaged)) {
470 $tmparray = explode('@', (string) $this->ismultientitymanaged);
471 $sql .= " LEFT JOIN ".$this->db->prefix().$tmparray[1]." as pt ON t.".$this->db->sanitize($tmparray[0])." = pt.rowid";
472 $sql .= " WHERE pt.entity IN (".getEntity($this->element).")";
473 } else {
474 $sql .= " WHERE 1 = 1";
475 }
476
477 // Manage filter
478 $errormessage = '';
479 $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage);
480 if ($errormessage) {
481 $this->errors[] = $errormessage;
482 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
483 return -1;
484 }
485
486 if (!empty($sortfield)) {
487 $sql .= $this->db->order($sortfield, $sortorder);
488 }
489 if (!empty($limit)) {
490 $sql .= $this->db->plimit($limit, $offset);
491 }
492
493 $resql = $this->db->query($sql);
494 if ($resql) {
495 $num = $this->db->num_rows($resql);
496 $i = 0;
497 while ($i < ($limit ? min($limit, $num) : $num)) {
498 $obj = $this->db->fetch_object($resql);
499
500 $record = new self($this->db);
501 $record->setVarsFromFetchObj($obj);
502
503 if (!empty($record->isextrafieldmanaged)) {
504 $record->fetch_optionals();
505 }
506
507 $records[$record->id] = $record;
508
509 $i++;
510 }
511 $this->db->free($resql);
512
513 return $records;
514 } else {
515 $this->errors[] = 'Error '.$this->db->lasterror();
516 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
517
518 return -1;
519 }
520 }
521
529 public function update(User $user, $notrigger = 0)
530 {
531 return $this->updateCommon($user, $notrigger);
532 }
533
541 public function delete(User $user, $notrigger = 0)
542 {
543 return $this->deleteCommon($user, $notrigger);
544 //return $this->deleteCommon($user, $notrigger, 1);
545 }
546
555 public function deleteLine(User $user, $idline, $notrigger = 0)
556 {
557 if ($this->status < 0) {
558 $this->error = 'ErrorDeleteLineNotAllowedByObjectStatus';
559 return -2;
560 }
561
562 return $this->deleteLineCommon($user, $idline, $notrigger);
563 }
564
565
573 public function validate($user, $notrigger = 0)
574 {
575 global $conf;
576
577 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
578
579 $error = 0;
580
581 // Protection
582 if ($this->status == self::STATUS_VALIDATED) {
583 dol_syslog(get_class($this)."::validate action abandoned: already validated", LOG_WARNING);
584 return 0;
585 }
586
587 /* if (! ((!getDolGlobalInt('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('mymodule', 'myobject', 'write'))
588 || (getDolGlobalInt('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('mymodule', 'myobject_advance', 'validate')))
589 {
590 $this->error='NotEnoughPermissions';
591 dol_syslog(get_class($this)."::valid ".$this->error, LOG_ERR);
592 return -1;
593 }*/
594
595 $now = dol_now();
596
597 $this->db->begin();
598
599 // Define new ref
600 if (preg_match('/^[\‍(]?PROV/i', $this->ref) || empty($this->ref)) { // empty should not happened, but when it occurs, the test save life
601 $num = $this->getNextNumRef();
602 } else {
603 $num = (string) $this->ref;
604 }
605 $this->newref = $num;
606
607 if (!empty($num)) {
608 // Validate
609 $sql = "UPDATE ".$this->db->prefix().$this->table_element;
610 $sql .= " SET ";
611 if (!empty($this->fields['ref'])) {
612 $sql .= " ref = '".$this->db->escape($num)."',";
613 }
614 $sql .= " status = ".self::STATUS_VALIDATED;
615 if (!empty($this->fields['date_validation'])) {
616 $sql .= ", date_validation = '".$this->db->idate($now)."'";
617 }
618 if (!empty($this->fields['fk_user_valid'])) {
619 $sql .= ", fk_user_valid = ".((int) $user->id);
620 }
621 $sql .= " WHERE rowid = ".((int) $this->id);
622
623 dol_syslog(get_class($this)."::validate()", LOG_DEBUG);
624 $resql = $this->db->query($sql);
625 if (!$resql) {
626 dol_print_error($this->db);
627 $this->error = $this->db->lasterror();
628 $error++;
629 }
630
631 if (!$error && !$notrigger) {
632 // Call trigger
633 $result = $this->call_trigger('MYOBJECT_VALIDATE', $user);
634 if ($result < 0) {
635 $error++;
636 }
637 // End call triggers
638 }
639 }
640
641 if (!$error) {
642 $this->oldref = $this->ref;
643
644 // Rename directory if dir was a temporary ref
645 if (preg_match('/^[\‍(]?PROV/i', $this->ref)) {
646 // Now we rename also files into index
647 $sql = 'UPDATE '.$this->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)."'";
648 $sql .= " WHERE filename LIKE '".$this->db->escape($this->ref)."%' AND filepath = 'myobject/".$this->db->escape($this->ref)."' and entity = ".$conf->entity;
649 $resql = $this->db->query($sql);
650 if (!$resql) {
651 $error++;
652 $this->error = $this->db->lasterror();
653 }
654 $sql = 'UPDATE '.$this->db->prefix()."ecm_files set filepath = 'myobject/".$this->db->escape($this->newref)."'";
655 $sql .= " WHERE filepath = 'myobject/".$this->db->escape($this->ref)."' and entity = ".$conf->entity;
656 $resql = $this->db->query($sql);
657 if (!$resql) {
658 $error++;
659 $this->error = $this->db->lasterror();
660 }
661
662 // We rename directory ($this->ref = old ref, $num = new ref) in order not to lose the attachments
663 $oldref = dol_sanitizeFileName($this->ref);
664 $newref = dol_sanitizeFileName($num);
665 $dirsource = $conf->mymodule->dir_output.'/myobject/'.$oldref;
666 $dirdest = $conf->mymodule->dir_output.'/myobject/'.$newref;
667 if (!$error && file_exists($dirsource)) {
668 dol_syslog(get_class($this)."::validate() rename dir ".$dirsource." into ".$dirdest);
669
670 if (@rename($dirsource, $dirdest)) {
671 dol_syslog("Rename ok");
672 // Rename docs starting with $oldref with $newref
673 $listoffiles = dol_dir_list($conf->mymodule->dir_output.'/myobject/'.$newref, 'files', 1, '^'.preg_quote($oldref, '/'));
674 foreach ($listoffiles as $fileentry) {
675 $dirsource = $fileentry['name'];
676 $dirdest = preg_replace('/^'.preg_quote($oldref, '/').'/', $newref, $dirsource);
677 $dirsource = $fileentry['path'].'/'.$dirsource;
678 $dirdest = $fileentry['path'].'/'.$dirdest;
679 @rename($dirsource, $dirdest);
680 }
681 }
682 }
683 }
684 }
685
686 // Set new ref and current status
687 if (!$error) {
688 $this->ref = $num;
689 $this->status = self::STATUS_VALIDATED;
690 }
691
692 if (!$error) {
693 $this->db->commit();
694 return 1;
695 } else {
696 $this->db->rollback();
697 return -1;
698 }
699 }
700
701
709 public function setDraft($user, $notrigger = 0)
710 {
711 // Protection
712 if ($this->status <= self::STATUS_DRAFT) {
713 return 0;
714 }
715
716 /* if (! ((!getDolGlobalInt('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('mymodule','write'))
717 || (getDolGlobalInt('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('mymodule','mymodule_advance','validate'))))
718 {
719 $this->error='Permission denied';
720 return -1;
721 }*/
722
723 return $this->setStatusCommon($user, self::STATUS_DRAFT, $notrigger, 'MYMODULE_MYOBJECT_UNVALIDATE');
724 }
725
733 public function cancel($user, $notrigger = 0)
734 {
735 // Protection
736 if ($this->status != self::STATUS_VALIDATED) {
737 return 0;
738 }
739
740 /* if (! ((!getDolGlobalInt('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('mymodule','write'))
741 || (getDolGlobalInt('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('mymodule','mymodule_advance','validate'))))
742 {
743 $this->error='Permission denied';
744 return -1;
745 }*/
746
747 return $this->setStatusCommon($user, self::STATUS_CANCELED, $notrigger, 'MYMODULE_MYOBJECT_CANCEL');
748 }
749
757 public function reopen($user, $notrigger = 0)
758 {
759 // Protection
760 if ($this->status == self::STATUS_VALIDATED) {
761 return 0;
762 }
763
764 /*if (! ((!getDolGlobalInt('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('mymodule','write'))
765 || (getDolGlobalInt('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('mymodule','mymodule_advance','validate'))))
766 {
767 $this->error='Permission denied';
768 return -1;
769 }*/
770
771 return $this->setStatusCommon($user, self::STATUS_VALIDATED, $notrigger, 'MYMODULE_MYOBJECT_REOPEN');
772 }
773
781 public function getTooltipContentArray($params)
782 {
783 global $langs;
784
785 $datas = [];
786
787 if (getDolGlobalInt('MAIN_OPTIMIZEFORTEXTBROWSER')) {
788 return ['optimize' => $langs->trans("ShowMyObject")];
789 }
790 $datas['picto'] = img_picto('', $this->picto).' <u>'.$langs->trans("MyObject").'</u>';
791 if (isset($this->status)) {
792 $datas['picto'] .= ' '.$this->getLibStatut(5);
793 }
794 if (property_exists($this, 'ref')) {
795 $datas['ref'] = '<br><b>'.$langs->trans('Ref').':</b> '.$this->ref;
796 }
797 if (property_exists($this, 'label')) {
798 $datas['label'] = '<br>'.$langs->trans('Label').':</b> '.$this->label;
799 }
800
801 return $datas;
802 }
803
814 public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
815 {
816 global $conf, $langs, $hookmanager;
817
818 if (!empty($conf->dol_no_mouse_hover)) {
819 $notooltip = 1; // Force disable tooltips
820 }
821
822 $result = '';
823 $params = [
824 'id' => (string) $this->id,
825 'objecttype' => $this->element.($this->module ? '@'.$this->module : ''),
826 'option' => $option,
827 ];
828 $classfortooltip = 'classfortooltip';
829 $dataparams = '';
830 if (getDolGlobalInt('MAIN_ENABLE_AJAX_TOOLTIP')) {
831 $classfortooltip = 'classforajaxtooltip';
832 $dataparams = ' data-params="'.dol_escape_htmltag(json_encode($params)).'"';
833 $label = '';
834 } else {
835 $label = implode($this->getTooltipContentArray($params));
836 }
837
838 $baseurl = dol_buildpath('/mymodule/myobject_card.php', 1);
839 $query = ['id' => $this->id];
840 if ($option !== 'nolink') {
841 // Add param to save lastsearch_values or not
842 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
843 if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
844 $add_save_lastsearch_values = 1;
845 }
846 if ($add_save_lastsearch_values) {
847 $query = array_merge($query, ['save_lastsearch_values' => 1]);
848 }
849 }
850 $url = dolBuildUrl($baseurl, $query);
851
852 $linkclose = '';
853 if (empty($notooltip)) {
854 if (getDolGlobalInt('MAIN_OPTIMIZEFORTEXTBROWSER')) {
855 $label = $langs->trans("ShowMyObject");
856 $linkclose .= ' alt="'.dolPrintHTMLForAttribute($label).'"';
857 }
858 $linkclose .= ($label ? ' title="'.dolPrintHTMLForAttribute($label).'"' : ' title="tocomplete"');
859 $linkclose .= $dataparams.' class="'.$classfortooltip.($morecss ? ' '.$morecss : '').'"';
860 } else {
861 $linkclose = ($morecss ? ' class="'.$morecss.'"' : '');
862 }
863
864 if ($option == 'nolink') {
865 $linkstart = '<span';
866 } else {
867 $linkstart = '<a href="'.$url.'"';
868 }
869 $linkstart .= $linkclose.'>';
870 if ($option == 'nolink') {
871 $linkend = '</span>';
872 } else {
873 $linkend = '</a>';
874 }
875
876 $result .= $linkstart;
877
878 if (empty($this->showphoto_on_popup)) {
879 if ($withpicto) {
880 $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), (($withpicto != 2) ? 'class="paddingright"' : ''), 0, 0, $notooltip ? 0 : 1);
881 }
882 } else {
883 if ($withpicto) {
884 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
885
886 list($class, $module) = explode('@', $this->picto);
887 $upload_dir = $conf->$module->multidir_output[$conf->entity]."/$class/".dol_sanitizeFileName($this->ref);
888 $filearray = dol_dir_list($upload_dir, "files");
889 $filename = $filearray[0]['name'];
890 if (!empty($filename)) {
891 $pospoint = strpos($filearray[0]['name'], '.');
892
893 $pathtophoto = $class.'/'.$this->ref.'/thumbs/'.substr($filename, 0, $pospoint).'_mini'.substr($filename, $pospoint);
894 if (!getDolGlobalString(strtoupper($module.'_'.$class).'_FORMATLISTPHOTOSASUSERS')) {
895 $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>';
896 } else {
897 $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>';
898 }
899
900 $result .= '</div>';
901 } else {
902 $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'"'), 0, 0, $notooltip ? 0 : 1);
903 }
904 }
905 }
906
907 if ($withpicto != 2) {
908 $result .= $this->ref;
909 }
910
911 $result .= $linkend;
912 //if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : '');
913
914 global $action, $hookmanager;
915 $hookmanager->initHooks(array($this->element.'dao'));
916 $parameters = array('id' => $this->id, 'getnomurl' => &$result);
917 $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
918 if ($reshook > 0) {
919 $result = $hookmanager->resPrint;
920 } else {
921 $result .= $hookmanager->resPrint;
922 }
923
924 return $result;
925 }
926
934 public function getKanbanView($option = '', $arraydata = null)
935 {
936 global $conf, $langs;
937
938 $selected = (empty($arraydata['selected']) ? 0 : $arraydata['selected']);
939
940 $return = '<div class="box-flex-item box-flex-grow-zero">';
941 $return .= '<div class="info-box info-box-sm">';
942 $return .= '<span class="info-box-icon bg-infobox-action">';
943 $return .= img_picto('', $this->picto);
944 $return .= '</span>';
945 $return .= '<div class="info-box-content">';
946 $return .= '<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">'.(method_exists($this, 'getNomUrl') ? $this->getNomUrl() : $this->ref).'</span>';
947 if ($selected >= 0) {
948 $return .= '<input id="cb'.$this->id.'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->id.'"'.($selected ? ' checked="checked"' : '').'>';
949 }
950 if (property_exists($this, 'label')) {
951 $return .= ' <div class="inline-block opacitymedium valignmiddle tdoverflowmax100">'.$this->label.'</div>';
952 }
953 if (property_exists($this, 'thirdparty') && is_object($this->thirdparty)) {
954 $return .= '<br><div class="info-box-ref tdoverflowmax150">'.$this->thirdparty->getNomUrl(1).'</div>';
955 }
956 if (property_exists($this, 'amount')) {
957 $return .= '<br>';
958 $return .= '<span class="info-box-label amount">'.price($this->amount, 0, $langs, 1, -1, -1, $conf->currency).'</span>';
959 }
960 if (method_exists($this, 'getLibStatut')) {
961 $return .= '<br><div class="info-box-status">'.$this->getLibStatut(3).'</div>';
962 }
963 $return .= '</div>';
964 $return .= '</div>';
965 $return .= '</div>';
966
967 return $return;
968 }
969
976 public function getLabelStatus($mode = 0)
977 {
978 return $this->LibStatut($this->status, $mode);
979 }
980
987 public function getLibStatut($mode = 0)
988 {
989 return $this->LibStatut($this->status, $mode);
990 }
991
992 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1000 public function LibStatut($status, $mode = 0)
1001 {
1002 // phpcs:enable
1003 if (is_null($status)) {
1004 return '';
1005 }
1006
1007 $paramsBadge = array('badgeParams' => array('attr' => array(
1008 'data-status-element' => $this->element,
1009 'data-status' => (int) $status
1010 )));
1011
1012
1013 if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
1014 global $langs;
1015 //$langs->load("mymodule@mymodule");
1016 $this->labelStatus[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft');
1017 $this->labelStatus[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Enabled');
1018 $this->labelStatus[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('Disabled');
1019 $this->labelStatusShort[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft');
1020 $this->labelStatusShort[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Enabled');
1021 $this->labelStatusShort[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('Disabled');
1022 }
1023
1024 $statusType = 'status'.$status;
1025 //if ($status == self::STATUS_VALIDATED) $statusType = 'status1';
1026 if ($status == self::STATUS_CANCELED) {
1027 $statusType = 'status6';
1028 }
1029
1030 return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode, '', $paramsBadge);
1031 }
1032
1039 public function info($id)
1040 {
1041 $sql = "SELECT t.rowid, t.date_creation as datec";
1042 if (!empty($this->isextrafieldmanaged) && $this->isextrafieldmanaged == 1) {
1043 $sql .= ", GREATEST(t.tms, COALESCE(te.tms, t.tms)) as datem";
1044 } else {
1045 $sql .= ", t.tms as datem";
1046 }
1047 if (!empty($this->fields['date_validation'])) {
1048 $sql .= ", t.date_validation as datev";
1049 }
1050 if (!empty($this->fields['fk_user_creat'])) {
1051 $sql .= ", t.fk_user_creat";
1052 }
1053 if (!empty($this->fields['fk_user_modif'])) {
1054 $sql .= ", t.fk_user_modif";
1055 }
1056 if (!empty($this->fields['fk_user_valid'])) {
1057 $sql .= ", t.fk_user_valid";
1058 }
1059 $sql .= " FROM ".$this->db->prefix().$this->table_element." as t";
1060 if (!empty($this->isextrafieldmanaged) && $this->isextrafieldmanaged == 1) {
1061 $sql .= " LEFT JOIN ".$this->db->prefix().$this->table_element."_extrafields as te ON te.fk_object = t.rowid";
1062 }
1063 $sql .= " WHERE t.rowid = ".((int) $id);
1064
1065 $result = $this->db->query($sql);
1066 if ($result) {
1067 if ($this->db->num_rows($result)) {
1068 $obj = $this->db->fetch_object($result);
1069
1070 $this->id = $obj->rowid;
1071
1072 if (!empty($this->fields['fk_user_creat'])) {
1073 $this->user_creation_id = $obj->fk_user_creat;
1074 }
1075 if (!empty($this->fields['fk_user_modif'])) {
1076 $this->user_modification_id = $obj->fk_user_modif;
1077 }
1078 if (!empty($this->fields['fk_user_valid'])) {
1079 $this->user_validation_id = $obj->fk_user_valid;
1080 }
1081 $this->date_creation = $this->db->jdate($obj->datec);
1082 $this->date_modification = empty($obj->datem) ? '' : $this->db->jdate($obj->datem);
1083 if (!empty($obj->datev)) {
1084 $this->date_validation = empty($obj->datev) ? '' : $this->db->jdate($obj->datev);
1085 }
1086 }
1087
1088 $this->db->free($result);
1089 } else {
1090 dol_print_error($this->db);
1091 }
1092 }
1093
1100 public function initAsSpecimen()
1101 {
1102 // Set here init that are not commonf fields
1103 // $this->property1 = ...
1104 // $this->property2 = ...
1105
1106 return $this->initAsSpecimenCommon();
1107 }
1108
1114 public function getLinesArray()
1115 {
1116 $this->lines = array();
1117
1118 $objectline = new MyObjectLine($this->db);
1119 $result = $objectline->fetchAll('ASC', 'position', 0, 0, '(fk_myobject:=:'.((int) $this->id).')');
1120
1121 if (is_numeric($result)) {
1122 $this->setErrorsFromObject($objectline);
1123 return $result;
1124 } else {
1125 $this->lines = $result;
1126 return $this->lines;
1127 }
1128 }
1129
1135 public function getNextNumRef()
1136 {
1137 global $langs, $conf;
1138 $langs->load("mymodule@mymodule");
1139
1140 if (!getDolGlobalString('MYMODULE_MYOBJECT_ADDON')) {
1141 $conf->global->MYMODULE_MYOBJECT_ADDON = 'mod_myobject_standard';
1142 }
1143
1144 if (getDolGlobalString('MYMODULE_MYOBJECT_ADDON')) {
1145 $mybool = false;
1146
1147 $file = getDolGlobalString('MYMODULE_MYOBJECT_ADDON').".php";
1148 $classname = getDolGlobalString('MYMODULE_MYOBJECT_ADDON');
1149
1150 // Include file with class
1151 $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
1152 foreach ($dirmodels as $reldir) {
1153 $dir = dol_buildpath($reldir."core/modules/mymodule/");
1154
1155 // Load file with numbering class (if found)
1156 $mybool = $mybool || @include_once $dir.$file;
1157 }
1158
1159 if (!$mybool) {
1160 dol_print_error(null, "Failed to include file ".$file);
1161 return '';
1162 }
1163
1164 if (class_exists($classname)) {
1165 $obj = new $classname();
1166 '@phan-var-force ModeleNumRefMyObject $obj';
1167 $numref = $obj->getNextValue($this);
1168
1169 if ($numref != '' && $numref != '-1') {
1170 return $numref;
1171 } else {
1172 $this->error = $obj->error;
1173 //dol_print_error($this->db,get_class($this)."::getNextNumRef ".$obj->error);
1174 return "";
1175 }
1176 } else {
1177 print $langs->trans("Error")." ".$langs->trans("ClassNotFound").' '.$classname;
1178 return "";
1179 }
1180 } else {
1181 print $langs->trans("ErrorNumberingModuleNotSetup", $this->element);
1182 return "";
1183 }
1184 }
1185
1197 public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams = null)
1198 {
1199 global $langs;
1200
1201 $result = 0;
1202 $includedocgeneration = 0;
1203
1204 $langs->load("mymodule@mymodule");
1205
1206 if (!dol_strlen($modele)) {
1207 if (!empty($this->model_pdf)) {
1208 $modele = $this->model_pdf;
1209 } else {
1210 $modele = getDolGlobalString('MYOBJECT_ADDON_PDF', 'standard_myobject');
1211 }
1212 }
1213
1214 $modelpath = "core/modules/mymodule/doc/";
1215
1216 if ($includedocgeneration && !empty($modele)) {
1217 $result = $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
1218 }
1219
1220 return $result;
1221 }
1222
1232 public function validateField($fields, $fieldKey, $fieldValue)
1233 {
1234 // Add your own validation rules here.
1235 // ...
1236
1237 return parent::validateField($fields, $fieldKey, $fieldValue);
1238 }
1239
1247 public function doScheduledJob()
1248 {
1249 //global $conf, $langs;
1250
1251 //$conf->global->SYSLOG_FILE = 'DOL_DATA_ROOT/dolibarr_mydedicatedlogfile.log';
1252
1253 $error = 0;
1254 $this->output = '';
1255 $this->error = '';
1256
1257 dol_syslog(__METHOD__." start", LOG_INFO);
1258
1259 $now = dol_now();
1260
1261 $this->db->begin();
1262
1263 // ...
1264
1265 $this->db->commit();
1266
1267 dol_syslog(__METHOD__." end", LOG_INFO);
1268
1269 return $error;
1270 }
1271}
1272
1273
1274require_once DOL_DOCUMENT_ROOT.'/core/class/commonobjectline.class.php';
1275
1280{
1281 // To complete with content of an object MyObjectLine
1282 // We should have a field rowid, fk_myobject and position
1283
1288 public $parent_element = ''; // Example: '' or 'myobject'
1289
1294 public $fk_parent_attribute = ''; // Example: '' or 'fk_myobject'
1295
1299 public $isextrafieldmanaged = 0;
1300
1305 public $ismultientitymanaged = 0;
1306
1307
1313 public function __construct(DoliDB $db)
1314 {
1315 $this->db = $db;
1316 }
1317}
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
$object ref
Definition info.php:90
Parent class of all other business classes (invoices, contracts, proposals, orders,...
deleteLineCommon(User $user, $idline, $notrigger=0)
Delete a line of object in database.
commonGenerateDocument($modelspath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams=null)
Common function for all objects extending CommonObject for generating documents.
setErrorsFromObject($object)
setErrorsFromObject
createCommon(User $user, $notrigger=0)
Create object in the database.
getFieldList($alias='', $excludefields=array())
Function to concat keys of fields.
updateCommon(User $user, $notrigger=0)
Update object into database.
setStatusCommon($user, $status, $notrigger=0, $triggercode='')
Set to a status.
initAsSpecimenCommon()
Initialise object with example values Id must be 0 if object instance is a specimen.
copy_linked_contact($objFrom, $source='internal')
Copy contact from one element to current.
fetchLinesCommon($morewhere='', $noextrafields=0)
Load object in memory from the database.
fetchCommon($id, $ref=null, $morewhere='', $noextrafields=0)
Load object in memory from the database.
deleteCommon(User $user, $notrigger=0, $forcechilddeletion=0)
Delete object in database.
Parent class for class inheritance lines of business objects This class is useless for the moment so ...
Class to manage Dolibarr database access.
Class for 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:64
dol_now($mode='gmt')
Return date for now.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2, $allowothertags=array())
Show picto whatever it's its name (generic function)
dolBuildUrl($url, $params=[], $addtoken=false)
Return path of url.
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $allowothertags=array())
Show a picto called object_picto (generic function)
dol_sanitizeFileName($str, $newstr='_', $unaccent=1, $includequotes=0, $allowdash=0)
Clean a string to use it as a file name.
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
forgeSQLFromUniversalSearchCriteria($filter, &$errorstr='', $noand=0, $nopar=0, $noerror=0)
forgeSQLFromUniversalSearchCriteria
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dolGetStatus($statusLabel='', $statusLabelShort='', $html='', $statusType='status0', $displayMode=0, $url='', $params=array())
Output the badge of a status.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
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.
if(getDolGlobalString( 'TAKEPOS_SHOW_CUSTOMER')) print $langs trans('Date')." left 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 PaymentTypeShortLIQ right SELECT p pos_change as p datep as p p num_paiement as f pf amount as amount
Definition receipt.php:466