Passed
Push — master ( b5dddf...91d417 )
by Richard
09:12
created

XoopsNotificationHandler::subscribe()   B

Complexity

Conditions 9
Paths 65

Size

Total Lines 42
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 28
dl 0
loc 42
rs 8.0555
c 0
b 0
f 0
cc 9
nc 65
nop 6
1
<?php
2
/**
3
 * XOOPS Kernel Class
4
 *
5
 * You may not change or alter any portion of this comment or credits
6
 * of supporting developers from this source code or any supporting source code
7
 * which is considered copyrighted (c) material of the original comment or credit authors.
8
 * This program is distributed in the hope that it will be useful,
9
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11
 *
12
 * @copyright       (c) 2000-2016 XOOPS Project (www.xoops.org)
13
 * @license             GNU GPL 2 (http://www.gnu.org/licenses/gpl-2.0.html)
14
 * @package             kernel
15
 * @since               2.0.0
16
 * @author              Michael van Dam <[email protected]>
17
 * @author              Kazumi Ono (AKA onokazu) http://www.myweb.ne.jp/, http://jp.xoops.org/
18
 */
19
defined('XOOPS_ROOT_PATH') || exit('Restricted access');
20
21
// RMV-NOTIFY
22
include_once $GLOBALS['xoops']->path('include/notification_constants.php');
23
include_once $GLOBALS['xoops']->path('include/notification_functions.php');
24
25
/**
26
 * A Notification
27
 *
28
 * @package             kernel
29
 * @subpackage          notification
30
 *
31
 * @author              Michael van Dam    <[email protected]>
32
 * @copyright       (c) 2000-2016 XOOPS Project (www.xoops.org)
33
 */
34
class XoopsNotification extends XoopsObject
35
{
36
    /**
37
     * Constructor
38
     **/
39
    public function __construct()
40
    {
41
        parent::__construct();
42
        $this->initVar('not_id', XOBJ_DTYPE_INT, null, false);
43
        $this->initVar('not_modid', XOBJ_DTYPE_INT, null, false);
44
        $this->initVar('not_category', XOBJ_DTYPE_TXTBOX, null, false, 30);
45
        $this->initVar('not_itemid', XOBJ_DTYPE_INT, 0, false);
46
        $this->initVar('not_event', XOBJ_DTYPE_TXTBOX, null, false, 30);
47
        $this->initVar('not_uid', XOBJ_DTYPE_INT, 0, true);
48
        $this->initVar('not_mode', XOBJ_DTYPE_INT, 0, false);
49
    }
50
51
    // FIXME:???
52
    // To send email to multiple users simultaneously, we would need to move
53
    // the notify functionality to the handler class.  BUT, some of the tags
54
    // are user-dependent, so every email msg will be unique.  (Unless maybe use
55
    // smarty for email templates in the future.)  Also we would have to keep
56
    // track if each user wanted email or PM.
57
58
    /**
59
     * Returns Class Base Variable not_id
60
     * @param  string $format
61
     * @return mixed
62
     */
63
    public function id($format = 'N')
64
    {
65
        return $this->getVar('not_id', $format);
66
    }
67
68
    /**
69
     * Returns Class Base Variable not_id
70
     * @param  string $format
71
     * @return mixed
72
     */
73
    public function not_id($format = '')
74
    {
75
        return $this->getVar('not_id', $format);
76
    }
77
78
    /**
79
     * Returns Class Base Variable not_modid
80
     * @param  string $format
81
     * @return mixed
82
     */
83
    public function not_modid($format = '')
84
    {
85
        return $this->getVar('not_modid', $format);
86
    }
87
88
    /**
89
     * Returns Class Base Variable mid
90
     * @param  string $format
91
     * @return mixed
92
     */
93
    public function not_category($format = '')
94
    {
95
        return $this->getVar('not_category', $format);
96
    }
97
98
    /**
99
     * Returns Class Base Variable not_itemid
100
     * @param  string $format
101
     * @return mixed
102
     */
103
    public function not_itemid($format = '')
104
    {
105
        return $this->getVar('not_itemid', $format);
106
    }
107
108
    /**
109
     * Returns Class Base Variable not_event
110
     * @param  string $format
111
     * @return mixed
112
     */
113
    public function not_event($format = '')
114
    {
115
        return $this->getVar('not_event', $format);
116
    }
117
118
    /**
119
     * Returns Class Base Variable not_uid
120
     * @param  string $format
121
     * @return mixed
122
     */
123
    public function not_uid($format = '')
124
    {
125
        return $this->getVar('not_uid', $format);
126
    }
127
128
    /**
129
     * Returns Class Base Variable not_mode
130
     * @param  string $format
131
     * @return mixed
132
     */
133
    public function not_mode($format = '')
134
    {
135
        return $this->getVar('not_mode', $format);
136
    }
137
138
    /**
139
     * Send a notification message to the user
140
     *
141
     * @param string $template_dir Template directory
142
     * @param string $template     Template name
143
     * @param string $subject      Subject line for notification message
144
     * @param array  $tags         Array of substitutions for template variables
145
     *
146
     * @return bool true if success, false if error
147
     **/
148
    public function notifyUser($template_dir, $template, $subject, $tags)
149
    {
150
        // Check the user's notification preference.
151
        /* @var $member_handler XoopsMemberHandler */
152
        $member_handler = xoops_getHandler('member');
153
        $user           = $member_handler->getUser($this->getVar('not_uid'));
154
        if (!is_object($user)) {
155
            return true;
156
        }
157
        $method = $user->getVar('notify_method');
158
159
        $xoopsMailer = xoops_getMailer();
160
        include_once $GLOBALS['xoops']->path('include/notification_constants.php');
161
        switch ($method) {
162
            case XOOPS_NOTIFICATION_METHOD_PM:
163
                $xoopsMailer->usePM();
164
                /* @var $config_handler XoopsConfigHandler  */
165
                $config_handler    = xoops_getHandler('config');
166
                $xoopsMailerConfig = $config_handler->getConfigsByCat(XOOPS_CONF_MAILER);
167
                $xoopsMailer->setFromUser($member_handler->getUser($xoopsMailerConfig['fromuid']));
168
                foreach ($tags as $k => $v) {
169
                    $xoopsMailer->assign($k, $v);
170
                }
171
                break;
172
            case XOOPS_NOTIFICATION_METHOD_EMAIL:
173
                $xoopsMailer->useMail();
174
                foreach ($tags as $k => $v) {
175
                    $xoopsMailer->assign($k, preg_replace('/&amp;/i', '&', $v));
176
                }
177
                break;
178
            default:
179
                return true; // report error in user's profile??
180
//                break;
181
        }
182
183
        // Set up the mailer
184
        $xoopsMailer->setTemplateDir($template_dir);
185
        $xoopsMailer->setTemplate($template);
186
        $xoopsMailer->setToUsers($user);
187
        //global $xoopsConfig;
188
        //$xoopsMailer->setFromEmail($xoopsConfig['adminmail']);
189
        //$xoopsMailer->setFromName($xoopsConfig['sitename']);
190
        $xoopsMailer->setSubject($subject);
191
        $success = $xoopsMailer->send();
192
193
        // If send-once-then-delete, delete notification
194
        // If send-once-then-wait, disable notification
195
        include_once $GLOBALS['xoops']->path('include/notification_constants.php');
196
        $notification_handler = xoops_getHandler('notification');
197
198
        if ($this->getVar('not_mode') == XOOPS_NOTIFICATION_MODE_SENDONCETHENDELETE) {
199
            $notification_handler->delete($this);
200
201
            return $success;
202
        }
203
204
        if ($this->getVar('not_mode') == XOOPS_NOTIFICATION_MODE_SENDONCETHENWAIT) {
205
            $this->setVar('not_mode', XOOPS_NOTIFICATION_MODE_WAITFORLOGIN);
206
            $notification_handler->insert($this);
207
        }
208
209
        return $success;
210
    }
211
}
212
213
/**
214
 * XOOPS notification handler class.
215
 *
216
 * This class is responsible for providing data access mechanisms to the data source
217
 * of XOOPS notification class objects.
218
 *
219
 *
220
 * @package             kernel
221
 * @subpackage          notification
222
 *
223
 * @author              Michael van Dam <[email protected]>
224
 * @copyright       (c) 2000-2016 XOOPS Project (www.xoops.org)
225
 */
226
class XoopsNotificationHandler extends XoopsObjectHandler
227
{
228
    /**
229
     * Create a {@link XoopsNotification}
230
     *
231
     * @param bool $isNew Flag the object as "new"?
232
     *
233
     * @return XoopsNotification
234
     */
235
    public function create($isNew = true)
236
    {
237
        $notification = new XoopsNotification();
238
        if ($isNew) {
239
            $notification->setNew();
240
        }
241
242
        return $notification;
243
    }
244
245
    /**
246
     * Retrieve a {@link XoopsNotification}
247
     *
248
     * @param int $id ID
249
     *
250
     * @return XoopsNotification {@link XoopsNotification}, FALSE on fail
251
     **/
252
    public function get($id)
253
    {
254
        $notification = false;
255
        $id           = (int)$id;
256
        if ($id > 0) {
257
            $sql = 'SELECT * FROM ' . $this->db->prefix('xoopsnotifications') . ' WHERE not_id=' . $id;
258
            if (!$result = $this->db->query($sql)) {
0 ignored issues
show
Bug introduced by
The method query() does not exist on XoopsDatabase. Since it exists in all sub-types, consider adding an abstract or default implementation to XoopsDatabase. ( Ignorable by Annotation )

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

258
            if (!$result = $this->db->/** @scrutinizer ignore-call */ query($sql)) {
Loading history...
259
                return $notification;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $notification returns the type false which is incompatible with the documented return type XoopsNotification.
Loading history...
260
            }
261
            $numrows = $this->db->getRowsNum($result);
0 ignored issues
show
Bug introduced by
The method getRowsNum() does not exist on XoopsDatabase. Since it exists in all sub-types, consider adding an abstract or default implementation to XoopsDatabase. ( Ignorable by Annotation )

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

261
            /** @scrutinizer ignore-call */ 
262
            $numrows = $this->db->getRowsNum($result);
Loading history...
262
            if ($numrows == 1) {
263
                $notification = new XoopsNotification();
264
                $notification->assignVars($this->db->fetchArray($result));
0 ignored issues
show
Bug introduced by
The method fetchArray() does not exist on XoopsDatabase. Since it exists in all sub-types, consider adding an abstract or default implementation to XoopsDatabase. ( Ignorable by Annotation )

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

264
                $notification->assignVars($this->db->/** @scrutinizer ignore-call */ fetchArray($result));
Loading history...
265
            }
266
        }
267
268
        return $notification;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $notification could also return false which is incompatible with the documented return type XoopsNotification. Did you maybe forget to handle an error condition?

If the returned type also contains false, it is an indicator that maybe an error condition leading to the specific return statement remains unhandled.

Loading history...
269
    }
270
271
    /**
272
     * Write a notification(subscription) to database
273
     *
274
     * @param  XoopsObject|XoopsNotification $notification a XoopsNotification object
275
     *
276
     * @return bool true on success, otherwise false
277
     **/
278
    public function insert(XoopsObject $notification)
279
    {
280
        $className = 'XoopsNotification';
281
        if (!($notification instanceof $className)) {
282
            return false;
283
        }
284
        if (!$notification->isDirty()) {
285
            return true;
286
        }
287
        if (!$notification->cleanVars()) {
288
            return false;
289
        }
290
        foreach ($notification->cleanVars as $k => $v) {
291
            ${$k} = $v;
292
        }
293
        if ($notification->isNew()) {
294
            $not_id = $this->db->genId('xoopsnotifications_not_id_seq');
0 ignored issues
show
Bug introduced by
The method genId() does not exist on XoopsDatabase. Since it exists in all sub-types, consider adding an abstract or default implementation to XoopsDatabase. ( Ignorable by Annotation )

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

294
            /** @scrutinizer ignore-call */ 
295
            $not_id = $this->db->genId('xoopsnotifications_not_id_seq');
Loading history...
295
            $sql    = sprintf('INSERT INTO %s (not_id, not_modid, not_itemid, not_category, not_uid, not_event, not_mode) VALUES (%u, %u, %u, %s, %u, %s, %u)', $this->db->prefix('xoopsnotifications'), $not_id, $not_modid, $not_itemid, $this->db->quoteString($not_category), $not_uid, $this->db->quoteString($not_event), $not_mode);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $not_event seems to be never defined.
Loading history...
Comprehensibility Best Practice introduced by
The variable $not_modid seems to be never defined.
Loading history...
Comprehensibility Best Practice introduced by
The variable $not_mode seems to be never defined.
Loading history...
Bug introduced by
The method quoteString() does not exist on XoopsDatabase. Since it exists in all sub-types, consider adding an abstract or default implementation to XoopsDatabase. ( Ignorable by Annotation )

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

295
            $sql    = sprintf('INSERT INTO %s (not_id, not_modid, not_itemid, not_category, not_uid, not_event, not_mode) VALUES (%u, %u, %u, %s, %u, %s, %u)', $this->db->prefix('xoopsnotifications'), $not_id, $not_modid, $not_itemid, $this->db->/** @scrutinizer ignore-call */ quoteString($not_category), $not_uid, $this->db->quoteString($not_event), $not_mode);
Loading history...
Comprehensibility Best Practice introduced by
The variable $not_uid does not exist. Did you maybe mean $not_id?
Loading history...
Comprehensibility Best Practice introduced by
The variable $not_itemid does not exist. Did you maybe mean $not_id?
Loading history...
Comprehensibility Best Practice introduced by
The variable $not_category seems to be never defined.
Loading history...
296
        } else {
297
            $sql = sprintf('UPDATE %s SET not_modid = %u, not_itemid = %u, not_category = %s, not_uid = %u, not_event = %s, not_mode = %u WHERE not_id = %u', $this->db->prefix('xoopsnotifications'), $not_modid, $not_itemid, $this->db->quoteString($not_category), $not_uid, $this->db->quoteString($not_event), $not_mode, $not_id);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $not_id seems to be never defined.
Loading history...
298
        }
299
        if (!$result = $this->db->query($sql)) {
0 ignored issues
show
Unused Code introduced by
The assignment to $result is dead and can be removed.
Loading history...
300
            return false;
301
        }
302
        if (empty($not_id)) {
303
            $not_id = $this->db->getInsertId();
0 ignored issues
show
Bug introduced by
The method getInsertId() does not exist on XoopsDatabase. Since it exists in all sub-types, consider adding an abstract or default implementation to XoopsDatabase. ( Ignorable by Annotation )

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

303
            /** @scrutinizer ignore-call */ 
304
            $not_id = $this->db->getInsertId();
Loading history...
304
        }
305
        $notification->assignVar('not_id', $not_id);
306
307
        return true;
308
    }
309
310
    /**
311
     * Delete a {@link XoopsNotification} from the database
312
     *
313
     * @param  XoopsObject|XoopsNotification $notification a XoopsNotification object
314
     *
315
     * @return bool true on success, otherwise false
316
     **/
317
    public function delete(XoopsObject $notification)
318
    {
319
        $className = 'XoopsNotification';
320
        if (!($notification instanceof $className)) {
321
            return false;
322
        }
323
324
        $sql = sprintf('DELETE FROM %s WHERE not_id = %u', $this->db->prefix('xoopsnotifications'), $notification->getVar('not_id'));
0 ignored issues
show
Bug introduced by
It seems like $notification->getVar('not_id') can also be of type array and array; however, parameter $args of sprintf() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

324
        $sql = sprintf('DELETE FROM %s WHERE not_id = %u', $this->db->prefix('xoopsnotifications'), /** @scrutinizer ignore-type */ $notification->getVar('not_id'));
Loading history...
325
        if (!$result = $this->db->query($sql)) {
0 ignored issues
show
Unused Code introduced by
The assignment to $result is dead and can be removed.
Loading history...
326
            return false;
327
        }
328
329
        return true;
330
    }
331
332
    /**
333
     * Get some {@link XoopsNotification}s
334
     *
335
     * @param CriteriaElement|CriteriaCompo $criteria
336
     * @param bool            $id_as_key Use IDs as keys into the array?
337
     *
338
     * @return array Array of {@link XoopsNotification} objects
339
     **/
340
    public function getObjects(CriteriaElement $criteria = null, $id_as_key = false)
341
    {
342
        $ret   = array();
343
        $limit = $start = 0;
344
        $sql   = 'SELECT * FROM ' . $this->db->prefix('xoopsnotifications');
345
        if (isset($criteria) && is_subclass_of($criteria, 'CriteriaElement')) {
346
            $sql .= ' ' . $criteria->renderWhere();
0 ignored issues
show
Bug introduced by
The method renderWhere() does not exist on CriteriaElement. Did you maybe mean render()? ( Ignorable by Annotation )

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

346
            $sql .= ' ' . $criteria->/** @scrutinizer ignore-call */ renderWhere();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
347
            $sort = ($criteria->getSort() != '') ? $criteria->getSort() : 'not_id';
348
            $sql .= ' ORDER BY ' . $sort . ' ' . $criteria->getOrder();
349
            $limit = $criteria->getLimit();
350
            $start = $criteria->getStart();
351
        }
352
        $result = $this->db->query($sql, $limit, $start);
353
        if (!$result) {
354
            return $ret;
355
        }
356
        while (false !== ($myrow = $this->db->fetchArray($result))) {
357
            $notification = new XoopsNotification();
358
            $notification->assignVars($myrow);
359
            if (!$id_as_key) {
360
                $ret[] = $notification;
361
            } else {
362
                $ret[$myrow['not_id']] = $notification;
363
            }
364
            unset($notification);
365
        }
366
367
        return $ret;
368
    }
369
370
    // TODO: Need this??
371
    /**
372
     * Count Notifications
373
     *
374
     * @param CriteriaElement|CriteriaCompo $criteria {@link CriteriaElement}
375
     *
376
     * @return int Count
377
     **/
378
    public function getCount(CriteriaElement $criteria = null)
379
    {
380
        $sql = 'SELECT COUNT(*) FROM ' . $this->db->prefix('xoopsnotifications');
381
        if (isset($criteria) && is_subclass_of($criteria, 'CriteriaElement')) {
382
            $sql .= ' ' . $criteria->renderWhere();
383
        }
384
        if (!$result = $this->db->query($sql)) {
385
            return 0;
386
        }
387
        list($count) = $this->db->fetchRow($result);
0 ignored issues
show
Bug introduced by
The method fetchRow() does not exist on XoopsDatabase. Since it exists in all sub-types, consider adding an abstract or default implementation to XoopsDatabase. ( Ignorable by Annotation )

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

387
        /** @scrutinizer ignore-call */ 
388
        list($count) = $this->db->fetchRow($result);
Loading history...
388
389
        return $count;
390
    }
391
392
    /**
393
     * Delete multiple notifications
394
     *
395
     * @param CriteriaElement|CriteriaCompo $criteria {@link CriteriaElement}
396
     *
397
     * @return bool
398
     **/
399
    public function deleteAll(CriteriaElement $criteria = null)
400
    {
401
        $sql = 'DELETE FROM ' . $this->db->prefix('xoopsnotifications');
402
        if (isset($criteria) && is_subclass_of($criteria, 'CriteriaElement')) {
403
            $sql .= ' ' . $criteria->renderWhere();
404
        }
405
        if (!$result = $this->db->query($sql)) {
0 ignored issues
show
Unused Code introduced by
The assignment to $result is dead and can be removed.
Loading history...
406
            return false;
407
        }
408
409
        return true;
410
    }
411
412
    // TODO: rename this...
413
    // Also, should we have get by module, get by category, etc...??
414
    /**
415
     * @param $module_id
416
     * @param $category
417
     * @param $item_id
418
     * @param $event
419
     * @param $user_id
420
     *
421
     * @return bool
422
     */
423
    public function &getNotification($module_id, $category, $item_id, $event, $user_id)
424
    {
425
        $criteria = new CriteriaCompo();
426
        $criteria->add(new Criteria('not_modid', (int)$module_id));
427
        $criteria->add(new Criteria('not_category', $this->db->escape($category)));
0 ignored issues
show
Bug introduced by
The method escape() does not exist on XoopsDatabase. Since it exists in all sub-types, consider adding an abstract or default implementation to XoopsDatabase. ( Ignorable by Annotation )

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

427
        $criteria->add(new Criteria('not_category', $this->db->/** @scrutinizer ignore-call */ escape($category)));
Loading history...
428
        $criteria->add(new Criteria('not_itemid', (int)$item_id));
429
        $criteria->add(new Criteria('not_event', $this->db->escape($event)));
430
        $criteria->add(new Criteria('not_uid', (int)$user_id));
431
        $objects = $this->getObjects($criteria);
432
        if (count($objects) == 1) {
433
            return $objects[0];
434
        }
435
        $inst = false;
436
437
        return $inst;
438
    }
439
440
    /**
441
     * Determine if a user is subscribed to a particular event in
442
     * a particular module.
443
     *
444
     * @param string $category  Category of notification event
445
     * @param int    $item_id   Item ID of notification event
446
     * @param string $event     Event
447
     * @param int    $module_id ID of module (default current module)
448
     * @param int    $user_id   ID of user (default current user)
449
     *                          return int  0 if not subscribe; non-zero if subscribed
450
     *
451
     * @return int
452
     */
453
    public function isSubscribed($category, $item_id, $event, $module_id, $user_id)
454
    {
455
        $criteria = new CriteriaCompo();
456
        $criteria->add(new Criteria('not_modid', (int)$module_id));
457
        $criteria->add(new Criteria('not_category', $this->db->escape($category)));
458
        $criteria->add(new Criteria('not_itemid', (int)$item_id));
459
        $criteria->add(new Criteria('not_event', $this->db->escape($event)));
460
        $criteria->add(new Criteria('not_uid', (int)$user_id));
461
462
        return $this->getCount($criteria);
463
    }
464
465
    // TODO: how about a function to subscribe a whole group of users???
466
    // e.g. if we want to add all moderators to be notified of subscription
467
    // of new threads...
468
    /**
469
     * Subscribe for notification for an event(s)
470
     *
471
     * @param string $category  category of notification
472
     * @param int    $item_id   ID of the item
473
     * @param mixed  $events    event string or array of events
474
     * @param int    $mode      force a particular notification mode
475
     *                          (e.g. once_only) (default to current user preference)
476
     * @param int    $module_id ID of the module (default to current module)
477
     * @param int    $user_id   ID of the user (default to current user)
478
     *                          *
479
     *
480
     * @return bool
481
     */
482
    public function subscribe($category, $item_id, $events, $mode = null, $module_id = null, $user_id = null)
483
    {
484
        if (!isset($user_id)) {
485
            global $xoopsUser;
486
            if (empty($xoopsUser)) {
487
                return false; // anonymous cannot subscribe
488
            } else {
489
                $user_id = $xoopsUser->getVar('uid');
490
            }
491
        }
492
493
        if (!isset($module_id)) {
494
            global $xoopsModule;
495
            $module_id = $xoopsModule->getVar('mid');
496
        }
497
498
        if (!isset($mode)) {
499
            $user = new XoopsUser($user_id);
500
            $mode = $user->getVar('notify_mode');
501
        }
502
503
        if (!is_array($events)) {
504
            $events = array($events);
505
        }
506
        foreach ($events as $event) {
507
            /* @var  $notification XoopsNotification */
508
            if ($notification = $this->getNotification($module_id, $category, $item_id, $event, $user_id)) {
509
                if ($notification->getVar('not_mode') != $mode) {
510
                    $this->updateByField($notification, 'not_mode', $mode);
511
                }
512
            } else {
513
                $notification = $this->create();
514
                $notification->setVar('not_modid', $module_id);
515
                $notification->setVar('not_category', $category);
516
                $notification->setVar('not_itemid', $item_id);
517
                $notification->setVar('not_uid', $user_id);
518
                $notification->setVar('not_event', $event);
519
                $notification->setVar('not_mode', $mode);
520
                $this->insert($notification);
521
            }
522
        }
523
        return null;
524
    }
525
526
    // TODO: this will be to provide a list of everything a particular
527
    // user has subscribed to... e.g. for on the 'Profile' page, similar
528
    // to how we see the various posts etc. that the user has made.
529
    // We may also want to have a function where we can specify module id
530
    /**
531
     * Get a list of notifications by user ID
532
     *
533
     * @param int $user_id ID of the user
534
     *
535
     * @return array Array of {@link XoopsNotification} objects
536
     **/
537
    public function getByUser($user_id)
538
    {
539
        $criteria = new Criteria('not_uid', $user_id);
540
541
        return $this->getObjects($criteria, true);
542
    }
543
544
    // TODO: rename this??
545
    /**
546
     * Get a list of notification events for the current item/mod/user
547
     *
548
     * @param $category
549
     * @param $item_id
550
     * @param $module_id
551
     * @param $user_id
552
     * @return array
553
     */
554
    public function getSubscribedEvents($category, $item_id, $module_id, $user_id)
555
    {
556
        $criteria = new CriteriaCompo();
557
        $criteria->add(new Criteria('not_modid', (int)$module_id));
558
        $criteria->add(new Criteria('not_category', $this->db->escape($category)));
559
        if ($item_id) {
560
            $criteria->add(new Criteria('not_itemid', (int)$item_id));
561
        }
562
        $criteria->add(new Criteria('not_uid', (int)$user_id));
563
        $results = $this->getObjects($criteria, true);
564
        $ret     = array();
565
        foreach (array_keys($results) as $i) {
566
            $ret[] = $results[$i]->getVar('not_event');
567
        }
568
569
        return $ret;
570
    }
571
572
    // TODO: is this a useful function?? (Copied from comment_handler)
573
    /**
574
     * Retrieve items by their ID
575
     *
576
     * @param int    $module_id Module ID
577
     * @param int    $item_id   Item ID
578
     * @param string $order     Sort order
579
     *
580
     * @param null   $status
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $status is correct as it would always require null to be passed?
Loading history...
581
     *
582
     * @return array Array of {@link XoopsNotification} objects
583
     */
584
    public function getByItemId($module_id, $item_id, $order = null, $status = null)
585
    {
586
        $criteria = new CriteriaCompo(new Criteria('com_modid', (int)$module_id));
587
        $criteria->add(new Criteria('com_itemid', (int)$item_id));
588
        if (isset($status)) {
589
            $criteria->add(new Criteria('com_status', (int)$status));
590
        }
591
        if (isset($order)) {
592
            $criteria->setOrder($order);
593
        }
594
595
        return $this->getObjects($criteria);
596
    }
597
598
    /**
599
     * Send notifications to users
600
     *
601
     * @param string $category     notification category
602
     * @param int    $item_id      ID of the item
603
     * @param array  $events       trigger events
604
     * @param array  $extra_tags   array of substitutions for template to be
605
     *                              merged with the one from function..
606
     * @param array  $user_list    only notify the selected users
607
     * @param int    $module_id    ID of the module
608
     * @param int    $omit_user_id ID of the user to omit from notifications. (default to current user).  set to 0 for all users to receive notification.
609
     * @internal param string $event notification event
610
     */
611
    // TODO:(?) - pass in an event LIST.  This will help to avoid
612
    // problem of sending people multiple emails for similar events.
613
    // BUT, then we need an array of mail templates, etc...  Unless
614
    // mail templates can include logic in the future, then we can
615
    // tailor the mail so it makes sense for any of the possible
616
    // (or combination of) events.
617
    public function triggerEvents($category, $item_id, $events, $extra_tags = array(), $user_list = array(), $module_id = null, $omit_user_id = null)
618
    {
619
        if (!is_array($events)) {
0 ignored issues
show
introduced by
The condition is_array($events) is always true.
Loading history...
620
            $events = array($events);
621
        }
622
        foreach ($events as $event) {
623
            $this->triggerEvent($category, $item_id, $event, $extra_tags, $user_list, $module_id, $omit_user_id);
0 ignored issues
show
Bug introduced by
$category of type string is incompatible with the type integer expected by parameter $category of XoopsNotificationHandler::triggerEvent(). ( Ignorable by Annotation )

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

623
            $this->triggerEvent(/** @scrutinizer ignore-type */ $category, $item_id, $event, $extra_tags, $user_list, $module_id, $omit_user_id);
Loading history...
624
        }
625
    }
626
627
    /**
628
     * Enter description here...
629
     *
630
     * @param  int   $category
631
     * @param  int   $item_id
632
     * @param  int   $event
633
     * @param  array $extra_tags
634
     * @param  array $user_list
635
     * @param  int   $module_id
636
     * @param  int   $omit_user_id
637
     * @return mixed
638
     */
639
    public function triggerEvent($category, $item_id, $event, $extra_tags = array(), $user_list = array(), $module_id = null, $omit_user_id = null)
640
    {
641
        if (!isset($module_id)) {
642
            global $xoopsModule;
643
            $module    = $xoopsModule;
644
            $module_id = !empty($xoopsModule) ? $xoopsModule->getVar('mid') : 0;
645
        } else {
646
            /* @var $module_handler XoopsModuleHandler */
647
            $module_handler = xoops_getHandler('module');
648
            $module         = $module_handler->get($module_id);
649
        }
650
651
        // Check if event is enabled
652
        /* @var $config_handler XoopsConfigHandler  */
653
        $config_handler = xoops_getHandler('config');
654
        $mod_config     = $config_handler->getConfigsByCat(0, $module->getVar('mid'));
655
        if (empty($mod_config['notification_enabled'])) {
656
            return false;
657
        }
658
        $category_info =& notificationCategoryInfo($category, $module_id);
659
        $event_info    =& notificationEventInfo($category, $event, $module_id);
660
        if (!in_array(notificationGenerateConfig($category_info, $event_info, 'option_name'), $mod_config['notification_events']) && empty($event_info['invisible'])) {
0 ignored issues
show
Bug introduced by
It seems like $category_info can also be of type false; however, parameter $category of notificationGenerateConfig() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

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

660
        if (!in_array(notificationGenerateConfig(/** @scrutinizer ignore-type */ $category_info, $event_info, 'option_name'), $mod_config['notification_events']) && empty($event_info['invisible'])) {
Loading history...
Bug introduced by
It seems like $event_info can also be of type false; however, parameter $event of notificationGenerateConfig() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

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

660
        if (!in_array(notificationGenerateConfig($category_info, /** @scrutinizer ignore-type */ $event_info, 'option_name'), $mod_config['notification_events']) && empty($event_info['invisible'])) {
Loading history...
661
            return false;
662
        }
663
664
        if (!isset($omit_user_id)) {
665
            global $xoopsUser;
666
            $omit_user_id = 0;
667
            if (!empty($xoopsUser)) {
668
                $omit_user_id = $xoopsUser->getVar('uid');
669
            }
670
        }
671
        $criteria = new CriteriaCompo();
672
        $criteria->add(new Criteria('not_modid', (int)$module_id));
673
        $criteria->add(new Criteria('not_category', $this->db->escape($category)));
674
        $criteria->add(new Criteria('not_itemid', (int)$item_id));
675
        $criteria->add(new Criteria('not_event', $this->db->escape($event)));
676
        $mode_criteria = new CriteriaCompo();
677
        $mode_criteria->add(new Criteria('not_mode', XOOPS_NOTIFICATION_MODE_SENDALWAYS), 'OR');
678
        $mode_criteria->add(new Criteria('not_mode', XOOPS_NOTIFICATION_MODE_SENDONCETHENDELETE), 'OR');
679
        $mode_criteria->add(new Criteria('not_mode', XOOPS_NOTIFICATION_MODE_SENDONCETHENWAIT), 'OR');
680
        $criteria->add($mode_criteria);
681
        if (!empty($user_list)) {
682
            $user_criteria = new CriteriaCompo();
683
            foreach ($user_list as $user) {
684
                $user_criteria->add(new Criteria('not_uid', (int)$user), 'OR');
685
            }
686
            $criteria->add($user_criteria);
687
        }
688
        $notifications = $this->getObjects($criteria);
689
        if (empty($notifications)) {
690
            return null;
691
        }
692
693
        // Add some tag substitutions here
694
695
        $not_config = $module->getInfo('notification');
696
        $tags       = array();
697
        if (!empty($not_config)) {
698
            if (!empty($not_config['tags_file'])) {
699
                $tags_file = $GLOBALS['xoops']->path('modules/' . $module->getVar('dirname') . '/' . $not_config['tags_file']);
700
                if (file_exists($tags_file)) {
701
                    include_once $tags_file;
702
                    if (!empty($not_config['tags_func'])) {
703
                        $tags_func = $not_config['tags_func'];
704
                        if (function_exists($tags_func)) {
705
                            $tags = $tags_func($category, (int)$item_id, $event);
706
                        }
707
                    }
708
                }
709
            }
710
            // RMV-NEW
711
            if (!empty($not_config['lookup_file'])) {
712
                $lookup_file = $GLOBALS['xoops']->path('modules/' . $module->getVar('dirname') . '/' . $not_config['lookup_file']);
713
                if (file_exists($lookup_file)) {
714
                    include_once $lookup_file;
715
                    if (!empty($not_config['lookup_func'])) {
716
                        $lookup_func = $not_config['lookup_func'];
717
                        if (function_exists($lookup_func)) {
718
                            $item_info = $lookup_func($category, (int)$item_id);
719
                        }
720
                    }
721
                }
722
            }
723
        }
724
        $tags['X_ITEM_NAME']       = !empty($item_info['name']) ? $item_info['name'] : '[' . _NOT_ITEMNAMENOTAVAILABLE . ']';
725
        $tags['X_ITEM_URL']        = !empty($item_info['url']) ? $item_info['url'] : '[' . _NOT_ITEMURLNOTAVAILABLE . ']';
726
        $tags['X_ITEM_TYPE']       = !empty($category_info['item_name']) ? $category_info['title'] : '[' . _NOT_ITEMTYPENOTAVAILABLE . ']';
727
        $tags['X_MODULE']          = $module->getVar('name');
728
        $tags['X_MODULE_URL']      = XOOPS_URL . '/modules/' . $module->getVar('dirname') . '/';
729
        $tags['X_NOTIFY_CATEGORY'] = $category;
730
        $tags['X_NOTIFY_EVENT']    = $event;
731
732
        $template_dir = $event_info['mail_template_dir'];
733
        $template     = $event_info['mail_template'] . '.tpl';
734
        $subject      = $event_info['mail_subject'];
735
736
        foreach ($notifications as $notification) {
737
            if (empty($omit_user_id) || $notification->getVar('not_uid') != $omit_user_id) {
738
                // user-specific tags
739
                //$tags['X_UNSUBSCRIBE_URL'] = 'TODO';
740
                // TODO: don't show unsubscribe link if it is 'one-time' ??
741
                $tags['X_UNSUBSCRIBE_URL'] = XOOPS_URL . '/notifications.php';
742
                $tags                      = array_merge($tags, $extra_tags);
743
                $notification->notifyUser($template_dir, $template, $subject, $tags);
744
            }
745
        }
746
        return null;
747
    }
748
749
    /**
750
     * Delete all notifications for one user
751
     *
752
     * @param  int $user_id ID of the user
753
     * @return bool
754
     **/
755
    public function unsubscribeByUser($user_id)
756
    {
757
        $criteria = new Criteria('not_uid', (int)$user_id);
758
759
        return $this->deleteAll($criteria);
760
    }
761
762
    // TODO: allow these to use current module, etc...
763
    /**
764
     * Unsubscribe notifications for an event(s).
765
     *
766
     * @param string $category  category of the events
767
     * @param int    $item_id   ID of the item
768
     * @param mixed  $events    event string or array of events
769
     * @param int    $module_id ID of the module (default current module)
770
     * @param int    $user_id   UID of the user (default current user)
771
     *
772
     * @return bool
773
     **/
774
    public function unsubscribe($category, $item_id, $events, $module_id = null, $user_id = null)
775
    {
776
        if (!isset($user_id)) {
777
            global $xoopsUser;
778
            if (empty($xoopsUser)) {
779
                return false; // anonymous cannot subscribe
780
            } else {
781
                $user_id = $xoopsUser->getVar('uid');
782
            }
783
        }
784
        if (!isset($module_id)) {
785
            global $xoopsModule;
786
            $module_id = $xoopsModule->getVar('mid');
787
        }
788
        $criteria = new CriteriaCompo();
789
        $criteria->add(new Criteria('not_modid', (int)$module_id));
790
        $criteria->add(new Criteria('not_category', $this->db->escape($category)));
791
        $criteria->add(new Criteria('not_itemid', (int)$item_id));
792
        $criteria->add(new Criteria('not_uid', (int)$user_id));
793
        if (!is_array($events)) {
794
            $events = array($events);
795
        }
796
        $event_criteria = new CriteriaCompo();
797
        foreach ($events as $event) {
798
            $event_criteria->add(new Criteria('not_event', $this->db->escape($event)), 'OR');
799
        }
800
        $criteria->add($event_criteria);
801
802
        return $this->deleteAll($criteria);
803
    }
804
805
    // TODO: When 'update' a module, may need to switch around some
806
    //  notification classes/IDs...  or delete the ones that no longer
807
    //  exist.
808
    /**
809
     * Delete all notifications for a particular module
810
     *
811
     * @param  int $module_id ID of the module
812
     * @return bool
813
     **/
814
    public function unsubscribeByModule($module_id)
815
    {
816
        $criteria = new Criteria('not_modid', (int)$module_id);
817
818
        return $this->deleteAll($criteria);
819
    }
820
821
    /**
822
     * Delete all subscriptions for a particular item.
823
     *
824
     * @param int    $module_id ID of the module to which item belongs
825
     * @param string $category  Notification category of the item
826
     * @param int    $item_id   ID of the item
827
     *
828
     * @return bool
829
     **/
830
    public function unsubscribeByItem($module_id, $category, $item_id)
831
    {
832
        $criteria = new CriteriaCompo();
833
        $criteria->add(new Criteria('not_modid', (int)$module_id));
834
        $criteria->add(new Criteria('not_category', $this->db->escape($category)));
835
        $criteria->add(new Criteria('not_itemid', (int)$item_id));
836
837
        return $this->deleteAll($criteria);
838
    }
839
840
    /**
841
     * Perform notification maintenance activites at login time.
842
     * In particular, any notifications for the newly logged-in
843
     * user with mode XOOPS_NOTIFICATION_MODE_WAITFORLOGIN are
844
     * switched to mode XOOPS_NOTIFICATION_MODE_SENDONCETHENWAIT.
845
     *
846
     * @param int $user_id ID of the user being logged in
847
     **/
848
    public function doLoginMaintenance($user_id)
849
    {
850
        $criteria = new CriteriaCompo();
851
        $criteria->add(new Criteria('not_uid', (int)$user_id));
852
        $criteria->add(new Criteria('not_mode', XOOPS_NOTIFICATION_MODE_WAITFORLOGIN));
853
854
        $notifications = $this->getObjects($criteria, true);
855
        foreach ($notifications as $n) {
856
            $n->setVar('not_mode', XOOPS_NOTIFICATION_MODE_SENDONCETHENWAIT);
857
            $this->insert($n);
858
        }
859
    }
860
861
    /**
862
     * Update
863
     *
864
     * @param XoopsNotification $notification {@link XoopsNotification} object
865
     * @param string            $field_name   Name of the field
866
     * @param mixed             $field_value  Value to write
867
     *
868
     * @return bool
869
     **/
870
    public function updateByField(XoopsNotification $notification, $field_name, $field_value)
871
    {
872
        $notification->unsetNew();
873
        $notification->setVar($field_name, $field_value);
874
875
        return $this->insert($notification);
876
    }
877
}
878