[ Index ] |
PHP Cross Reference of moodle-2.8 |
[Summary view] [Print] [Text view]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 /** 18 * Classes for Blogs. 19 * 20 * @package moodlecore 21 * @subpackage blog 22 * @copyright 2009 Nicolas Connault 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 */ 25 26 defined('MOODLE_INTERNAL') || die(); 27 28 require_once($CFG->libdir . '/filelib.php'); 29 30 /** 31 * Blog_entry class. Represents an entry in a user's blog. Contains all methods for managing this entry. 32 * This class does not contain any HTML-generating code. See blog_listing sub-classes for such code. 33 * This class follows the Object Relational Mapping technique, its member variables being mapped to 34 * the fields of the post table. 35 * 36 * @package moodlecore 37 * @subpackage blog 38 * @copyright 2009 Nicolas Connault 39 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 40 */ 41 class blog_entry implements renderable { 42 // Public Database fields. 43 public $id; 44 public $userid; 45 public $subject; 46 public $summary; 47 public $rating = 0; 48 public $attachment; 49 public $publishstate; 50 51 // Locked Database fields (Don't touch these). 52 public $courseid = 0; 53 public $groupid = 0; 54 public $module = 'blog'; 55 public $moduleid = 0; 56 public $coursemoduleid = 0; 57 public $content; 58 public $format = 1; 59 public $uniquehash = ''; 60 public $lastmodified; 61 public $created; 62 public $usermodified; 63 64 // Other class variables. 65 public $form; 66 public $tags = array(); 67 68 /** @var StdClass Data needed to render the entry */ 69 public $renderable; 70 71 /** 72 * Constructor. If given an id, will fetch the corresponding record from the DB. 73 * 74 * @param mixed $idorparams A blog entry id if INT, or data for a new entry if array 75 */ 76 public function __construct($id=null, $params=null, $form=null) { 77 global $DB, $PAGE, $CFG; 78 79 if (!empty($id)) { 80 $object = $DB->get_record('post', array('id' => $id)); 81 foreach ($object as $var => $val) { 82 $this->$var = $val; 83 } 84 } else if (!empty($params) && (is_array($params) || is_object($params))) { 85 foreach ($params as $var => $val) { 86 $this->$var = $val; 87 } 88 } 89 90 if (!empty($CFG->useblogassociations)) { 91 $associations = $DB->get_records('blog_association', array('blogid' => $this->id)); 92 foreach ($associations as $association) { 93 $context = context::instance_by_id($association->contextid); 94 if ($context->contextlevel == CONTEXT_COURSE) { 95 $this->courseassoc = $association->contextid; 96 } else if ($context->contextlevel == CONTEXT_MODULE) { 97 $this->modassoc = $association->contextid; 98 } 99 } 100 } 101 102 $this->form = $form; 103 } 104 105 106 /** 107 * Gets the required data to print the entry 108 */ 109 public function prepare_render() { 110 111 global $DB, $CFG, $PAGE; 112 113 $this->renderable = new StdClass(); 114 115 $this->renderable->user = $DB->get_record('user', array('id'=>$this->userid)); 116 117 // Entry comments. 118 if (!empty($CFG->usecomments) and $CFG->blogusecomments) { 119 require_once($CFG->dirroot . '/comment/lib.php'); 120 121 $cmt = new stdClass(); 122 $cmt->context = context_user::instance($this->userid); 123 $cmt->courseid = $PAGE->course->id; 124 $cmt->area = 'format_blog'; 125 $cmt->itemid = $this->id; 126 $cmt->showcount = $CFG->blogshowcommentscount; 127 $cmt->component = 'blog'; 128 $this->renderable->comment = new comment($cmt); 129 } 130 131 $this->summary = file_rewrite_pluginfile_urls($this->summary, 'pluginfile.php', SYSCONTEXTID, 'blog', 'post', $this->id); 132 133 // External blog link. 134 if ($this->uniquehash && $this->content) { 135 if ($externalblog = $DB->get_record('blog_external', array('id' => $this->content))) { 136 $urlparts = parse_url($externalblog->url); 137 $this->renderable->externalblogtext = get_string('retrievedfrom', 'blog') . get_string('labelsep', 'langconfig'); 138 $this->renderable->externalblogtext .= html_writer::link($urlparts['scheme'] . '://' . $urlparts['host'], 139 $externalblog->name); 140 } 141 } 142 143 // Retrieve associations. 144 $this->renderable->unassociatedentry = false; 145 if (!empty($CFG->useblogassociations)) { 146 147 // Adding the entry associations data. 148 if ($associations = $associations = $DB->get_records('blog_association', array('blogid' => $this->id))) { 149 150 // Check to see if the entry is unassociated with group/course level access. 151 if ($this->publishstate == 'group' || $this->publishstate == 'course') { 152 $this->renderable->unassociatedentry = true; 153 } 154 155 foreach ($associations as $key => $assocrec) { 156 157 if (!$context = context::instance_by_id($assocrec->contextid, IGNORE_MISSING)) { 158 unset($associations[$key]); 159 continue; 160 } 161 162 // The renderer will need the contextlevel of the association. 163 $associations[$key]->contextlevel = $context->contextlevel; 164 165 // Course associations. 166 if ($context->contextlevel == CONTEXT_COURSE) { 167 // TODO: performance!!!! 168 $instancename = $DB->get_field('course', 'shortname', array('id' => $context->instanceid)); 169 170 $associations[$key]->url = $assocurl = new moodle_url('/course/view.php', 171 array('id' => $context->instanceid)); 172 $associations[$key]->text = $instancename; 173 $associations[$key]->icon = new pix_icon('i/course', $associations[$key]->text); 174 } 175 176 // Mod associations. 177 if ($context->contextlevel == CONTEXT_MODULE) { 178 179 // Getting the activity type and the activity instance id. 180 $sql = 'SELECT cm.instance, m.name FROM {course_modules} cm 181 JOIN {modules} m ON m.id = cm.module 182 WHERE cm.id = :cmid'; 183 $modinfo = $DB->get_record_sql($sql, array('cmid' => $context->instanceid)); 184 // TODO: performance!!!! 185 $instancename = $DB->get_field($modinfo->name, 'name', array('id' => $modinfo->instance)); 186 187 $associations[$key]->type = get_string('modulename', $modinfo->name); 188 $associations[$key]->url = new moodle_url('/mod/' . $modinfo->name . '/view.php', 189 array('id' => $context->instanceid)); 190 $associations[$key]->text = $instancename; 191 $associations[$key]->icon = new pix_icon('icon', $associations[$key]->text, $modinfo->name); 192 } 193 } 194 } 195 $this->renderable->blogassociations = $associations; 196 } 197 198 // Entry attachments. 199 $this->renderable->attachments = $this->get_attachments(); 200 201 $this->renderable->usercanedit = blog_user_can_edit_entry($this); 202 } 203 204 205 /** 206 * Gets the entry attachments list 207 * @return array List of blog_entry_attachment instances 208 */ 209 public function get_attachments() { 210 211 global $CFG; 212 213 require_once($CFG->libdir.'/filelib.php'); 214 215 $syscontext = context_system::instance(); 216 217 $fs = get_file_storage(); 218 $files = $fs->get_area_files($syscontext->id, 'blog', 'attachment', $this->id); 219 220 // Adding a blog_entry_attachment for each non-directory file. 221 $attachments = array(); 222 foreach ($files as $file) { 223 if ($file->is_directory()) { 224 continue; 225 } 226 $attachments[] = new blog_entry_attachment($file, $this->id); 227 } 228 229 return $attachments; 230 } 231 232 /** 233 * Inserts this entry in the database. Access control checks must be done by calling code. 234 * 235 * @param mform $form Used for attachments 236 * @return void 237 */ 238 public function process_attachment($form) { 239 $this->form = $form; 240 } 241 242 /** 243 * Inserts this entry in the database. Access control checks must be done by calling code. 244 * TODO Set the publishstate correctly 245 * @return void 246 */ 247 public function add() { 248 global $CFG, $USER, $DB; 249 250 unset($this->id); 251 $this->module = 'blog'; 252 $this->userid = (empty($this->userid)) ? $USER->id : $this->userid; 253 $this->lastmodified = time(); 254 $this->created = time(); 255 256 // Insert the new blog entry. 257 $this->id = $DB->insert_record('post', $this); 258 259 // Update tags. 260 $this->add_tags_info(); 261 262 if (!empty($CFG->useblogassociations)) { 263 $this->add_associations(); 264 } 265 266 tag_set('post', $this->id, $this->tags, 'core', context_user::instance($this->userid)->id); 267 268 // Trigger an event for the new entry. 269 $event = \core\event\blog_entry_created::create(array( 270 'objectid' => $this->id, 271 'relateduserid' => $this->userid 272 )); 273 $event->set_blog_entry($this); 274 $event->trigger(); 275 } 276 277 /** 278 * Updates this entry in the database. Access control checks must be done by calling code. 279 * 280 * @param array $params Entry parameters. 281 * @param moodleform $form Used for attachments. 282 * @param array $summaryoptions Summary options. 283 * @param array $attachmentoptions Attachment options. 284 * 285 * @return void 286 */ 287 public function edit($params=array(), $form=null, $summaryoptions=array(), $attachmentoptions=array()) { 288 global $CFG, $DB; 289 290 $sitecontext = context_system::instance(); 291 $entry = $this; 292 293 $this->form = $form; 294 foreach ($params as $var => $val) { 295 $entry->$var = $val; 296 } 297 298 $entry = file_postupdate_standard_editor($entry, 'summary', $summaryoptions, $sitecontext, 'blog', 'post', $entry->id); 299 $entry = file_postupdate_standard_filemanager($entry, 300 'attachment', 301 $attachmentoptions, 302 $sitecontext, 303 'blog', 304 'attachment', 305 $entry->id); 306 307 if (!empty($CFG->useblogassociations)) { 308 $entry->add_associations(); 309 } 310 311 $entry->lastmodified = time(); 312 313 // Update record. 314 $DB->update_record('post', $entry); 315 tag_set('post', $entry->id, $entry->tags, 'core', context_user::instance($this->userid)->id); 316 317 $event = \core\event\blog_entry_updated::create(array( 318 'objectid' => $entry->id, 319 'relateduserid' => $entry->userid 320 )); 321 $event->set_blog_entry($entry); 322 $event->trigger(); 323 } 324 325 /** 326 * Deletes this entry from the database. Access control checks must be done by calling code. 327 * 328 * @return void 329 */ 330 public function delete() { 331 global $DB; 332 333 $this->delete_attachments(); 334 $this->remove_associations(); 335 336 // Get record to pass onto the event. 337 $record = $DB->get_record('post', array('id' => $this->id)); 338 $DB->delete_records('post', array('id' => $this->id)); 339 tag_set('post', $this->id, array(), 'core', context_user::instance($this->userid)->id); 340 341 $event = \core\event\blog_entry_deleted::create(array( 342 'objectid' => $this->id, 343 'relateduserid' => $this->userid 344 )); 345 $event->add_record_snapshot("post", $record); 346 $event->set_blog_entry($this); 347 $event->trigger(); 348 } 349 350 /** 351 * Function to add all context associations to an entry. 352 * TODO : Remove $action in 2.9 (MDL-41330) 353 * 354 * @param string $action - This does nothing, do not use it. This is present only for Backward compatibility. 355 */ 356 public function add_associations($action = null) { 357 358 if (!empty($action)) { 359 debugging('blog_entry->add_associations() does not accept any argument', DEBUG_DEVELOPER); 360 } 361 362 $this->remove_associations(); 363 364 if (!empty($this->courseassoc)) { 365 $this->add_association($this->courseassoc); 366 } 367 368 if (!empty($this->modassoc)) { 369 $this->add_association($this->modassoc); 370 } 371 } 372 373 /** 374 * Add a single association for a blog entry 375 * TODO : Remove $action in 2.9 (MDL-41330) 376 * 377 * @param int $contextid - id of context to associate with the blog entry. 378 * @param string $action - This does nothing, do not use it. This is present only for Backward compatibility. 379 */ 380 public function add_association($contextid, $action = null) { 381 global $DB; 382 383 if (!empty($action)) { 384 debugging('blog_entry->add_association() accepts only one argument', DEBUG_DEVELOPER); 385 } 386 387 $assocobject = new StdClass; 388 $assocobject->contextid = $contextid; 389 $assocobject->blogid = $this->id; 390 $id = $DB->insert_record('blog_association', $assocobject); 391 392 // Trigger an association created event. 393 $context = context::instance_by_id($contextid); 394 $eventparam = array( 395 'objectid' => $id, 396 'other' => array('associateid' => $context->instanceid, 'subject' => $this->subject, 'blogid' => $this->id), 397 'relateduserid' => $this->userid 398 ); 399 if ($context->contextlevel == CONTEXT_COURSE) { 400 $eventparam['other']['associatetype'] = 'course'; 401 402 } else if ($context->contextlevel == CONTEXT_MODULE) { 403 $eventparam['other']['associatetype'] = 'coursemodule'; 404 } 405 $event = \core\event\blog_association_created::create($eventparam); 406 $event->trigger(); 407 } 408 409 /** 410 * remove all associations for a blog entry 411 * @return voic 412 */ 413 public function remove_associations() { 414 global $DB; 415 $DB->delete_records('blog_association', array('blogid' => $this->id)); 416 } 417 418 /** 419 * Deletes all the user files in the attachments area for an entry 420 * 421 * @return void 422 */ 423 public function delete_attachments() { 424 $fs = get_file_storage(); 425 $fs->delete_area_files(SYSCONTEXTID, 'blog', 'attachment', $this->id); 426 $fs->delete_area_files(SYSCONTEXTID, 'blog', 'post', $this->id); 427 } 428 429 /** 430 * function to attach tags into an entry 431 * @return void 432 */ 433 public function add_tags_info() { 434 435 $tags = array(); 436 437 if ($otags = optional_param('otags', '', PARAM_INT)) { 438 foreach ($otags as $tagid) { 439 // TODO : make this use the tag name in the form. 440 if ($tag = tag_get('id', $tagid)) { 441 $tags[] = $tag->name; 442 } 443 } 444 } 445 446 tag_set('post', $this->id, $tags, 'core', context_user::instance($this->userid)->id); 447 } 448 449 /** 450 * User can edit a blog entry if this is their own blog entry and they have 451 * the capability moodle/blog:create, or if they have the capability 452 * moodle/blog:manageentries. 453 * This also applies to deleting of entries. 454 * 455 * @param int $userid Optional. If not given, $USER is used 456 * @return boolean 457 */ 458 public function can_user_edit($userid=null) { 459 global $CFG, $USER; 460 461 if (empty($userid)) { 462 $userid = $USER->id; 463 } 464 465 $sitecontext = context_system::instance(); 466 467 if (has_capability('moodle/blog:manageentries', $sitecontext)) { 468 return true; // Can edit any blog entry. 469 } 470 471 if ($this->userid == $userid && has_capability('moodle/blog:create', $sitecontext)) { 472 return true; // Can edit own when having blog:create capability. 473 } 474 475 return false; 476 } 477 478 /** 479 * Checks to see if a user can view the blogs of another user. 480 * Only blog level is checked here, the capabilities are enforced 481 * in blog/index.php 482 * 483 * @param int $targetuserid ID of the user we are checking 484 * 485 * @return bool 486 */ 487 public function can_user_view($targetuserid) { 488 global $CFG, $USER, $DB; 489 $sitecontext = context_system::instance(); 490 491 if (empty($CFG->enableblogs) || !has_capability('moodle/blog:view', $sitecontext)) { 492 return false; // Blog system disabled or user has no blog view capability. 493 } 494 495 if (isloggedin() && $USER->id == $targetuserid) { 496 return true; // Can view own entries in any case. 497 } 498 499 if (has_capability('moodle/blog:manageentries', $sitecontext)) { 500 return true; // Can manage all entries. 501 } 502 503 // Coming for 1 entry, make sure it's not a draft. 504 if ($this->publishstate == 'draft' && !has_capability('moodle/blog:viewdrafts', $sitecontext)) { 505 return false; // Can not view draft of others. 506 } 507 508 // Coming for 1 entry, make sure user is logged in, if not a public blog. 509 if ($this->publishstate != 'public' && !isloggedin()) { 510 return false; 511 } 512 513 switch ($CFG->bloglevel) { 514 case BLOG_GLOBAL_LEVEL: 515 return true; 516 break; 517 518 case BLOG_SITE_LEVEL: 519 if (isloggedin()) { // Not logged in viewers forbidden. 520 return true; 521 } 522 return false; 523 break; 524 525 case BLOG_USER_LEVEL: 526 default: 527 $personalcontext = context_user::instance($targetuserid); 528 return has_capability('moodle/user:readuserblogs', $personalcontext); 529 break; 530 } 531 } 532 533 /** 534 * Use this function to retrieve a list of publish states available for 535 * the currently logged in user. 536 * 537 * @return array This function returns an array ideal for sending to moodles' 538 * choose_from_menu function. 539 */ 540 541 public static function get_applicable_publish_states() { 542 global $CFG; 543 $options = array(); 544 545 // Everyone gets draft access. 546 if ($CFG->bloglevel >= BLOG_USER_LEVEL) { 547 $options['draft'] = get_string('publishtonoone', 'blog'); 548 } 549 550 if ($CFG->bloglevel > BLOG_USER_LEVEL) { 551 $options['site'] = get_string('publishtosite', 'blog'); 552 } 553 554 if ($CFG->bloglevel >= BLOG_GLOBAL_LEVEL) { 555 $options['public'] = get_string('publishtoworld', 'blog'); 556 } 557 558 return $options; 559 } 560 } 561 562 /** 563 * Abstract Blog_Listing class: used to gather blog entries and output them as listings. One of the subclasses must be used. 564 * 565 * @package moodlecore 566 * @subpackage blog 567 * @copyright 2009 Nicolas Connault 568 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 569 */ 570 class blog_listing { 571 /** 572 * Array of blog_entry objects. 573 * @var array $entries 574 */ 575 public $entries = array(); 576 577 /** 578 * An array of blog_filter_* objects 579 * @var array $filters 580 */ 581 public $filters = array(); 582 583 /** 584 * Constructor 585 * 586 * @param array $filters An associative array of filtername => filterid 587 */ 588 public function __construct($filters=array()) { 589 // Unset filters overridden by more specific filters. 590 foreach ($filters as $type => $id) { 591 if (!empty($type) && !empty($id)) { 592 $this->filters[$type] = blog_filter::get_instance($id, $type); 593 } 594 } 595 596 foreach ($this->filters as $type => $filter) { 597 foreach ($filter->overrides as $override) { 598 if (array_key_exists($override, $this->filters)) { 599 unset($this->filters[$override]); 600 } 601 } 602 } 603 } 604 605 /** 606 * Fetches the array of blog entries. 607 * 608 * @return array 609 */ 610 public function get_entries($start=0, $limit=10) { 611 global $DB; 612 613 if (empty($this->entries)) { 614 if ($sqlarray = $this->get_entry_fetch_sql(false, 'created DESC')) { 615 $this->entries = $DB->get_records_sql($sqlarray['sql'], $sqlarray['params'], $start, $limit); 616 } else { 617 return false; 618 } 619 } 620 621 return $this->entries; 622 } 623 624 public function get_entry_fetch_sql($count=false, $sort='lastmodified DESC', $userid = false) { 625 global $DB, $USER, $CFG; 626 627 if (!$userid) { 628 $userid = $USER->id; 629 } 630 631 $allnamefields = get_all_user_name_fields(true, 'u'); 632 // The query used to locate blog entries is complicated. It will be built from the following components: 633 $requiredfields = "p.*, $allnamefields, u.email"; // The SELECT clause. 634 $tables = array('p' => 'post', 'u' => 'user'); // Components of the FROM clause (table_id => table_name). 635 // Components of the WHERE clause (conjunction). 636 $conditions = array('u.deleted = 0', 'p.userid = u.id', '(p.module = \'blog\' OR p.module = \'blog_external\')'); 637 638 // Build up a clause for permission constraints. 639 640 $params = array(); 641 642 // Fix for MDL-9165, use with readuserblogs capability in a user context can read that user's private blogs. 643 // Admins can see all blogs regardless of publish states, as described on the help page. 644 if (has_capability('moodle/user:readuserblogs', context_system::instance())) { 645 // Don't add permission constraints. 646 647 } else if (!empty($this->filters['user']) 648 && has_capability('moodle/user:readuserblogs', 649 context_user::instance((empty($this->filters['user']->id) ? 0 : $this->filters['user']->id)))) { 650 // Don't add permission constraints. 651 652 } else { 653 if (isloggedin() and !isguestuser()) { 654 // Dont check association records if there aren't any. 655 $assocexists = $DB->record_exists('blog_association', array()); 656 657 // Begin permission sql clause. 658 $permissionsql = '(p.userid = ? '; 659 $params[] = $userid; 660 661 if ($CFG->bloglevel >= BLOG_SITE_LEVEL) { // Add permission to view site-level entries. 662 $permissionsql .= " OR p.publishstate = 'site' "; 663 } 664 665 if ($CFG->bloglevel >= BLOG_GLOBAL_LEVEL) { // Add permission to view global entries. 666 $permissionsql .= " OR p.publishstate = 'public' "; 667 } 668 669 $permissionsql .= ') '; // Close permissions sql clause. 670 } else { // Default is access to public entries. 671 $permissionsql = "p.publishstate = 'public'"; 672 } 673 $conditions[] = $permissionsql; // Add permission constraints. 674 } 675 676 foreach ($this->filters as $type => $blogfilter) { 677 $conditions = array_merge($conditions, $blogfilter->conditions); 678 $params = array_merge($params, $blogfilter->params); 679 $tables = array_merge($tables, $blogfilter->tables); 680 } 681 682 $tablessql = ''; // Build up the FROM clause. 683 foreach ($tables as $tablename => $table) { 684 $tablessql .= ($tablessql ? ', ' : '').'{'.$table.'} '.$tablename; 685 } 686 687 $sql = ($count) ? 'SELECT COUNT(*)' : 'SELECT ' . $requiredfields; 688 $sql .= " FROM $tablessql WHERE " . implode(' AND ', $conditions); 689 $sql .= ($count) ? '' : " ORDER BY $sort"; 690 691 return array('sql' => $sql, 'params' => $params); 692 } 693 694 /** 695 * Outputs all the blog entries aggregated by this blog listing. 696 * 697 * @return void 698 */ 699 public function print_entries() { 700 global $CFG, $USER, $DB, $OUTPUT, $PAGE; 701 $sitecontext = context_system::instance(); 702 703 // Blog renderer. 704 $output = $PAGE->get_renderer('blog'); 705 706 $page = optional_param('blogpage', 0, PARAM_INT); 707 $limit = optional_param('limit', get_user_preferences('blogpagesize', 10), PARAM_INT); 708 $start = $page * $limit; 709 710 $morelink = '<br /> '; 711 712 if ($sqlarray = $this->get_entry_fetch_sql(true)) { 713 $totalentries = $DB->count_records_sql($sqlarray['sql'], $sqlarray['params']); 714 } else { 715 $totalentries = 0; 716 } 717 718 $entries = $this->get_entries($start, $limit); 719 $pagingbar = new paging_bar($totalentries, $page, $limit, $this->get_baseurl()); 720 $pagingbar->pagevar = 'blogpage'; 721 $blogheaders = blog_get_headers(); 722 723 echo $OUTPUT->render($pagingbar); 724 725 if (has_capability('moodle/blog:create', $sitecontext)) { 726 // The user's blog is enabled and they are viewing their own blog. 727 $userid = optional_param('userid', null, PARAM_INT); 728 729 if (empty($userid) || (!empty($userid) && $userid == $USER->id)) { 730 731 $courseid = optional_param('courseid', null, PARAM_INT); 732 $modid = optional_param('modid', null, PARAM_INT); 733 734 $addurl = new moodle_url("$CFG->wwwroot/blog/edit.php"); 735 $urlparams = array('action' => 'add', 736 'userid' => $userid, 737 'courseid' => $courseid, 738 'groupid' => optional_param('groupid', null, PARAM_INT), 739 'modid' => $modid, 740 'tagid' => optional_param('tagid', null, PARAM_INT), 741 'tag' => optional_param('tag', null, PARAM_INT), 742 'search' => optional_param('search', null, PARAM_INT)); 743 744 $urlparams = array_filter($urlparams); 745 $addurl->params($urlparams); 746 747 $addlink = '<div class="addbloglink">'; 748 $addlink .= '<a href="'.$addurl->out().'">'. $blogheaders['stradd'].'</a>'; 749 $addlink .= '</div>'; 750 echo $addlink; 751 } 752 } 753 754 if ($entries) { 755 $count = 0; 756 foreach ($entries as $entry) { 757 $blogentry = new blog_entry(null, $entry); 758 759 // Get the required blog entry data to render it. 760 $blogentry->prepare_render(); 761 echo $output->render($blogentry); 762 763 $count++; 764 } 765 766 echo $OUTPUT->render($pagingbar); 767 768 if (!$count) { 769 print '<br /><div style="text-align:center">'. get_string('noentriesyet', 'blog') .'</div><br />'; 770 } 771 772 print $morelink.'<br />'."\n"; 773 return; 774 } 775 } 776 777 // Find the base url from $_GET variables, for print_paging_bar. 778 public function get_baseurl() { 779 $getcopy = $_GET; 780 781 unset($getcopy['blogpage']); 782 783 if (!empty($getcopy)) { 784 $first = false; 785 $querystring = ''; 786 787 foreach ($getcopy as $var => $val) { 788 if (!$first) { 789 $first = true; 790 $querystring .= "?$var=$val"; 791 } else { 792 $querystring .= '&'.$var.'='.$val; 793 $hasparam = true; 794 } 795 } 796 } else { 797 $querystring = '?'; 798 } 799 800 return strip_querystring(qualified_me()) . $querystring; 801 802 } 803 } 804 805 /** 806 * Abstract class for blog_filter objects. 807 * A set of core filters are implemented here. To write new filters, you need to subclass 808 * blog_filter and give it the name of the type you want (for example, blog_filter_entry). 809 * The blog_filter abstract class will automatically use it when the filter is added to the 810 * URL. The first parameter of the constructor is the ID of your filter, but it can be a string 811 * or have any other meaning you wish it to have. The second parameter is called $type and is 812 * used as a sub-type for filters that have a very similar implementation (see blog_filter_context for an example) 813 */ 814 abstract class blog_filter { 815 /** 816 * An array of strings representing the available filter types for each blog_filter. 817 * @var array $availabletypes 818 */ 819 public $availabletypes = array(); 820 821 /** 822 * The type of filter (for example, types of blog_filter_context are site, course and module) 823 * @var string $type 824 */ 825 public $type; 826 827 /** 828 * The unique ID for a filter's associated record 829 * @var int $id 830 */ 831 public $id; 832 833 /** 834 * An array of table aliases that are used in the WHERE conditions 835 * @var array $tables 836 */ 837 public $tables = array(); 838 839 /** 840 * An array of WHERE conditions 841 * @var array $conditions 842 */ 843 public $conditions = array(); 844 845 /** 846 * An array of SQL params 847 * @var array $params 848 */ 849 public $params = array(); 850 851 /** 852 * An array of filter types which this particular filter type overrides: their conditions will not be evaluated 853 */ 854 public $overrides = array(); 855 856 public function __construct($id, $type=null) { 857 $this->id = $id; 858 $this->type = $type; 859 } 860 861 /** 862 * TODO This is poor design. A parent class should not know anything about its children. 863 * The default case helps to resolve this design issue 864 */ 865 public static function get_instance($id, $type) { 866 867 switch ($type) { 868 case 'site': 869 case 'course': 870 case 'module': 871 return new blog_filter_context($id, $type); 872 break; 873 874 case 'group': 875 case 'user': 876 return new blog_filter_user($id, $type); 877 break; 878 879 case 'tag': 880 return new blog_filter_tag($id); 881 break; 882 883 default: 884 $classname = "blog_filter_$type"; 885 if (class_exists($classname)) { 886 return new $classname($id, $type); 887 } 888 } 889 } 890 } 891 892 /** 893 * This filter defines the context level of the blog entries being searched: site, course, module 894 */ 895 class blog_filter_context extends blog_filter { 896 /** 897 * Constructor 898 * 899 * @param string $type 900 * @param int $id 901 */ 902 public function __construct($id=null, $type='site') { 903 global $SITE, $CFG, $DB; 904 905 if (empty($id)) { 906 $this->type = 'site'; 907 } else { 908 $this->id = $id; 909 $this->type = $type; 910 } 911 912 $this->availabletypes = array('site' => get_string('site'), 913 'course' => get_string('course'), 914 'module' => get_string('activity')); 915 916 switch ($this->type) { 917 case 'course': // Careful of site course! 918 // Ignore course filter if blog associations are not enabled. 919 if ($this->id != $SITE->id && !empty($CFG->useblogassociations)) { 920 $this->overrides = array('site'); 921 $context = context_course::instance($this->id); 922 $this->tables['ba'] = 'blog_association'; 923 $this->conditions[] = 'p.id = ba.blogid'; 924 $this->conditions[] = 'ba.contextid = '.$context->id; 925 break; 926 } else { 927 // We are dealing with the site course, do not break from the current case. 928 } 929 930 case 'site': 931 // No special constraints. 932 break; 933 case 'module': 934 if (!empty($CFG->useblogassociations)) { 935 $this->overrides = array('course', 'site'); 936 937 $context = context_module::instance($this->id); 938 $this->tables['ba'] = 'blog_association'; 939 $this->tables['p'] = 'post'; 940 $this->conditions = array('p.id = ba.blogid', 'ba.contextid = ?'); 941 $this->params = array($context->id); 942 } 943 break; 944 } 945 } 946 } 947 948 /** 949 * This filter defines the user level of the blog entries being searched: a userid or a groupid. 950 * It can be combined with a context filter in order to refine the search. 951 */ 952 class blog_filter_user extends blog_filter { 953 public $tables = array('u' => 'user'); 954 955 /** 956 * Constructor 957 * 958 * @param string $type 959 * @param int $id 960 */ 961 public function __construct($id=null, $type='user') { 962 global $CFG, $DB, $USER; 963 $this->availabletypes = array('user' => get_string('user'), 'group' => get_string('group')); 964 965 if (empty($id)) { 966 $this->id = $USER->id; 967 $this->type = 'user'; 968 } else { 969 $this->id = $id; 970 $this->type = $type; 971 } 972 973 if ($this->type == 'user') { 974 $this->conditions = array('u.id = ?'); 975 $this->params = array($this->id); 976 $this->overrides = array('group'); 977 978 } else if ($this->type == 'group') { 979 $this->overrides = array('course', 'site'); 980 981 $this->tables['gm'] = 'groups_members'; 982 $this->conditions[] = 'p.userid = gm.userid'; 983 $this->conditions[] = 'gm.groupid = ?'; 984 $this->params[] = $this->id; 985 986 if (!empty($CFG->useblogassociations)) { // Only show blog entries associated with this course. 987 $coursecontext = context_course::instance($DB->get_field('groups', 'courseid', array('id' => $this->id))); 988 $this->tables['ba'] = 'blog_association'; 989 $this->conditions[] = 'gm.groupid = ?'; 990 $this->conditions[] = 'ba.contextid = ?'; 991 $this->conditions[] = 'ba.blogid = p.id'; 992 $this->params[] = $this->id; 993 $this->params[] = $coursecontext->id; 994 } 995 } 996 997 } 998 } 999 1000 /** 1001 * This filter defines a tag by which blog entries should be searched. 1002 */ 1003 class blog_filter_tag extends blog_filter { 1004 public $tables = array('t' => 'tag', 'ti' => 'tag_instance', 'p' => 'post'); 1005 1006 /** 1007 * Constructor 1008 * 1009 * @return void 1010 */ 1011 public function __construct($id) { 1012 global $DB; 1013 $this->id = $id; 1014 1015 $this->conditions = array('ti.tagid = t.id', 1016 "ti.itemtype = 'post'", 1017 'ti.itemid = p.id', 1018 't.id = ?'); 1019 $this->params = array($this->id); 1020 } 1021 } 1022 1023 /** 1024 * This filter defines a specific blog entry id. 1025 */ 1026 class blog_filter_entry extends blog_filter { 1027 public $conditions = array('p.id = ?'); 1028 public $overrides = array('site', 'course', 'module', 'group', 'user', 'tag'); 1029 1030 public function __construct($id) { 1031 $this->id = $id; 1032 $this->params[] = $this->id; 1033 } 1034 } 1035 1036 /** 1037 * This filter restricts the results to a time interval in seconds up to time() 1038 */ 1039 class blog_filter_since extends blog_filter { 1040 public function __construct($interval) { 1041 $this->conditions[] = 'p.lastmodified >= ? AND p.lastmodified <= ?'; 1042 $this->params[] = time() - $interval; 1043 $this->params[] = time(); 1044 } 1045 } 1046 1047 /** 1048 * Filter used to perform full-text search on an entry's subject, summary and content 1049 */ 1050 class blog_filter_search extends blog_filter { 1051 1052 public function __construct($searchterm) { 1053 global $DB; 1054 $this->conditions = array("(".$DB->sql_like('p.summary', '?', false)." OR 1055 ".$DB->sql_like('p.content', '?', false)." OR 1056 ".$DB->sql_like('p.subject', '?', false).")"); 1057 $this->params[] = "%$searchterm%"; 1058 $this->params[] = "%$searchterm%"; 1059 $this->params[] = "%$searchterm%"; 1060 } 1061 } 1062 1063 1064 /** 1065 * Renderable class to represent an entry attachment 1066 */ 1067 class blog_entry_attachment implements renderable { 1068 1069 public $filename; 1070 public $url; 1071 public $file; 1072 1073 /** 1074 * Gets the file data 1075 * 1076 * @param stored_file $file 1077 * @param int $entryid Attachment entry id 1078 */ 1079 public function __construct($file, $entryid) { 1080 1081 global $CFG; 1082 1083 $this->file = $file; 1084 $this->filename = $file->get_filename(); 1085 $this->url = file_encode_url($CFG->wwwroot . '/pluginfile.php', 1086 '/' . SYSCONTEXTID . '/blog/attachment/' . $entryid . '/' . $this->filename); 1087 } 1088 1089 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 20:29:05 2014 | Cross-referenced by PHPXref 0.7.1 |