lib.php 29 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<?php
/**
 * This program is part of Mahara
 *
 *  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 2 of the License, or
 *  (at your option) any later version.
 *
 *  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.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
 *
 * @package    mahara
 * @subpackage artefact-blog
 * @author     Alastair Pharo <alastair@catalyst.net.nz>
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL
 * @copyright  (C) 2006,2007 Catalyst IT Ltd http://catalyst.net.nz
 *
 */

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',
        );
    }

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

    public static function menu_items() {
        return array(
Martyn Smith's avatar
Martyn Smith committed
47
48
            array(
                'name' => 'myblogs',
49
                'link' => '',
Martyn Smith's avatar
Martyn Smith committed
50
            )
51
52
        );
    }
53
54
55
56

    public static function get_toplevel_artefact_types() {
        return array('blog');
    }
57
58
59
60
61

    public static function get_cron() {
        return array(
            (object)array(
                'callfunction' => 'clean_post_files',
Richard Mansfield's avatar
Richard Mansfield committed
62
63
                'hour'         => '4',
                'minute'       => '40'
64
65
66
67
68
69
70
71
72
            )
        );
    }

    /**
     * This function cleans out any files that have been uploaded, but which
     * are not associated with a blog, because of an aborted blog creation.
     */
    public static function clean_post_files() {
73

Richard Mansfield's avatar
Richard Mansfield committed
74
75
76
77
78
79
80
81
82
83
84
85
        $bloguploadbase = get_config('dataroot') . ArtefactTypeBlogPost::$blogattachmentroot;
        if (!$basedir = opendir($bloguploadbase)) {
            throw new Exception('Unable to read blog upload directory '.$bloguploadbase);
        }

        $currenttime = time();

        // Read through all the upload session directories
        while (false !== ($sessionupload = readdir($basedir))) {
            if ($sessionupload != "." && $sessionupload != "..") {
                $sessionupload = $bloguploadbase . $sessionupload;
                $subdir = opendir($sessionupload);
86

Richard Mansfield's avatar
Richard Mansfield committed
87
88
89
90
91
92
93
94
95
96
97
98
99
                // Remove all files older than the session timeout plus two hours.
                while (false !== ($uploadfile = readdir($subdir))) {
                    if ($uploadfile != "." && $uploadfile != "..") {
                        $uploadfile = $sessionupload . '/' . $uploadfile;
                        if ($currenttime - filemtime($uploadfile) > get_config('session_timeout') + 7200) {
                            unlink($uploadfile);
                        }
                    }
                }

                closedir($subdir);
                rmdir($sessionupload);
            }
100
        }
Richard Mansfield's avatar
Richard Mansfield committed
101
102

        closedir($basedir);
103
    }
104
105
106
107
108
109
110
}

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

Alastair Pharo's avatar
Alastair Pharo committed
111
112
113
114
115
    /**
     * This constant gives the per-page pagination for listing blogs.
     */
    const pagination = 10;
    
116
117
118
    
    /** 
     * Whether comments are allowed on this blog or not.
Alastair Pharo's avatar
Alastair Pharo committed
119
120
     *
     * @var boolean
121
122
123
124
125
     */
    protected $commentsallowed = false;

    /** 
     * Whether the blog owner will be notified of comments or not.
Alastair Pharo's avatar
Alastair Pharo committed
126
127
     *
     * @var boolean
128
129
130
     */
    protected $commentsnotify = false;

131
132
133
134
135
136
137
    /**
     * We override the constructor to fetch the extra data.
     *
     * @param integer
     * @param object
     */
    public function __construct($id = 0, $data = null) {
138
        global $USER;
139
140
        parent::__construct($id, $data);

141
        if (!$data) {
142
143
144
145
146
147
            if ($this->id) {
                if ($blogdata = get_record('artefact_blog_blog', 'blog', $this->id)) {
                    foreach($blogdata as $name => $value) {
                        if (property_exists($this, $name)) {
                            $this->$name = $value;
                        }
148
                    }
149
                }
150
151
152
153
                else {
                    // This should never happen unless the user is playing around with blog IDs in the location bar or similar
                    throw new ArtefactNotFoundException(get_string('blogdoesnotexist', 'artefact.blog'));
                }
154
            }
155
        }
156
157
158
159

        if (empty($this->id)) {
            $this->container = 1;
        }
160
161
162
        else if ($this->owner != $USER->get('id')) {
            throw new AccessDeniedException(get_string('youarenottheownerofthisblogpost', 'artefact.blog'));
        }
163
164
165
166
    }

    public function is_container() {
        return true;
167
    }
Alastair Pharo's avatar
Alastair Pharo committed
168
169

    /**
170
171
172
     * 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
173
     */
174
    public function commit() {
175
176
177
178
179
180
181
182
183
184
185
186
187
188
        // 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();

        // Reset dirtyness for the time being.
        $this->dirty = true;

Alastair Pharo's avatar
Alastair Pharo committed
189
        $data = (object)array(
190
191
192
193
194
195
196
197
198
199
200
201
202
            'blog'            => $this->get('id'),
            'commentsallowed' => ($this->get('commentsallowed') ? 1 : 0),
            'commentsnotify'  => ($this->get('commentsnotify') ? 1 : 0)
        );

        if ($new) {
            insert_record('artefact_blog_blog', $data);
        }
        else {
            update_record('artefact_blog_blog', $data, 'blog');
        }

        $this->dirty = false;
203
204
    }

Alastair Pharo's avatar
Alastair Pharo committed
205
    /**
206
207
     * This function extends ArtefactType::delete() by deleting blog-specific
     * data.
Alastair Pharo's avatar
Alastair Pharo committed
208
     */
209
    public function delete() {
210
211
212
213
214
215
216
217
218
        if (empty($this->id)) {
            return;
        }

        // Delete the blog-specific data.
        delete_records('artefact_blog_blog', 'blog', $this->id);

        // Delete the artefact and all children.
        parent::delete();
219
220
    }

221
222
223
224
225
226
    /**
     * This function overrides the default functionality for listing children,
     * using a smarty template and tablerenderer stuff.
     *
     * @param array
     * @return string
Alastair Pharo's avatar
Alastair Pharo committed
227
     */
228
229
230
231
232
233
234
    protected function listchildren($options) {
        // This is because if there are multiple blocks on a page, they need separate
        // js variables.
        $blockid = isset($options['blockid'])
            ? $options['blockid']
            : mt_rand();

235
236
        $this->add_to_render_path($options);

237
238
        // This uses the above blockid, so needs to be inlcuded after.
        $javascript = require(get_config('docroot') . 'artefact/blog/render/blog_listchildren.js.php');
239

240
241
242
243
        $smarty = smarty();
        $smarty->assign('artefact', $this);
        $smarty->assign('blockid', $blockid);
        $smarty->assign_by_ref('options', $options);
244
        return array('html' => $smarty->fetch('artefact:blog:render/blog_listchildren.tpl'),
245
                     'javascript' => $javascript);
246
247
    }

248

249
250
    public function describe_size() {
        return $this->count_children() . ' ' . get_string('posts', 'artefact.blog');
251
252
253
    }


254
255
256
257
258
259
260
261
262
    /**
     * This function implements the render_full functionality for blogs.
     * Rendering full involves rendering blog posts with render_full, and
     * possibly some other stuff.
     *
     * @param array
     * @return string
     */
    function render_full($options) {
Alastair Pharo's avatar
Alastair Pharo committed
263
264
265
266
267
268
        // This is because if there are multiple blocks on a page, they need separate
        // js variables.
        $blockid = isset($options['blockid'])
            ? $options['blockid']
            : mt_rand();

269
270
        $this->add_to_render_path($options);

Alastair Pharo's avatar
Alastair Pharo committed
271
272
273
        // This uses the above blockid, so needs to be inlcuded after.
        $javascript = require(get_config('docroot') . 'artefact/blog/render/blog_renderfull.js.php');
        
274
        $smarty = smarty();
275
276
277
278
279
280
281
282
        if (isset($options['viewid'])) {
            $smarty->assign('artefacttitle', '<a href="' . get_config('wwwroot') . 'view/view.php?view=' 
                                             . $options['viewid'] . '&artefact=' . $this->get('id')
                                             . '">' . $this->get('title') . '</a>');
        }
        else {
            $smarty->assign('artefacttitle', $this->get('title'));
        }
Alastair Pharo's avatar
Alastair Pharo committed
283
        $smarty->assign('blockid', $blockid);
284
        $smarty->assign_by_ref('options', $options);
285
        return array('html' => $smarty->fetch('artefact:blog:render/blog_renderfull.tpl'),
286
                     'javascript' => $javascript);
287
    }
Richard Mansfield's avatar
Richard Mansfield committed
288

289
290
    protected function get_metadata($options=array()) {
        $data = parent::get_metadata($options);
Richard Mansfield's avatar
Richard Mansfield committed
291
292
293
294
295
296
        $data['description'] = array('name' => get_string('description'),
                                     'value' => $this->get('description'));
        $data['type']['value'] = get_string($this->get('artefacttype'), 'artefact.blog');
        $data['size'] = array('name' => get_string('size'),
                              'value' => $this->count_children() . ' ' 
                                         . get_string('posts', 'artefact.blog'));
Martyn Smith's avatar
Martyn Smith committed
297
298
299
300
301

        if (isset($options['viewid']) && artefact_in_view($id = $this->get('id'), $options['viewid'])) {
            $data['title']['value'] = '<a href="' . get_config('wwwroot') . 'view/view.php?view=' . $options['viewid'] . '&artefact=' . $id . '">' . $data['title']['value'] . '</a>';
        }

Richard Mansfield's avatar
Richard Mansfield committed
302
303
304
305
306
        return $data;
    }

    protected function render_metadata($options) {
        $smarty = smarty();
Martyn Smith's avatar
Martyn Smith committed
307
        $smarty->assign('PROPERTIES', $this->get_metadata($options));
308
309
        return array('html' => $smarty->fetch('artefact:blog:render/blog_rendermetadata.tpl'),
                     'javascript' => null);
Richard Mansfield's avatar
Richard Mansfield committed
310
311
    }

312
                
313
314
315
316
    public function get_icon() {
    }

    public static function get_render_list() {
317
        return array_values(array_unique(array_merge(
318
319
320
321
322
            array(
                FORMAT_ARTEFACT_LISTCHILDREN,
                FORMAT_ARTEFACT_RENDERFULL
            ),
            parent::get_render_list()
323
        )));
324
325
    }

Nigel McNie's avatar
Nigel McNie committed
326
    public static function is_singular() {
Penny Leach's avatar
Penny Leach committed
327
328
329
        return false;
    }

Alastair Pharo's avatar
Alastair Pharo committed
330
    public static function collapse_config() {
331
332
    }

Alastair Pharo's avatar
Alastair Pharo committed
333
334
335
336
337
338
339
340
341
    /**
     * This function returns a list of the given user's blogs.
     *
     * @param User
     * @return array (count: integer, data: array)
     */
    public static function get_blog_list(User $user, $limit = self::pagination, $offset = 0) {
        ($result = get_records_sql_array("
         SELECT id, title, description
342
         FROM {artefact}
Alastair Pharo's avatar
Alastair Pharo committed
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
         WHERE owner = ?
          AND artefacttype = 'blog'
         ORDER BY title
         LIMIT ? OFFSET ?", array($user->get('id'), $limit, $offset)))
            || ($result = array());

        $count = (int)get_field('artefact', 'COUNT(*)', 'owner', $user->get('id'), 'artefacttype', 'blog');

        return array($count, $result);
    }

    /**
     * This function creates a new blog.
     *
     * @param User
     * @param array
     */
Alastair Pharo's avatar
Alastair Pharo committed
360
    public static function new_blog(User $user, array $values) {
Alastair Pharo's avatar
Alastair Pharo committed
361
362
363
364
        $artefact = new ArtefactTypeBlog();
        $artefact->set('title', $values['title']);
        $artefact->set('description', $values['description']);
        $artefact->set('owner', $user->get('id'));
365
366
        $artefact->set('commentsallowed', $values['commentsallowed'] ? true : false);
        $artefact->set('commentsnotify', $values['commentsnotify'] ? true : false);
367
        $artefact->set('tags', $values['tags']);
Alastair Pharo's avatar
Alastair Pharo committed
368
        $artefact->commit();
369
    }
Alastair Pharo's avatar
Alastair Pharo committed
370
371
372
373
374
375
376
377
378
379
380
381
382

    /**
     * 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']);
383
384
385
386
        if ($user->get('id') != $artefact->get('owner')) {
            return;
        }
        
Alastair Pharo's avatar
Alastair Pharo committed
387
388
389
390
        $artefact->set('title', $values['title']);
        $artefact->set('description', $values['description']);
        $artefact->set('commentsallowed', $values['commentsallowed'] ? true : false);
        $artefact->set('commentsnotify', $values['commentsnotify'] ? true : false);
391
        $artefact->set('tags', $values['tags']);
Alastair Pharo's avatar
Alastair Pharo committed
392
393
        $artefact->commit();
    }
394
395
396
397

    public function public_feedback_allowed() {
        return $this->get('commentsallowed');
    }
398
399
400
401
402
403


    public function feedback_notify_owner() {
        return $this->get('commentsnotify');
    }

Martyn Smith's avatar
Martyn Smith committed
404
405
    public static function get_links($id) {
        $wwwroot = get_config('wwwroot');
406

Martyn Smith's avatar
Martyn Smith committed
407
408
409
410
411
        return array(
            '_default'                                  => $wwwroot . 'artefact/blog/view/?id=' . $id,
            get_string('blogsettings', 'artefact.blog') => $wwwroot . 'artefact/blog/settings/?id=' . $id,
        );
    }
412
413
414
415
416
417
418
}

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

Alastair Pharo's avatar
Alastair Pharo committed
419
420
421
422
423
    /**
     * This gives the number of blog posts to display at a time.
     */
    const pagination = 10;

424
    /**
Alastair Pharo's avatar
Alastair Pharo committed
425
426
427
428
429
430
431
432
433
434
435
436
437
     * 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) {
438
        global $USER;
Alastair Pharo's avatar
Alastair Pharo committed
439
440
        parent::__construct($id, $data);

441
        if (!$data) {
442
443
444
445
446
447
            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;
                        }
448
                    }
Alastair Pharo's avatar
Alastair Pharo committed
449
                }
450
451
452
453
                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'));
                }
454
455
456
            }
        }

457
        if ($this->id && $this->owner != $USER->get('id')) {
458
            throw new AccessDeniedException(get_string('youarenottheownerofthisblogpost', 'artefact.blog'));
Alastair Pharo's avatar
Alastair Pharo committed
459
460
461
462
463
464
        }
    }

    /**
     * This function extends ArtefactType::commit() by adding additional data
     * into the artefact_blog_blogpost table.
465
     */
466
    public function commit() {
Alastair Pharo's avatar
Alastair Pharo committed
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
        if (empty($this->dirty)) {
            return;
        }

        $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');
        }

        $this->dirty = false;
490
491
    }

492
    /**
Alastair Pharo's avatar
Alastair Pharo committed
493
494
     * This function extends ArtefactType::delete() by also deleting anything
     * that's in blogpost.
495
     */
496
    public function delete() {
Alastair Pharo's avatar
Alastair Pharo committed
497
498
499
        if (empty($this->id)) {
            return;
        }
500

Martyn Smith's avatar
Martyn Smith committed
501
        delete_records('artefact_blog_blogpost_file', 'blogpost', $this->id);
Alastair Pharo's avatar
Alastair Pharo committed
502
503
504
505
        delete_records('artefact_blog_blogpost', 'blogpost', $this->id);
      
        parent::delete();
    }
506
  
507
508
    public function describe_size() {
        return $this->count_attachments() . ' ' . get_string('attachments', 'artefact.blog');
509
510
511
512
513
514
515
516
517
    }

    /**
     * This function displays the blogpost in renderfull mode.
     *
     * @param array
     */
    protected function render_full($options) {
        $smarty = smarty();
518
519
520
521
522
523
524
525
        if (isset($options['viewid'])) {
            $smarty->assign('artefacttitle', '<a href="' . get_config('wwwroot') . 'view/view.php?view=' 
                                             . $options['viewid'] . '&artefact=' . $this->get('id')
                                             . '">' . $this->get('title') . '</a>');
        }
        else {
            $smarty->assign('artefacttitle', $this->get('title'));
        }
526
527
528
529
530
531
532

        // We need to make sure that the images in the post have the right viewid associated with them
        $postcontent = $this->get('description');
        if (isset($options['viewid'])) {
            $postcontent = preg_replace('#(<img src=".*artefact/file/download\.php\?file=\d+)#', '\1&amp;view=' . $options['viewid'], $postcontent);
        }
        $smarty->assign('artefactdescription', $postcontent);
533
        $smarty->assign('artefact', $this);
534
535
        $attachments = $this->get_attached_files();
        if ($attachments) {
536
            $this->add_to_render_path($options);
537
            require_once('artefact.php');
538
            foreach ($attachments as &$attachment) {
539
                $f = artefact_instance_from_id($attachment->id);
540
541
                $rf = $f->render(FORMAT_ARTEFACT_LISTSELF, $options);
                $attachment->content = $rf['html'];
542
543
544
            }
            $smarty->assign('attachments', $attachments);
        }
545
546
547
        $smarty->assign('postedbyon', get_string('postedbyon', 'artefact.blog',
                                                 display_name($this->owner),
                                                 format_date($this->ctime)));
548
549
        return array('html' => $smarty->fetch('artefact:blog:render/blogpost_renderfull.tpl'),
                     'javascript' => null);
550
551
    }

552
553
554
555
556
557
558
559
560
561
562
563
    public function attachment_id_list() {
        if (!$list = get_column('artefact_blog_blogpost_file', 'file', 'blogpost', $this->get('id'))) {
            $list = array();
        }
        return $list;
    }

    public function attach_file($artefactid) {
        $data = new StdClass;
        $data->blogpost = $this->get('id');
        $data->file = $artefactid;
        insert_record('artefact_blog_blogpost_file', $data);
564
565
566
567
568

        $data->artefact = $data->file;
        $data->parent = $data->blogpost;
        $data->dirty = true;
        insert_record('artefact_parent_cache', $data);
569
570
571
572
    }

    public function detach_file($artefactid) {
        delete_records('artefact_blog_blogpost_file', 'blogpost', $this->get('id'), 'file', $artefactid);
573
        delete_records('artefact_parent_cache', 'parent', $this->get('id'), 'artefact', $artefactid);
574
575
    }

Richard Mansfield's avatar
Richard Mansfield committed
576
577
578
579
580
581

    protected function count_attachments() {
        return count_records('artefact_blog_blogpost_file', 'blogpost', $this->get('id'));
    }


582
583
    protected function get_metadata($options=array()) {
        $data = parent::get_metadata($options);
Richard Mansfield's avatar
Richard Mansfield committed
584
585
586
587
588
589
        unset($data['description']);
        unset($data['size']);
        $data['type']['value'] = get_string($this->get('artefacttype'), 'artefact.blog');
        $data['attachments'] = array('name' => get_string('attachments', 'artefact.blog'),
                                     'value' => $this->count_attachments() . ' ' 
                                               . get_string('files', 'artefact.file'));
590
591
592
        if (isset($options['viewid']) && artefact_in_view($id = $this->get('id'), $options['viewid'])) {
            $data['title']['value'] = '<a href="' . get_config('wwwroot') . 'view/view.php?view=' . $options['viewid'] . '&artefact=' . $id . '">' . $data['title']['value'] . '</a>';
        }
Richard Mansfield's avatar
Richard Mansfield committed
593
594
595
596
        return $data;
    }

                
597
    protected function render_metadata($options=array()) {
Richard Mansfield's avatar
Richard Mansfield committed
598
        $smarty = smarty();
599
        $smarty->assign('PROPERTIES', $this->get_metadata($options));
600
601
        return array('html' => $smarty->fetch('artefact:blog:render/blog_rendermetadata.tpl'),
                     'javascript' => null);
Richard Mansfield's avatar
Richard Mansfield committed
602
603
604
605
    }



606
607
608
609
    public function get_icon() {
    }

    public static function get_render_list() {
610
        return array_values(array_unique(array_merge(
611
612
613
614
615
            array(
                FORMAT_ARTEFACT_LISTSELF,
                FORMAT_ARTEFACT_RENDERFULL
            ),
            parent::get_render_list()
616
        )));
617
618
    }

Nigel McNie's avatar
Nigel McNie committed
619
    public static function is_singular() {
Penny Leach's avatar
Penny Leach committed
620
621
622
        return false;
    }

Alastair Pharo's avatar
Alastair Pharo committed
623
    public static function collapse_config() {
624
625
    }

Alastair Pharo's avatar
Alastair Pharo committed
626
627
628
629
630
631
632
633
634
    /**
     * This function returns a list of the current user's blog posts, for the
     * given blog.
     *
     * @param User
     * @param integer
     * @param integer
     */
    public static function get_posts(User $user, $id, $limit = self::pagination, $offset = 0) {
635
        ($result = get_records_sql_assoc("
Alastair Pharo's avatar
Alastair Pharo committed
636
         SELECT a.id, a.title, a.description, a.ctime, a.mtime, bp.published
637
638
         FROM {artefact} a
          LEFT OUTER JOIN {artefact_blog_blogpost} bp
Alastair Pharo's avatar
Alastair Pharo committed
639
640
641
642
           ON a.id = bp.blogpost
         WHERE a.parent = ?
          AND a.artefacttype = 'blogpost'
          AND a.owner = ?
643
         ORDER BY bp.published ASC, a.ctime DESC
Alastair Pharo's avatar
Alastair Pharo committed
644
645
646
647
648
649
650
651
         LIMIT ? OFFSET ?;", array(
            $id,
            $user->get('id'),
            $limit,
            $offset
        )))
            || ($result = array());

652
653
654
655
        $count = (int)get_field('artefact', 'COUNT(*)', 'owner', $user->get('id'), 
                                'artefacttype', 'blogpost', 'parent', $id);

        // Get the attached files.
656
        if (count($result) > 0) {
657
658
659
660
            $idlist = implode(', ', array_map(create_function('$a', 'return $a->id;'), $result));
            $files = get_records_sql_array('
               SELECT
                  bf.blogpost, bf.file, a.artefacttype, a.title, a.description
661
662
               FROM {artefact_blog_blogpost_file} bf
                  INNER JOIN {artefact} a ON bf.file = a.id
663
664
665
666
667
668
669
               WHERE bf.blogpost IN (' . $idlist . ')', '');
            if ($files) {
                foreach ($files as $file) {
                    $result[$file->blogpost]->files[] = $file;
                }
            }
        }
Alastair Pharo's avatar
Alastair Pharo committed
670

671
        return array($count, array_values($result));
Alastair Pharo's avatar
Alastair Pharo committed
672
673
    }

674
675
676
677
678
679
680
681
    /** 
     * This function returns a list of rendered blog posts.
     *
     * @param integer
     * @param integer
     * @param integer
     * @param integer
     */
682
    public static function render_posts($format, $options, $id, $limit = self::pagination, $offset = 0) {
Alastair Pharo's avatar
Alastair Pharo committed
683
        ($postids = get_records_sql_array("
684
         SELECT a.id
685
686
         FROM {artefact} a
          LEFT OUTER JOIN {artefact_blog_blogpost} bp
687
688
689
690
           ON a.id = bp.blogpost
         WHERE a.parent = ?
          AND bp.published = 1
         ORDER BY a.ctime DESC
Alastair Pharo's avatar
Alastair Pharo committed
691
692
         LIMIT ? OFFSET ?;", array($id, $limit, $offset)))
            || ($postids = array());
693
694
695
696
697
698

        $posts = array();
        foreach($postids as $postid) {
            $blogpost = new ArtefactTypeBlogPost($postid->id);
            $posts[] = array(
                'id' => $postid->id,
699
                'content' => $blogpost->render($format, (array) $options)
700
701
702
            );
        }

Alastair Pharo's avatar
Alastair Pharo committed
703
704
        $count = (int)get_field_sql("
         SELECT COUNT(*)
705
706
         FROM {artefact} a
          LEFT OUTER JOIN {artefact_blog_blogpost} bp
Alastair Pharo's avatar
Alastair Pharo committed
707
708
709
           ON a.id = bp.blogpost
         WHERE a.parent = ?
          AND bp.published = 1", array($id));
710
711
712
713

        return array($count, $posts);
    }

Alastair Pharo's avatar
Alastair Pharo committed
714
715
716
717
718
719
720
721
722
723
    /**
     * 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
724
        $artefact->set('published', $values['published']);
Alastair Pharo's avatar
Alastair Pharo committed
725
        $artefact->set('owner', $user->get('id'));
726
        $artefact->set('parent', $values['parent']);
Alastair Pharo's avatar
Alastair Pharo committed
727
        $artefact->commit();
728
        return true;
729
    }
Alastair Pharo's avatar
Alastair Pharo committed
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745

    /** 
     * 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']);
746
        $artefact->set('tags', $values['tags']);
Alastair Pharo's avatar
Alastair Pharo committed
747
748
749
750
        $artefact->commit();
        return true;
    }

751
752
753
    // Where to store temporary blog post files under dataroot
    static $blogattachmentroot = 'artefact/blog/uploads/';

754
755
756
757
758
759
760

    public static function get_temp_file_path($createid, $uploadnumber) {
        return get_config('dataroot') . self::$blogattachmentroot 
            . session_id() . $createid . '/' . $uploadnumber;
    }


761
762
763
764
765
766
767
768
    /**
     * Returns the size of a temporary attachment
     */
    public static function temp_attachment_size($createid, $uploadnumber) {
        return filesize(self::get_temp_file_path($createid, $uploadnumber));
    }


769
770
771
772
    /** 
     * This function saves an uploaded file to a temporary directory in dataroot
     *
     */
773
    public static function save_attachment_temporary($inputname, $dirname, $filename) {
774
775
        require_once('uploadmanager.php');
        $um = new upload_manager($inputname);
776
777
778
        $result = new StdClass;
        $tempdir = self::$blogattachmentroot . $dirname;
        $result->error = $um->process_file_upload($tempdir, $filename);
779
        $result->oldextension = $um->original_filename_extension();
780
781
782
783
        $tempfile = $tempdir . '/' . $filename;
        safe_require('artefact', 'file');
        $result->type = ArtefactTypeFile::detect_artefact_type($tempfile);
        return $result;
784
785
786
    }


787
788
789
    /**
     * Save a temporary uploaded file to the myfiles area.
     */
790
    public function save_attachment($directory, $filename, $title, $description, $oldextension, $tags) {
791
792
793
794
795
796
797

        // Create the blogfiles folder if it doesn't exist yet.
        $blogfilesid = self::blogfiles_folder_id();
        if (!$blogfilesid) {
            return false;
        }

798
799
800
801
802
803
804
        global $USER;

        safe_require('artefact', 'file');

        $data = new StdClass;
        $data->title = $title;
        $data->description = $description;
805
        $data->tags = $tags;
Richard Mansfield's avatar
Richard Mansfield committed
806
807
        $data->owner = $USER->get('id');
        $data->adminfiles = 0; // No admin blogs yet...
808
        $data->parent = $blogfilesid;
809
        $data->oldextension = $oldextension;
Richard Mansfield's avatar
Richard Mansfield committed
810
811
        
        $path = self::$blogattachmentroot . $directory . '/' . $filename;
812

Richard Mansfield's avatar
Richard Mansfield committed
813
        if (!$fileid = ArtefactTypeFile::save_file($path, $data)) {
814
815
            return false;
        }
816
817

        $this->attach_file($fileid);
818
        return $fileid;
819
820
821
822
823
824
825
826
827
    }

    public static function blogfiles_folder_id() {
        $name = get_string('blogfilesdirname', 'artefact.blog');
        $description = get_string('blogfilesdirdescription', 'artefact.blog');
        safe_require('artefact', 'file');
        return ArtefactTypeFolder::get_folder_id($name, $description);
    }

Alastair Pharo's avatar
Alastair Pharo committed
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
    /**
     * 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;
    }
851
852
853
854
855
856
857
858

    /**
     * This function returns a list of files attached to a post to use
     * when displaying or editing a blog post
     *
     * @return array
     */
    public function get_attached_files() {
859
        $list = get_records_sql_array('SELECT a.id, a.artefacttype, a.title, a.description 
860
861
            FROM {artefact_blog_blogpost_file} f
            INNER JOIN {artefact} a ON a.id = f.file
862
            WHERE f.blogpost = ' . $this->id, '');
863
864

        // load tags
Martyn Smith's avatar
Martyn Smith committed
865
866
867
868
        if ($list) {
            foreach ( $list as &$attachment ) {
                $attachment->tags = join(', ', get_column('artefact_tag', 'tag', 'artefact', $attachment->id));
            }
869
870
        }
        return $list;
871
    }
872

873
    public function public_feedback_allowed() {
874
875
876
877
        // Comments are not allowed on posts when the blog has
        // commentsallowed set to 0;
        $parent = get_field('artefact', 'parent', 'id', $this->get('id'));
        return get_field('artefact_blog_blog', 'commentsallowed', 'blog', $parent);
878
    }
879
    
880
    
881
882
883
884
885
886
887
    public function feedback_notify_owner() {
        // Notify owner of comments on posts when the blog has
        // commentsnotify set to 1;
        $parent = get_field('artefact', 'parent', 'id', $this->get('id'));
        return get_field('artefact_blog_blog', 'commentsnotify', 'blog', $parent);
    }
    
Martyn Smith's avatar
Martyn Smith committed
888
889
890
891
892
893
894
    public static function get_links($id) {
        $wwwroot = get_config('wwwroot');

        return array(
            '_default'                                  => $wwwroot . 'artefact/blog/post.php?blogpost=' . $id,
        );
    }
895
}
896
897

?>