-
Notifications
You must be signed in to change notification settings - Fork 29
/
Copy pathlocallib.php
5725 lines (5253 loc) · 219 KB
/
locallib.php
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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
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
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
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
294
295
296
297
298
299
300
301
302
303
304
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
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
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
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
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
630
631
632
633
634
635
636
637
638
639
640
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
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
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
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle 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.
//
// Moodle 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 Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Library of functions used by the oublog module.
*
* This contains functions that are called from within the oublog module only
* Functions that are also called by core Moodle are in {@link lib.php}
*
* @author Matt Clarkson <[email protected]>
* @author Sam Marshall <[email protected]>
* @author M Kassaei <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
* @package oublog
*/
require_once($CFG->libdir . '/portfolio/caller.php');
require_once($CFG->libdir . '/gradelib.php');
require_once($CFG->libdir . '/filelib.php');
/**#@+
* Constants defining the visibility levels of blog posts
*/
define('OUBLOG_VISIBILITY_COURSEUSER', 100);
define('OUBLOG_VISIBILITY_LOGGEDINUSER', 200);
define('OUBLOG_VISIBILITY_PUBLIC', 300);
/**#@-*/
/**#@+
* Constants defining the ability to post comments
*/
define('OUBLOG_COMMENTS_PREVENT', 0);
define('OUBLOG_COMMENTS_ALLOW', 1);
define('OUBLOG_COMMENTS_ALLOWPUBLIC', 2);
/**#@-*/
/**#@+
* Constants for the 'approval' field in modreated comments
*/
define('OUBLOG_MODERATED_UNSET', 0);
define('OUBLOG_MODERATED_APPROVED', 1);
define('OUBLOG_MODERATED_REJECTED', 2);
/**#@-*/
/**#@+
* Constant defining the max number of items in an RSS or Atom feed
*/
define('OUBLOG_MAX_FEED_ITEMS', 20);
/**#@-*/
/**#@+
* Constants defining the visibility for participation pages
*/
define('OUBLOG_USER_PARTICIPATION', 2);
define('OUBLOG_MY_PARTICIPATION', 1);
define('OUBLOG_NO_PARTICIPATION', 0);
define('OUBLOG_PARTICIPATION_PERPAGE', 50);
/**#@-*/
// Constants defining stats time filter.
define('OUBLOG_STATS_TIMEFILTER_ALL', 0);
define('OUBLOG_STATS_TIMEFILTER_MONTH', 1);
define('OUBLOG_STATS_TIMEFILTER_YEAR', 2);
// Constants defining grading options.
define('OUBLOG_NO_GRADING', 0);
define('OUBLOG_TEACHER_GRADING', 1);
define('OUBLOG_USE_RATING', 2);
/**#@+
* Constant defining the number of posts to display per page for export
*/
define('OUBLOG_POSTS_PER_PAGE_EXPORT', 50);
/**#@+
* Constant defining the max length of tags
*/
define('OUBLOG_EXPORT_TAGS_LENGTH', 40);
define('OUBLOG_TAGS_SHOW', 500);
/**
* Get a blog from a user id
*
* @param int $userid
* @return mixed Oublog object on success, false on failure
*/
function oublog_get_personal_blog($userid) {
global $CFG, $DB;
if (!$blog = $DB->get_record('oublog', array('global'=>1))) {
throw new moodle_exception('globalblogmissing', 'oublog');
}
if (!$oubloginstance = $DB->get_record('oublog_instances', array('oublogid'=>$blog->id, 'userid'=>$userid))) {
$user = $DB->get_record('user', array('id'=>$userid));
$a = (object) array('name' => fullname($user), 'displayname' => oublog_get_displayname($blog));
oublog_add_bloginstance($blog->id, $userid, get_string('defaultpersonalblogname', 'oublog', $a));
if (!$oubloginstance = $DB->get_record('oublog_instances', array('oublogid'=>$blog->id, 'userid'=>$user->id))) {
throw new moodle_exception('invalidblog', 'oublog');
}
}
return(array($blog, $oubloginstance));
}
/**
* Obtains the oublog object based on a post ID.
* @param int $postid Post ID
* @return object Moodle data object for oublog row, or false if not found
*/
function oublog_get_blog_from_postid($postid) {
global $DB;
$postid = (int)$postid;
return $DB->get_record_sql("
SELECT
o.*
FROM
{oublog_posts} p
INNER JOIN {oublog_instances} i on i.id = p.oubloginstancesid
INNER JOIN {oublog} o ON o.id = i.oublogid
WHERE
p.id= ? ", array($postid));
}
/**
* Checks if a user is allowed to view a blog. If not, will not return (calls
* an error function and exits).
* @param object $oublog
* @param object $context
* @param object $cm
* @return void
*/
function oublog_check_view_permissions($oublog, $context, $cm=null) {
global $COURSE, $PAGE, $DB;
$capability=$oublog->global ? 'mod/oublog:viewpersonal' : 'mod/oublog:view';
switch ($oublog->maxvisibility) {
case OUBLOG_VISIBILITY_PUBLIC:
if ($oublog->course == $COURSE->id or empty($oublog->course)) {
$oublogcourse = $COURSE;
} else {
$oublogcourse = $DB->get_record('course', array('id'=>$oublog->course),
'*', MUST_EXIST);
}
$PAGE->set_course($oublogcourse);
$PAGE->set_cm($cm, $oublogcourse);
$PAGE->set_pagelayout('incourse');
if ($oublog->global && isloggedin()) {
// Personal blog: Check view permission (if not logged in will see public posts).
if (!has_capability($capability, $context)) {
throw new moodle_exception('accessdenied', 'oublog');
}
}
return;
case OUBLOG_VISIBILITY_LOGGEDINUSER:
require_login(SITEID, false);
if ($oublog->course == $COURSE->id or empty($oublog->course)) {
$oublogcourse = $COURSE;
} else {
$oublogcourse = $DB->get_record('course', array('id'=>$oublog->course),
'*', MUST_EXIST);
}
$PAGE->set_course($oublogcourse);
$PAGE->set_cm($cm, $oublogcourse);
$PAGE->set_pagelayout('incourse');
// Check oublog:view cap
if (!has_capability($capability, $context)) {
throw new moodle_exception('accessdenied', 'oublog');
}
return;
case OUBLOG_VISIBILITY_COURSEUSER:
require_course_login($oublog->course, false, $cm);
// Check oublog:view cap
if (!has_capability($capability, $context)) {
throw new moodle_exception('accessdenied', 'oublog');
}
return;
default:
throw new moodle_exception('invalidvisibility', 'oublog');
}
}
/**
* Checks if user can post to the blog depending on time limits
* @param object $oublog
* @param context $context
* @return bool True if can post
*/
function oublog_can_post_now($oublog, $context) {
if (($oublog->postfrom == 0 || $oublog->postfrom <= time()) &&
($oublog->postuntil == 0 || $oublog->postuntil > time())) {
// Within time limits.
return true;
}
if ($oublog->global && $context->contextlevel != CONTEXT_SYSTEM) {
// Global blog override and check at system context.
$context = context_system::instance();
}
return has_capability('mod/oublog:ignorepostperiod', $context);
}
/**
* Determines whether the user can make a post to the given blog.
* @param $oublog Blog object
* @param $bloguserid Userid of person who owns blog (only needed for
* personal blog)
* @param $cm Course-module (only needed if not personal blog)
* @return bool True if user is allowed to make posts
*/
function oublog_can_post($oublog, $bloguserid=0, $cm=null) {
global $USER;
if ($oublog->global) {
if ($bloguserid==0) {
debugging('Calls to oublog_can_post for personal blogs must supply userid!', DEBUG_DEVELOPER);
}
// This needs to be your blog and you need the 'contributepersonal'
// permission at system level
return $bloguserid==$USER->id &&
has_capability('mod/oublog:contributepersonal',
context_system::instance());
} else {
// Need specific post permission in this blog
return has_capability('mod/oublog:post',
context_module::instance($cm->id));
}
}
/**
* Determines whether the user can comment on the given blog post, presuming
* that they are allowed to see it.
* @param $cm Course-module (null if personal blog)
* @param $oublog Blog object
* @param $post Post object
* @param bool $ignoretime True to ignore any comment time limits
* @return bool True if user is allowed to make comments
*/
function oublog_can_comment($cm, $oublog, $post, $ignoretime = false) {
global $USER;
if ($oublog->global) {
// Just need the 'contributepersonal' permission at system level, OR
// if you are not logged in but the blog allows public comments.
// Note that if you ARE logged in you must have the capability. This is
// because logged-in comments do not go through moderation, so we want
// to be able to prevent them by removing the capability. They will
// still be able to make comments by logging out, but these will then
// go through moderation.
$blogok =
(!isloggedin() && $oublog->allowcomments == OUBLOG_COMMENTS_ALLOWPUBLIC) ||
has_capability('mod/oublog:contributepersonal',
context_system::instance());
} else {
$modcontext = context_module::instance($cm->id);
// Three ways you can comment to a course blog:
$blogok =
// 1. Blog allows public comments and you're not logged in.
$oublog->allowcomments == (OUBLOG_COMMENTS_ALLOWPUBLIC && !isloggedin()) ||
// 2. Post is visible to all logged-in users+, and you have the
// comment capabilty in context.
($post->visibility >= OUBLOG_VISIBILITY_LOGGEDINUSER
&& $oublog->maxvisibility >= OUBLOG_VISIBILITY_LOGGEDINUSER
&& has_capability('mod/oublog:comment',
$modcontext)) ||
// 3. You have comment permission in the specific context
// (= course member) and you are allowed to write to the blog
// group i.e. it's your group.
(has_capability('mod/oublog:comment', $modcontext) &&
oublog_is_writable_group($cm));
// Note this logic is still a bit weird with regard to groups. If
// there is a course blog with visible groups, users in other groups
// can't comment; there is a CONTRIB bug request for us to make an
// option for this. In that same situation, if a post is set to be
// visible to logged-in users, now people not in groups can suddenly
// comment. Hmmm. We might need another level of ->allowcomments to
// make this make sense, or some other changes.
}
// Test comment time period.
$timeok = (($oublog->commentfrom == 0 || $oublog->commentfrom <= time()) &&
($oublog->commentuntil == 0 || $oublog->commentuntil > time()));
if ($ignoretime) {
$timeok = true;
}
if (!$timeok && has_capability('mod/oublog:ignorecommentperiod',
$oublog->global ? context_system::instance() : context_module::instance($cm->id))) {
$timeok = true;
}
// If the blog allows comments, this post must allow comments and either
// it allows public comments or you're logged in (and not guest)
return $blogok && $post->allowcomments &&
($post->allowcomments >= OUBLOG_COMMENTS_ALLOWPUBLIC ||
(isloggedin() && !isguestuser())) && $timeok;
}
/**
* Wrapper around groups_get_activity_group.
* @param object $cm Moodle course-module (possibly with extra cache fields)
* @param boolean $update True to update from URL (must be first call on page)
*/
function oublog_get_activity_group($cm, $update=false) {
return groups_get_activity_group($cm, $update);
}
/**
* Wrapper around groups_get_activity_groupmode.
* @param object $cm Moodle course-module (possibly with extra cache fields)
* @param object $course Optional course parameter; should be included in
* first call in page
*/
function oublog_get_activity_groupmode($cm, $course=null) {
return groups_get_activity_groupmode($cm, $course);
}
/**
* Checks whether a group is writable GIVEN THAT YOU CAN SEE THE BLOG
* (i.e. this does not handle the separate-groups case, only visible-groups).
* The information is static-cached so this function can be called multiple
* times.
* @param object $cm Moodle course-module
*/
function oublog_is_writable_group($cm) {
static $writablecm;
if (!isset($writablecm)) {
$writablecm = array();
}
if (!isset($writablecm[$cm->id])) {
$writablecm[$cm->id] = array();
}
$groupmode = oublog_get_activity_groupmode($cm, $cm->course);
if ($groupmode != VISIBLEGROUPS) {
// If no groups, then they must be allowed to access this;
// if separate groups, then because this is defined to only work
// for entries you can see, you must be allowed to access; so only
// doubt is for visible groups.
return true;
}
$groupid = oublog_get_activity_group($cm);
if (isset($writablecm[$cm->id][$groupid])) {
return $writablecm[$cm->id][$groupid];
}
$writablecm[$cm->id][$groupid] = groups_is_member($groupid) ||
has_capability('moodle/site:accessallgroups',
context_module::instance($cm->id));
return $writablecm[$cm->id][$groupid];
}
/**
* Determine if a user can view a post. Note that you must also call
* oublog_check_view_permissions for the blog as a whole.
*
* @param object $post
* @param object $user
* @param object $context
* @param stdClass|cm_info $cm Course-module object
* @param stdClass $oublog Blog object
* @param stdClass|cm_info|null $childcm Child course-module or null if none
* @param stdClass|null $childoublog Child blog object or null if none
* @return bool
*/
function oublog_can_view_post($post, $user, $context, $cm, $oublog, $childcm = null, $childoublog = null) {
global $DB;
if (empty($post->userid)) {
// Not sent userid from pluginfile etc so get it.
if ($instance = $DB->get_record('oublog_instances',
array('id' => $post->oubloginstancesid), 'userid')) {
$post->userid = $instance->userid;
}
}
// If you don't have capabilities and it's not yours, you can't see it.
if ($post->deletedby && !has_capability('mod/oublog:manageposts', $context, $user->id) &&
($post->userid !== $user->id)) {
return false;
}
// Public visibility means everyone.
if ($post->visibility == OUBLOG_VISIBILITY_PUBLIC) {
return true;
}
// Logged-in user visibility means everyone logged in, but no guests.
if ($post->visibility==OUBLOG_VISIBILITY_LOGGEDINUSER &&
(isloggedin() && !isguestuser())) {
return true;
} else if ($post->visibility==OUBLOG_VISIBILITY_LOGGEDINUSER) {
return false;
}
if ($post->visibility!=OUBLOG_VISIBILITY_COURSEUSER) {
throw new moodle_exception('invalidvisibilitylevel', 'oublog', '', $post->visibility);
}
$correctindividual = isset($childoublog->individual) ? $childoublog->individual : $oublog->individual;
$correctglobal = isset($childoublog->global) ? $childoublog->global : $oublog->global;
$correctcm = $childcm ? $childcm : $cm;
// Otherwise this is set to course visibility.
if ($correctglobal) {
// Private posts - only same user or has capability viewprivate can see.
if (has_capability('mod/oublog:viewprivate', context_system::instance(), $user->id)) {
return true;
}
return $post->userid == $user->id;
} else {
// Check oublog:view capability at module level.
// This might not have been checked yet because if the blog is
// set to public, you're allowed to view it, but maybe not this
// post.
if (!has_capability('mod/oublog:view', $context, $user->id)) {
return false;
}
// Is it a separate individuals blog? If so, you can only view your own unless you have
// permission.
if ($correctindividual == OUBLOG_SEPARATE_INDIVIDUAL_BLOGS &&
!has_capability('mod/oublog:viewindividual', $context, $user->id) &&
$post->userid != $user->id) {
return false;
}
// Is the blog in separate groups mode, and you don't have access all groups?
$groupmode = groups_get_activity_groupmode($correctcm);
if ($groupmode == SEPARATEGROUPS &&
!has_capability('moodle/site:accessallgroups', $context, $user->id)) {
if ($correctindividual == OUBLOG_VISIBLE_INDIVIDUAL_BLOGS ||
$correctindividual == OUBLOG_SEPARATE_INDIVIDUAL_BLOGS) {
// For visible individual blog (or separate if you have view individuals), you can
// only view entries from somebody in another of the groups you are in (that match
// the activity grouping if set).
$groupingjoin = '';
$params = [];
if ($correctcm->groupingid) {
$groupingjoin = "
JOIN {groupings_groups} gg ON gg.groupid = gm.groupid AND gg.groupingid = ?
JOIN {groupings_groups} gg2 ON gg2.groupid = gm2.groupid AND gg2.groupingid = ?";
$params = [$correctcm->groupingid, $correctcm->groupingid];
}
$sql = "SELECT 1
FROM {groups_members} gm
JOIN {groups} g ON g.id = gm.groupid
JOIN {groups_members} gm2 ON gm2.groupid = gm.groupid
$groupingjoin
JOIN {groups} g2 ON g2.id = gm2.groupid AND g2.courseid = g.courseid
WHERE gm.userid = ? AND gm2.userid = ? AND g.courseid = ?";
$params = array_merge($params, [$user->id, $post->userid, $correctcm->course]);
if (!$DB->record_exists_sql($sql, $params)) {
return false;
}
} else if ($post->groupid) {
// For group blog, you can only view entries in one of the groups you are in.
$mygroups = groups_get_user_groups($correctcm->course, $user->id);
if ($correctcm->groupingid) {
if (empty($mygroups[$correctcm->groupingid][$post->groupid])) {
return false;
}
} else {
// For some stupid reason this is stored in a different way for zero versus
// all the groupings.
if (!in_array($post->groupid, $mygroups[0])) {
return false;
}
}
}
}
return true;
}
}
/**
* Add a new blog post
*
* @param mixed $post An object containing all required post fields
* @param object $cm Course-module for blog
* @return mixed PostID on success or false
*/
function oublog_add_post($post, $cm, $oublog, $course) {
global $DB, $CFG;
require_once($CFG->libdir . '/completionlib.php');
$post->itemid = $post->message['itemid'];
$post->message = $post->message['text'];
$modcontext = context_module::instance($cm->id);
if (!isset($post->oubloginstancesid)) {
if (!$post->oubloginstancesid = $DB->get_field('oublog_instances', 'id', array('oublogid'=>$post->oublogid, 'userid'=>$post->userid))) {
if (!$post->oubloginstancesid = oublog_add_bloginstance($post->oublogid, $post->userid)) {
return(false);
}
}
}
if (!isset($post->timeposted)) {
$post->timeposted = time();
}
// Begin transaction
$tw = $DB->start_delegated_transaction();
if (!$postid = $DB->insert_record('oublog_posts', $post)) {
return(false);
}
// Now do filestuff.
if ($post->attachments) {
file_save_draft_area_files($post->attachments, $modcontext->id, 'mod_oublog', 'attachment', $postid, array('subdirs' => 0));
}
$post->message = file_save_draft_area_files($post->itemid, $modcontext->id, 'mod_oublog', 'message', $postid, array('subdirs'=>0), $post->message);
$DB->set_field('oublog_posts', 'message', $post->message, array('id'=>$postid));
if (isset($post->tags)) {
oublog_update_item_tags($post->oubloginstancesid, $postid, $post->tags, $post->visibility);
}
$post->id = $postid; // Needed by later code in callers (sometimes).
// Inform completion system, if available
$completion = new completion_info($course);
if ($completion->is_enabled($cm) && ($oublog->completionposts)) {
$completion->update_state($cm, COMPLETION_COMPLETE);
}
$tw->allow_commit();
return($postid);
}
/**
* Update a blog post
*
* @param mixed $post An object containing all required post fields
* @param object $cm Course-module for blog
* @return bool
*/
function oublog_edit_post($post, $cm) {
global $USER, $DB;
$post->itemid = $post->message['itemid'];
$post->message = $post->message['text'];
$modcontext = context_module::instance($cm->id);
if (!isset($post->id) || !$oldpost = $DB->get_record('oublog_posts', array('id'=>$post->id))) {
return(false);
}
$oubloginstance = $DB->get_record('oublog_instances', ['id' => $oldpost->oubloginstancesid],
'id, userid', IGNORE_MISSING);
if (!$oubloginstance) {
return(false);
}
$post->oubloginstancesid = $oubloginstance->id;
// Begin transaction
$tw = $DB->start_delegated_transaction();
// insert edit history
$edit = new stdClass();
$edit->postid = $post->id;
$edit->userid = $oldpost->lasteditedby ? $oldpost->lasteditedby : $oubloginstance->userid;
$edit->timeupdated = time();
$edit->oldtitle = $oldpost->title;
$edit->oldmessage = $oldpost->message;
if (!$editid = $DB->insert_record('oublog_edits', $edit)) {
return(false);
}
// Get list of files attached to this post and attach them to the edit.
$fs = get_file_storage();
if ($files = $fs->get_area_files($modcontext->id, 'mod_oublog', 'attachment', $post->id, "timemodified", false)) {
foreach ($files as $file) {
// Add this file to the edit record.
$fs->create_file_from_storedfile(array(
'filearea' => 'edit',
'itemid' => $editid), $file);
}
}
// Save new files.
$post->message = file_save_draft_area_files($post->itemid, $modcontext->id, 'mod_oublog', 'message', $post->id, array('subdirs'=>0), $post->message);
file_save_draft_area_files($post->attachments, $modcontext->id, 'mod_oublog', 'attachment', $post->id, array('subdirs' => 0));
// Update tags
if (!oublog_update_item_tags($post->oubloginstancesid, $post->id, $post->tags, $post->visibility)) {
return(false);
}
// Update the post
$post->timeupdated = $edit->timeupdated;
$post->lasteditedby = $USER->id;
if (isset($post->groupid)) {
unset($post->groupid); // Can't change group
}
if (!$DB->update_record('oublog_posts', $post)) {
return(false);
}
$tw->allow_commit();
return(true);
}
/**
* Get all data required to print a list of blog posts as efficiently as possible
*
*
* @param object $oublog
* @param int $offset
* @param int $userid
* @param bool $ignoreprivate set true to not return private posts (global blog only)
* @param object $masterblog
* @param int $paginglimit limit post per page
* @param string $sqlorder port sorting
* @return mixed all data to print a list of blog posts
*/
function oublog_get_posts($oublog, $context, $offset, $cm, $groupid, $individualid = -1,
$userid = null, $tag = '', $canaudit = false, $ignoreprivate = null, $masterblog = null, $paginglimit = null, $sqlorder = '') {
global $CFG, $USER, $DB;
$params = array();
// Check master blog.
$postsoublog = !empty($masterblog) ? $masterblog : $oublog;
$sqlwhere = "bi.oublogid = ?";
$params[] = $postsoublog->id;
$sqljoin = '';
if (empty($sqlorder)) {
$sqlorder = 'timeposted DESC';
}
if (empty($paginglimit)) {
$paginglimit = $oublog->postperpage;
}
$sqlorder = str_replace('title', 'p.title', $sqlorder);
$sqlorder = str_replace('author', 'u.firstname', $sqlorder);
$sqlorder = str_replace('timeposted', 'p.timeposted', $sqlorder);
if (isset($userid)) {
$sqlwhere .= " AND bi.userid = ? ";
$params[] = $userid;
}
// Individual blog.
if ($individualid > -1) {
$capable = oublog_individual_has_permissions($cm, $oublog, $groupid, $individualid);
oublog_individual_add_to_sqlwhere($sqlwhere, $params, 'bi.userid', $postsoublog->id, $groupid, $individualid, $capable);
} else {// No individual blog.
if (isset($groupid) && $groupid) {
$sqlwhere .= " AND p.groupid = ? ";
$params[] = $groupid;
}
}
if (!$canaudit) {
$sqlwhere .= " AND (p.deletedby IS NULL or bi.userid = ?)";
$params[] = $USER->id;
}
if ($tag) {
$sqlwhere .= " AND t.tag = ? ";
$params[] = $tag;
$sqljoin .= " INNER JOIN {oublog_taginstances} ti ON p.id = ti.postid
INNER JOIN {oublog_tags} t ON ti.tagid = t.id ";
}
// Visibility checks.
if (!isloggedin() || isguestuser()) {
$sqlwhere .= " AND p.visibility =" . OUBLOG_VISIBILITY_PUBLIC;
} else {
if ($oublog->global) {
// Unless the current user has manageposts capability,
// they cannot view 'private' posts except their own.
if ($ignoreprivate) {
$sqlwhere .= ' AND (p.visibility > ' . OUBLOG_VISIBILITY_COURSEUSER . ')';
} else if (!has_capability('mod/oublog:manageposts', context_system::instance())) {
$sqlwhere .= " AND (p.visibility >" . OUBLOG_VISIBILITY_COURSEUSER .
" OR (p.visibility = " . OUBLOG_VISIBILITY_COURSEUSER . " AND u.id = ?))";
$params[] = $USER->id;
}
} else {
$context = context_module::instance($cm->id);
if (has_capability('mod/oublog:view', $context)) {
$sqlwhere .= " AND (p.visibility >= " . OUBLOG_VISIBILITY_COURSEUSER . " )";
} else {
$sqlwhere .= " AND p.visibility > " . OUBLOG_VISIBILITY_COURSEUSER;
}
}
}
$userfieldsapi = \core_user\fields::for_name();
$usernamefields = $userfieldsapi->get_sql('u', false, '', '', false)->selects;
$delusernamefields = $userfieldsapi->get_sql('ud', false, 'del', '', false)->selects;
$editusernamefields = $userfieldsapi->get_sql('ue', false, 'ed', '', false)->selects;
// Get posts. The post has the field timeposted not timecreated,
// which is tested in rating::user_can_rate().
$fieldlist = "p.*, p.timeposted AS timecreated, bi.oublogid, $usernamefields,
bi.userid, u.idnumber, u.picture, u.imagealt, u.email, u.username,
$delusernamefields,
$editusernamefields";
$from = "FROM {oublog_posts} p
INNER JOIN {oublog_instances} bi ON p.oubloginstancesid = bi.id
INNER JOIN {user} u ON bi.userid = u.id
LEFT JOIN {user} ud ON p.deletedby = ud.id
LEFT JOIN {user} ue ON p.lasteditedby = ue.id
$sqljoin";
$sql = "SELECT $fieldlist
$from
WHERE $sqlwhere
ORDER BY $sqlorder
";
$countsql = "SELECT count(p.id) $from WHERE $sqlwhere";
$rs = $DB->get_recordset_sql($sql, $params, $offset, $paginglimit);
// Get paging info
$recordcnt = $DB->count_records_sql($countsql, $params);
if (!$rs->valid()) {
return array(false, $recordcnt);
}
$cnt = 0;
$posts = array();
$postids = array();
foreach ($rs as $post) {
if ($cnt > $paginglimit) {
break;
}
if (oublog_can_view_post($post, $USER, $context, $cm, $oublog)) {
if ($oublog->maxvisibility < $post->visibility) {
$post->visibility = $oublog->maxvisibility;
}
if ($oublog->allowcomments == OUBLOG_COMMENTS_PREVENT) {
$post->allowcomments = OUBLOG_COMMENTS_PREVENT;
}
$posts[$post->id] = $post;
$postids[] = (int)$post->id;
$cnt++;
}
}
$rs->close();
if (empty($posts)) {
return array(false, $recordcnt);
}
// Get tags for all posts on page
$sql = "SELECT t.*, ti.postid
FROM {oublog_taginstances} ti
INNER JOIN {oublog_tags} t ON ti.tagid = t.id
WHERE ti.postid IN (".implode(",", $postids).") ";
$rs = $DB->get_recordset_sql($sql);
foreach ($rs as $tag) {
$posts[$tag->postid]->tags[$tag->id] = $tag->tag;
}
// Load ratings.
require_once($CFG->dirroot.'/rating/lib.php');
if ($oublog->assessed != RATING_AGGREGATE_NONE && $postsoublog->assessed != RATING_AGGREGATE_NONE) {
$ratingoptions = new stdClass();
$ratingoptions->context = $context;
$ratingoptions->component = 'mod_oublog';
$ratingoptions->ratingarea = 'post';
$ratingoptions->items = $posts;
$ratingoptions->aggregate = $oublog->assessed;// The aggregation method.
$ratingoptions->scaleid = $oublog->scale;
$ratingoptions->userid = $USER->id;
$ratingoptions->assesstimestart = $oublog->assesstimestart;
$ratingoptions->assesstimefinish = $oublog->assesstimefinish;
$rm = new rating_manager();
$posts = $rm->get_ratings($ratingoptions);
}
$rs->close();
// Get comments for post on the page
$sql = "SELECT c.id, c.postid, c.timeposted, c.authorname, c.authorip, c.timeapproved, c.userid, $usernamefields, u.picture, u.imagealt, u.email, u.idnumber
FROM {oublog_comments} c
LEFT JOIN {user} u ON c.userid = u.id
WHERE c.postid IN (".implode(",", $postids).") AND c.deletedby IS NULL
ORDER BY c.timeposted ASC ";
$rs = $DB->get_recordset_sql($sql);
foreach ($rs as $comment) {
$posts[$comment->postid]->comments[$comment->id] = $comment;
}
$rs->close();
// Get count of comments waiting approval for posts on the page...
if ($oublog->allowcomments >= OUBLOG_COMMENTS_ALLOWPUBLIC) {
// Make list of all posts that allow public comments
$publicallowed = array();
foreach ($posts as $post) {
if ($post->allowcomments >= OUBLOG_COMMENTS_ALLOWPUBLIC) {
$publicallowed[] = (int)$post->id;
}
}
// Only run a db query if there are some posts that allow public
// comments (so, no performance degradation if feature is not used)
if (count($publicallowed) > 0) {
$sql = "SELECT cm.postid, COUNT(1) AS numpending
FROM {oublog_comments_moderated} cm
WHERE cm.postid IN (".implode(",", $publicallowed).")
AND cm.approval = 0
GROUP BY cm.postid";
$rs = $DB->get_recordset_sql($sql);
foreach ($rs as $postinfo) {
$posts[$postinfo->postid]->pendingcomments = $postinfo->numpending;
}
$rs->close();
}
}
return(array($posts, $recordcnt));
}
/**
* Get all data required to print a single blog post as efficiently as possible
*
*
* @param int $postid
* @return mixed all data to print a list of blog posts
*/
function oublog_get_post($postid, $canaudit=false) {
global $DB;
$userfieldsapi = \core_user\fields::for_name();
$usernamefields = $userfieldsapi->get_sql('u', false, '', '', false)->selects;
$delusernamefields = $userfieldsapi->get_sql('ud', false, 'del', '', false)->selects;
$editusernamefields = $userfieldsapi->get_sql('ue', false, 'ed', '', false)->selects;
// Get post
$sql = "SELECT p.*, bi.oublogid, $usernamefields, u.picture, u.imagealt, bi.userid, u.idnumber, u.email, u.username, u.mailformat,
$delusernamefields,
$editusernamefields
FROM {oublog_posts} p
INNER JOIN {oublog_instances} bi ON p.oubloginstancesid = bi.id
INNER JOIN {user} u ON bi.userid = u.id
LEFT JOIN {user} ud ON p.deletedby = ud.id
LEFT JOIN {user} ue ON p.lasteditedby = ue.id
WHERE p.id = ?
ORDER BY p.timeposted DESC
";
if (!$post = $DB->get_record_sql($sql, array($postid))) {
return(false);
}
// Get tags for all posts on page
$sql = "SELECT t.*, ti.postid
FROM {oublog_taginstances} ti
INNER JOIN {oublog_tags} t ON ti.tagid = t.id
WHERE ti.postid = ? ";
$rs = $DB->get_recordset_sql($sql, array($postid));
foreach ($rs as $tag) {
$post->tags[$tag->id] = $tag->tag;
}
$rs->close();
// Get comments for post on the page
if ($post->allowcomments) {
$sql = "SELECT c.*, $usernamefields, u.picture, u.imagealt, u.email, u.idnumber,
$delusernamefields
FROM {oublog_comments} c
LEFT JOIN {user} u ON c.userid = u.id
LEFT JOIN {user} ud ON c.deletedby = ud.id
WHERE c.postid = ? ";
if (!$canaudit) {
$sql .= " AND c.deletedby IS NULL ";
}
$sql .= " ORDER BY c.timeposted ASC ";
$rs = $DB->get_recordset_sql($sql, array($postid));
foreach ($rs as $comment) {
$post->comments[$comment->id] = $comment;
}
$rs->close();
}
// Get edits for this post
$sql = "SELECT e.id, e.timeupdated, e.oldtitle, e.userid, $usernamefields, u.picture, u.imagealt, u.email, u.idnumber
FROM {oublog_edits} e
INNER JOIN {user} u ON e.userid = u.id
WHERE e.postid = ?
ORDER BY e.timeupdated DESC ";
$rs = $DB->get_recordset_sql($sql, array($postid));
foreach ($rs as $edit) {
$post->edits[$edit->id] = $edit;
}
$rs->close();
return($post);
}
/**
* Add a blog_instance
*
* @param int $oublogid
* @param int $userid
* @param string $name
* @param string $summary
* @return mixed oubloginstancesid on success or false
*/
function oublog_add_bloginstance($oublogid, $userid, $name='', $summary=null) {
global $DB;
$oubloginstance = new stdClass;
$oubloginstance->oublogid = $oublogid;
$oubloginstance->userid = $userid;
$oubloginstance->name = $name;
$oubloginstance->summary = $summary;
$oubloginstance->accesstoken = md5(uniqid(rand(), true));
return($DB->insert_record('oublog_instances', $oubloginstance));
}
/**
* Clarifies a $tags value which may be a string or an array of values,
* returning an array of strings.
* @param mixed $tags
* @return array Array of tag strings
*/
function oublog_clarify_tags($tags) {
if (is_string($tags)) {
if (!$tags = explode(',', $tags)) {
return array();
}
} else if (!is_array($tags)) {
return array();
}
foreach ($tags as $idx => $tag) {
$tag = trim($tag);
if (empty($tag)) {
unset($tags[$idx]);
continue;
}
$tags[$idx] = $tag;
}
$tags = array_unique($tags);
return $tags;
}
/**
* Update a posts tags
*
* @param int $oubloginstanceid
* @param int $postid
* @param mixed $tags Comma separated string or an array
* @uses $CFG
*/
function oublog_update_item_tags($oubloginstancesid, $postid, $tags, $postvisibility=OUBLOG_VISIBILITY_COURSEUSER) {
global $CFG, $DB;
$tagssql = array();
$tagids = array();
// Removed any existing
$DB->delete_records('oublog_taginstances', array('postid'=>$postid));
$tags=oublog_clarify_tags($tags);
if (empty($tags)) {
return(true);
}
// get the id's of the know tags
list($tagsql, $tagparams) = $DB->get_in_or_equal($tags);
$sql = "SELECT tag, id FROM {oublog_tags} WHERE tag $tagsql";
$tagids = $DB->get_records_sql($sql, $tagparams);
// insert the remainder
foreach ($tags as $tag) {
if (!isset($tagids[$tag])) {
$tagobj = (object) array('tag' => $tag);