Passed
Push — GENERAL_BUG_REVIEW_240911 ( 3362b2...8cbbee )
by Rafael
49:13
created

MailingTargets::addTargetsToDatabase()   B

Complexity

Conditions 9
Paths 34

Size

Total Lines 82
Code Lines 45

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 9
eloc 45
nc 34
nop 2
dl 0
loc 82
rs 7.6444
c 0
b 0
f 0

How to fix   Long Method   

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-2004  Rodolphe Quiedeville        <[email protected]>
4
 * Copyright (C) 2004-2008  Laurent Destailleur         <[email protected]>
5
 * Copyright (C) 2004       Eric Seigne                 <[email protected]>
6
 * Copyright (C) 2024       Rafael San José             <[email protected]>
7
 *
8
 * This program is free software; you can redistribute it and/or modify
9
 * it under the terms of the GNU General Public License as published by
10
 * the Free Software Foundation; either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20
 * or see https://www.gnu.org/
21
 */
22
23
namespace Dolibarr\Code\Mailing\Classes;
24
25
use DoliDB;
26
use Exception;
27
28
/**
29
 *      \file       htdocs/core/modules/mailings/modules_mailings.php
30
 *      \ingroup    mailing
31
 *      \brief      File with parent class of emailing target selectors modules
32
 */
33
34
require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/functions.lib.php';
35
36
/**
37
 *      Parent class of emailing target selectors modules
38
 */
39
class MailingTargets // This can't be abstract as it is used for some method
40
{
41
    /**
42
     * @var DoliDB      Database handler (result of a new DoliDB)
43
     */
44
    public $db;
45
46
    /**
47
     * @var string Error code (or message)
48
     */
49
    public $error = '';
50
51
    /**
52
     * @var array of errors
53
     */
54
    public $errors;
55
56
    /**
57
     * @var string  Condition to be enabled
58
     */
59
    public $enabled;
60
61
    /**
62
     * @var string Name of the module
63
     */
64
    public $name;
65
66
    /**
67
     * @var string Description of the module
68
     */
69
    public $desc;
70
71
    /**
72
     * @var string Tooltip to show after description of the module
73
     */
74
    public $tooltip = '';
75
76
    /**
77
     * @var string To store the SQL string used to find the recipients
78
     */
79
    public $sql;
80
81
82
    public $evenunsubscribe = 0;        // Set this to 1 if you want to flag you also want to include email in target that has opt-out.
83
84
85
    /**
86
     *  Constructor
87
     *
88
     * @param DoliDB $db Database handler
89
     */
90
    public function __construct($db)
91
    {
92
        $this->db = $db;
93
    }
94
95
    /**
96
     * Return description of email selector
97
     *
98
     * @return     string      Return translation of module label. Try translation of $this->name then translation of 'MailingModuleDesc'.$this->name, or $this->desc if not found
99
     */
100
    public function getDesc()
101
    {
102
        global $langs, $form;
103
104
        $langs->load("mails");
105
        $transstring = "MailingModuleDesc" . $this->name;
106
        $s = '';
107
108
        if ($langs->trans($this->name) != $this->name) {
109
            $s = $langs->trans($this->name);
110
        } elseif ($langs->trans($transstring) != $transstring) {
111
            $s = $langs->trans($transstring);
112
        } else {
113
            $s = $this->desc;
114
        }
115
116
        if ($this->tooltip && is_object($form)) {
117
            $s .= ' ' . $form->textwithpicto('', $langs->trans($this->tooltip), 1, 1);
118
        }
119
        return $s;
120
    }
121
122
    /**
123
     *  Return number of records for email selector
124
     *
125
     * @return     integer      Example
126
     */
127
    public function getNbOfRecords()
128
    {
129
        return 0;
130
    }
131
132
    /**
133
     * Retourne nombre de destinataires
134
     *
135
     * @param string $sql Sql request to count
136
     * @return     int|string               Nb of recipient, or <0 if error, or '' if NA
137
     */
138
    public function getNbOfRecipients($sql)
139
    {
140
        $result = $this->db->query($sql);
141
        if ($result) {
142
            $total = 0;
143
            while ($obj = $this->db->fetch_object($result)) {
144
                $total += $obj->nb;
145
            }
146
            return $total;
147
        } else {
148
            $this->error = $this->db->lasterror();
149
            return -1;
150
        }
151
    }
152
153
    /**
154
     * Affiche formulaire de filtre qui apparait dans page de selection
155
     * des destinataires de mailings
156
     *
157
     * @return     string      Retourne zone select
158
     */
159
    public function formFilter()
160
    {
161
        return '';
162
    }
163
164
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
165
166
    /**
167
     * Met a jour nombre de destinataires
168
     *
169
     * @param int $mailing_id Id of emailing
170
     * @return  int                          Return integer < 0 si erreur, nb destinataires si ok
171
     */
172
    public function update_nb($mailing_id)
173
    {
174
        // phpcs:enable
175
        // Mise a jour nombre de destinataire dans table des mailings
176
        $sql = "SELECT COUNT(*) nb FROM " . MAIN_DB_PREFIX . "mailing_cibles";
177
        $sql .= " WHERE fk_mailing = " . ((int)$mailing_id);
178
        $result = $this->db->query($sql);
179
        if ($result) {
180
            $obj = $this->db->fetch_object($result);
181
            $nb = $obj->nb;
182
183
            $sql = "UPDATE " . MAIN_DB_PREFIX . "mailing";
184
            $sql .= " SET nbemail = " . ((int)$nb) . " WHERE rowid = " . ((int)$mailing_id);
185
            if (!$this->db->query($sql)) {
186
                dol_syslog($this->db->error());
187
                $this->error = $this->db->error();
188
                return -1;
189
            }
190
        } else {
191
            return -1;
192
        }
193
        return $nb;
194
    }
195
196
    /**
197
     * Add a list of targets into the database
198
     *
199
     * @param int $mailing_id Id of emailing
200
     * @param array $cibles Array with targets
201
     * @return  int                    Return integer < 0 if error, nb added if OK
202
     */
203
    public function addTargetsToDatabase($mailing_id, $cibles)
204
    {
205
        global $conf;
206
207
        $this->db->begin();
208
209
        // Insert emailing targets from array into database
210
        $j = 0;
211
        $num = count($cibles);
212
        foreach ($cibles as $targetarray) {
213
            if (!empty($targetarray['email'])) { // avoid empty email address
214
                $sql = "INSERT INTO " . MAIN_DB_PREFIX . "mailing_cibles";
215
                $sql .= " (fk_mailing,";
216
                $sql .= " fk_contact,";
217
                $sql .= " lastname, firstname, email, other, source_url, source_id,";
218
                $sql .= " tag,";
219
                $sql .= " source_type)";
220
                $sql .= " VALUES (" . ((int)$mailing_id) . ",";
221
                $sql .= (empty($targetarray['fk_contact']) ? '0' : (int)$targetarray['fk_contact']) . ",";
222
                $sql .= "'" . $this->db->escape($targetarray['lastname']) . "',";
223
                $sql .= "'" . $this->db->escape($targetarray['firstname']) . "',";
224
                $sql .= "'" . $this->db->escape($targetarray['email']) . "',";
225
                $sql .= "'" . $this->db->escape($targetarray['other']) . "',";
226
                $sql .= "'" . $this->db->escape($targetarray['source_url']) . "',";
227
                $sql .= (empty($targetarray['source_id']) ? 'null' : "'" . $this->db->escape($targetarray['source_id']) . "'") . ",";
228
                $sql .= "'" . $this->db->escape(dol_hash($conf->file->instance_unique_id . ";" . $targetarray['email'] . ";" . $targetarray['lastname'] . ";" . ((int)$mailing_id) . ";" . getDolGlobalString('MAILING_EMAIL_UNSUBSCRIBE_KEY'), 'md5')) . "',";
229
                $sql .= "'" . $this->db->escape($targetarray['source_type']) . "')";
230
                dol_syslog(__METHOD__, LOG_DEBUG);
231
                $result = $this->db->query($sql);
232
                if ($result) {
233
                    $j++;
234
                } else {
235
                    if ($this->db->errno() != 'DB_ERROR_RECORD_ALREADY_EXISTS') {
236
                        // Si erreur autre que doublon
237
                        dol_syslog($this->db->error() . ' : ' . $targetarray['email']);
238
                        $this->error = $this->db->error() . ' : ' . $targetarray['email'];
239
                        $this->db->rollback();
240
                        return -1;
241
                    }
242
                }
243
            }
244
        }
245
246
        dol_syslog(__METHOD__ . ": mailing " . $j . " targets added");
247
248
        /*
249
        //Update the status to show thirdparty mail that don't want to be contacted anymore'
250
        $sql = "UPDATE ".MAIN_DB_PREFIX."mailing_cibles";
251
        $sql .= " SET statut=3";
252
        $sql .= " WHERE fk_mailing = ".((int) $mailing_id)." AND email in (SELECT email FROM ".MAIN_DB_PREFIX."societe where fk_stcomm=-1)";
253
        $sql .= " AND source_type='thirdparty'";
254
        dol_syslog(__METHOD__.": mailing update status to display thirdparty mail that do not want to be contacted");
255
        $result=$this->db->query($sql);
256
257
        //Update the status to show contact mail that don't want to be contacted anymore'
258
        $sql = "UPDATE ".MAIN_DB_PREFIX."mailing_cibles";
259
        $sql .= " SET statut=3";
260
        $sql .= " WHERE fk_mailing = ".((int) $mailing_id)." AND source_type='contact' AND (email in (SELECT sc.email FROM ".MAIN_DB_PREFIX."socpeople AS sc ";
261
        $sql .= " INNER JOIN ".MAIN_DB_PREFIX."societe s ON s.rowid=sc.fk_soc WHERE s.fk_stcomm=-1 OR no_email=1))";
262
        dol_syslog(__METHOD__.": mailing update status to display contact mail that do not want to be contacted",LOG_DEBUG);
263
        $result=$this->db->query($sql);
264
        */
265
266
        if (empty($this->evenunsubscribe)) {
267
            $sql = "UPDATE " . MAIN_DB_PREFIX . "mailing_cibles as mc";
268
            $sql .= " SET mc.statut = 3";
269
            $sql .= " WHERE mc.fk_mailing = " . ((int)$mailing_id);
270
            $sql .= " AND EXISTS (SELECT rowid FROM " . MAIN_DB_PREFIX . "mailing_unsubscribe as mu WHERE mu.email = mc.email and mu.entity = " . ((int)$conf->entity) . ")";
271
272
            dol_syslog(__METHOD__ . ":mailing update status to display emails that do not want to be contacted anymore", LOG_DEBUG);
273
            $result = $this->db->query($sql);
274
            if (!$result) {
275
                dol_print_error($this->db);
276
            }
277
        }
278
279
        // Update nb of recipient into emailing record
280
        $this->update_nb($mailing_id);
281
282
        $this->db->commit();
283
284
        return $j;
285
    }
286
287
    // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
288
289
    /**
290
     *  Supprime tous les destinataires de la table des cibles
291
     *
292
     * @param int $mailing_id Id of emailing
293
     * @return void
294
     */
295
    public function clear_target($mailing_id)
296
    {
297
        // phpcs:enable
298
        $sql = "DELETE FROM " . MAIN_DB_PREFIX . "mailing_cibles";
299
        $sql .= " WHERE fk_mailing = " . ((int)$mailing_id);
300
301
        if (!$this->db->query($sql)) {
302
            dol_syslog($this->db->error());
303
        }
304
305
        $this->update_nb($mailing_id);
306
    }
307
308
309
    /**
310
     *  Return list of widget. Function used by admin page htdoc/admin/widget.
311
     *  List is sorted by widget filename so by priority to run.
312
     *
313
     * @param array $forcedir null=All default directories. This parameter is used by modulebuilder module only.
314
     * @return array                       Array list of widget
315
     */
316
    public static function getEmailingSelectorsList($forcedir = null)
317
    {
318
        global $langs, $db;
319
320
        $files = array();
321
        $fullpath = array();
322
        $relpath = array();
323
        $iscoreorexternal = array();
324
        $modules = array();
325
        $orders = array();
326
        $i = 0;
327
328
        $diremailselector = array('/core/modules/mailings/'); // $conf->modules_parts['emailings'] is not required
329
        if (is_array($forcedir)) {
330
            $diremailselector = $forcedir;
331
        }
332
333
        foreach ($diremailselector as $reldir) {
334
            $dir = dol_buildpath($reldir, 0);
335
            $newdir = dol_osencode($dir);
336
337
            // Check if directory exists (we do not use dol_is_dir to avoid loading files.lib.php at each call)
338
            if (!is_dir($newdir)) {
339
                continue;
340
            }
341
342
            $handle = opendir($newdir);
343
            if (is_resource($handle)) {
344
                while (($file = readdir($handle)) !== false) {
345
                    $reg = array();
346
                    if (is_readable($newdir . '/' . $file) && preg_match('/^(.+)\.modules.php/', $file, $reg)) {
347
                        if (preg_match('/\.back$/', $file) || preg_match('/^(.+)\.disabled\.php/', $file)) {
348
                            continue;
349
                        }
350
351
                        $part1 = $reg[1];
352
353
                        //$modName = ucfirst($reg[1]);
354
                        $modName = 'mailing_' . $reg[1];  // name of selector submodule
355
                        //print "file=$file modName=$modName"; exit;
356
                        if (in_array($modName, $modules)) {
357
                            $langs->load("errors");
358
                            print '<div class="error">' . $langs->trans("Error") . ' : ' . $langs->trans("ErrorDuplicateEmalingSelector", $modName, "") . '</div>';
359
                        } else {
360
                            try {
361
                                //print $newdir.'/'.$file;
362
                                include_once $newdir . '/' . $file;
363
                            } catch (Exception $e) {
364
                                print $e->getMessage();
365
                            }
366
                        }
367
368
                        $files[$i] = $file;
369
                        $fullpath[$i] = $dir . '/' . $file;
370
                        $relpath[$i] = preg_replace('/^\//', '', $reldir) . '/' . $file;
371
                        $iscoreorexternal[$i] = ($reldir == '/core/modules/mailings/' ? 'internal' : 'external');
372
                        $modules[$i] = $modName;
373
                        $orders[$i] = $part1; // Set sort criteria value
374
375
                        $i++;
376
                    }
377
                }
378
                closedir($handle);
379
            }
380
        }
381
        //echo "<pre>";print_r($modules);echo "</pre>";
382
383
        asort($orders);
384
385
        $widget = array();
386
        $j = 0;
387
388
        // Loop on each emailing selector
389
        foreach ($orders as $key => $value) {
390
            $modName = $modules[$key];
391
            if (empty($modName)) {
392
                continue;
393
            }
394
395
            if (!class_exists($modName)) {
396
                print 'Error: An emailing selector file was found but its class "' . $modName . '" was not found.' . "<br>\n";
397
                continue;
398
            }
399
400
            $objMod = new $modName($db);
401
            if (is_object($objMod)) {
402
                // Define disabledbyname and disabledbymodule
403
                $disabledbyname = 0;
404
                $disabledbymodule = 0; // TODO Set to 2 if module is not enabled
405
                $module = '';
406
407
                // Check if widget file is disabled by name
408
                if (preg_match('/NORUN$/i', $files[$key])) {
409
                    $disabledbyname = 1;
410
                }
411
412
                // We set info of modules
413
                $widget[$j]['picto'] = (empty($objMod->picto) ? (empty($objMod->boximg) ? img_object('', 'generic') : $objMod->boximg) : img_object('', $objMod->picto));
414
                $widget[$j]['file'] = $files[$key];
415
                $widget[$j]['fullpath'] = $fullpath[$key];
416
                $widget[$j]['relpath'] = $relpath[$key];
417
                $widget[$j]['iscoreorexternal'] = $iscoreorexternal[$key];
418
                $widget[$j]['version'] = empty($objMod->version) ? '' : $objMod->version;
419
                $widget[$j]['status'] = img_picto($langs->trans("Active"), 'tick');
420
                if ($disabledbyname > 0 || $disabledbymodule > 1) {
421
                    $widget[$j]['status'] = '';
422
                }
423
424
                $text = '<b>' . $langs->trans("Description") . ':</b><br>';
425
                $text .= $objMod->boxlabel . '<br>';
426
                $text .= '<br><b>' . $langs->trans("Status") . ':</b><br>';
427
                if ($disabledbymodule == 2) {
428
                    $text .= $langs->trans("WidgetDisabledAsModuleDisabled", $module) . '<br>';
429
                }
430
431
                $widget[$j]['info'] = $text;
432
            }
433
            $j++;
434
        }
435
436
        return $widget;
437
    }
438
}
439