lib.php 48.2 KB
Newer Older
1
2
3
4
<?php
/**
 *
 * @package    mahara
Penny Leach's avatar
Penny Leach committed
5
 * @subpackage artefact-internal
6
 * @author     Catalyst IT Ltd
7
8
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL version 3 or later
 * @copyright  For copyright information on Mahara, please see the README file distributed with this software.
9
10
11
12
 *
 */

defined('INTERNAL') || die();
13
14
15
if (file_exists(get_config('docroot') . 'local/lib/artefact_internal.php')) {
    include_once(get_config('docroot') . 'local/lib/artefact_internal.php');
}
16
17
18
19

class PluginArtefactInternal extends PluginArtefact {

    public static function get_artefact_types() {
20
        $types = array(
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
            'firstname',
            'lastname',
            'studentid',
            'preferredname',
            'introduction',
            'email',
            'officialwebsite',
            'personalwebsite',
            'blogaddress',
            'address',
            'town',
            'city',
            'country',
            'homenumber',
            'businessnumber',
            'mobilenumber',
            'faxnumber',
            'occupation',
            'industry',
            'html',
41
            'socialprofile',
42
        );
43
44
45
46
47
        if (class_exists('PluginArtefactInternalLocal', false)) {
            $localtypes = PluginArtefactInternalLocal::get_artefact_types();
            $types = array_merge($types, $localtypes);
        }
        return $types;
48
49
50
    }

    public static function get_profile_artefact_types() {
51
        $types = array(
52
53
54
55
56
            'firstname',
            'lastname',
            'studentid',
            'preferredname',
            'introduction',
Martyn Smith's avatar
Martyn Smith committed
57
            'email',
58
59
            'officialwebsite',
            'personalwebsite',
60
            'blogaddress',
Martyn Smith's avatar
Martyn Smith committed
61
            'address',
62
            'town',
Martyn Smith's avatar
Martyn Smith committed
63
            'city',
64
            'country',
Martyn Smith's avatar
Martyn Smith committed
65
66
67
            'homenumber',
            'businessnumber',
            'mobilenumber',
68
69
70
            'faxnumber',
            'occupation',
            'industry',
71
            'socialprofile',
72
        );
73
74
75
76
77
        if (class_exists('PluginArtefactInternalLocal', false)) {
            $localtypes = PluginArtefactInternalLocal::get_profile_artefact_types();
            $types = array_merge($types, $localtypes);
        }
        return $types;
78
    }
79
80

    public static function get_contactinfo_artefact_types() {
81
        $types = array(
82
83
84
85
86
87
88
89
90
91
92
93
            'email',
            'officialwebsite',
            'personalwebsite',
            'blogaddress',
            'address',
            'town',
            'city',
            'country',
            'homenumber',
            'businessnumber',
            'mobilenumber',
            'faxnumber',
94
            'socialprofile',
95
        );
96
97
98
99
100
        if (class_exists('PluginArtefactInternalLocal', false)) {
            $localtypes = PluginArtefactInternalLocal::get_contactinfo_artefact_types();
            $types = array_merge($types, $localtypes);
        }
        return $types;
101
    }
Aaron Wells's avatar
Aaron Wells committed
102

103
104
105
    public static function get_block_types() {
        return array();
    }
106
107
108
109
110

    public static function get_plugin_name() {
        return 'internal';
    }

111
112
113
114
    public static function is_active() {
        return get_field('artefact_installed', 'active', 'name', 'internal');
    }

115
    public static function right_nav_menu_items() {
116
        return array(
117
118
            'profile' => array(
                'path' => 'profile',
119
                'url' => 'artefact/internal/index.php',
120
                'title' => get_string('profile', 'artefact.internal'),
121
                'weight' => 10,
122
                'iconclass' => 'id-card-o',
123
            ),
124
125
126
127
128
129
130
        );
    }

    public static function menu_items() {
        return array(
            'create/notes' => array(
                'path' => 'create/notes',
131
132
                'url' => 'artefact/internal/notes.php',
                'title' => get_string('Notes', 'artefact.internal'),
133
                'weight' => 40,
134
            ),
135
136
        );
    }
137

138
139
    public static function submenu_items() {
        $tabs = array(
140
141
142
            'subnav' => array(
                'class' => 'profile'
            ),
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
            'profile' => array(
                'page'  => 'profile',
                'url'   => 'artefact/internal/index.php',
                'title' => get_string('aboutme', 'artefact.internal'),
            ),
            'contact' => array(
                'page'  => 'contact',
                'url'   => 'artefact/internal/index.php?fs=contact',
                'title' => get_string('contact', 'artefact.internal'),
            ),
            'social' => array(
                'page'  => 'social',
                'url'   => 'artefact/internal/index.php?fs=social',
                'title' => get_string('social', 'artefact.internal'),
            ),
            'general' => array(
                'page'  => 'general',
                'url'   => 'artefact/internal/index.php?fs=general',
                'title' => get_string('general'),
            ),
        );
        if (!get_field('artefact_installed_type', 'name', 'name', 'socialprofile')) {
            unset($tabs['social']);
        }
        if (defined('INTERNAL_SUBPAGE') && isset($tabs[INTERNAL_SUBPAGE])) {
            $tabs[INTERNAL_SUBPAGE]['selected'] = true;
        }
        return $tabs;
    }

173
174
175
176
177
178
179
180
181
182
183
184
185
186
    public static function get_cron() {
        return array(
            (object)array(
                'callfunction' => 'clean_email_validations',
                'hour'         => '4',
                'minute'       => '10',
            ),
        );
    }

    public static function clean_email_validations() {
        delete_records_select('artefact_internal_profile_email', 'verified=0 AND expiry IS NOT NULL AND expiry < ?', array(db_format_timestamp(time())));
    }

187
188
189
    public static function sort_child_data($a, $b) {
        return strnatcasecmp($a->text, $b->text);
    }
190
191
192
193

    public static function can_be_disabled() {
        return false;
    }
194
195
196

    public static function get_artefact_type_content_types() {
        return array(
197
198
199
            'introduction'  => array('text'),
            'html'          => array('text'),
            'socialprofile' => array('html'),
200
201
        );
    }
202
203
204
205
206
207

    /**
     * This method is provided by the plugin class so it can be used by the
     * profileinfo and contactinfo blocktypes. See the blocktypes'
     * export_blockinstance_config_leap method for more information.
     *
Francois Marier's avatar
Francois Marier committed
208
     * Leap2A export doesn't export profile related artefacts as entries, so we
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
     * need to take that into account when exporting config for it.
     *
     * @param BlockInstance $bi The blockinstance to export the config for.
     * @return array The config for the blockinstance
     */
    public static function export_blockinstance_config_leap(BlockInstance $bi) {
        static $cache = array();
        $owner = $bi->get_view()->get('owner');

        // This blocktype is only allowed in personal views
        if (!$owner) {
            return array();
        }

        if (!isset($cache[$owner])) {
            $cache[$owner] = get_records_sql_assoc("SELECT id, artefacttype, title
                FROM {artefact}
Francois Marier's avatar
Francois Marier committed
226
                WHERE \"owner\" = ?
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
                AND artefacttype IN (
                    SELECT name
                    FROM {artefact_installed_type}
                    WHERE plugin = 'internal'
            )", array($owner));
        }

        $configdata = $bi->get('configdata');

        $result = array();
        if (is_array($configdata)) {
            // Convert the actual profile artefact IDs to their field names
            if (isset($configdata['artefactids']) && is_array($configdata['artefactids'])) {
                $result['fields'] = array();
                foreach ($configdata['artefactids'] as $id) {
                    $result['fields'][] = $cache[$owner][$id]->artefacttype;
                }
244
                $result['fields'] = json_encode(array($result['fields']));
245
246
            }

Francois Marier's avatar
Francois Marier committed
247
            // Email addresses are not entries in Leap2A (they're elements on
248
249
250
            // the persondata element), so we export the actual address here
            // instead of an artefact ID.
            if (!empty($configdata['email']) && isset($cache[$owner][$configdata['email']])) {
251
                $result['email'] = json_encode(array($cache[$owner][$configdata['email']]->title));
252
253
254
            }

            if (!empty($configdata['profileicon'])) {
255
                $result['artefactid'] = json_encode(array(intval($configdata['profileicon'])));
256
257
258
            }

            if (isset($configdata['introtext'])) {
259
                $result['introtext'] = json_encode(array($configdata['introtext']));
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
            }
        }

        return $result;
    }

    /**
     * This method is provided by the plugin class so it can be used by the
     * profileinfo and contactinfo blocktypes. See the blocktypes'
     * import_create_blockinstance_leap method for more information.
     *
     * @param array $biconfig   The block instance config
     * @param array $viewconfig The view config
     * @return BlockInstance The newly made block instance
     */
    public static function import_create_blockinstance_leap(array $biconfig, array $viewconfig) {
        static $cache = array();
        $configdata = array();

        // This blocktype is only allowed in personal views
        if (empty($viewconfig['owner'])) {
            return;
        }
        $owner = $viewconfig['owner'];

        if (isset($biconfig['config']) && is_array($biconfig['config'])) {
            $impcfg = $biconfig['config'];
            if (isset($impcfg['fields']) && is_array($impcfg['fields'])) {
                // Convert the fields to their artefact ids
                $configdata['artefactids'] = array();
                foreach ($impcfg['fields'] as $field) {
                    if (!isset($cache[$owner])) {
                        $cache[$owner] = get_records_sql_assoc("SELECT artefacttype, id
                            FROM {artefact}
Francois Marier's avatar
Francois Marier committed
294
                            WHERE \"owner\" = ?
295
296
297
298
299
300
301
                            AND artefacttype IN (
                                SELECT name
                                FROM {artefact_installed_type}
                                WHERE plugin = 'internal'
                        )", array($owner));
                    }

302
303
304
                    if (isset($cache[$owner][$field])) {
                        $configdata['artefactids'][] = $cache[$owner][$field]->id;
                    }
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
                }
            }

            if (!empty($impcfg['email'])) {
                if ($artefactid = get_field('artefact_internal_profile_email', 'artefact', 'owner', $owner, 'email', $impcfg['email'])) {
                    $configdata['email'] = $artefactid;
                }
            }

            if (!empty($impcfg['artefactid'])) {
                $configdata['profileicon'] = intval($impcfg['artefactid']);
            }

            if (isset($impcfg['introtext'])) {
                $configdata['introtext'] = $impcfg['introtext'];
            }
        }
        $bi = new BlockInstance(0,
            array(
                'blocktype'  => $biconfig['type'],
                'configdata' => $configdata,
            )
        );

        return $bi;
    }
331
332

    public static function progressbar_additional_items() {
333
334
335
336
337
        return array(
                (object)array(
                    'name' => 'joingroup',
                    'title' => get_string('progressbaritem_joingroup', 'artefact.internal'),
                    'plugin' => 'internal',
338
                    'active' => get_field('artefact_installed', 'active', 'name', 'internal'),
339
340
341
342
343
344
345
                    'iscountable' => true,
                    'is_metaartefact' => true,
                ),
                (object)array(
                    'name' => 'makefriend',
                    'title' => get_string('progressbaritem_makefriend', 'artefact.internal'),
                    'plugin' => 'internal',
346
                    'active' => get_field('artefact_installed', 'active', 'name', 'internal'),
347
348
349
350
                    'iscountable' => true,
                    'is_metaartefact' => true,
                )
        );
351
352
    }

353
    public static function progressbar_metaartefact_count($name) {
354
355
        global $USER;

356
        $meta = new stdClass();
357
        $meta->artefacttype = $name;
358
        $meta->completed = 0;
359
        switch ($name) {
360
361
362
363
364
365
366
367
            case 'joingroup':
                $sql = "SELECT COUNT(*) AS completed
                         FROM {group_member}
                       WHERE member = ?";
                $count = get_records_sql_array($sql, array($USER->get('id')));
                $meta->completed = $count[0]->completed;
                break;
            case 'makefriend':
368
                // We count make friend as either initiating or accepting a friendship
369
370
                $sql = "SELECT COUNT(*) AS completed
                         FROM {usr_friend}
371
372
                       WHERE usr1 = ? OR usr2 = ?";
                $count = get_records_sql_array($sql, array($USER->get('id'), $USER->get('id')));
373
374
                $meta->completed = $count[0]->completed;
                break;
375
376
            default:
                return false;
377
378
379
380
381
382
        }
        return $meta;
    }

    public static function progressbar_link($artefacttype) {
        switch ($artefacttype) {
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
            case 'firstname':
            case 'lastname':
            case 'studentid':
            case 'preferredname':
            case 'introduction':
                return 'artefact/internal/index.php';
                break;
            case 'email':
            case 'officialwebsite':
            case 'personalwebsite':
            case 'blogaddress':
            case 'address':
            case 'town':
            case 'city':
            case 'country':
            case 'homenumber':
            case 'businessnumber':
            case 'mobilenumber':
            case 'faxnumber':
                return 'artefact/internal/index.php?fs=contact';
                break;
404
405
            case 'socialprofile':
                return 'artefact/internal/index.php?fs=social';
406
407
408
409
410
411
                break;
            case 'occupation':
            case 'industry':
                return 'artefact/internal/index.php?fs=general';
                break;
            case 'joingroup':
412
                return 'group/index.php?filter=notmember';
413
414
                break;
            case 'makefriend':
415
                return 'user/index.php';
416
417
418
                break;
            default:
                return 'view/index.php';
419
420
        }
    }
Penny Leach's avatar
Penny Leach committed
421
422
}

423
424
class ArtefactTypeProfile extends ArtefactType {

425
426
427
    /**
     * overriding this because profile fields
     * are unique in that except for email, you only get ONE
428
429
430
     * so if we don't get an id, we still need to go look for it.
     * On the other hand, if our caller knows the artefact is new,
     * we can skip the query.
431
     */
432
    public function __construct($id=0, $data=null, $new = FALSE) {
433
        $type = $this->get_artefact_type();
434
        if (!empty($id) || $type == 'email' || $type == 'socialprofile') {
435
436
437
            return parent::__construct($id, $data);
        }
        if (!empty($data['owner'])) {
438
            if (!$new && $a = get_record('artefact', 'artefacttype', $type, 'owner', $data['owner'])) {
439
                return parent::__construct($a->id, $a);
Aaron Wells's avatar
Aaron Wells committed
440
            }
Penny Leach's avatar
Penny Leach committed
441
442
            else {
                $this->owner = $data['owner'];
443
            }
Aaron Wells's avatar
Aaron Wells committed
444
        }
445
446
447
        $this->ctime = time();
        $this->atime = time();
        $this->artefacttype = $type;
448
449
450
451
452
453
454
455
456
457
458
459
        if (empty($id)) {
            $this->dirty = true;
            $this->ctime = $this->mtime = time();
            if (empty($data)) {
                $data = array();
            }
            foreach ((array)$data as $field => $value) {
                if (property_exists($this, $field)) {
                    $this->{$field} = $value;
                }
            }
        }
460
461
    }

462
463
464
465
466
467
468
    public function set($field, $value) {
        if ($field == 'title' && empty($value)) {
            return $this->delete();
        }
        return parent::set($field, $value);
    }

469
    public static function get_icon($options=null) {
470
471
472

    }

473
    public static function is_singular() {
Penny Leach's avatar
Penny Leach committed
474
475
        return true;
    }
Aaron Wells's avatar
Aaron Wells committed
476

Martyn Smith's avatar
Martyn Smith committed
477
    public static function get_all_fields() {
478
        $out = array(
Martyn Smith's avatar
Martyn Smith committed
479
480
481
482
483
484
485
486
            'firstname'       => 'text',
            'lastname'        => 'text',
            'studentid'       => 'text',
            'preferredname'   => 'text',
            'introduction'    => 'wysiwyg',
            'email'           => 'emaillist',
            'officialwebsite' => 'text',
            'personalwebsite' => 'text',
487
            'blogaddress'     => 'text',
Martyn Smith's avatar
Martyn Smith committed
488
489
490
491
492
493
494
495
496
497
            'address'         => 'textarea',
            'town'            => 'text',
            'city'            => 'text',
            'country'         => 'select',
            'homenumber'      => 'text',
            'businessnumber'  => 'text',
            'mobilenumber'    => 'text',
            'faxnumber'       => 'text',
            'occupation'      => 'text',
            'industry'        => 'text',
498
            'maildisabled'    => 'html',
Martyn Smith's avatar
Martyn Smith committed
499
        );
500
501
502
503
504
505
506
        $social = array();
        if (get_record('blocktype_installed', 'active', 1, 'name', 'socialprofile')) {
            $social = array(
                'socialprofile'   => 'html',
            );
        }
        $out = array_merge($out, $social);
507
508
509
510
        if (class_exists('ArtefactTypeProfileLocal', false)) {
            $localfields = ArtefactTypeProfileLocal::get_all_fields();
            $out = array_merge($out, $localfields);
        }
511
        return $out;
Martyn Smith's avatar
Martyn Smith committed
512
513
    }

514
    public static function get_field_element_data() {
515
        // we make sure the first/last/preferred names are safe as they get used in emails sent out
516
        return array(
517
518
            'firstname'       => array('rules' => array('maxlength' => 50, 'safetext' => true)),
            'lastname'        => array('rules' => array('maxlength' => 50, 'safetext' => true)),
519
            'studentid'       => array('rules' => array('maxlength' => 50)),
520
            'preferredname'   => array('rules' => array('maxlength' => 50, 'safetext' => true)),
521
522
523
        );
    }

524
    public static function get_mandatory_fields() {
525
526
527
528
529
530
531
532
533
        $m = array();
        $all = self::get_all_fields();
        $alwaysm = self::get_always_mandatory_fields();
        if ($man = get_config_plugin('artefact', 'internal', 'profilemandatory')) {
            $mandatory = explode(',', $man);
        }
        else {
            $mandatory = array();
        }
534
535
536
537
538
        // If socialprofile is disabled, we need to remove any fields that may
        // have been selected when it was enabled.
        // If socialprofile is enabled, we need to remove any fields that my
        // have been selected when it was disabled.
        $need_to_update = false;
539
        foreach ($mandatory as $mf) {
540
541
542
543
544
545
546
547
548
549
            if (isset($all[$mf])) {
                $m[$mf] = $all[$mf];
            }
            else {
                $need_to_update = true;
            }
        }
        if ($need_to_update) {
            // We need to save the config settings for the mandatory fields for the plugin.
            set_config_plugin('artefact', 'internal', 'profilemandatory', join(',', array_keys($m)));
550
551
552
553
        }
        return array_merge($m, $alwaysm);
    }

554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
    public static function get_adminusersearch_fields() {
        $m = array();
        $all = self::get_all_fields();
        $alwaysm = self::get_always_mandatory_fields();
        if ($man = get_config_plugin('artefact', 'internal', 'profileadminusersearch')) {
            $mandatory = explode(',', $man);
        }
        else {
            $mandatory = array();
        }
        // If socialprofile is disabled, we need to remove any fields that may
        // have been selected when it was enabled.
        // If socialprofile is enabled, we need to remove any fields that my
        // have been selected when it was disabled.
        $need_to_update = false;
        foreach ($mandatory as $mf) {
            if (isset($all[$mf])) {
                $m[$mf] = $all[$mf];
            }
            else {
                $need_to_update = true;
            }
        }
        if ($need_to_update) {
            // We need to save the config settings for the mandatory fields for the plugin.
            set_config_plugin('artefact', 'internal', 'profileadminusersearch', join(',', array_keys($m)));
        }
        return array_merge($m, $alwaysm);
    }

584
    public static function get_always_mandatory_fields() {
Martyn Smith's avatar
Martyn Smith committed
585
        return array(
Aaron Wells's avatar
Aaron Wells committed
586
587
            'firstname' => 'text',
            'lastname'  => 'text',
588
            'email'     => 'emaillist',
Martyn Smith's avatar
Martyn Smith committed
589
        );
590
    }
591

592
593
594
595
596
597
598
599
600
    public static function get_always_adminusersearchable_fields() {
        return array(
            'firstname'       => 'text',
            'lastname'        => 'text',
            'preferredname'   => 'text',
            'email'           => 'emaillist',
        );
    }

601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
    public static function get_all_searchable_fields() {
        return array(
            'firstname'       => 'text',
            'lastname'        => 'text',
            'studentid'       => 'text',
            'preferredname'   => 'text',
            'email'           => 'emaillist',
        );
    }

    public static function get_always_searchable_fields() {
        return array(
            'firstname'       => 'text',
            'lastname'        => 'text',
            'preferredname'   => 'text',
        );
    }

    public static function get_searchable_fields() {
        if ($pub = get_config_plugin('artefact', 'internal', 'profilepublic')) {
            $public = explode(',', $pub);
        }
        else {
            $public = array();
        }

        $all      = self::get_all_searchable_fields();
        $selected = self::get_always_searchable_fields();

630
631
632
633
634
        // If socialprofile is disabled, we need to remove any fields that may
        // have been selected when it was enabled.
        // If socialprofile is enabled, we need to remove any fields that my
        // have been selected when it was disabled.
        $need_to_update = false;
635
636
637
638
        foreach ($public as $pf) {
            if (isset($all[$pf])) {
                $selected[$pf] = $all[$pf];
            }
639
640
641
642
643
644
            else {
                $need_to_update = true;
            }
        }
        if ($need_to_update) {
            set_config_plugin('artefact', 'internal', 'profilepublic', join(',', array_keys($selected)));
645
646
647
648
649
        }

        return $selected;
    }

650
651
652
653
654
    public static function has_config() {
        return true;
    }

    public static function get_config_options() {
655
        $allmandatory    = self::get_all_fields();
656
        $alwaysmandatory = self::get_always_mandatory_fields();
657
        $mandatory       = self::get_mandatory_fields();
658

659
660
661
        $mandatoryfields = array();
        foreach (array_keys($allmandatory) as $field) {
            $mandatoryfields[$field] = array(
662
                'title'        => get_string($field, 'artefact.internal'),
663
664
665
                'value'        => $field,
                'defaultvalue' => isset($alwaysmandatory[$field]) || isset($mandatory[$field]),
                'disabled'     => isset($alwaysmandatory[$field]),
666
            );
667
668
669
670
671
        }

        $allsearchable    = self::get_all_searchable_fields();
        $alwayssearchable = self::get_always_searchable_fields();
        $searchable       = self::get_searchable_fields();
672

673
674
675
676
677
678
679
        $searchablefields = array();
        foreach (array_keys($allsearchable) as $field) {
            $searchablefields[$field] = array(
                'title'        => get_string($field, 'artefact.internal'),
                'value'        => $field,
                'defaultvalue' => isset($alwayssearchable[$field]) || isset($searchable[$field]),
                'disabled'     => isset($alwayssearchable[$field]),
680
681
            );
        }
682

683
684
685
686
687
688
689
690
691
692
693
694
        $adminusersearch = self::get_adminusersearch_fields();
        $alwaysadminusersearch = self::get_always_adminusersearchable_fields();
        $adminusersearchfields = array();
        foreach (array_keys($allmandatory) as $field) {
            $adminusersearchfields[$field] = array(
                'title'        => get_string($field, 'artefact.internal'),
                'value'        => $field,
                'defaultvalue' => isset($alwaysadminusersearch[$field]) || isset($adminusersearch[$field]),
                'disabled'     => isset($alwaysadminusersearch[$field]),
            );
        }

695
696
697
698
        $form = array(
            'elements'   => array(
                'mandatory' =>  array(
                    'title'        => get_string('mandatoryfields', 'artefact.internal'),
699
700
                    'description'  => get_string('mandatoryfieldsdescription', 'artefact.internal'),
                    'help'         => true,
701
                    'class'        => 'stacked',
702
703
704
705
706
707
708
                    'type'         => 'checkboxes',
                    'elements'     => $mandatoryfields,
                    'options'      => $allmandatory, // Only the keys are used by validateoptions
                    'rules'        => array('validateoptions' => true),
                ),
                'searchable' =>  array(
                    'title'        => get_string('searchablefields', 'artefact.internal'),
709
710
                    'description'  => get_string('searchablefieldsdescription', 'artefact.internal'),
                    'help'         => true,
711
                    'class'        => 'stacked',
712
713
714
715
716
                    'type'         => 'checkboxes',
                    'elements'     => $searchablefields,
                    'options'      => $allsearchable, // Only the keys are used by validateoptions
                    'rules'        => array('validateoptions' => true),
                ),
717
718
719
720
721
722
723
724
725
726
                'adminusersearch' => array(
                    'title'        => get_string('adminusersearchfields', 'artefact.internal'),
                    'description'  => get_string('adminusersearchfieldsdescription', 'artefact.internal'),
                    'help'         => true,
                    'class'        => 'stacked',
                    'type'         => 'checkboxes',
                    'elements'     => $adminusersearchfields,
                    'options'      => $allmandatory, // Only the keys are used by validateoptions
                    'rules'        => array('validateoptions' => true),
                ),
727
728
729
            ),
        );

730
731
732
        return $form;
    }

733
    public function save_config_options(Pieform $form, $values) {
734
735
736
737
        $mandatory = array_merge(array_keys(self::get_always_mandatory_fields()), $values['mandatory']);
        set_config_plugin('artefact', 'internal', 'profilemandatory', join(',', $mandatory));
        $searchable = array_merge(array_keys(self::get_always_searchable_fields()), $values['searchable']);
        set_config_plugin('artefact', 'internal', 'profilepublic', join(',', $searchable));
738
739
        $adminusersearch = array_merge(array_keys(self::get_always_adminusersearchable_fields()), $values['adminusersearch']);
        set_config_plugin('artefact', 'internal', 'profileadminusersearch', join(',', $adminusersearch));
740
    }
Martyn Smith's avatar
Martyn Smith committed
741
742
743
744
745

    public static function get_links($id) {
        $wwwroot = get_config('wwwroot');

        return array(
746
            '_default' => $wwwroot . 'artefact/internal/index.php',
Martyn Smith's avatar
Martyn Smith committed
747
748
        );
    }
749
750
751
752

    public function in_view_list() {
        return false;
    }
753

754
755
756
    public function display_title($maxlen=null) {
        return get_string($this->get('artefacttype'), 'artefact.internal');
    }
757
758
}

759
760
761
762
class ArtefactTypeProfileField extends ArtefactTypeProfile {
    public static function collapse_config() {
        return 'profile';
    }
763
764

    public function render_self($options) {
765
        return array('html' => hsc($this->title), 'javascript' => null);
766
    }
767
768
769
770

    /**
     * Render the import entry request for profile fields
     */
771
    public static function render_import_entry_request($entry_content, $renderfields=array()) {
772
773
        return clean_html($entry_content['title']);
    }
774
775
776
}

class ArtefactTypeCachedProfileField extends ArtefactTypeProfileField {
777

778
    public function commit() {
779
        global $USER;
780
        parent::commit();
781
        $field = $this->get_artefact_type();
782
783
        if (!$this->deleted) {
            set_field('usr', $field, $this->title, 'id', $this->owner);
784
785
786
        }
        if ($this->owner == $USER->get('id')) {
            $USER->{$field} = $this->title;
Nigel McNie's avatar
Nigel McNie committed
787
        }
788
789
790
    }

    public function delete() {
791
        parent::delete();
792
793
        $field = $this->get_artefact_type();
        set_field('usr', $field, null, 'id', $this->owner);
794
        $this->title = null;
795
796
797
798
    }

}

799
800
801
class ArtefactTypeFirstname extends ArtefactTypeCachedProfileField {}
class ArtefactTypeLastname extends ArtefactTypeCachedProfileField {}
class ArtefactTypePreferredname extends ArtefactTypeCachedProfileField {}
802
class ArtefactTypeEmail extends ArtefactTypeProfileField {
803
804
805
806
    public static function is_singular() {
        return false;
    }

807
808
    public function commit() {

809
        parent::commit();
810
811

        $email_record = get_record('artefact_internal_profile_email', 'owner', $this->owner, 'email', $this->title);
812

813
        if(!$email_record) {
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
            if (record_exists('artefact_internal_profile_email', 'owner', $this->owner, 'artefact', $this->id)) {
                update_record(
                    'artefact_internal_profile_email',
                    (object) array(
                        'email'     => $this->title,
                        'verified'  => 1,
                    ),
                    (object) array(
                        'owner'     => $this->owner,
                        'artefact'  => $this->id,
                    )
                );
                if (get_field('artefact_internal_profile_email', 'principal', 'owner', $this->owner, 'artefact', $this->id)) {
                    update_record('usr', (object) array( 'email' => $this->title, 'id' => $this->owner));
                }
            }
            else {
                $principal = get_record('artefact_internal_profile_email', 'owner', $this->owner, 'principal', 1);

                insert_record(
                    'artefact_internal_profile_email',
                    (object) array(
                        'owner'     => $this->owner,
                        'email'     => $this->title,
                        'verified'  => 1,
                        'principal' => ( $principal ? 0 : 1 ),
                        'artefact'  => $this->id,
                    )
                );
843
                update_record('usr', (object)array('email' => $this->title, 'id' => $this->owner));
844
            }
845
846
        }
    }
847
848
849
850
851

    public function delete() {
        delete_records('artefact_internal_profile_email', 'artefact', $this->id);
        parent::delete();
    }
852

853
    public static function bulk_delete($artefactids, $log=false) {
854
855
856
857
858
859
860
861
862
863
864
865
        if (empty($artefactids)) {
            return;
        }

        $idstr = join(',', array_map('intval', $artefactids));

        db_begin();
        delete_records_select('artefact_internal_profile_email', 'artefact IN (' . $idstr . ')');
        parent::bulk_delete($artefactids);
        db_commit();
    }

866
867
868
869
870
871
872
873
874
    public function render_self($options) {
        if (array_key_exists('link', $options) && $options['link'] == true) {
            $html = '<a href="mailto:' . hsc($this->title) . '">' . hsc($this->title) . '</a>';
        }
        else {
            $html = $this->title;
        }
        return array('html' => $html, 'javascript' => null);
    }
875
876
877
878

    static public function is_allowed_in_progressbar() {
        return false;
    }
879
}
880

881
class ArtefactTypeStudentid extends ArtefactTypeCachedProfileField {}
882
class ArtefactTypeIntroduction extends ArtefactTypeProfileField {
883
884
885
886
887
888
    public function commit() {
        $this->set('description', $this->title);
        $this->set('title', 'introduction');
        parent::commit();
    }

889
    public function render_self($options) {
890
        return array('html' => clean_html($this->description), 'javascript' => null);
891
892
    }
}
893
class ArtefactTypeWebAddress extends ArtefactTypeProfileField {
Penny Leach's avatar
Penny Leach committed
894

895
896
    public function commit() {
        $url = $this->get('title');
897
        if (strlen($url) && strpos($url, '://') == false) {
898
899
900
901
902
            $this->set('title', 'http://' . $url);
        }
        parent::commit();
    }

Penny Leach's avatar
Penny Leach committed
903
    public function render_self($options) {
904
        if (array_key_exists('link', $options) && $options['link'] == true) {
905
            $html = '<a href="' . hsc($this->title) . '">' . hsc($this->title) . '</a>';
906
907
908
909
910
        }
        else {
            $html = $this->title;
        }
        return array('html' => $html, 'javascript' => null);
911
912
    }
}
913
914
class ArtefactTypeOfficialwebsite extends ArtefactTypeWebAddress {}
class ArtefactTypePersonalwebsite extends ArtefactTypeWebAddress {}
915
class ArtefactTypeBlogAddress extends ArtefactTypeWebAddress {}
916
917
918
919
920
class ArtefactTypeAddress extends ArtefactTypeProfileField {
    public function render_self($options) {
        return array('html' => format_whitespace($this->title), 'javascript' => null);
    }
}
921
922
class ArtefactTypeTown extends ArtefactTypeProfileField {}
class ArtefactTypeCity extends ArtefactTypeProfileField {}
923
class ArtefactTypeCountry extends ArtefactTypeProfileField {
Penny Leach's avatar
Penny Leach committed
924
925
926
927

    public function render_self($options) {
          $countries = getoptions_country();
          return array('html' => $countries[$this->title], 'javascript' => null);
928
    }
929
930
931
    /**
     * Render the import entry request for country fields
     */
932
    public static function render_import_entry_request($entry_content, $renderfields=array()) {
933
934
935
        $countries = getoptions_country();
        return (isset($countries[$entry_content['title']]) ? $countries[$entry_content['title']] : '');
    }
936
937
938
939
940
941
942
943
944
945
946
947
    /**
     * Format value for display
     */
    function format_result($raw) {
        return get_string("country.{$raw}");
    }
    /**
     * Use custom template for display on User -> Search page
     */
    function usersearch_column_structure() {
        return array('name' => 'country', 'sort' => true, 'template' => 'admin/users/searchcountrycolumn.tpl');
    }
948
}
949
950
951
952
class ArtefactTypeHomenumber extends ArtefactTypeProfileField {}
class ArtefactTypeBusinessnumber extends ArtefactTypeProfileField {}
class ArtefactTypeMobilenumber extends ArtefactTypeProfileField {}
class ArtefactTypeFaxnumber extends ArtefactTypeProfileField {}
Martyn Smith's avatar
Martyn Smith committed
953
954
class ArtefactTypeOccupation extends ArtefactTypeProfileField {}
class ArtefactTypeIndustry extends ArtefactTypeProfileField {}
955
956
957

/* Artefact type for generic html fragments */
class ArtefactTypeHtml extends ArtefactType {
958
959
960
961
962
963
964
965
966

    public function describe_size() {
        return $this->count_attachments() . ' ' . get_string('attachments', 'artefact.blog');
    }

    public function can_have_attachments() {
        return true;
    }

967
    public static function get_icon($options=null) {
968
        global $THEME;
969
        return false;
970
971
972
973
974
975
976
    }

    public static function is_singular() {
        return false;
    }

    public static function get_links($id) {
977
978
979
        return array(
            '_default' => get_config('wwwroot') . 'artefact/internal/editnote.php?id=' . $id,
        );
980
    }
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000

    public function render_self($options) {
        $smarty = smarty_core();
        $smarty->assign('title', $this->get('title'));
        $smarty->assign('owner', $this->get('owner'));
        $smarty->assign('tags', $this->get('tags'));
        $smarty->assign('description', $this->get('description'));
        if (!empty($options['details']) and get_config('licensemetadata')) {
            $smarty->assign('license', render_license($this));
        }
        else {
            $smarty->assign('license', false);
        }
        $attachments = $this->get_attachments();
        if ($attachments) {
            require_once(get_config('docroot') . 'artefact/lib.php');
            foreach ($attachments as &$attachment) {
                $f = artefact_instance_from_id($attachment->id);
                $attachment->size = $f->describe_size();
                $attachment->iconpath = $f->get_icon(array('id' => $attachment->id, 'viewid' => isset($options['viewid']) ? $options['viewid'] : 0));
1001
                $attachment->viewpath = get_config('wwwroot') . 'artefact/artefact.php?artefact=' . $attachment->id . '&view=' . (isset($options['viewid']) ? $options['viewid'] : 0);
1002
1003
1004
1005
1006
1007
1008
                $attachment->downloadpath = get_config('wwwroot') . 'artefact/file/download.php?file=' . $attachment->id;
                if (isset($options['viewid'])) {
                    $attachment->downloadpath .= '&view=' . $options['viewid'];
                }
            }
            $smarty->assign('attachments', $attachments);
        }
1009
        $smarty->assign('view', (isset($options['viewid']) ? $options['viewid'] : null));
1010
1011
1012
1013
1014
        return array(
            'html' => $smarty->fetch('artefact.tpl'),
            'javascript'=>''
        );
    }
1015
1016
1017
1018

    public static function is_allowed_in_progressbar() {
        return false;
    }
1019
1020
1021

    public function update_artefact_references(&$view, &$template, &$artefactcopies, $oldid) {
        parent::update_artefact_references($view, $template, $artefactcopies, $oldid);
1022
        // 1. Attach copies of the files that were attached to the old note.
1023
1024
1025
1026
1027
1028
1029
        if (isset($artefactcopies[$oldid]->oldattachments)) {
            foreach ($artefactcopies[$oldid]->oldattachments as $a) {
                if (isset($artefactcopies[$a])) {
                    $this->attach($artefactcopies[$a]->newid);
                }
            }
        }
1030
1031
1032
1033
1034
1035
1036
        // 2. Update embedded images in the note and db
        $regexp = array();
        $replacetext = array();
        if (!empty($artefactcopies[$oldid]->oldembeds)) {
            foreach ($artefactcopies[$oldid]->oldembeds as $a) {
                if (isset($artefactcopies[$a])) {
                    // Change the old image id to the new one
1037
1038
                    $regexp[] = '#<img([^>]+)src="' . get_config('wwwroot') . 'artefact/file/download.php\?file=' . $a . '([^0-9])#';
                    $replacetext[] = '<img$1src="' . get_config('wwwroot') . 'artefact/file/download.php?file=' . $artefactcopies[$a]->newid . '$2';
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
                }
            }
            require_once('embeddedimage.php');
            $newdescription = EmbeddedImage::prepare_embedded_images(
                    preg_replace($regexp, $replacetext, $this->get('description')),
                    'textbox',
                    $this->get('id'),
                    $view->get('group')
                );
            $this->set('description', $newdescription);
        }
1050
    }
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
    /**
     * This function extends ArtefactType::delete() by deleting embedded images
     */
    public function delete() {
        if (empty($this->id)) {
            return;
        }

        db_begin();
        // Delete embedded images in the note
        require_once('embeddedimage.php');
        EmbeddedImage::delete_embedded_images('textbox', $this->id);
        // Delete the artefact and all children.
        parent::delete();
        db_commit();
    }

1068
}
1069
1070
1071
1072


class ArtefactTypeSocialprofile extends ArtefactTypeProfileField {

1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
    public static $socialnetworks = array(
        'facebook',
        'twitter',
        'tumblr',
        'instagram',
        'pinterest',
        'aim',
        'icq',
        'jabber',
        'skype',
        'yahoo',
    );

1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
    public static function is_singular() {
        return false;
    }

    public function can_have_attachments() {
        return false;
    }

    public function render_self($options) {
        if (array_key_exists('link', $options) && $options['link'] == true) {
            $link = self::get_profile_link($this->title, $this->note);
1097
1098
1099
1100
1101
1102
1103
            if ($link) {
                $html = '<a href="' . hsc($link) . '">' . hsc($this->title) . '</a>';
            }
            else {
                // No valid link, even though you asked for one.
                $html = hsc($this->title);
            }
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
        }
        else {
            $html = $this->title;
        }
        return array('html' => $html, 'javascript' => null);
    }

    /**
     * Render the import entry request for social profile fields
     */
1114
    public static function render_import_entry_request($entry_content, $renderfields=array()) {
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
        $html = '<strong>' . $entry_content['description'] . ':</strong>&nbsp;' . $entry_content['title'];
        return clean_html($html);
    }

    /**
     * Get an array of all the social profiles input for this user.
     * @return array of social profiles.
     */
    public function get_social_profiles() {
        global $USER;

        $sql = 'SELECT * FROM {artefact}
            WHERE owner = ? AND artefacttype = ?
            ORDER BY description ASC';

        if (!$data = get_records_sql_array($sql, array($USER->get('id'), 'socialprofile'))) {
            $data = array();
        }

        $data = self::get_profile_icons($data);
        return $data;
    }

    /*
     * Create and return url of input messaging system or return social profile url of input social site.
     *
     * @param string $data The string containing messaging username or user social profile url
     * @param string $type Social profile subtype; one of icq, aim, yahoo, skype, jabber or webpage (default)
     * @return string The URL address
     */
1145
1146
1147
1148
1149
1150
1151
    public static function get_profile_link($data, $type) {

        // If they've entered a full URL, just use that
        if (filter_var($data, FILTER_VALIDATE_URL)) {
            return $data;
        }

1152
        switch ($type) {
1153
1154
1155
            case 'facebook':
                $link = 'https://www.facebook.com/' . hsc($data);
                break;
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
            case 'twitter':
                // Strip an "@" sign if they put one on.
                if (strlen($data) && $data[0] == '@') {
                    $data = substr($data, 1);
                }
                $link = 'https://twitter.com/' . hsc($data);
                break;
            case 'instagram':
                // Strip an "@" sign if they put one on.
                if (strlen($data) && $data[0] == '@') {
                    $data = substr($data, 1);
                }
                $link = 'https://instagram.com/' . hsc($data) . '/';
                break;
            case 'pinterest':
                $link = 'https://www.pinterest.com/' . hsc($data) . '/';
                break;
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
            case 'icq':
                $link = 'http://www.icq.com/people/' . hsc($data);
                break;
            case 'aim':
                $link = 'aim:goim?screenname=' . hsc($data);
                break;
            case 'yahoo':
                $link = 'ymsgr:chat?' . hsc($data);
                break;
            case 'skype':
                $link = 'skype:' . hsc($data) . '?call';
                break;
            case 'jabber':
                $link = 'xmpp:' . hsc($data);
                break;
            default:
1189
                $link = false;
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
        }

        return $link;
    }

    /**
     * Add favicon of different messaging systems or
     * social sites, contained in the input data.
     * @param array $data with details of the social profile.
     * $data[]->note - the type of social profile (i.e. icq, aim, etc).
     * $data[]->title - display name of the social profile.
     * $data[]->icon - the URL of the icon. Will be populated by this function.
     * @return array of icon details for the specified social profile.
     * $newdata[]->note - originally passed into function.
     * $newdata[]->title - originally passed into function.
     * $newdata[]->icon - the URL of the icon.
     * $newdata[]->link - URL or application call.
     */
1208
    public static function get_profile_icons($data) {
1209
1210
        $newdata = array();
        foreach ($data as $record) {
1211
1212
1213

            $record->link = self::get_profile_link($record->title, $record->note);

1214
            switch ($record->note) {
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
                case 'facebook':
                    $record->icon = favicon_display_url('facebook.com');
                    break;
                case 'tumblr':
                    $record->icon = favicon_display_url('tumblr.com');
                    break;
                case 'twitter':
                    $record->icon = favicon_display_url('twitter.com');
                    break;
                case 'instagram':
                    $record->icon = favicon_display_url('instagram.com');
                    break;
                case 'pinterest':
                    $record->icon = favicon_display_url('www.pinterest.com');
                    break;
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
                case 'icq':
                    $record->icon = favicon_display_url('www.icq.com');
                    break;
                case 'aim':
                    $record->icon = favicon_display_url('www.aim.com');
                    break;
                case 'yahoo':
                    $record->icon = favicon_display_url('messenger.yahoo.com');
                    break;
                case 'skype':
                    // Since www.skype.com favicon is not working...
                    $record->icon = favicon_display_url('support.skype.com');
                    break;
                case 'jabber':
                    // Since www.jabber.org favicon is not working...
                    $record->icon = favicon_display_url('planet.jabber.org');
                    break;
                default:
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
                    // We'll fall back to the "no favicon" default icon
                    $record->icon = favicon_display_url('example.com');

                    // If they've supplied a URL, use its favicon
                    if (filter_var($record->title, FILTER_VALIDATE_URL)) {
                        $url = parse_url($record->title);
                        // Check if $url['host'] actually exists - just in case
                        // it was badly formatted.
                        if (isset($url['host'])) {
                            $record->icon = favicon_display_url($url['host']);
                        }
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
                    }
            }
            $newdata[] = $record;
        }
        return $newdata;
    }

    public function render_profile_element() {
        $data = self::get_social_profiles();

        // Build pagination for 'socialprofile' artefacts table
        $baseurl = get_config('wwwroot') . 'artefact/internal/index.php' .
                   '?' . http_build_query(array('fs' => 'social'));
        $count   = count($data);
        $limit   = 500;
        $offset  = 0;

        $pagination = build_pagination(array(
            'id'        => 'socialprofiles_pagination',
            'url'       => $baseurl,
            'datatable' => 'socialprofilelist',
            'count'     => $count,
            'limit'     => $limit,
            'offset'    => $offset,
        ));

        // User may delete social profile if:
        //  - there is more than 1 social profile and 'socialprofile' is a mandatory field.
        //  - 'socialprofile' is not mandatory.
        $candelete = true;
        $mandatory_fields = ArtefactTypeProfile::get_mandatory_fields();
        if (isset($mandatory_fields['socialprofile']) && count($data) <= 1) {
            $candelete = false;
        }

        $smarty = smarty_core();
        $smarty->assign('controls', true);
        $smarty->assign('rows', $data);
        $smarty->assign('candelete', $candelete);
        $smarty->assign('pagination', $pagination);

        return array(
            'type' => 'html',
            'value' => $smarty->fetch('artefact:internal:socialprofiles.tpl')
        );
    }

    /**
     * Used in the mandatory fields check during the authentication process.
     */
    public function get_new_profile_elements() {

1311
1312
1313
1314
1315
        $socialnetworkoptions = array();
        foreach (ArtefactTypeSocialprofile::$socialnetworks as $socialnetwork) {
            $socialnetworkoptions[$socialnetwork] = get_string($socialnetwork . '.input', 'artefact.internal');
        }

1316
1317
1318
1319
        $items = array(
            'socialprofile_profiletype' => array(
                'type'        => 'select',
                'title'       => get_string('profiletype', 'artefact.internal'),
1320
1321
                'options'     => $socialnetworkoptions,
                'allowother'  => true,
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
                'width'        => 171,
                'rules'        => array('required' => true),
            ),
            'socialprofile_profileurl' => array(
                'type'         => 'text',
                'title'        => get_string('profileurl', 'artefact.internal'),
                'description'  => get_string('profileurldesc', 'artefact.internal'),
                'defaultvalue' => null,
                'size'         => 40,
                'rules'        => array('required' => true),
            ),
        );
        $element = array(
            'type'     => 'fieldset',
            'legend'   => get_string('social', 'artefact.internal'),
            'class'    => 'social',
            'elements' => $items,
        );

        return $element;
    }

}