Monday, January 23, 2017

Adding search to your Moodle plugin

Part One - The Basics

In Moodle 3.1, the "Global Search" feature was introduced. This feature provides the ability for a user to search for text within the entire site for entered terms. The results obey all role and capability rules, so only parts that can be legitimately accessed by the requesting user are returned.

As delivered, core activities are included in the global search. But plugins need to provide code to the search API in order to be included in the search results. In this series of blog posts, I am going to add the search feature to my questionnaire plugin.

Some resources that will help with this task are:


The global search feature uses search engine plugins to provide the search functions. Currently, there is only one plugin, that uses an external technology called Solr. In order to use search, and enable me to test my work, I will install it in my development environment. Moodle provides documentation to do this. Since I am using OSX with Macports, I follow those instructions. After that, I use the administration functions in my Moodle site to enable global search and verify that it is working. I'm not going to go into the details of that here, but the documentation links were enough for me to successfully do this.

Before I start, I'm going to use the search function to see how it works with the existing activities, and verify that it is not working for mine. I'm using Moodle 3.2 with the Boost theme. The search function is located in the upper right part of the navigation bar, with a text box entry next to a magnifying glass icon as below:


Once I enter my search text, for example "test", the screen displays everything it found and some further options. Under the "filter" section, there is a "Search area" drop down that lists all of the areas available to search within (see image below). My plugin does not appear there, so I presume this will be one of the places that I will see a change once I have enabled search in my plugin.


I also notice that in those filter choices, some of the activities show only "activity information" while others show this and other levels of the activity. These correspond to what content an activity returns to the search function. Looking at the documentation, I see that returning the "activity information" is the easiest case, and does not require much work at all. I am going to start there.

I have created a working branch off of my latest Moodle 3.2 branch called GLOBALSEARCH_32 as my starting point. You can follow along on Github here.

The documentation makes this look pretty straight forward. I create a subdirectory called search in my plugin's classes subdirectory. In that new directory, I add a file named activity.php. The contents, are basically this (you can see the entire file here):

    namespace mod_questionnaire\search;

    class activity extends \core_search\base_activity {
    }

I'm going to update my development site with this new code, and see what happens. After copying, I check the filter dropdown as above, but I don't see the questionnaire in the list. In all likelihood, I need to purge all of the caches. After doing that, the page reloads, but gives me the following error:

Invalid get_string() identifier: 'search:activity' or component 'mod_questionnaire'. Perhaps you are missing $string['search:activity'] = ''; in mod/questionnaire/lang/en/questionnaire.php?
  • line 349 of /lib/classes/string_manager_standard.php: call to debugging()
  • line 7076 of /lib/moodlelib.php: call to core_string_manager_standard->get_string()
  • line 146 of /search/classes/base.php: call to get_string()
  • line 62 of /search/classes/output/form/search.php: call to core_search\base->get_visible_name()
  • line 204 of /lib/formslib.php: call to core_search\output\form\search->definition()
  • line 59 of /search/index.php: call to moodleform->__construct()
It looks like I need to define a specific language string as well. The error nicely tells me exactly what I need. I add the line:
    $string['search:activity'] = 'Questionnaire - activity information';
to the lang/en/questionnaire.php file and try again. This time, I have no error, and the drop down shows my activity in the list:


However, when I perform a search that should include a questionnaire, it does not show up. The most likely reason is that the search engine has not indexed the plugin into its database yet. The global search can be scheduled to reindex its database, and it can also be manually reindexed. At the main global search administration page, admin/settings.php?section=manageglobalsearch, there is an "Index data" link. Reviewing that page, I can see that there is a section for "Questionnaire - activity information", that is showing as never having been indexed. When I click the "Update indexed contents" button, also on that page, my questionnaire now shows as having been indexed. I perform my search again, and I can now see results from my questionnaire.

Adding the basic search functionality turned out to be extremely easy. I simple had to add one file that extended a class, and one language string. In the next post, I'll add extra levels of searching to include questionnaire "subtitle" and "additional info" sections.


No comments:

Post a Comment