lib.php 30.7 KB
Newer Older
1
2
<?php
/**
Francois Marier's avatar
Francois Marier committed
3
 * Mahara: Electronic portfolio, weblog, resume builder and social networking
4
5
 * Copyright (C) 2006-2009 Catalyst IT Ltd and others; see:
 *                         http://wiki.mahara.org/Contributors
6
 *
Francois Marier's avatar
Francois Marier committed
7
8
9
10
 * 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.
11
 *
Francois Marier's avatar
Francois Marier committed
12
13
14
15
 * 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.
16
 *
Francois Marier's avatar
Francois Marier committed
17
18
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
20
21
 *
 * @package    mahara
 * @subpackage artefact-blog
22
 * @author     Catalyst IT Ltd
23
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL
24
 * @copyright  (C) 2006-2009 Catalyst IT Ltd http://catalyst.net.nz
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
 *
 */

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

/** 
 * Users can create blogs and blog posts using this plugin.
 */
class PluginArtefactBlog extends PluginArtefact {

    public static function get_artefact_types() {
        return array(
            'blog',
            'blogpost',
        );
    }
41
42
43
44
    
    public static function get_block_types() {
        return array();
    }
45
46
47
48
49
50

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

    public static function menu_items() {
51
        global $USER;
52
53
54
        $tab = array(
            'path'   => 'myportfolio/blogs',
            'weight' => 30,
55
        );
56
57
58
59
60
61
62
63
64
        if ($USER->get_account_preference('multipleblogs')) {
            $tab['url']   = 'artefact/blog/';
            $tab['title'] = get_string('myblogs', 'artefact.blog');
        }
        else {
            $tab['url']   = 'artefact/blog/view/';
            $tab['title'] = get_string('myblog', 'artefact.blog');
        }
        return array($tab);
65
    }
66

67
    public static function get_cron() {
68
        return array();
69
70
    }

71

72
73
74
75
76
77
78
79
80
81
    public static function get_event_subscriptions() {
        return array(
            (object)array(
                'plugin'       => 'blog',
                'event'        => 'createuser',
                'callfunction' => 'create_default_blog',
            ),
        );
    }

82
83
84
85
86
87
88
    public static function block_advanced_options_element($configdata, $artefacttype) {
        $strartefacttype = get_string($artefacttype, 'artefact.blog');
        return array(
            'type' => 'fieldset',
            'name' => 'advanced',
            'collapsible' => true,
            'collapsed' => false,
89
            'legend' => get_string('moreoptions', 'artefact.blog'),
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
            'elements' => array(
                'copytype' => array(
                    'type' => 'select',
                    'title' => get_string('blockcopypermission', 'view'),
                    'description' => get_string('blockcopypermissiondesc', 'view'),
                    'defaultvalue' => isset($configdata['copytype']) ? $configdata['copytype'] : 'nocopy',
                    'options' => array(
                        'nocopy' => get_string('copynocopy', 'artefact.blog'),
                        'reference' => get_string('copyreference', 'artefact.blog', $strartefacttype),
                        'full' => get_string('copyfull', 'artefact.blog', $strartefacttype),
                    ),
                ),
            ),
        );
    }

106
107
108
109
110
111
112
113
    public static function create_default_blog($event, $user) {
        $name = display_name($user, null, true);
        $blog = new ArtefactTypeBlog(0, (object) array(
            'title'       => get_string('defaultblogtitle', 'artefact.blog', $name),
            'owner'       => $user['id'],
        ));
        $blog->commit();
    }
114
115
116
117
118
119

    public static function get_artefact_type_content_types() {
        return array(
            'blogpost' => array('text'),
        );
    }
120
121
122
123
124
125
126
}

/**
 * A Blog artefact is a collection of BlogPost artefacts.
 */
class ArtefactTypeBlog extends ArtefactType {

Alastair Pharo's avatar
Alastair Pharo committed
127
128
129
130
    /**
     * This constant gives the per-page pagination for listing blogs.
     */
    const pagination = 10;
131
132


133
134
135
136
137
138
139
140
    /**
     * We override the constructor to fetch the extra data.
     *
     * @param integer
     * @param object
     */
    public function __construct($id = 0, $data = null) {
        parent::__construct($id, $data);
141
142
143
144
145
146

        if (empty($this->id)) {
            $this->container = 1;
        }
    }

Alastair Pharo's avatar
Alastair Pharo committed
147
    /**
148
149
150
     * This function updates or inserts the artefact.  This involves putting
     * some data in the artefact table (handled by parent::commit()), and then
     * some data in the artefact_blog_blog table.
Alastair Pharo's avatar
Alastair Pharo committed
151
     */
152
    public function commit() {
153
154
155
156
157
158
159
160
161
162
163
164
        // Just forget the whole thing when we're clean.
        if (empty($this->dirty)) {
            return;
        }
      
        // We need to keep track of newness before and after.
        $new = empty($this->id);
        
        // Commit to the artefact table.
        parent::commit();

        $this->dirty = false;
165
166
    }

Alastair Pharo's avatar
Alastair Pharo committed
167
    /**
168
169
     * This function extends ArtefactType::delete() by deleting blog-specific
     * data.
Alastair Pharo's avatar
Alastair Pharo committed
170
     */
171
    public function delete() {
172
173
174
175
176
177
        if (empty($this->id)) {
            return;
        }

        // Delete the artefact and all children.
        parent::delete();
178
179
    }

180
181
182
183
184
185
186
187
188
189
190
191
192
    /**
     * Checks that the person viewing this blog is the owner. If not, throws an 
     * AccessDeniedException. Used in the blog section to ensure only the 
     * owners of the blogs can view or change them there. Other people see 
     * blogs when they are placed in views.
     */
    public function check_permission() {
        global $USER;
        if ($USER->get('id') != $this->owner) {
            throw new AccessDeniedException(get_string('youarenottheownerofthisblog', 'artefact.blog'));
        }
    }

193

194
195
    public function describe_size() {
        return $this->count_children() . ' ' . get_string('posts', 'artefact.blog');
196
197
    }

198
    /**
199
     * Renders a blog.
200
201
202
203
204
205
206
     *
     * @param  array  Options for rendering
     * @return array  A two key array, 'html' and 'javascript'.
     */
    public function render_self($options) {
        $this->add_to_render_path($options);

207
208
209
210
211
212
213
214
215
216
217
        if (!isset($options['limit'])) {
            $limit = self::pagination;
        }
        else if ($options['limit'] === false) {
            $limit = null;
        }
        else {
            $limit = (int) $options['limit'];
        }
        $offset = isset($options['offset']) ? intval($options['offset']) : 0;

218
219
220
221
222
        if (!isset($options['countcomments'])) {
            // Count comments if this is a view
            $options['countcomments'] = (!empty($options['viewid']));
        }

223
224
225
226
        $posts = ArtefactTypeBlogpost::get_posts($this->id, $limit, $offset, $options);

        $template = 'artefact:blog:viewposts.tpl';

227
228
229
230
        $baseurl = get_config('wwwroot') . 'view/artefact.php?artefact=' . $this->id;
        if (!empty($options['viewid'])) {
            $baseurl .= '&view=' . $options['viewid'];
        }
231
232
233
234
235
236
237
238
239
        $pagination = array(
            'baseurl' => $baseurl,
            'id' => 'blogpost_pagination',
            'datatable' => 'postlist',
            'jsonscript' => 'artefact/blog/posts.json.php',
        );

        ArtefactTypeBlogpost::render_posts($posts, $template, $options, $pagination);

240
241
        $smarty = smarty_core();
        if (isset($options['viewid'])) {
242
243
            $smarty->assign('artefacttitle', '<a href="' . get_config('wwwroot') . 'view/artefact.php?artefact='
                                             . $this->get('id') . '&view=' . $options['viewid']
Richard Mansfield's avatar
Richard Mansfield committed
244
                                             . '">' . hsc($this->get('title')) . '</a>');
245
246
        }
        else {
Richard Mansfield's avatar
Richard Mansfield committed
247
            $smarty->assign('artefacttitle', hsc($this->get('title')));
248
249
        }

250
        $options['hidetitle'] = true;
251
        $smarty->assign('options', $options);
252
        $smarty->assign('description', $this->get('description'));
253
254
        $smarty->assign('owner', $this->get('owner'));
        $smarty->assign('tags', $this->get('tags'));
255

256
        $smarty->assign_by_ref('posts', $posts);
257

258
        return array('html' => $smarty->fetch('artefact:blog:blog.tpl'), 'javascript' => '');
259
260
    }

261
                
262
    public static function get_icon($options=null) {
263
264
        global $THEME;
        return $THEME->get_url('images/blog.gif', false, 'artefact/blog');
265
266
    }

Nigel McNie's avatar
Nigel McNie committed
267
    public static function is_singular() {
Penny Leach's avatar
Penny Leach committed
268
269
270
        return false;
    }

Alastair Pharo's avatar
Alastair Pharo committed
271
    public static function collapse_config() {
272
273
    }

Alastair Pharo's avatar
Alastair Pharo committed
274
275
276
277
278
279
    /**
     * This function returns a list of the given user's blogs.
     *
     * @param User
     * @return array (count: integer, data: array)
     */
280
281
    public static function get_blog_list($limit, $offset) {
        global $USER;
Alastair Pharo's avatar
Alastair Pharo committed
282
        ($result = get_records_sql_array("
283
         SELECT b.id, b.title, b.description, b.locked, COUNT(p.id) AS postcount
284
285
         FROM {artefact} b LEFT JOIN {artefact} p ON (p.parent = b.id AND p.artefacttype = 'blogpost')
         WHERE b.owner = ? AND b.artefacttype = 'blog'
286
         GROUP BY b.id, b.title, b.description, b.locked
287
         ORDER BY b.title", array($USER->get('id')), $offset, $limit))
Alastair Pharo's avatar
Alastair Pharo committed
288
289
            || ($result = array());

290
        $count = (int)get_field('artefact', 'COUNT(*)', 'owner', $USER->get('id'), 'artefacttype', 'blog');
Alastair Pharo's avatar
Alastair Pharo committed
291
292
293
294

        return array($count, $result);
    }

295
296
297
    public static function build_blog_list_html(&$blogs) {
        $smarty = smarty_core();
        $smarty->assign_by_ref('blogs', $blogs);
298
299
        $blogs->tablerows = $smarty->fetch('artefact:blog:bloglist.tpl');
        $pagination = build_pagination(array(
300
301
302
            'id' => 'bloglist_pagination',
            'class' => 'center',
            'url' => get_config('wwwroot') . 'artefact/blog/index.php',
303
304
            'jsonscript' => 'artefact/blog/index.json.php',
            'datatable' => 'bloglist',
305
306
307
308
309
310
311
312
313
314
315
            'count' => $blogs->count,
            'limit' => $blogs->limit,
            'offset' => $blogs->offset,
            'firsttext' => '',
            'previoustext' => '',
            'nexttext' => '',
            'lasttext' => '',
            'numbersincludefirstlast' => false,
            'resultcounttextsingular' => get_string('blog', 'artefact.blog'),
            'resultcounttextplural' => get_string('blogs', 'artefact.blog'),
        ));
316
317
        $blogs->pagination = $pagination['html'];
        $blogs->pagination_js = $pagination['javascript'];
318
319
    }

Alastair Pharo's avatar
Alastair Pharo committed
320
321
322
323
324
325
    /**
     * This function creates a new blog.
     *
     * @param User
     * @param array
     */
Alastair Pharo's avatar
Alastair Pharo committed
326
    public static function new_blog(User $user, array $values) {
Alastair Pharo's avatar
Alastair Pharo committed
327
328
329
330
        $artefact = new ArtefactTypeBlog();
        $artefact->set('title', $values['title']);
        $artefact->set('description', $values['description']);
        $artefact->set('owner', $user->get('id'));
331
        $artefact->set('tags', $values['tags']);
Alastair Pharo's avatar
Alastair Pharo committed
332
        $artefact->commit();
333
    }
Alastair Pharo's avatar
Alastair Pharo committed
334
335
336
337
338
339
340
341
342
343
344
345
346

    /**
     * This function updates an existing blog.
     *
     * @param User
     * @param array
     */
    public static function edit_blog(User $user, array $values) {
        if (empty($values['id']) || !is_numeric($values['id'])) {
            return;
        }

        $artefact = new ArtefactTypeBlog($values['id']);
347
348
349
350
        if ($user->get('id') != $artefact->get('owner')) {
            return;
        }
        
Alastair Pharo's avatar
Alastair Pharo committed
351
352
        $artefact->set('title', $values['title']);
        $artefact->set('description', $values['description']);
353
        $artefact->set('tags', $values['tags']);
Alastair Pharo's avatar
Alastair Pharo committed
354
355
        $artefact->commit();
    }
356

Martyn Smith's avatar
Martyn Smith committed
357
358
    public static function get_links($id) {
        $wwwroot = get_config('wwwroot');
359

Martyn Smith's avatar
Martyn Smith committed
360
361
362
363
364
        return array(
            '_default'                                  => $wwwroot . 'artefact/blog/view/?id=' . $id,
            get_string('blogsettings', 'artefact.blog') => $wwwroot . 'artefact/blog/settings/?id=' . $id,
        );
    }
365
366
367
368
369

    public function copy_extra($new) {
        $new->set('title', get_string('Copyof', 'mahara', $this->get('title')));
    }

370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
    /**
     * Returns the number of posts in this blog that have been published.
     *
     * The result of this function looked up from the database each time, so 
     * cache it if you know it's safe to do so.
     *
     * @return int
     */
    public function count_published_posts() {
        return (int)get_field_sql("
            SELECT COUNT(*)
            FROM {artefact} a
            LEFT JOIN {artefact_blog_blogpost} bp ON a.id = bp.blogpost
            WHERE a.parent = ?
            AND bp.published = 1", array($this->get('id')));
    }

387
388
389
390
391
392
393
}

/**
 * BlogPost artefacts occur within Blog artefacts
 */
class ArtefactTypeBlogPost extends ArtefactType {

394
    /**
Alastair Pharo's avatar
Alastair Pharo committed
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
     * This defines whether the blogpost is published or not.
     *
     * @var boolean
     */
    protected $published = false;

    /**
     * We override the constructor to fetch the extra data.
     *
     * @param integer
     * @param object
     */
    public function __construct($id = 0, $data = null) {
        parent::__construct($id, $data);

410
411
412
413
414
        if ($this->id) {
            if ($bpdata = get_record('artefact_blog_blogpost', 'blogpost', $this->id)) {
                foreach($bpdata as $name => $value) {
                    if (property_exists($this, $name)) {
                        $this->$name = $value;
415
                    }
Alastair Pharo's avatar
Alastair Pharo committed
416
                }
417
418
419
420
            }
            else {
                // This should never happen unless the user is playing around with blog post IDs in the location bar or similar
                throw new ArtefactNotFoundException(get_string('blogpostdoesnotexist', 'artefact.blog'));
421
422
            }
        }
423
424
425
        else {
            $this->allowcomments = 1; // Turn comments on for new posts
        }
Alastair Pharo's avatar
Alastair Pharo committed
426
427
428
    }

    /**
429
     * This method extends ArtefactType::commit() by adding additional data
Alastair Pharo's avatar
Alastair Pharo committed
430
     * into the artefact_blog_blogpost table.
431
432
433
434
435
     *
     * This method also works out what blockinstances this blogpost is in, and 
     * informs them that they should re-check what artefacts they have in them.
     * The post content may now link to different artefacts. See {@link 
     * PluginBlocktypeBlogPost::get_artefacts for more information}
436
     */
437
    public function commit() {
Alastair Pharo's avatar
Alastair Pharo committed
438
439
440
441
        if (empty($this->dirty)) {
            return;
        }

442
        db_begin();
Alastair Pharo's avatar
Alastair Pharo committed
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
        $new = empty($this->id);
      
        parent::commit();

        $this->dirty = true;

        $data = (object)array(
            'blogpost'  => $this->get('id'),
            'published' => ($this->get('published') ? 1 : 0)
        );

        if ($new) {
            insert_record('artefact_blog_blogpost', $data);
        }
        else {
            update_record('artefact_blog_blogpost', $data, 'blogpost');
        }

461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
        // We want to get all blockinstances that contain this blog post. That is currently:
        // 1) All blogpost blocktypes with this post in it
        // 2) All blog blocktypes with this posts's blog in it
        //
        // With these, we tell them to rebuild what artefacts they have in them, 
        // since the post content could have changed and now have links to 
        // different artefacts in it
        $blockinstanceids = (array)get_column_sql('SELECT block
            FROM {view_artefact}
            WHERE artefact = ?
            OR artefact = ?', array($this->get('id'), $this->get('parent')));
        if ($blockinstanceids) {
            require_once(get_config('docroot') . 'blocktype/lib.php');
            foreach ($blockinstanceids as $id) {
                $instance = new BlockInstance($id);
                $instance->rebuild_artefact_list();
            }
        }

        db_commit();
Alastair Pharo's avatar
Alastair Pharo committed
481
        $this->dirty = false;
482
483
    }

484
    /**
Alastair Pharo's avatar
Alastair Pharo committed
485
486
     * This function extends ArtefactType::delete() by also deleting anything
     * that's in blogpost.
487
     */
488
    public function delete() {
Alastair Pharo's avatar
Alastair Pharo committed
489
490
491
        if (empty($this->id)) {
            return;
        }
492

493
        db_begin();
494
        $this->detach(); // Detach all file attachments
Alastair Pharo's avatar
Alastair Pharo committed
495
496
497
        delete_records('artefact_blog_blogpost', 'blogpost', $this->id);
      
        parent::delete();
498
        db_commit();
Alastair Pharo's avatar
Alastair Pharo committed
499
    }
500

501
502
503
504
505
506
507
508
509
510
511
512
513
514
    public static function bulk_delete($artefactids) {
        if (empty($artefactids)) {
            return;
        }

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

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


515
516
517
518
519
520
521
522
523
524
525
526
    /**
     * Checks that the person viewing this blog is the owner. If not, throws an 
     * AccessDeniedException. Used in the blog section to ensure only the 
     * owners of the blogs can view or change them there. Other people see 
     * blogs when they are placed in views.
     */
    public function check_permission() {
        global $USER;
        if ($USER->get('id') != $this->owner) {
            throw new AccessDeniedException(get_string('youarenottheownerofthisblogpost', 'artefact.blog'));
        }
    }
527
  
528
529
    public function describe_size() {
        return $this->count_attachments() . ' ' . get_string('attachments', 'artefact.blog');
530
531
    }

532
533
    public function render_self($options) {
        $smarty = smarty_core();
534
535
536
537
538
        $artefacturl = get_config('wwwroot') . 'view/artefact.php?artefact=' . $this->get('id');
        if (isset($options['viewid'])) {
            $artefacturl .= '&view=' . $options['viewid'];
        }
        $smarty->assign('artefacturl', $artefacturl);
539
540
        if (empty($options['hidetitle'])) {
            if (isset($options['viewid'])) {
541
                $smarty->assign('artefacttitle', '<a href="' . $artefacturl . '">' . hsc($this->get('title')) . '</a>');
542
543
            }
            else {
Richard Mansfield's avatar
Richard Mansfield committed
544
                $smarty->assign('artefacttitle', hsc($this->get('title')));
545
546
547
548
            }
        }

        // We need to make sure that the images in the post have the right viewid associated with them
549
        $postcontent = $this->get('description');
550
        if (isset($options['viewid'])) {
551
552
            safe_require('artefact', 'file');
            $postcontent = ArtefactTypeFolder::append_view_url($postcontent, $options['viewid']);
553
554
555
556
557
558
559
            if (isset($options['countcomments']) && $this->allowcomments) {
                safe_require('artefact', 'comment');
                $empty = array();
                $ids = array($this->id);
                $commentcount = ArtefactTypeComment::count_comments($empty, $ids);
                $smarty->assign('commentcount', $commentcount ? $commentcount[$this->id]->comments : 0);
            }
560
561
562
        }
        $smarty->assign('artefactdescription', $postcontent);
        $smarty->assign('artefact', $this);
563
        $attachments = $this->get_attachments();
564
565
        if ($attachments) {
            $this->add_to_render_path($options);
566
            require_once(get_config('docroot') . 'artefact/lib.php');
567
568
569
            foreach ($attachments as &$attachment) {
                $f = artefact_instance_from_id($attachment->id);
                $attachment->size = $f->describe_size();
570
571
                $attachment->iconpath = $f->get_icon(array('id' => $attachment->id, 'viewid' => isset($options['viewid']) ? $options['viewid'] : 0));
                $attachment->viewpath = get_config('wwwroot') . 'view/artefact.php?artefact=' . $attachment->id . '&view=' . (isset($options['viewid']) ? $options['viewid'] : 0);
572
573
                $attachment->downloadpath = get_config('wwwroot') . 'artefact/file/download.php?file=' . $attachment->id;
                if (isset($options['viewid'])) {
574
                    $attachment->downloadpath .= '&view=' . $options['viewid'];
575
576
577
578
579
580
581
582
583
584
585
586
                }
            }
            $smarty->assign('attachments', $attachments);
        }
        $smarty->assign('postedbyon', get_string('postedbyon', 'artefact.blog',
                                                 display_name($this->owner),
                                                 format_date($this->ctime)));
        return array('html' => $smarty->fetch('artefact:blog:render/blogpost_renderfull.tpl'),
                     'javascript' => '');
    }


587
588
    public function can_have_attachments() {
        return true;
Richard Mansfield's avatar
Richard Mansfield committed
589
590
591
    }


592
    public static function get_icon($options=null) {
593
594
        global $THEME;
        return $THEME->get_url('images/blogpost.gif', false, 'artefact/blog');
595
596
    }

Nigel McNie's avatar
Nigel McNie committed
597
    public static function is_singular() {
Penny Leach's avatar
Penny Leach committed
598
599
600
        return false;
    }

Alastair Pharo's avatar
Alastair Pharo committed
601
    public static function collapse_config() {
602
603
    }

Alastair Pharo's avatar
Alastair Pharo committed
604
    /**
605
     * This function returns a list of posts in a given blog.
Alastair Pharo's avatar
Alastair Pharo committed
606
607
608
     *
     * @param integer
     * @param integer
609
     * @param integer
610
     * @param array
Alastair Pharo's avatar
Alastair Pharo committed
611
     */
612
    public static function get_posts($id, $limit, $offset, $viewoptions=null) {
Alastair Pharo's avatar
Alastair Pharo committed
613

614
615
616
617
        $results = array(
            'limit'  => $limit,
            'offset' => $offset,
        );
618

619
620
621
622
623
624
625
626
627
628
629
        // If viewoptions is null, we're getting posts for the my blogs area,
        // and we should get all posts & show drafts first.  Otherwise it's a
        // blog in a view, and we should only get published posts.

        $from = "
            FROM {artefact} a LEFT JOIN {artefact_blog_blogpost} bp ON a.id = bp.blogpost
            WHERE a.artefacttype = 'blogpost' AND a.parent = ?";

        if (!is_null($viewoptions)) {
            if (isset($viewoptions['before'])) {
                $from .= " AND a.ctime < '{$viewoptions['before']}'";
630
            }
631
632
            $from .= ' AND bp.published = 1';
        }
633

634
635
636
637
638
        $results['count'] = count_records_sql('SELECT COUNT(*) ' . $from, array($id));

        $data = get_records_sql_assoc('
            SELECT
                a.id, a.title, a.description, a.author, a.authorname, ' .
639
640
                db_format_tsfield('a.ctime', 'ctime') . ', ' . db_format_tsfield('a.mtime', 'mtime') . ',
                a.locked, bp.published, a.allowcomments ' . $from . '
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
            ORDER BY bp.published ASC, a.ctime DESC',
            array($id),
            $offset, $limit
        );

        if (!$data) {
            $results['data'] = array();
            return $results;
        }

        // Get the attached files.
        $postids = array_map(create_function('$a', 'return $a->id;'), $data);
        $files = ArtefactType::attachments_from_id_list($postids);
        if ($files) {
            safe_require('artefact', 'file');
            foreach ($files as &$file) {
                $file->icon = call_static_method(generate_artefact_class_name($file->artefacttype), 'get_icon', array('id' => $file->attachment));
                $data[$file->artefact]->files[] = $file;
            }
        }

        if ($tags = ArtefactType::tags_from_id_list($postids)) {
            foreach($tags as &$at) {
                $data[$at->artefact]->tags[] = $at->tag;
            }
        }

668
669
670
671
672
673
674
        // Get comment counts
        if (!empty($viewoptions['countcomments'])) {
            safe_require('artefact', 'comment');
            $viewids = array();
            $commentcounts = ArtefactTypeComment::count_comments($viewids, array_keys($data));
        }

675
676
677
678
679
680
        // Format dates properly
        foreach ($data as &$post) {
            if (is_null($viewoptions)) {
                // My Blogs area: create forms for publishing & deleting posts.
                if (!$post->published) {
                    $post->publish = ArtefactTypeBlogpost::publish_form($post->id);
681
                }
682
                $post->delete = ArtefactTypeBlogpost::delete_form($post->id);
683
            }
684
685
686
            else {
                $by = $post->author ? display_default_name($post->author) : $post->authorname;
                $post->postedby = get_string('postedbyon', 'artefact.blog', $by, format_date($post->ctime));
687
688
689
                if (isset($commentcounts)) {
                    $post->commentcount = isset($commentcounts[$post->id]) ? $commentcounts[$post->id]->comments : 0;
                }
690
691
692
            }
            $post->ctime = format_date($post->ctime, 'strftimedaydatetime');
            $post->mtime = format_date($post->mtime);
693
        }
Alastair Pharo's avatar
Alastair Pharo committed
694

695
696
697
        $results['data'] = array_values($data);

        return $results;
698
699
    }

700
701
702
703
704
705
706
707
708
    /**
     * This function renders a list of posts as html
     *
     * @param array posts
     * @param string template
     * @param array options
     * @param array pagination
     */
    public function render_posts(&$posts, $template, $options, $pagination) {
709
        $smarty = smarty_core();
710
        $smarty->assign('options', $options);
711
712
        $smarty->assign('posts', $posts['data']);

713
714
        $posts['tablerows'] = $smarty->fetch($template);

715
        if ($posts['limit'] && $pagination) {
716
            $pagination = build_pagination(array(
717
718
719
720
721
722
723
724
725
726
727
728
729
730
                'id' => $pagination['id'],
                'class' => 'center',
                'datatable' => $pagination['datatable'],
                'url' => $pagination['baseurl'],
                'jsonscript' => $pagination['jsonscript'],
                'count' => $posts['count'],
                'limit' => $posts['limit'],
                'offset' => $posts['offset'],
                'numbersincludefirstlast' => false,
                'resultcounttextsingular' => get_string('post', 'artefact.blog'),
                'resultcounttextplural' => get_string('posts', 'artefact.blog'),
            ));
            $posts['pagination'] = $pagination['html'];
            $posts['pagination_js'] = $pagination['javascript'];
731
        }
Alastair Pharo's avatar
Alastair Pharo committed
732
733
    }

734
    /** 
Alastair Pharo's avatar
Alastair Pharo committed
735
736
737
738
739
740
741
742
743
744
    /**
     * This function creates a new blog post.
     *
     * @param User
     * @param array
     */
    public static function new_post(User $user, array $values) {
        $artefact = new ArtefactTypeBlogPost();
        $artefact->set('title', $values['title']);
        $artefact->set('description', $values['description']);
Alastair Pharo's avatar
Alastair Pharo committed
745
        $artefact->set('published', $values['published']);
Alastair Pharo's avatar
Alastair Pharo committed
746
        $artefact->set('owner', $user->get('id'));
747
        $artefact->set('parent', $values['parent']);
Alastair Pharo's avatar
Alastair Pharo committed
748
        $artefact->commit();
749
        return true;
750
    }
Alastair Pharo's avatar
Alastair Pharo committed
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766

    /** 
     * This function updates an existing blog post.
     *
     * @param User
     * @param array
     */
    public static function edit_post(User $user, array $values) {
        $artefact = new ArtefactTypeBlogPost($values['id']);
        if ($user->get('id') != $artefact->get('owner')) {
            return false;
        }

        $artefact->set('title', $values['title']);
        $artefact->set('description', $values['description']);
        $artefact->set('published', $values['published']);
767
        $artefact->set('tags', $values['tags']);
Alastair Pharo's avatar
Alastair Pharo committed
768
769
770
771
        $artefact->commit();
        return true;
    }

772

773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
    public static function publish_form($id) {
        return pieform(array(
            'name' => 'publish_' . $id,
            'successcallback' => 'publish_submit',
            'jsform' => true,
            'jssuccesscallback' => 'publish_success',
            'renderer' => 'oneline',
            'elements' => array(
                'publish' => array(
                    'type' => 'hidden',
                    'value' => $id,
                    'help' => true,
                ),
                'submit' => array(
                    'type' => 'submit',
788
                    'class' => 'publish',
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
                    'value' => get_string('publish', 'artefact.blog'),
                ),
            ),
        ));
    }


    public static function delete_form($id) {
        return pieform(array(
            'name' => 'delete_' . $id,
            'successcallback' => 'delete_submit',
            'jsform' => true,
            'jssuccesscallback' => 'delete_success',
            'renderer' => 'oneline',
            'elements' => array(
                'delete' => array(
                    'type' => 'hidden',
                    'value' => $id,
                    'help' => true,
                ),
                'submit' => array(
Evonne Cheung's avatar
Evonne Cheung committed
810
                    'class' => 'icon btn-del',
811
812
813
814
815
816
817
818
819
                    'type' => 'submit',
                    'value' => get_string('delete', 'artefact.blog'),
                    'confirm' => get_string('deleteblogpost?', 'artefact.blog'),
                ),
            ),
        ));
    }


Alastair Pharo's avatar
Alastair Pharo committed
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
    /**
     * This function publishes the blog post.
     *
     * @return boolean
     */
    public function publish() {
        if (!$this->id) {
            return false;
        }
        
        $data = (object)array(
            'blogpost'  => $this->id,
            'published' => 1
        );

        if (get_field('artefact_blog_blogpost', 'COUNT(*)', 'blogpost', $this->id)) {
            update_record('artefact_blog_blogpost', $data, 'blogpost');
        }
        else {
            insert_record('artefact_blog_blogpost', $data);
        }
        return true;
    }
843

844
    
Martyn Smith's avatar
Martyn Smith committed
845
846
847
848
849
850
851
    public static function get_links($id) {
        $wwwroot = get_config('wwwroot');

        return array(
            '_default'                                  => $wwwroot . 'artefact/blog/post.php?blogpost=' . $id,
        );
    }
852
853
854
855
856
857
858
859
860
861

    public function update_artefact_references(&$view, &$template, &$artefactcopies, $oldid) {
        parent::update_artefact_references($view, $template, $artefactcopies, $oldid);
        // Attach copies of the files that were attached to the old post.
        // Update <img> tags in the post body to refer to the new image artefacts.
        $regexp = array();
        $replacetext = array();
        if (isset($artefactcopies[$oldid]->oldattachments)) {
            foreach ($artefactcopies[$oldid]->oldattachments as $a) {
                if (isset($artefactcopies[$a])) {
862
                    $this->attach($artefactcopies[$a]->newid);
863
864
865
866
867
868
869
870
                }
                $regexp[] = '#<img([^>]+)src="' . get_config('wwwroot') . 'artefact/file/download.php\?file=' . $a . '"#';
                $replacetext[] = '<img$1src="' . get_config('wwwroot') . 'artefact/file/download.php?file=' . $artefactcopies[$a]->newid . '"';
            }
            $this->set('description', preg_replace($regexp, $replacetext, $this->get('description')));
        }
    }

871
872
873
874
875
    /**
     * During the copying of a view, we might be allowed to copy
     * blogposts but not the containing blog.  We need to create a new
     * blog to hold the copied posts.
     */
876
    public function default_parent_for_copy(&$view, &$template, $artefactstoignore) {
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
        static $blogid;

        if (!empty($blogid)) {
            return $blogid;
        }

        $blogname = get_string('viewposts', 'artefact.blog', $view->get('id'));
        $data = (object) array(
            'title'       => $blogname,
            'description' => get_string('postscopiedfromview', 'artefact.blog', $template->get('title')),
            'owner'       => $view->get('owner'),
            'group'       => $view->get('group'),
            'institution' => $view->get('institution'),
        );
        $blog = new ArtefactTypeBlog(0, $data);
        $blog->commit();

        $blogid = $blog->get('id');

        return $blogid;
    }
898
899
900
901
902
903
904
905

    /**
     * Looks through the blog post text for links to download artefacts, and 
     * returns the IDs of those artefacts.
     */
    public function get_referenced_artefacts_from_postbody() {
        return artefact_get_references_in_html($this->get('description'));
    }
906
}
907

908

909
?>