Merge branch 'MDL-67797-master' of git://github.com/sarjona/moodle
authorEloy Lafuente (stronk7) <stronk7@moodle.org>
Mon, 27 Apr 2020 21:00:59 +0000 (23:00 +0200)
committerEloy Lafuente (stronk7) <stronk7@moodle.org>
Mon, 27 Apr 2020 21:00:59 +0000 (23:00 +0200)
contentbank/classes/content.php
contentbank/classes/contentbank.php
contentbank/index.php
contentbank/tests/contentbank_test.php

index 28cb965..a77b7a0 100644 (file)
@@ -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;
index 2e89d42..0a21353 100644 (file)
@@ -15,7 +15,7 @@
 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
 
 /**
- * Content bank manager class
+ * Content bank class
  *
  * @package    core_contentbank
  * @copyright  2020 Amaia Anabitarte <amaia@moodle.com>
@@ -25,7 +25,7 @@
 namespace core_contentbank;
 
 /**
- * Content bank manager class
+ * Content bank class
  *
  * @package    core_contentbank
  * @copyright  2020 Amaia Anabitarte <amaia@moodle.com>
@@ -44,8 +44,9 @@ class contentbank {
         $enabledtypes = \core\plugininfo\contenttype::get_enabled_plugins();
         $types = [];
         foreach ($enabledtypes as $name) {
-            $classname = "\\contenttype_$name\\contenttype";
-            if (class_exists($classname)) {
+            $contenttypeclassname = "\\contenttype_$name\\contenttype";
+            $contentclassname = "\\contenttype_$name\\content";
+            if (class_exists($contenttypeclassname) && class_exists($contentclassname)) {
                 $types[] = $name;
             }
         }
@@ -65,16 +66,14 @@ class contentbank {
             $supportedextensions = [];
             foreach ($this->get_enabled_content_types() as $type) {
                 $classname = "\\contenttype_$type\\contenttype";
-                if (class_exists($classname)) {
-                    $manager = new $classname;
-                    if ($manager->is_feature_supported($manager::CAN_UPLOAD)) {
-                        $extensions = $manager->get_manageable_extensions();
-                        foreach ($extensions as $extension) {
-                            if (array_key_exists($extension, $supportedextensions)) {
-                                $supportedextensions[$extension][] = $type;
-                            } else {
-                                $supportedextensions[$extension] = [$type];
-                            }
+                $contenttype = new $classname;
+                if ($contenttype->is_feature_supported($contenttype::CAN_UPLOAD)) {
+                    $extensions = $contenttype->get_manageable_extensions();
+                    foreach ($extensions as $extension) {
+                        if (array_key_exists($extension, $supportedextensions)) {
+                            $supportedextensions[$extension][] = $type;
+                        } else {
+                            $supportedextensions[$extension] = [$type];
                         }
                     }
                 }
@@ -100,12 +99,10 @@ class contentbank {
             foreach ($supportedextensions as $extension => $types) {
                 foreach ($types as $type) {
                     $classname = "\\contenttype_$type\\contenttype";
-                    if (class_exists($classname)) {
-                        $manager = new $classname($context);
-                        if ($manager->can_upload()) {
-                            $contextextensions[$extension] = $type;
-                            break;
-                        }
+                    $contenttype = new $classname($context);
+                    if ($contenttype->can_upload()) {
+                        $contextextensions[$extension] = $type;
+                        break;
                     }
                 }
             }
@@ -155,4 +152,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;
+    }
 }
index 3a3e9c3..bbf9786 100644 (file)
@@ -27,6 +27,7 @@ require('../config.php');
 require_login();
 
 $contextid    = optional_param('contextid', \context_system::instance()->id, PARAM_INT);
+$search = optional_param('search', '', PARAM_CLEAN);
 $context = context::instance_by_id($contextid, MUST_EXIST);
 
 require_capability('moodle/contentbank:access', $context);
@@ -46,27 +47,13 @@ $PAGE->set_heading($title);
 $PAGE->set_pagetype('contenbank');
 
 // Get all contents managed by active plugins to render.
-$foldercontents = array();
-$contents = $DB->get_records('contentbank_content', ['contextid' => $contextid]);
-foreach ($contents as $content) {
-    $plugin = core_plugin_manager::instance()->get_plugin_info($content->contenttype);
-    if (!$plugin || !$plugin->is_enabled()) {
-        continue;
-    }
-    $contentclass = "\\$content->contenttype\\content";
-    if (class_exists($contentclass)) {
-        $contentmanager = new $contentclass($content);
-        if ($contentmanager->can_view()) {
-            $foldercontents[] = $contentmanager;
-        }
-    }
-}
+$cb = new \core_contentbank\contentbank();
+$foldercontents = $cb->search_contents($search, $contextid);
 
 // Get the toolbar ready.
 $toolbar = array ();
 if (has_capability('moodle/contentbank:upload', $context)) {
     // Don' show upload button if there's no plugin to support any file extension.
-    $cb = new \core_contentbank\contentbank();
     $accepted = $cb->get_supported_extensions_as_string($context);
     if (!empty($accepted)) {
         $importurl = new moodle_url('/contentbank/upload.php', ['contextid' => $contextid]);
index 199b73a..824f7a5 100644 (file)
@@ -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,
+                []
+            ],
+        ];
+    }
 }