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

Notify::getNotificationsArray()   F

Complexity

Conditions 37
Paths 1296

Size

Total Lines 156
Code Lines 102

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 37
eloc 102
nc 1296
nop 5
dl 0
loc 156
rs 0
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/* Copyright (C) 2003-2005  Rodolphe Quiedeville        <[email protected]>
4
 * Copyright (C) 2004-2011  Laurent Destailleur         <[email protected]>
5
 * Copyright (C) 2014	    Juanjo Menent		        <[email protected]>
6
 * Copyright (C) 2018 	    Philippe Grand		        <[email protected]>
7
 * Copyright (C) 2021 	    Thibault FOUCART		    <[email protected]>
8
 * Copyright (C) 2022       Anthony Berton     	        <[email protected]>
9
 * Copyright (C) 2023       William Mead                <[email protected]>
10
 * Copyright (C) 2024       Jon Bendtsen                <[email protected]>
11
 * Copyright (C) 2024		MDW							<[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\Core\Classes;
29
30
use DoliDB;
31
32
/**
33
 *      \file       htdocs/core/class/notify.class.php
34
 *      \ingroup    notification
35
 *      \brief      File of class to manage notifications
36
 */
37
38
require_once constant('DOL_DOCUMENT_ROOT') . '/core/class/CMailFile.class.php';
39
40
41
/**
42
 *      Class to manage the table of subscription to notifications
43
 */
44
class Notify
45
{
46
    /**
47
     * @var int ID
48
     */
49
    public $id;
50
51
    /**
52
     * @var DoliDB Database handler.
53
     */
54
    public $db;
55
56
    /**
57
     * @var string type
58
     */
59
    public $type;
60
61
    /**
62
     * @var string threshold
63
     */
64
    public $threshold;
65
66
    /**
67
     * @var string context
68
     */
69
    public $context;
70
71
72
    /**
73
     * @var int     ID of event action that trigger the notification
74
     */
75
    public $event;
76
77
    /**
78
     * @var int     Third-party ID
79
     */
80
    public $socid;
81
82
    /**
83
     * @var int     (Third-party) Contact ID
84
     */
85
    public $contact_id;
86
87
    /**
88
     * @var string fk_user
89
     */
90
    public $fk_user;
91
92
    /**
93
     * @var string email
94
     */
95
    public $email;
96
97
98
    /**
99
     * Date creation record (datec)
100
     *
101
     * @var integer
102
     */
103
    public $datec;
104
105
    /**
106
     * Date modified record (datem)
107
     *
108
     * @var integer
109
     */
110
    public $datem;
111
112
    /**
113
     * @var string Error code (or message)
114
     */
115
    public $error = '';
116
117
    /**
118
     * @var string[] Error codes (or messages)
119
     */
120
    public $errors = array();
121
122
    public $author;
123
    public $ref;
124
    public $date;
125
    public $duree;
126
    public $note;
127
128
    /**
129
     * @var int Project ID
130
     */
131
    public $fk_project;
132
133
    // This codes actions are defined into table llx_notify_def
134
    public static $arrayofnotifsupported = array(
135
        'BILL_CANCEL',
136
        'BILL_VALIDATE',
137
        'BILL_PAYED',
138
        'ORDER_CANCEL',
139
        'ORDER_CREATE',
140
        'ORDER_VALIDATE',
141
        'ORDER_CLOSE',
142
        'PROPAL_VALIDATE',
143
        'PROPAL_CLOSE_SIGNED',
144
        'PROPAL_CLOSE_REFUSED',
145
        'FICHINTER_VALIDATE',
146
        'FICHINTER_CLOSE',
147
        'FICHINTER_ADD_CONTACT',
148
        'ORDER_SUPPLIER_CANCEL',
149
        'ORDER_SUPPLIER_VALIDATE',
150
        'ORDER_SUPPLIER_APPROVE',
151
        'ORDER_SUPPLIER_SUBMIT',
152
        'ORDER_SUPPLIER_REFUSE',
153
        'SHIPPING_VALIDATE',
154
        'EXPENSE_REPORT_VALIDATE',
155
        'EXPENSE_REPORT_APPROVE',
156
        'HOLIDAY_VALIDATE',
157
        'HOLIDAY_APPROVE',
158
        'ACTION_CREATE'
159
    );
160
161
    /**
162
     *  Constructor
163
     *
164
     *  @param      DoliDB      $db     Database handler
165
     */
166
    public function __construct($db)
167
    {
168
        $this->db = $db;
169
    }
170
171
172
    /**
173
     *  Return message that say how many notification (and to which email) will occurs on requested event.
174
     *  This is to show confirmation messages before event is recorded.
175
     *
176
     *  @param  string  $action     Id of action in llx_c_action_trigger
177
     *  @param  int     $socid      Id of third party
178
     *  @param  Object  $object     Object the notification is about
179
     *  @return string              Message
180
     */
181
    public function confirmMessage($action, $socid, $object)
182
    {
183
        global $langs;
184
        $langs->load("mails");
185
186
        // Get full list of all notifications subscribed for $action, $socid and $object
187
        $listofnotiftodo = $this->getNotificationsArray($action, $socid, $object, 0);
188
189
        if (getDolGlobalString('NOTIFICATION_EMAIL_DISABLE_CONFIRM_MESSAGE_USER')) {
190
            foreach ($listofnotiftodo as $val) {
191
                if ($val['type'] == 'touser') {
192
                    unset($listofnotiftodo[$val['email']]);
193
                    //$listofnotiftodo = array_merge($listofnotiftodo);
194
                }
195
            }
196
        }
197
        if (getDolGlobalString('NOTIFICATION_EMAIL_DISABLE_CONFIRM_MESSAGE_CONTACT')) {
198
            foreach ($listofnotiftodo as $val) {
199
                if ($val['type'] == 'tocontact') {
200
                    unset($listofnotiftodo[$val['email']]);
201
                    //$listofnotiftodo = array_merge($listofnotiftodo);
202
                }
203
            }
204
        }
205
        if (getDolGlobalString('NOTIFICATION_EMAIL_DISABLE_CONFIRM_MESSAGE_FIX')) {
206
            foreach ($listofnotiftodo as $val) {
207
                if ($val['type'] == 'tofixedemail') {
208
                    unset($listofnotiftodo[$val['email']]);
209
                    //$listofnotiftodo = array_merge($listofnotiftodo);
210
                }
211
            }
212
        }
213
214
        $texte = '';
215
        $nb = -1;
216
        if (is_array($listofnotiftodo)) {
217
            $nb = count($listofnotiftodo);
218
        }
219
        if ($nb < 0) {
220
            $texte = img_object($langs->trans("Notifications"), 'email', 'class="pictofixedwidth"') . $langs->trans("ErrorFailedToGetListOfNotificationsToSend");
221
        } elseif ($nb == 0) {
222
            $texte = img_object($langs->trans("Notifications"), 'email', 'class="pictofixedwidth"') . $langs->trans("NoNotificationsWillBeSent");
223
        } elseif ($nb == 1) {
224
            $texte = img_object($langs->trans("Notifications"), 'email', 'class="pictofixedwidth"') . $langs->trans("ANotificationsWillBeSent");
225
        } else { // Always >= 2 if ($nb >= 2) {
226
            $texte = img_object($langs->trans("Notifications"), 'email', 'class="pictofixedwidth"') . $langs->trans("SomeNotificationsWillBeSent", $nb);
227
        }
228
229
        if (is_array($listofnotiftodo)) {
230
            $i = 0;
231
            foreach ($listofnotiftodo as $val) {
232
                if ($i) {
233
                    $texte .= ', ';
234
                } else {
235
                    $texte .= ' (';
236
                }
237
                if ($val['isemailvalid']) {
238
                    $texte .= $val['email'];
239
                } else {
240
                    $texte .= $val['emaildesc'];
241
                }
242
                $i++;
243
            }
244
            if ($i) {
245
                $texte .= ')';
246
            }
247
        }
248
249
        return $texte;
250
    }
251
252
    /**
253
     *  Delete a notification from database
254
     *
255
     *  @param      User|null   $user       User deleting
256
     *  @return     int                     Return integer <0 if KO, >0 if OK
257
     */
258
    public function delete(User $user = null)
0 ignored issues
show
Bug introduced by
The type Dolibarr\Code\Core\Classes\User was not found. Did you mean User? If so, make sure to prefix the type with \.
Loading history...
259
    {
260
        $error = 0;
261
262
        dol_syslog(get_class($this) . "::delete " . $this->id, LOG_DEBUG);
263
264
        $this->db->begin();
265
266
        if (!$error) {
267
            $sql = "DELETE FROM " . MAIN_DB_PREFIX . "notify_def";
268
            $sql .= " WHERE rowid = " . ((int) $this->id);
269
270
            if (!$this->db->query($sql)) {
271
                $error++;
272
                $this->errors[] = $this->db->lasterror();
273
            }
274
        }
275
276
        if (!$error) {
277
            $this->db->commit();
278
            return 1;
279
        } else {
280
            $this->db->rollback();
281
            return -1 * $error;
282
        }
283
    }
284
285
    /**
286
     * Create notification information record.
287
     *
288
     * @param   User|null   $user       User
289
     * @param   int         $notrigger  1=Disable triggers
290
     * @return  int                     Return integer <0 if KO, > 0 if OK (ID of newly created company notification information)
291
     */
292
    public function create(User $user = null, $notrigger = 0)
293
    {
294
        $now = dol_now();
295
296
        $error = 0;
297
298
        // Check parameters
299
        if (empty($this->socid)) {
300
            $this->error = 'BadValueForParameter';
301
            $this->errors[] = $this->error;
302
            return -1;
303
        }
304
305
        if (empty($this->datec)) {
306
            $this->datec = $now;
307
        }
308
309
        $this->db->begin();
310
311
        $sql = "INSERT INTO " . MAIN_DB_PREFIX . "notify_def (fk_soc, fk_action, fk_contact, type, datec)";
312
        $sql .= " VALUES (" . ((int) $this->socid) . ", " . ((int) $this->event) . ", " . ((int) $this->contact_id) . ",";
313
        $sql .= "'" . $this->db->escape($this->type) . "', '" . $this->db->idate($this->datec) . "')";
314
315
        $resql = $this->db->query($sql);
316
        if ($resql) {
317
            if ($this->db->affected_rows($resql)) {
318
                $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX . "notify_def");
319
            }
320
        } else {
321
            $error++;
322
            $this->error = $this->db->lasterror();
323
            $this->errors[] = $this->error;
324
        }
325
326
        if (!$error) {
327
            $this->db->commit();
328
            return $this->id;
329
        } else {
330
            $this->db->rollback();
331
            return -1;
332
        }
333
    }
334
335
    /**
336
     *  Load record from database
337
     *
338
     *  @param  int     $id         Id of record
339
     *  @param  int     $socid      Id of company. If this is filled, function will return only records belonging to this thirdparty
340
     *  @param  string  $type       If id of company filled, we say if we want record of this type only
341
     *  @return int                 Return integer <0 if KO, >0 if OK
342
     */
343
    public function fetch($id, $socid = 0, $type = 'email')
344
    {
345
        if (empty($id) && empty($socid)) {
346
            return -1;
347
        }
348
349
        $sql = "SELECT rowid, fk_action as event, fk_soc as socid, fk_contact as contact_id, type, datec, tms as datem";
350
        $sql .= " FROM " . MAIN_DB_PREFIX . "notify_def";
351
352
        if ($id) {
353
            $sql .= " WHERE rowid = " . ((int) $id);
354
        } elseif ($socid > 0) {
355
            $sql .= " WHERE fk_soc  = " . ((int) $socid);
356
            if ($type) {
357
                $sql .= " AND type = '" . $this->db->escape($type) . "'";
358
            }
359
        }
360
361
        $resql = $this->db->query($sql);
362
        if ($resql) {
363
            if ($this->db->num_rows($resql)) {
364
                $obj = $this->db->fetch_object($resql);
365
366
                $this->id = $obj->rowid;
367
                $this->type = $obj->type;
368
                $this->event = $obj->event;
369
                $this->socid = $obj->socid;
370
                $this->contact_id = $obj->contact_id;
371
                $this->fk_user = $obj->fk_user;
372
                $this->email = $obj->email;
373
                $this->threshold = $obj->threshold;
374
                $this->context  = $obj->context;
375
                $this->datec = $this->db->jdate($obj->datec);
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->db->jdate($obj->datec) can also be of type string. However, the property $datec is declared as type integer. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
376
                $this->datem = $this->db->jdate($obj->datem);
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->db->jdate($obj->datem) can also be of type string. However, the property $datem is declared as type integer. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
377
            }
378
            $this->db->free($resql);
379
380
            return 1;
381
        } else {
382
            dol_print_error($this->db);
383
            return -1;
384
        }
385
    }
386
387
    /**
388
     *  Update record in database
389
     *
390
     *  @param  User|null   $user        Object user
391
     *  @param  int         $notrigger   1=Disable triggers
392
     *  @return int                      Return integer <=0 if KO, >0 if OK
393
     */
394
    public function update(User $user = null, $notrigger = -1)
395
    {
396
        global $langs;
397
398
        $error = 0;
399
400
        if (!$this->id) {
401
            return -1;
402
        }
403
404
        $this->db->begin();
405
406
        $sql = "UPDATE " . MAIN_DB_PREFIX . "notify_def SET";
407
        $sql .= " type = '" . $this->db->escape($this->type) . "'";
408
        // $sql .= ",fk_user = ".((int) $this->fk_user);
409
        // $sql .= ",email = '".$this->db->escape($this->email)."'";
410
        // $sql .= ",threshold = '".$this->db->escape($this->threshold)."'";
411
        // $sql .= ",context = '".$this->db->escape($this->context)."'";
412
        $sql .= ",fk_soc = " . ((int) $this->socid);
413
        $sql .= ",fk_action = " . ((int) $this->event);
414
        $sql .= ",fk_contact = " . ((int) $this->contact_id);
415
        $sql .= " WHERE rowid = " . ((int) $this->id);
416
417
        $result = $this->db->query($sql);
418
        if (!$result) {
419
            $error++;
420
            if ($this->db->errno() == 'DB_ERROR_RECORD_ALREADY_EXISTS') {
421
                $this->error = $langs->trans('ErrorDuplicateField');
422
            } else {
423
                $this->error = $this->db->lasterror();
424
            }
425
            $this->errors[] = $this->error;
426
        }
427
428
        if (!$error) {
429
            $this->db->commit();
430
            return 1;
431
        } else {
432
            $this->db->rollback();
433
            return -1;
434
        }
435
    }
436
437
    /**
438
     * Return number of notifications activated, for all or a given action code (and third party)
439
     *
440
     * @param   string  $notifcode      Code of action in llx_c_action_trigger (new usage) or Id of action in llx_c_action_trigger (old usage)
441
     * @param   int     $socid          Id of third party or 0 for all thirdparties or -1 for no thirdparties
442
     * @param   Object  $object         Object the notification is about (need it to check threshold value of some notifications)
443
     * @param   int     $userid         Id of user or 0 for all users or -1 for no users
444
     * @param   array   $scope          Scope where to search
445
     * @return  array|int               Return integer <0 if KO, array of notifications to send if OK
446
     */
447
    public function getNotificationsArray($notifcode, $socid = 0, $object = null, $userid = 0, $scope = array('thirdparty', 'user', 'global'))
448
    {
449
        global $conf, $user;
450
451
        $error = 0;
452
        $resarray = array();
453
454
        $valueforthreshold = 0;
455
        if (is_object($object)) {
456
            $valueforthreshold = $object->total_ht;
457
        }
458
459
        $sqlnotifcode = '';
460
        if ($notifcode) {
461
            if (is_numeric($notifcode)) {
462
                $sqlnotifcode = " AND n.fk_action = " . ((int) $notifcode); // Old usage
463
            } else {
464
                $sqlnotifcode = " AND a.code = '" . $this->db->escape($notifcode) . "'"; // New usage
465
            }
466
        }
467
468
        // Subscription per contact
469
        if (!$error) {
470
            if ($socid >= 0 && in_array('thirdparty', $scope)) {
471
                $sql = "SELECT a.code, c.email, c.rowid, c.statut as status";
472
                $sql .= " FROM " . $this->db->prefix() . "notify_def as n,";
473
                $sql .= " " . $this->db->prefix() . "socpeople as c,";
474
475
                $sql .= " " . $this->db->prefix() . "c_action_trigger as a,";
476
                $sql .= " " . $this->db->prefix() . "societe as s";
477
                $sql .= " WHERE n.fk_contact = c.rowid";
478
                $sql .= " AND a.rowid = n.fk_action";
479
                $sql .= " AND n.fk_soc = s.rowid";
480
                $sql .= $sqlnotifcode;
481
                $sql .= " AND s.entity IN (" . getEntity('societe') . ")";
482
                if ($socid > 0) {
483
                    $sql .= " AND s.rowid = " . ((int) $socid);
484
                }
485
486
                dol_syslog(__METHOD__ . " " . $notifcode . ", " . $socid, LOG_DEBUG);
487
488
                $resql = $this->db->query($sql);
489
                if ($resql) {
490
                    $num = $this->db->num_rows($resql);
491
                    $i = 0;
492
                    while ($i < $num) {
493
                        $obj = $this->db->fetch_object($resql);
494
                        // we want to notify only if contact is enable
495
                        if ($obj && $obj->status ==  1) {
496
                            $newval2 = trim($obj->email);
497
                            $isvalid = isValidEmail($newval2);
498
                            if (empty($resarray[$newval2])) {
499
                                $resarray[$newval2] = array('type' => 'tocontact', 'code' => trim($obj->code), 'emaildesc' => 'Contact id ' . $obj->rowid, 'email' => $newval2, 'contactid' => $obj->rowid, 'isemailvalid' => $isvalid);
500
                            }
501
                        }
502
                        $i++;
503
                    }
504
                } else {
505
                    $error++;
506
                    $this->error = $this->db->lasterror();
507
                }
508
            }
509
        }
510
511
        // Subscription per user
512
        if (!$error) {
513
            if ($userid >= 0 && in_array('user', $scope)) {
514
                $sql = "SELECT a.code, c.email, c.rowid";
515
                $sql .= " FROM " . $this->db->prefix() . "notify_def as n,";
516
                $sql .= " " . $this->db->prefix() . "user as c,";
517
                $sql .= " " . $this->db->prefix() . "c_action_trigger as a";
518
                $sql .= " WHERE n.fk_user = c.rowid";
519
                $sql .= " AND a.rowid = n.fk_action";
520
                $sql .= $sqlnotifcode;
521
                $sql .= " AND c.entity IN (" . getEntity('user') . ")";
522
                if ($userid > 0) {
523
                    $sql .= " AND c.rowid = " . ((int) $userid);
524
                }
525
526
                dol_syslog(__METHOD__ . " " . $notifcode . ", " . $socid, LOG_DEBUG);
527
528
                $resql = $this->db->query($sql);
529
                if ($resql) {
530
                    $num = $this->db->num_rows($resql);
531
                    $i = 0;
532
                    while ($i < $num) {
533
                        $obj = $this->db->fetch_object($resql);
534
                        if ($obj) {
535
                            $newval2 = trim($obj->email);
536
                            $isvalid = isValidEmail($newval2);
537
                            if (empty($resarray[$newval2])) {
538
                                $resarray[$newval2] = array('type' => 'touser', 'code' => trim($obj->code), 'emaildesc' => 'User id ' . $obj->rowid, 'email' => $newval2, 'userid' => $obj->rowid, 'isemailvalid' => $isvalid);
539
                            }
540
                        }
541
                        $i++;
542
                    }
543
                } else {
544
                    $error++;
545
                    $this->error = $this->db->lasterror();
546
                }
547
            }
548
        }
549
550
        // Subscription global
551
        if (!$error) {
552
            if (in_array('global', $scope)) {
553
                // List of notifications enabled for fixed email
554
                foreach ($conf->global as $key => $val) {
555
                    if ($notifcode) {
556
                        if ($val == '' || !preg_match('/^NOTIFICATION_FIXEDEMAIL_' . $notifcode . '_THRESHOLD_HIGHER_(.*)$/', $key, $reg)) {
557
                            continue;
558
                        }
559
                    } else {
560
                        if ($val == '' || !preg_match('/^NOTIFICATION_FIXEDEMAIL_.*_THRESHOLD_HIGHER_(.*)$/', $key, $reg)) {
561
                            continue;
562
                        }
563
                    }
564
565
                    $threshold = (float) $reg[1];
566
                    if ($valueforthreshold < $threshold) {
567
                        continue;
568
                    }
569
570
                    $tmpemail = explode(',', $val);
571
                    foreach ($tmpemail as $key2 => $val2) {
572
                        $newval2 = trim($val2);
573
                        if ($newval2 == '__SUPERVISOREMAIL__') {
574
                            if ($user->fk_user > 0) {
575
                                $tmpuser = new User($this->db);
576
                                $tmpuser->fetch($user->fk_user);
577
                                if ($tmpuser->email) {
578
                                    $newval2 = trim($tmpuser->email);
579
                                } else {
580
                                    $newval2 = '';
581
                                }
582
                            } else {
583
                                $newval2 = '';
584
                            }
585
                        }
586
                        if ($newval2) {
587
                            $isvalid = isValidEmail($newval2, 0);
588
                            if (empty($resarray[$newval2])) {
589
                                $resarray[$newval2] = array('type' => 'tofixedemail', 'code' => trim($key), 'emaildesc' => trim($val2), 'email' => $newval2, 'isemailvalid' => $isvalid);
590
                            }
591
                        }
592
                    }
593
                }
594
            }
595
        }
596
597
        if ($error) {
598
            return -1;
599
        }
600
601
        //var_dump($resarray);
602
        return $resarray;
603
    }
604
605
    /**
606
     *  Check if notification are active for couple action/company.
607
     *  If yes, send mail and save trace into llx_notify.
608
     *
609
     *  @param  string  $notifcode          Code of action in llx_c_action_trigger (new usage) or Id of action in llx_c_action_trigger (old usage)
610
     *  @param  Object  $object             Object the notification deals on
611
     *  @param  array   $filename_list      List of files to attach (full path of filename on file system)
612
     *  @param  array   $mimetype_list      List of MIME type of attached files
613
     *  @param  array   $mimefilename_list  List of attached file name in message
614
     *  @return int                         Return integer <0 if KO, or number of changes if OK
615
     */
616
    public function send($notifcode, $object, $filename_list = array(), $mimetype_list = array(), $mimefilename_list = array())
617
    {
618
        global $user, $conf, $langs, $mysoc;
619
        global $hookmanager;
620
        global $dolibarr_main_url_root;
621
        global $action;
622
623
        // Complete the array Notify::$arrayofnotifsupported
624
        if (!is_object($hookmanager)) {
625
            include_once DOL_DOCUMENT_ROOT . '/core/class/hookmanager.class.php';
626
            $hookmanager = new HookManager($this->db);
627
        }
628
        $hookmanager->initHooks(array('notification'));
629
630
        $parameters = array('notifcode' => $notifcode);
631
        $reshook = $hookmanager->executeHooks('notifsupported', $parameters, $object, $action);
632
        if (empty($reshook)) {
633
            if (!empty($hookmanager->resArray['arrayofnotifsupported'])) {
634
                Notify::$arrayofnotifsupported = array_merge(Notify::$arrayofnotifsupported, $hookmanager->resArray['arrayofnotifsupported']);
635
            }
636
        }
637
638
        // If the trigger code is not managed by the Notification module
639
        if (!in_array($notifcode, Notify::$arrayofnotifsupported)) {
640
            return 0;
641
        }
642
643
        include_once DOL_DOCUMENT_ROOT . '/core/lib/files.lib.php';
644
645
        dol_syslog(get_class($this) . "::send notifcode=" . $notifcode . ", object id=" . $object->id);
646
647
        $langs->load("other");
648
649
        // Define $urlwithroot
650
        $urlwithouturlroot = preg_replace('/' . preg_quote(DOL_URL_ROOT, '/') . '$/i', '', trim($dolibarr_main_url_root));
651
        $urlwithroot = $urlwithouturlroot . DOL_URL_ROOT; // This is to use external domain name found into config file
652
        //$urlwithroot=DOL_MAIN_URL_ROOT;                       // This is to use same domain name than current
653
654
        // Define some vars
655
        $application = 'Dolibarr';
656
        if (getDolGlobalString('MAIN_APPLICATION_TITLE')) {
657
            $application = getDolGlobalString('MAIN_APPLICATION_TITLE');
658
        }
659
        $from = getDolGlobalString('NOTIFICATION_EMAIL_FROM');
660
        $object_type = '';
661
        $link = '';
662
        $num = 0;
663
        $error = 0;
664
665
        $oldref = (empty($object->oldref) ? $object->ref : $object->oldref);
666
        $newref = (empty($object->newref) ? $object->ref : $object->newref);
667
668
        $sql = '';
669
670
        // Check notification per third party
671
        if (!empty($object->socid) && $object->socid > 0) {
672
            $sql .= "SELECT 'tocontactid' as type_target, c.email, c.rowid as cid, c.lastname, c.firstname, c.default_lang,";
673
            $sql .= " a.rowid as adid, a.label, a.code, n.rowid, n.threshold, n.context, n.type";
674
            $sql .= " FROM " . $this->db->prefix() . "socpeople as c,";
675
            $sql .= " " . $this->db->prefix() . "c_action_trigger as a,";
676
            $sql .= " " . $this->db->prefix() . "notify_def as n,";
677
            $sql .= " " . $this->db->prefix() . "societe as s";
678
            $sql .= " WHERE n.fk_contact = c.rowid AND a.rowid = n.fk_action";
679
            $sql .= " AND n.fk_soc = s.rowid";
680
            $sql .= " AND c.statut = 1";
681
            if (is_numeric($notifcode)) {
682
                $sql .= " AND n.fk_action = " . ((int) $notifcode); // Old usage
683
            } else {
684
                $sql .= " AND a.code = '" . $this->db->escape($notifcode) . "'"; // New usage
685
            }
686
            $sql .= " AND s.rowid = " . ((int) $object->socid);
687
688
            $sql .= "\nUNION\n";
689
        }
690
691
        // Check notification per user
692
        $sql .= "SELECT 'touserid' as type_target, c.email, c.rowid as cid, c.lastname, c.firstname, c.lang as default_lang,";
693
        $sql .= " a.rowid as adid, a.label, a.code, n.rowid, n.threshold, n.context, n.type";
694
        $sql .= " FROM " . $this->db->prefix() . "user as c,";
695
        $sql .= " " . $this->db->prefix() . "c_action_trigger as a,";
696
        $sql .= " " . $this->db->prefix() . "notify_def as n";
697
        $sql .= " WHERE n.fk_user = c.rowid AND a.rowid = n.fk_action";
698
        $sql .= " AND c.statut = 1";
699
        if (is_numeric($notifcode)) {
700
            $sql .= " AND n.fk_action = " . ((int) $notifcode); // Old usage
701
        } else {
702
            $sql .= " AND a.code = '" . $this->db->escape($notifcode) . "'"; // New usage
703
        }
704
705
        // Check notification fixed
706
        // TODO Move part found after, into a sql here
707
708
709
        // Loop on all notifications enabled
710
        $result = $this->db->query($sql);
711
        if ($result) {
712
            $num = $this->db->num_rows($result);
713
            $projtitle = '';
714
            if (is_object($object->project) || $object->fetch_project() > 0) {
715
                $projtitle = '(' . $object->project->title . ')';
716
            }
717
718
            if ($num > 0) {
719
                $i = 0;
720
                while ($i < $num && !$error) {  // For each notification couple defined (third party/actioncode)
721
                    $obj = $this->db->fetch_object($result);
722
723
                    $sendto = dolGetFirstLastname($obj->firstname, $obj->lastname) . " <" . $obj->email . ">";
724
                    $notifcodedefid = $obj->adid;
725
                    $trackid = '';
726
                    if ($obj->type_target == 'tocontactid') {
727
                        $trackid = 'ctc' . $obj->cid;
728
                    }
729
                    if ($obj->type_target == 'touserid') {
730
                        $trackid = 'use' . $obj->cid;
731
                    }
732
733
                    if (dol_strlen($obj->email)) {
734
                        // Set output language
735
                        $outputlangs = $langs;
736
                        if ($obj->default_lang && $obj->default_lang != $langs->defaultlang) {
737
                            $outputlangs = new Translate('', $conf);
738
                            $outputlangs->setDefaultLang($obj->default_lang);
739
                            $outputlangs->loadLangs(array("main", "other"));
740
                        }
741
742
                        $appli = $mysoc->name;
743
744
                        $subject = '[' . $appli . '] ' . $outputlangs->transnoentitiesnoconv("DolibarrNotification") . ($projtitle ? ' ' . $projtitle : '');
745
746
                        switch ($notifcode) {
747
                            case 'BILL_CANCEL':
748
                                $link = '<a href="' . $urlwithroot . '/compta/facture/card.php?facid=' . $object->id . '&entity=' . $object->entity . '">' . $newref . '</a>';
749
                                $dir_output = $conf->facture->dir_output . "/" . get_exdir(0, 0, 0, 1, $object, 'invoice');
750
                                $object_type = 'facture';
751
                                $mesg = $outputlangs->transnoentitiesnoconv("EMailTextInvoiceCanceled", $link);
752
                                break;
753
                            case 'BILL_VALIDATE':
754
                                $link = '<a href="' . $urlwithroot . '/compta/facture/card.php?facid=' . $object->id . '&entity=' . $object->entity . '">' . $newref . '</a>';
755
                                $dir_output = $conf->facture->dir_output . "/" . get_exdir(0, 0, 0, 1, $object, 'invoice');
756
                                $object_type = 'facture';
757
                                $mesg = $outputlangs->transnoentitiesnoconv("EMailTextInvoiceValidated", $link);
758
                                break;
759
                            case 'BILL_PAYED':
760
                                $link = '<a href="' . $urlwithroot . '/compta/facture/card.php?facid=' . $object->id . '&entity=' . $object->entity . '">' . $newref . '</a>';
761
                                $dir_output = $conf->facture->dir_output . "/" . get_exdir(0, 0, 0, 1, $object, 'invoice');
762
                                $object_type = 'facture';
763
                                $mesg = $outputlangs->transnoentitiesnoconv("EMailTextInvoicePayed", $link);
764
                                break;
765
                            case 'ORDER_CANCEL':
766
                                $link = '<a href="' . $urlwithroot . '/commande/card.php?id=' . $object->id . '&entity=' . $object->entity . '">' . $newref . '</a>';
767
                                $dir_output = $conf->commande->dir_output . "/" . get_exdir(0, 0, 0, 1, $object, 'commande');
768
                                $object_type = 'order';
769
                                $mesg = $outputlangs->transnoentitiesnoconv("EMailTextOrderCanceled", $link);
770
                                break;
771
                            case 'ORDER_VALIDATE':
772
                                $link = '<a href="' . $urlwithroot . '/commande/card.php?id=' . $object->id . '&entity=' . $object->entity . '">' . $newref . '</a>';
773
                                $dir_output = $conf->commande->dir_output . "/" . get_exdir(0, 0, 0, 1, $object, 'commande');
774
                                $object_type = 'order';
775
                                $mesg = $outputlangs->transnoentitiesnoconv("EMailTextOrderValidated", $link);
776
                                break;
777
                            case 'ORDER_CLOSE':
778
                                $link = '<a href="' . $urlwithroot . '/commande/card.php?id=' . $object->id . '&entity=' . $object->entity . '">' . $newref . '</a>';
779
                                $dir_output = $conf->commande->dir_output . "/" . get_exdir(0, 0, 0, 1, $object, 'commande');
780
                                $object_type = 'order';
781
                                $labeltouse = getDolGlobalString('ORDER_CLOSE_TEMPLATE');
782
                                $mesg = $outputlangs->transnoentitiesnoconv("EMailTextOrderClose", $link);
783
                                break;
784
                            case 'PROPAL_VALIDATE':
785
                                $link = '<a href="' . $urlwithroot . '/comm/propal/card.php?id=' . $object->id . '&entity=' . $object->entity . '">' . $newref . '</a>';
786
                                $dir_output = $conf->propal->multidir_output[$object->entity] . "/" . get_exdir(0, 0, 0, 1, $object, 'propal');
787
                                $object_type = 'propal';
788
                                $mesg = $outputlangs->transnoentitiesnoconv("EMailTextProposalValidated", $link);
789
                                break;
790
                            case 'PROPAL_CLOSE_REFUSED':
791
                                $link = '<a href="' . $urlwithroot . '/comm/propal/card.php?id=' . $object->id . '&entity=' . $object->entity . '">' . $newref . '</a>';
792
                                $dir_output = $conf->propal->multidir_output[$object->entity] . "/" . get_exdir(0, 0, 0, 1, $object, 'propal');
793
                                $object_type = 'propal';
794
                                $labeltouse = getDolGlobalString('PROPAL_CLOSE_REFUSED_TEMPLATE');
795
                                $mesg = $outputlangs->transnoentitiesnoconv("EMailTextProposalClosedRefused", $link);
796
                                if (!empty($object->context['closedfromonlinesignature'])) {
797
                                    $mesg .= ' - From online page';
798
                                }
799
                                break;
800
                            case 'PROPAL_CLOSE_SIGNED':
801
                                $link = '<a href="' . $urlwithroot . '/comm/propal/card.php?id=' . $object->id . '&entity=' . $object->entity . '">' . $newref . '</a>';
802
                                $dir_output = $conf->propal->multidir_output[$object->entity] . "/" . get_exdir(0, 0, 0, 1, $object, 'propal');
803
                                $object_type = 'propal';
804
                                $mesg = $outputlangs->transnoentitiesnoconv("EMailTextProposalClosedSigned", $link);
805
                                if (!empty($object->context['closedfromonlinesignature'])) {
806
                                    $mesg .= ' - From online page';
807
                                }
808
                                break;
809
                            case 'FICHINTER_ADD_CONTACT':
810
                                $link = '<a href="' . $urlwithroot . '/fichinter/card.php?id=' . $object->id . '&entity=' . $object->entity . '">' . $newref . '</a>';
811
                                $dir_output = $conf->ficheinter->dir_output;
812
                                $object_type = 'ficheinter';
813
                                $mesg = $outputlangs->transnoentitiesnoconv("EMailTextInterventionAddedContact", $link);
814
                                break;
815
                            case 'FICHINTER_VALIDATE':
816
                                $link = '<a href="' . $urlwithroot . '/fichinter/card.php?id=' . $object->id . '&entity=' . $object->entity . '">' . $newref . '</a>';
817
                                $dir_output = $conf->ficheinter->dir_output;
818
                                $object_type = 'ficheinter';
819
                                $mesg = $outputlangs->transnoentitiesnoconv("EMailTextInterventionValidated", $link);
820
                                break;
821
                            case 'FICHINTER_CLOSE':
822
                                $link = '<a href="' . $urlwithroot . '/fichinter/card.php?id=' . $object->id . '&entity=' . $object->entity . '">' . $newref . '</a>';
823
                                $dir_output = $conf->ficheinter->dir_output;
824
                                $object_type = 'ficheinter';
825
                                $mesg = $outputlangs->transnoentitiesnoconv("EMailTextInterventionClosed", $link);
826
                                break;
827
                            case 'ORDER_SUPPLIER_VALIDATE':
828
                                $link = '<a href="' . $urlwithroot . '/fourn/commande/card.php?id=' . $object->id . '&entity=' . $object->entity . '">' . $newref . '</a>';
829
                                $dir_output = $conf->fournisseur->commande->multidir_output[$object->entity] . "/" . get_exdir(0, 0, 0, 1, $object);
830
                                $object_type = 'order_supplier';
831
                                $labeltouse = isset($conf->global->ORDER_SUPPLIER_VALIDATE_TEMPLATE) ? $conf->global->ORDER_SUPPLIER_VALIDATE_TEMPLATE : '';
832
                                $mesg = $outputlangs->transnoentitiesnoconv("Hello") . ",\n\n";
833
                                $mesg .= $outputlangs->transnoentitiesnoconv("EMailTextSupplierOrderValidatedBy", $link, $user->getFullName($outputlangs));
834
                                $mesg .= "\n\n" . $outputlangs->transnoentitiesnoconv("Sincerely") . ".\n\n";
835
                                break;
836
                            case 'ORDER_SUPPLIER_CANCEL':
837
                                $link = '<a href="' . $urlwithroot . '/fourn/commande/card.php?id=' . $object->id . '&entity=' . $object->entity . '">' . $newref . '</a>';
838
                                $dir_output = $conf->fournisseur->commande->multidir_output[$object->entity] . "/" . get_exdir(0, 0, 0, 1, $object);
839
                                $object_type = 'order_supplier';
840
                                $mesg = $outputlangs->transnoentitiesnoconv("Hello") . ",\n\n";
841
                                $mesg .= $outputlangs->transnoentitiesnoconv("EMailTextSupplierOrderCanceledBy", $link, $user->getFullName($outputlangs));
842
                                $mesg .= "\n\n" . $outputlangs->transnoentitiesnoconv("Sincerely") . ".\n\n";
843
                                break;
844
                            case 'ORDER_SUPPLIER_APPROVE':
845
                                $link = '<a href="' . $urlwithroot . '/fourn/commande/card.php?id=' . $object->id . '&entity=' . $object->entity . '">' . $newref . '</a>';
846
                                $dir_output = $conf->fournisseur->commande->multidir_output[$object->entity] . "/" . get_exdir(0, 0, 0, 1, $object);
847
                                $object_type = 'order_supplier';
848
                                $labeltouse = isset($conf->global->ORDER_SUPPLIER_APPROVE_TEMPLATE) ? $conf->global->ORDER_SUPPLIER_APPROVE_TEMPLATE : '';
849
                                $mesg = $outputlangs->transnoentitiesnoconv("Hello") . ",\n\n";
850
                                $mesg .= $outputlangs->transnoentitiesnoconv("EMailTextSupplierOrderApprovedBy", $link, $user->getFullName($outputlangs));
851
                                $mesg .= "\n\n" . $outputlangs->transnoentitiesnoconv("Sincerely") . ".\n\n";
852
                                break;
853
                            case 'ORDER_SUPPLIER_SUBMIT':
854
                                $link = '<a href="' . $urlwithroot . '/fourn/commande/card.php?id=' . $object->id . '&entity=' . $object->entity . '">' . $newref . '</a>';
855
                                $dir_output = $conf->fournisseur->commande->multidir_output[$object->entity] . "/" . get_exdir(0, 0, 0, 1, $object);
856
                                $object_type = 'order_supplier';
857
                                $mesg = $outputlangs->transnoentitiesnoconv("Hello") . ",\n\n";
858
                                $mesg .= $outputlangs->transnoentitiesnoconv("EMailTextSupplierOrderSubmittedBy", $link, $user->getFullName($outputlangs));
859
                                $mesg .= "\n\n" . $outputlangs->transnoentitiesnoconv("Sincerely") . ".\n\n";
860
                                break;
861
                            case 'ORDER_SUPPLIER_REFUSE':
862
                                $link = '<a href="' . $urlwithroot . '/fourn/commande/card.php?id=' . $object->id . '&entity=' . $object->entity . '">' . $newref . '</a>';
863
                                $dir_output = $conf->fournisseur->commande->multidir_output[$object->entity] . "/" . get_exdir(0, 0, 0, 1, $object);
864
                                $object_type = 'order_supplier';
865
                                $labeltouse = isset($conf->global->ORDER_SUPPLIER_REFUSE_TEMPLATE) ? $conf->global->ORDER_SUPPLIER_REFUSE_TEMPLATE : '';
866
                                $mesg = $outputlangs->transnoentitiesnoconv("Hello") . ",\n\n";
867
                                $mesg .= $outputlangs->transnoentitiesnoconv("EMailTextSupplierOrderRefusedBy", $link, $user->getFullName($outputlangs));
868
                                $mesg .= "\n\n" . $outputlangs->transnoentitiesnoconv("Sincerely") . ".\n\n";
869
                                break;
870
                            case 'SHIPPING_VALIDATE':
871
                                $link = '<a href="' . $urlwithroot . '/expedition/card.php?id=' . $object->id . '&entity=' . $object->entity . '">' . $newref . '</a>';
872
                                $dir_output = $conf->expedition->dir_output . "/sending/" . get_exdir(0, 0, 0, 1, $object, 'shipment');
873
                                $object_type = 'shipping';
874
                                $mesg = $outputlangs->transnoentitiesnoconv("EMailTextExpeditionValidated", $link);
875
                                break;
876
                            case 'EXPENSE_REPORT_VALIDATE':
877
                                $link = '<a href="' . $urlwithroot . '/expensereport/card.php?id=' . $object->id . '&entity=' . $object->entity . '">' . $newref . '</a>';
878
                                $dir_output = $conf->expensereport->dir_output;
879
                                $object_type = 'expensereport';
880
                                $mesg = $outputlangs->transnoentitiesnoconv("EMailTextExpenseReportValidated", $link);
881
                                break;
882
                            case 'EXPENSE_REPORT_APPROVE':
883
                                $link = '<a href="' . $urlwithroot . '/expensereport/card.php?id=' . $object->id . '&entity=' . $object->entity . '">' . $newref . '</a>';
884
                                $dir_output = $conf->expensereport->dir_output;
885
                                $object_type = 'expensereport';
886
                                $mesg = $outputlangs->transnoentitiesnoconv("EMailTextExpenseReportApproved", $link);
887
                                break;
888
                            case 'HOLIDAY_VALIDATE':
889
                                $link = '<a href="' . $urlwithroot . '/holiday/card.php?id=' . $object->id . '&entity=' . $object->entity . '">' . $newref . '</a>';
890
                                $dir_output = $conf->holiday->dir_output;
891
                                $object_type = 'holiday';
892
                                $mesg = $outputlangs->transnoentitiesnoconv("EMailTextHolidayValidated", $link);
893
                                break;
894
                            case 'HOLIDAY_APPROVE':
895
                                $link = '<a href="' . $urlwithroot . '/holiday/card.php?id=' . $object->id . '&entity=' . $object->entity . '">' . $newref . '</a>';
896
                                $dir_output = $conf->holiday->dir_output;
897
                                $object_type = 'holiday';
898
                                $mesg = $outputlangs->transnoentitiesnoconv("EMailTextHolidayApproved", $link);
899
                                break;
900
                            case 'ACTION_CREATE':
901
                                $link = '<a href="' . $urlwithroot . '/comm/action/card.php?id=' . $object->id . '&entity=' . $object->entity . '">' . $newref . '</a>';
902
                                $dir_output = $conf->agenda->dir_output;
903
                                $object_type = 'action';
904
                                $mesg = $outputlangs->transnoentitiesnoconv("EMailTextActionAdded", $link);
905
                                break;
906
                            default:
907
                                $object_type = $object->element;
908
                                $dir_output = $conf->$object_type->multidir_output[$object->entity ? $object->entity : $conf->entity] . "/" . get_exdir(0, 0, 0, 1, $object, $object_type);
909
                                $template = $notifcode . '_TEMPLATE';
910
                                $mesg = $outputlangs->transnoentitiesnoconv('Notify_' . $notifcode) . ' ' . $newref . ' ' . $dir_output;
911
                                break;
912
                        }
913
914
                        include_once DOL_DOCUMENT_ROOT . '/core/class/html.formmail.class.php';
915
                        $formmail = new FormMail($this->db);
916
                        $arraydefaultmessage = null;
917
918
                        $template = $notifcode . '_TEMPLATE';
919
                        $labeltouse = getDolGlobalString($template);
920
                        if (!empty($labeltouse)) {
921
                            $arraydefaultmessage = $formmail->getEMailTemplate($this->db, $object_type . '_send', $user, $outputlangs, 0, 1, $labeltouse);
922
                        }
923
                        if (!empty($labeltouse) && is_object($arraydefaultmessage) && $arraydefaultmessage->id > 0) {
924
                            $substitutionarray = getCommonSubstitutionArray($outputlangs, 0, null, $object);
925
                            complete_substitutions_array($substitutionarray, $outputlangs, $object);
926
                            $subject = make_substitutions($arraydefaultmessage->topic, $substitutionarray, $outputlangs);
927
                            $message = make_substitutions($arraydefaultmessage->content, $substitutionarray, $outputlangs);
928
                        } else {
929
                            $message = $outputlangs->transnoentities("YouReceiveMailBecauseOfNotification", $application, $mysoc->name) . "\n";
930
                            $message .= $outputlangs->transnoentities("YouReceiveMailBecauseOfNotification2", $application, $mysoc->name) . "\n";
931
                            $message .= "\n";
932
                            $message .= $mesg;
933
                        }
934
935
                        $ref = dol_sanitizeFileName($newref);
936
                        $pdf_path = $dir_output . "/" . $ref . ".pdf";
937
                        if (!dol_is_file($pdf_path) || (is_object($arraydefaultmessage) && $arraydefaultmessage->id > 0 && !$arraydefaultmessage->joinfiles)) {
938
                            // We can't add PDF as it is not generated yet.
939
                            $filepdf = '';
940
                        } else {
941
                            $filepdf = $pdf_path;
942
                            $filename_list[] = $filepdf;
943
                            $mimetype_list[] = mime_content_type($filepdf);
944
                            $mimefilename_list[] = $ref . ".pdf";
945
                        }
946
947
                        $labeltouse = !empty($labeltouse) ? $labeltouse : '';
948
949
                        // Replace keyword __SUPERVISOREMAIL__
950
                        if (preg_match('/__SUPERVISOREMAIL__/', $sendto)) {
951
                            $newval = '';
952
                            if ($user->fk_user > 0) {
953
                                $supervisoruser = new User($this->db);
954
                                $supervisoruser->fetch($user->fk_user);
955
                                if ($supervisoruser->email) {
956
                                    $newval = trim(dolGetFirstLastname($supervisoruser->firstname, $supervisoruser->lastname) . ' <' . $supervisoruser->email . '>');
957
                                }
958
                            }
959
                            dol_syslog("Replace the __SUPERVISOREMAIL__ key into recipient email string with " . $newval);
960
                            $sendto = preg_replace('/__SUPERVISOREMAIL__/', $newval, $sendto);
961
                            $sendto = preg_replace('/,\s*,/', ',', $sendto); // in some case you can have $sendto like "email, __SUPERVISOREMAIL__ , otheremail" then you have "email,  , othermail" and it's not valid
962
                            $sendto = preg_replace('/^[\s,]+/', '', $sendto); // Clean start of string
963
                            $sendto = preg_replace('/[\s,]+$/', '', $sendto); // Clean end of string
964
                        }
965
966
                        $parameters = array('notifcode' => $notifcode, 'sendto' => $sendto, 'from' => $from, 'file' => $filename_list, 'mimefile' => $mimetype_list, 'filename' => $mimefilename_list, 'outputlangs' => $outputlangs, 'labeltouse' => $labeltouse);
967
                        if (!isset($action)) {
968
                            $action = '';
969
                        }
970
971
                        $reshook = $hookmanager->executeHooks('formatNotificationMessage', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
972
                        if (empty($reshook)) {
973
                            if (!empty($hookmanager->resArray['files'])) {
974
                                $filename_list = $hookmanager->resArray['files']['file'];
975
                                $mimetype_list = $hookmanager->resArray['files']['mimefile'];
976
                                $mimefilename_list = $hookmanager->resArray['files']['filename'];
977
                            }
978
                            if (!empty($hookmanager->resArray['subject'])) {
979
                                $subject .= $hookmanager->resArray['subject'];
980
                            }
981
                            if (!empty($hookmanager->resArray['message'])) {
982
                                $message .= $hookmanager->resArray['message'];
983
                            }
984
                        }
985
986
                        $mailfile = new CMailFile(
987
                            $subject,
988
                            $sendto,
989
                            $from,
990
                            $message,
991
                            $filename_list,
992
                            $mimetype_list,
993
                            $mimefilename_list,
994
                            '',
995
                            '',
996
                            0,
997
                            -1,
998
                            '',
999
                            '',
1000
                            $trackid,
1001
                            '',
1002
                            'notification'
1003
                        );
1004
1005
                        if ($mailfile->sendfile()) {
1006
                            if ($obj->type_target == 'touserid') {
1007
                                $sql = "INSERT INTO " . $this->db->prefix() . "notify (daten, fk_action, fk_soc, fk_user, type, objet_type, type_target, objet_id, email)";
1008
                                $sql .= " VALUES ('" . $this->db->idate(dol_now()) . "', " . ((int) $notifcodedefid) . ", " . ($object->socid > 0 ? ((int) $object->socid) : 'null') . ", " . ((int) $obj->cid) . ", '" . $this->db->escape($obj->type) . "', '" . $this->db->escape($object_type) . "', '" . $this->db->escape($obj->type_target) . "', " . ((int) $object->id) . ", '" . $this->db->escape($obj->email) . "')";
1009
                            } else {
1010
                                $sql = "INSERT INTO " . $this->db->prefix() . "notify (daten, fk_action, fk_soc, fk_contact, type, objet_type, type_target, objet_id, email)";
1011
                                $sql .= " VALUES ('" . $this->db->idate(dol_now()) . "', " . ((int) $notifcodedefid) . ", " . ($object->socid > 0 ? ((int) $object->socid) : 'null') . ", " . ((int) $obj->cid) . ", '" . $this->db->escape($obj->type) . "', '" . $this->db->escape($object_type) . "', '" . $this->db->escape($obj->type_target) . "', " . ((int) $object->id) . ", '" . $this->db->escape($obj->email) . "')";
1012
                            }
1013
                            if (!$this->db->query($sql)) {
1014
                                dol_print_error($this->db);
1015
                            }
1016
                        } else {
1017
                            $error++;
1018
                            $this->errors[] = $mailfile->error;
1019
                        }
1020
                    } else {
1021
                        dol_syslog("No notification sent for " . $sendto . " because email is empty");
1022
                    }
1023
                    $i++;
1024
                }
1025
            } else {
1026
                dol_syslog("No notification to thirdparty sent, nothing into notification setup for the thirdparty socid = " . (empty($object->socid) ? '' : $object->socid));
1027
            }
1028
        } else {
1029
            $error++;
1030
            $this->errors[] = $this->db->lasterror();
1031
            dol_syslog("Failed to get list of notification to send " . $this->db->lasterror(), LOG_ERR);
1032
            return -1;
1033
        }
1034
1035
        // Check notification using fixed email
1036
        // TODO Move vars NOTIFICATION_FIXEDEMAIL into table llx_notify_def and inclulde the case into previous loop of sql result
1037
        if (!$error) {
1038
            foreach ($conf->global as $key => $val) {
1039
                $reg = array();
1040
                if ($val == '' || !preg_match('/^NOTIFICATION_FIXEDEMAIL_' . $notifcode . '_THRESHOLD_HIGHER_(.*)$/', $key, $reg)) {
1041
                    continue;
1042
                }
1043
1044
                $sendto = $val;
1045
1046
                $threshold = (float) $reg[1];
1047
                if (!empty($object->total_ht) && $object->total_ht <= $threshold) {
1048
                    dol_syslog("A notification is requested for notifcode = " . $notifcode . " but amount = " . $object->total_ht . " so lower than threshold = " . $threshold . ". We discard this notification");
1049
                    continue;
1050
                }
1051
1052
                $notifcodedefid = dol_getIdFromCode($this->db, $notifcode, 'c_action_trigger', 'code', 'rowid');
1053
                if ($notifcodedefid <= 0) {
1054
                    dol_print_error($this->db, 'Failed to get id from code');
1055
                }
1056
                $trackid = '';
1057
1058
                $object_type = '';
1059
                $link = '';
1060
                $num++;
1061
1062
                $appli = $mysoc->name;
1063
1064
                $subject = '[' . $appli . '] ' . $langs->transnoentitiesnoconv("DolibarrNotification") . ($projtitle ? ' ' . $projtitle : '');
1065
1066
                switch ($notifcode) {
1067
                    case 'BILL_VALIDATE':
1068
                        $link = '<a href="' . $urlwithroot . '/compta/facture/card.php?facid=' . $object->id . '&entity=' . $object->entity . '">' . $newref . '</a>';
1069
                        $dir_output = $conf->facture->dir_output . "/" . get_exdir(0, 0, 0, 1, $object, 'invoice');
1070
                        $object_type = 'facture';
1071
                        $mesg = $langs->transnoentitiesnoconv("EMailTextInvoiceValidated", $link);
1072
                        break;
1073
                    case 'BILL_PAYED':
1074
                        $link = '<a href="' . $urlwithroot . '/compta/facture/card.php?facid=' . $object->id . '&entity=' . $object->entity . '">' . $newref . '</a>';
1075
                        $dir_output = $conf->facture->dir_output . "/" . get_exdir(0, 0, 0, 1, $object, 'invoice');
1076
                        $object_type = 'facture';
1077
                        $mesg = $langs->transnoentitiesnoconv("EMailTextInvoicePayed", $link);
1078
                        break;
1079
                    case 'ORDER_VALIDATE':
1080
                        $link = '<a href="' . $urlwithroot . '/commande/card.php?id=' . $object->id . '&entity=' . $object->entity . '">' . $newref . '</a>';
1081
                        $dir_output = $conf->commande->dir_output . "/" . get_exdir(0, 0, 0, 1, $object, 'commande');
1082
                        $object_type = 'order';
1083
                        $mesg = $langs->transnoentitiesnoconv("EMailTextOrderValidated", $link);
1084
                        break;
1085
                    case 'ORDER_CLOSE':
1086
                        $link = '<a href="' . $urlwithroot . '/commande/card.php?id=' . $object->id . '&entity=' . $object->entity . '">' . $newref . '</a>';
1087
                        $dir_output = $conf->commande->dir_output . "/" . get_exdir(0, 0, 0, 1, $object, 'commande');
1088
                        $object_type = 'order';
1089
                        $mesg = $langs->transnoentitiesnoconv("EMailTextOrderClose", $link);
1090
                        break;
1091
                    case 'PROPAL_VALIDATE':
1092
                        $link = '<a href="' . $urlwithroot . '/comm/propal/card.php?id=' . $object->id . '&entity=' . $object->entity . '">' . $newref . '</a>';
1093
                        $dir_output = $conf->propal->multidir_output[$object->entity] . "/" . get_exdir(0, 0, 0, 1, $object, 'propal');
1094
                        $object_type = 'propal';
1095
                        $mesg = $langs->transnoentitiesnoconv("EMailTextProposalValidated", $link);
1096
                        break;
1097
                    case 'PROPAL_CLOSE_SIGNED':
1098
                        $link = '<a href="' . $urlwithroot . '/comm/propal/card.php?id=' . $object->id . '&entity=' . $object->entity . '">' . $newref . '</a>';
1099
                        $dir_output = $conf->propal->multidir_output[$object->entity] . "/" . get_exdir(0, 0, 0, 1, $object, 'propal');
1100
                        $object_type = 'propal';
1101
                        $mesg = $langs->transnoentitiesnoconv("EMailTextProposalClosedSigned", $link);
1102
                        break;
1103
                    case 'FICHINTER_ADD_CONTACT':
1104
                        $link = '<a href="' . $urlwithroot . '/fichinter/card.php?id=' . $object->id . '&entity=' . $object->entity . '">' . $newref . '</a>';
1105
                        $dir_output = $conf->ficheinter->dir_output;
1106
                        $object_type = 'ficheinter';
1107
                        $mesg = $langs->transnoentitiesnoconv("EMailTextInterventionAddedContact", $link);
1108
                        break;
1109
                    case 'FICHINTER_VALIDATE':
1110
                        $link = '<a href="' . $urlwithroot . '/fichinter/card.php?id=' . $object->id . '&entity=' . $object->entity . '">' . $newref . '</a>';
1111
                        $dir_output = $conf->facture->dir_output;
1112
                        $object_type = 'ficheinter';
1113
                        $mesg = $langs->transnoentitiesnoconv("EMailTextInterventionValidated", $link);
1114
                        break;
1115
                    case 'FICHINTER_CLOSE':
1116
                        $link = '<a href="' . $urlwithroot . '/fichinter/card.php?id=' . $object->id . '&entity=' . $object->entity . '">' . $newref . '</a>';
1117
                        $dir_output = $conf->facture->dir_output;
1118
                        $object_type = 'ficheinter';
1119
                        $mesg = $langs->transnoentitiesnoconv("EMailTextInterventionClosed", $link);
1120
                        break;
1121
                    case 'ORDER_SUPPLIER_CANCEL':
1122
                        $link = '<a href="' . $urlwithroot . '/fourn/commande/card.php?id=' . $object->id . '&entity=' . $object->entity . '">' . $newref . '</a>';
1123
                        $dir_output = $conf->fournisseur->commande->multidir_output[$object->entity] . "/" . get_exdir(0, 0, 0, 1, $object);
1124
                        $object_type = 'order_supplier';
1125
                        $mesg = $langs->transnoentitiesnoconv("Hello") . ",\n\n";
1126
                        $mesg .= $langs->transnoentitiesnoconv("EMailTextSupplierOrderCanceledBy", $link, $user->getFullName($langs));
1127
                        $mesg .= "\n\n" . $langs->transnoentitiesnoconv("Sincerely") . ".\n\n";
1128
                        break;
1129
                    case 'ORDER_SUPPLIER_VALIDATE':
1130
                        $link = '<a href="' . $urlwithroot . '/fourn/commande/card.php?id=' . $object->id . '&entity=' . $object->entity . '">' . $newref . '</a>';
1131
                        $dir_output = $conf->fournisseur->commande->multidir_output[$object->entity] . "/" . get_exdir(0, 0, 0, 1, $object);
1132
                        $object_type = 'order_supplier';
1133
                        $mesg = $langs->transnoentitiesnoconv("Hello") . ",\n\n";
1134
                        $mesg .= $langs->transnoentitiesnoconv("EMailTextSupplierOrderValidatedBy", $link, $user->getFullName($langs));
1135
                        $mesg .= "\n\n" . $langs->transnoentitiesnoconv("Sincerely") . ".\n\n";
1136
                        break;
1137
                    case 'ORDER_SUPPLIER_APPROVE':
1138
                        $link = '<a href="' . $urlwithroot . '/fourn/commande/card.php?id=' . $object->id . '&entity=' . $object->entity . '">' . $newref . '</a>';
1139
                        $dir_output = $conf->fournisseur->commande->multidir_output[$object->entity] . "/" . get_exdir(0, 0, 0, 1, $object);
1140
                        $object_type = 'order_supplier';
1141
                        $mesg = $langs->transnoentitiesnoconv("Hello") . ",\n\n";
1142
                        $mesg .= $langs->transnoentitiesnoconv("EMailTextSupplierOrderApprovedBy", $link, $user->getFullName($langs));
1143
                        $mesg .= "\n\n" . $langs->transnoentitiesnoconv("Sincerely") . ".\n\n";
1144
                        break;
1145
                    case 'ORDER_SUPPLIER_SUBMIT':
1146
                        $link = '<a href="' . $urlwithroot . '/fourn/commande/card.php?id=' . $object->id . '&entity=' . $object->entity . '">' . $newref . '</a>';
1147
                        $dir_output = $conf->fournisseur->commande->multidir_output[$object->entity] . "/" . get_exdir(0, 0, 0, 1, $object);
1148
                        $object_type = 'order_supplier';
1149
                        $mesg = $langs->transnoentitiesnoconv("Hello") . ",\n\n";
1150
                        $mesg .= $langs->transnoentitiesnoconv("EMailTextSupplierOrderSubmittedBy", $link, $user->getFullName($langs));
1151
                        $mesg .= "\n\n" . $langs->transnoentitiesnoconv("Sincerely") . ".\n\n";
1152
                        break;
1153
                    case 'ORDER_SUPPLIER_REFUSE':
1154
                        $link = '<a href="' . $urlwithroot . '/fourn/commande/card.php?id=' . $object->id . '&entity=' . $object->entity . '">' . $newref . '</a>';
1155
                        $dir_output = $conf->fournisseur->commande->multidir_output[$object->entity] . "/" . get_exdir(0, 0, 0, 1, $object);
1156
                        $object_type = 'order_supplier';
1157
                        $mesg = $langs->transnoentitiesnoconv("Hello") . ",\n\n";
1158
                        $mesg .= $langs->transnoentitiesnoconv("EMailTextSupplierOrderRefusedBy", $link, $user->getFullName($langs));
1159
                        $mesg .= "\n\n" . $langs->transnoentitiesnoconv("Sincerely") . ".\n\n";
1160
                        break;
1161
                    case 'SHIPPING_VALIDATE':
1162
                        $link = '<a href="' . $urlwithroot . '/expedition/card.php?id=' . $object->id . '&entity=' . $object->entity . '">' . $newref . '</a>';
1163
                        $dir_output = $conf->expedition->dir_output . "/sending/" . get_exdir(0, 0, 0, 1, $object, 'shipment');
1164
                        $object_type = 'order_supplier';
1165
                        $mesg = $langs->transnoentitiesnoconv("EMailTextExpeditionValidated", $link);
1166
                        break;
1167
                    case 'EXPENSE_REPORT_VALIDATE':
1168
                        $link = '<a href="' . $urlwithroot . '/expensereport/card.php?id=' . $object->id . '&entity=' . $object->entity . '">' . $newref . '</a>';
1169
                        $dir_output = $conf->expensereport->dir_output;
1170
                        $object_type = 'expensereport';
1171
                        $mesg = $langs->transnoentitiesnoconv("EMailTextExpenseReportValidated", $link);
1172
                        break;
1173
                    case 'EXPENSE_REPORT_APPROVE':
1174
                        $link = '<a href="' . $urlwithroot . '/expensereport/card.php?id=' . $object->id . '&entity=' . $object->entity . '">' . $newref . '</a>';
1175
                        $dir_output = $conf->expensereport->dir_output;
1176
                        $object_type = 'expensereport';
1177
                        $mesg = $langs->transnoentitiesnoconv("EMailTextExpenseReportApproved", $link);
1178
                        break;
1179
                    case 'HOLIDAY_VALIDATE':
1180
                        $link = '<a href="' . $urlwithroot . '/holiday/card.php?id=' . $object->id . '&entity=' . $object->entity . '">' . $newref . '</a>';
1181
                        $dir_output = $conf->holiday->dir_output;
1182
                        $object_type = 'holiday';
1183
                        $mesg = $langs->transnoentitiesnoconv("EMailTextHolidayValidated", $link);
1184
                        break;
1185
                    case 'HOLIDAY_APPROVE':
1186
                        $link = '<a href="' . $urlwithroot . '/holiday/card.php?id=' . $object->id . '&entity=' . $object->entity . '">' . $newref . '</a>';
1187
                        $dir_output = $conf->holiday->dir_output;
1188
                        $object_type = 'holiday';
1189
                        $mesg = $langs->transnoentitiesnoconv("EMailTextHolidayApproved", $link);
1190
                        break;
1191
                    case 'ACTION_CREATE':
1192
                        $link = '<a href="' . $urlwithroot . '/comm/action/card.php?id=' . $object->id . '&entity=' . $object->entity . '">' . $newref . '</a>';
1193
                        $dir_output = $conf->agenda->dir_output;
1194
                        $object_type = 'action';
1195
                        $mesg = $langs->transnoentitiesnoconv("EMailTextActionAdded", $link);
1196
                        break;
1197
                    default:
1198
                        $object_type = $object->element;
1199
                        $dir_output = $conf->$object_type->multidir_output[$object->entity ? $object->entity : $conf->entity] . "/" . get_exdir(0, 0, 0, 1, $object, $object_type);
1200
                        $mesg = $langs->transnoentitiesnoconv('Notify_' . $notifcode) . ' ' . $newref;
1201
                        break;
1202
                }
1203
                $ref = dol_sanitizeFileName($newref);
1204
                $pdf_path = $dir_output . "/" . $ref . "/" . $ref . ".pdf";
1205
                if (!dol_is_file($pdf_path)) {
1206
                    // We can't add PDF as it is not generated yet.
1207
                    $filepdf = '';
1208
                } else {
1209
                    $filepdf = $pdf_path;
1210
                    $filename_list[] = $pdf_path;
1211
                    $mimetype_list[] = mime_content_type($filepdf);
1212
                    $mimefilename_list[] = $ref . ".pdf";
1213
                }
1214
1215
                // Set output language
1216
                $outputlangs = $langs;
1217
1218
                // if an e-mail template is configured for this notification code (for instance 'SHIPPING_VALIDATE_TEMPLATE', ...),
1219
                // we fetch this template by its label. Otherwise, a default message content will be sent.
1220
                $mailTemplateLabel = getDolGlobalString($notifcode . '_TEMPLATE');
1221
                $emailTemplate = null;
1222
                if (!empty($mailTemplateLabel)) {
1223
                    include_once DOL_DOCUMENT_ROOT . '/core/class/html.formmail.class.php';
1224
                    $formmail = new FormMail($this->db);
1225
                    $emailTemplate = $formmail->getEMailTemplate($this->db, $object_type . '_send', $user, $outputlangs, 0, 1, $mailTemplateLabel);
1226
                }
1227
                if (!empty($mailTemplateLabel) && is_object($emailTemplate) && $emailTemplate->id > 0) {
1228
                    if (property_exists($object, 'thirdparty') && $object->thirdparty instanceof Societe && $object->thirdparty->default_lang && $object->thirdparty->default_lang != $langs->defaultlang) {
0 ignored issues
show
Bug introduced by
The type Dolibarr\Code\Core\Classes\Societe was not found. Did you mean Societe? If so, make sure to prefix the type with \.
Loading history...
1229
                        $outputlangs = new Translate('', $conf);
1230
                        $outputlangs->setDefaultLang($object->thirdparty->default_lang);
1231
                        $outputlangs->loadLangs(array('main', 'other'));
1232
                    }
1233
                    $substitutionarray = getCommonSubstitutionArray($outputlangs, 0, null, $object);
1234
                    complete_substitutions_array($substitutionarray, $outputlangs, $object);
1235
                    $subject = make_substitutions($emailTemplate->topic, $substitutionarray, $outputlangs);
1236
                    $message = make_substitutions($emailTemplate->content, $substitutionarray, $outputlangs);
1237
                } else {
1238
                    $message = '';
1239
                    $message .= $outputlangs->transnoentities("YouReceiveMailBecauseOfNotification2", $application, $mysoc->name) . "\n";
1240
                    $message .= "\n";
1241
                    $message .= $mesg;
1242
1243
                    $message = nl2br($message);
1244
                }
1245
1246
                // Replace keyword __SUPERVISOREMAIL__
1247
                if (preg_match('/__SUPERVISOREMAIL__/', $sendto)) {
1248
                    $newval = '';
1249
                    if ($user->fk_user > 0) {
1250
                        $supervisoruser = new User($this->db);
1251
                        $supervisoruser->fetch($user->fk_user);
1252
                        if ($supervisoruser->email) {
1253
                            $newval = trim(dolGetFirstLastname($supervisoruser->firstname, $supervisoruser->lastname) . ' <' . $supervisoruser->email . '>');
1254
                        }
1255
                    }
1256
                    dol_syslog("Replace the __SUPERVISOREMAIL__ key into recipient email string with " . $newval);
1257
                    $sendto = preg_replace('/__SUPERVISOREMAIL__/', $newval, $sendto);
1258
                    $sendto = preg_replace('/,\s*,/', ',', $sendto); // in some case you can have $sendto like "email, __SUPERVISOREMAIL__ , otheremail" then you have "email,  , othermail" and it's not valid
1259
                    $sendto = preg_replace('/^[\s,]+/', '', $sendto); // Clean start of string
1260
                    $sendto = preg_replace('/[\s,]+$/', '', $sendto); // Clean end of string
1261
                }
1262
1263
                if ($sendto) {
1264
                    $parameters = array('notifcode' => $notifcode, 'sendto' => $sendto, 'from' => $from, 'file' => $filename_list, 'mimefile' => $mimetype_list, 'filename' => $mimefilename_list, 'subject' => &$subject, 'message' => &$message);
1265
                    $reshook = $hookmanager->executeHooks('formatNotificationMessage', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1266
                    if (empty($reshook)) {
1267
                        if (!empty($hookmanager->resArray['files'])) {
1268
                            $filename_list = $hookmanager->resArray['files']['file'];
1269
                            $mimetype_list = $hookmanager->resArray['files']['mimefile'];
1270
                            $mimefilename_list = $hookmanager->resArray['files']['filename'];
1271
                        }
1272
                        if (!empty($hookmanager->resArray['subject'])) {
1273
                            $subject .= $hookmanager->resArray['subject'];
1274
                        }
1275
                        if (!empty($hookmanager->resArray['message'])) {
1276
                            $message .= $hookmanager->resArray['message'];
1277
                        }
1278
                    }
1279
                    $mailfile = new CMailFile(
1280
                        $subject,
1281
                        $sendto,
1282
                        $from,
1283
                        $message,
1284
                        $filename_list,
1285
                        $mimetype_list,
1286
                        $mimefilename_list,
1287
                        '',
1288
                        '',
1289
                        0,
1290
                        1,
1291
                        '',
1292
                        $trackid,
1293
                        '',
1294
                        '',
1295
                        'notification'
1296
                    );
1297
1298
                    if ($mailfile->sendfile()) {
1299
                        $sql = "INSERT INTO " . $this->db->prefix() . "notify (daten, fk_action, fk_soc, fk_contact, type, type_target, objet_type, objet_id, email)";
1300
                        $sql .= " VALUES ('" . $this->db->idate(dol_now()) . "', " . ((int) $notifcodedefid) . ", " . ($object->socid > 0 ? ((int) $object->socid) : 'null') . ", null, 'email', 'tofixedemail', '" . $this->db->escape($object_type) . "', " . ((int) $object->id) . ", '" . $this->db->escape($sendto) . "')";
1301
                        if (!$this->db->query($sql)) {
1302
                            dol_print_error($this->db);
1303
                        }
1304
                    } else {
1305
                        $error++;
1306
                        $this->errors[] = $mailfile->error;
1307
                    }
1308
                }
1309
            }
1310
        }
1311
1312
        if (!$error) {
1313
            return $num;
1314
        } else {
1315
            return -1 * $error;
1316
        }
1317
    }
1318
}
1319