diff --git a/mod/forum/lang/en/forum.php b/mod/forum/lang/en/forum.php index 457ebf010af..48ebfc6ed16 100644 --- a/mod/forum/lang/en/forum.php +++ b/mod/forum/lang/en/forum.php @@ -35,6 +35,8 @@ $string['allsubscribe'] = 'Subscribe to all forums'; $string['allunsubscribe'] = 'Unsubscribe from all forums'; $string['alreadyfirstpost'] = 'This is already the first post in the discussion'; $string['anyfile'] = 'Any file'; +$string['areaattachment'] = 'Attachments'; +$string['areapost'] = 'Messages'; $string['attachment'] = 'Attachment'; $string['attachment_help'] = 'You can optionally attach one or more files to a forum post. If you attach an image, it will be displayed after the message.'; $string['attachmentnopost'] = 'You cannot export attachments without a post id'; diff --git a/mod/forum/lib.php b/mod/forum/lib.php index fa68e428025..c357581fd08 100644 --- a/mod/forum/lib.php +++ b/mod/forum/lib.php @@ -4014,6 +4014,10 @@ function forum_print_attachments($post, $cm, $type) { } } +//////////////////////////////////////////////////////////////////////////////// +// File API // +//////////////////////////////////////////////////////////////////////////////// + /** * Lists all browsable file areas * @@ -4025,8 +4029,10 @@ function forum_print_attachments($post, $cm, $type) { * @return array */ function forum_get_file_areas($course, $cm, $context) { - $areas = array(); - return $areas; + return array( + 'attachment' => get_string('areaattachment', 'mod_forum'), + 'post' => get_string('areapost', 'mod_forum'), + ); } /** @@ -4052,11 +4058,28 @@ function forum_get_file_info($browser, $areas, $course, $cm, $context, $filearea return null; } - $fileareas = array('attachment', 'post'); - if (!in_array($filearea, $fileareas)) { + // filearea must contain a real area + if (!isset($areas[$filearea])) { return null; } + // this is enforced by {@link file_info_context_course} currently + if (!has_capability('moodle/course:managefiles', $context)) { + return null; + } + + // Note that forum_user_can_see_post() additionally allows access for parent roles + // and it explicitly checks qanda forum type, too. One day, when we stop requiring + // course:managefiles, we will need to extend this. + if (!has_capability('mod/forum:viewdiscussion', $context)) { + return null; + } + + if (is_null($itemid)) { + require_once($CFG->dirroot.'/mod/forum/locallib.php'); + return new forum_file_info_container($browser, $course, $cm, $context, $areas, $filearea); + } + if (!$post = $DB->get_record('forum_posts', array('id' => $itemid))) { return null; } @@ -4092,7 +4115,7 @@ function forum_get_file_info($browser, $areas, $course, $cm, $context, $filearea } $urlbase = $CFG->wwwroot.'/pluginfile.php'; - return new file_info_stored($browser, $context, $storedfile, $urlbase, $filearea, $itemid, true, true, false); + return new file_info_stored($browser, $context, $storedfile, $urlbase, $itemid, true, true, false, false); } /** @@ -4118,8 +4141,10 @@ function forum_pluginfile($course, $cm, $context, $filearea, $args, $forcedownlo require_course_login($course, true, $cm); - $fileareas = array('attachment', 'post'); - if (!in_array($filearea, $fileareas)) { + $areas = forum_get_file_areas($course, $cm, $context); + + // filearea must contain a real area + if (!isset($areas[$filearea])) { return false; } diff --git a/mod/forum/locallib.php b/mod/forum/locallib.php index a14038056cc..dd1b3affb32 100644 --- a/mod/forum/locallib.php +++ b/mod/forum/locallib.php @@ -391,3 +391,119 @@ class forum_portfolio_caller extends portfolio_module_caller_base { return array(PORTFOLIO_FORMAT_FILE, PORTFOLIO_FORMAT_RICHHTML, PORTFOLIO_FORMAT_PLAINHTML, PORTFOLIO_FORMAT_LEAP2A); } } + + +/** + * Class representing the virtual node with all itemids in the file browser + * + * @category files + * @copyright 2012 David Mudrak + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class forum_file_info_container extends file_info { + /** @var file_browser */ + protected $browser; + /** @var stdClass */ + protected $course; + /** @var stdClass */ + protected $cm; + /** @var string */ + protected $component; + /** @var stdClass */ + protected $context; + /** @var array */ + protected $areas; + /** @var string */ + protected $filearea; + + /** + * Constructor (in case you did not realize it ;-) + * + * @param file_browser $browser + * @param stdClass $course + * @param stdClass $cm + * @param stdClass $context + * @param array $areas + * @param string $filearea + */ + public function __construct($browser, $course, $cm, $context, $areas, $filearea) { + parent::__construct($browser, $context); + $this->browser = $browser; + $this->course = $course; + $this->cm = $cm; + $this->component = 'mod_forum'; + $this->context = $context; + $this->areas = $areas; + $this->filearea = $filearea; + } + + /** + * @return array with keys contextid, filearea, itemid, filepath and filename + */ + public function get_params() { + return array( + 'contextid' => $this->context->id, + 'component' => $this->component, + 'filearea' => $this->filearea, + 'itemid' => null, + 'filepath' => null, + 'filename' => null, + ); + } + + /** + * Can new files or directories be added via the file browser + * + * @return bool + */ + public function is_writable() { + return false; + } + + /** + * Should this node be considered as a folder in the file browser + * + * @return bool + */ + public function is_directory() { + return true; + } + + /** + * Returns localised visible name of this node + * + * @return string + */ + public function get_visible_name() { + return $this->areas[$this->filearea]; + } + + /** + * Returns list of children nodes + * + * @return array of file_info instances + */ + public function get_children() { + global $DB; + + $children = array(); + $itemids = $DB->get_records('files', array('contextid' => $this->context->id, 'component' => $this->component, + 'filearea' => $this->filearea), 'itemid DESC', "DISTINCT itemid"); + foreach ($itemids as $itemid => $unused) { + if ($child = $this->browser->get_file_info($this->context, 'mod_forum', $this->filearea, $itemid)) { + $children[] = $child; + } + } + + return $children; + } + + /** + * Returns parent file_info instance + * + * @return file_info or null for root + */ + public function get_parent() { + return $this->browser->get_file_info($this->context); + } +}