Skip to content

Commit

Permalink
Add index to local string table to load all strings for one instance …
Browse files Browse the repository at this point in the history
…at once.
  • Loading branch information
srobotta committed Dec 4, 2024
1 parent 14d549c commit 7da679a
Show file tree
Hide file tree
Showing 4 changed files with 165 additions and 12 deletions.
71 changes: 61 additions & 10 deletions classes/repository/instance_repository.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ public static function get_by_id(int $id): instance {
$category = db_instance_category::to_instance_category($dbocategory);

// Load category headers.
$dbolocalizedstrings = self::get_strings(localized_string_type::INSTANCE_CATEGORY_HEADER, $category->get_id());
$dbolocalizedstrings = self::get_strings(localized_string_type::INSTANCE_CATEGORY_HEADER, $category->get_id(), $id);
foreach ($dbolocalizedstrings as $dbo) {
$header = db_localized_string::to_localized_string($dbo);
$category->add_header($header);
Expand All @@ -81,7 +81,7 @@ public static function get_by_id(int $id): instance {
foreach ($criteria as $criterion) {

// Load criterion description.
$dbodescriptions = self::get_strings(localized_string_type::INSTANCE_CRITERION, $criterion->get_id());
$dbodescriptions = self::get_strings(localized_string_type::INSTANCE_CRITERION, $criterion->get_id(), $id);
foreach ($dbodescriptions as $dbodescription) {
$description = db_localized_string::to_localized_string($dbodescription);
$criterion->add_description($description);
Expand All @@ -104,7 +104,7 @@ public static function get_by_id(int $id): instance {
// Load subrating very positive texts.
localized_string_type::INSTANCE_SUBRATING_VERY_POSITIVE => 'verypositives',
] as $type => $attribute) {
$dbotitles = self::get_strings($type, $subrating->get_id());
$dbotitles = self::get_strings($type, $subrating->get_id(), $id);
foreach ($dbotitles as $dbotitle) {
$item = db_localized_string::to_localized_string($dbotitle);
$subrating->{$attribute}[] = $item;
Expand All @@ -113,39 +113,39 @@ public static function get_by_id(int $id): instance {

// Load subrating descriptions.
$dbosubratingdescriptions = self::get_strings(localized_string_type::INSTANCE_SUBRATING_DESCRIPTION,
$subrating->get_id());
$subrating->get_id(), $id);
foreach ($dbosubratingdescriptions as $dbosubratingdescription) {
$subratingdescription = db_localized_string::to_localized_string($dbosubratingdescription);
$subrating->add_description($subratingdescription);
}

// Load subrating very negative texts.
$dboverynegatives = self::get_strings(localized_string_type::INSTANCE_SUBRATING_VERY_NEGATIVE,
$subrating->get_id());
$subrating->get_id(), $id);
foreach ($dboverynegatives as $dboverynegative) {
$verynegative = db_localized_string::to_localized_string($dboverynegative);
$subrating->add_verynegative($verynegative);
}

// Load subrating negative texts.
$dbonegatives = self::get_strings(localized_string_type::INSTANCE_SUBRATING_NEGATIVE,
$subrating->get_id());
$subrating->get_id(), $id);
foreach ($dbonegatives as $dbonegative) {
$negative = db_localized_string::to_localized_string($dbonegative);
$subrating->add_negative($negative);
}

// Load subrating positive texts.
$dbopositives = self::get_strings(localized_string_type::INSTANCE_SUBRATING_POSITIVE,
$subrating->get_id());
$subrating->get_id(), $id);
foreach ($dbopositives as $dbopositive) {
$positive = db_localized_string::to_localized_string($dbopositive);
$subrating->add_positive($positive);
}

// Load subrating very positive texts.
$dboverypositives = self::get_strings(localized_string_type::INSTANCE_SUBRATING_VERY_POSITIVE,
$subrating->get_id());
$subrating->get_id(), $id);
foreach ($dboverypositives as $dboverypositive) {
$verypositive = db_localized_string::to_localized_string($dboverypositive);
$subrating->add_verypositive($verypositive);
Expand All @@ -167,22 +167,35 @@ public static function get_by_id(int $id): instance {
*
* @param string $type
* @param int $subratingid
* @param int $instanceid
* @param bool $throwonerror
* @return array
* @throws \coding_exception
* @throws \dml_exception
*/
private static function get_strings(string $type, int $subratingid, bool $throwonerror = false): array {
private static function get_strings(string $type, int $subratingid, int $instanceid = 0, bool $throwonerror = false): array {
global $DB;

static $sortedstrings = [];
$typeid = localized_string_type::str2id($type);

if ($instanceid > 0) {
$strings = self::get_strings_for_instance($instanceid);
if (array_key_exists($typeid, $strings) && array_key_exists($subratingid, $strings[$typeid])) {
return $strings[$typeid][$subratingid];
}
if ($throwonerror) {
throw new \coding_exception("No strings for type $type and subratingid $subratingid");
}
return [];
}
$cachekey = $type . '~~' . $subratingid;

if (!array_key_exists($cachekey, $sortedstrings) || PHPUNIT_TEST) {
$sortedstrings[$cachekey] = [];
$rs = $DB->get_recordset(
tables::LOCALIZED_STRING_TABLE,
['typeid' => localized_string_type::str2id($type), 'foreignkey' => $subratingid]
['typeid' => $typeid, 'foreignkey' => $subratingid]
);
foreach ($rs as $dboheader) {
$dbobj = new db_localized_string;
Expand All @@ -207,6 +220,44 @@ private static function get_strings(string $type, int $subratingid, bool $throwo
return $sortedstrings[$cachekey];
}

/**
* Same as get_strings but for a specific instance, load the string all at once.
*
* @param int $id - instance id of the verbal feedback activity.
* @return array
*/
private static function get_strings_for_instance(int $id): array {
global $DB;

static $byinstance = [];

if (!array_key_exists($id, $byinstance) || PHPUNIT_TEST) {
$byinstance[$id] = [];
$rs = $DB->get_recordset(tables::LOCALIZED_STRING_TABLE, ['instanceid' => $id]);
foreach ($rs as $dboheader) {
$dbobj = new db_localized_string;
$dbobj->id = $dboheader->id;
$dbobj->languageid = $dboheader->languageid;
$dbobj->string = $dboheader->string;
$dbobj->typeid = $dboheader->typeid;
$dbobj->foreignkey = $dboheader->foreignkey;
$dbobj->instanceid = $dboheader->instanceid;

if (!array_key_exists($dbobj->typeid, $byinstance[$id])) {
$byinstance[$id][$dbobj->typeid] = [];
}
if (!array_key_exists($dbobj->foreignkey, $byinstance[$id][$dbobj->typeid])) {
$byinstance[$id][$dbobj->typeid][$dbobj->foreignkey] = [];
}
// Store the localized string by instanceid, typeid, foreignkey, languageid.
$byinstance[$id][$dbobj->typeid][$dbobj->foreignkey][$dbobj->languageid] = $dbobj;
}
$rs->close();
}

return $byinstance[$id];
}

/**
* Gets all criteria hashed by category id for a specific instance.
* @param int $id - instance id
Expand Down
15 changes: 14 additions & 1 deletion classes/repository/model/db_localized_string.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,38 +29,50 @@
* The database localized string class
*/
class db_localized_string {

/**
* @var int The id
*/
public $id;

/**
* @var int The type
*/
public $typeid;

/**
* @var int The foreign key
*/

public $foreignkey;

/**
* @var string The language id
*/
public $languageid;

/**
* @var string The string
*/
public $string;

/**
* @var int The instance id of the verbal feedback activity
*/
public $instanceid;

/**
* Return a localized string database object
*
* @param localized_string $localizedstring The localized string
* @param string $type The string type
* @param int $foreignkey The foreign key
* @param int $instanceid The instance id
* @return db_localized_string
* @throws \Exception
*/
public static function from_localized_string(localized_string $localizedstring, string $type,
int $foreignkey): db_localized_string {
int $foreignkey, int $instanceid): db_localized_string {
if (!localized_string_type::exists($type)) {
throw new \Exception("unknown localized_string_type");
}
Expand All @@ -70,6 +82,7 @@ public static function from_localized_string(localized_string $localizedstring,
$dbo->foreignkey = $foreignkey;
$dbo->languageid = $localizedstring->get_language_id();
$dbo->string = $localizedstring->get_string();
$dbo->instanceid = $instanceid;
return $dbo;
}

Expand Down
89 changes: 89 additions & 0 deletions db/upgrade.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/

use mod_verbalfeedback\repository\tables;
use mod_verbalfeedback\repository\model\localized_string_type;

/**
Expand Down Expand Up @@ -105,5 +106,93 @@ function xmldb_verbalfeedback_upgrade($oldversion) {
upgrade_mod_savepoint(true, 2024101700, 'verbalfeedback');
}

if ($oldversion < 2024120400) {
// Add instance id to localized string table and put an index on it so that when loading
// the strings, we can load them all at once by instance id of the verbal feedback activity.
$table = new xmldb_table('verbalfeedback_local_string');
$field = new xmldb_field('instanceid', XMLDB_TYPE_INTEGER, '3', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, 0);

if (!$dbman->field_exists($table, $field)) {
$dbman->add_field($table, $field);
}

add_instance_to_localized_string();
$table->add_index('instanceidx', XMLDB_INDEX_NOTUNIQUE, ['instanceid']);

upgrade_mod_savepoint(true, 2024120400, 'verbalfeedback');
}

return true;
}


/**
* Go over all existing strings in the database and add instance id of the verbal feedback activity to the localized string.
*/
function add_instance_to_localized_string() {
global $DB;

// Category header.
$sql = sprintf('
UPDATE {%2$s} SET instanceid = {%1$s}.instanceid FROM {%1$s}
WHERE {%1$s}.id = {%2$s}.foreignkey AND {%2$s}.typeid IN (?, ?)',
tables::INSTANCE_CATEGORY_TABLE,
tables::LOCALIZED_STRING_TABLE,
);
$DB->execute($sql, [
localized_string_type::str2id(localized_string_type::INSTANCE_CATEGORY_HEADER),
localized_string_type::str2id(localized_string_type::TEMPLATE_CATEGORY_HEADER),
]);

// Category criterion.
$sql = sprintf('
SELECT {%1$s}.id, {%2$s}.instanceid FROM {%1$s} JOIN {%2$s} ON {%2$s}.id = {%1$s}.categoryid
WHERE {%2$s}.id IN (SELECT DISTINCT(id) FROM {%2$s})
',
tables::INSTANCE_CRITERION_TABLE,
tables::INSTANCE_CATEGORY_TABLE
);
$results = $DB->get_records_sql($sql);
foreach ($results as $result) {
$DB->execute(
sprintf('UPDATE {%s} SET instanceid = ?
WHERE foreignkey = ? AND typeid IN (?, ?)', tables::LOCALIZED_STRING_TABLE),
[
$result->instanceid,
$result->id,
localized_string_type::str2id(localized_string_type::INSTANCE_CRITERION),
localized_string_type::str2id(localized_string_type::TEMPLATE_CRITERION),
]
);
}

// Subcriteria.
$sql = sprintf('
SELECT {%1$s}.id, {%3$s}.instanceid
FROM {%1$s}
JOIN {%2$s} ON {%1$s}.criterionid = {%2$s}.id
JOIN {%3$s} ON {%2$s}.categoryid = {%3$s}.id
', tables::INSTANCE_SUBRATING_TABLE, tables::INSTANCE_CRITERION_TABLE, tables::INSTANCE_CATEGORY_TABLE);
$results = $DB->get_records_sql($sql);
foreach ($results as $result) {
$DB->execute(
sprintf('UPDATE {%s} SET instanceid = ?
WHERE foreignkey = ? AND typeid IN (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', tables::LOCALIZED_STRING_TABLE),
[
$result->instanceid,
$result->id,
localized_string_type::str2id(localized_string_type::INSTANCE_SUBRATING_TITLE),
localized_string_type::str2id(localized_string_type::INSTANCE_SUBRATING_DESCRIPTION),
localized_string_type::str2id(localized_string_type::INSTANCE_SUBRATING_VERY_NEGATIVE),
localized_string_type::str2id(localized_string_type::INSTANCE_SUBRATING_NEGATIVE),
localized_string_type::str2id(localized_string_type::INSTANCE_SUBRATING_POSITIVE),
localized_string_type::str2id(localized_string_type::INSTANCE_SUBRATING_VERY_POSITIVE),
localized_string_type::str2id(localized_string_type::TEMPLATE_SUBRATING_DESCRIPTION),
localized_string_type::str2id(localized_string_type::TEMPLATE_SUBRATING_VERY_NEGATIVE),
localized_string_type::str2id(localized_string_type::TEMPLATE_SUBRATING_NEGATIVE),
localized_string_type::str2id(localized_string_type::TEMPLATE_SUBRATING_POSITIVE),
localized_string_type::str2id(localized_string_type::TEMPLATE_SUBRATING_VERY_POSITIVE),
]
);
}
}
2 changes: 1 addition & 1 deletion version.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
defined('MOODLE_INTERNAL') || die();

$plugin->component = 'mod_verbalfeedback';
$plugin->version = 2024101700;
$plugin->version = 2024120400;
$plugin->requires = 2022112800;
$plugin->maturity = MATURITY_STABLE;
$plugin->cron = 0;
Expand Down

0 comments on commit 7da679a

Please sign in to comment.