Totara comments

Totara comments

What are Totara comments?

Totara comments is a new plugin introduced in Totara 13. This plugin is used with the Weka editor to allow users to comment and reply to other users' comments on your site. This is a standalone plugin and can easily be used by other plugins.

How Totara comments work

The Totara comments plugin has its own graphQL queries and comment helper class which provides CRUD functions. For capabilities, the Totara comments plugin introduces a new approach (Interactor) to do the capability check and Interactor will return to Vue template along with comments. 

The diagram below shows how the plugin works.

A diagram showing how Totara comments work.
A diagram showing how Totara comments work.

Here we use comment loader to load records from the database and map records into the comment model. In other words, the comment model is like a wrapper class of comment entity.

Main API classes and methods

Namespaces and classes

Class 

Purpose

Class 

Purpose

totara_comment\entity\comment

Stores comment record.

totara_comment\event

Comment events and lets other plugins observe the events.

totara_comment\formatter

Formats the comment/reply content.

totara_comment\interactor

Checks the actor's capability.

totara_comment\loader\comment_loader

 

Loads comment records from DB and map into comment models. It works as data provider, in other words, if front-end needs to render comments into page, we call loader to help web API to load the data and return data to Web API through the comment modal.

totara_comment\pagination

Implements comment pagination .

totara_comment\userdata

Purge and export comment that related to the user.

totara_comment\watcher

Watches hooks from other plugins.

totara_comment\webapi\resolver\mutation

totara_comment\webapi\resolver\query

totara_comment\webapi\resolver\type

Web API to provide the interface to front-end.

Totara comments have the following structure:

Name

Type

Note

PK

FK

Name

Type

Note

PK

FK

id

INT

Comment ID.

true

 

userid

INT

The user who clicked like on a component.

 

 

area

CHAR(20)

The area name.

 

 

component

CHAR(20)

The component name.

 

 

instanceid

INT

The component's instance ID.

 

 

parentid

INT

Remember comment ID for reply.

 

 

timecreated

INT

Timestamp.

 

 

format

INT

Format content.

 

 

content

TEXT

User's comment.

 

 

timemodified

INT

Timestamp.

 

 

timedeleted

INT

Timestamp.

 

 

reasondeleted

INT 

Reason why the comment was deleted.

 

 

How to add comments to a component

To use Totara comments, the developer needs to create a specific folder and files under your component /totata_comment/comment_resolver.

// example your comment +-- classes | +-- totara_comment | +-- comment_resolver.php

Enable weka_editor:

weka_editor.php
// under db direotory, create editor_weka.php $editor = [ 'comment' => [ 'showtoolbar' => false, 'includeextensions' => [ '\editor_weka\extension\hashtag', '\editor_weka\extension\mention' ] ] ];

Clarify area for weka_editor:

<Weka :id="id" component="totara_playlist" area="content" :doc="content.doc" :placeholder="$str('description', 'engage_article')" @update="handleUpdate" />

Add dependence into version.php:

version.php
$plugin->dependencies = [ 'totara_comment' => 2019101500, 'editor_weka' => 2019111800, ];

Triggering and observing event (optional)

While it is not necessary to use comment events for this, it is considered good practice to trigger an event to observe it for processing because it is facilitates decoupling and predictability of code.

To do it, make sure that event exists (the developer can check totara_comment\classes\event).

db/events
$observers = [ //... [ 'eventname' => \totara_comment\event\comment_created::class, 'callback' => [\engage_article\observer\comment_observer::class, 'on_comment_created'] ], [ 'eventname' => \totara_comment\event\reply_created::class, 'callback' => [\engage_article\observer\comment_observer::class, 'on_reply_created'] ], [ 'eventname' => \totara_comment\event\comment_updated::class, 'callback' => [\engage_article\observer\comment_observer::class, 'on_comment_updated'] ] //... ];

Event handler in the callback:

observer/comment_observer
final class comment_observer { //... public static function on_comment_created(comment_created $event): void { $record = $event->get_record_snapshot(comment::get_entity_table(), $event->objectid); $comment = comment::from_record($record); static::handle_comment($comment); } public static function on_comment_updated(comment_updated $event): void { $record = $event->get_record_snapshot(comment::get_entity_table(), $event->objectid); $comment = comment::from_record($record); static::handle_comment($comment); } //... }

Best practices

Components do not need to handle comment graphQL queries and mutation, all of them will be handled in the totara_comment, the components just need to make comment_resolver based on the component requirement for comment and for decoupling, the components only need to event handler in the callback to satisfy their need.