diff --git a/contentbank/classes/content.php b/contentbank/classes/content.php index 28cb9650797..a77b7a08e84 100644 --- a/contentbank/classes/content.php +++ b/contentbank/classes/content.php @@ -211,7 +211,7 @@ abstract class content { * * @return bool True if content could be accessed. False otherwise. */ - public function can_view(): bool { + public function is_view_allowed(): bool { // There's no capability at content level to check, // but plugins can overwrite this method in case they want to check something related to content properties. return true; diff --git a/contentbank/classes/contentbank.php b/contentbank/classes/contentbank.php index 2e89d42d96c..c5ab6c13bb8 100644 --- a/contentbank/classes/contentbank.php +++ b/contentbank/classes/contentbank.php @@ -155,4 +155,54 @@ class contentbank { } return null; } + + /** + * Find the contents with %$search% in the contextid defined. + * If contextid and search are empty, all contents are returned. + * In all the cases, only the contents for the enabled contentbank-type plugins are returned. + * + * @param string|null $search Optional string to search (for now it will search only into the name). + * @param int $contextid Optional contextid to search. + * @return array The contents for the enabled contentbank-type plugins having $search as name and placed in $contextid. + */ + public function search_contents(?string $search = null, ?int $contextid = 0): array { + global $DB; + + $contents = []; + + // Get only contents for enabled content-type plugins. + $contenttypes = array_map(function($contenttypename) { + return "contenttype_$contenttypename"; + }, $this->get_enabled_content_types()); + if (empty($contenttypes)) { + // Early return if there are no content-type plugins enabled. + return $contents; + } + + list($sqlcontenttypes, $params) = $DB->get_in_or_equal($contenttypes, SQL_PARAMS_NAMED); + $sql = " contenttype $sqlcontenttypes "; + + // Filter contents on this context (if defined). + if (!empty($contextid)) { + $params['contextid'] = $contextid; + $sql .= ' AND contextid = :contextid '; + } + + // Search for contents having this string (if defined). + if (!empty($search)) { + $sql .= ' AND ' . $DB->sql_like('name', ':name', false, false); + $params['name'] = '%' . $DB->sql_like_escape($search) . '%'; + } + + $records = $DB->get_records_select('contentbank_content', $sql, $params); + foreach ($records as $record) { + $contentclass = "\\$record->contenttype\\content"; + $content = new $contentclass($record); + if ($content->is_view_allowed()) { + $contents[] = $content; + } + } + + return $contents; + } } diff --git a/contentbank/tests/contentbank_test.php b/contentbank/tests/contentbank_test.php index 199b73a4cf4..824f7a51a6b 100644 --- a/contentbank/tests/contentbank_test.php +++ b/contentbank/tests/contentbank_test.php @@ -175,4 +175,143 @@ class core_contentbank_testcase extends advanced_testcase { $supporter = $cb->get_extension_supporter($extension, $systemcontext); $this->assertEquals($expected, $supporter); } + + /** + * Test the behaviour of search_contents(). + * + * @dataProvider search_contents_provider + * @param string $search String to search. + * @param int $contextid Contextid to search. + * @param int $expectedresult Expected result. + * @param array $contexts List of contexts where to create content. + */ + public function test_search_contents(?string $search, int $contextid, int $expectedresult, array $contexts = []): void { + global $DB; + + $this->resetAfterTest(); + + // Create users. + $managerroleid = $DB->get_field('role', 'id', ['shortname' => 'manager']); + $manager = $this->getDataGenerator()->create_user(); + $this->getDataGenerator()->role_assign($managerroleid, $manager->id); + + // Add some content to the content bank. + $generator = $this->getDataGenerator()->get_plugin_generator('core_contentbank'); + foreach ($contexts as $context) { + $records = $generator->generate_contentbank_data('contenttype_h5p', 3, + $manager->id, $context, false); + } + + // Search for some content. + $cb = new \core_contentbank\contentbank(); + $contents = $cb->search_contents($search, $contextid); + + $this->assertCount($expectedresult, $contents); + if (!empty($contents) && !empty($search)) { + foreach ($contents as $content) { + $this->assertContains($search, $content->get_name()); + } + } + } + + /** + * Data provider for test_search_contents(). + * + * @return array + */ + public function search_contents_provider(): array { + // Create a category and a course. + $systemcontext = \context_system::instance(); + $coursecat = $this->getDataGenerator()->create_category(); + $course = $this->getDataGenerator()->create_course(); + $coursecatcontext = \context_coursecat::instance($coursecat->id); + $coursecontext = \context_course::instance($course->id); + + return [ + 'Search all content in all contexts' => [ + null, + 0, + 9, + [$systemcontext, $coursecatcontext, $coursecontext] + ], + 'Search in all contexts for existing string in all contents' => [ + 'content', + 0, + 9, + [$systemcontext, $coursecatcontext, $coursecontext] + ], + 'Search in all contexts for unexisting string in all contents' => [ + 'chocolate', + 0, + 0, + [$systemcontext, $coursecatcontext, $coursecontext] + ], + 'Search in all contexts for existing string in some contents' => [ + '1', + 0, + 3, + [$systemcontext, $coursecatcontext, $coursecontext] + ], + 'Search in all contexts for existing string in some contents (create only 1 context)' => [ + '1', + 0, + 1, + [$systemcontext] + ], + 'Search in system context for existing string in all contents' => [ + 'content', + $systemcontext->id, + 3, + [$systemcontext, $coursecatcontext, $coursecontext] + ], + 'Search in category context for unexisting string in all contents' => [ + 'chocolate', + $coursecatcontext->id, + 0, + [$systemcontext, $coursecatcontext, $coursecontext] + ], + 'Search in course context for existing string in some contents' => [ + '1', + $coursecontext->id, + 1, + [$systemcontext, $coursecatcontext, $coursecontext] + ], + 'Search in system context' => [ + null, + $systemcontext->id, + 3, + [$systemcontext, $coursecatcontext, $coursecontext] + ], + 'Search in course context with existing content' => [ + null, + $coursecontext->id, + 3, + [$systemcontext, $coursecatcontext, $coursecontext] + ], + 'Search in course context without existing content' => [ + null, + $coursecontext->id, + 0, + [$systemcontext, $coursecatcontext] + ], + 'Search in an empty contentbank' => [ + null, + 0, + 0, + [] + ], + 'Search in a context in an empty contentbank' => [ + null, + $systemcontext->id, + 0, + [] + ], + 'Search for a string in an empty contentbank' => [ + 'content', + 0, + 0, + [] + ], + ]; + } }