dolibarr  20.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-2024 Frédéric France <frederic.france@free.fr>
4  * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
5  * Copyright (C) ---Put here your own copyright and developer email---
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program. If not, see <https://www.gnu.org/licenses/>.
19  */
20 
27 // Put here all includes required by your class file
28 require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
29 //require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php';
30 //require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php';
31 
35 class MyObject extends CommonObject
36 {
40  public $module = 'mymodule';
41 
45  public $element = 'myobject';
46 
50  public $table_element = 'mymodule_myobject';
51 
55  //public $element_for_permission = 'mymodule';
56 
61  public $ismultientitymanaged = 0;
62 
66  public $isextrafieldmanaged = 1;
67 
71  public $picto = 'fa-file';
72 
73 
74  const STATUS_DRAFT = 0;
75  const STATUS_VALIDATED = 1;
76  const STATUS_CANCELED = 9;
77 
117  // BEGIN MODULEBUILDER PROPERTIES
121  public $fields = array(
122  'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'visible' => -2, 'noteditable' => 1, 'notnull' => 1, 'index' => 1, 'position' => 1, 'comment' => 'Id', 'css' => 'left'),
123  'entity' => array('type' => 'integer', 'label' => 'Entity', 'enabled' => 1, 'visible' => 0, 'notnull' => 1, 'default' => 1, 'index' => 1, 'position' => 10),
124  'ref' => array('type' => 'varchar(128)', 'label' => 'Ref', 'enabled' => 1, 'visible' => 1, 'noteditable' => 0, 'default' => '', 'notnull' => 1, 'showoncombobox' => 1, 'index' => 1, 'position' => 20, 'searchall' => 1, 'comment' => 'Reference of object', 'validate' => 1),
125  'label' => array('type' => 'varchar(255)', 'label' => 'Label', 'enabled' => 1, 'visible' => 1, 'position' => 30, 'searchall' => 1, 'css' => 'minwidth300', 'cssview' => 'wordbreak', 'help' => 'Help text', 'showoncombobox' => 2, 'validate' => 1, 'alwayseditable' => 1),
126  'amount' => array('type' => 'price', 'label' => 'Amount', 'enabled' => 1, 'visible' => 1, 'default' => 'null', 'position' => 40, 'searchall' => 0, 'isameasure' => 1, 'help' => 'Help text for amount', 'validate' => 1),
127  'qty' => array('type' => 'real', 'label' => 'Qty', 'enabled' => 1, 'visible' => 1, 'default' => '0', 'position' => 45, 'searchall' => 0, 'isameasure' => 1, 'help' => 'Help text for quantity', 'css' => 'maxwidth75imp', 'validate' => 1),
128  'fk_soc' => array('type' => 'integer:Societe:societe/class/societe.class.php:1:((status:=:1) AND (entity:IN:__SHARED_ENTITIES__))', 'picto' => 'company', 'label' => 'ThirdParty', 'visible' => 1, 'enabled' => 'isModEnabled("societe")', 'position' => 50, 'notnull' => -1, 'index' => 1, 'help' => 'OrganizationEventLinkToThirdParty', 'validate' => 1, 'css' => 'maxwidth500 widthcentpercentminusxx', 'csslist' => 'tdoverflowmax150'),
129  'fk_project' => array('type' => 'integer:Project:projet/class/project.class.php:1', 'label' => 'Project', 'picto' => 'project', 'enabled' => 'isModEnabled("project")', 'visible' => -1, 'position' => 52, 'notnull' => -1, 'index' => 1, 'validate' => 1, 'css' => 'maxwidth500 widthcentpercentminusxx', 'csslist' => 'tdoverflowmax150'),
130  'description' => array('type' => 'text', 'label' => 'Description', 'enabled' => 1, 'visible' => 3, 'position' => 60, 'validate' => 1),
131  'note_public' => array('type' => 'html', 'label' => 'NotePublic', 'enabled' => 1, 'visible' => 0, 'position' => 61, 'validate' => 1, 'cssview' => 'wordbreak'),
132  'note_private' => array('type' => 'html', 'label' => 'NotePrivate', 'enabled' => 1, 'visible' => 0, 'position' => 62, 'validate' => 1, 'cssview' => 'wordbreak'),
133  'date_creation' => array('type' => 'datetime', 'label' => 'DateCreation', 'enabled' => 1, 'visible' => -2, 'notnull' => 1, 'position' => 500),
134  'tms' => array('type' => 'timestamp', 'label' => 'DateModification', 'enabled' => 1, 'visible' => -2, 'notnull' => 0, 'position' => 501),
135  //'date_validation ' =>array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>1, 'visible'=>-2, 'position'=>502),
136  'fk_user_creat' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserAuthor', 'picto' => 'user', 'enabled' => 1, 'visible' => -2, 'notnull' => 1, 'position' => 510, 'foreignkey' => 'user.rowid', 'csslist' => 'tdoverflowmax150'),
137  'fk_user_modif' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserModif', 'picto' => 'user', 'enabled' => 1, 'visible' => -2, 'notnull' => -1, 'position' => 511, 'csslist' => 'tdoverflowmax150'),
138  //'fk_user_valid' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'UserValidation', 'enabled'=>1, 'visible'=>-1, 'position'=>512),
139  'last_main_doc' => array('type' => 'varchar(255)', 'label' => 'LastMainDoc', 'enabled' => 1, 'visible' => 0, 'notnull' => 0, 'position' => 600),
140  'import_key' => array('type' => 'varchar(14)', 'label' => 'ImportId', 'enabled' => 1, 'visible' => -2, 'notnull' => -1, 'index' => 0, 'position' => 1000),
141  'model_pdf' => array('type' => 'varchar(255)', 'label' => 'Model pdf', 'enabled' => 1, 'visible' => 0, 'notnull' => -1, 'position' => 1010),
142  'status' => array('type' => 'integer', 'label' => 'Status', 'enabled' => 1, 'visible' => 1, 'notnull' => 1, 'default' => 0, 'index' => 1, 'position' => 2000, 'arrayofkeyval' => array(0 => 'Draft', 1 => 'Validated', 9 => 'Canceled'), 'validate' => 1),
143  );
144 
148  public $rowid;
149 
153  public $ref;
154 
158  public $entity;
159 
163  public $label;
164 
168  public $amount;
169 
173  public $socid; // both socid and fk_soc are used
174  public $fk_soc; // both socid and fk_soc are used
175 
179  public $status;
180 
184  public $date_creation;
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 with ID of parent key if this object has a parent
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' it will
233  // * call method deleteByParentField(parentId, ParentFkFieldName) to fetch and delete child object
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  $resultcreate = $this->createCommon($user, $notrigger);
297 
298  //$resultvalidate = $this->validate($user, $notrigger);
299 
300  return $resultcreate;
301  }
302 
310  public function createFromClone(User $user, $fromid)
311  {
312  global $langs, $extrafields;
313  $error = 0;
314 
315  dol_syslog(__METHOD__, LOG_DEBUG);
316 
317  $object = new self($this->db);
318 
319  $this->db->begin();
320 
321  // Load source object
322  $result = $object->fetchCommon($fromid);
323  if ($result > 0 && !empty($object->table_element_line)) {
324  $object->fetchLines();
325  }
326 
327  // get lines so they will be clone
328  //foreach($this->lines as $line)
329  // $line->fetch_optionals();
330 
331  // Reset some properties
332  unset($object->id);
333  unset($object->fk_user_creat);
334  unset($object->import_key);
335 
336  // Clear fields
337  if (property_exists($object, 'ref')) {
338  $object->ref = empty($this->fields['ref']['default']) ? "Copy_Of_".$object->ref : $this->fields['ref']['default'];
339  }
340  if (property_exists($object, 'label')) {
341  $object->label = empty($this->fields['label']['default']) ? $langs->trans("CopyOf")." ".$object->label : $this->fields['label']['default'];
342  }
343  if (property_exists($object, 'status')) {
344  $object->status = self::STATUS_DRAFT;
345  }
346  if (property_exists($object, 'date_creation')) {
347  $object->date_creation = dol_now();
348  }
349  if (property_exists($object, 'date_modification')) {
350  $object->date_modification = null;
351  }
352  // ...
353  // Clear extrafields that are unique
354  if (is_array($object->array_options) && count($object->array_options) > 0) {
355  $extrafields->fetch_name_optionals_label($this->table_element);
356  foreach ($object->array_options as $key => $option) {
357  $shortkey = preg_replace('/options_/', '', $key);
358  if (!empty($extrafields->attributes[$this->table_element]['unique'][$shortkey])) {
359  //var_dump($key);
360  //var_dump($clonedObj->array_options[$key]); exit;
361  unset($object->array_options[$key]);
362  }
363  }
364  }
365 
366  // Create clone
367  $object->context['createfromclone'] = 'createfromclone';
368  $result = $object->createCommon($user);
369  if ($result < 0) {
370  $error++;
372  }
373 
374  if (!$error) {
375  // copy internal contacts
376  if ($this->copy_linked_contact($object, 'internal') < 0) {
377  $error++;
378  }
379  }
380 
381  if (!$error) {
382  // copy external contacts if same company
383  if (!empty($object->socid) && property_exists($this, 'fk_soc') && $this->fk_soc == $object->socid) {
384  if ($this->copy_linked_contact($object, 'external') < 0) {
385  $error++;
386  }
387  }
388  }
389 
390  unset($object->context['createfromclone']);
391 
392  // End
393  if (!$error) {
394  $this->db->commit();
395  return $object;
396  } else {
397  $this->db->rollback();
398  return -1;
399  }
400  }
401 
411  public function fetch($id, $ref = null, $noextrafields = 0, $nolines = 0)
412  {
413  $result = $this->fetchCommon($id, $ref, '', $noextrafields);
414  if ($result > 0 && !empty($this->table_element_line) && empty($nolines)) {
415  $this->fetchLines($noextrafields);
416  }
417  return $result;
418  }
419 
426  public function fetchLines($noextrafields = 0)
427  {
428  $this->lines = array();
429 
430  $result = $this->fetchLinesCommon('', $noextrafields);
431  return $result;
432  }
433 
434 
449  public function fetchAll($sortorder = '', $sortfield = '', $limit = 1000, $offset = 0, string $filter = '', $filtermode = 'AND')
450  {
451  dol_syslog(__METHOD__, LOG_DEBUG);
452 
453  $records = array();
454 
455  $sql = "SELECT ";
456  $sql .= $this->getFieldList('t');
457  $sql .= " FROM ".$this->db->prefix().$this->table_element." as t";
458  if (isset($this->isextrafieldmanaged) && $this->isextrafieldmanaged == 1) {
459  $sql .= " LEFT JOIN ".$this->db->prefix().$this->table_element."_extrafields as te ON te.fk_object = t.rowid";
460  }
461  if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) {
462  $sql .= " WHERE t.entity IN (".getEntity($this->element).")";
463  } else {
464  $sql .= " WHERE 1 = 1";
465  }
466 
467  // Manage filter
468  $errormessage = '';
469  $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage);
470  if ($errormessage) {
471  $this->errors[] = $errormessage;
472  dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
473  return -1;
474  }
475 
476  if (!empty($sortfield)) {
477  $sql .= $this->db->order($sortfield, $sortorder);
478  }
479  if (!empty($limit)) {
480  $sql .= $this->db->plimit($limit, $offset);
481  }
482 
483  $resql = $this->db->query($sql);
484  if ($resql) {
485  $num = $this->db->num_rows($resql);
486  $i = 0;
487  while ($i < ($limit ? min($limit, $num) : $num)) {
488  $obj = $this->db->fetch_object($resql);
489 
490  $record = new self($this->db);
491  $record->setVarsFromFetchObj($obj);
492 
493  if (!empty($record->isextrafieldmanaged)) {
494  $record->fetch_optionals();
495  }
496 
497  $records[$record->id] = $record;
498 
499  $i++;
500  }
501  $this->db->free($resql);
502 
503  return $records;
504  } else {
505  $this->errors[] = 'Error '.$this->db->lasterror();
506  dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
507 
508  return -1;
509  }
510  }
511 
519  public function update(User $user, $notrigger = 0)
520  {
521  return $this->updateCommon($user, $notrigger);
522  }
523 
531  public function delete(User $user, $notrigger = 0)
532  {
533  return $this->deleteCommon($user, $notrigger);
534  //return $this->deleteCommon($user, $notrigger, 1);
535  }
536 
545  public function deleteLine(User $user, $idline, $notrigger = 0)
546  {
547  if ($this->status < 0) {
548  $this->error = 'ErrorDeleteLineNotAllowedByObjectStatus';
549  return -2;
550  }
551 
552  return $this->deleteLineCommon($user, $idline, $notrigger);
553  }
554 
555 
563  public function validate($user, $notrigger = 0)
564  {
565  global $conf;
566 
567  require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
568 
569  $error = 0;
570 
571  // Protection
572  if ($this->status == self::STATUS_VALIDATED) {
573  dol_syslog(get_class($this)."::validate action abandoned: already validated", LOG_WARNING);
574  return 0;
575  }
576 
577  /* if (! ((!getDolGlobalInt('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('mymodule', 'myobject', 'write'))
578  || (getDolGlobalInt('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('mymodule', 'myobject_advance', 'validate')))
579  {
580  $this->error='NotEnoughPermissions';
581  dol_syslog(get_class($this)."::valid ".$this->error, LOG_ERR);
582  return -1;
583  }*/
584 
585  $now = dol_now();
586 
587  $this->db->begin();
588 
589  // Define new ref
590  if (!$error && (preg_match('/^[\‍(]?PROV/i', $this->ref) || empty($this->ref))) { // empty should not happened, but when it occurs, the test save life
591  $num = $this->getNextNumRef();
592  } else {
593  $num = $this->ref;
594  }
595  $this->newref = $num;
596 
597  if (!empty($num)) {
598  // Validate
599  $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element;
600  $sql .= " SET ";
601  if (!empty($this->fields['ref'])) {
602  $sql .= " ref = '".$this->db->escape($num)."',";
603  }
604  $sql .= " status = ".self::STATUS_VALIDATED;
605  if (!empty($this->fields['date_validation'])) {
606  $sql .= ", date_validation = '".$this->db->idate($now)."'";
607  }
608  if (!empty($this->fields['fk_user_valid'])) {
609  $sql .= ", fk_user_valid = ".((int) $user->id);
610  }
611  $sql .= " WHERE rowid = ".((int) $this->id);
612 
613  dol_syslog(get_class($this)."::validate()", LOG_DEBUG);
614  $resql = $this->db->query($sql);
615  if (!$resql) {
616  dol_print_error($this->db);
617  $this->error = $this->db->lasterror();
618  $error++;
619  }
620 
621  if (!$error && !$notrigger) {
622  // Call trigger
623  $result = $this->call_trigger('MYOBJECT_VALIDATE', $user);
624  if ($result < 0) {
625  $error++;
626  }
627  // End call triggers
628  }
629  }
630 
631  if (!$error) {
632  $this->oldref = $this->ref;
633 
634  // Rename directory if dir was a temporary ref
635  if (preg_match('/^[\‍(]?PROV/i', $this->ref)) {
636  // Now we rename also files into index
637  $sql = 'UPDATE '.MAIN_DB_PREFIX."ecm_files set filename = CONCAT('".$this->db->escape($this->newref)."', SUBSTR(filename, ".(strlen($this->ref) + 1).")), filepath = 'myobject/".$this->db->escape($this->newref)."'";
638  $sql .= " WHERE filename LIKE '".$this->db->escape($this->ref)."%' AND filepath = 'myobject/".$this->db->escape($this->ref)."' and entity = ".$conf->entity;
639  $resql = $this->db->query($sql);
640  if (!$resql) {
641  $error++;
642  $this->error = $this->db->lasterror();
643  }
644  $sql = 'UPDATE '.MAIN_DB_PREFIX."ecm_files set filepath = 'myobject/".$this->db->escape($this->newref)."'";
645  $sql .= " WHERE filepath = 'myobject/".$this->db->escape($this->ref)."' and entity = ".$conf->entity;
646  $resql = $this->db->query($sql);
647  if (!$resql) {
648  $error++;
649  $this->error = $this->db->lasterror();
650  }
651 
652  // We rename directory ($this->ref = old ref, $num = new ref) in order not to lose the attachments
653  $oldref = dol_sanitizeFileName($this->ref);
654  $newref = dol_sanitizeFileName($num);
655  $dirsource = $conf->mymodule->dir_output.'/myobject/'.$oldref;
656  $dirdest = $conf->mymodule->dir_output.'/myobject/'.$newref;
657  if (!$error && file_exists($dirsource)) {
658  dol_syslog(get_class($this)."::validate() rename dir ".$dirsource." into ".$dirdest);
659 
660  if (@rename($dirsource, $dirdest)) {
661  dol_syslog("Rename ok");
662  // Rename docs starting with $oldref with $newref
663  $listoffiles = dol_dir_list($conf->mymodule->dir_output.'/myobject/'.$newref, 'files', 1, '^'.preg_quote($oldref, '/'));
664  foreach ($listoffiles as $fileentry) {
665  $dirsource = $fileentry['name'];
666  $dirdest = preg_replace('/^'.preg_quote($oldref, '/').'/', $newref, $dirsource);
667  $dirsource = $fileentry['path'].'/'.$dirsource;
668  $dirdest = $fileentry['path'].'/'.$dirdest;
669  @rename($dirsource, $dirdest);
670  }
671  }
672  }
673  }
674  }
675 
676  // Set new ref and current status
677  if (!$error) {
678  $this->ref = $num;
679  $this->status = self::STATUS_VALIDATED;
680  }
681 
682  if (!$error) {
683  $this->db->commit();
684  return 1;
685  } else {
686  $this->db->rollback();
687  return -1;
688  }
689  }
690 
691 
699  public function setDraft($user, $notrigger = 0)
700  {
701  // Protection
702  if ($this->status <= self::STATUS_DRAFT) {
703  return 0;
704  }
705 
706  /* if (! ((!getDolGlobalInt('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('mymodule','write'))
707  || (getDolGlobalInt('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('mymodule','mymodule_advance','validate'))))
708  {
709  $this->error='Permission denied';
710  return -1;
711  }*/
712 
713  return $this->setStatusCommon($user, self::STATUS_DRAFT, $notrigger, 'MYMODULE_MYOBJECT_UNVALIDATE');
714  }
715 
723  public function cancel($user, $notrigger = 0)
724  {
725  // Protection
726  if ($this->status != self::STATUS_VALIDATED) {
727  return 0;
728  }
729 
730  /* if (! ((!getDolGlobalInt('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('mymodule','write'))
731  || (getDolGlobalInt('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('mymodule','mymodule_advance','validate'))))
732  {
733  $this->error='Permission denied';
734  return -1;
735  }*/
736 
737  return $this->setStatusCommon($user, self::STATUS_CANCELED, $notrigger, 'MYMODULE_MYOBJECT_CANCEL');
738  }
739 
747  public function reopen($user, $notrigger = 0)
748  {
749  // Protection
750  if ($this->status == self::STATUS_VALIDATED) {
751  return 0;
752  }
753 
754  /*if (! ((!getDolGlobalInt('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('mymodule','write'))
755  || (getDolGlobalInt('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('mymodule','mymodule_advance','validate'))))
756  {
757  $this->error='Permission denied';
758  return -1;
759  }*/
760 
761  return $this->setStatusCommon($user, self::STATUS_VALIDATED, $notrigger, 'MYMODULE_MYOBJECT_REOPEN');
762  }
763 
771  public function getTooltipContentArray($params)
772  {
773  global $langs;
774 
775  $datas = [];
776 
777  if (getDolGlobalInt('MAIN_OPTIMIZEFORTEXTBROWSER')) {
778  return ['optimize' => $langs->trans("ShowMyObject")];
779  }
780  $datas['picto'] = img_picto('', $this->picto).' <u>'.$langs->trans("MyObject").'</u>';
781  if (isset($this->status)) {
782  $datas['picto'] .= ' '.$this->getLibStatut(5);
783  }
784  if (property_exists($this, 'ref')) {
785  $datas['ref'] = '<br><b>'.$langs->trans('Ref').':</b> '.$this->ref;
786  }
787  if (property_exists($this, 'label')) {
788  $datas['ref'] = '<br>'.$langs->trans('Label').':</b> '.$this->label;
789  }
790 
791  return $datas;
792  }
793 
804  public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
805  {
806  global $conf, $langs, $hookmanager;
807 
808  if (!empty($conf->dol_no_mouse_hover)) {
809  $notooltip = 1; // Force disable tooltips
810  }
811 
812  $result = '';
813  $params = [
814  'id' => $this->id,
815  'objecttype' => $this->element.($this->module ? '@'.$this->module : ''),
816  'option' => $option,
817  ];
818  $classfortooltip = 'classfortooltip';
819  $dataparams = '';
820  if (getDolGlobalInt('MAIN_ENABLE_AJAX_TOOLTIP')) {
821  $classfortooltip = 'classforajaxtooltip';
822  $dataparams = ' data-params="'.dol_escape_htmltag(json_encode($params)).'"';
823  $label = '';
824  } else {
825  $label = implode($this->getTooltipContentArray($params));
826  }
827 
828  $url = dol_buildpath('/mymodule/myobject_card.php', 1).'?id='.$this->id;
829 
830  if ($option !== 'nolink') {
831  // Add param to save lastsearch_values or not
832  $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
833  if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
834  $add_save_lastsearch_values = 1;
835  }
836  if ($url && $add_save_lastsearch_values) {
837  $url .= '&save_lastsearch_values=1';
838  }
839  }
840 
841  $linkclose = '';
842  if (empty($notooltip)) {
843  if (getDolGlobalInt('MAIN_OPTIMIZEFORTEXTBROWSER')) {
844  $label = $langs->trans("ShowMyObject");
845  $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"';
846  }
847  $linkclose .= ($label ? ' title="'.dol_escape_htmltag($label, 1).'"' : ' title="tocomplete"');
848  $linkclose .= $dataparams.' class="'.$classfortooltip.($morecss ? ' '.$morecss : '').'"';
849  } else {
850  $linkclose = ($morecss ? ' class="'.$morecss.'"' : '');
851  }
852 
853  if ($option == 'nolink' || empty($url)) {
854  $linkstart = '<span';
855  } else {
856  $linkstart = '<a href="'.$url.'"';
857  }
858  $linkstart .= $linkclose.'>';
859  if ($option == 'nolink' || empty($url)) {
860  $linkend = '</span>';
861  } else {
862  $linkend = '</a>';
863  }
864 
865  $result .= $linkstart;
866 
867  if (empty($this->showphoto_on_popup)) {
868  if ($withpicto) {
869  $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), (($withpicto != 2) ? 'class="paddingright"' : ''), 0, 0, $notooltip ? 0 : 1);
870  }
871  } else {
872  if ($withpicto) {
873  require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
874 
875  list($class, $module) = explode('@', $this->picto);
876  $upload_dir = $conf->$module->multidir_output[$conf->entity]."/$class/".dol_sanitizeFileName($this->ref);
877  $filearray = dol_dir_list($upload_dir, "files");
878  $filename = $filearray[0]['name'];
879  if (!empty($filename)) {
880  $pospoint = strpos($filearray[0]['name'], '.');
881 
882  $pathtophoto = $class.'/'.$this->ref.'/thumbs/'.substr($filename, 0, $pospoint).'_mini'.substr($filename, $pospoint);
883  if (!getDolGlobalString(strtoupper($module.'_'.$class).'_FORMATLISTPHOTOSASUSERS')) {
884  $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>';
885  } else {
886  $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>';
887  }
888 
889  $result .= '</div>';
890  } else {
891  $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'"'), 0, 0, $notooltip ? 0 : 1);
892  }
893  }
894  }
895 
896  if ($withpicto != 2) {
897  $result .= $this->ref;
898  }
899 
900  $result .= $linkend;
901  //if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : '');
902 
903  global $action, $hookmanager;
904  $hookmanager->initHooks(array($this->element.'dao'));
905  $parameters = array('id' => $this->id, 'getnomurl' => &$result);
906  $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
907  if ($reshook > 0) {
908  $result = $hookmanager->resPrint;
909  } else {
910  $result .= $hookmanager->resPrint;
911  }
912 
913  return $result;
914  }
915 
923  public function getKanbanView($option = '', $arraydata = null)
924  {
925  global $conf, $langs;
926 
927  $selected = (empty($arraydata['selected']) ? 0 : $arraydata['selected']);
928 
929  $return = '<div class="box-flex-item box-flex-grow-zero">';
930  $return .= '<div class="info-box info-box-sm">';
931  $return .= '<span class="info-box-icon bg-infobox-action">';
932  $return .= img_picto('', $this->picto);
933  $return .= '</span>';
934  $return .= '<div class="info-box-content">';
935  $return .= '<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">'.(method_exists($this, 'getNomUrl') ? $this->getNomUrl() : $this->ref).'</span>';
936  if ($selected >= 0) {
937  $return .= '<input id="cb'.$this->id.'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->id.'"'.($selected ? ' checked="checked"' : '').'>';
938  }
939  if (property_exists($this, 'label')) {
940  $return .= ' <div class="inline-block opacitymedium valignmiddle tdoverflowmax100">'.$this->label.'</div>';
941  }
942  if (property_exists($this, 'thirdparty') && is_object($this->thirdparty)) {
943  $return .= '<br><div class="info-box-ref tdoverflowmax150">'.$this->thirdparty->getNomUrl(1).'</div>';
944  }
945  if (property_exists($this, 'amount')) {
946  $return .= '<br>';
947  $return .= '<span class="info-box-label amount">'.price($this->amount, 0, $langs, 1, -1, -1, $conf->currency).'</span>';
948  }
949  if (method_exists($this, 'getLibStatut')) {
950  $return .= '<br><div class="info-box-status">'.$this->getLibStatut(3).'</div>';
951  }
952  $return .= '</div>';
953  $return .= '</div>';
954  $return .= '</div>';
955 
956  return $return;
957  }
958 
965  public function getLabelStatus($mode = 0)
966  {
967  return $this->LibStatut($this->status, $mode);
968  }
969 
976  public function getLibStatut($mode = 0)
977  {
978  return $this->LibStatut($this->status, $mode);
979  }
980 
981  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
989  public function LibStatut($status, $mode = 0)
990  {
991  // phpcs:enable
992  if (is_null($status)) {
993  return '';
994  }
995 
996  if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
997  global $langs;
998  //$langs->load("mymodule@mymodule");
999  $this->labelStatus[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft');
1000  $this->labelStatus[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Enabled');
1001  $this->labelStatus[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('Disabled');
1002  $this->labelStatusShort[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft');
1003  $this->labelStatusShort[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Enabled');
1004  $this->labelStatusShort[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('Disabled');
1005  }
1006 
1007  $statusType = 'status'.$status;
1008  //if ($status == self::STATUS_VALIDATED) $statusType = 'status1';
1009  if ($status == self::STATUS_CANCELED) {
1010  $statusType = 'status6';
1011  }
1012 
1013  return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode);
1014  }
1015 
1022  public function info($id)
1023  {
1024  $sql = "SELECT rowid,";
1025  $sql .= " date_creation as datec, tms as datem";
1026  if (!empty($this->fields['date_validation'])) {
1027  $sql .= ", date_validation as datev";
1028  }
1029  if (!empty($this->fields['fk_user_creat'])) {
1030  $sql .= ", fk_user_creat";
1031  }
1032  if (!empty($this->fields['fk_user_modif'])) {
1033  $sql .= ", fk_user_modif";
1034  }
1035  if (!empty($this->fields['fk_user_valid'])) {
1036  $sql .= ", fk_user_valid";
1037  }
1038  $sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element." as t";
1039  $sql .= " WHERE t.rowid = ".((int) $id);
1040 
1041  $result = $this->db->query($sql);
1042  if ($result) {
1043  if ($this->db->num_rows($result)) {
1044  $obj = $this->db->fetch_object($result);
1045 
1046  $this->id = $obj->rowid;
1047 
1048  if (!empty($this->fields['fk_user_creat'])) {
1049  $this->user_creation_id = $obj->fk_user_creat;
1050  }
1051  if (!empty($this->fields['fk_user_modif'])) {
1052  $this->user_modification_id = $obj->fk_user_modif;
1053  }
1054  if (!empty($this->fields['fk_user_valid'])) {
1055  $this->user_validation_id = $obj->fk_user_valid;
1056  }
1057  $this->date_creation = $this->db->jdate($obj->datec);
1058  $this->date_modification = empty($obj->datem) ? '' : $this->db->jdate($obj->datem);
1059  if (!empty($obj->datev)) {
1060  $this->date_validation = empty($obj->datev) ? '' : $this->db->jdate($obj->datev);
1061  }
1062  }
1063 
1064  $this->db->free($result);
1065  } else {
1066  dol_print_error($this->db);
1067  }
1068  }
1069 
1076  public function initAsSpecimen()
1077  {
1078  // Set here init that are not commonf fields
1079  // $this->property1 = ...
1080  // $this->property2 = ...
1081 
1082  return $this->initAsSpecimenCommon();
1083  }
1084 
1090  public function getLinesArray()
1091  {
1092  $this->lines = array();
1093 
1094  $objectline = new MyObjectLine($this->db);
1095  $result = $objectline->fetchAll('ASC', 'position', 0, 0, '(fk_myobject:=:'.((int) $this->id).')');
1096 
1097  if (is_numeric($result)) {
1098  $this->setErrorsFromObject($objectline);
1099  return $result;
1100  } else {
1101  $this->lines = $result;
1102  return $this->lines;
1103  }
1104  }
1105 
1111  public function getNextNumRef()
1112  {
1113  global $langs, $conf;
1114  $langs->load("mymodule@mymodule");
1115 
1116  if (!getDolGlobalString('MYMODULE_MYOBJECT_ADDON')) {
1117  $conf->global->MYMODULE_MYOBJECT_ADDON = 'mod_myobject_standard';
1118  }
1119 
1120  if (getDolGlobalString('MYMODULE_MYOBJECT_ADDON')) {
1121  $mybool = false;
1122 
1123  $file = getDolGlobalString('MYMODULE_MYOBJECT_ADDON').".php";
1124  $classname = getDolGlobalString('MYMODULE_MYOBJECT_ADDON');
1125 
1126  // Include file with class
1127  $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
1128  foreach ($dirmodels as $reldir) {
1129  $dir = dol_buildpath($reldir."core/modules/mymodule/");
1130 
1131  // Load file with numbering class (if found)
1132  $mybool |= @include_once $dir.$file;
1133  }
1134 
1135  if ($mybool === false) {
1136  dol_print_error(null, "Failed to include file ".$file);
1137  return '';
1138  }
1139 
1140  if (class_exists($classname)) {
1141  $obj = new $classname();
1142  $numref = $obj->getNextValue($this);
1143 
1144  if ($numref != '' && $numref != '-1') {
1145  return $numref;
1146  } else {
1147  $this->error = $obj->error;
1148  //dol_print_error($this->db,get_class($this)."::getNextNumRef ".$obj->error);
1149  return "";
1150  }
1151  } else {
1152  print $langs->trans("Error")." ".$langs->trans("ClassNotFound").' '.$classname;
1153  return "";
1154  }
1155  } else {
1156  print $langs->trans("ErrorNumberingModuleNotSetup", $this->element);
1157  return "";
1158  }
1159  }
1160 
1172  public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams = null)
1173  {
1174  global $langs;
1175 
1176  $result = 0;
1177  $includedocgeneration = 0;
1178 
1179  $langs->load("mymodule@mymodule");
1180 
1181  if (!dol_strlen($modele)) {
1182  $modele = 'standard_myobject';
1183 
1184  if (!empty($this->model_pdf)) {
1185  $modele = $this->model_pdf;
1186  } elseif (getDolGlobalString('MYOBJECT_ADDON_PDF')) {
1187  $modele = getDolGlobalString('MYOBJECT_ADDON_PDF');
1188  }
1189  }
1190 
1191  $modelpath = "core/modules/mymodule/doc/";
1192 
1193  if ($includedocgeneration && !empty($modele)) {
1194  $result = $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
1195  }
1196 
1197  return $result;
1198  }
1199 
1209  public function validateField($fields, $fieldKey, $fieldValue)
1210  {
1211  // Add your own validation rules here.
1212  // ...
1213 
1214  return parent::validateField($fields, $fieldKey, $fieldValue);
1215  }
1216 
1224  public function doScheduledJob()
1225  {
1226  //global $conf, $langs;
1227 
1228  //$conf->global->SYSLOG_FILE = 'DOL_DATA_ROOT/dolibarr_mydedicatedlogfile.log';
1229 
1230  $error = 0;
1231  $this->output = '';
1232  $this->error = '';
1233 
1234  dol_syslog(__METHOD__." start", LOG_INFO);
1235 
1236  $now = dol_now();
1237 
1238  $this->db->begin();
1239 
1240  // ...
1241 
1242  $this->db->commit();
1243 
1244  dol_syslog(__METHOD__." end", LOG_INFO);
1245 
1246  return $error;
1247  }
1248 }
1249 
1250 
1251 require_once DOL_DOCUMENT_ROOT.'/core/class/commonobjectline.class.php';
1252 
1257 {
1258  // To complete with content of an object MyObjectLine
1259  // We should have a field rowid, fk_myobject and position
1260 
1264  public $isextrafieldmanaged = 0;
1265 
1271  public function __construct(DoliDB $db)
1272  {
1273  $this->db = $db;
1274  }
1275 }
if($user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
Definition: card.php:58
print $langs trans("AuditedSecurityEvents").'</strong >< span class="opacitymedium"></span >< br > status
Or an array listing all the potential status of the object: array: int of the status => translated la...
Definition: security.php:604
$object ref
Definition: info.php:79
Parent class of all other business classes (invoices, contracts, proposals, orders,...
deleteLineCommon(User $user, $idline, $notrigger=0)
Delete a line of object in database.
commonGenerateDocument($modelspath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams=null)
Common function for all objects extending CommonObject for generating documents.
setErrorsFromObject($object)
setErrorsFromObject
createCommon(User $user, $notrigger=0)
Create object into database.
getFieldList($alias='', $excludefields=array())
Function to concat keys of fields.
updateCommon(User $user, $notrigger=0)
Update object into database.
setStatusCommon($user, $status, $notrigger=0, $triggercode='')
Set to a status.
initAsSpecimenCommon()
Initialise object with example values Id must be 0 if object instance is a specimen.
copy_linked_contact($objFrom, $source='internal')
Copy contact from one element to current.
fetchLinesCommon($morewhere='', $noextrafields=0)
Load object in memory from the database.
fetchCommon($id, $ref=null, $morewhere='', $noextrafields=0)
Load object in memory from the database.
deleteCommon(User $user, $notrigger=0, $forcechilddeletion=0)
Delete object in database.
call_trigger($triggerName, $user)
Call trigger based on this instance.
Parent class for class inheritance lines of business objects This class is useless for the moment so ...
Class to manage Dolibarr database access.
Class for MyObject.
generateDocument($modele, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0, $moreparams=null)
Create a document onto disk according to template module.
createFromClone(User $user, $fromid)
Clone an object into another one.
getKanbanView($option='', $arraydata=null)
Return a thumb for kanban views.
getLibStatut($mode=0)
Return the label of the status.
create(User $user, $notrigger=0)
Create object into database.
update(User $user, $notrigger=0)
Update object into database.
getTooltipContentArray($params)
getTooltipContentArray
reopen($user, $notrigger=0)
Set back to validated status.
setDraft($user, $notrigger=0)
Set draft status.
getNomUrl($withpicto=0, $option='', $notooltip=0, $morecss='', $save_lastsearch_value=-1)
Return a link to the object card (with optionally the picto)
LibStatut($status, $mode=0)
Return the label of a given status.
validateField($fields, $fieldKey, $fieldValue)
Return validation test result for a field.
getNextNumRef()
Returns the reference to the following non used object depending on the active numbering module.
fetchAll($sortorder='', $sortfield='', $limit=1000, $offset=0, string $filter='', $filtermode='AND')
Load list of objects in memory from the database.
initAsSpecimen()
Initialise object with example values Id must be 0 if object instance is a specimen.
__construct(DoliDB $db)
Constructor.
deleteLine(User $user, $idline, $notrigger=0)
Delete a line of object in database.
cancel($user, $notrigger=0)
Set cancel status.
fetchLines($noextrafields=0)
Load object lines in memory from the database.
info($id)
Load the info information in the object.
doScheduledJob()
Action executed by scheduler CAN BE A CRON TASK.
fetch($id, $ref=null, $noextrafields=0, $nolines=0)
Load object in memory from the database.
getLabelStatus($mode=0)
Return the label of the status.
validate($user, $notrigger=0)
Validate object.
getLinesArray()
Create an array of lines.
Class MyObjectLine.
__construct(DoliDB $db)
Constructor.
Class to manage Dolibarr users.
Definition: user.class.php:50
if(isModEnabled('invoice') && $user->hasRight('facture', 'lire')) if((isModEnabled('fournisseur') &&!getDolGlobalString('MAIN_USE_NEW_SUPPLIERMOD') && $user->hasRight("fournisseur", "facture", "lire"))||(isModEnabled('supplier_invoice') && $user->hasRight("supplier_invoice", "lire"))) if(isModEnabled('don') && $user->hasRight('don', 'lire')) if(isModEnabled('tax') && $user->hasRight('tax', 'charges', 'lire')) if(isModEnabled('invoice') &&isModEnabled('order') && $user->hasRight("commande", "lire") &&!getDolGlobalString('WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER')) $sql
Social contributions to pay.
Definition: index.php:744
dol_dir_list($utf8_path, $types="all", $recursive=0, $filter="", $excludefilter=null, $sortcriteria="name", $sortorder=SORT_ASC, $mode=0, $nohook=0, $relativename="", $donotfollowsymlinks=0, $nbsecondsold=0)
Scan a directory and return a list of files/directories.
Definition: files.lib.php:63
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0)
Show a picto called object_picto (generic function)
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
forgeSQLFromUniversalSearchCriteria($filter, &$errorstr='', $noand=0, $nopar=0, $noerror=0)
forgeSQLFromUniversalSearchCriteria
dol_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dolGetStatus($statusLabel='', $statusLabelShort='', $html='', $statusType='status0', $displayMode=0, $url='', $params=array())
Output the badge of a status.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1)
Clean a string to use it as a file name.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
getDolGlobalString($key, $default='')
Return 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.
td amount
Definition: global.inc.php:554