Upgrading to ME v28.0
Upgrading Guide for the release for v28.0
Important Upgrade Notes
Release 1.28 contains version changes that are important to note:
Laravel Update from 9.x -> 11.x
beyondcode/laravel-websockets -> Laravel/Reverb
Laminas Replacements
Node.js version update from 14.18.3 -> 18.x and higher
Moment.js -> day.js
ADODB 5.21.* -> 5.22.*
Please review the Important Changes section before proceeding.
Upgrading to v28.0
For traditonal upgrading see: Part 1: Source Code Update
Incremental upgrading
Elentra ME v28.0 has been tagged continuously during development process which allows the ability to upgrade incrementally instead of all at once.
There are 48 patches releases that contain the pattern of v28.0-rc.X
. Upgrading incrementally allows to upgrade patch by patch or to upgrade by multiple patches.
There are two types of patch releases, Technical and Product patch releases. Product patch releases contains a title of module worked on:
v28.0-rc.44 Exam Improvements
Each important upgrades will contain a patch release number to identify when the change has been merged in.
Important Changes - Library Upgrades
This release contains significant changes, and you will need to regression test all of your customisation in case these updates break them.
Laravel 9.x -> 11.x
Laravel 9.x → 10.x: Elentra ME v28.0-rc.3
Laravel 10.x upgrade requires change to DB::raw See: https://github.com/ElentraProject/elentra-1x-api/pull/1079
Laravel 10.x → 11.x: Elentra ME v28.0-rc.43
Laravel Future Support:
9
8.0 - 8.2
February 8th, 2022
August 8th, 2023
February 6th, 2024
10
8.1 - 8.3
February 14th, 2023
August 6th, 2024
February 4th, 2025
11
8.2 - 8.4
March 12th, 2024
September 3rd, 2025
March 12th, 2026
12
8.2 - 8.4
Q1 2025
Q3 2026
Q1 2027
Laravel Web-sockets
Changes were made to remove the web-socket library beyondcode/laravel-websockets
which has been abandoned by the maintainers.
Please See: https://github.com/beyondcode/laravel-websockets
To resolve this issue, beyondcode/laravel-websockets
has been replaced with Laravel Reverb which has been released March 12th 2024.
This change requires update across all Elentra repositories.
ME: Elentra ME v28.0-rc.17 API: v11.0-rc.6 EJS2: v2.7.4 DEV: v5.0.3
Configuration notes
In general, the configuration should be managed exclusively through the www-root/core/config/settings.inc.php
file. This means you don't need to worry about the .env
files in elentra-1x-api
and elentra-2x-js
. The values in the .env
files will be ignored if corresponding values are set in settings.inc.php
.
// Public websocket settings
define("WEBSOCKETS_AUTH_ENDPOINT", "/api/v2/broadcasting/auth"); // Endpoint for authenticating websocket connections
define("WEBSOCKETS_SERVER", "localhost"); // Hostname or address of the websocket server e.g.: elentra.med.university.edu
define("WEBSOCKETS_PORT", 6001); // Port number for websocket connections Note: Default port is usually 443 for HTTPS
// Server websocket settings: specify the host and port on which to run the websockets server (reverb by default) itself, (usually 0.0.0.0:6001)
define("WEBSOCKETS_SERVER_HOST", "0.0.0.0");
define("WEBSOCKETS_SERVER_PORT", 6001);
define("WEBSOCKETS_SCHEME", "http"); // Scheme used for websocket connections Note: Consider using 'https' for secure websocket connections
define("WEBSOCKETS_CLUSTER", "");
// Websocket's app credentials (you may leave them as they are for development mode)
define("WEBSOCKETS_APP_ID", AUTH_APP_ID);
define("WEBSOCKETS_APP_KEY", "elentra-pusher-key");
define("WEBSOCKETS_APP_SECRET", "elentra-app-secret");
Setup Instructions
Before running the php artisan reverb:start
command, ensure you execute the following commands, assuming you have an up-to-date branch:
cd /var/www/vhosts/elentra-1x-me
composer install
composer update
cd /var/www/vhosts/elentra-1x-me/www-root/core/library/vendor/elentrapackages/elentra-1x-api
composer install
composer update
php artisan cache:clear
php artisan optimize:clear
php artisan reverb:start
Laminas
Elentra ME has been using Laminas/Zend for a very long time that offers the same features that Laravel also supports. There was no need to have two frameworks that offer the same features, therefore v28.0 has removed Laminas libraries that can be replaced.
Replace Laminas Cache
Patch: Elentra ME v28.0-rc.4
Laminas cache was replaced with Laravel Cache by creating a wrapper around the Laminas Cache methods to ensure that no invasive changes are needed
Replace Laminas Feed and Laminas HTTP
Patch: Elentra ME v28.0-rc.4
Laminas Feed and Laminas HTTP were being used for RSS feeds that are rendered on the dashboard. This was replaced with vedmant/laravel-feed-reader
on Elentra-1x-api.
Remove Laminas JSON and Laminas MATH
Laminas JSON was being used decode JSON which was replace with PHP native method of json_decode.
Laminas MATH was not being used within the application and can be removed
Node.js
Patch: Elentra ME v28.0-rc.1
Elentra EJS2 now supports Node.js version 18 and higher. Ensure that custom added libraries are compatible with Node.js version 18 and higher
Moment.js
Patch: Elentra ME v28.0-rc.8
Moment.js has been deprecated and was replace by days.js. The change requires to replace moment()
with dayjs()
- var start_date = moment(state.min_date).unix();
- var end_date = moment(state.max_date).subtract(1, 'second').unix();
+ var start_date = dayjs(state.min_date).unix();
+ var end_date = dayjs(state.max_date).subtract(1, 'second').unix();
Ensure that any uses of momont.js is replaced with dayjs
ADODB
Paches: Elentra ME v28.0-rc.40, Elentra ME v28.0-rc.43
There are significant changes with the ADODB upgrade from 5.21.* to 5.22.* that contains error handing and data integrity checks within the base class. These changes require a large amount of attention to ensure that current functionality is not impacted. There is a new setting called “STRICT_MODE” which allows developers to turn on some checks, it is highly recommended to turn this off in production mode.
Invalid Constraints
A new data integrity check is to ensure that all constraint columns must have an associated class attribute with same name. Code Snippet of Check:
if (!in_array($constraint_key, $class_vars)) {
throw new Exception("Invalid constraint key ". $constraint_key ." for ". __FUNCTION__ ." in ". get_called_class(). " model.");
}
Example Error
Example Class:
class myModel extends Models_Base {
private $id, $name;
}
Example Table:
id | name | deleted_date
Example call:
return $self->fetchRow(array(
array("key" => "id", "value" => $id, "method" => "="),
array("key" => "name", "value" => $name, "method" => "="),
array("key" => "deleted_date", "value" => null, "method" => "IS")
));
Since delete_date
is not a class attribute of myModel class, an error is rendered.
Example of resolving the error:
class myModel extends Models_Base {
private $id,
$name,
$delete_date;
}
No Constraints
This check is to ensure that fetchAll
and fetchRow
have constraints passed as a non-empty array or as an empty value. fetchAll
without a constraint should use getAll ADODB method instead.
Code Snippet of Check:
if (!is_array($constraints) || empty($constraints)) {
throw new Exception("No constraints provided for ". __FUNCTION__ ." in ". get_called_class(). " model.");
}
Example Error:
return $self->fetchRow();
Failed Query
Query failure check has been implemented that will throw an error if the query fails and the exception returns the database error message back for logging. Query failures originally would return false then pass the boolean up the stack which cause an ambiguous datatype between no results and query fail.
Code Snippet of Check:
if ($result === false && $db->ErrorMsg()) {
throw new Exception("Error fetching row ". get_called_class(). " record: " . $db->ErrorMsg());
}
This might uncover previously unknown failing queries as a widely used pattern in Elentra is to pass false for no results but also pass false to failing queries.
Constraint and Value EQ Check
A query integrity check was added to ensure that no queries is executed with an =
constraint using value of null
. The reason for this is that any query that runs with an =
constraint with null
value will always return an empty results therefore should use IS NULL
or IS NOT NULL
instead.
Code Snippet of Check:
if (is_null($value)) {
Models_Base::triggerStrict("Value cannot be null, use `IS` or `IS NOT` instead.");
}
Example Error:
$name = null;
return $self->fetchRow(array(
array("key" => "id", "value" => $id, "method" => "="),
array("key" => "name", "value" => $name, "method" => "=")
));
Example of resolving the error:
Resolving this error is more difficult and requires investigations since a condition of the query doesn’t contain a value.
// Example of the most common issue:
$results = $self->fetchRow(array(
array("key" => "deleted_date", "value" => null, "method" => "=")
));
// Should be:
$results = $self->fetchRow(array(
array("key" => "deleted_date", "value" => null, "method" => "IS")
));
// Results will be an empty result
Failed Query Throws an Exception
With Strict Mode on, any ADODB query failure will throw an exception that will render an error message to the end user.
if (defined("STRICT_MODE") && STRICT_MODE) {
require_once(ENTRADA_ABSOLUTE . "/core/includes/database-exception-handler.inc.php");
$db->raiseErrorFn = 'database_exception_handler';
}
Consortium Members can edit the exception behaviour by editing database-exception-handler.inc.php
<?php
/*
This method is used to handle database exceptions. It is called by the database class when an exception is thrown.
The method will throw a new exception with the error message and error number.
*/
function database_exception_handler(
string $dbms,
string $fn,
int $errno,
string $errmsg,
string $p1,
array|bool $p2,
object &$thisConnection
) {
// Falls back to the default error handler
throw new Exception(
"Database Exception: " . $dbms . " error in " . $fn . "(): " . $errmsg . " (" . $errno . ")",
$errno
);
}
Strict Mode
Strict mode was introduced to prevent an overwhelming amount of fatal errors during production. If a developer determines that an exception should under a strict mode can call the method triggerStrict
in order to prevent the exception.
private static function triggerStrict($message) {
application_log("error", $message);
if (defined("STRICT_MODE") && STRICT_MODE) {
throw new Exception($message);
}
}
Important Changes - Architectural Changes
Replacing Prototype with JQuery
Patches: Elentra ME v28.0-rc.1, Elentra ME v28.0-rc.2, Elentra ME v28.0-rc.3
Prototype is a JS library that has been part of the Elentra application since the first release. The library has not been updated since Sept. 2015 which the library scriptaculous is dependant on also hasn’t been updated from Dec. 2010.
Prototype will override JS event listeners of “show” and “hide” that bootstrap relies on. For this reason, a effort was made forward to remove prototype and scriptaculous from Elentra ME. Since Prototype is used throughout the application, additional logic was added on spa.head.php file:
<?php
$url = $_SERVER['REQUEST_URI'];
// Admin Events Page has removed Prototype therefore DO NOT include it
$include_scripts = true;
$excluded_pages = ['/events', '/admin/events', '/dashboard', '/communities'];
foreach ($excluded_pages as $page) {
if (strncmp($url, $page, strlen($page)) === 0) {
$include_scripts = false; // Don't include the scripts if the current page matches any excluded page
break;
}
}
// Include the scripts if the flag is still
if ($include_scripts) {
?>
<!-- Legacy Prototype -->
<script src="<?php echo script(ENTRADA_RELATIVE . '/javascript/scriptaculous/prototype.js'); ?>"></script>
<script src="<?php echo script(ENTRADA_RELATIVE . '/javascript/scriptaculous/scriptaculous.js'); ?>"></script>
<script src="<?php echo script(ENTRADA_RELATIVE . '/javascript/livepipe/livepipe.js'); ?>"></script>
<script src="<?php echo script(ENTRADA_RELATIVE . '/javascript/livepipe/window.js'); ?>"></script>
<?php
}
?>
When a page does not have prototype, it’s url is added to the list of excluded pages so that prototype can be slowly removed from Elentra.
Remove unused JS Files
Patches: Elentra ME v28.0-rc.11, Elentra ME v28.0-rc.12, Elentra ME v28.0-rc.15, Elentra ME v28.0-rc.16, Elentra ME v28.0-rc.19
List of removed files:
Remove unused API ednpoints
Patches: Elentra ME v28.0-rc.14, Elentra ME v28.0-rc.16
List of files removed:
API Consolidation
Patches: Elentra ME v28.0-rc.11, Elentra ME v28.0-rc.12, Elentra ME v28.0-rc.19, Elentra Me v28.0-rc.23, Elentra ME v28.0-rc.26
List of files moved:
www-root/core/modules/admin/assessments/blueprints/api-blueprints.inc.php -> www-root/api/blueprints.php
[Elentra ME v28.0-rc.11]www-root/core/modules/admin/assessments/cbmeforms/api-forms.inc.php → www-root/api/assessments/cbmeforms/forms.php
[Elentra ME v28.0-rc.12]www-root/core/modules/admin/assessments/cbmeforms/api-list.inc.php → www-root/api/assessments/cbmeforms/list.php
[Elentra ME v28.0-rc.12]www-root/core/modules/admin/assessments/distributions/api-distributions.inc.php → www-root/api/assessments/distributions/distributions.php
[Elentra ME v28.0-rc.19]www-root/core/modules/admin/assessments/forms/api-forms.inc.php → www-root/api/assessments/forms/forms.php
[Elentra Me v28.0-rc.23]www-root/core/modules/admin/assessments/items/api-items.inc.php → www-root/api/assessments/items/items.php
[Elentra Me v28.0-rc.23]www-root/core/modules/admin/assessments/scales/api-scales.inc.php → www-root/api/assessments/scales/scales.php
[Elentra Me v28.0-rc.23]www-root/core/modules/admin/assessments/rubrics/api-rubric.inc.php → www-root/api/assessments/rubrics/rubrics.php
[Elentra ME v28.0-rc.26]www-root/core/modules/admin/assessments/portfolios/api-portfolios.inc.php → www-root/api/assessments/portfolios/portfolios.php
[Elentra ME v28.0-rc.26]www-root/core/modules/admin/assessments/api-assessment-reports.inc.php → www-root/api/assessments/assessment-reports.php
[Elentra ME v28.0-rc.43]www-root/core/modules/admin/assessments/api-dashboard.inc.php → www-root/api/assessments/dashboard.php
[Elentra ME v28.0-rc.43]www-root/core/modules/admin/assessments/api-evaluation-reports.inc.php → www-root/api/assessments/evaluation-reports.php
[Elentra ME v28.0-rc.43]www-root/core/modules/admin/assessments/api-tools-feedbacks-reports.inc.php → www-root/api/assessments/tools-feedbacks-reports.php
[Elentra ME v28.0-rc.43]www-root/core/modules/admin/assessments/api-user-photo-upload.inc.php → www-root/api/assessments/user-photo-upload.php
[Elentra ME v28.0-rc.43]www-root/core/modules/admin/courses/api-courses.inc.php → www-root/api/courses/courses.php
[Elentra ME v28.0-rc.43]www-root/core/modules/admin/courses/api-image.inc.php → www-root/api/courses/image.php
[Elentra ME v28.0-rc.43]www-root/core/modules/admin/awards/api-awards.inc.php -> www-root/api/awards/awards.php
[Elentra ME v28.0-rc.43]www-root/core/modules/admin/courses/cbme/api-cbme.inc.php → www-root/api/courses/cbme/cbme.php
[Elentra ME v28.0-rc.43]www-root/core/modules/admin/courses/cbme/api-curriculumtags.inc.php → www-root/api/courses/cbme/curriculumtags.php
[Elentra ME v28.0-rc.43]
Remove functions.inc.php methods
Patches: Elentra ME v28.0-rc.12, Elentra ME v28.0-rc.30
List of methods removed:
check_body [Elentra ME v28.0-rc.12]
fetch_curriculum_objectives_children [Elentra ME v28.0-rc.30]
fetch_objective_child_mapped_course [Elentra ME v28.0-rc.30]
clerkship_categories_inselect [Elentra ME v28.0-rc.30]
clerkship_generate_included_categories [Elentra ME v28.0-rc.30]
clerkship_categories_inarray [Elentra ME v28.0-rc.30]
clerkship_categories_name [Elentra ME v28.0-rc.30]
permissions_fetch [Elentra ME v28.0-rc.30]
permissions_by_module [Elentra ME v28.0-rc.30]
count_notice_reads [Elentra ME v28.0-rc.30]
xml_encode [Elentra ME v28.0-rc.30]
xml_decode [Elentra ME v28.0-rc.30]
generate_organisation_select [Elentra ME v28.0-rc.30]
nl2br_replace [Elentra ME v28.0-rc.30]
br2nl_replace [Elentra ME v28.0-rc.30]
NotifyFn [Elentra ME v28.0-rc.30]
communities_generate_url [Elentra ME v28.0-rc.30]
communities_regenerate_url [Elentra ME v28.0-rc.30]
communities_module_title [Elentra ME v28.0-rc.30]
communities_module_details [Elentra ME v28.0-rc.30]
communities_module_deactivate [Elentra ME v28.0-rc.30]
folder_select_view [Elentra ME v28.0-rc.30]
communities_pages_fetch_parent_id [Elentra ME v28.0-rc.30]
communities_pages_count [Elentra ME v28.0-rc.30]
communities_pages_move [Elentra ME v28.0-rc.30]
recursive_delete_file [Elentra ME v28.0-rc.30]
fetch_mime_type [Elentra ME v28.0-rc.30]
quiz_completed_attempts [Elentra ME v28.0-rc.30]
quiz_count_questions [Elentra ME v28.0-rc.30]
clerkship_get_agerange [Elentra ME v28.0-rc.30]
courses_fetch_objectives_cperiod [Elentra ME v28.0-rc.30]
course_fetch_course_audience [Elentra ME v28.0-rc.30]
tracking_output_calendar_controls [Elentra ME v28.0-rc.30]
isUserInEventAttandance [Elentra ME v28.0-rc.30]
events_fetch_event_audience_for_user [Elentra ME v28.0-rc.30]
assessment_objectives_display_leafs [Elentra ME v28.0-rc.30]
assessment_objectives_bottom_leaves [Elentra ME v28.0-rc.30]
assessment_objective_decendant_mapped_course [Elentra ME v28.0-rc.30]
event_objectives_display_leafs [Elentra ME v28.0-rc.30]
event_objectives_bottom_leaves [Elentra ME v28.0-rc.30]
event_objectives_display_leaf [Elentra ME v28.0-rc.30]
event_objective_decendant_mapped_course [Elentra ME v28.0-rc.30]
event_objectives_in_list [Elentra ME v28.0-rc.30]
events_all_active_objectives [Elentra ME v28.0-rc.30]
course_objectives_multiple_select_options_checked [Elentra ME v28.0-rc.30]
course_objectives_multiple_select_table [Elentra ME v28.0-rc.30]
number_suffix [Elentra ME v28.0-rc.30]
getDefaultEnrollment [Elentra ME v28.0-rc.30]
display_default_enrollment [Elentra ME v28.0-rc.30]
objectives_inlists [Elentra ME v28.0-rc.30]
objectives_inlists_conf [Elentra ME v28.0-rc.30]
objectives_inselect [Elentra ME v28.0-rc.30]
objectives_delete [Elentra ME v28.0-rc.30]
objectives_delete_for_org [Elentra ME v28.0-rc.30]
objectives_intable [Elentra ME v28.0-rc.30]
build_option [Elentra ME v28.0-rc.30]
display_status_messages [Elentra ME v28.0-rc.30]
display_mspr_details [Elentra ME v28.0-rc.30]
objectives_competency_courses [Elentra ME v28.0-rc.30]
objectives_output_calendar_controls [Elentra ME v28.0-rc.30]
clear_error [Elentra ME v28.0-rc.30]
clear_success [Elentra ME v28.0-rc.30]
notice_redirect [Elentra ME v28.0-rc.30]
evaluations_fetch_attempts [Elentra ME v28.0-rc.30]
substitute_vars [Elentra ME v28.0-rc.30]
validate_in_array [Elentra ME v28.0-rc.30]
validate_user_ids [Elentra ME v28.0-rc.30]
validate_course_id [Elentra ME v28.0-rc.30]
validate_organisation_id [Elentra ME v28.0-rc.30]
or_bin [Elentra ME v28.0-rc.30]
allowed_tags [Elentra ME v28.0-rc.30]
display_person [Elentra ME v28.0-rc.30]
display_person_email [Elentra ME v28.0-rc.30]
display_photo [Elentra ME v28.0-rc.30]
display_photo_link [Elentra ME v28.0-rc.30]
display_photo_placeholder [Elentra ME v28.0-rc.30]
display_zoom_controls [Elentra ME v28.0-rc.30]
validate_integer_field [Elentra ME v28.0-rc.30]
groups_get_explicitly_enrolled_course_ids [Elentra ME v28.0-rc.30]
groups_get_all_course_lists [Elentra ME v28.0-rc.30]
filtered_words [Elentra ME v28.0-rc.30]
clean_empty_values [Elentra ME v28.0-rc.30]
prepare_filter_string [Elentra ME v28.0-rc.30]
event_text_change [Elentra ME v28.0-rc.30]
fetch_objective_parents [Elentra ME v28.0-rc.30]
count_objective_child_events [Elentra ME v28.0-rc.30]
count_objective_child_courses [Elentra ME v28.0-rc.30]
cmp_last_first [Elentra ME v28.0-rc.30]
cmp_group_name [Elentra ME v28.0-rc.30]
cmp_names_ASC [Elentra ME v28.0-rc.30]
cmp_names_DESC [Elentra ME v28.0-rc.30]
cmp_views_ASC [Elentra ME v28.0-rc.30]
cmp_views_DESC [Elentra ME v28.0-rc.30]
cmp_first_view_ASC [Elentra ME v28.0-rc.30]
cmp_first_view_DESC [Elentra ME v28.0-rc.30]
cmp_last_view_ASC [Elentra ME v28.0-rc.30]
cmp_last_view_DESC [Elentra ME v28.0-rc.30]
cmp_number [Elentra ME v28.0-rc.30]
unixStringtoDate [Elentra ME v28.0-rc.30]
assessments_items_subnavigation [Elentra ME v28.0-rc.30]
removeElementsByTagName [Elentra ME v28.0-rc.30]
hidden_params [Elentra ME v28.0-rc.30]
isUsingSecureBrowser [Elentra ME v28.0-rc.30]
Notifications
Patches: Elentra ME v28.0-rc.33
The notifications was refactored to increase readability and maintainability by removing the switch statement and replacing it with a match statement.
New Directory Tree:
↪ Notifications
↪ templates
↪ ...
↪ BaseNotification.class.php
↪ INotificationGenerator.class.php
↪ Notification.class.php
Match Statement
$notification_body_generator = match($notification_user->getContentType()){
"assessment" => new AssessmentNotification($notification_user, $params),
"assessment_approver" => new AssessmentApproverNotification($params["proxy_id"], $params),
"assessment_complete_now_drafted" => new AssessmentCompleteNowNotification($params["record_id"], "drafted"),
"assessment_complete_now_submitted" => new AssessmentCompleteNowNotification($params["record_id"], "submitted"),
"assessment_delegation" => new AssessmentDelegationNotification($params["record_id"], $params["proxy_id"], $params["subcontent_id"], $params["nuser_id"]),
"assessment_delegation_assignment_removed" => new AssessmentDelegationAssignmentRemovedNotification($notification_user, $params["proxy_id"], $params["subcontent_id"]),
"assessment_delegation_general" => new AssessmentDelegationGeneralNotification($params["record_id"], $params["proxy_id"], $params["subcontent_id"]),
"assessment_delegation_required_target_assessor" => new AssessmentDelegationRequiredTargetAssessorNotification($params["record_id"], $params["proxy_id"], $params),
"assessment_feedback" => new AssessmentFeedbackNotificaiton($params["record_id"], $params["proxy_id"]),
"assessment_flagged_response" => new AssessmentFlaggedNotification($params["record_id"], $params["proxy_id"]),
"assessment_expiry_warning" => new AssessmentExpiryWarningNotification($notification_user, $params["record_id"], $params["proxy_id"]),
"assessment_general" => new AssessmentGeneralNotification($params["proxy_id"], $params["record_id"], $notification_user),
"assessment_removal" => new AssessmentRemovalNotification($notification_user, $params["record_id"], $params["proxy_id"]),
"assessment_submitted" => new AssessmentSubmittedNotification($params["record_id"], $params["proxy_id"], $params),
"assessment_submitted_notify_approver" => new AssessmentSubmittedNotifyApproverNotification($params["record_id"], $params["proxy_id"]),
"assessment_submitted_notify_learner" => new AssessmentSubmittedNotifyLearnerNotification($params["record_id"]),
"assessment_task_deleted" => new AssessmentTaskDeletedNotification($params["record_id"], $params["subcontent_id"]),
"assessment_task_deleted_forwarded" => new AssessmentTaskDeletedForwardedNotification($params["record_id"], $params["subcontent_id"]),
"assessment_task_forwarded" => new AssessmentTaskForwardedNotification($notification_user, $params["proxy_id"], $params["record_id"]),
"assessment_task_reopened" => new AssessmentTaskReopenedNotification($params["record_id"], $params["subcontent_id"]),
"delegated_assessment_task_deleted" => new DelegatedAssessmentTaskDeletedNotification($notification_user, $params["record_id"]),
"delegation_task_deleted" => new DelegationTaskDeletedNotification($notification_user, $params["record_id"]),
"distribution_assessment_summary" => new DistributionAssessmentSummaryNotification($notification_user, $params["record_id"], $params["proxy_id"], $params["subcontent_id"]),
"evaluation" => new EvaluationNotification($notification_user, $params["record_id"], $params["subcontent_id"]),
"evaluation_overdue" => new EvaluationNotification($notification_user, $params["record_id"], $params["subcontent_id"]),
"evaluation_request" => new EvaluationRequestNotification($notification_user, $params["proxy_id"], $params["record_id"]),
"evaluation_threshold" => new EvaluationThresholdNotification($notification_user, $params["proxy_id"], $params["record_id"]),
"logbook_rotation" => new LogbookRotationNotification($notification_user, $params["proxy_id"], $params["record_id"]),
"notification-assessment-embargoed-submitted" => new NotificationAssessmentEmbargoedSubmittedNotification($params["record_id"]),
"preceptor_access_request" => new PreceptorAccessRequestNotification($params["record_id"], $params["proxy_id"]),
"preceptor_inactive_access_request" => new PreceptorInactiveAccessNotification($params["record_id"], $params["proxy_id"]),
"reminder_distribution_assessment_summary" => new DistributionAssessmentSummaryNotification($notification_user, $params["record_id"], $params["proxy_id"], $params["subcontent_id"]),
"submit_assessment_on_behalf" => new SubmitAssessmentOnBehalfNotification($notification_user, $params["record_id"], $params["proxy_id"]),
default => $notification_body_generator = new DefaultNotification($notification_user, $params["record_id"], $params["proxy_id"], $params["nuser_id"])
};
Last updated