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 <mvandam@caltech.edu>
17 * @author              Kazumi Ono (AKA onokazu) http://www.myweb.ne.jp/, http://jp.xoops.org/
18 */
19defined('XOOPS_ROOT_PATH') || exit('Restricted access');
20
21// RMV-NOTIFY
22include_once $GLOBALS['xoops']->path('include/notification_constants.php');
23include_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    <mvandam@caltech.edu>
32 * @copyright       (c) 2000-2016 XOOPS Project (www.xoops.org)
33 */
34class 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 XoopsMemberHandler $member_handler */
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 XoopsConfigHandler $config_handler */
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 <mvandam@caltech.edu>
224 * @copyright       (c) 2000-2016 XOOPS Project (www.xoops.org)
225 */
226class 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)) {
259                return $notification;
260            }
261            $numrows = $this->db->getRowsNum($result);
262            if ($numrows == 1) {
263                $notification = new XoopsNotification();
264                $notification->assignVars($this->db->fetchArray($result));
265            }
266        }
267
268        return $notification;
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');
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);
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);
298        }
299        if (!$result = $this->db->query($sql)) {
300            return false;
301        }
302        if (empty($not_id)) {
303            $not_id = $this->db->getInsertId();
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'));
325        if (!$result = $this->db->query($sql)) {
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();
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);
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)) {
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)));
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  XoopsNotification $notification */
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
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)) {
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);
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 XoopsModuleHandler $module_handler */
647            $module_handler = xoops_getHandler('module');
648            $module         = $module_handler->get($module_id);
649        }
650
651        // Check if event is enabled
652        /* @var XoopsConfigHandler $config_handler */
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'])) {
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