activity.php 27.4 KB
Newer Older
1
2
<?php
/**
Francois Marier's avatar
Francois Marier committed
3
 * Mahara: Electronic portfolio, weblog, resume builder and social networking
4
 * Copyright (C) 2006-2008 Catalyst IT Ltd (http://www.catalyst.net.nz)
5
 *
Francois Marier's avatar
Francois Marier committed
6
7
8
9
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
10
 *
Francois Marier's avatar
Francois Marier committed
11
12
13
14
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
15
 *
Francois Marier's avatar
Francois Marier committed
16
17
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18
19
20
 *
 * @package    mahara
 * @subpackage core
21
 * @author     Catalyst IT Ltd
22
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL
23
 * @copyright  (C) 2006-2008 Catalyst IT Ltd http://catalyst.net.nz
24
25
26
27
28
29
30
31
32
33
34
35
 *
 */

defined('INTERNAL') || die();

/**
 * This is the function to call whenever anything happens
 * that is going to end up on a user's activity page.
 * 
 * @param string $activitytype type of activity
 * @param mixed $data data 
 */
36
37
function activity_occurred($activitytype, $data, $plugintype=null, $pluginname=null) {
    $at = activity_locate_typerecord($activitytype, $plugintype, $pluginname);
38
39
    if (!empty($at->delay)) {
        $delayed = new StdClass;
40
        $delayed->type = $at->id;
41
42
43
44
45
        $delayed->data = serialize($data);
        $delayed->ctime = db_format_timestamp(time());
        insert_record('activity_queue', $delayed);
    }
    else {
46
        handle_activity($at, $data);
47
    }
48
49
50
51
52
53
54
55
56
}

/** 
 * This function dispatches all the activity stuff
 * to whatever notification plugin it needs to
 * and figures out all the implications of 
 * activity and who needs to know about it.
 * 
 * @param object $activitytype record from activity_type
57
58
59
 * @param mixed $data must contain message to save.
 * it can also contain url.
 * each activity type has different requirements of $data - 
60
61
62
63
64
65
66
 *  - <b>contactus</b> must contain $message, $subject (optional), $fromname, $fromaddress, $userfrom (if a logged in user)
 *  - <b>objectionable</b> must contain $message, $view and $artefact if applicable
 *  - <b>maharamessage</b> must contain $users, an array of userids. $subject and $message (contents of message)
 *  - <b>usermessage</b> must contain $userto, id of recipient user, $userfrom, id of user from 
    -       and $subject and $message (contents of message)
 *  - <b>feedback (artefact)</b> must contain both $artefact (id) and $view (id) and $message 
 *  - <b>feedback (view)</b> must contain $view (id) and $message
67
 *  - <b>watchlist (view) </b> must contain $view (id of view) as $message
68
 *  - <b>viewaccess</b> must contain $owner userid of view owner AND $view (id of view) and $oldusers array of userids before access change was committed.
69
 */
70
function handle_activity($activitytype, $data, $cron=false) {
71
    $data = (object)$data;
72
    $activitytype = activity_locate_typerecord($activitytype);
73

74
75
76
77
78
79
80
    $classname = 'ActivityType' . ucfirst($activitytype->name);
    if (!empty($activitytype->plugintype)) {
        safe_require($activitytype->plugintype, $activitytype->pluginname);
        $classname = 'ActivityType' . 
            ucfirst($activitytype->plugintype) . 
            ucfirst($activitytype->pluginname) . 
            ucfirst($activitytype->name);
81
    }
82

83
    $activity = new $classname($data, $cron);
84
    if (!$activity->any_users()) {
85
86
        return;
    }
87

88
    $activity->notify_users();
89
90
91
}

/**
92
93
 * this function returns an array of users who subsribe to a particular activitytype 
 * including the notification method they are using to subscribe to it.
94
 *
95
 * @param int $activitytype the id of the activity type
96
97
98
 * @param array $userids an array of userids to filter by
 * @param array $userobjs an array of user objects to filterby
 * @param bool $adminonly whether to filter by admin flag
99
 * @param array $admininstitutions list of institution names to get admins for
100
101
 * @return array of users
 */
102
103
function activity_get_users($activitytype, $userids=null, $userobjs=null, $adminonly=false,
                            $admininstitutions = array()) {
104
    $values = array($activitytype);
105
106
    $sql = '
        SELECT
107
108
            u.id, u.username, u.firstname, u.lastname, u.preferredname, u.email, u.admin, u.staff, 
            p.method, ap.value AS lang
109
110
111
112
113
114
        FROM {usr} u
        LEFT JOIN {usr_activity_preference} p
            ON p.usr = u.id ' . (empty($admininstitutions) ? '' : '
        LEFT OUTER JOIN {usr_institution} ui
            ON (u.id = ui.usr
                AND ui.institution IN ('.join(',',array_map('db_quote',$admininstitutions)).'))') . '
115
116
        LEFT OUTER JOIN {usr_account_preference} ap
            ON (ap.usr = u.id AND ap.field = \'lang\')
117
        WHERE (p.activity = ? ' . ($adminonly ? '' : ' OR p.activity IS NULL') . ')';
118
119
120
121
122
123
124
125
    if (!empty($userobjs) && is_array($userobjs)) {
        $sql .= ' AND u.id IN (' . implode(',',db_array_to_ph($userobjs)) . ')';
        $values = array_merge($values, array_to_fields($userobjs));
    } 
    else if (!empty($userids) && is_array($userids)) {
        $sql .= ' AND u.id IN (' . implode(',',db_array_to_ph($userids)) . ')';
        $values = array_merge($values, $userids);
    }
126
127
128
    if (!empty($admininstitutions)) {
        $sql .= '
        GROUP BY
129
130
            u.id, u.username, u.firstname, u.lastname, u.preferredname, u.email, u.admin, u.staff,
            p.method, ap.value
131
132
133
134
        HAVING (u.admin = 1 OR SUM(ui.admin) > 0)';
    } else if ($adminonly) {
        $sql .= ' AND u.admin = 1';
    }
135
    return get_records_sql_array($sql, $values);
136
137
}

138
139
140
141
142
143
/**
 * this function inserts a default set of activity preferences for a given user
 * id
 */
function activity_set_defaults($user_id) {
    $activitytypes = get_records_array('activity_type', 'admin', 0);
144
145
    $haveemail = in_array('email', array_map(create_function('$a', 'return $a->name;'),
                                             plugins_installed('notification')));
146
    foreach ($activitytypes as $type) {
147
        if ($haveemail) {
148
            $method = 'email';
149
150
        }
        else {
151
152
            $method = 'internal';
        }
153
154
        insert_record('usr_activity_preference', (object)array(
            'usr' => $user_id,
Richard Mansfield's avatar
Richard Mansfield committed
155
            'activity' => $type->id,
156
            'method' => $method,
157
        ));
158
159
160
161
    }
    
}

162
163
164
165
function activity_add_admin_defaults($userids) {
    $activitytypes = get_records_array('activity_type', 'admin', 1);
    foreach ($activitytypes as $type) {
        foreach ($userids as $id) {
166
            if (!record_exists('usr_activity_preference', 'usr', $id, 'activity', $type->id)) {
167
168
                insert_record('usr_activity_preference', (object)array(
                    'usr' => $id,
169
                    'activity' => $type->id,
170
171
172
173
174
175
176
177
                    'method' => 'internal',
                ));
            }
        }
    }
}


178
179
function activity_process_queue() {

180
    db_begin();
181
    if ($toprocess = get_records_array('activity_queue')) {
182
183
184
        // Hack to avoid duplicate watchlist notifications on the same view
        $watchlist = activity_locate_typerecord('watchlist');
        $viewsnotified = array();
185
        foreach ($toprocess as $activity) {
186
187
188
189
190
191
192
            $data = unserialize($activity->data);
            if ($activity->type == $watchlist->id && !empty($data->view)) {
                if (isset($viewsnotified[$data->view])) {
                    continue;
                }
                $viewsnotified[$data->view] = true;
            }
193
194
195
196
197
198
199
200
            try {
                handle_activity($activity->type, $data, true);
            }
            catch (MaharaException $e) {
                // Exceptions can happen while processing the queue, we just 
                // log them and continue
                log_debug($e->getMessage());
            }
201
202
203
204
205
        }
        delete_records('activity_queue');
    }
    db_commit();
}
206

207
function activity_get_viewaccess_users($view, $owner, $type) {
208
    $type = activity_locate_typerecord($type);
209
    $sql = "SELECT userid, u.*, p.method, ap.value AS lang
210
211
                FROM (
                SELECT (CASE WHEN usr1 = ? THEN usr2 ELSE usr1 END) AS userid 
212
213
214
                    FROM {usr_friend} f
                    JOIN {view} v ON (v.owner = f.usr1 OR v.owner = f.usr2)
                    JOIN {view_access} vu ON vu.view = v.id
215
                        WHERE (usr1 = ? OR usr2 = ?) AND vu.accesstype = ? AND v.id = ? 
216
                UNION SELECT usr AS userid 
217
                    FROM {view_access_usr} u 
218
                        WHERE u.view = ?
219
                UNION SELECT m.member 
220
                    FROM {group_member} m
221
222
223
                    JOIN {view_access_group} vg ON vg.group = m.group
                    JOIN {group} g ON (g.id = vg.group AND g.deleted = 0)
                        WHERE vg.view = ? AND (vg.tutoronly = ? OR m.tutor = ?)
224
225
226
                UNION SELECT g.owner
                    FROM {group} g
                    JOIN {view_access_group} ag ON ag.group = g.id
227
                        WHERE ag.view = ? AND g.deleted = 0
228
                ) AS userlist
229
                JOIN {usr} u ON u.id = userlist.userid
230
231
                LEFT JOIN {usr_activity_preference} p ON p.usr = u.id AND p.activity = ?
                LEFT JOIN {usr_account_preference} ap ON ap.usr = u.id AND ap.field = 'lang'";
232
    $values = array($owner, $owner, $owner, 'friends', $view, $view, $view, 0, 1, $view, $type->id);
233
    if (!$u = get_records_sql_assoc($sql, $values)) {
234
235
236
        $u = array();
    }
    return $u;
237
238
}

239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
function activity_locate_typerecord($activitytype, $plugintype=null, $pluginname=null) {
    if (is_object($activitytype)) {
        return $activitytype;
    }
    if (is_numeric($activitytype)) {
        $at = get_record('activity_type', 'id', $activitytype);
    }
    else {
        if (empty($plugintype) && empty($pluginname)) {
            $at = get_record_select('activity_type', 
                'name = ? AND plugintype IS NULL AND pluginname IS NULL', 
                array($activitytype));
        } 
        else {
            $at = get_record('activity_type', 'name', $activitytype, 'plugintype', $plugintype, 'pluginname', $pluginname);
        }
    }
    if (empty($at)) {
        throw new Exception("Invalid activity type $activitytype");
    }
    return $at;
}
261
262
263
264
265
266
267
268

/** activity type classes **/
abstract class ActivityType {
    
    protected $subject;
    protected $message;
    protected $users = array();
    protected $url;
269
    protected $id;
270
271
    protected $type;
    protected $activityname;
272
    protected $cron;
273
274
275
276
277
278
279
280
   
    public function get_id() {
        if (!isset($this->id)) {
            $tmp = activity_locate_typerecord($this->get_type());
            $this->id = $tmp->id;
        }
        return $this->id;
    }
281
282
283
284
285
286
287
288
289
290
291
292
293
294
    
    public function get_type() {
        $prefix = 'ActivityType';
        return strtolower(substr(get_class($this), strlen($prefix)));
    }

    public function any_users() {
        return (is_array($this->users) && count($this->users) > 0);
    }

    public function get_users() {
        return $this->users;
    }

295
296
    public function __construct($data, $cron=false) {
        $this->cron = $cron;
297
298
        $this->set_parameters($data);
        $this->ensure_parameters();
299
        $this->activityname = strtolower(substr(get_class($this), strlen('ActivityType')));
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
    }

    private function set_parameters($data) {
        foreach ($data as $key => $value) {
            if (property_exists($this, $key)) {
                $this->{$key} = $value;
            }
        }   
    }

    private function ensure_parameters() {
        foreach ($this->get_required_parameters() as $param) {
            if (!isset($this->{$param})) {
                throw new ParamOutOfRangeException(get_string('missingparam', 'activity', $param, $this->get_type()));
            }
        }
    }

    public function to_stdclass() {
       return (object)get_object_vars($this); 
    }
321
322
323
324

    public function get_message($user) {
        return $this->message;
    }
325
        
326
327
328
    public function get_subject($user) {
        return $this->subject;
    }
329
330

    abstract function get_required_parameters();
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354

    public function notify_user($user) {
        $userdata = $this->to_stdclass();
        // some stuff gets overridden by user specific stuff
        if (!empty($user->url)) {
            $userdata->url = $user->url;
        }
        if (empty($user->lang) || $user->lang == 'default') {
            $user->lang = get_config('lang');
        }
        $userdata->message = $this->get_message($user);
        $userdata->subject = $this->get_subject($user);
        if (empty($user->method)) {
            $user->method = 'internal';
        }
        if ($user->method != 'internal') {
            $method = $user->method;
            safe_require('notification', $method, 'lib.php', 'require_once');
            try {
                call_static_method(generate_class_name('notification', $method), 'notify_user', $user, $userdata);
                $user->markasread = true; // if we're doing something else, don't generate unread internal ones.
            }
            catch (Exception $e) {
                $user->markasread = false; // if we fail (eg email falls over), don't mark it as read...
355
                // @todo Catalyst IT Ltd
356
357
358
359
360
361
362
363
364
365
366
367
368
369
            }
        }
        // always do internal
        call_static_method('PluginNotificationInternal', 'notify_user', $user, $userdata);
    }

    public function notify_users() {
        safe_require('notification', 'internal', 'lib.php', 'require_once');
        $this->type = $this->get_id();

        foreach ($this->get_users() as $user) {
            $this->notify_user($user);
        }
    }
370
371
372
373
374
}


abstract class ActivityTypeAdmin extends ActivityType { 

375
376
    public function __construct($data, $cron=false) {
        parent::__construct($data, $cron);
377
        $this->users = activity_get_users($this->get_id(), null, null, true);
378
379
380
381
382
383
384
385
386
    }
}

class ActivityTypeContactus extends ActivityTypeAdmin {
    
    protected $fromname;
    protected $fromemail;
    protected $userfrom;

387
388
    function __construct($data, $cron=false) { 
        parent::__construct($data, $cron);
389
390
391
392
        if (!empty($this->userfrom)) {
            $this->url = get_config('wwwroot') . 'user/view.php?id=' . $this->userfrom;
        }
    }
393
394
395
396
397
398
399
400
401
402
403

    function get_subject($user) {
        return get_string_from_language($user->lang, 'newcontactus', 'activity');
    }

    function get_message($user) {
        return get_string_from_language($user->lang, 'newcontactusfrom', 'activity') . ' ' . $this->fromname 
            . '<' . $this->fromemail .'>' . (isset($this->subject) ? ': ' . $this->subject : '')
            . "\n\n" . $this->message;
    }

404
405
406
407
408
409
410
411
412
    public function get_required_parameters() {
        return array('message', 'fromname', 'fromemail');
    }
}

class ActivityTypeObjectionable extends ActivityTypeAdmin {

    protected $view;
    protected $artefact;
413
    protected $reporter;
414

415
416
    function __construct($data, $cron=false) { 
        parent::__construct($data, $cron);
417
418
419
420
421
422
423
424
425
        if (empty($this->artefact)) {
            $this->url = get_config('wwwroot') . 'view/view.php?id=' . $this->view;
        }
        else {
            $this->url = get_config('wwwroot') . 'view/artefact.php?artefact=' . $this->artefact . '&view=' . $this->view;
        }
    }

    function get_subject($user) {
426
427
428
429
        if (!$viewtitle = get_field('view', 'title', 'id', $this->view)) {
            throw new ViewNotFoundException(get_string('viewnotfound', 'error', $this->view));
        }
        if (empty($this->artefact)) {
430
431
            return get_string_from_language($user->lang, 'objectionablecontentview', 'activity',
                                            $viewtitle, display_name($this->reporter, $user));
432
433
434
435
436
        }
        else {
            if (!$artefacttitle = get_field('artefact', 'title', 'id', $this->artefact)) {
                throw new ArtefactNotFoundException(get_string('artefactnotfound', 'error', $this->artefact));
            }
437
438
            return get_string_from_language($user->lang, 'objectionablecontentartefact', 'activity',
                                            $artefacttitle, display_name($this->reporter, $user));
439
440
441
442
        }
    }

    public function get_required_parameters() {
443
        return array('message', 'view', 'reporter');
444
445
446
447
448
449
450
451
452
453
    }

}

class ActivityTypeVirusRepeat extends ActivityTypeAdmin {

    protected $username;
    protected $fullname;
    protected $userid;

454
455
    public function __construct($data, $cron=false) { 
        parent::__construct($data, $cron);
456
457
458
    }

    public function get_subject($user) {
459
        $userstring = $this->username . ' (' . $this->fullname . ') (userid:' . $this->userid . ')' ;
460
461
462
463
464
        return get_string_from_language($user->lang, 'virusrepeatsubject', 'mahara', $userstring);
    }

    public function get_message($user) {
        return get_string_from_language($user->lang, 'virusrepeatmessage');
465
466
467
468
469
470
471
472
473
    }

    public function get_required_parameters() {
        return array('username', 'fullname', 'userid');
    }
}

class ActivityTypeVirusRelease extends ActivityTypeAdmin {

474
475
    public function __construct($data, $cron=false) { 
        parent::__construct($data, $cron);
476
477
478
479
480
481
482
483
484
    }

    public function get_required_parameters() {
        return array();
    }
}

class ActivityTypeMaharamessage extends ActivityType {

485
486
    public function __construct($data, $cron=false) { 
        parent::__construct($data, $cron);
487
        $this->users = activity_get_users($this->get_id(), $this->users);
488
489
490
491
492
493
494
    }

    public function get_required_parameters() {
        return array('message', 'subject', 'users');
    }
}

495
496
497
498
499
500
501
class ActivityTypeInstitutionmessage extends ActivityType {

    protected $messagetype;
    protected $institution;
    protected $username;
    protected $fullname;

502
503
    public function __construct($data, $cron=false) {
        parent::__construct($data, $cron);
504
505
506
507
508
        if ($this->messagetype == 'request') {
            $this->url = get_config('wwwroot') . 'admin/users/institutionusers.php';
            $this->users = activity_get_users($this->get_id(), null, null, null,
                                              array($this->institution->name));
        } else if ($this->messagetype == 'invite') {
509
            $this->url = get_config('wwwroot') . 'account/institutions.php';
510
511
512
513
            $this->users = activity_get_users($this->get_id(), $this->users);
        }
    }

514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
    public function get_subject($user) {
        if ($this->messagetype == 'request') {
            $userstring = $this->fullname . ' (' . $this->username . ')';
            return get_string_from_language($user->lang, 'institutionrequestsubject', 'activity', $userstring, 
                                            $this->institution->displayname);
        } else if ($this->messagetype == 'invite') {
            return get_string_from_language($user->lang, 'institutioninvitesubject', 'activity', 
                                            $this->institution->displayname);
        }
    }

    public function get_message($user) {
        if ($this->messagetype == 'request') {
            return get_string_from_language($user->lang, 'institutionrequestmessage', 'activity');
        } else if ($this->messagetype == 'invite') {
            return get_string_from_language($user->lang, 'institutioninvitemessage', 'activity');
        }
    }

533
534
535
536
537
    public function get_required_parameters() {
        return array('messagetype', 'institution');
    }
}

538
539
540
541
542
class ActivityTypeUsermessage extends ActivityType { 

    protected $userto;
    protected $userfrom;

543
544
    public function __construct($data, $cron=false) { 
        parent::__construct($data, $cron);
545
        $this->users = activity_get_users($this->get_id(), array($this->userto));
546
547
548
549
550
        if (empty($this->url)) {
            $this->url = get_config('wwwroot') . 'user/view.php?id=' . $this->userfrom;
        }
    } 

551
552
    public function get_subject($user) {
        if (empty($this->subject)) {
Clare Lenihan's avatar
Clare Lenihan committed
553
            return get_string_from_language($user->lang, 'newusermessage', 'group',
554
555
556
557
558
                                            display_name($this->userfrom));
        }
        return $this->subject;
    }

559
560
561
562
563
564
565
566
567
568
569
    public function get_required_parameters() {
        return array('message', 'userto', 'userfrom');
    }
    
}

class ActivityTypeFeedback extends ActivityType { 

    protected $view;
    protected $artefact;

570
571
572
    private $viewrecord;
    private $artefactinstance;

573
574
    public function __construct($data, $cron=false) { 
        parent::__construct($data, $cron);
575

576
        if (!empty($this->artefact)) { // feedback on artefact
577
            $userid = null;
578
579
580
581
            require_once(get_config('docroot') . 'artefact/lib.php');
            $this->artefactinstance = artefact_instance_from_id($this->artefact);
            if ($this->artefactinstance->feedback_notify_owner()) {
                $userid = $this->artefactinstance->get('owner');
582
583
            }
            if (empty($this->url)) {
584
585
                $this->url = get_config('wwwroot') . 'view/artefact.php?artefact=' 
                    . $this->artefact . '&view=' . $this->view;
586
587
588
            }
        } 
        else { // feedback on view.
589
            if (!$this->viewrecord = get_record('view', 'id', $this->view)) {
590
591
                throw new ViewNotFoundException(get_string('viewnotfound', 'error', $this->view));
            }
592
            $userid = $this->viewrecord->owner;
593
594
595
596
597
            if (empty($this->url)) {
                $this->url = get_config('wwwroot') . 'view/view.php?id=' . $this->view;
            }
        }
        if ($userid) {
598
            $this->users = activity_get_users($this->get_id(), array($userid));
599
600
601
        } 
    }

602
603
604
605
606
607
608
609
610
611
612
    public function get_subject($user) {
        if (!empty($this->artefact)) { // feedback on artefact
            return get_string_from_language($user->lang, 'newfeedbackonartefact', 'activity')
                . ' ' . $this->artefactinstance->get('title');
        }
        else {
            return get_string_from_language($user->lang, 'newfeedbackonview', 'activity')
                . ' ' . $this->viewrecord->title;
        }
    }

613
614
615
616
617
618
619
620
621
    public function get_required_parameters() {
        return array('message', 'view');
    }
}

class ActivityTypeWatchlist extends ActivityType { 

    protected $view;

622
623
    private $viewinfo;

624
625
    public function __construct($data, $cron) { 
        parent::__construct($data, $cron); 
626
627
        //$oldsubject = $this->subject;
        if (!$this->viewinfo = get_record_sql('SELECT u.*, v.title FROM {usr} u
628
629
                                         JOIN {view} v ON v.owner = u.id
                                         WHERE v.id = ?', array($this->view))) {
630
            if (!empty($this->cron)) { // probably deleted already
631
632
633
634
                return;
            }
            throw new ViewNotFoundException(get_string('viewnotfound', 'error', $this->view));
        }
635
636
637
638
639
        // mysql compatibility (sigh...)
        $casturl = 'CAST(? AS TEXT)';
        if (get_config('dbtype') == 'mysql') {
            $casturl = 'CAST(? AS CHAR)'; // note, NOT varchar
        }
640
        $sql = 'SELECT u.*, p.method, ap.value AS lang, ' . $casturl . ' AS url
641
642
643
644
645
                    FROM {usr_watchlist_view} wv
                    JOIN {usr} u
                        ON wv.usr = u.id
                    LEFT JOIN {usr_activity_preference} p
                        ON p.usr = u.id
646
647
                    LEFT OUTER JOIN {usr_account_preference} ap
                        ON (ap.usr = u.id AND ap.field = \'lang\')
648
649
650
651
652
                    WHERE (p.activity = ? OR p.activity IS NULL)
                    AND wv.view = ?
               ';
        $this->users = get_records_sql_array($sql, 
                                       array(get_config('wwwroot') . 'view/view.php?id=' 
653
                                             . $this->view, $this->get_id(), $this->view));
654
655
656
657
658
659
660
    }

    public function get_subject($user) {
        return get_string_from_language($user->lang, 'newwatchlistmessage', 'activity');
    }

    public function get_message($user) {
661
662
        return get_string_from_language($user->lang, 'newwatchlistmessageview', 'activity', 
                                        display_name($this->viewinfo, $user), $this->viewinfo->title);
663
664
665
    }

    public function get_required_parameters() {
666
        return array('view');
667
668
669
670
671
672
673
674
    }
}

class ActivityTypeNewview extends ActivityType { 

    protected $owner;
    protected $view;

675
676
    private $viewinfo;

677
678
    public function __construct($data, $cron=false) { 
        parent::__construct($data, $cron);
679
        if (!$this->viewinfo = get_record_sql('SELECT u.*, v.title FROM {usr} u
680
681
                                         JOIN {view} v ON v.owner = u.id
                                         WHERE v.id = ?', array($this->view))) {
682
            if (!empty($this->cron)) { //probably deleted already
683
684
685
686
687
688
689
690
                return;
            }
            throw new ViewNotFoundException(get_string('viewnotfound', 'error', $this->view));
        }

        $this->url = get_config('wwwroot') . 'view/view.php?id=' . $this->view;

        // add users on friendslist or userlist...
691
        $this->users = activity_get_viewaccess_users($this->view, $this->owner, $this->get_id()); 
692
693
694
695
696
697
698
    }

    public function get_subject($user) {
        return get_string_from_language($user->lang, 'newviewsubject', 'activity');
    }
    
    public function get_message($user) {
699
700
        return get_string_from_language($user->lang, 'newviewmessage', 'activity', 
                                        display_name($this->viewinfo, $user), $this->viewinfo->title);
701
702
703
704
705
706
707
708
709
710
711
712
713
    }
    
    public function get_required_parameters() {
        return array('owner', 'view');
    }
}

class ActivityTypeViewaccess extends ActivityType { 

    protected $view;
    protected $owner;
    protected $oldusers; // this can be empty though

714
715
    private $viewinfo;

716
717
    public function __construct($data, $cron=false) { 
        parent::__construct($data, $cron);
718
        if (!$this->viewinfo = get_record_sql('SELECT u.*, v.title FROM {usr} u
719
720
                                         JOIN {view} v ON v.owner = u.id
                                         WHERE v.id = ?', array($this->view))) {
721
            if (!empty($this->cron)) { // probably deleted already
722
723
724
725
726
727
                return;
            }
            throw new ViewNotFoundException(get_string('viewnotfound', 'error', $this->view));
        }
        $this->url = get_config('wwwroot') . 'view/view.php?id=' . $this->view;
        $this->users = array_diff_key(
728
            activity_get_viewaccess_users($this->view, $this->owner, $this->get_id()),
729
730
            $this->oldusers
        );
731
    }
732

733
734
735
736
737
    public function get_subject($user) {
        return get_string('newviewaccesssubject', 'activity');
    }
    
    public function get_message($user) {
738
739
        return get_string_from_language($user->lang, 'newviewaccessmessage', 'activity',
                                        $this->viewinfo->title, display_name($this->viewinfo, $user));
740
741
    }
    
742
743
744
745
746
    public function get_required_parameters() {
        return array('view', 'owner', 'oldusers');
    }
}

747
748
749
750
751
752
abstract class ActivityTypePlugin extends ActivityType {

    abstract public function get_plugintype();

    abstract public function get_pluginname();

753
754
755
756
757
    public function get_type() {
        $prefix = 'ActivityType' . $this->get_plugintype() . $this->get_pluginname();
        return strtolower(substr(get_class($this), strlen($prefix)));
    }

758
759
760
761
762
763
764
765
766
    public function get_id() {
        if (!isset($this->id)) {
            $tmp = activity_locate_typerecord($this->get_type(), $this->get_plugintype(), $this->get_pluginname());
            $this->id = $tmp->id;
        }
        return $this->id;
    }
}

767
?>