MDL-85706 message: implement messages datasource for custom reporting.
Create new entities for report data on messages/conversations, joined to the user entity, providing data for the reportbuilder editor.
This commit is contained in:
@@ -49,7 +49,9 @@ $string['contactblocked'] = 'Contact blocked';
|
||||
$string['contactrequests'] = 'Contact requests';
|
||||
$string['contactrequestsent'] = 'Contact request sent';
|
||||
$string['contacts'] = 'Contacts';
|
||||
$string['conversation'] = 'Conversation';
|
||||
$string['conversationactions'] = 'Conversation actions menu';
|
||||
$string['conversationtype'] = 'Type';
|
||||
$string['decline'] = 'Decline';
|
||||
$string['defaultmessageoutputs'] = 'Notification settings';
|
||||
$string['deleteallconfirm'] = "Are you sure you would like to delete this entire conversation? This will not delete it for other conversation participants.";
|
||||
@@ -214,6 +216,7 @@ $string['processorsettings'] = 'Processor settings';
|
||||
$string['providerenabled'] = 'Sending "{$a}" enabled status';
|
||||
$string['providerprocesorislocked'] = '"{$a->provider}" on "{$a->processor}" is locked on';
|
||||
$string['providerprocesorisdisallowed'] = '"{$a->provider}" on "{$a->processor}" is locked off';
|
||||
$string['recipient'] = 'Recipient';
|
||||
$string['removecontact'] = 'Remove contact';
|
||||
$string['removecontactconfirm'] = 'Are you sure you want to remove {$a} from your contacts?';
|
||||
$string['removecoursefilter'] = 'Remove filter for course {$a}';
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
<?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/>.
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace core_message\reportbuilder\datasource;
|
||||
|
||||
use core\lang_string;
|
||||
use core_message\reportbuilder\local\entities\{conversation, message};
|
||||
use core_reportbuilder\datasource;
|
||||
use core_reportbuilder\local\entities\user;
|
||||
use core_reportbuilder\local\filters\text;
|
||||
use core_reportbuilder\local\helpers\database;
|
||||
|
||||
/**
|
||||
* Messages datasource
|
||||
*
|
||||
* @package core_message
|
||||
* @copyright 2025 Paul Holden <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class messages extends datasource {
|
||||
/**
|
||||
* Return user friendly name of the datasource
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_name(): string {
|
||||
return get_string('messages', 'core_message');
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise report
|
||||
*/
|
||||
protected function initialise(): void {
|
||||
// Message.
|
||||
$messageentity = new message();
|
||||
$messagealias = $messageentity->get_table_alias('messages');
|
||||
|
||||
$this->set_main_table('messages', $messagealias);
|
||||
$this->add_entity($messageentity);
|
||||
|
||||
// Conversation.
|
||||
$conversationentity = new conversation();
|
||||
$conversationalias = $conversationentity->get_table_alias('message_conversations');
|
||||
$this->add_entity($conversationentity
|
||||
->add_join("LEFT JOIN {message_conversations} {$conversationalias}
|
||||
ON {$conversationalias}.id = {$messagealias}.conversationid"));
|
||||
|
||||
// Author.
|
||||
$authorentity = new user();
|
||||
$authoralias = $authorentity->get_table_alias('user');
|
||||
$this->add_entity($authorentity
|
||||
->add_join("LEFT JOIN {user} {$authoralias} ON {$authoralias}.id = {$messagealias}.useridfrom"));
|
||||
|
||||
// Recipient.
|
||||
$recipiententity = new user();
|
||||
$recipientalias = $recipiententity->get_table_alias('user');
|
||||
$membersalias = database::generate_alias();
|
||||
$this->add_entity($recipiententity
|
||||
->set_entity_name('recipient')
|
||||
->set_entity_title(new lang_string('recipient', 'core_message'))
|
||||
->add_joins($conversationentity->get_joins())
|
||||
->add_joins([
|
||||
"LEFT JOIN {message_conversation_members} {$membersalias}
|
||||
ON {$membersalias}.conversationid = {$conversationalias}.id
|
||||
AND {$membersalias}.userid != {$messagealias}.useridfrom",
|
||||
"LEFT JOIN {user} {$recipientalias} ON {$recipientalias}.id = {$membersalias}.userid",
|
||||
]));
|
||||
|
||||
// Add all columns/filters/conditions from entities to be available in custom reports.
|
||||
$this->add_all_from_entities();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the columns that will be added to the report as part of default setup
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function get_default_columns(): array {
|
||||
return [
|
||||
'user:fullname',
|
||||
'recipient:fullname',
|
||||
'message:message',
|
||||
'message:timecreated',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the default sorting that will be added to the report upon creation
|
||||
*
|
||||
* @return int[]
|
||||
*/
|
||||
public function get_default_column_sorting(): array {
|
||||
return [
|
||||
'user:fullname' => SORT_ASC,
|
||||
'recipient:fullname' => SORT_ASC,
|
||||
'message:timecreated' => SORT_ASC,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the filters that will be added to the report upon creation
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function get_default_filters(): array {
|
||||
return [
|
||||
'user:fullname',
|
||||
'recipient:fullname',
|
||||
'message:message',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the conditions that will be added to the report upon creation
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function get_default_conditions(): array {
|
||||
return [
|
||||
'message:message',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the condition values that will be set for the report upon creation
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_default_condition_values(): array {
|
||||
return [
|
||||
'message:message_operator' => text::IS_NOT_EMPTY,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,205 @@
|
||||
<?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/>.
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace core_message\reportbuilder\local\entities;
|
||||
|
||||
use core\lang_string;
|
||||
use core_message\api;
|
||||
use core_reportbuilder\local\entities\base;
|
||||
use core_reportbuilder\local\filters\{boolean_select, date, select, text};
|
||||
use core_reportbuilder\local\helpers\format;
|
||||
use core_reportbuilder\local\report\{column, filter};
|
||||
|
||||
/**
|
||||
* Conversation entity
|
||||
*
|
||||
* @package core_message
|
||||
* @copyright 2025 Paul Holden <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class conversation extends base {
|
||||
/**
|
||||
* Database tables that this entity uses
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
protected function get_default_tables(): array {
|
||||
return [
|
||||
'message_conversations',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* The default title for this entity
|
||||
*
|
||||
* @return lang_string
|
||||
*/
|
||||
protected function get_default_entity_title(): lang_string {
|
||||
return new lang_string('conversation', 'core_message');
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise the entity
|
||||
*
|
||||
* @return base
|
||||
*/
|
||||
public function initialise(): base {
|
||||
$columns = $this->get_all_columns();
|
||||
foreach ($columns as $column) {
|
||||
$this->add_column($column);
|
||||
}
|
||||
|
||||
// All the filters defined by the entity can also be used as conditions.
|
||||
$filters = $this->get_all_filters();
|
||||
foreach ($filters as $filter) {
|
||||
$this
|
||||
->add_filter($filter)
|
||||
->add_condition($filter);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns list of all available columns
|
||||
*
|
||||
* @return column[]
|
||||
*/
|
||||
protected function get_all_columns(): array {
|
||||
$conversationalias = $this->get_table_alias('message_conversations');
|
||||
|
||||
// Type.
|
||||
$columns[] = (new column(
|
||||
'type',
|
||||
new lang_string('conversationtype', 'core_message'),
|
||||
$this->get_entity_name(),
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->add_field("{$conversationalias}.type")
|
||||
->set_is_sortable(true)
|
||||
->add_callback(static function (?string $type): string {
|
||||
$types = [
|
||||
api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => new lang_string('individualconversations', 'core_message'),
|
||||
api::MESSAGE_CONVERSATION_TYPE_GROUP => new lang_string('groupconversations', 'core_message'),
|
||||
api::MESSAGE_CONVERSATION_TYPE_SELF => new lang_string('selfconversation', 'core_message'),
|
||||
];
|
||||
if ($type === null || !array_key_exists($type, $types)) {
|
||||
return '';
|
||||
}
|
||||
return (string) $types[$type];
|
||||
});
|
||||
|
||||
// Name.
|
||||
$columns[] = (new column(
|
||||
'name',
|
||||
new lang_string('name'),
|
||||
$this->get_entity_name(),
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->add_field("{$conversationalias}.name")
|
||||
->set_is_sortable(true)
|
||||
->add_callback(static function (?string $name): string {
|
||||
if ($name === null) {
|
||||
return '';
|
||||
}
|
||||
return format_string($name);
|
||||
});
|
||||
|
||||
// Enabled.
|
||||
$columns[] = (new column(
|
||||
'enabled',
|
||||
new lang_string('enabled', 'core_message'),
|
||||
$this->get_entity_name(),
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->set_type(column::TYPE_BOOLEAN)
|
||||
->add_field("{$conversationalias}.enabled")
|
||||
->set_is_sortable(true)
|
||||
->add_callback([format::class, 'boolean_as_text']);
|
||||
|
||||
// Time created.
|
||||
$columns[] = (new column(
|
||||
'timecreated',
|
||||
new lang_string('timecreated', 'core_reportbuilder'),
|
||||
$this->get_entity_name(),
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->set_type(column::TYPE_TIMESTAMP)
|
||||
->add_field("{$conversationalias}.timecreated")
|
||||
->set_is_sortable(true)
|
||||
->add_callback([format::class, 'userdate']);
|
||||
|
||||
return $columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return list of all available filters
|
||||
*
|
||||
* @return filter[]
|
||||
*/
|
||||
protected function get_all_filters(): array {
|
||||
$conversationalias = $this->get_table_alias('message_conversations');
|
||||
|
||||
// Type.
|
||||
$filters[] = (new filter(
|
||||
select::class,
|
||||
'type',
|
||||
new lang_string('conversationtype', 'core_message'),
|
||||
$this->get_entity_name(),
|
||||
"{$conversationalias}.type",
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->set_options([
|
||||
api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL => new lang_string('individualconversations', 'core_message'),
|
||||
api::MESSAGE_CONVERSATION_TYPE_GROUP => new lang_string('groupconversations', 'core_message'),
|
||||
api::MESSAGE_CONVERSATION_TYPE_SELF => new lang_string('selfconversation', 'core_message'),
|
||||
]);
|
||||
|
||||
// Name.
|
||||
$filters[] = (new filter(
|
||||
text::class,
|
||||
'name',
|
||||
new lang_string('name'),
|
||||
$this->get_entity_name(),
|
||||
"{$conversationalias}.name",
|
||||
))
|
||||
->add_joins($this->get_joins());
|
||||
|
||||
// Enabled.
|
||||
$filters[] = (new filter(
|
||||
boolean_select::class,
|
||||
'enabled',
|
||||
new lang_string('enabled', 'core_message'),
|
||||
$this->get_entity_name(),
|
||||
"{$conversationalias}.enabled",
|
||||
))
|
||||
->add_joins($this->get_joins());
|
||||
|
||||
// Time created.
|
||||
$filters[] = (new filter(
|
||||
date::class,
|
||||
'timecreated',
|
||||
new lang_string('timecreated', 'core_reportbuilder'),
|
||||
$this->get_entity_name(),
|
||||
"{$conversationalias}.timecreated",
|
||||
))
|
||||
->add_joins($this->get_joins());
|
||||
|
||||
return $filters;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
<?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/>.
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace core_message\reportbuilder\local\entities;
|
||||
|
||||
use core\lang_string;
|
||||
use core_reportbuilder\local\entities\base;
|
||||
use core_reportbuilder\local\filters\{date, text};
|
||||
use core_reportbuilder\local\helpers\format;
|
||||
use core_reportbuilder\local\report\{column, filter};
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
* Message entity
|
||||
*
|
||||
* @package core_message
|
||||
* @copyright 2025 Paul Holden <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class message extends base {
|
||||
/**
|
||||
* Database tables that this entity uses
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
protected function get_default_tables(): array {
|
||||
return [
|
||||
'messages',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* The default title for this entity
|
||||
*
|
||||
* @return lang_string
|
||||
*/
|
||||
protected function get_default_entity_title(): lang_string {
|
||||
return new lang_string('message', 'core_message');
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise the entity
|
||||
*
|
||||
* @return base
|
||||
*/
|
||||
public function initialise(): base {
|
||||
$columns = $this->get_all_columns();
|
||||
foreach ($columns as $column) {
|
||||
$this->add_column($column);
|
||||
}
|
||||
|
||||
// All the filters defined by the entity can also be used as conditions.
|
||||
$filters = $this->get_all_filters();
|
||||
foreach ($filters as $filter) {
|
||||
$this
|
||||
->add_filter($filter)
|
||||
->add_condition($filter);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns list of all available columns
|
||||
*
|
||||
* @return column[]
|
||||
*/
|
||||
protected function get_all_columns(): array {
|
||||
$messagealias = $this->get_table_alias('messages');
|
||||
|
||||
// Subject.
|
||||
$columns[] = (new column(
|
||||
'subject',
|
||||
new lang_string('subject'),
|
||||
$this->get_entity_name(),
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->add_field("{$messagealias}.subject")
|
||||
->set_is_sortable(true)
|
||||
->add_callback(static function (?string $subject): string {
|
||||
if ($subject === null) {
|
||||
return '';
|
||||
}
|
||||
return format_string($subject);
|
||||
});
|
||||
|
||||
// Message.
|
||||
$columns[] = (new column(
|
||||
'message',
|
||||
new lang_string('message', 'core_message'),
|
||||
$this->get_entity_name(),
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->add_fields("{$messagealias}.fullmessage, {$messagealias}.fullmessageformat, {$messagealias}.fullmessagetrust")
|
||||
->set_is_sortable(true)
|
||||
->add_callback(static function (?string $fullmessage, stdClass $message): string {
|
||||
if ($fullmessage === null) {
|
||||
return '';
|
||||
}
|
||||
return format_text($fullmessage, $message->fullmessageformat, ['trusted' => $message->fullmessagetrust]);
|
||||
});
|
||||
|
||||
// Time created.
|
||||
$columns[] = (new column(
|
||||
'timecreated',
|
||||
new lang_string('timecreated', 'core_reportbuilder'),
|
||||
$this->get_entity_name(),
|
||||
))
|
||||
->add_joins($this->get_joins())
|
||||
->set_type(column::TYPE_TIMESTAMP)
|
||||
->add_field("{$messagealias}.timecreated")
|
||||
->set_is_sortable(true)
|
||||
->add_callback([format::class, 'userdate']);
|
||||
|
||||
return $columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return list of all available filters
|
||||
*
|
||||
* @return filter[]
|
||||
*/
|
||||
protected function get_all_filters(): array {
|
||||
$messagealias = $this->get_table_alias('messages');
|
||||
|
||||
// Subject.
|
||||
$filters[] = (new filter(
|
||||
text::class,
|
||||
'subject',
|
||||
new lang_string('subject'),
|
||||
$this->get_entity_name(),
|
||||
"{$messagealias}.subject",
|
||||
))
|
||||
->add_joins($this->get_joins());
|
||||
|
||||
// Message.
|
||||
$filters[] = (new filter(
|
||||
text::class,
|
||||
'message',
|
||||
new lang_string('message', 'core_message'),
|
||||
$this->get_entity_name(),
|
||||
"{$messagealias}.fullmessage",
|
||||
))
|
||||
->add_joins($this->get_joins());
|
||||
|
||||
// Time created.
|
||||
$filters[] = (new filter(
|
||||
date::class,
|
||||
'timecreated',
|
||||
new lang_string('timecreated', 'core_reportbuilder'),
|
||||
$this->get_entity_name(),
|
||||
"{$messagealias}.timecreated",
|
||||
))
|
||||
->add_joins($this->get_joins());
|
||||
|
||||
return $filters;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,300 @@
|
||||
<?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/>.
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace core_message\reportbuilder\datasource;
|
||||
|
||||
use core\clock;
|
||||
use core_message\api;
|
||||
use core_message\tests\helper;
|
||||
use core_reportbuilder_generator;
|
||||
use core_reportbuilder\local\filters\{boolean_select, date, select, text};
|
||||
use core_reportbuilder\tests\core_reportbuilder_testcase;
|
||||
|
||||
/**
|
||||
* Unit tests for messages datasource
|
||||
*
|
||||
* @package core_message
|
||||
* @covers \core_message\reportbuilder\datasource\messages
|
||||
* @copyright 2025 Paul Holden <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
final class messages_test extends core_reportbuilder_testcase {
|
||||
/** @var clock $clock */
|
||||
private readonly clock $clock;
|
||||
|
||||
/**
|
||||
* Mock the clock
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
$this->clock = $this->mock_clock_with_frozen(1622502000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test default datasource
|
||||
*/
|
||||
public function test_datasource_default(): void {
|
||||
$this->resetAfterTest();
|
||||
|
||||
// Test subject.
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
$userone = $this->getDataGenerator()->create_and_enrol($course, 'student', ['firstname' => 'Zoe', 'lastname' => 'Zebra']);
|
||||
$usertwo = $this->getDataGenerator()->create_and_enrol($course, 'student', ['firstname' => 'Morris', 'lastname' => 'Moo']);
|
||||
$userthree = $this->getDataGenerator()->create_and_enrol($course, 'student', ['firstname' => 'Aaron', 'lastname' => 'Ant']);
|
||||
|
||||
$groupconversation = api::create_conversation(
|
||||
api::MESSAGE_CONVERSATION_TYPE_GROUP,
|
||||
[$userone->id, $usertwo->id, $userthree->id],
|
||||
);
|
||||
helper::send_fake_message_to_conversation($userone, $groupconversation->id, 'Are you somewhere feeling lonely?');
|
||||
|
||||
$this->clock->bump(HOURSECS);
|
||||
|
||||
$privateconversation = api::create_conversation(
|
||||
api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
|
||||
[$userone->id, $usertwo->id],
|
||||
);
|
||||
helper::send_fake_message_to_conversation($usertwo, $privateconversation->id, 'Or is someone loving you?');
|
||||
|
||||
/** @var core_reportbuilder_generator $generator */
|
||||
$generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
|
||||
$report = $generator->create_report(['name' => 'Messages', 'source' => messages::class, 'default' => 1]);
|
||||
|
||||
$content = $this->get_custom_report_content($report->get('id'));
|
||||
|
||||
// Default columns are author, recipient, message, time created. Sorted by author, recipient, time created.
|
||||
$this->assertEquals([
|
||||
[
|
||||
fullname($usertwo),
|
||||
fullname($userone),
|
||||
'<div class="text_to_html">Or is someone loving you?</div>',
|
||||
'Tuesday, 1 June 2021, 8:00 AM',
|
||||
],
|
||||
[
|
||||
fullname($userone),
|
||||
fullname($userthree),
|
||||
'<div class="text_to_html">Are you somewhere feeling lonely?</div>',
|
||||
'Tuesday, 1 June 2021, 7:00 AM',
|
||||
],
|
||||
[
|
||||
fullname($userone),
|
||||
fullname($usertwo),
|
||||
'<div class="text_to_html">Are you somewhere feeling lonely?</div>',
|
||||
'Tuesday, 1 June 2021, 7:00 AM',
|
||||
],
|
||||
], array_map('array_values', $content));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test datasource columns that aren't added by default
|
||||
*/
|
||||
public function test_datasource_non_default_columns(): void {
|
||||
$this->resetAfterTest();
|
||||
|
||||
// Test subject.
|
||||
$userone = $this->getDataGenerator()->create_user();
|
||||
$usertwo = $this->getDataGenerator()->create_user();
|
||||
|
||||
$conversation = api::create_conversation(
|
||||
api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
|
||||
[$userone->id, $usertwo->id],
|
||||
'My conversation',
|
||||
);
|
||||
helper::send_fake_message_to_conversation($userone, $conversation->id);
|
||||
|
||||
/** @var core_reportbuilder_generator $generator */
|
||||
$generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
|
||||
$report = $generator->create_report(['name' => 'Messages', 'source' => messages::class, 'default' => 0]);
|
||||
|
||||
// Message.
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'message:subject']);
|
||||
|
||||
// Conversation.
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'conversation:type']);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'conversation:name']);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'conversation:enabled']);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'conversation:timecreated']);
|
||||
|
||||
$content = $this->get_custom_report_content($report->get('id'));
|
||||
|
||||
$this->assertEquals([
|
||||
[
|
||||
'No subject',
|
||||
'Private',
|
||||
'My conversation',
|
||||
'Yes',
|
||||
'Tuesday, 1 June 2021, 7:00 AM',
|
||||
],
|
||||
], array_map('array_values', $content));
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for {@see test_datasource_filters}
|
||||
*
|
||||
* @return array[]
|
||||
*/
|
||||
public static function datasource_filters_provider(): array {
|
||||
return [
|
||||
// Message.
|
||||
'Message subject' => ['message:subject', [
|
||||
'message:subject_operator' => text::IS_EQUAL_TO,
|
||||
'message:subject_value' => 'No subject',
|
||||
], true],
|
||||
'Message subject (no match)' => ['message:subject', [
|
||||
'message:subject_operator' => text::IS_EQUAL_TO,
|
||||
'message:subject_value' => 'Another subject',
|
||||
], false],
|
||||
'Message content' => ['message:message', [
|
||||
'message:message_operator' => text::IS_EQUAL_TO,
|
||||
'message:message_value' => 'Hi',
|
||||
], true],
|
||||
'Message content (no match)' => ['message:message', [
|
||||
'message:message_operator' => text::IS_EQUAL_TO,
|
||||
'message:message_value' => 'Bye',
|
||||
], false],
|
||||
'Message time created' => ['message:timecreated', [
|
||||
'message:timecreated_operator' => date::DATE_RANGE,
|
||||
'message:timecreated_from' => 1622502000,
|
||||
], true],
|
||||
'Message time created (no match)' => ['message:timecreated', [
|
||||
'message:timecreated_operator' => date::DATE_RANGE,
|
||||
'message:timecreated_to' => 1622502000,
|
||||
], false],
|
||||
|
||||
// Conversation.
|
||||
'Conversation type' => ['conversation:type', [
|
||||
'conversation:type_operator' => select::EQUAL_TO,
|
||||
'conversation:type_value' => api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
|
||||
], true],
|
||||
'Conversation type (no match)' => ['conversation:type', [
|
||||
'conversation:type_operator' => select::EQUAL_TO,
|
||||
'conversation:type_value' => api::MESSAGE_CONVERSATION_TYPE_GROUP,
|
||||
], false],
|
||||
'Conversation name' => ['conversation:name', [
|
||||
'conversation:name_operator' => text::IS_EQUAL_TO,
|
||||
'conversation:name_value' => 'My conversation',
|
||||
], true],
|
||||
'Conversation name (no match)' => ['conversation:name', [
|
||||
'conversation:name_operator' => text::IS_EQUAL_TO,
|
||||
'conversation:name_value' => 'Another conversation',
|
||||
], false],
|
||||
'Conversation enabled' => ['conversation:enabled', [
|
||||
'conversation:enabled_operator' => boolean_select::CHECKED,
|
||||
], true],
|
||||
'Conversation enabled (no match)' => ['conversation:enabled', [
|
||||
'conversation:enabled_operator' => boolean_select::NOT_CHECKED,
|
||||
], false],
|
||||
'Conversation time created' => ['conversation:timecreated', [
|
||||
'conversation:timecreated_operator' => date::DATE_RANGE,
|
||||
'conversation:timecreated_from' => 1622502000,
|
||||
], true],
|
||||
'Conversation time created (no match)' => ['conversation:timecreated', [
|
||||
'conversation:timecreated_operator' => date::DATE_RANGE,
|
||||
'conversation:timecreated_to' => 1622502000,
|
||||
], false],
|
||||
|
||||
// Author.
|
||||
'User firstname' => ['user:firstname', [
|
||||
'user:firstname_operator' => text::IS_EQUAL_TO,
|
||||
'user:firstname_value' => 'Zoe',
|
||||
], true],
|
||||
'User firstname (no match)' => ['user:firstname', [
|
||||
'user:firstname_operator' => text::IS_EQUAL_TO,
|
||||
'user:firstname_value' => 'Aaron',
|
||||
], false],
|
||||
|
||||
// Recipient.
|
||||
'Recipient firstname' => ['recipient:firstname', [
|
||||
'recipient:firstname_operator' => text::IS_EQUAL_TO,
|
||||
'recipient:firstname_value' => 'Aaron',
|
||||
], true],
|
||||
'Recipient firstname (no match)' => ['recipient:firstname', [
|
||||
'recipient:firstname_operator' => text::IS_EQUAL_TO,
|
||||
'recipient:firstname_value' => 'Zoe',
|
||||
], false],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test datasource filters
|
||||
*
|
||||
* @param string $filtername
|
||||
* @param array $filtervalues
|
||||
* @param bool $expectmatch
|
||||
*
|
||||
* @dataProvider datasource_filters_provider
|
||||
*/
|
||||
public function test_datasource_filters(string $filtername, array $filtervalues, bool $expectmatch): void {
|
||||
$this->resetAfterTest();
|
||||
|
||||
// Test subject.
|
||||
$userone = $this->getDataGenerator()->create_user(['firstname' => 'Zoe']);
|
||||
$usertwo = $this->getDataGenerator()->create_user(['firstname' => 'Aaron']);
|
||||
|
||||
$conversation = api::create_conversation(
|
||||
api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
|
||||
[$userone->id, $usertwo->id],
|
||||
'My conversation',
|
||||
);
|
||||
helper::send_fake_message_to_conversation($userone, $conversation->id, 'Hi');
|
||||
|
||||
/** @var core_reportbuilder_generator $generator */
|
||||
$generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
|
||||
|
||||
// Create report containing single column, and given filter.
|
||||
$report = $generator->create_report(['name' => 'Messages', 'source' => messages::class, 'default' => 0]);
|
||||
$generator->create_column(['reportid' => $report->get('id'), 'uniqueidentifier' => 'message:subject']);
|
||||
|
||||
// Add filter, set it's values.
|
||||
$generator->create_filter(['reportid' => $report->get('id'), 'uniqueidentifier' => $filtername]);
|
||||
$content = $this->get_custom_report_content($report->get('id'), 0, $filtervalues);
|
||||
|
||||
if ($expectmatch) {
|
||||
$this->assertEquals([
|
||||
['No subject'],
|
||||
], array_map('array_values', $content));
|
||||
} else {
|
||||
$this->assertEmpty($content);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stress test datasource
|
||||
*
|
||||
* In order to execute this test PHPUNIT_LONGTEST should be defined as true in phpunit.xml or directly in config.php
|
||||
*/
|
||||
public function test_stress_datasource(): void {
|
||||
if (!PHPUNIT_LONGTEST) {
|
||||
$this->markTestSkipped('PHPUNIT_LONGTEST is not defined');
|
||||
}
|
||||
|
||||
$this->resetAfterTest();
|
||||
|
||||
// Test subject.
|
||||
$userone = $this->getDataGenerator()->create_user();
|
||||
$usertwo = $this->getDataGenerator()->create_user();
|
||||
|
||||
$conversation = api::create_conversation(api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL, [$userone->id, $usertwo->id]);
|
||||
helper::send_fake_message_to_conversation($userone, $conversation->id);
|
||||
|
||||
$this->datasource_stress_test_columns(messages::class);
|
||||
$this->datasource_stress_test_columns_aggregation(messages::class);
|
||||
$this->datasource_stress_test_conditions(messages::class, 'message:subject');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user