Skip to content

Commit

Permalink
Merge branch 'MDL-65252-master' of git://github.com/lameze/moodle
Browse files Browse the repository at this point in the history
  • Loading branch information
junpataleta committed Jul 6, 2021
2 parents 2f4647c + 2a95ac4 commit 761f1d7
Show file tree
Hide file tree
Showing 13 changed files with 368 additions and 638 deletions.
61 changes: 55 additions & 6 deletions mod/forum/classes/local/builders/exported_posts.php
Expand Up @@ -32,10 +32,9 @@
use mod_forum\local\factories\legacy_data_mapper as legacy_data_mapper_factory;
use mod_forum\local\factories\exporter as exporter_factory;
use mod_forum\local\factories\vault as vault_factory;
use context;
use mod_forum\local\factories\manager as manager_factory;
use core_tag_tag;
use moodle_exception;
use rating_manager;
use renderer_base;
use stdClass;

Expand Down Expand Up @@ -72,27 +71,31 @@ class exported_posts {
/** @var rating_manager $ratingmanager Rating manager */
private $ratingmanager;

/** @var manager_factory $managerfactory Manager factory */
private $managerfactory;

/**
* Constructor.
*
* @param renderer_base $renderer Core renderer
* @param legacy_data_mapper_factory $legacydatamapperfactory Legacy data mapper factory
* @param exporter_factory $exporterfactory Exporter factory
* @param vault_factory $vaultfactory Vault factory
* @param rating_manager $ratingmanager Rating manager
* @param manager_factory $managerfactory Manager factory
*/
public function __construct(
renderer_base $renderer,
legacy_data_mapper_factory $legacydatamapperfactory,
exporter_factory $exporterfactory,
vault_factory $vaultfactory,
rating_manager $ratingmanager
manager_factory $managerfactory
) {
$this->renderer = $renderer;
$this->legacydatamapperfactory = $legacydatamapperfactory;
$this->exporterfactory = $exporterfactory;
$this->vaultfactory = $vaultfactory;
$this->ratingmanager = $ratingmanager;
$this->managerfactory = $managerfactory;
$this->ratingmanager = $managerfactory->get_rating_manager();
}

/**
Expand Down Expand Up @@ -139,6 +142,7 @@ public function build(
$authorsbyid = $this->get_authors_for_posts($posts);
$authorcontextids = $this->get_author_context_ids(array_keys($authorsbyid));
$attachmentsbypostid = $this->get_attachments_for_posts($groupedposts);
$inlineattachments = $this->get_inline_attachments_for_posts($groupedposts);
$groupsbycourseandauthorid = $this->get_author_groups_from_posts($groupedposts);
$tagsbypostid = $this->get_tags_from_posts($posts);
$ratingbypostid = $this->get_ratings_from_posts($user, $groupedposts);
Expand All @@ -154,6 +158,12 @@ public function build(
'posts' => $groupedposts
] = $grouping;

// Exclude posts the user cannot see, such as certain posts in Q and A forums.
$capabilitymanager = $this->managerfactory->get_capability_manager($forum);
$groupedposts = array_filter($groupedposts, function($post) use ($capabilitymanager, $user, $discussion) {
return $capabilitymanager->can_view_post($user, $discussion, $post);
});

$forumid = $forum->get_id();
$courseid = $forum->get_course_record()->id;
$postsexporter = $this->exporterfactory->get_posts_exporter(
Expand All @@ -168,7 +178,8 @@ public function build(
$readreceiptcollectionbyforumid[$forumid] ?? null,
$tagsbypostid,
$ratingbypostid,
true
true,
$inlineattachments
);
['posts' => $exportedgroupedposts] = (array) $postsexporter->export($this->renderer);
$exportedposts = array_merge($exportedposts, $exportedgroupedposts);
Expand Down Expand Up @@ -261,6 +272,44 @@ private function get_author_context_ids(array $authorids) : array {
return $authorvault->get_context_ids_for_author_ids($authorids);
}

/**
* Load the list of all inline attachments for the posts. The list of attachments will be
* indexed by the post id.
*
* @param array $groupedposts List of posts grouped by discussions.
* @return stored_file[]
*/
private function get_inline_attachments_for_posts(array $groupedposts) : array {
$inlineattachmentsbypostid = [];
$postattachmentvault = $this->vaultfactory->get_post_attachment_vault();
$postsbyforum = array_reduce($groupedposts, function($carry, $grouping) {
['forum' => $forum, 'posts' => $posts] = $grouping;

$forumid = $forum->get_id();
if (!isset($carry[$forumid])) {
$carry[$forumid] = [
'forum' => $forum,
'posts' => []
];
}

$carry[$forumid]['posts'] = array_merge($carry[$forumid]['posts'], $posts);
return $carry;
}, []);

foreach ($postsbyforum as $grouping) {
['forum' => $forum, 'posts' => $posts] = $grouping;
$inlineattachments = $postattachmentvault->get_inline_attachments_for_posts($forum->get_context(), $posts);

// Have to loop in order to maintain the correct indexes since they are numeric.
foreach ($inlineattachments as $postid => $attachment) {
$inlineattachmentsbypostid[$postid] = $attachment;
}
}

return $inlineattachmentsbypostid;
}

/**
* Load the list of all attachments for the posts. The list of attachments will be
* indexed by the post id.
Expand Down
28 changes: 28 additions & 0 deletions mod/forum/classes/local/exporters/post.php
Expand Up @@ -273,6 +273,10 @@ protected static function define_other_properties() {
'multiple' => true,
'type' => $attachmentdefinition
],
'messageinlinefiles' => [
'multiple' => true,
'type' => stored_file_exporter::read_properties_definition(),
],
'tags' => [
'optional' => true,
'default' => null,
Expand Down Expand Up @@ -366,6 +370,7 @@ protected function get_other_values(renderer_base $output) {
$rating = $this->related['rating'];
$tags = $this->related['tags'];
$attachments = $this->related['attachments'];
$inlineattachments = $this->related['messageinlinefiles'];
$includehtml = $this->related['includehtml'];
$isdeleted = $post->is_deleted();
$isprivatereply = $post->is_private_reply();
Expand Down Expand Up @@ -409,6 +414,7 @@ protected function get_other_values(renderer_base $output) {
// Only bother loading the content if the user can see it.
$loadcontent = $canview && !$isdeleted;
$exportattachments = $loadcontent && !empty($attachments);
$exportinlineattachments = $loadcontent && !empty($inlineattachments);

if ($loadcontent) {
$subject = $post->get_subject();
Expand Down Expand Up @@ -478,6 +484,8 @@ protected function get_other_values(renderer_base $output) {
'discuss' => $discussurl ? $discussurl->out(false) : null,
],
'attachments' => ($exportattachments) ? $this->export_attachments($attachments, $post, $output, $canexport) : [],
'messageinlinefiles' => ($exportinlineattachments) ? $this->export_inline_attachments($inlineattachments,
$post, $output) : [],
'tags' => ($loadcontent && $hastags) ? $this->export_tags($tags) : [],
'html' => $includehtml ? [
'rating' => ($loadcontent && $hasrating) ? $output->render($rating) : null,
Expand Down Expand Up @@ -505,6 +513,7 @@ protected static function define_related() {
'context' => 'context',
'authorgroups' => 'stdClass[]',
'attachments' => '\stored_file[]?',
'messageinlinefiles' => '\stored_file[]?',
'tags' => '\core_tag_tag[]?',
'rating' => 'rating?',
'includehtml' => 'bool'
Expand Down Expand Up @@ -612,6 +621,25 @@ private function export_attachments(array $attachments, post_entity $post, rende
}, $attachments);
}

/**
* Get the exported inline attachments for a post.
*
* @param array $inlineattachments The list of inline attachments for the post
* @param post_entity $post The post being exported
* @param renderer_base $output Renderer base
* @return array
*/
private function export_inline_attachments(array $inlineattachments, post_entity $post, renderer_base $output) : array {

return array_map(function($attachment) use (
$output,
$post
) {
$exporter = new stored_file_exporter($attachment, ['context' => $this->related['context']]);
return $exporter->export($output);;
}, $inlineattachments);
}

/**
* Export the list of tags.
*
Expand Down
13 changes: 11 additions & 2 deletions mod/forum/classes/local/exporters/posts.php
Expand Up @@ -49,6 +49,8 @@ class posts extends exporter {
private $authorcontextids;
/** @var array $attachmentsbypostid List of attachments indexed by post id */
private $attachmentsbypostid;
/** @var array $inlineattachmentsbypostid List of inline attachments indexed by post id */
private $inlineattachmentsbypostid;
/** @var array $groupsbyauthorid List of author's groups indexed by author id */
private $groupsbyauthorid;
/** @var array $tagsbypostid List of tags indexed by post id */
Expand All @@ -67,6 +69,7 @@ class posts extends exporter {
* @param array $tagsbypostid List of tags indexed by post id
* @param array $ratingbypostid List of ratings indexed by post id
* @param array $related The related objects for exporting
* @param array $inlineattachmentsbypostid List of inline attachments indexed by post id
*/
public function __construct(
array $posts,
Expand All @@ -76,12 +79,14 @@ public function __construct(
array $groupsbyauthorid = [],
array $tagsbypostid = [],
array $ratingbypostid = [],
array $related = []
array $related = [],
array $inlineattachmentsbypostid = []
) {
$this->posts = $posts;
$this->authorsbyid = $authorsbyid;
$this->authorcontextids = $authorcontextids;
$this->attachmentsbypostid = $attachmentsbypostid;
$this->inlineattachmentsbypostid = $inlineattachmentsbypostid;
$this->groupsbyauthorid = $groupsbyauthorid;
$this->tagsbypostid = $tagsbypostid;
$this->ratingbypostid = $ratingbypostid;
Expand Down Expand Up @@ -113,6 +118,7 @@ protected function get_other_values(renderer_base $output) {
$authorsbyid = $this->authorsbyid;
$authorcontextids = $this->authorcontextids;
$attachmentsbypostid = $this->attachmentsbypostid;
$inlineattachmentsbypostid = $this->inlineattachmentsbypostid;
$groupsbyauthorid = $this->groupsbyauthorid;
$tagsbypostid = $this->tagsbypostid;
$ratingbypostid = $this->ratingbypostid;
Expand All @@ -125,20 +131,23 @@ function($post) use (
$groupsbyauthorid,
$tagsbypostid,
$ratingbypostid,
$output
$output,
$inlineattachmentsbypostid
) {
$authorid = $post->get_author_id();
$postid = $post->get_id();
$author = isset($authorsbyid[$authorid]) ? $authorsbyid[$authorid] : [];
$authorcontextid = isset($authorcontextids[$authorid]) ? $authorcontextids[$authorid] : null;
$attachments = isset($attachmentsbypostid[$postid]) ? $attachmentsbypostid[$postid] : [];
$inlineattachments = isset($inlineattachmentsbypostid[$postid]) ? $inlineattachmentsbypostid[$postid] : [];
$authorgroups = isset($groupsbyauthorid[$authorid]) ? $groupsbyauthorid[$authorid] : [];
$tags = isset($tagsbypostid[$postid]) ? $tagsbypostid[$postid] : [];
$rating = isset($ratingbypostid[$postid]) ? $ratingbypostid[$postid] : null;
$exporter = new post_exporter($post, array_merge($related, [
'author' => $author,
'authorcontextid' => $authorcontextid,
'attachments' => $attachments,
'messageinlinefiles' => $inlineattachments,
'authorgroups' => $authorgroups,
'tags' => $tags,
'rating' => $rating
Expand Down
2 changes: 1 addition & 1 deletion mod/forum/classes/local/factories/builder.php
Expand Up @@ -91,7 +91,7 @@ public function get_exported_posts_builder() : exported_posts_builder {
$this->legacydatamapperfactory,
$this->exporterfactory,
$this->vaultfactory,
$this->managerfactory->get_rating_manager()
$this->managerfactory
);
}

Expand Down
9 changes: 6 additions & 3 deletions mod/forum/classes/local/factories/exporter.php
Expand Up @@ -224,7 +224,8 @@ public static function get_discussion_summaries_export_structure() {
* @param array $tagsbypostid List of tags for each post indexed by post id
* @param rating[] $ratingbypostid List of ratings for each post indexed by post id
* @param bool $includehtml Include some pre-constructed HTML in the export
* @return post_exporter
* @param array $inlineattachmentsbypostid List of attachments for each post indexed by post id
* @return posts_exporter
*/
public function get_posts_exporter(
stdClass $user,
Expand All @@ -238,7 +239,8 @@ public function get_posts_exporter(
post_read_receipt_collection_entity $readreceiptcollection = null,
array $tagsbypostid = [],
array $ratingbypostid = [],
bool $includehtml = false
bool $includehtml = false,
array $inlineattachmentsbypostid = []
) : posts_exporter {
return new posts_exporter(
$posts,
Expand All @@ -257,7 +259,8 @@ public function get_posts_exporter(
'context' => $forum->get_context(),
'readreceiptcollection' => $readreceiptcollection,
'includehtml' => $includehtml
]
],
$inlineattachmentsbypostid
);
}

Expand Down
30 changes: 26 additions & 4 deletions mod/forum/classes/local/vaults/post_attachment.php
Expand Up @@ -44,8 +44,6 @@
class post_attachment {
/** The component for attachments */
private const COMPONENT = 'mod_forum';
/** File area for attachments */
private const FILE_AREA = 'attachment';
/** Sort the attachments by filename */
private const SORT = 'filename';
/** Don't include directories */
Expand All @@ -68,17 +66,18 @@ public function __construct(file_storage $filestorage) {
*
* @param context $context The (forum) context that the posts are in
* @param post_entity[] $posts The list of posts to load attachments for
* @param string $area The file storage area, can be 'attachment' or 'post' for inline attachments.
* @return array Post attachments indexed by post id
*/
public function get_attachments_for_posts(context $context, array $posts) {
private function get_area_attachments_for_posts(context $context, array $posts, string $area) {
$itemids = array_map(function($post) {
return $post->get_id();
}, $posts);

$files = $this->filestorage->get_area_files(
$context->id,
self::COMPONENT,
self::FILE_AREA,
$area,
$itemids,
self::SORT,
self::INCLUDE_DIRECTORIES
Expand All @@ -95,4 +94,27 @@ public function get_attachments_for_posts(context $context, array $posts) {
return $carry;
}, $filesbyid);
}

/**
* Get attachment for posts.
*
* @param context $context The (forum) context that the posts are in
* @param post_entity[] $posts The list of posts to load attachments for
* @return array Post attachments indexed by post id
*/
public function get_attachments_for_posts(context $context, array $posts) {
return $this->get_area_attachments_for_posts($context, $posts, 'attachment');
}

/**
* Get inline attachments for posts.
*
* @param context $context The (forum) context that the posts are in
* @param post_entity[] $posts The list of posts to load attachments for
* @return array Post attachments indexed by post id
*/
public function get_inline_attachments_for_posts(context $context, array $posts) {
return $this->get_area_attachments_for_posts($context, $posts, 'post');
}

}
10 changes: 0 additions & 10 deletions mod/forum/db/services.php
Expand Up @@ -48,16 +48,6 @@
'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE)
),

'mod_forum_get_forum_discussion_posts' => array(
'classname' => 'mod_forum_external',
'methodname' => 'get_forum_discussion_posts',
'classpath' => 'mod/forum/externallib.php',
'description' => 'Returns a list of forum posts for a discussion.',
'type' => 'read',
'capabilities' => 'mod/forum:viewdiscussion, mod/forum:viewqandawithoutposting',
'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE)
),

'mod_forum_get_forum_discussions_paginated' => array(
'classname' => 'mod_forum_external',
'methodname' => 'get_forum_discussions_paginated',
Expand Down

0 comments on commit 761f1d7

Please sign in to comment.