Passed
Push — EXTRACT_CLASSES ( 0382f2...c25e41 )
by Rafael
52:18
created

ActionComm::replaceProduct()   A

Complexity

Conditions 2

Size

Total Lines 10
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
nop 3
dl 0
loc 10
rs 10
c 0
b 0
f 0
1
<?php
2
3
/* Copyright (C) 2002-2004  Rodolphe Quiedeville        <[email protected]>
4
 * Copyright (C) 2004-2011  Laurent Destailleur         <[email protected]>
5
 * Copyright (C) 2005-2012  Regis Houssin               <[email protected]>
6
 * Copyright (C) 2011-2017  Juanjo Menent               <[email protected]>
7
 * Copyright (C) 2015	    Marcos García		        <[email protected]>
8
 * Copyright (C) 2018	    Nicolas ZABOURI	            <[email protected]>
9
 * Copyright (C) 2018-2024  Frédéric France             <[email protected]>
10
 * Copyright (C) 2024		MDW						    <[email protected]>
11
 * Copyright (C) 2024		William Mead			    <[email protected]>
12
 * Copyright (C) 2024       Rafael San José             <[email protected]>
13
 *
14
 * This program is free software; you can redistribute it and/or modify
15
 * it under the terms of the GNU General Public License as published by
16
 * the Free Software Foundation; either version 3 of the License, or
17
 * (at your option) any later version.
18
 *
19
 * This program is distributed in the hope that it will be useful,
20
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22
 * GNU General Public License for more details.
23
 *
24
 * You should have received a copy of the GNU General Public License
25
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
26
 */
27
28
namespace Dolibarr\Code\Comm\Classes;
29
30
/**
31
 *       \file       htdocs/comm/action/class/actioncomm.class.php
32
 *       \ingroup    agenda
33
 *       \brief      File of class to manage agenda events (actions)
34
 */
35
36
require_once constant('DOL_DOCUMENT_ROOT') . '/comm/action/class/cactioncomm.class.php';
37
use Dolibarr\Core\Base\CommonObject;
38
require_once constant('DOL_DOCUMENT_ROOT') . '/core/class/CMailFile.class.php';
39
require_once constant('DOL_DOCUMENT_ROOT') . '/comm/action/class/actioncommreminder.class.php';
40
41
42
/**
43
 *      Class to manage agenda events (actions)
44
 */
45
class ActionComm extends CommonObject
46
{
47
    /**
48
     * @var string ID to identify managed object
49
     */
50
    public $element = 'action';
51
52
    /**
53
     * @var string Name of table without prefix where object is stored
54
     */
55
    public $table_element = 'actioncomm';
56
57
    /**
58
     * @var string Name of id column
59
     */
60
    public $table_rowid = 'id';
61
62
    /**
63
     * @var string Name of icon for actioncomm object. Filename of icon is object_action.png
64
     */
65
    public $picto = 'action';
66
67
    /**
68
     * @var int<0,2> 0=Default
69
     *               1=View may be restricted to sales representative only if no permission to see all or to company of external user if external user
70
     *               2=Same than 1 but accept record if fksoc is empty
71
     */
72
    public $restrictiononfksoc = 2;
73
74
    /**
75
     * @var int Id of the event
76
     */
77
    public $id;
78
79
    /**
80
     * @var string Id of the event. Use $id as possible
81
     */
82
    public $ref;
83
84
    /**
85
     * @var int Id into parent table llx_c_actioncomm (used only if option to use type is set)
86
     *          This field is stored info fk_action. It contains the id into table llx_ac_actioncomm.
87
     */
88
    public $type_id;
89
90
    /**
91
     * @var string Calendar of event (Type of type of event). 'system'=Default calendar, 'systemauto'=Auto calendar, 'birthdate', 'holiday', 'module'=Calendar specific to a module
92
     *             This field contains the type into table llx_ac_actioncomm ('system', 'systemauto', ...). It should be named 'type_type'.
93
     */
94
    public $type;
95
96
    /**
97
     * @var string Code into parent table llx_c_actioncomm (used only if option to use type is set). With default setup, should be AC_OTH_AUTO or AC_OTH.
98
     *             This field contains the code into table llx_ac_actioncomm.
99
     */
100
    public $type_code;
101
102
    /**
103
     * @var string Type label
104
     */
105
    public $type_label;
106
107
    /**
108
     * @var string Color into parent table llx_c_actioncomm (used only if option to use type is set)
109
     */
110
    public $type_color;
111
112
    /**
113
     * @var string Picto for type of event (used only if option to use type is set)
114
     */
115
    public $type_picto;
116
117
    /**
118
     * @var string Free code to identify action. Ie: Agenda trigger add here AC_TRIGGERNAME ('AC_COMPANY_CREATE', 'AC_PROPAL_VALIDATE', ...)
119
     *             This field is stored into field 'code' into llx_actioncomm.
120
     */
121
    public $code;
122
123
    /**
124
     * @var string Agenda event label
125
     */
126
    public $label;
127
128
    /**
129
     * @var int Date creation record (datec)
130
     */
131
    public $datec;
132
133
    /**
134
     * @var int Duration (duree)
135
     */
136
    public $duree;
137
138
    /**
139
     * @var int Date modification record (tms)
140
     */
141
    public $datem;
142
143
    /**
144
     * @var User Object user that create action
0 ignored issues
show
Bug introduced by
The type Dolibarr\Code\Comm\Classes\User was not found. Did you mean User? If so, make sure to prefix the type with \.
Loading history...
145
     * @deprecated
146
     * @see $authorid
147
     */
148
    public $author;
149
150
    /**
151
     * @var User Object user that modified action
152
     * @deprecated
153
     * @see $usermodid
154
     */
155
    public $usermod;
156
157
    /**
158
     * @var int Id user that create action
159
     */
160
    public $authorid;
161
162
    /**
163
     * @var int Id user that modified action
164
     */
165
    public $usermodid;
166
167
    /**
168
     * @var int Date action start (datep)
169
     */
170
    public $datep;
171
172
    /**
173
     * @var int Date action end (datef)
174
     */
175
    public $datef;
176
177
    /**
178
     * @var int This is date start action (datep) but modified to not be outside calendar view.
179
     */
180
    public $date_start_in_calendar;
181
182
    /**
183
     * @var int This is date end action (datef) but modified to not be outside calendar view.
184
     */
185
    public $date_end_in_calendar;
186
187
    /**
188
     * @var int Date action end (datep2)
189
     */
190
    public $datep2;
191
192
    /**
193
     * @var int -1=Unknown duration
194
     * @deprecated Use ($datef - $datep)
195
     */
196
    public $durationp = -1;
197
198
    /**
199
     * @var int 1=Event on full day
200
     */
201
    public $fulldayevent = 0;
202
203
    /**
204
     * @var int 1=???
205
     */
206
    public $ponctuel;
207
208
    /**
209
     * @var int<-1,100> Percentage
210
     */
211
    public $percentage;
212
213
    /**
214
     * @var string Location
215
     */
216
    public $location;
217
218
    /**
219
     * @var int Transparency (ical standard). Used to say if people assigned to event are busy or not by event. 0=available, 1=busy, 2=busy (refused events)
220
     */
221
    public $transparency;
222
223
    /**
224
     * @var int     (0 By default)
225
     */
226
    public $priority;
227
228
    /**
229
     * @var array<int,array{id:int,transparency:int<0,1>}>  Array of users
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<int,array{id:int,transparency:int<0,1>}> at position 12 could not be parsed: Expected '}' at position 12, but found 'int'.
Loading history...
230
     */
231
    public $userassigned = array();
232
233
    /**
234
     * @var int     Id of user owner = fk_user_action into table
235
     */
236
    public $userownerid;
237
238
    /**
239
     * @var array<int,array{id:int,mandatory:int<0,1>,answer_status:int,transparency:int<0,1>}> Array of contact ids
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<int,array{id:int,m...transparency:int<0,1>}> at position 12 could not be parsed: Expected '}' at position 12, but found 'int'.
Loading history...
240
     */
241
    public $socpeopleassigned = array();
242
243
    /**
244
     * @var int[] Array of other contact emails (not user, not contact)
245
     */
246
    public $otherassigned = array();
247
248
    /**
249
     * @var array<int,ActionCommReminder>   Array of reminders
250
     */
251
    public $reminders = array();
252
253
    /**
254
     * @var int thirdparty id linked to action
255
     */
256
    public $socid;
257
258
    /**
259
     * @var int socpeople id linked to action
260
     */
261
    public $contact_id;
262
263
264
    /**
265
     * @var ?Societe Company linked to action (optional)
0 ignored issues
show
Bug introduced by
The type Dolibarr\Code\Comm\Classes\Societe was not found. Did you mean Societe? If so, make sure to prefix the type with \.
Loading history...
266
     * @deprecated
267
     * @see $socid
268
     */
269
    public $societe;
270
271
    /**
272
     * @var ?Contact Contact linked to action (optional)
273
     * @deprecated
274
     * @see $contact_id
275
     */
276
    public $contact;
277
278
    // Properties for links to other objects
279
    /**
280
     * @var int         Id of linked object
281
     */
282
    public $fk_element; // Id of record
283
284
    /**
285
     * @var int         Id of linked object, alternative for API or other
286
     */
287
    public $elementid;
288
289
    /**
290
     * @var string      Type of record. This if property ->element of object linked to.
291
     */
292
    public $elementtype;
293
294
    /**
295
     * @var int id of calendar
296
     */
297
    public $fk_bookcal_calendar;
298
299
    /**
300
     * @var string Ical name
301
     */
302
    public $icalname;
303
304
    /**
305
     * @var string Ical color  (Hex value for color on 6 nibles)
306
     */
307
    public $icalcolor;
308
309
    /**
310
     * @var string Extraparam
311
     */
312
    public $extraparams;
313
314
    /**
315
     * @var array<int,array{id:int,type:string,actionparam:string,status:int}> Actions
316
     */
317
    public $actions = array();
318
319
    /**
320
     * @var string Email msgid
321
     */
322
    public $email_msgid;
323
324
    /**
325
     * @var string Email from
326
     */
327
    public $email_from;
328
329
    /**
330
     * @var string Email sender
331
     */
332
    public $email_sender;
333
334
    /**
335
     * @var string Email to
336
     */
337
    public $email_to;
338
339
    /**
340
     * @var string Email tocc
341
     */
342
    public $email_tocc;
343
    /**
344
     * @var string Email tobcc
345
     */
346
    public $email_tobcc;
347
348
    /**
349
     * @var string Email subject
350
     */
351
    public $email_subject;
352
353
    /**
354
     * @var string Email errors to
355
     */
356
    public $errors_to;
357
358
    /**
359
     * @var int number of vote for an event
360
     */
361
    public $num_vote;
362
363
    /**
364
     * @var int if event is paid
365
     */
366
    public $event_paid;
367
368
    /**
369
     * @var int status use but Event organisation module
370
     */
371
    public $status;
372
373
    /**
374
     * @var string IP address
375
     */
376
    public $ip;
377
378
    /*
379
     * Properties to manage the recurring events
380
     */
381
    /** @var string A string YYYYMMDDHHMMSS shared by allevent of same series */
382
    public $recurid;
383
    /** @var string Rule of recurring */
384
    public $recurrule;
385
    /** @var string Repeat until this date */
386
    public $recurdateend;
387
388
    /** @var int Duration of phone call when the event is a phone call */
389
    public $calling_duration;
390
391
392
    /**
393
     * Typical value for a event that is in a todo state
394
     */
395
    const EVENT_TODO = 0;
396
397
    /**
398
     * Typical value for a event that is in a progress state
399
     */
400
    const EVENT_IN_PROGRESS = 50;
401
402
    /**
403
     * Typical value for a event that is in a finished state
404
     */
405
    const EVENT_FINISHED = 100;
406
407
408
    public $fields = array();
409
410
    /**
411
     *      Constructor
412
     *
413
     *      @param      DoliDB      $db      Database handler
414
     */
415
    public function __construct(DoliDB $db)
0 ignored issues
show
Bug introduced by
The type Dolibarr\Code\Comm\Classes\DoliDB was not found. Did you mean DoliDB? If so, make sure to prefix the type with \.
Loading history...
416
    {
417
        $this->db = $db;
418
419
        $this->ismultientitymanaged = 1;
420
    }
421
422
    /**
423
     *    Add an action/event into database.
424
     *    $this->type_id OR $this->type_code must be set.
425
     *
426
     *    @param    User        $user           Object user making action
427
     *    @param    int<0,1>    $notrigger      1 = disable triggers, 0 = enable triggers
428
     *    @return   int                         Id of created event, < 0 if KO
429
     */
430
    public function create(User $user, $notrigger = 0)
431
    {
432
        global $langs, $conf;
433
434
        $error = 0;
435
        $now = dol_now();
436
437
        // Check parameters
438
        if (!isset($this->userownerid) || (string) $this->userownerid === '') { // $this->userownerid may be 0 (anonymous event) or > 0
439
            dol_syslog("You tried to create an event but mandatory property userownerid was empty (you can define it to 0 for anonymous event)", LOG_WARNING);
440
            $this->errors[] = 'ErrorActionCommPropertyUserowneridNotDefined';
441
            return -1;
442
        }
443
444
        // Clean parameters
445
        $this->label = dol_trunc(trim($this->label), 128);
446
        $this->location = (!empty($this->location) ? dol_trunc(trim($this->location), 128) : "");
447
        $this->note_private = dol_htmlcleanlastbr(trim(empty($this->note_private) ? $this->note : $this->note_private));
448
        if (empty($this->percentage)) {
449
            $this->percentage = 0;
450
        }
451
        if (empty($this->priority) || !is_numeric($this->priority)) {
452
            $this->priority = 0;
453
        }
454
        if (empty($this->fulldayevent)) {
455
            $this->fulldayevent = 0;
456
        }
457
        if (empty($this->transparency)) {
458
            $this->transparency = 0;
459
        }
460
        if ($this->percentage > 100) {
461
            $this->percentage = 100;
462
        }
463
        if (empty($this->datep) && $this->datep != '0') {   // We should not insert event in calendar without a start date
464
            $this->datep = $now;
465
        }
466
        if (!empty($this->datep) && !empty($this->datef)) {
467
            $this->durationp = ($this->datef - $this->datep); // deprecated
468
        }
469
        if (!empty($this->datep) && !empty($this->datef) && $this->datep > $this->datef) {
470
            $this->datef = $this->datep;
471
        }
472
        if (!isset($this->fk_project) || $this->fk_project < 0) {
473
            $this->fk_project = 0;
474
        }
475
        // For backward compatibility
476
        if ($this->elementtype == 'facture') {
477
            $this->elementtype = 'invoice';
478
        }
479
        if ($this->elementtype == 'commande') {
480
            $this->elementtype = 'order';
481
        }
482
        if ($this->elementtype == 'contrat') {
483
            $this->elementtype = 'contract';
484
        }
485
        if (empty($this->fk_element) && !empty($this->elementid)) {
486
            $this->fk_element = $this->elementid;
487
        }
488
489
        if (!is_array($this->userassigned) && !empty($this->userassigned)) {    // For backward compatibility when userassigned was an int instead of an array
490
            $tmpid = (int) $this->userassigned;
491
            $this->userassigned = array();
492
            $this->userassigned[$tmpid] = array('id' => $tmpid, 'transparency' => $this->transparency);
493
        }
494
495
        $userownerid = $this->userownerid;
496
497
        // Be sure assigned user is defined as an array of array('id'=>,'mandatory'=>,...).
498
        if (empty($this->userassigned) || count($this->userassigned) == 0 || !is_array($this->userassigned)) {
499
            $this->userassigned = array($userownerid => array('id' => $userownerid, 'transparency' => $this->transparency));
500
        }
501
502
        if (!$this->type_id || !$this->type_code) {
503
            $key = empty($this->type_id) ? $this->type_code : $this->type_id;
504
505
            // Get id from code
506
            $cactioncomm = new CActionComm($this->db);
507
            $result = $cactioncomm->fetch($key);
508
509
            if ($result > 0) {
510
                $this->type_id = $cactioncomm->id;
511
                $this->type_code = $cactioncomm->code;
512
            } elseif ($result == 0) {
513
                $this->error = $langs->trans('ErrorActionCommBadType', $this->type_id, $this->type_code);
514
                return -1;
515
            } else {
516
                $this->error = $cactioncomm->error;
517
                return -1;
518
            }
519
        }
520
        $code = empty($this->code) ? $this->type_code : $this->code;
521
522
        // Check parameters
523
        if (!$this->type_id) {
524
            $this->error = "ErrorWrongParameters";
525
            return -1;
526
        }
527
528
        $this->db->begin();
529
530
        $sql = "INSERT INTO " . MAIN_DB_PREFIX . "actioncomm";
531
        $sql .= "(ref,";
532
        $sql .= "datec,";
533
        $sql .= "datep,";
534
        $sql .= "datep2,";
535
        $sql .= "durationp,"; // deprecated
536
        $sql .= "fk_action,";
537
        $sql .= "code,";
538
        $sql .= "ref_ext,";
539
        $sql .= "fk_soc,";
540
        $sql .= "fk_project,";
541
        $sql .= "note,";
542
        $sql .= "fk_contact,";
543
        $sql .= "fk_user_author,";
544
        $sql .= "fk_user_action,";
545
        $sql .= "label,percent,priority,fulldayevent,location,";
546
        $sql .= "transparency,";
547
        $sql .= "fk_element,";
548
        $sql .= "elementtype,";
549
        $sql .= "fk_bookcal_calendar,";
550
        $sql .= "entity,";
551
        $sql .= "extraparams,";
552
        // Fields emails
553
        $sql .= "email_msgid,";
554
        $sql .= "email_from,";
555
        $sql .= "email_sender,";
556
        $sql .= "email_to,";
557
        $sql .= "email_tocc,";
558
        $sql .= "email_tobcc,";
559
        $sql .= "email_subject,";
560
        $sql .= "errors_to,";
561
        $sql .= "recurid,";
562
        $sql .= "recurrule,";
563
        $sql .= "recurdateend,";
564
        $sql .= "num_vote,";
565
        $sql .= "event_paid,";
566
        $sql .= "status,";
567
        $sql .= "ip";
568
        $sql .= ") VALUES (";
569
        $sql .= "'(PROV)', ";
570
        $sql .= "'" . $this->db->idate($now) . "', ";   // date creation
571
        $sql .= "'" . $this->db->idate($this->datep) . "', ";   // date start event
572
        $sql .= (strval($this->datef) != '' ? "'" . $this->db->idate($this->datef) . "'" : "null") . ", ";
573
        $sql .= ((isset($this->durationp) && $this->durationp >= 0 && $this->durationp != '') ? "'" . $this->db->escape($this->durationp) . "'" : "null") . ", "; // deprecated
574
        $sql .= (isset($this->type_id) ? $this->type_id : "null") . ",";
575
        $sql .= ($code ? ("'" . $this->db->escape($code) . "'") : "null") . ", ";
576
        $sql .= (!empty($this->ref_ext) ? "'" . $this->db->escape($this->ref_ext) . "'" : "null") . ", ";
577
        $sql .= ((isset($this->socid) && $this->socid > 0) ? ((int) $this->socid) : "null") . ", ";
578
        $sql .= ((isset($this->fk_project) && $this->fk_project > 0) ? ((int) $this->fk_project) : "null") . ", ";
579
        $sql .= " '" . $this->db->escape($this->note_private) . "', ";
580
        $sql .= ((isset($this->contact_id) && $this->contact_id > 0) ? ((int) $this->contact_id) : "null") . ", "; // deprecated, use ->socpeopleassigned
581
        $sql .= (isset($user->id) && $user->id > 0 ? $user->id : "null") . ", ";
582
        $sql .= ($userownerid > 0 ? $userownerid : "null") . ", ";
583
        $sql .= "'" . $this->db->escape($this->label) . "', ";
584
        $sql .= "'" . $this->db->escape($this->percentage) . "', ";
585
        $sql .= "'" . $this->db->escape($this->priority) . "', ";
586
        $sql .= "'" . $this->db->escape($this->fulldayevent) . "', ";
587
        $sql .= "'" . $this->db->escape($this->location) . "', ";
588
        $sql .= "'" . $this->db->escape($this->transparency) . "', ";
589
        $sql .= (!empty($this->fk_element) ? ((int) $this->fk_element) : "null") . ", ";
590
        $sql .= (!empty($this->elementtype) ? "'" . $this->db->escape($this->elementtype) . "'" : "null") . ", ";
591
        $sql .= (!empty($this->fk_bookcal_calendar) ? "'" . $this->db->escape($this->fk_bookcal_calendar) . "'" : "null") . ", ";
592
        $sql .= ((int) $conf->entity) . ",";
593
        $sql .= (!empty($this->extraparams) ? "'" . $this->db->escape($this->extraparams) . "'" : "null") . ", ";
594
        // Fields emails
595
        $sql .= (!empty($this->email_msgid) ? "'" . $this->db->escape($this->email_msgid) . "'" : "null") . ", ";
596
        $sql .= (!empty($this->email_from) ? "'" . $this->db->escape($this->email_from) . "'" : "null") . ", ";
597
        $sql .= (!empty($this->email_sender) ? "'" . $this->db->escape($this->email_sender) . "'" : "null") . ", ";
598
        $sql .= (!empty($this->email_to) ? "'" . $this->db->escape($this->email_to) . "'" : "null") . ", ";
599
        $sql .= (!empty($this->email_tocc) ? "'" . $this->db->escape($this->email_tocc) . "'" : "null") . ", ";
600
        $sql .= (!empty($this->email_tobcc) ? "'" . $this->db->escape($this->email_tobcc) . "'" : "null") . ", ";
601
        $sql .= (!empty($this->email_subject) ? "'" . $this->db->escape($this->email_subject) . "'" : "null") . ", ";
602
        $sql .= (!empty($this->errors_to) ? "'" . $this->db->escape($this->errors_to) . "'" : "null") . ", ";
603
        $sql .= (!empty($this->recurid) ? "'" . $this->db->escape($this->recurid) . "'" : "null") . ", ";
604
        $sql .= (!empty($this->recurrule) ? "'" . $this->db->escape($this->recurrule) . "'" : "null") . ", ";
605
        $sql .= (!empty($this->recurdateend) ? "'" . $this->db->idate($this->recurdateend) . "'" : "null") . ", ";
606
        $sql .= (!empty($this->num_vote) ? (int) $this->num_vote : "null") . ", ";
607
        $sql .= (!empty($this->event_paid) ? (int) $this->event_paid : 0) . ", ";
608
        $sql .= (!empty($this->status) ? (int) $this->status : "0") . ", ";
609
        $sql .= (!empty($this->ip) ? "'" . $this->db->escape($this->ip) . "'" : "null");
610
        $sql .= ")";
611
612
        dol_syslog(get_class($this) . "::add", LOG_DEBUG);
613
        $resql = $this->db->query($sql);
614
        if ($resql) {
615
            $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX . "actioncomm", "id");
616
            $this->ref = (string) $this->id;
617
            $sql = "UPDATE " . MAIN_DB_PREFIX . "actioncomm SET ref='" . $this->db->escape($this->ref) . "' WHERE id=" . $this->id;
618
            $resql = $this->db->query($sql);
619
            if (!$resql) {
620
                $error++;
621
                dol_syslog('Error to process ref: ' . $this->db->lasterror(), LOG_ERR);
622
                $this->errors[] = $this->db->lasterror();
623
            }
624
            // Now insert assigned users
625
            if (!$error) {
626
                //dol_syslog(var_export($this->userassigned, true));
627
                $already_inserted = array();
628
                foreach ($this->userassigned as $key => $val) {
629
                    // Common value with new behavior is to have $val = array('id'=>iduser, 'transparency'=>0|1) and $this->userassigned is an array of iduser => $val.
630
                    if (!is_array($val)) {  // For backward compatibility when $val='id'.
631
                        $val = array('id' => $val);
632
                    }
633
634
                    if ($val['id'] > 0) {
635
                        if (!empty($already_inserted[$val['id']])) {
636
                            continue;
637
                        }
638
639
                        $sql = "INSERT INTO " . MAIN_DB_PREFIX . "actioncomm_resources(fk_actioncomm, element_type, fk_element, mandatory, transparency, answer_status)";
640
                        $sql .= " VALUES(" . ((int) $this->id) . ", 'user', " . ((int) $val['id']) . ", " . (empty($val['mandatory']) ? '0' : ((int) $val['mandatory'])) . ", " . (empty($val['transparency']) ? '0' : ((int) $val['transparency'])) . ", " . (empty($val['answer_status']) ? '0' : ((int) $val['answer_status'])) . ")";
641
642
                        $resql = $this->db->query($sql);
643
                        if (!$resql) {
644
                            $error++;
645
                            dol_syslog('Error to process userassigned: ' . $this->db->lasterror(), LOG_ERR);
646
                            $this->errors[] = $this->db->lasterror();
647
                        } else {
648
                            $already_inserted[$val['id']] = true;
649
                        }
650
                        //var_dump($sql);exit;
651
                    }
652
                }
653
            }
654
655
            if (!$error) {
656
                if (!empty($this->socpeopleassigned)) {
657
                    $already_inserted = array();
658
                    foreach ($this->socpeopleassigned as $id => $val) {
659
                        // Common value with new behavior is to have $this->socpeopleassigned an array of idcontact => dummyvalue
660
                        if (!empty($already_inserted[$id])) {
661
                            continue;
662
                        }
663
664
                        $sql = "INSERT INTO " . MAIN_DB_PREFIX . "actioncomm_resources(fk_actioncomm, element_type, fk_element, mandatory, transparency, answer_status)";
665
                        $sql .= " VALUES(" . ((int) $this->id) . ", 'socpeople', " . ((int) $id) . ", 0, 0, 0)";
666
667
                        $resql = $this->db->query($sql);
668
                        if (!$resql) {
669
                            $error++;
670
                            dol_syslog('Error to process socpeopleassigned: ' . $this->db->lasterror(), LOG_ERR);
671
                            $this->errors[] = $this->db->lasterror();
672
                        } else {
673
                            $already_inserted[$id] = true;
674
                        }
675
                    }
676
                }
677
            }
678
679
            if (!$error) {
680
                // Actions on extra fields
681
                $result = $this->insertExtraFields();
682
                if ($result < 0) {
683
                    $error++;
684
                }
685
            }
686
687
            if (!$error && !$notrigger) {
688
                // Call trigger
689
                $result = $this->call_trigger('ACTION_CREATE', $user);
690
                if ($result < 0) {
691
                    $error++;
692
                }
693
                // End call triggers
694
            }
695
696
            if (!$error) {
697
                $this->db->commit();
698
                return $this->id;
699
            } else {
700
                $this->db->rollback();
701
                return -1;
702
            }
703
        } else {
704
            $this->db->rollback();
705
            $this->error = $this->db->lasterror();
706
            return -1;
707
        }
708
    }
709
710
    /**
711
     *  Load an object from its id and create a new one in database
712
     *
713
     *  @param      User            $fuser          Object user making action
714
     *  @param      int             $socid          Id of thirdparty
715
     *  @return     int                             New id of clone
716
     */
717
    public function createFromClone(User $fuser, $socid)
718
    {
719
        global $hookmanager;
720
721
        $error = 0;
722
723
        $this->db->begin();
724
725
        // Load source object
726
        $objFrom = clone $this;
727
728
        // Retrieve all extrafield
729
        // fetch optionals attributes and labels
730
        $this->fetch_optionals();
731
732
        //$this->fetch_userassigned();
733
        $this->fetchResources();
734
735
        $this->id = 0;
736
        $this->recurid = '';
737
        $this->recurrule = '';
738
        $this->recurdateend = '';
739
740
        // Create clone
741
        $this->context['createfromclone'] = 'createfromclone';
742
        $result = $this->create($fuser);
743
        if ($result < 0) {
744
            $error++;
745
        }
746
747
        if (!$error) {
748
            // Hook of thirdparty module
749
            if (is_object($hookmanager)) {
750
                $parameters = array('objFrom' => $objFrom);
751
                $action = '';
752
                $reshook = $hookmanager->executeHooks('createFrom', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
753
                if ($reshook < 0) {
754
                    $this->setErrorsFromObject($hookmanager);
755
                    $error++;
756
                }
757
            }
758
759
            // Call trigger
760
            $result = $this->call_trigger('ACTION_CLONE', $fuser);
761
            if ($result < 0) {
762
                $error++;
763
            }
764
            // End call triggers
765
        }
766
767
        unset($this->context['createfromclone']);
768
769
        // End
770
        if (!$error) {
771
            $this->db->commit();
772
            return $this->id;
773
        } else {
774
            $this->db->rollback();
775
            return -1;
776
        }
777
    }
778
779
    /**
780
     *  Load object from database
781
     *
782
     *  @param  int         $id                 Id of action to get
783
     *  @param  string      $ref                Ref of action to get
784
     *  @param  string      $ref_ext            Ref ext to get
785
     *  @param  string      $email_msgid        Email msgid
786
     *  @param  int<0,1>    $loadresources      1=Load also resources
787
     *  @return int<-1,1>                       Return integer <0 if KO, >0 if OK
788
     */
789
    public function fetch($id, $ref = '', $ref_ext = '', $email_msgid = '', $loadresources = 1)
790
    {
791
        global $langs;
792
793
        if (empty($id) && empty($ref) && empty($ref_ext) && empty($email_msgid)) {
794
            dol_syslog(get_class($this) . "::fetch Bad parameters", LOG_WARNING);
795
            return -1;
796
        }
797
798
        $sql = "SELECT a.id,";
799
        $sql .= " a.ref as ref,";
800
        $sql .= " a.entity,";
801
        $sql .= " a.ref_ext,";
802
        $sql .= " a.datep,";
803
        $sql .= " a.datep2,";
804
        $sql .= " a.durationp,"; // deprecated
805
        $sql .= " a.datec,";
806
        $sql .= " a.tms as datem,";
807
        $sql .= " a.code, a.label, a.note as note_private,";
808
        $sql .= " a.fk_soc,";
809
        $sql .= " a.fk_project,";
810
        $sql .= " a.fk_user_author, a.fk_user_mod,";
811
        $sql .= " a.fk_user_action,";
812
        $sql .= " a.fk_contact, a.percent as percentage,";
813
        $sql .= " a.fk_element as elementid, a.elementtype,";
814
        $sql .= " a.priority, a.fulldayevent, a.location, a.transparency,";
815
        $sql .= " a.email_msgid, a.email_subject, a.email_from, a.email_sender, a.email_to, a.email_tocc, a.email_tobcc, a.errors_to,";
816
        $sql .= " c.id as type_id, c.type as type_type, c.code as type_code, c.libelle as type_label, c.color as type_color, c.picto as type_picto,";
817
        $sql .= " s.nom as socname,";
818
        $sql .= " u.firstname, u.lastname as lastname,";
819
        $sql .= " num_vote, event_paid, a.status";
820
        $sql .= " FROM " . MAIN_DB_PREFIX . "actioncomm as a ";
821
        $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "c_actioncomm as c ON a.fk_action=c.id ";
822
        $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "user as u on u.rowid = a.fk_user_author";
823
        $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "societe as s on s.rowid = a.fk_soc";
824
        $sql .= " WHERE ";
825
        if ($ref) {
826
            $sql .= " a.ref = '" . $this->db->escape($ref) . "'";
827
        } elseif ($ref_ext) {
828
            $sql .= " a.ref_ext = '" . $this->db->escape($ref_ext) . "'";
829
        } elseif ($email_msgid) {
830
            $sql .= " a.email_msgid = '" . $this->db->escape($email_msgid) . "'";
831
        } else {
832
            $sql .= " a.id = " . ((int) $id);
833
        }
834
835
        dol_syslog(get_class($this) . "::fetch", LOG_DEBUG);
836
        $resql = $this->db->query($sql);
837
        if ($resql) {
838
            $num = $this->db->num_rows($resql);
839
            if ($num) {
840
                $obj = $this->db->fetch_object($resql);
841
842
                $this->id         = $obj->id;
843
                $this->entity = $obj->entity;
844
                $this->ref        = $obj->ref;
845
                $this->ref_ext    = $obj->ref_ext;
846
847
                // Properties of parent table llx_c_actioncomm
848
                $this->type_id    = $obj->type_id;
849
                $this->type_code  = $obj->type_code;
850
                $this->type_color = $obj->type_color;
851
                $this->type_picto = $obj->type_picto;
852
                $this->type       = $obj->type_type;
853
                /*$transcode = $langs->trans("Action".$obj->type_code);
854
                $this->type       = (($transcode != "Action".$obj->type_code) ? $transcode : $obj->type_label); */
855
                $transcode = $langs->trans("Action" . $obj->type_code . 'Short');
856
857
                $this->code = $obj->code;
858
                $this->label = $obj->label;
859
                $this->datep = $this->db->jdate($obj->datep);
860
                $this->datef = $this->db->jdate($obj->datep2);
861
862
                $this->datec = $this->db->jdate($obj->datec);
863
                $this->datem = $this->db->jdate($obj->datem);
864
865
                $this->note = $obj->note_private; // deprecated
0 ignored issues
show
Deprecated Code introduced by
The property Dolibarr\Core\Base\CommonObject::$note has been deprecated: Use $note_private instead. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

865
                /** @scrutinizer ignore-deprecated */ $this->note = $obj->note_private; // deprecated

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
866
                $this->note_private = $obj->note_private;
867
                $this->percentage = $obj->percentage;
868
869
                $this->authorid = $obj->fk_user_author;
870
                $this->usermodid = $obj->fk_user_mod;
871
872
                if (!is_object($this->author)) {
873
                    $this->author = new User($this->db); // To avoid warning
874
                }
875
                $this->author->id = $obj->fk_user_author; // deprecated
876
                $this->author->firstname = $obj->firstname; // deprecated
877
                $this->author->lastname = $obj->lastname; // deprecated
878
                if (!is_object($this->usermod)) {
879
                    $this->usermod = new User($this->db); // To avoid warning
880
                }
881
                $this->usermod->id = $obj->fk_user_mod; // deprecated
882
883
                $this->userownerid = $obj->fk_user_action;
884
                $this->priority             = $obj->priority;
885
                $this->fulldayevent         = $obj->fulldayevent;
886
                $this->location             = $obj->location;
887
                $this->transparency         = $obj->transparency;
888
889
                $this->socid = $obj->fk_soc; // To have fetch_thirdparty method working
890
                $this->contact_id = $obj->fk_contact; // To have fetch_contact method working
891
                $this->fk_project = $obj->fk_project; // To have fetch_projet method working
892
893
                //$this->societe->id            = $obj->fk_soc;         // deprecated
894
                //$this->contact->id            = $obj->fk_contact;     // deprecated
895
896
                $this->fk_element = $obj->elementid;
897
                $this->elementid = $obj->elementid;
898
                $this->elementtype = $obj->elementtype;
899
900
                $this->num_vote = $obj->num_vote;
901
                $this->event_paid = $obj->event_paid;
902
                $this->status = $obj->status;
903
904
                //email information
905
                $this->email_msgid = $obj->email_msgid;
906
                $this->email_from = $obj->email_from;
907
                $this->email_sender = $obj->email_sender;
908
                $this->email_to = $obj->email_to;
909
                $this->email_tocc = $obj->email_tocc;
910
                $this->email_tobcc = $obj->email_tobcc;
911
                $this->email_subject = $obj->email_subject;
912
                $this->errors_to = $obj->errors_to;
913
914
                $this->fetch_optionals();
915
916
                if ($loadresources) {
917
                    $this->fetchResources();
918
                }
919
            }
920
921
            $this->db->free($resql);
922
        } else {
923
            $this->error = $this->db->lasterror();
924
            return -1;
925
        }
926
927
        return $num;
928
    }
929
930
    /**
931
     *    Initialize $this->userassigned & this->socpeopleassigned array with list of id of user and contact assigned to event
932
     *
933
     *    @return   int<-1,1>           Return integer <0 if KO, >0 if OK
934
     */
935
    public function fetchResources()
936
    {
937
        $this->userassigned = array();
938
        $this->socpeopleassigned = array();
939
940
        $sql = 'SELECT fk_actioncomm, element_type, fk_element, answer_status, mandatory, transparency';
941
        $sql .= ' FROM ' . MAIN_DB_PREFIX . 'actioncomm_resources';
942
        $sql .= ' WHERE fk_actioncomm = ' . ((int) $this->id);
943
        $sql .= " AND element_type IN ('user', 'socpeople')";
944
        $resql = $this->db->query($sql);
945
        if ($resql) {
946
            // If owner is known, we must but id first into list
947
            if ($this->userownerid > 0) {
948
                $this->userassigned[$this->userownerid] = array('id' => $this->userownerid); // Set first so will be first into list.
949
            }
950
951
            while ($obj = $this->db->fetch_object($resql)) {
952
                if ($obj->fk_element > 0) {
953
                    switch ($obj->element_type) {
954
                        case 'user':
955
                            $this->userassigned[$obj->fk_element] = array('id' => $obj->fk_element, 'mandatory' => $obj->mandatory, 'answer_status' => $obj->answer_status, 'transparency' => $obj->transparency);
956
                            if (empty($this->userownerid)) {
957
                                $this->userownerid = $obj->fk_element; // If not defined (should not happened, we fix this)
958
                            }
959
                            break;
960
                        case 'socpeople':
961
                            $this->socpeopleassigned[$obj->fk_element] = array('id' => $obj->fk_element, 'mandatory' => $obj->mandatory, 'answer_status' => $obj->answer_status, 'transparency' => $obj->transparency);
962
                            break;
963
                    }
964
                }
965
            }
966
967
            return 1;
968
        } else {
969
            dol_print_error($this->db);
970
            return -1;
971
        }
972
    }
973
974
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
975
    /**
976
     *    Initialize this->userassigned array with list of id of user assigned to event
977
     *
978
     *    @param    bool    $override   Override $this->userownerid when empty. TODO This should be false by default. True is here to fix corrupted data.
979
     *    @return   int<-1,1>           Return integer <0 if KO, >0 if OK
980
     */
981
    public function fetch_userassigned($override = true)
982
    {
983
		// phpcs:enable
984
        $sql = "SELECT fk_actioncomm, element_type, fk_element, answer_status, mandatory, transparency";
985
        $sql .= " FROM " . MAIN_DB_PREFIX . "actioncomm_resources";
986
        $sql .= " WHERE element_type = 'user' AND fk_actioncomm = " . ((int) $this->id);
987
988
        $resql2 = $this->db->query($sql);
989
        if ($resql2) {
990
            $this->userassigned = array();
991
992
            // If owner is known, we must but id first into list
993
            if ($this->userownerid > 0) {
994
                // Set first so will be first into list.
995
                $this->userassigned[$this->userownerid] = array('id' => $this->userownerid);
996
            }
997
998
            while ($obj = $this->db->fetch_object($resql2)) {
999
                if ($obj->fk_element > 0) {
1000
                    $this->userassigned[$obj->fk_element] = array('id' => $obj->fk_element,
1001
                                                                  'mandatory' => $obj->mandatory,
1002
                                                                  'answer_status' => $obj->answer_status,
1003
                                                                  'transparency' => $obj->transparency);
1004
                }
1005
1006
                if ($override === true) {
1007
                    // If not defined (should not happened, we fix this)
1008
                    if (empty($this->userownerid)) {
1009
                        $this->userownerid = $obj->fk_element;
1010
                    }
1011
                }
1012
            }
1013
1014
            return 1;
1015
        } else {
1016
            dol_print_error($this->db);
1017
            return -1;
1018
        }
1019
    }
1020
1021
    /**
1022
     *    Delete event from database
1023
     *
1024
     *    @param    User        $user           User making the delete
1025
     *    @param    int<0,1>    $notrigger      1 = disable triggers, 0 = enable triggers
1026
     *    @return   int<-2,1>                   Return integer <0 if KO, >0 if OK
1027
     */
1028
    public function delete($user, $notrigger = 0)
1029
    {
1030
        $error = 0;
1031
1032
        dol_syslog(get_class($this) . "::delete", LOG_DEBUG);
1033
1034
        $this->db->begin();
1035
1036
        // remove categorie association
1037
        if (!$error) {
1038
            $sql = "DELETE FROM " . MAIN_DB_PREFIX . "categorie_actioncomm";
1039
            $sql .= " WHERE fk_actioncomm=" . ((int) $this->id);
1040
1041
            $res = $this->db->query($sql);
1042
            if (!$res) {
1043
                $this->error = $this->db->lasterror();
1044
                $error++;
1045
            }
1046
        }
1047
1048
        // remove actioncomm_resources
1049
        if (!$error) {
1050
            $sql = "DELETE FROM " . MAIN_DB_PREFIX . "actioncomm_resources";
1051
            $sql .= " WHERE fk_actioncomm=" . ((int) $this->id);
1052
1053
            $res = $this->db->query($sql);
1054
            if (!$res) {
1055
                $this->error = $this->db->lasterror();
1056
                $error++;
1057
            }
1058
        }
1059
1060
        if (!$error) {
1061
            $sql = "DELETE FROM " . MAIN_DB_PREFIX . "actioncomm_reminder";
1062
            $sql .= " WHERE fk_actioncomm = " . ((int) $this->id);
1063
1064
            $res = $this->db->query($sql);
1065
            if (!$res) {
1066
                $this->error = $this->db->lasterror();
1067
                $error++;
1068
            }
1069
        }
1070
1071
        // Removed extrafields
1072
        if (!$error) {
1073
            $result = $this->deleteExtraFields();
1074
            if ($result < 0) {
1075
                $error++;
1076
                dol_syslog(get_class($this) . "::delete error -3 " . $this->error, LOG_ERR);
1077
            }
1078
        }
1079
1080
        // remove actioncomm
1081
        if (!$error) {
1082
            $sql = "DELETE FROM " . MAIN_DB_PREFIX . "actioncomm";
1083
            $sql .= " WHERE id=" . ((int) $this->id);
1084
1085
            $res = $this->db->query($sql);
1086
            if (!$res) {
1087
                $this->error = $this->db->lasterror();
1088
                $error++;
1089
            }
1090
        }
1091
1092
        if (!$error) {
1093
            if (!$notrigger) {
1094
                // Call trigger
1095
                $result = $this->call_trigger('ACTION_DELETE', $user);
1096
                if ($result < 0) {
1097
                    $error++;
1098
                }
1099
                // End call triggers
1100
            }
1101
1102
            if (!$error) {
1103
                $this->db->commit();
1104
                return 1;
1105
            } else {
1106
                $this->db->rollback();
1107
                return -2;
1108
            }
1109
        } else {
1110
            $this->db->rollback();
1111
            $this->error = $this->db->lasterror();
1112
            return -1;
1113
        }
1114
    }
1115
1116
    /**
1117
     *    Update action into database
1118
     *    If percentage = 100, on met a jour date 100%
1119
     *
1120
     *    @param    User        $user           Object user making change
1121
     *    @param    int<0,1>    $notrigger      1 = disable triggers, 0 = enable triggers
1122
     *    @return   int<-2,1>                   Return integer <0 if KO, >0 if OK
1123
     */
1124
    public function update(User $user, $notrigger = 0)
1125
    {
1126
        $error = 0;
1127
1128
        // Clean parameters
1129
        $this->label = trim($this->label);
1130
        $this->note_private = dol_htmlcleanlastbr(trim(!isset($this->note_private) ? $this->note : $this->note_private));
0 ignored issues
show
Deprecated Code introduced by
The property Dolibarr\Core\Base\CommonObject::$note has been deprecated: Use $note_private instead. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

1130
        $this->note_private = dol_htmlcleanlastbr(trim(!isset($this->note_private) ? /** @scrutinizer ignore-deprecated */ $this->note : $this->note_private));

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
1131
        if (empty($this->percentage)) {
1132
            $this->percentage = 0;
1133
        }
1134
        if (empty($this->priority) || !is_numeric($this->priority)) {
1135
            $this->priority = 0;
1136
        }
1137
        if (empty($this->transparency)) {
1138
            $this->transparency = 0;
1139
        }
1140
        if (empty($this->fulldayevent)) {
1141
            $this->fulldayevent = 0;
1142
        }
1143
        if ($this->percentage > 100) {
1144
            $this->percentage = 100;
1145
        }
1146
        //if ($this->percentage == 100 && ! $this->dateend) $this->dateend = $this->date;
1147
        if ($this->datep && $this->datef) {
1148
            $this->durationp = ($this->datef - $this->datep); // deprecated
0 ignored issues
show
Deprecated Code introduced by
The property Dolibarr\Code\Comm\Classes\ActionComm::$durationp has been deprecated: Use ($datef - $datep) ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

1148
            /** @scrutinizer ignore-deprecated */ $this->durationp = ($this->datef - $this->datep); // deprecated

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
1149
        }
1150
        //if ($this->date  && $this->dateend) $this->durationa=($this->dateend - $this->date);
1151
        if ($this->datep && $this->datef && $this->datep > $this->datef) {
1152
            $this->datef = $this->datep;
1153
        }
1154
        //if ($this->date  && $this->dateend && $this->date > $this->dateend) $this->dateend=$this->date;
1155
        if ($this->fk_project < 0) {
1156
            $this->fk_project = 0;
1157
        }
1158
1159
        $socid = (($this->socid > 0) ? $this->socid : 0);
1160
        $contactid = (($this->contact_id > 0) ? $this->contact_id : 0);
1161
        $userownerid = ($this->userownerid ? $this->userownerid : 0);
1162
1163
        // If a type_id is set, we must also have the type_code set
1164
        if ($this->type_id > 0) {
1165
            if (empty($this->type_code)) {
1166
                $cactioncomm = new CActionComm($this->db);
1167
                $result = $cactioncomm->fetch($this->type_id);
1168
                if ($result >= 0 && !empty($cactioncomm->code)) {
1169
                    $this->type_code = $cactioncomm->code;
1170
                }
1171
            }
1172
        }
1173
1174
        $code = $this->code;
1175
        if (empty($code) || (!empty($this->oldcopy) && $this->oldcopy->type_code != $this->type_code)) {    // If code unknown or if we change the type, we reset $code too
0 ignored issues
show
Bug Best Practice introduced by
The property type_code does not exist on Dolibarr\Core\Base\CommonObject. Since you implemented __get, consider adding a @property annotation.
Loading history...
1176
            $code = $this->type_code;
1177
        }
1178
1179
        $this->db->begin();
1180
1181
        $sql = "UPDATE " . MAIN_DB_PREFIX . "actioncomm";
1182
        $sql .= " SET percent = '" . $this->db->escape($this->percentage) . "'";
1183
        $sql .= ", fk_action = " . (int) $this->type_id;
1184
        $sql .= ", code = " . ($code ? "'" . $this->db->escape($code) . "'" : "null");
1185
        $sql .= ", label = " . ($this->label ? "'" . $this->db->escape($this->label) . "'" : "null");
1186
        $sql .= ", datep = " . (strval($this->datep) != '' ? "'" . $this->db->idate($this->datep) . "'" : 'null');
1187
        $sql .= ", datep2 = " . (strval($this->datef) != '' ? "'" . $this->db->idate($this->datef) . "'" : 'null');
1188
        $sql .= ", durationp = " . (isset($this->durationp) && $this->durationp >= 0 && $this->durationp != '' ? "'" . $this->db->escape($this->durationp) . "'" : "null"); // deprecated
0 ignored issues
show
Deprecated Code introduced by
The property Dolibarr\Code\Comm\Classes\ActionComm::$durationp has been deprecated: Use ($datef - $datep) ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

1188
        $sql .= ", durationp = " . (isset(/** @scrutinizer ignore-deprecated */ $this->durationp) && $this->durationp >= 0 && $this->durationp != '' ? "'" . $this->db->escape($this->durationp) . "'" : "null"); // deprecated

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
1189
        $sql .= ", note = '" . $this->db->escape($this->note_private) . "'";
1190
        $sql .= ", fk_project =" . ($this->fk_project > 0 ? ((int) $this->fk_project) : "null");
1191
        $sql .= ", fk_soc =" . ($socid > 0 ? ((int) $socid) : "null");
1192
        $sql .= ", fk_contact =" . ($contactid > 0 ? ((int) $contactid) : "null");
1193
        $sql .= ", priority = '" . $this->db->escape($this->priority) . "'";
1194
        $sql .= ", fulldayevent = '" . $this->db->escape($this->fulldayevent) . "'";
1195
        $sql .= ", location = " . ($this->location ? "'" . $this->db->escape($this->location) . "'" : "null");
1196
        $sql .= ", transparency = '" . $this->db->escape($this->transparency) . "'";
1197
        $sql .= ", fk_user_mod = " . ((int) $user->id);
1198
        $sql .= ", fk_user_action = " . ($userownerid > 0 ? ((int) $userownerid) : "null");
1199
        if (!empty($this->fk_element)) {
1200
            $sql .= ", fk_element=" . ($this->fk_element ? ((int) $this->fk_element) : "null");
1201
        }
1202
        if (!empty($this->elementtype)) {
1203
            $sql .= ", elementtype=" . ($this->elementtype ? "'" . $this->db->escape($this->elementtype) . "'" : "null");
1204
        }
1205
        if (!empty($this->num_vote)) {
1206
            $sql .= ", num_vote=" . ($this->num_vote ? (int) $this->num_vote : null);
1207
        }
1208
        if (!empty($this->event_paid)) {
1209
            $sql .= ", event_paid=" . ($this->event_paid ? (int) $this->event_paid : 0);
1210
        }
1211
        if (!empty($this->status)) {
1212
            $sql .= ", status=" . ($this->status ? (int) $this->status : 0);
1213
        }
1214
        $sql .= " WHERE id=" . ((int) $this->id);
1215
1216
        dol_syslog(get_class($this) . "::update", LOG_DEBUG);
1217
        if ($this->db->query($sql)) {
1218
            $action = 'update';
1219
1220
            // Actions on extra fields
1221
            if (!$error) {
1222
                $result = $this->insertExtraFields();
1223
                if ($result < 0) {
1224
                    $error++;
1225
                }
1226
            }
1227
1228
            // Now insert assignedusers
1229
            if (!$error) {
1230
                $sql = "DELETE FROM " . MAIN_DB_PREFIX . "actioncomm_resources where fk_actioncomm = " . ((int) $this->id) . " AND element_type = 'user'";
1231
                $resql = $this->db->query($sql);
1232
1233
                $already_inserted = array();
1234
                foreach ($this->userassigned as $key => $val) {
1235
                    if (!is_array($val)) {  // For backward compatibility when val=id
1236
                        $val = array('id' => $val);
1237
                    }
1238
                    if (!empty($already_inserted[$val['id']])) {
1239
                        continue;
1240
                    }
1241
1242
                    $sql = "INSERT INTO " . MAIN_DB_PREFIX . "actioncomm_resources(fk_actioncomm, element_type, fk_element, mandatory, transparency, answer_status)";
1243
                    $sql .= " VALUES(" . ((int) $this->id) . ", 'user', " . ((int) $val['id']) . ", " . (empty($val['mandatory']) ? '0' : ((int) $val['mandatory'])) . ", " . (empty($val['transparency']) ? '0' : ((int) $val['transparency'])) . ", " . (empty($val['answer_status']) ? '0' : ((int) $val['answer_status'])) . ")";
1244
1245
                    $resql = $this->db->query($sql);
1246
                    if (!$resql) {
1247
                        $error++;
1248
                        $this->errors[] = $this->db->lasterror();
1249
                    } else {
1250
                        $already_inserted[$val['id']] = true;
1251
                    }
1252
                    //var_dump($sql);exit;
1253
                }
1254
            }
1255
1256
            if (!$error) {
1257
                $sql = "DELETE FROM " . MAIN_DB_PREFIX . "actioncomm_resources where fk_actioncomm = " . ((int) $this->id) . " AND element_type = 'socpeople'";
1258
                $resql = $this->db->query($sql);
1259
1260
                if (!empty($this->socpeopleassigned)) {
1261
                    $already_inserted = array();
1262
                    foreach ($this->socpeopleassigned as $val) {
1263
                        if (!is_array($val)) {  // For backward compatibility when val=id
1264
                            $val = array('id' => $val);
1265
                        }
1266
                        if (!empty($already_inserted[$val['id']])) {
1267
                            continue;
1268
                        }
1269
1270
                        $sql = "INSERT INTO " . MAIN_DB_PREFIX . "actioncomm_resources(fk_actioncomm, element_type, fk_element, mandatory, transparency, answer_status)";
1271
                        $sql .= " VALUES(" . ((int) $this->id) . ", 'socpeople', " . ((int) $val['id']) . ", 0, 0, 0)";
1272
1273
                        $resql = $this->db->query($sql);
1274
                        if (!$resql) {
1275
                            $error++;
1276
                            $this->errors[] = $this->db->lasterror();
1277
                        } else {
1278
                            $already_inserted[$val['id']] = true;
1279
                        }
1280
                    }
1281
                }
1282
            }
1283
1284
            if (!$error && !$notrigger) {
1285
                // Call trigger
1286
                $result = $this->call_trigger('ACTION_MODIFY', $user);
1287
                if ($result < 0) {
1288
                    $error++;
1289
                }
1290
                // End call triggers
1291
            }
1292
1293
            if (!$error) {
1294
                $this->db->commit();
1295
                return 1;
1296
            } else {
1297
                $this->db->rollback();
1298
                dol_syslog(get_class($this) . "::update " . implode(',', $this->errors), LOG_ERR);
1299
                return -2;
1300
            }
1301
        } else {
1302
            $this->db->rollback();
1303
            $this->error = $this->db->lasterror();
1304
            return -1;
1305
        }
1306
    }
1307
1308
    /**
1309
     *  Load all objects with filters.
1310
     *  @TODO WARNING: This make a fetch on all records instead of making one request with a join.
1311
     *
1312
     *  @param      int     $socid          Filter by thirdparty
1313
     *  @param      int     $fk_element     Id of element action is linked to
1314
     *  @param      string  $elementtype    Type of element action is linked to
1315
     *  @param      string  $filter         Other filter
1316
     *  @param      string  $sortfield      Sort on this field
1317
     *  @param      string  $sortorder      ASC or DESC
1318
     *  @param      int     $limit          Limit number of answers
1319
     *  @return     ActionComm[]|string     Error string if KO, array with actions if OK
1320
     */
1321
    public function getActions($socid = 0, $fk_element = 0, $elementtype = '', $filter = '', $sortfield = 'a.datep', $sortorder = 'DESC', $limit = 0)
1322
    {
1323
        global $hookmanager;
1324
1325
        $resarray = array();
1326
1327
        dol_syslog(get_class() . "::getActions", LOG_DEBUG);
1328
1329
        // Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context
1330
        if (!is_object($hookmanager)) {
1331
            include_once DOL_DOCUMENT_ROOT . '/core/class/hookmanager.class.php';
1332
            $hookmanager = new HookManager($this->db);
1333
        }
1334
        $hookmanager->initHooks(array('agendadao'));
1335
1336
        $sql = "SELECT a.id";
1337
        $sql .= " FROM " . MAIN_DB_PREFIX . "actioncomm as a";
1338
        // Fields from hook
1339
        $parameters = array('sql' => &$sql, 'socid' => $socid, 'fk_element' => $fk_element, 'elementtype' => $elementtype);
1340
        $reshook = $hookmanager->executeHooks('getActionsListFrom', $parameters);    // Note that $action and $object may have been modified by hook
1341
        if (!empty($hookmanager->resPrint)) {
1342
            $sql .= $hookmanager->resPrint;
1343
        }
1344
        $sql .= " WHERE a.entity IN (" . getEntity('agenda') . ")";
1345
        if (!empty($socid)) {
1346
            $sql .= " AND a.fk_soc = " . ((int) $socid);
1347
        }
1348
        if (!empty($elementtype)) {
1349
            if ($elementtype == 'project') {
1350
                $sql .= ' AND a.fk_project = ' . ((int) $fk_element);
1351
            } elseif ($elementtype == 'contact') {
1352
                $sql .= ' AND a.id IN';
1353
                $sql .= " (SELECT fk_actioncomm FROM " . MAIN_DB_PREFIX . "actioncomm_resources WHERE";
1354
                $sql .= " element_type = 'socpeople' AND fk_element = " . ((int) $fk_element) . ')';
1355
            } else {
1356
                $sql .= " AND a.fk_element = " . ((int) $fk_element) . " AND a.elementtype = '" . $this->db->escape($elementtype) . "'";
1357
            }
1358
        }
1359
        if (!empty($filter)) {
1360
            $sql .= $filter;
1361
        }
1362
        // Fields where hook
1363
        $parameters = array('sql' => &$sql, 'socid' => $socid, 'fk_element' => $fk_element, 'elementtype' => $elementtype);
1364
        $reshook = $hookmanager->executeHooks('getActionsListWhere', $parameters);    // Note that $action and $object may have been modified by hook
1365
        if (!empty($hookmanager->resPrint)) {
1366
            $sql .= $hookmanager->resPrint;
1367
        }
1368
        if ($sortorder && $sortfield) {
1369
            $sql .= $this->db->order($sortfield, $sortorder);
1370
        }
1371
        $sql .= $this->db->plimit($limit, 0);
1372
1373
        $resql = $this->db->query($sql);
1374
        if ($resql) {
1375
            $num = $this->db->num_rows($resql);
1376
1377
            if ($num) {
1378
                for ($i = 0; $i < $num; $i++) {
1379
                    $obj = $this->db->fetch_object($resql);
1380
                    $actioncommstatic = new ActionComm($this->db);
1381
                    $actioncommstatic->fetch($obj->id);
1382
                    $resarray[$i] = $actioncommstatic;
1383
                }
1384
            }
1385
            $this->db->free($resql);
1386
            return $resarray;
1387
        } else {
1388
            return $this->db->lasterror();
1389
        }
1390
    }
1391
1392
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1393
    /**
1394
     * Load indicators for dashboard (this->nbtodo and this->nbtodolate)
1395
     *
1396
     * @param   User    $user               Object user
1397
     * @param   int     $load_state_board   Load indicator array this->nb
1398
     * @return WorkboardResponse|int<-1,1>  Return integer <0 if KO, WorkboardResponse if OK
1399
     */
1400
    public function load_board($user, $load_state_board = 0)
1401
    {
1402
		// phpcs:enable
1403
        global $conf, $langs;
1404
1405
        if (empty($load_state_board)) {
1406
            $sql = "SELECT a.id, a.datep as dp";
1407
        } else {
1408
            $this->nb = array();
1409
            $sql = "SELECT count(a.id) as nb";
1410
        }
1411
        $sql .= " FROM " . MAIN_DB_PREFIX . "actioncomm as a";
1412
        if (!$user->hasRight('agenda', 'allactions', 'read')) {
1413
            $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "actioncomm_resources AS ar ON a.id = ar.fk_actioncomm AND ar.element_type ='user' AND ar.fk_element = " . ((int) $user->id);
1414
        }
1415
        $sql .= " WHERE 1 = 1";
1416
        if (empty($load_state_board)) {
1417
            $sql .= " AND a.percent >= 0 AND a.percent < 100";
1418
        }
1419
        $sql .= " AND a.entity IN (" . getEntity('agenda') . ")";
1420
        if (!$user->hasRight('agenda', 'allactions', 'read')) {
1421
            $sql .= " AND (a.fk_user_author = " . ((int) $user->id) . " OR a.fk_user_action = " . ((int) $user->id);
1422
            $sql .= " OR ar.fk_element = " . ((int) $user->id);
1423
            $sql .= ")";
1424
        }
1425
        // If the internal user must only see his customers, force searching by him
1426
        $search_sale = 0;
1427
        if (!$user->hasRight('societe', 'client', 'voir')) {
1428
            $search_sale = $user->id;
1429
        }
1430
        // Search on sale representative
1431
        if ($search_sale && $search_sale != '-1') {
1432
            if ($search_sale == -2) {
1433
                $sql .= " AND NOT EXISTS (SELECT sc.fk_soc FROM " . MAIN_DB_PREFIX . "societe_commerciaux as sc WHERE sc.fk_soc = a.fk_soc)";
1434
            } elseif ($search_sale > 0) {
1435
                $sql .= " AND EXISTS (SELECT sc.fk_soc FROM " . MAIN_DB_PREFIX . "societe_commerciaux as sc WHERE sc.fk_soc = a.fk_soc AND sc.fk_user = " . ((int) $search_sale) . ")";
1436
            }
1437
        }
1438
1439
        $resql = $this->db->query($sql);
1440
        if ($resql) {
1441
            $response = null;  // Ensure the variable is defined
1442
            if (empty($load_state_board)) {
1443
                $agenda_static = new ActionComm($this->db);
1444
                $response = new WorkboardResponse();
1445
                $response->warning_delay = $conf->agenda->warning_delay / 60 / 60 / 24;
1446
                $response->label = $langs->trans("ActionsToDo");
1447
                $response->labelShort = $langs->trans("ActionsToDoShort");
1448
                $response->url = constant('BASE_URL') . '/comm/action/list.php?mode=show_list&actioncode=0&status=todo&mainmenu=agenda';
1449
                if ($user->hasRight("agenda", "allactions", "read")) {
1450
                    $response->url .= '&filtert=-1';
1451
                }
1452
                $response->img = img_object('', "action", 'class="inline-block valigntextmiddle"');
1453
            }
1454
            // This assignment in condition is not a bug. It allows walking the results.
1455
            while ($obj = $this->db->fetch_object($resql)) {
1456
                if (empty($load_state_board)) {
1457
                    '@phan-var-force WorkboardResponse $response
1458
					 @phan-var-force ActionComm $agenda_static';
1459
                    $response->nbtodo++;
1460
                    $agenda_static->datep = $this->db->jdate($obj->dp);
1461
                    if ($agenda_static->hasDelay()) {
1462
                        $response->nbtodolate++;
1463
                    }
1464
                } else {
1465
                    $this->nb["actionscomm"] = $obj->nb;
1466
                }
1467
            }
1468
1469
            $this->db->free($resql);
1470
            if (empty($load_state_board) && $response instanceof WorkboardResponse) {
1471
                return $response;
1472
            } else {
1473
                return 1;
1474
            }
1475
        } else {
1476
            dol_print_error($this->db);
1477
            $this->error = $this->db->error();
1478
            return -1;
1479
        }
1480
    }
1481
1482
1483
    /**
1484
     *  Charge les information d'ordre info dans l'objet facture
1485
     *
1486
     *  @param  int     $id         Id de la facture a charger
1487
     *  @return void
1488
     */
1489
    public function info($id)
1490
    {
1491
        $sql = 'SELECT ';
1492
        $sql .= ' a.id,';
1493
        $sql .= ' datec,';
1494
        $sql .= ' tms as datem,';
1495
        $sql .= ' fk_user_author,';
1496
        $sql .= ' fk_user_mod';
1497
        $sql .= ' FROM ' . MAIN_DB_PREFIX . 'actioncomm as a';
1498
        $sql .= ' WHERE a.id = ' . ((int) $id);
1499
1500
        dol_syslog(get_class($this) . "::info", LOG_DEBUG);
1501
        $result = $this->db->query($sql);
1502
        if ($result) {
1503
            if ($this->db->num_rows($result)) {
1504
                $obj = $this->db->fetch_object($result);
1505
1506
                $this->id = $obj->id;
1507
1508
                $this->user_creation_id = $obj->fk_user_author;
1509
                $this->user_modification_id = $obj->fk_user_mod;
1510
                $this->date_creation     = $this->db->jdate($obj->datec);
1511
                $this->date_modification = empty($obj->datem) ? '' : $this->db->jdate($obj->datem);
1512
            }
1513
            $this->db->free($result);
1514
        } else {
1515
            dol_print_error($this->db);
1516
        }
1517
    }
1518
1519
1520
    /**
1521
     *  Return the label of the status
1522
     *
1523
     *  @param  int<0,7>    $mode           0=Long label, 1=Short label, 2=Picto+Short label, 3=Picto, 4=Picto+Short label, 5=Short label+Picto, 6=Picto+Long label, 7=Very short label+Picto
1524
     *  @param  int<0,1>    $hidenastatus   1=Show nothing if status is "Not applicable"
1525
     *  @return string                  String with status
1526
     */
1527
    public function getLibStatut($mode, $hidenastatus = 0)
1528
    {
1529
        return $this->LibStatut($this->percentage, $mode, $hidenastatus, $this->datep);
1530
    }
1531
1532
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1533
    /**
1534
     *  Return label of action status
1535
     *
1536
     *  @param  int<0,100>  $percent        Percent
1537
     *  @param  int<0,7>    $mode           0=Long label, 1=Short label, 2=Picto+Short label, 3=Picto, 4=Picto+Short label, 5=Short label+Picto, 6=Picto+Long label, 7=Very short label+Picto
1538
     *  @param  int<0,1>    $hidenastatus   1=Show nothing if status is "Not applicable"
1539
     *  @param  int|string  $datestart      Date start of event
1540
     *  @return string                      Label
1541
     */
1542
    public function LibStatut($percent, $mode, $hidenastatus = 0, $datestart = '')
1543
    {
1544
		// phpcs:enable
1545
        global $langs;
1546
1547
        $labelStatus = $langs->transnoentitiesnoconv('StatusNotApplicable');
1548
        if ($percent == -1 && !$hidenastatus) {
1549
            $labelStatus = $langs->transnoentitiesnoconv('StatusNotApplicable');
1550
        } elseif ($percent == 0) {
1551
            $labelStatus = $langs->transnoentitiesnoconv('StatusActionToDo') . ' (0%)';
1552
        } elseif ($percent > 0 && $percent < 100) {
1553
            $labelStatus = $langs->transnoentitiesnoconv('StatusActionInProcess') . ' (' . $percent . '%)';
1554
        } elseif ($percent >= 100) {
1555
            $labelStatus = $langs->transnoentitiesnoconv('StatusActionDone') . ' (100%)';
1556
        }
1557
1558
        $labelStatusShort = $langs->transnoentitiesnoconv('StatusNotApplicable');
1559
        if ($percent == -1 && !$hidenastatus) {
1560
            $labelStatusShort = $langs->trans('NA');
1561
        } elseif ($percent == 0) {
1562
            $labelStatusShort = '0%';
1563
        } elseif ($percent > 0 && $percent < 100) {
1564
            $labelStatusShort = $percent . '%';
1565
        } elseif ($percent >= 100) {
1566
            $labelStatusShort = '100%';
1567
        }
1568
1569
        $statusType = 'status9';
1570
        if ($percent == -1 && !$hidenastatus) {
1571
            $statusType = 'status9';
1572
        }
1573
        if ($percent == 0) {
1574
            $statusType = 'status1';
1575
        }
1576
        if ($percent > 0 && $percent < 100) {
1577
            $statusType = 'status3';
1578
        }
1579
        if ($percent >= 100) {
1580
            $statusType = 'status6';
1581
        }
1582
1583
        return dolGetStatus($labelStatus, $labelStatusShort, '', $statusType, $mode);
1584
    }
1585
1586
    /**
1587
     * getTooltipContentArray
1588
     * @param array<string,mixed> $params params to construct tooltip data
1589
     * @since v18
1590
     * @return array{picto:string,ref?:string,title?:string,labeltype?:string,location?:string,transparency?:string,space?:string,mailtopic?:string,mailfrom?:string,mailto?:string,mailcc?:string,description?:string,note?:string,categories?:string}
1591
     */
1592
    public function getTooltipContentArray($params)
1593
    {
1594
        global $conf, $langs, $user;
1595
        $langs->load('agenda');
1596
1597
        $datas = array();
1598
        $nofetch = !empty($params['nofetch']);
1599
1600
        // Set label of type
1601
        $labeltype = '';
1602
        if ($this->type_code) {
1603
            $langs->load("commercial");
1604
            $labeltype = ($langs->transnoentities("Action" . $this->type_code) != "Action" . $this->type_code) ? $langs->transnoentities("Action" . $this->type_code) : $this->type_label;
1605
        }
1606
        if (!getDolGlobalString('AGENDA_USE_EVENT_TYPE')) {
1607
            if ($this->type_code != 'AC_OTH_AUTO') {
1608
                $labeltype = $langs->trans('ActionAC_MANUAL');
1609
            }
1610
        }
1611
        $datas['picto'] = img_picto('', $this->picto) . ' <u>' . $langs->trans('Action') . '</u>';
1612
        if (!empty($this->ref)) {
1613
            $datas['ref'] = '<br><b>' . $langs->trans('Ref') . ':</b> ' . dol_escape_htmltag($this->ref);
1614
        }
1615
        if (!empty($this->label)) {
1616
            $datas['title'] = '<br><b>' . $langs->trans('Title') . ':</b> ' . dol_escape_htmltag($this->label);
1617
        }
1618
        if (!empty($labeltype)) {
1619
            $datas['labeltype'] = '<br><b>' . $langs->trans('Type') . ':</b> ' . dol_escape_htmltag($labeltype);
1620
        }
1621
        if (!empty($this->location)) {
1622
            $datas['location'] = '<br><b>' . $langs->trans('Location') . ':</b> ' . dol_escape_htmltag($this->location);
1623
        }
1624
        if (isset($this->transparency)) {
1625
            $datas['transparency'] = '<br><b>' . $langs->trans('Busy') . ':</b> ' . yn($this->transparency);
1626
        }
1627
        if (!empty($this->email_msgid)) {
1628
            $langs->load("mails");
1629
            $datas['space'] = '<br>';
1630
            // $datas['email'] = '<br><b>'.img_picto('', 'email').' '.$langs->trans("Email").'</b>';
1631
            $datas['mailtopic'] = '<br><b>' . $langs->trans('MailTopic') . ':</b> ' . dol_escape_htmltag($this->email_subject);
1632
            $datas['mailfrom'] = '<br><b>' . $langs->trans('MailFrom') . ':</b> ' . str_replace(array('<', '>'), array('&amp;lt', '&amp;gt'), $this->email_from);
1633
            $datas['mailto'] = '<br><b>' . $langs->trans('MailTo') . ':</b> ' . str_replace(array('<', '>'), array('&amp;lt', '&amp;gt'), $this->email_to);
1634
            if (!empty($this->email_tocc)) {
1635
                $datas['mailcc'] = '<br><b>' . $langs->trans('MailCC') . ':</b> ' . str_replace(array('<', '>'), array('&amp;lt', '&amp;gt'), $this->email_tocc);
1636
            }
1637
            /* Disabled because bcc must remain by definition not visible
1638
            if (!empty($this->email_tobcc)) {
1639
                $datas['mailccc'] = '<br><b>'.$langs->trans('MailCCC').':</b> '.$this->email_tobcc;
1640
            } */
1641
        }
1642
        if (!empty($this->note_private)) {
1643
            $datas['description'] = '<br><b>' . $langs->trans('Description') . ':</b><br>';
1644
            // Try to limit length of content
1645
            $texttoshow = dolGetFirstLineOfText($this->note_private, 10);
1646
            // Restrict height of content into the tooltip
1647
            $datas['note'] = '<div class="tenlinesmax">';
1648
            $datas['note'] .= (dol_textishtml($texttoshow) ? str_replace(array("\r", "\n"), "", $texttoshow) : str_replace(array("\r", "\n"), '<br>', $texttoshow));
1649
            $datas['note'] .= '</div>';
1650
        }
1651
        // show categories for this record only in ajax to not overload lists
1652
        if (isModEnabled('category') && !$nofetch) {
1653
            require_once constant('DOL_DOCUMENT_ROOT') . '/categories/class/categorie.class.php';
1654
            $form = new Form($this->db);
1655
            $datas['categories'] = '<br>' . $form->showCategories($this->id, Categorie::TYPE_ACTIONCOMM, 1);
1656
        }
1657
1658
        return $datas;
1659
    }
1660
1661
    /**
1662
     *  Return URL of event
1663
     *  Use $this->id, $this->type_code, $this->label and $this->type_label
1664
     *
1665
     *  @param  int<0,2>    $withpicto              0 = No picto, 1 = Include picto into link, 2 = Only picto
1666
     *  @param  int         $maxlength              Max number of characters into label. If negative, use the ref as label.
1667
     *  @param  string      $classname              Force style class on a link
1668
     *  @param  string      $option                 '' = Link to action, 'birthday'= Link to contact, 'holiday' = Link to leave
1669
     *  @param  int<0,1>    $overwritepicto         1 = Overwrite picto with this one
1670
     *  @param  int<0,1>    $notooltip              1 = Disable tooltip
1671
     *  @param  int<-1,1>   $save_lastsearch_value  -1 = Auto, 0 = No save of lastsearch_values when clicking, 1 = Save lastsearch_values whenclicking
1672
     *  @return string                          Chaine avec URL
1673
     */
1674
    public function getNomUrl($withpicto = 0, $maxlength = 0, $classname = '', $option = '', $overwritepicto = 0, $notooltip = 0, $save_lastsearch_value = -1)
1675
    {
1676
        global $conf, $langs, $user, $hookmanager, $action;
1677
1678
        if (!empty($conf->dol_no_mouse_hover)) {
1679
            $notooltip = 1; // Force disable tooltips
1680
        }
1681
1682
        $canread = 0;
1683
        if ($user->hasRight('agenda', 'myactions', 'read') && ($this->authorid == $user->id || $this->userownerid == $user->id)) {
1684
            $canread = 1; // Can read my event
1685
        }
1686
        if ($user->hasRight('agenda', 'myactions', 'read') && array_key_exists($user->id, $this->userassigned)) {
1687
            $canread = 1; // Can read my event i am assigned
1688
        }
1689
        if ($user->hasRight('agenda', 'allactions', 'read')) {
1690
            $canread = 1; // Can read all event of other
1691
        }
1692
        if (!$canread) {
1693
            $option = 'nolink';
1694
        }
1695
1696
        $label = $this->label;
1697
1698
        $result = '';
1699
1700
        // Set label of type
1701
        $labeltype = '';
1702
        if ($this->type_code) {
1703
            $langs->load("commercial");
1704
            $labeltype = ($langs->transnoentities("Action" . $this->type_code) != "Action" . $this->type_code) ? $langs->transnoentities("Action" . $this->type_code) : $this->type_label;
1705
        }
1706
        if (!getDolGlobalString('AGENDA_USE_EVENT_TYPE')) {
1707
            if ($this->type_code != 'AC_OTH_AUTO') {
1708
                $labeltype = $langs->trans('ActionAC_MANUAL');
1709
            }
1710
        }
1711
1712
        $tooltip = img_picto('', $this->picto) . ' <u>' . $langs->trans('Action') . '</u>';
1713
        if (!empty($this->ref)) {
1714
            $tooltip .= '<br><b>' . $langs->trans('Ref') . ':</b> ' . dol_escape_htmltag($this->ref);
1715
        }
1716
        if (!empty($label)) {
1717
            $tooltip .= '<br><b>' . $langs->trans('Title') . ':</b> ' . dol_escape_htmltag($label);
1718
        }
1719
        if (!empty($labeltype)) {
1720
            $tooltip .= '<br><b>' . $langs->trans('Type') . ':</b> ' . dol_escape_htmltag($labeltype);
1721
        }
1722
        if (!empty($this->location)) {
1723
            $tooltip .= '<br><b>' . $langs->trans('Location') . ':</b> ' . dol_escape_htmltag($this->location);
1724
        }
1725
        if (isset($this->transparency)) {
1726
            $tooltip .= '<br><b>' . $langs->trans('Busy') . ':</b> ' . yn($this->transparency);
1727
        }
1728
        if (!empty($this->email_msgid)) {
1729
            $langs->load("mails");
1730
            $tooltip .= '<br>';
1731
            //$tooltip .= '<br><b>'.img_picto('', 'email').' '.$langs->trans("Email").'</b>';
1732
            $tooltip .= '<br><b>' . $langs->trans('MailTopic') . ':</b> ' . dol_escape_htmltag($this->email_subject);
1733
            $tooltip .= '<br><b>' . $langs->trans('MailFrom') . ':</b> ' . str_replace(array('<', '>'), array('&amp;lt', '&amp;gt'), !empty($this->email_from) ? $this->email_from : '');
1734
            $tooltip .= '<br><b>' . $langs->trans('MailTo') . ':</b> ' . str_replace(array('<', '>'), array('&amp;lt', '&amp;gt'), !empty($this->email_to) ? $this->email_to : '');
1735
            if (!empty($this->email_tocc)) {
1736
                $tooltip .= '<br><b>' . $langs->trans('MailCC') . ':</b> ' . str_replace(array('<', '>'), array('&amp;lt', '&amp;gt'), $this->email_tocc);
1737
            }
1738
            /* Disabled because bcc must remain by definition not visible
1739
            if (!empty($this->email_tobcc)) {
1740
                $tooltip .= '<br><b>'.$langs->trans('MailCCC').':</b> '.$this->email_tobcc;
1741
            } */
1742
        }
1743
        if (!empty($this->note_private)) {
1744
            $tooltip .= '<br><br><b>' . $langs->trans('Description') . ':</b><br>';
1745
            $texttoshow = dolGetFirstLineOfText($this->note_private, 8);    // Try to limit length of content
1746
            $tooltip .= '<div class="tenlinesmax">';                        // Restrict height of content into the tooltip
1747
            $tooltip .= (dol_textishtml($texttoshow) ? str_replace(array("\r", "\n"), "", $texttoshow) : str_replace(array("\r", "\n"), '<br>', $texttoshow));
1748
            $tooltip .= '</div>';
1749
        }
1750
        $linkclose = '';
1751
        $classfortooltip = 'classfortooltip';
1752
        $dataparams = '';
1753
        if (getDolGlobalInt('MAIN_ENABLE_AJAX_TOOLTIP')) {
1754
            $params = [
1755
                'id' => $this->id,
1756
                'objecttype' => $this->element,
1757
                'option' => $option,
1758
                'nofetch' => 1,
1759
            ];
1760
            $classfortooltip = 'classforajaxtooltip';
1761
            $dataparams = ' data-params="' . dol_escape_htmltag(json_encode($params)) . '"';
1762
            $tooltip = '';
1763
        }
1764
        if (empty($notooltip)) {
1765
            if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
1766
                $label = $langs->trans("ShowAction");
1767
                $linkclose .= ' alt="' . dol_escape_htmltag($tooltip, 1) . '"';
1768
            }
1769
            $linkclose .= ($tooltip ? ' title="' . dol_escape_htmltag($tooltip, 1) . '"' : ' title="tocomplete"');
1770
            $linkclose .= $dataparams . ' class="' . $classname . ' ' . $classfortooltip . '"';
1771
        } else {
1772
            $linkclose .= ' class="' . $classname . '"';
1773
        }
1774
1775
        $url = '';
1776
        if ($option == 'birthday') {
1777
            $url = constant('BASE_URL') . '/contact/perso.php?id=' . $this->id;
1778
        } elseif ($option == 'holiday') {
1779
            $url = constant('BASE_URL') . '/holiday/card.php?id=' . $this->id;
1780
        } else {
1781
            $url = constant('BASE_URL') . '/comm/action/card.php?id=' . $this->id;
1782
        }
1783
1784
        if ($option !== 'nolink') {
1785
            // Add param to save lastsearch_values or not
1786
            $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
1787
            if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
1788
                $add_save_lastsearch_values = 1;
1789
            }
1790
            if ($add_save_lastsearch_values) {
1791
                $url .= '&save_lastsearch_values=1';
1792
            }
1793
        }
1794
1795
        $linkstart = '<a href="' . $url . '"';
1796
        $linkstart .= $linkclose . '>';
1797
        $linkend = '</a>';
1798
1799
        if ($option == 'nolink') {
1800
            $linkstart = '';
1801
            $linkend = '';
1802
        }
1803
1804
        if ($withpicto == 2) {
1805
            if (getDolGlobalString('AGENDA_USE_EVENT_TYPE')) {
1806
                $label = $labeltype;
1807
            }
1808
            $labelshort = '';
1809
        } else {
1810
            if (getDolGlobalString('AGENDA_USE_EVENT_TYPE') && empty($label)) {
1811
                $label = $labeltype;
1812
            }
1813
            if ($maxlength < 0) {
1814
                $labelshort = $this->ref;
1815
            } else {
1816
                $labelshort = dol_trunc($label, $maxlength);
1817
            }
1818
        }
1819
1820
        if ($withpicto) {
1821
            if (getDolGlobalString('AGENDA_USE_EVENT_TYPE')) {  // Add code into ()
1822
                if ($labeltype) {
1823
                    $label .= (preg_match('/' . preg_quote($labeltype, '/') . '/', $label) ? '' : ' (' . $langs->transnoentities("Action" . $this->type_code) . ')');
1824
                }
1825
            }
1826
        }
1827
1828
        $result .= $linkstart;
1829
        if ($withpicto) {
1830
            $result .= img_object(($notooltip ? '' : $langs->trans("ShowAction") . ': ' . $label), ($overwritepicto ? $overwritepicto : 'action'), (($this->type_color && $overwritepicto) ? 'style="color: #' . $this->type_color . ' !important;" ' : '') . ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : ' class="' . (($withpicto != 2) ? 'paddingright ' : '') . '"'), 0, 0, $notooltip ? 0 : 1);
1831
        }
1832
        $result .= dol_escape_htmltag($labelshort);
1833
        $result .= $linkend;
1834
1835
        global $action;
1836
        $hookmanager->initHooks(array('actiondao'));
1837
        $parameters = array('id' => $this->id, 'getnomurl' => &$result);
1838
        $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
1839
        if ($reshook > 0) {
1840
            $result = $hookmanager->resPrint;
1841
        } else {
1842
            $result .= $hookmanager->resPrint;
1843
        }
1844
1845
        return $result;
1846
    }
1847
1848
    /**
1849
     *  Return Picto of type of event
1850
     *
1851
     *  @param  string      $morecss            More CSS
1852
     *  @param  string      $titlealt           Title alt
1853
     *  @return string                          HTML String
1854
     */
1855
    public function getTypePicto($morecss = 'pictofixedwidth paddingright valignmiddle', $titlealt = '')
1856
    {
1857
        global $conf;
1858
1859
        $imgpicto = '';
1860
        if (getDolGlobalString('AGENDA_USE_EVENT_TYPE')) {
1861
            $color = '';
1862
            if ($this->type_color) {
1863
                $color = 'style="color: #' . $this->type_color . ' !important;"';
1864
            }
1865
            if ($this->type_picto) {
1866
                $imgpicto = img_picto($titlealt, $this->type_picto, '', false, 0, 0, '', ($morecss ? ' ' . $morecss : ''));
1867
            } else {
1868
                if ($this->type_code == 'AC_RDV') {
1869
                    $imgpicto = img_picto($titlealt, 'meeting', $color, false, 0, 0, '', ($morecss ? ' ' . $morecss : ''));
1870
                } elseif ($this->type_code == 'AC_TEL') {
1871
                    $imgpicto = img_picto($titlealt, 'object_phoning', $color, false, 0, 0, '', ($morecss ? ' ' . $morecss : ''));
1872
                } elseif ($this->type_code == 'AC_FAX') {
1873
                    $imgpicto = img_picto($titlealt, 'object_phoning_fax', $color, false, 0, 0, '', ($morecss ? ' ' . $morecss : ''));
1874
                } elseif ($this->type_code == 'AC_EMAIL' || $this->type_code == 'AC_EMAIL_IN' || (!empty($this->code) && preg_match('/_SENTBYMAIL/', $this->code))) {
1875
                    $imgpicto = img_picto($titlealt, 'object_email', $color, false, 0, 0, '', ($morecss ? ' ' . $morecss : ''));
1876
                } elseif ($this->type_code == 'AC_INT') {
1877
                    $imgpicto = img_picto($titlealt, 'object_intervention', $color, false, 0, 0, '', ($morecss ? ' ' . $morecss : ''));
1878
                } elseif (!empty($this->code) && preg_match('/^TICKET_MSG/', $this->code)) {
1879
                    $imgpicto = img_picto($titlealt, 'object_conversation', $color, false, 0, 0, '', ($morecss ? ' ' . $morecss : ''));
1880
                } elseif ($this->type != 'systemauto') {
1881
                    $imgpicto = img_picto($titlealt, 'user-cog', $color, false, 0, 0, '', ($morecss ? ' ' . $morecss : ''));
1882
                } else {
1883
                    $imgpicto = img_picto($titlealt, 'cog', $color, false, 0, 0, '', ($morecss ? ' ' . $morecss : ''));
1884
                }
1885
            }
1886
        } else {
1887
            // 2 picto: 1 for auto, 1 for manual
1888
            if ($this->type != 'systemauto') {
1889
                $imgpicto = img_picto($titlealt, 'user-cog', '', false, 0, 0, '', ($morecss ? ' ' . $morecss : ''));
1890
            } else {
1891
                $imgpicto = img_picto($titlealt, 'cog', '', false, 0, 0, '', ($morecss ? ' ' . $morecss : ''));
1892
            }
1893
        }
1894
1895
        return $imgpicto;
1896
    }
1897
1898
1899
    /**
1900
     * Sets object to supplied categories.
1901
     *
1902
     * Deletes object from existing categories not supplied.
1903
     * Adds it to non existing supplied categories.
1904
     * Existing categories are left untouch.
1905
     *
1906
     * @param  int[]|int    $categories     Category or categories IDs
1907
     * @return int<-1,1>                    Return integer <0 if KO, >0 if OK
1908
     */
1909
    public function setCategories($categories)
1910
    {
1911
        // Handle single category
1912
        if (!is_array($categories)) {
1913
            $categories = array($categories);
1914
        }
1915
1916
        // Get current categories
1917
        include_once DOL_DOCUMENT_ROOT . '/categories/class/categorie.class.php';
1918
        $c = new Categorie($this->db);
1919
        $existing = $c->containing($this->id, Categorie::TYPE_ACTIONCOMM, 'id');
1920
1921
        // Diff
1922
        if (is_array($existing)) {
1923
            $to_del = array_diff($existing, $categories);
1924
            $to_add = array_diff($categories, $existing);
1925
        } else {
1926
            $to_del = array(); // Nothing to delete
1927
            $to_add = $categories;
1928
        }
1929
1930
        // Process
1931
        foreach ($to_del as $del) {
1932
            if ($c->fetch($del) > 0) {
1933
                $c->del_type($this, Categorie::TYPE_ACTIONCOMM);
1934
            }
1935
        }
1936
        foreach ($to_add as $add) {
1937
            if ($c->fetch($add) > 0) {
1938
                $c->add_type($this, Categorie::TYPE_ACTIONCOMM);
1939
            }
1940
        }
1941
        return 1;
1942
    }
1943
1944
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1945
    /**
1946
     * Export events from database into a cal file.
1947
     *
1948
     * @param string    $format                     The format of the export 'vcal', 'ical/ics' or 'rss'
1949
     * @param string    $type                       The type of the export 'event' or 'journal'
1950
     * @param integer   $cachedelay                 Do not rebuild file if date older than cachedelay seconds
1951
     * @param string    $filename                   The name for the exported file.
1952
     * @param array<string,int|string>  $filters    Array of filters. Example array('notolderthan'=>99, 'year'=>..., 'idfrom'=>..., 'actiontype'=>'systemauto', 'actioncode'=>'AC_PRODUCT_MODIFY', 'project'=>123, ...)
1953
     * @param int<0,1>  $exportholiday              0 = don't integrate holidays into the export, 1 = integrate holidays into the export
1954
     * @return int<-1,1>                            -1 = error on build export file, 0 = export okay
1955
     */
1956
    public function build_exportfile($format, $type, $cachedelay, $filename, $filters, $exportholiday = 0)
1957
    {
1958
        global $hookmanager;
1959
1960
		// phpcs:enable
1961
        global $conf, $langs, $dolibarr_main_url_root, $mysoc;
1962
1963
        require_once DOL_DOCUMENT_ROOT . "/core/lib/xcal.lib.php";
1964
        require_once DOL_DOCUMENT_ROOT . "/core/lib/date.lib.php";
1965
        require_once DOL_DOCUMENT_ROOT . "/core/lib/files.lib.php";
1966
1967
        dol_syslog(get_class($this) . "::build_exportfile Build export file format=" . $format . ", type=" . $type . ", cachedelay=" . $cachedelay . ", filename=" . $filename . ", filters size=" . count($filters), LOG_DEBUG);
1968
1969
        // Check parameters
1970
        if (empty($format)) {
1971
            return -1;
1972
        }
1973
1974
        // Clean parameters
1975
        if (!$filename) {
1976
            $extension = 'vcs';
1977
            if ($format == 'ical') {
1978
                $extension = 'ics';
1979
            }
1980
            $filename = $format . '.' . $extension;
1981
        }
1982
1983
        // Create dir and define output file (definitive and temporary)
1984
        $result = dol_mkdir($conf->agenda->dir_temp);
1985
        $outputfile = $conf->agenda->dir_temp . '/' . $filename;
1986
1987
        $result = 0;
1988
1989
        $buildfile = true;
1990
        $login = '';
1991
        $logina = '';
1992
        $logint = '';
1993
        $eventorganization = '';
1994
1995
        $now = dol_now();
1996
1997
        if ($cachedelay) {
1998
            $nowgmt = dol_now();
1999
            include_once DOL_DOCUMENT_ROOT . '/core/lib/files.lib.php';
2000
            if (dol_filemtime($outputfile) > ($nowgmt - $cachedelay)) {
2001
                dol_syslog(get_class($this) . "::build_exportfile file " . $outputfile . " is not older than now - cachedelay (" . $nowgmt . " - " . $cachedelay . "). Build is canceled");
2002
                $buildfile = false;
2003
            }
2004
        }
2005
2006
        if ($buildfile) {
2007
            // Build event array
2008
            $eventarray = array();
2009
2010
            if (!empty($filters['module']) && $filters['module'] == 'project@eventorganization') {
2011
                $sql = "SELECT p.rowid as id,";
2012
                $sql .= " p.date_start_event as datep,"; // Start
2013
                $sql .= " p.date_end_event as datep2,"; // End
2014
                $sql .= " p.datec, p.tms as datem,";
2015
                $sql .= " p.title as label, '' as code, p.note_public, p.note_private, 0 as type_id,";
2016
                $sql .= " p.fk_soc,";
2017
                $sql .= " p.fk_user_creat as fk_user_author, p.fk_user_modif as fk_user_mod,";
2018
                $sql .= " 0 as fk_user_action,";
2019
                $sql .= " 0 as fk_contact, 100 as percentage,";
2020
                $sql .= " 0 as fk_element, '' as elementtype,";
2021
                $sql .= " 1 as priority, 0 as fulldayevent, p.location, 0 as transparency,";
2022
                $sql .= " u.firstname, u.lastname, '" . $this->db->escape(getDolGlobalString("MAIN_INFO_SOCIETE_MAIL")) . "' as email,";
2023
                $sql .= " s.nom as socname,";
2024
                $sql .= " 0 as type_id, '' as type_code, '' as type_label";
2025
                $sql .= " FROM " . MAIN_DB_PREFIX . "projet as p";
2026
                $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "user as u on u.rowid = p.fk_user_creat"; // Link to get author of event for export
2027
                $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "societe as s on s.rowid = p.fk_soc";
2028
2029
                $parameters = array('filters' => $filters);
2030
                $reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters); // Note that $action and $object may have been modified by hook
2031
                $sql .= $hookmanager->resPrint;
2032
2033
                $sql .= " WHERE p.entity IN (" . getEntity('project') . ")";
2034
2035
                foreach ($filters as $key => $value) {
2036
                    if ($key == 'notolderthan' && $value != '') {
2037
                        $sql .= " AND p.date_start_event >= '" . $this->db->idate($now - ($value * 24 * 60 * 60)) . "'";
2038
                    }
2039
                    if ($key == 'year') {
2040
                        $sql .= " AND p.date_start_event BETWEEN '" . $this->db->idate(dol_get_first_day($value, 1)) . "' AND '" . $this->db->idate(dol_get_last_day($value, 12)) . "'";
2041
                    }
2042
                    if ($key == 'id') {
2043
                        $sql .= " AND p.id = " . (is_numeric($value) ? $value : 0);
2044
                    }
2045
                    if ($key == 'idfrom') {
2046
                        $sql .= " AND p.id >= " . (is_numeric($value) ? $value : 0);
2047
                    }
2048
                    if ($key == 'idto') {
2049
                        $sql .= " AND p.id <= " . (is_numeric($value) ? $value : 0);
2050
                    }
2051
                    if ($key == 'project') {
2052
                        $sql .= " AND p.rowid = " . (is_numeric($value) ? $value : 0);
2053
                    }
2054
                    if ($key == 'status') {
2055
                        $sql .= " AND p.fk_statut = " . ((int) $value);
2056
                    }
2057
                    // TODO Add filters on event code of meetings/talks only
2058
                }
2059
2060
                $sql .= " ORDER by date_start_event";
2061
2062
                $eventorganization = 'project';
2063
            } else {
2064
                $sql = "SELECT a.id,";
2065
                $sql .= " a.datep,"; // Start
2066
                $sql .= " a.datep2,"; // End
2067
                $sql .= " a.datec, a.tms as datem,";
2068
                $sql .= " a.label, a.code, '' as note_public, a.note as note_private, a.fk_action as type_id,";
2069
                $sql .= " a.fk_soc,";
2070
                $sql .= " a.fk_user_author, a.fk_user_mod,";
2071
                $sql .= " a.fk_user_action,";
2072
                $sql .= " a.fk_contact, a.percent as percentage,";
2073
                $sql .= " a.fk_element, a.elementtype,";
2074
                $sql .= " a.priority, a.fulldayevent, a.location, a.transparency,";
2075
                $sql .= " u.firstname, u.lastname, u.email,";
2076
                $sql .= " s.nom as socname,";
2077
                $sql .= " c.id as type_id, c.code as type_code, c.libelle as type_label,";
2078
                $sql .= " num_vote, event_paid, a.status";
2079
                $sql .= " FROM (" . MAIN_DB_PREFIX . "c_actioncomm as c, " . MAIN_DB_PREFIX . "actioncomm as a)";
2080
                $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "user as u on u.rowid = a.fk_user_author"; // Link to get author of event for export
2081
                $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "societe as s on s.rowid = a.fk_soc";
2082
2083
                $parameters = array('filters' => $filters);
2084
                $reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters); // Note that $action and $object may have been modified by hook
2085
                $sql .= $hookmanager->resPrint;
2086
2087
                // We must filter on assignment table
2088
                if (!empty($filters['logint']) && $filters['logint']) {
2089
                    $sql .= ", " . MAIN_DB_PREFIX . "actioncomm_resources as ar";
2090
                }
2091
                $sql .= " WHERE a.fk_action = c.id";
2092
                $sql .= " AND a.entity IN (" . getEntity('agenda') . ")";
2093
2094
                foreach ($filters as $key => $value) {
2095
                    if ($key == 'notolderthan' && $value != '') {
2096
                        $sql .= " AND a.datep >= '" . $this->db->idate($now - ($value * 24 * 60 * 60)) . "'";
2097
                    }
2098
                    if ($key == 'year') {
2099
                        $sql .= " AND a.datep BETWEEN '" . $this->db->idate(dol_get_first_day($value, 1)) . "' AND '" . $this->db->idate(dol_get_last_day($value, 12)) . "'";
2100
                    }
2101
                    if ($key == 'id') {
2102
                        $sql .= " AND a.id = " . (is_numeric($value) ? $value : 0);
2103
                    }
2104
                    if ($key == 'idfrom') {
2105
                        $sql .= " AND a.id >= " . (is_numeric($value) ? $value : 0);
2106
                    }
2107
                    if ($key == 'idto') {
2108
                        $sql .= " AND a.id <= " . (is_numeric($value) ? $value : 0);
2109
                    }
2110
                    if ($key == 'project') {
2111
                        $sql .= " AND a.fk_project = " . (is_numeric($value) ? $value : 0);
2112
                    }
2113
                    if ($key == 'notactiontype') {  // deprecated
2114
                        $sql .= " AND c.type <> '" . $this->db->escape($value) . "'";
2115
                    }
2116
                    if ($key == 'actiontype') { // 'system', 'systemauto', 'module', ...
2117
                        $newvalue = $value;
2118
                        $usenotin = 0;
2119
                        if (preg_match('/^!/', $newvalue)) {
2120
                            $newvalue = preg_replace('/^!/', '', $value);
2121
                            $usenotin = 1;
2122
                        }
2123
                        $arraynewvalue = explode(',', $newvalue);
2124
                        $newvalue = "";
2125
                        foreach ($arraynewvalue as $tmpval) {
2126
                            $newvalue .= ($newvalue ? "," : "") . "'" . $tmpval . "'";
2127
                        }
2128
                        if ($usenotin) {
2129
                            $sql .= " AND c.type NOT IN (" . $this->db->sanitize($newvalue, 1) . ")";
2130
                        } else {
2131
                            $sql .= " AND c.type IN (" . $this->db->sanitize($newvalue, 1) . ")";
2132
                        }
2133
                    }
2134
                    if ($key == 'actioncode') { // 'AC_COMPANY_CREATE', 'AC_COMPANY_MODIFY', ...
2135
                        $newvalue = $value;
2136
                        $usenotin = 0;
2137
                        if (preg_match('/^!/', $newvalue)) {
2138
                            $newvalue = preg_replace('/^!/', '', $value);
2139
                            $usenotin = 1;
2140
                        }
2141
                        $arraynewvalue = explode(',', $newvalue);
2142
                        $newvalue = "";
2143
                        foreach ($arraynewvalue as $tmpval) {
2144
                            $newvalue .= ($newvalue ? "," : "") . "'" . $tmpval . "'";
2145
                        }
2146
                        if ($usenotin) {
2147
                            $sql .= " AND a.code NOT IN (" . $this->db->sanitize($newvalue, 1) . ")";
2148
                        } else {
2149
                            $sql .= " AND a.code IN (" . $this->db->sanitize($newvalue, 1) . ")";
2150
                        }
2151
                    }
2152
2153
                    // We must filter on assignment table
2154
                    if ($key == 'logint') {
2155
                        $sql .= " AND ar.fk_actioncomm = a.id AND ar.element_type='user'";
2156
                    }
2157
                    if ($key == 'logina') {
2158
                        $logina = $value;
2159
                        $condition = '=';
2160
                        if (preg_match('/^!/', $logina)) {
2161
                            $logina = preg_replace('/^!/', '', $logina);
2162
                            $condition = '<>';
2163
                        }
2164
                        $userforfilter = new User($this->db);
2165
                        $result = $userforfilter->fetch(0, $logina);
2166
                        if ($result > 0) {
2167
                            $sql .= " AND a.fk_user_author " . $condition . " " . $userforfilter->id;
2168
                        } elseif ($result < 0 || $condition == '=') {
2169
                            $sql .= " AND a.fk_user_author = 0";
2170
                        }
2171
                    }
2172
                    if ($key == 'logint') {
2173
                        $logint = $value;
2174
                        $condition = '=';
2175
                        if (preg_match('/^!/', $logint)) {
2176
                            $logint = preg_replace('/^!/', '', $logint);
2177
                            $condition = '<>';
2178
                        }
2179
                        $userforfilter = new User($this->db);
2180
                        $result = $userforfilter->fetch(0, $logint);
2181
                        if ($result > 0) {
2182
                            $sql .= " AND ar.fk_element = " . ((int) $userforfilter->id);
2183
                        } elseif ($result < 0 || $condition == '=') {
2184
                            $sql .= " AND ar.fk_element = 0";
2185
                        }
2186
                    }
2187
                    if ($key == 'module') {
2188
                        if ($value == 'conforbooth@eventorganization') {
2189
                            $value = '@eventorganization';
2190
                        }
2191
                        $sql .= " AND c.module LIKE '%" . $this->db->escape($value) . "'";
2192
                    }
2193
                    if ($key == 'status') {
2194
                        $sql .= " AND a.status = " . ((int) $value);
2195
                    }
2196
                }
2197
2198
                $sql .= " AND a.datep IS NOT NULL"; // To exclude corrupted events and avoid errors in lightning/sunbird import
2199
2200
                $parameters = array('filters' => $filters);
2201
                $reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters); // Note that $action and $object may have been modified by hook
2202
                $sql .= $hookmanager->resPrint;
2203
2204
                $sql .= " ORDER by datep";
2205
            }
2206
2207
            if (!empty($filters['limit'])) {
2208
                $sql .= $this->db->plimit((int) $filters['limit']);
2209
            }
2210
2211
            //print $sql;exit;
2212
2213
            dol_syslog(get_class($this) . "::build_exportfile select event(s)", LOG_DEBUG);
2214
2215
            $resql = $this->db->query($sql);
2216
            if ($resql) {
2217
                $diff = 0;
2218
                while ($obj = $this->db->fetch_object($resql)) {
2219
                    $qualified = true;
2220
2221
                    // 'eid','startdate','duration','enddate','title','summary','category','email','url','desc','author'
2222
                    $event = array();
2223
                    $event['uid'] = 'dolibarragenda-' . $this->db->database_name . '-' . $obj->id . "@" . $_SERVER["SERVER_NAME"];
2224
                    $event['type'] = $type;
2225
2226
                    $datestart = $this->db->jdate($obj->datep) - (!getDolGlobalString('AGENDA_EXPORT_FIX_TZ') ? 0 : ($conf->global->AGENDA_EXPORT_FIX_TZ * 3600));
2227
2228
                    // fix for -> Warning: A non-numeric value encountered
2229
                    if (is_numeric($this->db->jdate($obj->datep2))) {
2230
                        $dateend = $this->db->jdate($obj->datep2) - (!getDolGlobalString('AGENDA_EXPORT_FIX_TZ') ? 0 : ($conf->global->AGENDA_EXPORT_FIX_TZ * 3600));
2231
                    } else {
2232
                        // use start date as fall-back to avoid pb with empty end date on ICS readers
2233
                        $dateend = $datestart;
2234
                    }
2235
2236
                    $duration = ($datestart && $dateend) ? ($dateend - $datestart) : 0;
2237
                    $event['summary'] = $obj->label . ($obj->socname ? " (" . $obj->socname . ")" : "");
2238
2239
                    if (!empty($filters['module']) && $filters['module'] == 'project@eventorganization') {
2240
                        $event['desc'] = $obj->note_public;
2241
                    } else {
2242
                        $event['desc'] = $obj->note_private;
2243
                    }
2244
                    $event['startdate'] = $datestart;
2245
                    $event['enddate'] = $dateend; // Not required with type 'journal'
2246
                    $event['duration'] = $duration; // Not required with type 'journal'
2247
                    $event['author'] = dolGetFirstLastname($obj->firstname, $obj->lastname);
2248
                    $event['priority'] = $obj->priority;
2249
                    $event['fulldayevent'] = $obj->fulldayevent;
2250
                    $event['location'] = $obj->location;
2251
                    $event['transparency'] = (($obj->transparency > 0) ? 'OPAQUE' : 'TRANSPARENT'); // OPAQUE (busy) or TRANSPARENT (not busy)
2252
                    $event['category'] = $obj->type_label;
2253
                    $event['email'] = $obj->email;
2254
2255
                    // Public URL of event
2256
                    if ($eventorganization != '') {
2257
                        $link_subscription = $dolibarr_main_url_root . '/public/eventorganization/attendee_new.php?id=' . ((int) $obj->id) . '&type=global&noregistration=1';
2258
                        $encodedsecurekey = dol_hash(getDolGlobalString('EVENTORGANIZATION_SECUREKEY') . 'conferenceorbooth' . ((int) $obj->id), 'md5');
2259
                        $link_subscription .= '&securekey=' . urlencode($encodedsecurekey);
2260
2261
                        $event['url'] = $link_subscription;
2262
                    }
2263
2264
                    $event['created'] = $this->db->jdate($obj->datec) - (!getDolGlobalString('AGENDA_EXPORT_FIX_TZ') ? 0 : ($conf->global->AGENDA_EXPORT_FIX_TZ * 3600));
2265
                    $event['modified'] = $this->db->jdate($obj->datem) - (!getDolGlobalString('AGENDA_EXPORT_FIX_TZ') ? 0 : ($conf->global->AGENDA_EXPORT_FIX_TZ * 3600));
2266
                    $event['num_vote'] = $this->num_vote;
2267
                    $event['event_paid'] = $this->event_paid;
2268
                    $event['status'] = $this->status;
2269
2270
                    // TODO: find a way to call "$this->fetch_userassigned();" without override "$this" properties
2271
                    $this->id = $obj->id;
2272
                    $this->fetch_userassigned(false);
2273
2274
                    $assignedUserArray = array();
2275
2276
                    foreach ($this->userassigned as $key => $value) {
2277
                        $assignedUser = new User($this->db);
2278
                        $assignedUser->fetch($value['id']);
2279
2280
                        $assignedUserArray[$key] = $assignedUser;
2281
                    }
2282
2283
                    $event['assignedUsers'] = $assignedUserArray;
2284
2285
                    if ($qualified && $datestart) {
2286
                        $eventarray[] = $event;
2287
                    }
2288
                    $diff++;
2289
                }
2290
2291
                $parameters = array('filters' => $filters, 'eventarray' => &$eventarray);
2292
                $reshook = $hookmanager->executeHooks('addMoreEventsExport', $parameters); // Note that $action and $object may have been modified by hook
2293
                if ($reshook > 0) {
2294
                    $eventarray = $hookmanager->resArray;
2295
                }
2296
            } else {
2297
                $this->error = $this->db->lasterror();
2298
                return -1;
2299
            }
2300
2301
            if ($exportholiday == 1) {
2302
                $langs->load("holiday");
2303
                $title = $langs->transnoentities("Holidays");
2304
2305
                $sql = "SELECT u.rowid as uid, u.lastname, u.firstname, u.email, u.statut, x.rowid, x.date_debut as date_start, x.date_fin as date_end, x.halfday, x.statut as status";
2306
                $sql .= " FROM " . MAIN_DB_PREFIX . "holiday as x, " . MAIN_DB_PREFIX . "user as u";
2307
                $sql .= " WHERE u.rowid = x.fk_user";
2308
                $sql .= " AND u.statut = '1'"; // Show only active users  (0 = inactive user, 1 = active user)
2309
                $sql .= " AND (x.statut = '2' OR x.statut = '3')"; // Show only public leaves (2 = leave wait for approval, 3 = leave approved)
2310
2311
                $resql = $this->db->query($sql);
2312
                if ($resql) {
2313
                    $num = $this->db->num_rows($resql);
2314
                    $i   = 0;
2315
2316
                    while ($i < $num) {
2317
                        $obj   = $this->db->fetch_object($resql);
2318
                        $event = array();
2319
2320
                        if ($obj->halfday == 1) {
2321
                            $event['fulldayevent'] = false;
2322
2323
                            $timestampStart = dol_stringtotime($obj->date_start . " 00:00:00", 0);
2324
                            $timestampEnd   = dol_stringtotime($obj->date_end . " 12:00:00", 0);
2325
                        } elseif ($obj->halfday == -1) {
2326
                            $event['fulldayevent'] = false;
2327
2328
                            $timestampStart = dol_stringtotime($obj->date_start . " 12:00:00", 0);
2329
                            $timestampEnd   = dol_stringtotime($obj->date_end . " 23:59:59", 0);
2330
                        } else {
2331
                            $event['fulldayevent'] = true;
2332
2333
                            $timestampStart = dol_stringtotime($obj->date_start . " 00:00:00", 0);
2334
                            $timestampEnd   = dol_stringtotime($obj->date_end . " 23:59:59", 0);
2335
                        }
2336
2337
                        if (getDolGlobalString('AGENDA_EXPORT_FIX_TZ')) {
2338
                            $timestampStart -= ($conf->global->AGENDA_EXPORT_FIX_TZ * 3600);
2339
                            $timestampEnd   -= ($conf->global->AGENDA_EXPORT_FIX_TZ * 3600);
2340
                        }
2341
2342
                        $urlwithouturlroot = preg_replace('/' . preg_quote(DOL_URL_ROOT, '/') . '$/i', '', trim($dolibarr_main_url_root));
2343
                        $urlwithroot       = $urlwithouturlroot . DOL_URL_ROOT;
2344
                        $url               = $urlwithroot . '/holiday/card.php?id=' . $obj->rowid;
2345
2346
                        $event['uid']          = 'dolibarrholiday-' . $this->db->database_name . '-' . $obj->rowid . "@" . $_SERVER["SERVER_NAME"];
2347
                        $event['author']       = dolGetFirstLastname($obj->firstname, $obj->lastname);
2348
                        $event['type']         = 'event';
2349
                        $event['category']     = "Holiday";
2350
                        $event['transparency'] = 'OPAQUE';
2351
                        $event['email']        = $obj->email;
2352
                        $event['created']      = $timestampStart;
2353
                        $event['modified']     = $timestampStart;
2354
                        $event['startdate']    = $timestampStart;
2355
                        $event['enddate']      = $timestampEnd;
2356
                        $event['duration']     = $timestampEnd - $timestampStart;
2357
                        $event['url']          = $url;
2358
2359
                        if ($obj->status == 2) {
2360
                            // 2 = leave wait for approval
2361
                            $event['summary'] = $title . " - " . $obj->lastname . " (wait for approval)";
2362
                        } else {
2363
                            // 3 = leave approved
2364
                            $event['summary'] = $title . " - " . $obj->lastname;
2365
                        }
2366
2367
                        $eventarray[] = $event;
2368
2369
                        $i++;
2370
                    }
2371
                }
2372
            }
2373
2374
            $langs->load("agenda");
2375
2376
            // Define title and desc
2377
            $title = '';
2378
            $more = '';
2379
            if ($login) {
2380
                $more = $langs->transnoentities("User") . ' ' . $login;
2381
            }
2382
            if ($logina) {
2383
                $more = $langs->transnoentities("ActionsAskedBy") . ' ' . $logina;
2384
            }
2385
            if ($logint) {
2386
                $more = $langs->transnoentities("ActionsToDoBy") . ' ' . $logint;
2387
            }
2388
            if ($eventorganization) {
2389
                $langs->load("eventorganization");
2390
                $title = $langs->transnoentities("OrganizedEvent") . (empty($eventarray[0]['label']) ? '' : ' ' . $eventarray[0]['label']);
2391
                $more = 'ICS file - ' . $langs->transnoentities("OrganizedEvent") . (empty($eventarray[0]['label']) ? '' : ' ' . $eventarray[0]['label']);
2392
            }
2393
            if ($more) {
2394
                if (empty($title)) {
2395
                    $title = 'Dolibarr actions ' . $mysoc->name . ' - ' . $more;
2396
                }
2397
                $desc = $more;
2398
                $desc .= ' (' . $mysoc->name . ' - built by Dolibarr)';
2399
            } else {
2400
                if (empty($title)) {
2401
                    $title = 'Dolibarr actions ' . $mysoc->name;
2402
                }
2403
                $desc = $langs->transnoentities('ListOfActions');
2404
                $desc .= ' (' . $mysoc->name . ' - built by Dolibarr)';
2405
            }
2406
2407
            // Create temp file
2408
            $outputfiletmp = tempnam($conf->agenda->dir_temp, 'tmp'); // Temporary file (allow call of function by different threads
2409
            dolChmod($outputfiletmp);
2410
2411
            // Write file
2412
            if ($format == 'vcal') {
2413
                $result = build_calfile($format, $title, $desc, $eventarray, $outputfiletmp);
2414
            } elseif ($format == 'ical') {
2415
                $result = build_calfile($format, $title, $desc, $eventarray, $outputfiletmp);
2416
            } elseif ($format == 'rss') {
2417
                $result = build_rssfile($format, $title, $desc, $eventarray, $outputfiletmp);
2418
            }
2419
2420
            if ($result >= 0) {
2421
                if (dol_move($outputfiletmp, $outputfile, 0, 1, 0, 0)) {
2422
                    $result = 1;
2423
                } else {
2424
                    $this->error = 'Failed to rename ' . $outputfiletmp . ' into ' . $outputfile;
2425
                    dol_syslog(get_class($this) . "::build_exportfile " . $this->error, LOG_ERR);
2426
                    dol_delete_file($outputfiletmp, 0, 1);
2427
                    $result = -1;
2428
                }
2429
            } else {
2430
                dol_syslog(get_class($this) . "::build_exportfile build_xxxfile function fails to for format=" . $format . " outputfiletmp=" . $outputfile, LOG_ERR);
2431
                dol_delete_file($outputfiletmp, 0, 1);
2432
                $langs->load("errors");
2433
                $this->error = $langs->trans("ErrorFailToCreateFile", $outputfile);
2434
            }
2435
        }
2436
2437
        return $result;
2438
    }
2439
2440
    /**
2441
     *  Initialise an instance with random values.
2442
     *  Used to build previews or test instances.
2443
     *  id must be 0 if object instance is a specimen.
2444
     *
2445
     *  @return int<1,1>     >0 if ok
2446
     */
2447
    public function initAsSpecimen()
2448
    {
2449
        global $user;
2450
2451
        $now = dol_now();
2452
2453
        // Initialise parameters
2454
        $this->id = 0;
2455
        $this->specimen = 1;
2456
2457
        $this->type_code = 'AC_OTH';
2458
        $this->code = 'AC_SPECIMEN_CODE';
2459
        $this->label = 'Label of event Specimen';
2460
        $this->datec = $now;
2461
        $this->datem = $now;
2462
        $this->datep = $now;
2463
        $this->datef = $now;
2464
        $this->fulldayevent = 0;
2465
        $this->percentage = 0;
2466
        $this->status = 0;
2467
        $this->location = 'Location';
2468
        $this->transparency = 1; // 1 means opaque
2469
        $this->priority = 1;
2470
        //$this->note_public = "This is a 'public' note.";
2471
        $this->note_private = "This is a 'private' note.";
2472
2473
        $this->userownerid = $user->id;
2474
        $this->userassigned[$user->id] = array('id' => $user->id, 'transparency' => 1);
2475
        return 1;
2476
    }
2477
2478
    /**
2479
     *  Function used to replace a thirdparty id with another one.
2480
     *
2481
     * @param   DoliDB  $dbs        Database handler, because function is static we name it $dbs not $db to avoid breaking coding test
2482
     * @param   int     $origin_id  Old thirdparty id
2483
     * @param   int     $dest_id    New thirdparty id
2484
     * @return  bool
2485
     */
2486
    public static function replaceThirdparty(DoliDB $dbs, $origin_id, $dest_id)
2487
    {
2488
        $tables = array(
2489
            'actioncomm'
2490
        );
2491
2492
        return CommonObject::commonReplaceThirdparty($dbs, $origin_id, $dest_id, $tables);
2493
    }
2494
2495
    /**
2496
     *  Function used to replace a product id with another one.
2497
     *
2498
     *  @param DoliDB $dbs Database handler
2499
     *  @param int $origin_id Old product id
2500
     *  @param int $dest_id New product id
2501
     *  @return bool
2502
     */
2503
    public static function replaceProduct(DoliDB $dbs, $origin_id, $dest_id)
2504
    {
2505
        $sql = 'UPDATE ' . MAIN_DB_PREFIX . 'actioncomm SET fk_element = ' . ((int) $dest_id) . ' WHERE elementtype="product" AND fk_element = ' . ((int) $origin_id);
2506
        // using $dbs, not $this->db because function is static
2507
        if (!$dbs->query($sql)) {
2508
            //$this->errors = $dbs->lasterror();
2509
            return false;
2510
        }
2511
2512
        return true;
2513
    }
2514
2515
    /**
2516
     *  Is the action delayed?
2517
     *
2518
     *  @return bool
2519
     */
2520
    public function hasDelay()
2521
    {
2522
        global $conf;
2523
2524
        $now = dol_now();
2525
2526
        return $this->datep && ($this->datep < ($now - $conf->agenda->warning_delay));
2527
    }
2528
2529
2530
    /**
2531
     *  Load event reminder of events
2532
     *
2533
     *  @param  string  $type       Type of reminder 'browser' or 'email'
2534
     *  @param  int     $fk_user    Id of user
2535
     *  @param  bool    $onlypast   true = get only past reminder, false = get all reminders linked to this
2536
     *  @return int<-1,max>         < if OK, else count of number of reminders
2537
     */
2538
    public function loadReminders($type = '', $fk_user = 0, $onlypast = true)
2539
    {
2540
        global $conf, $langs, $user;
2541
2542
        $error = 0;
2543
2544
        $this->reminders = array();
2545
2546
        //Select all action comm reminders for event
2547
        $sql = "SELECT rowid as id, typeremind, dateremind, status, offsetvalue, offsetunit, fk_user, fk_email_template, lasterror";
2548
        $sql .= " FROM " . MAIN_DB_PREFIX . "actioncomm_reminder";
2549
        $sql .= " WHERE fk_actioncomm = " . ((int) $this->id);
2550
        if ($onlypast) {
2551
            $sql .= " AND dateremind <= '" . $this->db->idate(dol_now()) . "'";
2552
        }
2553
        if ($type) {
2554
            $sql .= " AND typeremind = '" . $this->db->escape($type) . "'";
2555
        }
2556
        if ($fk_user > 0) {
2557
            $sql .= " AND fk_user = " . ((int) $fk_user);
2558
        }
2559
        if (!getDolGlobalString('AGENDA_REMINDER_EMAIL')) {
2560
            $sql .= " AND typeremind <> 'email'";
2561
        }
2562
        if (!getDolGlobalString('AGENDA_REMINDER_BROWSER')) {
2563
            $sql .= " AND typeremind <> 'browser'";
2564
        }
2565
2566
        $sql .= $this->db->order("dateremind", "ASC");
2567
        $resql = $this->db->query($sql);
2568
2569
        if ($resql) {
2570
            while ($obj = $this->db->fetch_object($resql)) {
2571
                $tmpactioncommreminder = new ActionCommReminder($this->db);
2572
                $tmpactioncommreminder->id = $obj->id;
2573
                $tmpactioncommreminder->typeremind = $obj->typeremind;
2574
                $tmpactioncommreminder->dateremind = $obj->dateremind;
2575
                $tmpactioncommreminder->offsetvalue = $obj->offsetvalue;
2576
                $tmpactioncommreminder->offsetunit = $obj->offsetunit;
2577
                $tmpactioncommreminder->status = $obj->status;
2578
                $tmpactioncommreminder->fk_user = $obj->fk_user;
2579
                $tmpactioncommreminder->fk_email_template = $obj->fk_email_template;
2580
                $tmpactioncommreminder->lasterror = $obj->lasterror;
2581
2582
                $this->reminders[$obj->id] = $tmpactioncommreminder;
2583
            }
2584
        } else {
2585
            $this->error = $this->db->lasterror();
2586
            $error++;
2587
        }
2588
2589
        return count($this->reminders);
2590
    }
2591
2592
2593
    /**
2594
     *  Send reminders by emails
2595
     *  CAN BE A CRON TASK
2596
     *
2597
     *  @return int<-1,1>|string     0 if OK, <>0 if KO (this function is used also by cron so only 0 is OK)
2598
     */
2599
    public function sendEmailsReminder()
2600
    {
2601
        global $conf, $langs, $user;
2602
2603
        $error = 0;
2604
        $this->output = '';
2605
        $this->error = '';
2606
        $nbMailSend = 0;
2607
        $errorsMsg = array();
2608
2609
        if (!isModEnabled('agenda')) {  // Should not happen. If module disabled, cron job should not be visible.
2610
            $langs->load("agenda");
2611
            $this->output = $langs->trans('ModuleNotEnabled', $langs->transnoentitiesnoconv("Agenda"));
2612
            return 0;
2613
        }
2614
        if (!getDolGlobalString('AGENDA_REMINDER_EMAIL')) {
2615
            $langs->load("agenda");
2616
            $this->output = $langs->trans('EventRemindersByEmailNotEnabled', $langs->transnoentitiesnoconv("Agenda"));
2617
            return 0;
2618
        }
2619
2620
        $now = dol_now();
2621
        $actionCommReminder = new ActionCommReminder($this->db);
2622
2623
        dol_syslog(__METHOD__ . " start", LOG_INFO);
2624
2625
        $this->db->begin();
2626
2627
        //Select all action comm reminders
2628
        $sql = "SELECT rowid as id FROM " . MAIN_DB_PREFIX . "actioncomm_reminder";
2629
        $sql .= " WHERE typeremind = 'email'";
2630
        $sql .= " AND status = 0";  // 0=No yet sent, -1=Error. TODO Include reminder in error once we can count number of error, so we can try 5 times and not more on errors.
2631
        $sql .= " AND dateremind <= '" . $this->db->idate($now) . "'";
2632
        $sql .= " AND entity IN (" . getEntity('actioncomm') . ")";
2633
        $sql .= $this->db->order("dateremind", "ASC");
2634
        $resql = $this->db->query($sql);
2635
2636
        if ($resql) {
2637
            require_once constant('DOL_DOCUMENT_ROOT') . '/core/class/html.formmail.class.php';
2638
            $formmail = new FormMail($this->db);
2639
            $to = null;  // Ensure 'to' is defined for static analysis
2640
2641
            while ($obj = $this->db->fetch_object($resql)) {
2642
                $res = $actionCommReminder->fetch($obj->id);
2643
                if ($res < 0) {
2644
                    $error++;
2645
                    $errorsMsg[] = "Failed to load invoice ActionComm Reminder";
2646
                }
2647
2648
                if (!$error) {
2649
                    //Select email template
2650
                    $arraymessage = $formmail->getEMailTemplate($this->db, 'actioncomm_send', $user, $langs, (!empty($actionCommReminder->fk_email_template)) ? $actionCommReminder->fk_email_template : -1, 1);
2651
2652
                    // Load event
2653
                    $res = $this->fetch($actionCommReminder->fk_actioncomm);
2654
                    if ($res > 0) {
2655
                        // PREPARE EMAIL
2656
                        $errormesg = '';
2657
2658
                        // Make substitution in email content
2659
                        $substitutionarray = getCommonSubstitutionArray($langs, 0, '', $this);
2660
2661
                        complete_substitutions_array($substitutionarray, $langs, $this);
2662
2663
                        // Content
2664
                        $sendContent = make_substitutions($langs->trans($arraymessage->content), $substitutionarray);
2665
2666
                        //Topic
2667
                        $sendTopic = (!empty($arraymessage->topic)) ? $arraymessage->topic : html_entity_decode($langs->transnoentities('EventReminder'));
2668
2669
                        // Recipient
2670
                        $recipient = new User($this->db);
2671
                        $res = $recipient->fetch($actionCommReminder->fk_user);
2672
                        if ($res > 0) {
2673
                            if (!empty($recipient->email)) {
2674
                                $to = $recipient->email;
2675
                            } else {
2676
                                $errormesg = "Failed to send remind to user id=" . $actionCommReminder->fk_user . ". No email defined for user.";
2677
                                $error++;
2678
                            }
2679
                        } else {
2680
                            $errormesg = "Failed to load recipient with user id=" . $actionCommReminder->fk_user;
2681
                            $error++;
2682
                        }
2683
2684
                        // Sender
2685
                        $from = getDolGlobalString('MAIN_MAIL_EMAIL_FROM');
2686
                        if (empty($from)) {
2687
                            $errormesg = "Failed to get sender into global setup MAIN_MAIL_EMAIL_FROM";
2688
                            $error++;
2689
                        }
2690
2691
                        if (!$error) {
2692
                            // Errors Recipient
2693
                            $errors_to = getDolGlobalString('MAIN_MAIL_ERRORS_TO');
2694
2695
                            // Mail Creation
2696
                            $cMailFile = new CMailFile($sendTopic, $to, $from, $sendContent, array(), array(), array(), '', "", 0, 1, $errors_to, '', '', '', '', '');
2697
2698
                            // Sending Mail
2699
                            if ($cMailFile->sendfile()) {
2700
                                $nbMailSend++;
2701
                            } else {
2702
                                $errormesg = 'Failed to send email to: ' . $to . ' ' . $cMailFile->error . implode(',', $cMailFile->errors);
2703
                                $error++;
2704
                            }
2705
                        }
2706
2707
                        if (!$error) {
2708
                            $actionCommReminder->status = $actionCommReminder::STATUS_DONE;
2709
2710
                            $res = $actionCommReminder->update($user);
2711
                            if ($res < 0) {
2712
                                $errorsMsg[] = "Failed to update status to done of ActionComm Reminder";
2713
                                $error++;
2714
                                break; // This is to avoid to have this error on all the selected email. If we fails here for one record, it may fails for others. We must solve first.
2715
                            }
2716
                        } else {
2717
                            $actionCommReminder->status = $actionCommReminder::STATUS_ERROR;
2718
                            $actionCommReminder->lasterror = dol_trunc($errormesg, 128, 'right', 'UTF-8', 1);
2719
2720
                            $res = $actionCommReminder->update($user);
2721
                            if ($res < 0) {
2722
                                $errorsMsg[] = "Failed to update status to error of ActionComm Reminder";
2723
                                $error++;
2724
                                break; // This is to avoid to have this error on all the selected email. If we fails here for one record, it may fails for others. We must solve first.
2725
                            } else {
2726
                                $errorsMsg[] = $errormesg;
2727
                            }
2728
                        }
2729
                    } else {
2730
                        $errorsMsg[] = 'Failed to fetch record actioncomm with ID = ' . $actionCommReminder->fk_actioncomm;
2731
                        $error++;
2732
                    }
2733
                }
2734
            }
2735
        } else {
2736
            $error++;
2737
        }
2738
2739
        if (!$error) {
2740
            // Delete also very old past events (we do not keep more than 1 month record in past)
2741
            $sql = "DELETE FROM " . MAIN_DB_PREFIX . "actioncomm_reminder";
2742
            $sql .= " WHERE dateremind < '" . $this->db->idate($now - (3600 * 24 * 32)) . "'";
2743
            $sql .= " AND status = " . ((int) $actionCommReminder::STATUS_DONE);
2744
            $resql = $this->db->query($sql);
2745
2746
            if (!$resql) {
2747
                $errorsMsg[] = 'Failed to delete old reminders';
2748
                //$error++;     // If this fails, we must not rollback other SQL requests already done. Never mind.
2749
            }
2750
        }
2751
2752
        if (!$error) {
2753
            $this->output = 'Nb of emails sent : ' . $nbMailSend;
2754
            $this->db->commit();
2755
2756
            dol_syslog(__METHOD__ . " end - " . $this->output, LOG_INFO);
2757
2758
            return 0;
2759
        } else {
2760
            $this->db->commit(); // We commit also on error, to have the error message recorded.
2761
            $this->error = 'Nb of emails sent : ' . $nbMailSend . ', ' . (!empty($errorsMsg) ? implode(', ', $errorsMsg) : $error);
2762
2763
            dol_syslog(__METHOD__ . " end - " . $this->error, LOG_INFO);
2764
2765
            return $error;
2766
        }
2767
    }
2768
2769
    /**
2770
     * Update the percent value of a event with the given id
2771
     *
2772
     * @param int           $id         The id of the event
2773
     * @param int<0,100>    $percent    The new percent value for the event
2774
     * @param int           $usermodid  The user who modified the percent
2775
     * @return int<-1,1>                1 when update of the event was successful, otherwise -1
2776
     */
2777
    public function updatePercent($id, $percent, $usermodid = 0)
2778
    {
2779
        $this->db->begin();
2780
2781
        $sql = "UPDATE " . MAIN_DB_PREFIX . "actioncomm ";
2782
        $sql .= " SET percent = " . (int) $percent;
2783
        if ($usermodid > 0) {
2784
            $sql .= ", fk_user_mod = " . $usermodid;
2785
        }
2786
        $sql .= " WHERE id = " . ((int) $id);
2787
2788
        if ($this->db->query($sql)) {
2789
            $this->db->commit();
2790
            return 1;
2791
        } else {
2792
            $this->db->rollback();
2793
            $this->error = $this->db->lasterror();
2794
            return -1;
2795
        }
2796
    }
2797
}
2798