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