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.

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
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

idINTComment ID.

true


useridINTThe user who clicked like on a component.

areaCHAR(20)

The area name.



componentCHAR(20)The component name.

instanceidINTThe component's instance ID.

parentidINTRemember comment ID for reply.

timecreatedINTTimestamp.

formatINTFormat content.

contentTEXTUser's comment.

timemodifiedINTTimestamp.

timedeletedINTTimestamp.

reasondeletedINT 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.