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 (https://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: */
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 <mvandam@caltech.edu>
32: * @copyright (c) 2000-2016 XOOPS Project (www.xoops.org)
33: */
34: class XoopsNotification extends XoopsObject
35: {
36: //PHP 8.2 Dynamic properties deprecated
37: public $not_id;
38: public $not_modid;
39: public $not_category;
40: public $not_itemid;
41: public $not_event;
42: public $not_uid;
43: public $not_mode;
44:
45: /**
46: * Constructor
47: **/
48: public function __construct()
49: {
50: parent::__construct();
51: $this->initVar('not_id', XOBJ_DTYPE_INT, null, false);
52: $this->initVar('not_modid', XOBJ_DTYPE_INT, null, false);
53: $this->initVar('not_category', XOBJ_DTYPE_TXTBOX, null, false, 30);
54: $this->initVar('not_itemid', XOBJ_DTYPE_INT, 0, false);
55: $this->initVar('not_event', XOBJ_DTYPE_TXTBOX, null, false, 30);
56: $this->initVar('not_uid', XOBJ_DTYPE_INT, 0, true);
57: $this->initVar('not_mode', XOBJ_DTYPE_INT, 0, false);
58: }
59:
60: // FIXME:???
61: // To send email to multiple users simultaneously, we would need to move
62: // the notify functionality to the handler class. BUT, some of the tags
63: // are user-dependent, so every email msg will be unique. (Unless maybe use
64: // smarty for email templates in the future.) Also we would have to keep
65: // track if each user wanted email or PM.
66:
67: /**
68: * Returns Class Base Variable not_id
69: * @param string $format
70: * @return mixed
71: */
72: public function id($format = 'N')
73: {
74: return $this->getVar('not_id', $format);
75: }
76:
77: /**
78: * Returns Class Base Variable not_id
79: * @param string $format
80: * @return mixed
81: */
82: public function not_id($format = '')
83: {
84: return $this->getVar('not_id', $format);
85: }
86:
87: /**
88: * Returns Class Base Variable not_modid
89: * @param string $format
90: * @return mixed
91: */
92: public function not_modid($format = '')
93: {
94: return $this->getVar('not_modid', $format);
95: }
96:
97: /**
98: * Returns Class Base Variable mid
99: * @param string $format
100: * @return mixed
101: */
102: public function not_category($format = '')
103: {
104: return $this->getVar('not_category', $format);
105: }
106:
107: /**
108: * Returns Class Base Variable not_itemid
109: * @param string $format
110: * @return mixed
111: */
112: public function not_itemid($format = '')
113: {
114: return $this->getVar('not_itemid', $format);
115: }
116:
117: /**
118: * Returns Class Base Variable not_event
119: * @param string $format
120: * @return mixed
121: */
122: public function not_event($format = '')
123: {
124: return $this->getVar('not_event', $format);
125: }
126:
127: /**
128: * Returns Class Base Variable not_uid
129: * @param string $format
130: * @return mixed
131: */
132: public function not_uid($format = '')
133: {
134: return $this->getVar('not_uid', $format);
135: }
136:
137: /**
138: * Returns Class Base Variable not_mode
139: * @param string $format
140: * @return mixed
141: */
142: public function not_mode($format = '')
143: {
144: return $this->getVar('not_mode', $format);
145: }
146:
147: /**
148: * Send a notification message to the user
149: *
150: * @param string $template_dir Template directory
151: * @param string $template Template name
152: * @param string $subject Subject line for notification message
153: * @param array $tags Array of substitutions for template variables
154: *
155: * @return bool true if success, false if error
156: **/
157: public function notifyUser($template_dir, $template, $subject, $tags)
158: {
159: // Check the user's notification preference.
160: /** @var XoopsMemberHandler $member_handler */
161: $member_handler = xoops_getHandler('member');
162: $user = $member_handler->getUser($this->getVar('not_uid'));
163: if (!is_object($user) || !$user->isActive()) {
164: return true;
165: }
166:
167: $method = $user->getVar('notify_method');
168:
169: $xoopsMailer = xoops_getMailer();
170: include_once $GLOBALS['xoops']->path('include/notification_constants.php');
171: switch ($method) {
172: case XOOPS_NOTIFICATION_METHOD_PM:
173: $xoopsMailer->usePM();
174: /** @var XoopsConfigHandler $config_handler */
175: $config_handler = xoops_getHandler('config');
176: $xoopsMailerConfig = $config_handler->getConfigsByCat(XOOPS_CONF_MAILER);
177: $xoopsMailer->setFromUser($member_handler->getUser($xoopsMailerConfig['fromuid']));
178: foreach ($tags as $k => $v) {
179: $xoopsMailer->assign($k, $v);
180: }
181: break;
182: case XOOPS_NOTIFICATION_METHOD_EMAIL:
183: $xoopsMailer->useMail();
184: foreach ($tags as $k => $v) {
185: $xoopsMailer->assign($k, preg_replace('/&amp;/i', '&', $v));
186: }
187: break;
188: default:
189: return true; // report error in user's profile??
190: // break;
191: }
192:
193: // Set up the mailer
194: $xoopsMailer->setTemplateDir($template_dir);
195: $xoopsMailer->setTemplate($template);
196: $xoopsMailer->setToUsers($user);
197: //global $xoopsConfig;
198: //$xoopsMailer->setFromEmail($xoopsConfig['adminmail']);
199: //$xoopsMailer->setFromName($xoopsConfig['sitename']);
200: $xoopsMailer->setSubject($subject);
201: $success = $xoopsMailer->send();
202:
203: // If send-once-then-delete, delete notification
204: // If send-once-then-wait, disable notification
205: include_once $GLOBALS['xoops']->path('include/notification_constants.php');
206: $notification_handler = xoops_getHandler('notification');
207:
208: if ($this->getVar('not_mode') == XOOPS_NOTIFICATION_MODE_SENDONCETHENDELETE) {
209: $notification_handler->delete($this);
210:
211: return $success;
212: }
213:
214: if ($this->getVar('not_mode') == XOOPS_NOTIFICATION_MODE_SENDONCETHENWAIT) {
215: $this->setVar('not_mode', XOOPS_NOTIFICATION_MODE_WAITFORLOGIN);
216: $notification_handler->insert($this);
217: }
218:
219: return $success;
220: }
221: }
222:
223: /**
224: * XOOPS notification handler class.
225: *
226: * This class is responsible for providing data access mechanisms to the data source
227: * of XOOPS notification class objects.
228: *
229: *
230: * @package kernel
231: * @subpackage notification
232: *
233: * @author Michael van Dam <mvandam@caltech.edu>
234: * @copyright (c) 2000-2016 XOOPS Project (www.xoops.org)
235: */
236: class XoopsNotificationHandler extends XoopsObjectHandler
237: {
238: /**
239: * Create a {@link XoopsNotification}
240: *
241: * @param bool $isNew Flag the object as "new"?
242: *
243: * @return XoopsNotification
244: */
245: public function create($isNew = true)
246: {
247: $notification = new XoopsNotification();
248: if ($isNew) {
249: $notification->setNew();
250: }
251:
252: return $notification;
253: }
254:
255: /**
256: * Retrieve a {@link XoopsNotification}
257: *
258: * @param int $id ID
259: *
260: * @return XoopsNotification|false {@link XoopsNotification}, false on fail
261: **/
262: public function get($id)
263: {
264: $notification = false;
265: $id = (int)$id;
266: if ($id > 0) {
267: $sql = 'SELECT * FROM ' . $this->db->prefix('xoopsnotifications') . ' WHERE not_id=' . $id;
268: $result = $this->db->query($sql);
269: if (!$this->db->isResultSet($result)) {
270: return $notification;
271: }
272: $numrows = $this->db->getRowsNum($result);
273: if ($numrows == 1) {
274: $notification = new XoopsNotification();
275: $notification->assignVars($this->db->fetchArray($result));
276: }
277: }
278:
279: return $notification;
280: }
281:
282: /**
283: * Write a notification(subscription) to database
284: *
285: * @param XoopsObject|XoopsNotification $notification a XoopsNotification object
286: *
287: * @return bool true on success, otherwise false
288: **/
289: public function insert(XoopsObject $notification)
290: {
291: $className = 'XoopsNotification';
292: if (!($notification instanceof $className)) {
293: return false;
294: }
295: if (!$notification->isDirty()) {
296: return true;
297: }
298: if (!$notification->cleanVars()) {
299: return false;
300: }
301: foreach ($notification->cleanVars as $k => $v) {
302: ${$k} = $v;
303: }
304: if ($notification->isNew()) {
305: $not_id = $this->db->genId('xoopsnotifications_not_id_seq');
306: $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);
307: } else {
308: $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);
309: }
310: if (!$result = $this->db->query($sql)) {
311: return false;
312: }
313: if (empty($not_id)) {
314: $not_id = $this->db->getInsertId();
315: }
316: $notification->assignVar('not_id', $not_id);
317:
318: return true;
319: }
320:
321: /**
322: * Delete a {@link XoopsNotification} from the database
323: *
324: * @param XoopsObject|XoopsNotification $notification a XoopsNotification object
325: *
326: * @return bool true on success, otherwise false
327: **/
328: public function delete(XoopsObject $notification)
329: {
330: $className = 'XoopsNotification';
331: if (!($notification instanceof $className)) {
332: return false;
333: }
334:
335: $sql = sprintf('DELETE FROM %s WHERE not_id = %u', $this->db->prefix('xoopsnotifications'), $notification->getVar('not_id'));
336: if (!$result = $this->db->query($sql)) {
337: return false;
338: }
339:
340: return true;
341: }
342:
343: /**
344: * Get some {@link XoopsNotification}s
345: *
346: * @param CriteriaElement|CriteriaCompo $criteria
347: * @param bool $id_as_key Use IDs as keys into the array?
348: *
349: * @return array Array of {@link XoopsNotification} objects
350: **/
351: public function getObjects(CriteriaElement $criteria = null, $id_as_key = false)
352: {
353: $ret = array();
354: $limit = $start = 0;
355: $sql = 'SELECT * FROM ' . $this->db->prefix('xoopsnotifications');
356: if (isset($criteria) && \method_exists($criteria, 'renderWhere')) {
357: $sql .= ' ' . $criteria->renderWhere();
358: $sort = ($criteria->getSort() != '') ? $criteria->getSort() : 'not_id';
359: $sql .= ' ORDER BY ' . $sort . ' ' . $criteria->getOrder();
360: $limit = $criteria->getLimit();
361: $start = $criteria->getStart();
362: }
363: $result = $this->db->query($sql, $limit, $start);
364: if (!$this->db->isResultSet($result)) {
365: return $ret;
366: }
367: /** @var array $myrow */
368: while (false !== ($myrow = $this->db->fetchArray($result))) {
369: $notification = new XoopsNotification();
370: $notification->assignVars($myrow);
371: if (!$id_as_key) {
372: $ret[] = $notification;
373: } else {
374: $ret[$myrow['not_id']] = $notification;
375: }
376: unset($notification);
377: }
378:
379: return $ret;
380: }
381:
382: // TODO: Need this??
383: /**
384: * Count Notifications
385: *
386: * @param CriteriaElement|CriteriaCompo $criteria {@link CriteriaElement}
387: *
388: * @return int Count
389: **/
390: public function getCount(CriteriaElement $criteria = null)
391: {
392: $sql = 'SELECT COUNT(*) FROM ' . $this->db->prefix('xoopsnotifications');
393: if (isset($criteria) && \method_exists($criteria, 'renderWhere')) {
394: $sql .= ' ' . $criteria->renderWhere();
395: }
396: $result = $this->db->query($sql);
397: if (!$this->db->isResultSet($result)) {
398: return 0;
399: }
400: list($count) = $this->db->fetchRow($result);
401:
402: return (int)$count;
403: }
404:
405: /**
406: * Delete multiple notifications
407: *
408: * @param CriteriaElement|CriteriaCompo $criteria {@link CriteriaElement}
409: *
410: * @return bool
411: **/
412: public function deleteAll(CriteriaElement $criteria = null)
413: {
414: $sql = 'DELETE FROM ' . $this->db->prefix('xoopsnotifications');
415: if (isset($criteria) && \method_exists($criteria, 'renderWhere')) {
416: $sql .= ' ' . $criteria->renderWhere();
417: }
418: if (!$result = $this->db->query($sql)) {
419: return false;
420: }
421:
422: return true;
423: }
424:
425: // TODO: rename this...
426: // Also, should we have get by module, get by category, etc...??
427: /**
428: * @param $module_id
429: * @param $category
430: * @param $item_id
431: * @param $event
432: * @param $user_id
433: *
434: * @return bool
435: */
436: public function &getNotification($module_id, $category, $item_id, $event, $user_id)
437: {
438: $criteria = new CriteriaCompo();
439: $criteria->add(new Criteria('not_modid', (int)$module_id));
440: $criteria->add(new Criteria('not_category', $this->db->escape($category)));
441: $criteria->add(new Criteria('not_itemid', (int)$item_id));
442: $criteria->add(new Criteria('not_event', $this->db->escape($event)));
443: $criteria->add(new Criteria('not_uid', (int)$user_id));
444: $objects = $this->getObjects($criteria);
445: if (count($objects) == 1) {
446: return $objects[0];
447: }
448: $inst = false;
449:
450: return $inst;
451: }
452:
453: /**
454: * Determine if a user is subscribed to a particular event in
455: * a particular module.
456: *
457: * @param string $category Category of notification event
458: * @param int $item_id Item ID of notification event
459: * @param string $event Event
460: * @param int $module_id ID of module (default current module)
461: * @param int $user_id ID of user (default current user)
462: * return int 0 if not subscribe; non-zero if subscribed
463: *
464: * @return int
465: */
466: public function isSubscribed($category, $item_id, $event, $module_id, $user_id)
467: {
468: $criteria = new CriteriaCompo();
469: $criteria->add(new Criteria('not_modid', (int)$module_id));
470: $criteria->add(new Criteria('not_category', $this->db->escape($category)));
471: $criteria->add(new Criteria('not_itemid', (int)$item_id));
472: $criteria->add(new Criteria('not_event', $this->db->escape($event)));
473: $criteria->add(new Criteria('not_uid', (int)$user_id));
474:
475: return $this->getCount($criteria);
476: }
477:
478: // TODO: how about a function to subscribe a whole group of users???
479: // e.g. if we want to add all moderators to be notified of subscription
480: // of new threads...
481: /**
482: * Subscribe for notification for an event(s)
483: *
484: * @param string $category category of notification
485: * @param int $item_id ID of the item
486: * @param mixed $events event string or array of events
487: * @param int $mode force a particular notification mode
488: * (e.g. once_only) (default to current user preference)
489: * @param int $module_id ID of the module (default to current module)
490: * @param int $user_id ID of the user (default to current user)
491: * *
492: *
493: * @return bool
494: */
495: public function subscribe($category, $item_id, $events, $mode = null, $module_id = null, $user_id = null)
496: {
497: if (!isset($user_id)) {
498: global $xoopsUser;
499: if (empty($xoopsUser)) {
500: return false; // anonymous cannot subscribe
501: } else {
502: $user_id = $xoopsUser->getVar('uid');
503: }
504: }
505:
506: if (!isset($module_id)) {
507: global $xoopsModule;
508: $module_id = $xoopsModule->getVar('mid');
509: }
510:
511: if (!isset($mode)) {
512: $user = new XoopsUser($user_id);
513: $mode = $user->getVar('notify_mode');
514: }
515:
516: if (!is_array($events)) {
517: $events = array($events);
518: }
519: foreach ($events as $event) {
520: /** @var XoopsNotification $notification */
521: if ($notification = $this->getNotification($module_id, $category, $item_id, $event, $user_id)) {
522: if ($notification->getVar('not_mode') != $mode) {
523: $this->updateByField($notification, 'not_mode', $mode);
524: }
525: } else {
526: $notification = $this->create();
527: $notification->setVar('not_modid', $module_id);
528: $notification->setVar('not_category', $category);
529: $notification->setVar('not_itemid', $item_id);
530: $notification->setVar('not_uid', $user_id);
531: $notification->setVar('not_event', $event);
532: $notification->setVar('not_mode', $mode);
533: $this->insert($notification);
534: }
535: }
536: return true;
537: }
538:
539: // TODO: this will be to provide a list of everything a particular
540: // user has subscribed to... e.g. for on the 'Profile' page, similar
541: // to how we see the various posts etc. that the user has made.
542: // We may also want to have a function where we can specify module id
543: /**
544: * Get a list of notifications by user ID
545: *
546: * @param int $user_id ID of the user
547: *
548: * @return array Array of {@link XoopsNotification} objects
549: **/
550: public function getByUser($user_id)
551: {
552: $criteria = new Criteria('not_uid', $user_id);
553:
554: return $this->getObjects($criteria, true);
555: }
556:
557: // TODO: rename this??
558: /**
559: * Get a list of notification events for the current item/mod/user
560: *
561: * @param $category
562: * @param $item_id
563: * @param $module_id
564: * @param $user_id
565: * @return array
566: */
567: public function getSubscribedEvents($category, $item_id, $module_id, $user_id)
568: {
569: $criteria = new CriteriaCompo();
570: $criteria->add(new Criteria('not_modid', (int)$module_id));
571: $criteria->add(new Criteria('not_category', $this->db->escape($category)));
572: if ($item_id) {
573: $criteria->add(new Criteria('not_itemid', (int)$item_id));
574: }
575: $criteria->add(new Criteria('not_uid', (int)$user_id));
576: $results = $this->getObjects($criteria, true);
577: $ret = array();
578: foreach (array_keys($results) as $i) {
579: $ret[] = $results[$i]->getVar('not_event');
580: }
581:
582: return $ret;
583: }
584:
585: // TODO: is this a useful function?? (Copied from comment_handler)
586: /**
587: * Retrieve items by their ID
588: *
589: * @param int $module_id Module ID
590: * @param int $item_id Item ID
591: * @param string $order Sort order
592: * @param int $mode not_mode see include/notification_constants.php
593: *
594: * @param null $status
595: *
596: * @return array Array of {@link XoopsNotification} objects
597: */
598: public function getByItemId($module_id, $item_id, $order = null, $mode = null)
599: {
600: $criteria = new CriteriaCompo(new Criteria('not_modid', (int)$module_id));
601: $criteria->add(new Criteria('not_itemid', (int)$item_id));
602: if (isset($mode)) {
603: $criteria->add(new Criteria('not_mode', (int)$mode));
604: }
605: if (isset($order)) {
606: $criteria->setOrder($order);
607: }
608:
609: return $this->getObjects($criteria);
610: }
611:
612: /**
613: * Send notifications to users
614: *
615: * @param string $category notification category
616: * @param int $item_id ID of the item
617: * @param array $events trigger events
618: * @param array $extra_tags array of substitutions for template to be
619: * merged with the one from function.
620: * @param array $user_list only notify the selected users
621: * @param int $module_id ID of the module
622: * @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.
623: * @internal param string $event notification event
624: */
625: // TODO:(?) - pass in an event LIST. This will help to avoid
626: // problem of sending people multiple emails for similar events.
627: // BUT, then we need an array of mail templates, etc... Unless
628: // mail templates can include logic in the future, then we can
629: // tailor the mail so it makes sense for any of the possible
630: // (or combination of) events.
631: public function triggerEvents($category, $item_id, $events, $extra_tags = array(), $user_list = array(), $module_id = null, $omit_user_id = null)
632: {
633: if (!is_array($events)) {
634: $events = array($events);
635: }
636: foreach ($events as $event) {
637: $this->triggerEvent($category, $item_id, $event, $extra_tags, $user_list, $module_id, $omit_user_id);
638: }
639: }
640:
641: /**
642: * Trigger a single notification event
643: *
644: * @param string $category
645: * @param int $item_id
646: * @param string $event
647: * @param array $extra_tags
648: * @param array $user_list
649: * @param int $module_id
650: * @param int $omit_user_id
651: * @return mixed
652: */
653: public function triggerEvent($category, $item_id, $event, $extra_tags = array(), $user_list = array(), $module_id = null, $omit_user_id = null)
654: {
655: if (!isset($module_id)) {
656: global $xoopsModule;
657: $module = $xoopsModule;
658: $module_id = !empty($xoopsModule) ? $xoopsModule->getVar('mid') : 0;
659: } else {
660: /** @var XoopsModuleHandler $module_handler */
661: $module_handler = xoops_getHandler('module');
662: $module = $module_handler->get($module_id);
663: }
664:
665: // Check if event is enabled
666: /** @var XoopsConfigHandler $config_handler */
667: $config_handler = xoops_getHandler('config');
668: $mod_config = $config_handler->getConfigsByCat(0, $module->getVar('mid'));
669: if (empty($mod_config['notification_enabled'])) {
670: return false;
671: }
672: $category_info =& notificationCategoryInfo($category, $module_id);
673: $event_info =& notificationEventInfo($category, $event, $module_id);
674: if (!in_array(notificationGenerateConfig($category_info, $event_info, 'option_name'), $mod_config['notification_events']) && empty($event_info['invisible'])) {
675: return false;
676: }
677:
678: if (!isset($omit_user_id)) {
679: global $xoopsUser;
680: $omit_user_id = 0;
681: if (!empty($xoopsUser)) {
682: $omit_user_id = $xoopsUser->getVar('uid');
683: }
684: }
685: $criteria = new CriteriaCompo();
686: $criteria->add(new Criteria('not_modid', (int)$module_id));
687: $criteria->add(new Criteria('not_category', $this->db->escape($category)));
688: $criteria->add(new Criteria('not_itemid', (int)$item_id));
689: $criteria->add(new Criteria('not_event', $this->db->escape($event)));
690: $mode_criteria = new CriteriaCompo();
691: $mode_criteria->add(new Criteria('not_mode', XOOPS_NOTIFICATION_MODE_SENDALWAYS), 'OR');
692: $mode_criteria->add(new Criteria('not_mode', XOOPS_NOTIFICATION_MODE_SENDONCETHENDELETE), 'OR');
693: $mode_criteria->add(new Criteria('not_mode', XOOPS_NOTIFICATION_MODE_SENDONCETHENWAIT), 'OR');
694: $criteria->add($mode_criteria);
695: if (!empty($user_list)) {
696: $user_criteria = new CriteriaCompo();
697: foreach ($user_list as $user) {
698: $user_criteria->add(new Criteria('not_uid', (int)$user), 'OR');
699: }
700: $criteria->add($user_criteria);
701: }
702: $notifications = $this->getObjects($criteria);
703: if (empty($notifications)) {
704: return null;
705: }
706:
707: // Add some tag substitutions here
708:
709: $not_config = $module->getInfo('notification');
710: $tags = array();
711: if (!empty($not_config)) {
712: if (!empty($not_config['tags_file'])) {
713: $tags_file = $GLOBALS['xoops']->path('modules/' . $module->getVar('dirname') . '/' . $not_config['tags_file']);
714: if (file_exists($tags_file)) {
715: include_once $tags_file;
716: if (!empty($not_config['tags_func'])) {
717: $tags_func = $not_config['tags_func'];
718: if (function_exists($tags_func)) {
719: $tags = $tags_func($category, (int)$item_id, $event);
720: }
721: }
722: }
723: }
724: // RMV-NEW
725: if (!empty($not_config['lookup_file'])) {
726: $lookup_file = $GLOBALS['xoops']->path('modules/' . $module->getVar('dirname') . '/' . $not_config['lookup_file']);
727: if (file_exists($lookup_file)) {
728: include_once $lookup_file;
729: if (!empty($not_config['lookup_func'])) {
730: $lookup_func = $not_config['lookup_func'];
731: if (function_exists($lookup_func)) {
732: $item_info = $lookup_func($category, (int)$item_id);
733: }
734: }
735: }
736: }
737: }
738: $tags['X_ITEM_NAME'] = !empty($item_info['name']) ? $item_info['name'] : '[' . _NOT_ITEMNAMENOTAVAILABLE . ']';
739: $tags['X_ITEM_URL'] = !empty($item_info['url']) ? $item_info['url'] : '[' . _NOT_ITEMURLNOTAVAILABLE . ']';
740: $tags['X_ITEM_TYPE'] = !empty($category_info['item_name']) ? $category_info['title'] : '[' . _NOT_ITEMTYPENOTAVAILABLE . ']';
741: $tags['X_MODULE'] = $module->getVar('name');
742: $tags['X_MODULE_URL'] = XOOPS_URL . '/modules/' . $module->getVar('dirname') . '/';
743: $tags['X_NOTIFY_CATEGORY'] = $category;
744: $tags['X_NOTIFY_EVENT'] = $event;
745:
746: $template_dir = $event_info['mail_template_dir'];
747: $template = $event_info['mail_template'] . '.tpl';
748: $subject = $event_info['mail_subject'];
749:
750: $merged_tags = array();
751:
752: // First loop: Merge tags only, don't notify
753: foreach ($notifications as $notification) {
754: if (empty($omit_user_id) || $notification->getVar('not_uid') != $omit_user_id) {
755: // user-specific tags
756: $tags = array();
757: $tags['X_UNSUBSCRIBE_URL'] = XOOPS_URL . '/notifications.php';
758:
759: // Check if the $tags array is not empty
760: if (!empty($tags)) {
761: // Merge tags into the merged_tags array
762: $merged_tags = array_merge($merged_tags, $tags);
763: }
764: }
765: }
766:
767: // Second loop: Notify users with the merged tags
768: foreach ($notifications as $notification) {
769: if (empty($omit_user_id) || $notification->getVar('not_uid') != $omit_user_id) {
770: $notification->notifyUser($template_dir, $template, $subject, $merged_tags);
771: }
772: }
773:
774: return null;
775: }
776:
777: /**
778: * Delete all notifications for one user
779: *
780: * @param int $user_id ID of the user
781: * @return bool
782: **/
783: public function unsubscribeByUser($user_id)
784: {
785: $criteria = new Criteria('not_uid', (int)$user_id);
786:
787: return $this->deleteAll($criteria);
788: }
789:
790: // TODO: allow these to use current module, etc...
791: /**
792: * Unsubscribe notifications for an event(s).
793: *
794: * @param string $category category of the events
795: * @param int $item_id ID of the item
796: * @param mixed $events event string or array of events
797: * @param int $module_id ID of the module (default current module)
798: * @param int $user_id UID of the user (default current user)
799: *
800: * @return bool
801: **/
802: public function unsubscribe($category, $item_id, $events, $module_id = null, $user_id = null)
803: {
804: if (!isset($user_id)) {
805: global $xoopsUser;
806: if (empty($xoopsUser)) {
807: return false; // anonymous cannot subscribe
808: } else {
809: $user_id = $xoopsUser->getVar('uid');
810: }
811: }
812: if (!isset($module_id)) {
813: global $xoopsModule;
814: $module_id = $xoopsModule->getVar('mid');
815: }
816: $criteria = new CriteriaCompo();
817: $criteria->add(new Criteria('not_modid', (int)$module_id));
818: $criteria->add(new Criteria('not_category', $this->db->escape($category)));
819: $criteria->add(new Criteria('not_itemid', (int)$item_id));
820: $criteria->add(new Criteria('not_uid', (int)$user_id));
821: if (!is_array($events)) {
822: $events = array($events);
823: }
824: $event_criteria = new CriteriaCompo();
825: foreach ($events as $event) {
826: $event_criteria->add(new Criteria('not_event', $this->db->escape($event)), 'OR');
827: }
828: $criteria->add($event_criteria);
829:
830: return $this->deleteAll($criteria);
831: }
832:
833: // TODO: When 'update' a module, may need to switch around some
834: // notification classes/IDs... or delete the ones that no longer
835: // exist.
836: /**
837: * Delete all notifications for a particular module
838: *
839: * @param int $module_id ID of the module
840: * @return bool
841: **/
842: public function unsubscribeByModule($module_id)
843: {
844: $criteria = new Criteria('not_modid', (int)$module_id);
845:
846: return $this->deleteAll($criteria);
847: }
848:
849: /**
850: * Delete all subscriptions for a particular item.
851: *
852: * @param int $module_id ID of the module to which item belongs
853: * @param string $category Notification category of the item
854: * @param int $item_id ID of the item
855: *
856: * @return bool
857: **/
858: public function unsubscribeByItem($module_id, $category, $item_id)
859: {
860: $criteria = new CriteriaCompo();
861: $criteria->add(new Criteria('not_modid', (int)$module_id));
862: $criteria->add(new Criteria('not_category', $this->db->escape($category)));
863: $criteria->add(new Criteria('not_itemid', (int)$item_id));
864:
865: return $this->deleteAll($criteria);
866: }
867:
868: /**
869: * Perform notification maintenance activites at login time.
870: * In particular, any notifications for the newly logged-in
871: * user with mode XOOPS_NOTIFICATION_MODE_WAITFORLOGIN are
872: * switched to mode XOOPS_NOTIFICATION_MODE_SENDONCETHENWAIT.
873: *
874: * @param int $user_id ID of the user being logged in
875: **/
876: public function doLoginMaintenance($user_id)
877: {
878: $criteria = new CriteriaCompo();
879: $criteria->add(new Criteria('not_uid', (int)$user_id));
880: $criteria->add(new Criteria('not_mode', XOOPS_NOTIFICATION_MODE_WAITFORLOGIN));
881:
882: $notifications = $this->getObjects($criteria, true);
883: foreach ($notifications as $n) {
884: $n->setVar('not_mode', XOOPS_NOTIFICATION_MODE_SENDONCETHENWAIT);
885: $this->insert($n);
886: }
887: }
888:
889: /**
890: * Update
891: *
892: * @param XoopsNotification $notification {@link XoopsNotification} object
893: * @param string $field_name Name of the field
894: * @param mixed $field_value Value to write
895: *
896: * @return bool
897: **/
898: public function updateByField(XoopsNotification $notification, $field_name, $field_value)
899: {
900: $notification->unsetNew();
901: $notification->setVar($field_name, $field_value);
902:
903: return $this->insert($notification);
904: }
905: }
906: