Merge branch 'MDL-62899-search-icons-master' of https://github.com/dmitriim/moodle
authorAndrew Nicols <andrew@nicols.co.uk>
Wed, 8 Aug 2018 05:17:34 +0000 (13:17 +0800)
committerAndrew Nicols <andrew@nicols.co.uk>
Wed, 8 Aug 2018 05:17:34 +0000 (13:17 +0800)
21 files changed:
course/classes/search/mycourse.php
course/classes/search/section.php
course/tests/search_test.php
message/classes/search/base_message.php
message/tests/search_received_test.php
message/tests/search_sent_test.php
search/classes/base.php
search/classes/base_block.php
search/classes/base_mod.php
search/classes/document.php
search/classes/document_icon.php [new file with mode: 0644]
search/classes/engine.php
search/templates/result.mustache
search/tests/base_activity_test.php
search/tests/base_block_test.php
search/tests/base_test.php
search/tests/document_icon_test.php [new file with mode: 0644]
search/tests/document_test.php
search/tests/engine_test.php
user/classes/search/user.php
user/tests/search_test.php

index 9c3378c..9cbdc58 100644 (file)
@@ -174,4 +174,14 @@ class mycourse extends \core_search\base {
     public function get_component_name() {
         return 'course';
     }
+
+    /**
+     * Returns an icon instance for the document.
+     *
+     * @param \core_search\document $doc
+     * @return \core_search\document_icon
+     */
+    public function get_doc_icon(\core_search\document $doc) : \core_search\document_icon {
+        return new \core_search\document_icon('i/course');
+    }
 }
index ce28664..42badb4 100644 (file)
@@ -195,4 +195,14 @@ class section extends \core_search\base {
     public function get_component_name() {
         return 'course';
     }
+
+    /**
+     * Returns an icon instance for the document.
+     *
+     * @param \core_search\document $doc
+     * @return \core_search\document_icon
+     */
+    public function get_doc_icon(\core_search\document $doc) : \core_search\document_icon {
+        return new \core_search\document_icon('i/section');
+    }
 }
index 9751f1a..ac9d44d 100644 (file)
@@ -446,4 +446,36 @@ class course_search_testcase extends advanced_testcase {
         $this->assertEquals(\core_search\manager::ACCESS_DELETED,
                 $searcharea->check_access($documents[1]->get('itemid')));
     }
+
+    /**
+     * Test document icon for mycourse area.
+     */
+    public function test_get_doc_icon_for_mycourse_area() {
+        $searcharea = \core_search\manager::get_search_area($this->mycoursesareaid);
+
+        $document = $this->getMockBuilder('\core_search\document')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $result = $searcharea->get_doc_icon($document);
+
+        $this->assertEquals('i/course', $result->get_name());
+        $this->assertEquals('moodle', $result->get_component());
+    }
+
+    /**
+     * Test document icon for section area.
+     */
+    public function test_get_doc_icon_for_section_area() {
+        $searcharea = \core_search\manager::get_search_area($this->sectionareaid);
+
+        $document = $this->getMockBuilder('\core_search\document')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $result = $searcharea->get_doc_icon($document);
+
+        $this->assertEquals('i/section', $result->get_name());
+        $this->assertEquals('moodle', $result->get_component());
+    }
 }
index 58479f2..5a3912f 100644 (file)
@@ -196,4 +196,15 @@ abstract class base_message extends \core_search\base {
               ORDER BY m.timecreated ASC";
         return $DB->get_recordset_sql($sql, $params);
     }
+
+    /**
+     * Returns an icon instance for the document.
+     *
+     * @param \core_search\document $doc
+     *
+     * @return \core_search\document_icon
+     */
+    public function get_doc_icon(\core_search\document $doc) : \core_search\document_icon {
+        return new \core_search\document_icon('t/message');
+    }
 }
index fcc2921..79b7137 100644 (file)
@@ -336,4 +336,20 @@ class message_received_search_testcase extends advanced_testcase {
 
         $this->assertFalse($doc);
     }
+
+    /**
+     * Test document icon.
+     */
+    public function test_get_doc_icon() {
+        $searcharea = \core_search\manager::get_search_area($this->messagereceivedareaid);
+
+        $document = $this->getMockBuilder('\core_search\document')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $result = $searcharea->get_doc_icon($document);
+
+        $this->assertEquals('t/message', $result->get_name());
+        $this->assertEquals('moodle', $result->get_component());
+    }
 }
index 69338d1..7edee7d 100644 (file)
@@ -351,4 +351,20 @@ class message_sent_search_testcase extends advanced_testcase {
         $this->assertFalse($doc);
 
     }
+
+    /**
+     * Test document icon.
+     */
+    public function test_get_doc_icon() {
+        $searcharea = \core_search\manager::get_search_area($this->messagesentareaid);
+
+        $document = $this->getMockBuilder('\core_search\document')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $result = $searcharea->get_doc_icon($document);
+
+        $this->assertEquals('t/message', $result->get_name());
+        $this->assertEquals('moodle', $result->get_component());
+    }
 }
index 4a619cd..ff1006f 100644 (file)
@@ -522,4 +522,14 @@ abstract class base {
     public function get_contexts_to_reindex() {
         return new \ArrayIterator([\context_system::instance()]);
     }
+
+    /**
+     * Returns an icon instance for the document.
+     *
+     * @param \core_search\document $doc
+     * @return \core_search\document_icon
+     */
+    public function get_doc_icon(document $doc) : document_icon {
+        return new document_icon('i/empty');
+    }
 }
index 42f63d4..6f4bdc8 100644 (file)
@@ -398,4 +398,14 @@ abstract class base_block extends base {
             return \context::instance_by_id($id);
         });
     }
+
+    /**
+     * Returns an icon instance for the document.
+     *
+     * @param \core_search\document $doc
+     * @return \core_search\document_icon
+     */
+    public function get_doc_icon(document $doc) : document_icon {
+        return new document_icon('e/anchor');
+    }
 }
index b45ae69..fcf5af6 100644 (file)
@@ -286,4 +286,14 @@ abstract class base_mod extends base {
     public function restrict_cm_access_by_group(\cm_info $cm) {
         return $cm->effectivegroupmode == SEPARATEGROUPS;
     }
+
+    /**
+     * Returns an icon instance for the document.
+     *
+     * @param \core_search\document $doc
+     * @return \core_search\document_icon
+     */
+    public function get_doc_icon(document $doc) : document_icon {
+        return new document_icon('icon', $this->get_module_name());
+    }
 }
index 5f76f94..e7dc914 100644 (file)
@@ -58,6 +58,11 @@ class document implements \renderable, \templatable {
      */
     protected $contexturl = null;
 
+    /**
+     * @var \core_search\document_icon Document icon instance.
+     */
+    protected $docicon = null;
+
     /**
      * @var int|null The content field filearea.
      */
@@ -496,6 +501,24 @@ class document implements \renderable, \templatable {
         return $this->docurl;
     }
 
+    /**
+     * Sets document icon instance.
+     *
+     * @param \core_search\document_icon $docicon
+     */
+    public function set_doc_icon(document_icon $docicon) {
+        $this->docicon = $docicon;
+    }
+
+    /**
+     * Gets document icon instance.
+     *
+     * @return \core_search\document_icon
+     */
+    public function get_doc_icon() {
+        return $this->docicon;
+    }
+
     public function set_context_url(\moodle_url $url) {
         $this->contexturl = $url;
     }
@@ -629,6 +652,10 @@ class document implements \renderable, \templatable {
             $data['userfullname'] = format_string($this->get('userfullname'), true, array('context' => $this->get('contextid')));
         }
 
+        if ($docicon = $this->get_doc_icon()) {
+            $data['icon'] = $output->image_url($docicon->get_name(), $docicon->get_component());
+        }
+
         return $data;
     }
 
diff --git a/search/classes/document_icon.php b/search/classes/document_icon.php
new file mode 100644 (file)
index 0000000..151f61f
--- /dev/null
@@ -0,0 +1,77 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Document icon class.
+ *
+ * @package    core_search
+ * @copyright  2018 Dmitrii Metelkin <dmitriim@catalyst-au.net>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace core_search;
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Represents a document icon.
+ *
+ * @package    core_search
+ * @copyright  2018 Dmitrii Metelkin <dmitriim@catalyst-au.net>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class document_icon {
+    /**
+     * Icon file name.
+     * @var string
+     */
+    protected $name;
+
+    /** Icon file component.
+     * @var string
+     */
+    protected $component;
+
+    /**
+     * Constructor.
+     *
+     * @param string $name Icon name.
+     * @param string $component Icon component.
+     */
+    public function __construct($name, $component = 'moodle') {
+        $this->name = $name;
+        $this->component = $component;
+    }
+
+    /**
+     * Returns name of the icon file.
+     *
+     * @return string
+     */
+    public function get_name() {
+        return $this->name;
+    }
+
+    /**
+     * Returns the component of the icon file.
+     *
+     * @return string
+     */
+    public function get_component() {
+        return $this->component;
+    }
+
+}
index fe7450d..a6b22fc 100644 (file)
@@ -199,6 +199,7 @@ abstract class engine {
         $doc->set_data_from_engine($docdata);
         $doc->set_doc_url($searcharea->get_doc_url($doc));
         $doc->set_context_url($searcharea->get_context_url($doc));
+        $doc->set_doc_icon($searcharea->get_doc_icon($doc));
 
         // Uses the internal caches to get required data needed to render the document later.
         $course = $this->get_course($doc->get('courseid'));
index 331c7a3..2cb7198 100644 (file)
@@ -62,7 +62,7 @@
 }}
 <div class="result">
     <h4 class="result-title">
-        <a href="{{{docurl}}}">{{{title}}}</a>
+        {{#icon}}<img class="icon" alt="" src="{{{icon}}}">{{/icon}}<a href="{{{docurl}}}">{{{title}}}</a>
     </h4>
     {{#content}}
         <div class="result-content">{{{content}}}</div>
index 6c61544..8f99a29 100644 (file)
@@ -373,4 +373,25 @@ class search_base_activity_testcase extends advanced_testcase {
         $contexts = iterator_to_array($glossaryarea->get_contexts_to_reindex(), false);
         $this->assertEquals([], $contexts);
     }
+
+    /**
+     * Test document icon.
+     */
+    public function test_get_doc_icon() {
+        $baseactivity = $this->getMockBuilder('\core_search\base_activity')
+            ->disableOriginalConstructor()
+            ->setMethods(array('get_module_name'))
+            ->getMockForAbstractClass();
+
+        $baseactivity->method('get_module_name')->willReturn('test_activity');
+
+        $document = $this->getMockBuilder('\core_search\document')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $result = $baseactivity->get_doc_icon($document);
+
+        $this->assertEquals('icon', $result->get_name());
+        $this->assertEquals('test_activity', $result->get_component());
+    }
 }
index 5a6d5c1..e6f3458 100644 (file)
@@ -444,4 +444,22 @@ class base_block_testcase extends advanced_testcase {
                 'areaid' => $area->get_area_id(), 'itemid' => 0];
         return $engine->to_document($area, $docdata);
     }
+
+    /**
+     * Test document icon.
+     */
+    public function test_get_doc_icon() {
+        $baseblock = $this->getMockBuilder('\core_search\base_block')
+            ->disableOriginalConstructor()
+            ->getMockForAbstractClass();
+
+        $document = $this->getMockBuilder('\core_search\document')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $result = $baseblock->get_doc_icon($document);
+
+        $this->assertEquals('e/anchor', $result->get_name());
+        $this->assertEquals('moodle', $result->get_component());
+    }
 }
index 08f3442..0d7cb18 100644 (file)
@@ -139,4 +139,22 @@ class search_base_testcase extends advanced_testcase {
         $this->assertEquals([\context_system::instance()],
                 iterator_to_array($area->get_contexts_to_reindex(), false));
     }
+
+    /**
+     * Test default document icon.
+     */
+    public function test_get_default_doc_icon() {
+        $basearea = $this->getMockBuilder('\core_search\base')
+            ->disableOriginalConstructor()
+            ->getMockForAbstractClass();
+
+        $document = $this->getMockBuilder('\core_search\document')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $result = $basearea->get_doc_icon($document);
+
+        $this->assertEquals('i/empty', $result->get_name());
+        $this->assertEquals('moodle', $result->get_component());
+    }
 }
diff --git a/search/tests/document_icon_test.php b/search/tests/document_icon_test.php
new file mode 100644 (file)
index 0000000..917a239
--- /dev/null
@@ -0,0 +1,53 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Document icon unit tests.
+ *
+ * @package    core_search
+ * @copyright  2018 Dmitrii Metelkin <dmitriim@catalyst-au.net>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Document icon unit tests.
+ *
+ * @package    core_search
+ * @copyright  2018 Dmitrii Metelkin <dmitriim@catalyst-au.net>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class search_document_icon_testcase extends advanced_testcase {
+    /**
+     * Test that default component gets returned correctly.
+     */
+    public function test_default_component() {
+        $docicon = new \core_search\document_icon('test_name');
+        $this->assertEquals('test_name', $docicon->get_name());
+        $this->assertEquals('moodle', $docicon->get_component());
+    }
+
+    /**
+     * Test that name and component get returned correctly.
+     */
+    public function test_can_get_name_and_component() {
+        $docicon = new \core_search\document_icon('test_name', 'test_component');
+        $this->assertEquals('test_name', $docicon->get_name());
+        $this->assertEquals('test_component', $docicon->get_component());
+    }
+
+}
index d7196f3..d74a2aa 100644 (file)
@@ -103,6 +103,22 @@ class search_document_testcase extends advanced_testcase {
         $this->assertEquals('Course &amp; Title', $export['coursefullname']);
     }
 
+    /**
+     * Test we can set and get document icon.
+     */
+    public function test_get_and_set_doc_icon() {
+        $document = $this->getMockBuilder('\core_search\document')
+            ->disableOriginalConstructor()
+            ->getMockForAbstractClass();
+
+        $this->assertNull($document->get_doc_icon());
+
+        $docicon = new \core_search\document_icon('test_name', 'test_component');
+        $document->set_doc_icon($docicon);
+
+        $this->assertEquals($docicon, $document->get_doc_icon());
+    }
+
     public function tearDown() {
         // For unit tests before PHP 7, teardown is called even on skip. So only do our teardown if we did setup.
         if ($this->generator) {
index cfe8667..4fdba57 100644 (file)
@@ -26,6 +26,7 @@
 defined('MOODLE_INTERNAL') || die();
 
 require_once(__DIR__ . '/fixtures/testable_core_search.php');
+require_once(__DIR__ . '/fixtures/mock_search_area.php');
 
 /**
  * Search engine base unit tests.
@@ -129,4 +130,24 @@ class search_engine_testcase extends advanced_testcase {
         $this->assertCount(1, $orders);
         $this->assertArrayHasKey('relevance', $orders);
     }
+
+    /**
+     * Test that search engine sets an icon before render a document.
+     */
+    public function test_engine_sets_doc_icon() {
+        $generator = self::getDataGenerator()->get_plugin_generator('core_search');
+        $generator->setup();
+
+        $area = new core_mocksearch\search\mock_search_area();
+        $engine = new \mock_search\engine();
+
+        $record = $generator->create_record();
+        $docdata = $area->get_document($record)->export_for_engine();
+
+        $doc = $engine->to_document($area, $docdata);
+
+        $this->assertNotNull($doc->get_doc_icon());
+
+        $generator->teardown();
+    }
 }
index 337fa28..479b4e0 100644 (file)
@@ -205,4 +205,15 @@ class user extends \core_search\base {
         return 'user';
     }
 
+    /**
+     * Returns an icon instance for the document.
+     *
+     * @param \core_search\document $doc
+     *
+     * @return \core_search\document_icon
+     */
+    public function get_doc_icon(\core_search\document $doc) : \core_search\document_icon {
+        return new \core_search\document_icon('i/user');
+    }
+
 }
index 5e7f5dc..030145f 100644 (file)
@@ -215,4 +215,18 @@ class user_search_testcase extends advanced_testcase {
         $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $searcharea->check_access($user2->id));
         $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $searcharea->check_access($user3->id));
     }
+
+    /**
+     * Test document icon.
+     */
+    public function test_get_doc_icon() {
+        $searcharea = \core_search\manager::get_search_area($this->userareaid);
+        $user = self::getDataGenerator()->create_user();
+        $doc = $searcharea->get_document($user);
+
+        $result = $searcharea->get_doc_icon($doc);
+
+        $this->assertEquals('i/user', $result->get_name());
+        $this->assertEquals('moodle', $result->get_component());
+    }
 }