From db5f98d29ac3ee468f68690a6b4c2adb554ec5b2 Mon Sep 17 00:00:00 2001 From: Tomo Tsuyuki Date: Wed, 18 Sep 2024 12:00:55 +1000 Subject: [PATCH 1/8] Issue #66: Add file search API --- classes/search/cmsfield.php | 61 +++++++++++++++++++++++++++++++++++-- 1 file changed, 59 insertions(+), 2 deletions(-) diff --git a/classes/search/cmsfield.php b/classes/search/cmsfield.php index e7e571d..ce212a9 100644 --- a/classes/search/cmsfield.php +++ b/classes/search/cmsfield.php @@ -72,7 +72,7 @@ public function get_document_recordset($modifiedfrom = 0, \context $context = nu JOIN {customfield_category} mcc ON mcf.categoryid = mcc.id $contextjoin WHERE mcd.timemodified >= ? AND mcc.component = 'mod_cms' AND mcc.area = 'cmsfield' - AND mcf.type IN ('textarea', 'text') + AND mcf.type IN ('textarea', 'text', 'file') GROUP BY mc.id ) cdata ON ccms.id = cdata.id JOIN {customfield_field} cmcf ON cmcf.id = cdata.fieldid @@ -81,10 +81,11 @@ public function get_document_recordset($modifiedfrom = 0, \context $context = nu null AS dataid, null AS value, null AS valueformat, mc.timecreated timecreated, mc.timemodified timemodified FROM {cms} mc + $contextjoin LEFT JOIN {customfield_data} mcd ON mc.id = mcd.instanceid WHERE mcd.id IS NULL AND mc.timecreated >= ? ORDER BY timemodified ASC"; - return $DB->get_recordset_sql($sql, array_merge($contextparams, [$modifiedfrom, $modifiedfrom])); + return $DB->get_recordset_sql($sql, array_merge($contextparams, [$modifiedfrom], $contextparams, [$modifiedfrom])); } /** @@ -253,4 +254,60 @@ protected function get_data($id) { } return $this->cmsdata[$id]; } + + /** + * Returns true if this area uses file indexing. + * + * @return bool + */ + public function uses_file_indexing() { + return true; + } + + /** + * Return the context info required to index files for + * this search area. + * + * @return array + */ + public function get_search_fileareas() { + return ['value']; + } + + /** + * Add the forum post attachments. + * + * @param document $document The current document + * @return null + */ + public function attach_files($document) { + global $DB; + + $fileareas = $this->get_search_fileareas(); + // File is in "customfield_file" for component, "value" for filearea, and for customfield data id for itemid. + $contextid = \context_system::instance()->id; + $component = 'customfield_file'; + $cmsid = $document->get('itemid'); + + // Search customfield data from cms record. + $sql = "SELECT mcd.id + FROM {cms} mc + JOIN {customfield_data} mcd ON mc.id = mcd.instanceid + JOIN {customfield_field} mcf ON mcf.id = mcd.fieldid + JOIN {customfield_category} mcc ON mcf.categoryid = mcc.id + WHERE mc.id = ? AND mcc.component = 'mod_cms' AND mcc.area = 'cmsfield' AND mcf.type = 'file'"; + $param = [$cmsid]; + $filedata = $DB->get_records_sql($sql, $param); + + foreach ($fileareas as $filearea) { + foreach ($filedata as $data) { + $fs = get_file_storage(); + $files = $fs->get_area_files($contextid, $component, $filearea, $data->id, '', false); + + foreach ($files as $file) { + $document->add_stored_file($file); + } + } + } + } } From bf17c2b3a70ae36baf16c5e06b714c893e9957bc Mon Sep 17 00:00:00 2001 From: Tomo Tsuyuki Date: Wed, 18 Sep 2024 13:21:54 +1000 Subject: [PATCH 2/8] Issue #66: Fix wrong function doc --- classes/search/cmsfield.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/classes/search/cmsfield.php b/classes/search/cmsfield.php index ce212a9..c787b5e 100644 --- a/classes/search/cmsfield.php +++ b/classes/search/cmsfield.php @@ -275,7 +275,7 @@ public function get_search_fileareas() { } /** - * Add the forum post attachments. + * Add the cms file attachments. * * @param document $document The current document * @return null From e30930e8871751712ff56810358e4cba12949133 Mon Sep 17 00:00:00 2001 From: Tomo Tsuyuki Date: Fri, 18 Oct 2024 10:05:58 +1100 Subject: [PATCH 3/8] Issue #66: Add template for search --- classes/search/cmsfield.php | 21 +++++++++++++++++++++ tests/search/search_test.php | 8 +++++--- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/classes/search/cmsfield.php b/classes/search/cmsfield.php index e7e571d..40b0c55 100644 --- a/classes/search/cmsfield.php +++ b/classes/search/cmsfield.php @@ -130,6 +130,14 @@ public function get_document($record, $options = []) { $value = $record->value; $valueformat = $record->valueformat; } + // Add mustache template to value. + if (!empty($defaultvalues[$record->typeid]->mustache)) { + $value .= ' ' . $defaultvalues[$record->typeid]->mustache; + if (empty($title)) { + $title = $defaultvalues[$record->typeid]->name; + } + $valueformat = FORMAT_HTML; + } // Prepare associative array with data from DB. $doc = \core_search\document_factory::instance($record->id, $this->componentname, $this->areaname); @@ -179,6 +187,19 @@ protected function get_default_values() { } $defaultvalues[$cmstype->typeid] = $data; } + + // Add mustache template for default value. + $sql = "SELECT mct.id, mct.name, mct.mustache + FROM {cms_types} mct"; + $mustaches = $DB->get_records_sql($sql); + foreach ($mustaches as $mustache) { + if (empty($defaultvalues[$mustache->id])) { + $defaultvalues[$mustache->id] = new \stdClass(); + } + $defaultvalues[$mustache->id]->name = $mustache->name; + $defaultvalues[$mustache->id]->mustache = $mustache->mustache; + } + $this->defaultvalues = $defaultvalues; } return $this->defaultvalues; diff --git a/tests/search/search_test.php b/tests/search/search_test.php index c628481..3f32543 100644 --- a/tests/search/search_test.php +++ b/tests/search/search_test.php @@ -82,6 +82,7 @@ public function setUp(): void { $cmstype = new cms_types(); $cmstype->set('name', 'Overview') ->set('idnumber', 'overview') + ->set('mustache', 'Template doc') ->set('title_mustache', 'Overview'); $cmstype->save(); $fieldcategory = self::getDataGenerator()->create_custom_field_category([ @@ -187,7 +188,8 @@ public function test_get_document_recordset(): void { $this->assertEquals($course->id, $doc->get('courseid')); $this->assertEquals($context->id, $doc->get('contextid')); $this->assertEquals($this->field->get('name'), $doc->get('title')); - $this->assertEquals($data->value, $doc->get('content')); + $this->assertStringContainsString($data->value, $doc->get('content')); + $this->assertStringContainsString($this->cmstype->get('mustache'), $doc->get('content')); // Static caches are working. $dbreads = $DB->perf_get_reads(); @@ -238,7 +240,7 @@ public function test_default_content(): void { $doc = $searcharea->get_document($record); $this->assertInstanceOf('\core_search\document', $doc); // Confirm the content is from defaultvalue from cms fieldtype. - $this->assertEquals('Default Text Overview', $doc->get('content')); + $this->assertStringContainsString('Default Text Overview', $doc->get('content')); $count++; } $this->assertEquals(1, $count); @@ -253,7 +255,7 @@ public function test_default_content(): void { foreach ($recordset as $record) { $this->assertInstanceOf('stdClass', $record); $doc = $searcharea->get_document($record); - $this->assertEquals('Update test 1', $doc->get('content')); + $this->assertStringContainsString('Update test 1', $doc->get('content')); $count++; } $this->assertEquals(1, $count); From a7dd6a5f31bd2d3ee212fe85e0d8b00852b8b8ca Mon Sep 17 00:00:00 2001 From: Tomo Tsuyuki Date: Fri, 25 Oct 2024 11:47:42 +1100 Subject: [PATCH 4/8] Issue #66 Replace from raw template to rendered one if possible --- classes/search/cmsfield.php | 18 ++++++++++++++++-- tests/search/search_test.php | 6 ------ 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/classes/search/cmsfield.php b/classes/search/cmsfield.php index 40b0c55..b5a2a05 100644 --- a/classes/search/cmsfield.php +++ b/classes/search/cmsfield.php @@ -18,6 +18,9 @@ defined('MOODLE_INTERNAL') || die(); +use mod_cms\local\model\cms; +use mod_cms\local\renderer; + require_once($CFG->dirroot . '/mod/cms/lib.php'); /** @@ -95,7 +98,6 @@ public function get_document_recordset($modifiedfrom = 0, \context $context = nu * @return \core_search\document */ public function get_document($record, $options = []) { - global $DB; try { $cm = $this->get_cm('cms', $record->id, $record->courseid); $context = \context_module::instance($cm->id); @@ -130,9 +132,21 @@ public function get_document($record, $options = []) { $value = $record->value; $valueformat = $record->valueformat; } + // Add mustache template to value. if (!empty($defaultvalues[$record->typeid]->mustache)) { - $value .= ' ' . $defaultvalues[$record->typeid]->mustache; + $cms = new cms($cm->instance); + $renderer = new renderer($cms); + ob_start(); + try { + // Indexer uses "Empty" session, it may get an error from rendering. + $value .= $renderer->get_html(); + } catch (\Exception $e) { + // Use template when an error occurs. + $value .= ' ' . $defaultvalues[$record->typeid]->mustache; + } + // Do not show any errors from rendering. + ob_end_clean(); if (empty($title)) { $title = $defaultvalues[$record->typeid]->name; } diff --git a/tests/search/search_test.php b/tests/search/search_test.php index 3f32543..c128be2 100644 --- a/tests/search/search_test.php +++ b/tests/search/search_test.php @@ -190,12 +190,6 @@ public function test_get_document_recordset(): void { $this->assertEquals($this->field->get('name'), $doc->get('title')); $this->assertStringContainsString($data->value, $doc->get('content')); $this->assertStringContainsString($this->cmstype->get('mustache'), $doc->get('content')); - - // Static caches are working. - $dbreads = $DB->perf_get_reads(); - $doc = $searcharea->get_document($record); - $this->assertEquals($dbreads, $DB->perf_get_reads()); - $this->assertInstanceOf('\core_search\document', $doc); $count++; } $this->assertEquals(1, $count); From 63e5b99db3972b1f1238c4a56a4ce8bf1a726c34 Mon Sep 17 00:00:00 2001 From: Tomo Tsuyuki Date: Mon, 28 Oct 2024 16:32:47 +1100 Subject: [PATCH 5/8] Issue #66 Use template render function --- classes/search/cmsfield.php | 146 ++--------------------------------- tests/search/search_test.php | 77 ++++++++++++------ 2 files changed, 61 insertions(+), 162 deletions(-) diff --git a/classes/search/cmsfield.php b/classes/search/cmsfield.php index b5a2a05..f75da60 100644 --- a/classes/search/cmsfield.php +++ b/classes/search/cmsfield.php @@ -31,7 +31,7 @@ * @copyright 2024 Catalyst IT * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class cmsfield extends \core_search\base_mod { +class cmsfield extends \core_search\base_activity { /** * @var array Internal quick static cache. @@ -43,53 +43,6 @@ class cmsfield extends \core_search\base_mod { */ protected $defaultvalues = null; - /** - * Returns recordset containing required data for indexing cmsfield records. - * - * @param int $modifiedfrom timestamp - * @param \context|null $context Optional context to restrict scope of returned results - * @return \moodle_recordset|null Recordset (or null if no results) - */ - public function get_document_recordset($modifiedfrom = 0, \context $context = null) { - global $DB; - - list ($contextjoin, $contextparams) = $this->get_context_restriction_sql( - $context, 'cms', 'mc'); - if ($contextjoin === null) { - return null; - } - - // Search area is from customfield_data, but if the record is missing from activity, use default value. - $sqlgroupconcat = $DB->sql_group_concat("mcd.value", ', ', 'mcf.sortorder'); - $sql = "SELECT ccms.id, ccms.course AS courseid, ccms.typeid, cmcf.name AS fieldname, cmcf.type, - cdata.dataid dataid, cdata.value AS value, cdata.valueformat AS valueformat, - cdata.timecreated AS timecreated, cdata.timemodified AS timemodified - FROM {cms} ccms - JOIN ( - SELECT mc.id, MAX(mcf.id) AS fieldid, - MAX(mcd.id) dataid, {$sqlgroupconcat} AS value, MAX(mcd.valueformat) AS valueformat, - MAX(mcd.timecreated) AS timecreated, MAX(mcd.timemodified) AS timemodified - FROM {cms} mc - JOIN {customfield_data} mcd ON mc.id = mcd.instanceid - JOIN {customfield_field} mcf ON mcf.id = mcd.fieldid - JOIN {customfield_category} mcc ON mcf.categoryid = mcc.id - $contextjoin - WHERE mcd.timemodified >= ? AND mcc.component = 'mod_cms' AND mcc.area = 'cmsfield' - AND mcf.type IN ('textarea', 'text') - GROUP BY mc.id - ) cdata ON ccms.id = cdata.id - JOIN {customfield_field} cmcf ON cmcf.id = cdata.fieldid - UNION - SELECT mc.id, mc.course AS courseid, mc.typeid, null AS fieldname, null AS type, - null AS dataid, null AS value, null AS valueformat, - mc.timecreated timecreated, mc.timemodified timemodified - FROM {cms} mc - LEFT JOIN {customfield_data} mcd ON mc.id = mcd.instanceid - WHERE mcd.id IS NULL AND mc.timecreated >= ? - ORDER BY timemodified ASC"; - return $DB->get_recordset_sql($sql, array_merge($contextparams, [$modifiedfrom, $modifiedfrom])); - } - /** * Returns the document associated with this data id. * @@ -99,7 +52,7 @@ public function get_document_recordset($modifiedfrom = 0, \context $context = nu */ public function get_document($record, $options = []) { try { - $cm = $this->get_cm('cms', $record->id, $record->courseid); + $cm = $this->get_cm('cms', $record->id, $record->course); $context = \context_module::instance($cm->id); } catch (\dml_missing_record_exception $ex) { // Notify it as we run here as admin, we should see everything. @@ -112,53 +65,18 @@ public function get_document($record, $options = []) { return false; } - $defaultvalues = $this->get_default_values(); - - // Check if it's default value or not. - if (empty($record->dataid)) { - $title = $defaultvalues[$record->typeid]->fieldname ?? ''; - $value = $defaultvalues[$record->typeid]->value ?? ''; - if (isset($defaultvalues[$record->typeid]->valueformat)) { - $valueformat = $defaultvalues[$record->typeid]->valueformat; - } else { - if ($record->type == 'textarea') { - $valueformat = FORMAT_HTML; - } else { - $valueformat = FORMAT_PLAIN; - } - } - } else { - $title = $record->fieldname; - $value = $record->value; - $valueformat = $record->valueformat; - } - - // Add mustache template to value. - if (!empty($defaultvalues[$record->typeid]->mustache)) { - $cms = new cms($cm->instance); - $renderer = new renderer($cms); - ob_start(); - try { - // Indexer uses "Empty" session, it may get an error from rendering. - $value .= $renderer->get_html(); - } catch (\Exception $e) { - // Use template when an error occurs. - $value .= ' ' . $defaultvalues[$record->typeid]->mustache; - } - // Do not show any errors from rendering. - ob_end_clean(); - if (empty($title)) { - $title = $defaultvalues[$record->typeid]->name; - } - $valueformat = FORMAT_HTML; - } + $cms = new cms($cm->instance); + $renderer = new renderer($cms); + $value = $renderer->get_html(); + $title = $cms->get('name'); + $valueformat = FORMAT_HTML; // Prepare associative array with data from DB. $doc = \core_search\document_factory::instance($record->id, $this->componentname, $this->areaname); $doc->set('title', content_to_text($title, false)); $doc->set('content', content_to_text($value, $valueformat)); $doc->set('contextid', $context->id); - $doc->set('courseid', $record->courseid); + $doc->set('courseid', $record->course); $doc->set('owneruserid', \core_search\manager::NO_OWNER_ID); $doc->set('modified', $record->timemodified); @@ -171,54 +89,6 @@ public function get_document($record, $options = []) { return $doc; } - /** - * Get default value for cms custom field. - * - * @return array - */ - protected function get_default_values() { - global $DB; - if (is_null($this->defaultvalues)) { - $defaultvalues = []; - $sql = "SELECT mcf.id fieldid, mct.id typeid, mcf.configdata, mcf.name fieldname - FROM {cms_types} mct - JOIN {customfield_category} mcc ON mcc.itemid = mct.id - JOIN {customfield_field} mcf ON mcf.categoryid = mcc.id - WHERE mcc.component = 'mod_cms' AND mcc.area = 'cmsfield' AND mcf.type IN ('textarea', 'text') - ORDER BY mct.id, mcf.sortorder"; - $cmstypes = $DB->get_records_sql($sql); - foreach ($cmstypes as $cmstype) { - if (empty($defaultvalues[$cmstype->typeid])) { - $data = new \stdClass(); - $configdata = json_decode($cmstype->configdata); - $data->value = $configdata->defaultvalue ?? 'Default value'; - $data->valueformat = $configdata->defaultvalueformat ?? 0; - $data->fieldname = $cmstype->fieldname; - } else { - $data = $defaultvalues[$cmstype->typeid]; - $configdata = json_decode($cmstype->configdata); - $data->value .= ', ' . $configdata->defaultvalue; - } - $defaultvalues[$cmstype->typeid] = $data; - } - - // Add mustache template for default value. - $sql = "SELECT mct.id, mct.name, mct.mustache - FROM {cms_types} mct"; - $mustaches = $DB->get_records_sql($sql); - foreach ($mustaches as $mustache) { - if (empty($defaultvalues[$mustache->id])) { - $defaultvalues[$mustache->id] = new \stdClass(); - } - $defaultvalues[$mustache->id]->name = $mustache->name; - $defaultvalues[$mustache->id]->mustache = $mustache->mustache; - } - - $this->defaultvalues = $defaultvalues; - } - return $this->defaultvalues; - } - /** * Whether the user can access the document or not. * diff --git a/tests/search/search_test.php b/tests/search/search_test.php index c128be2..21952cc 100644 --- a/tests/search/search_test.php +++ b/tests/search/search_test.php @@ -26,7 +26,8 @@ namespace mod_cms\search; -use mod_cms\customfield\cmsfield_handler; +use mod_cms\local\datasource\fields as dsfields; +use mod_cms\local\model\cms; use mod_cms\local\model\cms_types; defined('MOODLE_INTERNAL') || die(); @@ -82,7 +83,8 @@ public function setUp(): void { $cmstype = new cms_types(); $cmstype->set('name', 'Overview') ->set('idnumber', 'overview') - ->set('mustache', 'Template doc') + ->set('mustache', 'Template doc {{fields.overview}}') + ->set('datasources', ['fields']) ->set('title_mustache', 'Overview'); $cmstype->save(); $fieldcategory = self::getDataGenerator()->create_custom_field_category([ @@ -138,20 +140,25 @@ public function test_get_document_recordset(): void { $this->assertInstanceOf('\mod_cms\search\cmsfield', $searcharea); $course = self::getDataGenerator()->create_course(); + $overviews = []; // The name of cms activity is from cms_type, so we do not set when creating the activity. $generator = self::getDataGenerator()->get_plugin_generator('mod_cms'); + $overview1 = 'Test overview text 1'; $record = new \stdClass(); $record->course = $course->id; - $record->customfield_overview = 'Test overview text 1'; + $record->customfield_overview = $overview1; $record->typeid = $this->cmstype->get('id'); $cms1 = $generator->create_instance_with_data($record); + $overviews[$cms1->id] = $overview1; + $overview2 = 'Test overview text 2'; $record = new \stdClass(); $record->course = $course->id; - $record->customfield_overview = 'Test overview text 2'; + $record->customfield_overview = $overview2; $record->typeid = $this->cmstype->get('id'); $cms2 = $generator->create_instance_with_data($record); + $overviews[$cms2->id] = $overview2; // All records. $recordset = $searcharea->get_document_recordset(); @@ -168,19 +175,20 @@ public function test_get_document_recordset(): void { // Wait 1 sec to have new search string. sleep(1); $time = time(); + $overview3 = 'Test overview text 3'; $record = new \stdClass(); $record->course = $course->id; - $record->customfield_overview = 'Test overview text 3'; + $record->customfield_overview = $overview3; $record->typeid = $this->cmstype->get('id'); $cms3 = $generator->create_instance_with_data($record); $context = \context_module::instance($cms3->cmid); + $overviews[$cms3->id] = $overview3; // Return only new search. $recordset = $searcharea->get_document_recordset($time); $count = 0; foreach ($recordset as $record) { $this->assertInstanceOf('stdClass', $record); - $data = $DB->get_record('customfield_data', ['id' => $record->dataid]); $doc = $searcharea->get_document($record); $this->assertInstanceOf('\core_search\document', $doc); $this->assertEquals('mod_cms-cmsfield-' . $record->id, $doc->get('id')); @@ -188,17 +196,17 @@ public function test_get_document_recordset(): void { $this->assertEquals($course->id, $doc->get('courseid')); $this->assertEquals($context->id, $doc->get('contextid')); $this->assertEquals($this->field->get('name'), $doc->get('title')); - $this->assertStringContainsString($data->value, $doc->get('content')); - $this->assertStringContainsString($this->cmstype->get('mustache'), $doc->get('content')); + $this->assertStringContainsString($overviews[$doc->get('itemid')], $doc->get('content')); $count++; } $this->assertEquals(1, $count); $recordset->close(); // Update existing data. - $cms1->customfield_overview = 'Update test 1'; - $handler = cmsfield_handler::create($cms1->typeid); - $handler->instance_form_save($cms1); + $cms = new cms($cms1->id); + $ds = new dsfields($cms); + $ds->update_instance((object) ['id' => $cms1->id, 'customfield_overview' => 'Update test 1'], false); + // Return 2 records. $recordset = $searcharea->get_document_recordset($time); $this->assertTrue($recordset->valid()); @@ -230,7 +238,6 @@ public function test_default_content(): void { $count = 0; foreach ($recordset as $record) { $this->assertInstanceOf('stdClass', $record); - $this->assertEmpty($record->dataid); $doc = $searcharea->get_document($record); $this->assertInstanceOf('\core_search\document', $doc); // Confirm the content is from defaultvalue from cms fieldtype. @@ -241,9 +248,9 @@ public function test_default_content(): void { $recordset->close(); // Add custom data for the cms activity. - $cms1->customfield_overview = 'Update test 1'; - $handler = cmsfield_handler::create($cms1->typeid); - $handler->instance_form_save($cms1); + $cms = new cms($cms1->id); + $ds = new dsfields($cms); + $ds->update_instance((object) ['id' => $cms1->id, 'customfield_overview' => 'Update test 1'], false); $recordset = $searcharea->get_document_recordset(); $count = 0; foreach ($recordset as $record) { @@ -270,26 +277,45 @@ public function test_multiple_contents(): void { $searcharea = \core_search\manager::get_search_area($this->cmsareaid); $this->assertInstanceOf('\mod_cms\search\cmsfield', $searcharea); - $course = self::getDataGenerator()->create_course(); - $field = self::getDataGenerator()->create_custom_field([ + $cmstype = new cms_types(); + $cmstype->set('name', 'Multiple content') + ->set('idnumber', 'multiplecontent') + ->set('mustache', 'Overview: {{fields.overview}} Details: {{fields.details}}') + ->set('datasources', ['fields']) + ->set('title_mustache', 'Multiple content'); + $cmstype->save(); + $fieldcategory = self::getDataGenerator()->create_custom_field_category([ + 'name' => 'Multiple fields', + 'component' => 'mod_cms', + 'area' => 'cmsfield', + 'itemid' => $cmstype->get('id'), + ]); + $field1 = self::getDataGenerator()->create_custom_field([ + 'name' => 'Overview', + 'shortname' => 'overview', + 'type' => 'text', + 'categoryid' => $fieldcategory->get('id'), + 'configdata' => json_encode(['defaultvalue' => 'Default Text Overview']), + ]); + $field2 = self::getDataGenerator()->create_custom_field([ 'name' => 'Details', 'shortname' => 'details', 'type' => 'text', - 'categoryid' => $this->fieldcategory->get('id'), + 'categoryid' => $fieldcategory->get('id'), 'configdata' => json_encode(['defaultvalue' => 'Default Text Details']), ]); + $course = self::getDataGenerator()->create_course(); $generator = self::getDataGenerator()->get_plugin_generator('mod_cms'); $record = new \stdClass(); $record->course = $course->id; - $record->typeid = $this->cmstype->get('id'); + $record->typeid = $cmstype->get('id'); $cms1 = $generator->create_instance_with_data($record); $recordset = $searcharea->get_document_recordset(); $count = 0; foreach ($recordset as $record) { $this->assertInstanceOf('stdClass', $record); - $this->assertEmpty($record->dataid); $doc = $searcharea->get_document($record); $this->assertInstanceOf('\core_search\document', $doc); $this->assertStringContainsString('Default Text Overview', $doc->get('content')); @@ -300,10 +326,13 @@ public function test_multiple_contents(): void { $recordset->close(); // Add data for the cms activity. - $cms1->customfield_overview = 'Overview test 1'; - $cms1->customfield_details = 'Details test 1'; - $handler = cmsfield_handler::create($cms1->typeid); - $handler->instance_form_save($cms1); + $cms = new cms($cms1->id); + $ds = new dsfields($cms); + $cmsfields = new \stdClass(); + $cmsfields->id = $cms1->id; + $cmsfields->customfield_overview = 'Overview test 1'; + $cmsfields->customfield_details = 'Details test 1'; + $ds->update_instance($cmsfields, false); $recordset = $searcharea->get_document_recordset(); $count = 0; foreach ($recordset as $record) { From ae117f103429f312e3fef6d24c988650bb009ce9 Mon Sep 17 00:00:00 2001 From: Tomo Tsuyuki Date: Tue, 29 Oct 2024 11:16:16 +1100 Subject: [PATCH 6/8] Issue #66 Use parent functions and rename search class name --- classes/search/{cmsfield.php => activity.php} | 82 +------------------ lang/en/cms.php | 2 +- version.php | 2 +- 3 files changed, 3 insertions(+), 83 deletions(-) rename classes/search/{cmsfield.php => activity.php} (65%) diff --git a/classes/search/cmsfield.php b/classes/search/activity.php similarity index 65% rename from classes/search/cmsfield.php rename to classes/search/activity.php index 6c0de40..68dd29f 100644 --- a/classes/search/cmsfield.php +++ b/classes/search/activity.php @@ -31,17 +31,7 @@ * @copyright 2024 Catalyst IT * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class cmsfield extends \core_search\base_activity { - - /** - * @var array Internal quick static cache. - */ - protected $cmsdata = []; - - /** - * @var array Internal quick static cache. - */ - protected $defaultvalues = null; +class activity extends \core_search\base_activity { /** * Returns the document associated with this data id. @@ -89,76 +79,6 @@ public function get_document($record, $options = []) { return $doc; } - /** - * Whether the user can access the document or not. - * - * @param int $id data id - * @return bool - */ - public function check_access($id) { - try { - $data = $this->get_data($id); - $cminfo = $this->get_cm('cms', $data->id, $data->courseid); - $context = \context_module::instance($cminfo->id); - } catch (\dml_missing_record_exception $ex) { - return \core_search\manager::ACCESS_DELETED; - } catch (\dml_exception $ex) { - return \core_search\manager::ACCESS_DENIED; - } - - // Recheck uservisible although it should have already been checked in core_search. - if ($cminfo->uservisible === false) { - return \core_search\manager::ACCESS_DENIED; - } - - if (!has_capability('mod/cms:view', $context)) { - return \core_search\manager::ACCESS_DENIED; - } - - return \core_search\manager::ACCESS_GRANTED; - } - - /** - * Link to the cms. - * - * @param \core_search\document $doc - * @return \moodle_url - */ - public function get_doc_url(\core_search\document $doc) { - $contextmodule = \context::instance_by_id($doc->get('contextid')); - $cm = get_coursemodule_from_id('cms', $contextmodule->instanceid, $doc->get('courseid'), true); - return new \moodle_url('/course/view.php', ['id' => $doc->get('courseid'), 'section' => $cm->sectionnum]); - } - - /** - * Link to the cms. - * - * @param \core_search\document $doc - * @return \moodle_url - */ - public function get_context_url(\core_search\document $doc) { - $contextmodule = \context::instance_by_id($doc->get('contextid')); - return new \moodle_url('/mod/cms/view.php', ['id' => $contextmodule->instanceid]); - } - - /** - * Returns the specified data from its internal cache. - * - * @throws \dml_missing_record_exception - * @param int $id - * @return stdClass - */ - protected function get_data($id) { - global $DB; - if (empty($this->cmsdata[$id])) { - $sql = "SELECT mc.id, mc.course AS courseid - FROM {cms} mc - WHERE mc.id = :id"; - $this->cmsdata[$id] = $DB->get_record_sql($sql, ['id' => $id], MUST_EXIST); - } - return $this->cmsdata[$id]; - } - /** * Returns true if this area uses file indexing. * diff --git a/lang/en/cms.php b/lang/en/cms.php index 9e88fda..0e0e1e9 100644 --- a/lang/en/cms.php +++ b/lang/en/cms.php @@ -104,7 +104,7 @@ $string['error:no_config_hash'] = 'Module {$a} has no config hash.'; // Search strings. -$string['search:cmsfield'] = 'CMS'; +$string['search:activity'] = 'CMS - activity information'; // Site datasource strings. $string['site:displayname'] = 'Site Info'; diff --git a/version.php b/version.php index a79caa6..a23e888 100644 --- a/version.php +++ b/version.php @@ -25,7 +25,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2024090300; +$plugin->version = 2024090301; $plugin->requires = 2022112800; // Moodle 4.1 and above. $plugin->supported = [401, 401]; // Moodle 4.1. $plugin->component = 'mod_cms'; From d6cbad751e59d4a3e243bcf9d338959364ef85cb Mon Sep 17 00:00:00 2001 From: Tomo Tsuyuki Date: Tue, 29 Oct 2024 13:36:42 +1100 Subject: [PATCH 7/8] Issue #66 Fix phpunit error --- tests/search/search_test.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/search/search_test.php b/tests/search/search_test.php index 21952cc..5d77090 100644 --- a/tests/search/search_test.php +++ b/tests/search/search_test.php @@ -43,7 +43,7 @@ * @author Tomo Tsuyuki * @copyright 2024 Catalyst IT * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - * @coversDefaultClass \mod_cms\search\cmsfield + * @coversDefaultClass \mod_cms\search\activity */ class search_test extends \advanced_testcase { @@ -74,7 +74,7 @@ public function setUp(): void { $this->resetAfterTest(); set_config('enableglobalsearch', true); - $this->cmsareaid = \core_search\manager::generate_areaid('mod_cms', 'cmsfield'); + $this->cmsareaid = \core_search\manager::generate_areaid('mod_cms', 'activity'); // Set \core_search::instance to the mock_search_engine as we don't require the search engine to be working to test this. $search = \testable_core_search::instance(); @@ -137,7 +137,7 @@ public function test_get_document_recordset(): void { // Returns the instance as long as the area is supported. $searcharea = \core_search\manager::get_search_area($this->cmsareaid); - $this->assertInstanceOf('\mod_cms\search\cmsfield', $searcharea); + $this->assertInstanceOf('\mod_cms\search\activity', $searcharea); $course = self::getDataGenerator()->create_course(); $overviews = []; @@ -191,7 +191,7 @@ public function test_get_document_recordset(): void { $this->assertInstanceOf('stdClass', $record); $doc = $searcharea->get_document($record); $this->assertInstanceOf('\core_search\document', $doc); - $this->assertEquals('mod_cms-cmsfield-' . $record->id, $doc->get('id')); + $this->assertEquals('mod_cms-activity-' . $record->id, $doc->get('id')); $this->assertEquals($record->id, $doc->get('itemid')); $this->assertEquals($course->id, $doc->get('courseid')); $this->assertEquals($context->id, $doc->get('contextid')); @@ -223,7 +223,7 @@ public function test_get_document_recordset(): void { */ public function test_default_content(): void { $searcharea = \core_search\manager::get_search_area($this->cmsareaid); - $this->assertInstanceOf('\mod_cms\search\cmsfield', $searcharea); + $this->assertInstanceOf('\mod_cms\search\activity', $searcharea); $course = self::getDataGenerator()->create_course(); @@ -275,7 +275,7 @@ public function test_multiple_contents(): void { // Returns the instance as long as the area is supported. $searcharea = \core_search\manager::get_search_area($this->cmsareaid); - $this->assertInstanceOf('\mod_cms\search\cmsfield', $searcharea); + $this->assertInstanceOf('\mod_cms\search\activity', $searcharea); $cmstype = new cms_types(); $cmstype->set('name', 'Multiple content') From 480aaa22c0091c9ced4715ea72f820909250c799 Mon Sep 17 00:00:00 2001 From: Tomo Tsuyuki Date: Tue, 29 Oct 2024 13:44:20 +1100 Subject: [PATCH 8/8] Issue #66 Remove required file --- classes/search/activity.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/classes/search/activity.php b/classes/search/activity.php index 68dd29f..7209a2f 100644 --- a/classes/search/activity.php +++ b/classes/search/activity.php @@ -21,8 +21,6 @@ use mod_cms\local\model\cms; use mod_cms\local\renderer; -require_once($CFG->dirroot . '/mod/cms/lib.php'); - /** * Define search area. *