Developing a Smart Search Plugin
With the Joomla! 2.5 release, a new search component has been included to improve the search engine in Joomla! sites. Based on JXtended's Finder, Smart Search is quite the powerful tool and can be used to improve search results and show the user exactly what they want. Out of the box, Smart Search will work for most core data, but third party developers will have to create their own Finder plugins to interact with Smart Search. Not to worry, I'll help you get started with that now!
What do the Finder plugins do?
The Finder plugins are where the logic is built to search for items and automatically update them during normal site use. Without these plugins, data from a component cannot be indexed and processed during searches from the Smart Search component. This same requirement exists for the "classic" Search component to enable data to be searched.
What do the Finder plugins need?
Each plugin will have its own unique requirements, but there is some code that each plugin requires to allow for proper functioning. In lieu of posting numerous code snippets, I'll instead link you to the Finder plugin for com_content articles at GitHub: https://github.com/joomla/joomla-cms/blob/master/plugins/finder/content/content.php. I encourage you to follow along with the code as I describe it here.
Class Properties and External Dependencies
As you can see just below the file doc block, there are two files that are required to be loaded. The jimport call loads the JComponentHelper class, and this class is used in the index method. Next, the require_once statement loads the Finder plugin's parent class, FinderIndexerAdapter. All Finder plugins must extend this class in order to function properly.
Now, I'll explain each of the class properties set in this plugin, as well as a few properties in the parent class to be aware of:
- $context - This is an identifier for the plugin; in all core use, this is the part of the class name after plgFinder
- $extension - The extension the plugin supports, i.e. com_content
- $layout - The name of the sublayout that will be used when rendering search results; in core use, this is the name of the single item view on the component's front end (to further explain this, by default, the front end logic will search for a default_article.php template file in the search view of com_finder, and if not present, defaults to the default_result.php file)
- $type_title - The title of the content type being processed by the plugin; this will be used to display the name of the "Type" filtering option when the filters are available (note, this is tied to a language string as well; see the appropriate language file for details on the structure of the key)
- $table - The database table that the component's data is stored in (note: must use the #__ prefix here)
Additional properties in the parent FinderIndexerAdapter class are:
- $mime - If indexing various file types (such as PDF files), this property should to be set to the correct MIME of that data - defaults to NULL
- $db - The database object, all plugins should interact with the database using
- $state_field - This is the field in which the published state is stored in in the database (usually state or field) - defaults to state
Class Functions and Parent Information
Next, I'll describe each of the functions in this class as well as important methods to be aware of in the parent FinderIndexerAdapter class. Except for the Finder plugin for working with com_categories, each of these functions feeds into a parent class which contains generic code to update the index properties of an item. Developers who wish to override these functions should carefully review what the parent classes do so that their data is properly handled in all instances.
- public function __construct - Standard constructor class required by most plugins in order to load the plugin's language files from their default locations
- public function onFinderCategoryChangeState - New to Joomla! 2.5, this method is triggered at the same time as the onCategoryChangeState event, which is triggered when a category's published state is changed in the admin list view, used to update index properties of child items of a category (obviously, not needed for components which do not have a category->item structure)
- public function onFinderAfterDelete - This event acts at the same time as onContentAfterDelete and by default, removes the index data for items that have been removed either in the component or in the Smart Search administrator section.
- public function onFinderAfterSave - This event acts at the same time as onContentAfterSave and by default, updates the access level information for items when the item's access level is changed or when its parent category's access level is changed. The context check for the single item should include both the backend and frontend single item edit views to work properly.
- public function onFinderBeforeSave - This event acts at the same time as onContentBeforeSave and by default, queries for and stores the item or parent category's access level; used in conjunction with onFinderAfterSave to change the index data when the access level is changed
- public function onFinderChangeState - This event acts at the same time as onContentChangeState and by default, updates the published state information for items when the published state is changed in the administrator list view. Also, this method catches when the plugin is disabled and removes index data handled by the now disabled plugin.
- protected function index - This is the method that handles all processing to add items to the search index. This is where things such as the item's raw URL, routed URL, and metadata are set.
- protected function setup - This method is run prior to the index method and prepares the indexer to process the plugin's data. In core use, each extension's route helper is included so that the routing can be properly set during index.
- protected function getListQuery - This method sets a JDatabaseQuery object with a query to pull the data that should be indexed. The JDatabase and JDatabaseQuery APIs must be used here otherwise the indexer will fail.
Methods that developers should be aware of from the parent FinderIndexerAdapter class are:
- protected function getStateQuery - This method sets a JDatabaseQuery object with a query to pull the published state and access levels of an item and its parent category. Components not using a category->item structure will need to override this method in their plugins.
- protected function getUpdateQueryByTime - This method sets a JDatabaseQuery object with a query to pull the update time from a database table's "modified" field. Components which either don't store this data or use a different field name will need to override this method in their plugins.
- protected function getURL - This method returns the non-SEF URL of an item. Using com_content with an article ID of 1, the default return is "index.php?option=com_content&view=article&id=1. Developers who need to add additional information to the URL will need to override this method in their plugins.
Note that this is by no means a complete listing of the full API for the Smart Search component, but just a highlight of methods that developers need to be aware of at a minimum to write functioning plugins for their components.
I Have Questions!!!
Undoubtedly, there will be a question or three that will be asked about Smart Search. Obviously, the best resources to use will be the Joomla! Forums (http://forum.joomla.org) and Joomla! WIKI (http://docs.joomla.org). Several pages already exist on the WIKI with information about Smart Search, and I personally frequent the forums and read many of the threads and am willing to help answer questions about Smart Search. So, don't be shy, ask away!