Improve your Apache Solr "More Like This" blocks
The Apache Solr module for Drupal allows you to create ‘More Like This’ blocks that show content related to the currently viewed node. These blocks are very useful as they allow your visitors to serendipitously find similar content to that which they are currently viewing.
Unfortunately, while the default theming for ‘More Like This’ blocks is functional, it can be greatly improved by using view modes.
'More' doesn't have to be plain. Photo: MORE Tribute Wall, by Andy Proctor (creative commons) http://www.flickr.com/photos/andy...
The default theming function for the ‘More Like This’ blocks returns a simple list of linked node titles:
<span style="color: #000000"><span style="color: #0000BB"><?php<br></span><span style="color: #007700">function </span><span style="color: #0000BB">theme_apachesolr_search_mlt_recommendation_block</span><span style="color: #007700">(</span><span style="color: #0000BB">$vars</span><span style="color: #007700">) {<br> </span><span style="color: #0000BB">$docs </span><span style="color: #007700">= </span><span style="color: #0000BB">$vars</span><span style="color: #007700">[</span><span style="color: #DD0000">'docs'</span><span style="color: #007700">];<br> </span><span style="color: #0000BB">$links </span><span style="color: #007700">= array();<br> foreach (</span><span style="color: #0000BB">$docs </span><span style="color: #007700">as </span><span style="color: #0000BB">$result</span><span style="color: #007700">) {<br> </span><span style="color: #FF8000">// Suitable for single-site mode. Label is already safe.<br> </span><span style="color: #0000BB">$links</span><span style="color: #007700">[] = </span><span style="color: #0000BB">l</span><span style="color: #007700">(</span><span style="color: #0000BB">$result</span><span style="color: #007700">-></span><span style="color: #0000BB">label</span><span style="color: #007700">, </span><span style="color: #0000BB">$result</span><span style="color: #007700">-></span><span style="color: #0000BB">path</span><span style="color: #007700">, array(</span><span style="color: #DD0000">'html' </span><span style="color: #007700">=> </span><span style="color: #0000BB">TRUE</span><span style="color: #007700">));<br> }<br> </span><span style="color: #0000BB">$links </span><span style="color: #007700">= array(<br> </span><span style="color: #DD0000">'#theme' </span><span style="color: #007700">=> </span><span style="color: #DD0000">'item_list'</span><span style="color: #007700">,<br> </span><span style="color: #DD0000">'#items' </span><span style="color: #007700">=> </span><span style="color: #0000BB">$links</span><span style="color: #007700">,<br> );<br> return </span><span style="color: #0000BB">render</span><span style="color: #007700">(</span><span style="color: #0000BB">$links</span><span style="color: #007700">);<br>}<br></span><span style="color: #0000BB">?></span></span>
To allow the use of View modes for ‘More Like This’ blocks, we need to override this default theming in a custom module.
First, create a new module, and implement hook_theme_registry_alter() to override the default theme function executed when theme('apachesolr_search_mlt_recommendation_block'...) is called:
<span style="color: #000000"><span style="color: #0000BB"><?php<br></span><span style="color: #FF8000">/**<br> * Implements hook_theme_registry_alter<br> *<br> * Update the theme registry so our theme_example_mlt_recommendation_block() is used <br> * instead of the default when theme('apachesolr_search_mlt_recommendeation_block'...) is called.<br> */<br></span><span style="color: #007700">function </span><span style="color: #0000BB">example_theme_registry_alter</span><span style="color: #007700">(&</span><span style="color: #0000BB">$theme_registry</span><span style="color: #007700">) {<br> <br> </span><span style="color: #0000BB">$theme_registry</span><span style="color: #007700">[</span><span style="color: #DD0000">'apachesolr_search_mlt_recommendation_block'</span><span style="color: #007700">][</span><span style="color: #DD0000">'function'</span><span style="color: #007700">] = </span><span style="color: #DD0000">'theme_example_mlt_recommendation_block'</span><span style="color: #007700">;<br> <br> </span><span style="color: #FF8000">// Set the path to this module, so the theme knows where to find the theming function we defined above.<br> </span><span style="color: #0000BB">$theme_registry</span><span style="color: #007700">[</span><span style="color: #DD0000">'apachesolr_search_mlt_recommendation_block'</span><span style="color: #007700">][</span><span style="color: #DD0000">'theme path'</span><span style="color: #007700">] = </span><span style="color: #0000BB">drupal_get_path</span><span style="color: #007700">(</span><span style="color: #DD0000">'module'</span><span style="color: #007700">, </span><span style="color: #DD0000">'example'</span><span style="color: #007700">);<br>}<br></span><span style="color: #0000BB">?></span></span>
We then implement our new theming function which accepts the same input as the original theming function:
<span style="color: #000000"><span style="color: #0000BB"><?php<br></span><span style="color: #FF8000">/**<br> * Our own theming function the theme the MLT blocks to use node views.<br> */<br></span><span style="color: #007700">function </span><span style="color: #0000BB">theme_example_mlt_recommendation_block</span><span style="color: #007700">(</span><span style="color: #0000BB">$vars</span><span style="color: #007700">) {<br> </span><span style="color: #0000BB">$docs </span><span style="color: #007700">= </span><span style="color: #0000BB">$vars</span><span style="color: #007700">[</span><span style="color: #DD0000">'docs'</span><span style="color: #007700">];<br> </span><span style="color: #0000BB">$output </span><span style="color: #007700">= array();<br> </span><span style="color: #0000BB">$nids </span><span style="color: #007700">= array();<br> <br> foreach (</span><span style="color: #0000BB">$docs </span><span style="color: #007700">as </span><span style="color: #0000BB">$result</span><span style="color: #007700">) { <br> </span><span style="color: #FF8000">// Collect the nids from the results.<br> </span><span style="color: #007700">if (</span><span style="color: #0000BB">$result</span><span style="color: #007700">-></span><span style="color: #0000BB">entity_type </span><span style="color: #007700">== </span><span style="color: #DD0000">'node'</span><span style="color: #007700">) {<br> </span><span style="color: #0000BB">$nids</span><span style="color: #007700">[] = </span><span style="color: #0000BB">$result</span><span style="color: #007700">-></span><span style="color: #0000BB">entity_id</span><span style="color: #007700">;<br> }<br> }<br> <br> if (!empty(</span><span style="color: #0000BB">$nids</span><span style="color: #007700">)) { <br> </span><span style="color: #FF8000">// Load the nodes for the 'More Like This' results.<br> </span><span style="color: #0000BB">$nodes </span><span style="color: #007700">= </span><span style="color: #0000BB">node_load_multiple</span><span style="color: #007700">(</span><span style="color: #0000BB">$nids</span><span style="color: #007700">); <br> <br> </span><span style="color: #FF8000">// Format the nodes as with the 'example_mlt_view_mode' view mode.<br> </span><span style="color: #0000BB">$output </span><span style="color: #007700">= </span><span style="color: #0000BB">node_view_multiple</span><span style="color: #007700">(</span><span style="color: #0000BB">$nodes</span><span style="color: #007700">, </span><span style="color: #DD0000">'example_mlt_view_mode'</span><span style="color: #007700">);<br> }<br> <br> </span><span style="color: #FF8000">// Return the rendered output.<br> </span><span style="color: #007700">return </span><span style="color: #0000BB">render</span><span style="color: #007700">(</span><span style="color: #0000BB">$output</span><span style="color: #007700">);<br>}<br></span><span style="color: #0000BB">?></span></span>
As each search snippet is processed, we collect the nid
. We then load all the nodes we will need, and pass them to node_view_multiple()
for display, with an argument indicating the view mode to use. In this case, we are instructing node_view_multiple()
to use the example_mlt_view_mode
view mode.
The final task is to implement the new view mode needed for the ‘More Like This’ block. View Modes are a new concept for Drupal 7 which bring much flexibility to your node displays. For a full overview, read Custom Drupal 7 view modes: Different ways to see your content.
A new view mode called ‘More Like This block’ can be created as follows:
<span style="color: #000000"><span style="color: #0000BB"><?php<br></span><span style="color: #FF8000">/**<br> * Implements hook_entity_info_alter().<br> */<br></span><span style="color: #007700">function </span><span style="color: #0000BB">example_entity_info_alter</span><span style="color: #007700">(&</span><span style="color: #0000BB">$entity_info</span><span style="color: #007700">) {<br> <br> </span><span style="color: #FF8000">// Define a new View mode for 'More Like This blocks'. Ensure the <br> // machine name ('example_mlt_view_mode') matches the one defined in <br> // our call to node_view_multiple() above.<br> </span><span style="color: #0000BB">$entity_info</span><span style="color: #007700">[</span><span style="color: #DD0000">'node'</span><span style="color: #007700">][</span><span style="color: #DD0000">'view modes'</span><span style="color: #007700">][</span><span style="color: #DD0000">'example_mlt_view_mode'</span><span style="color: #007700">] = array(<br> </span><span style="color: #DD0000">'label' </span><span style="color: #007700">=> </span><span style="color: #0000BB">t</span><span style="color: #007700">(</span><span style="color: #DD0000">'More Like This block'</span><span style="color: #007700">),<br> </span><span style="color: #DD0000">'custom settings' </span><span style="color: #007700">=> </span><span style="color: #0000BB">TRUE</span><span style="color: #007700">,<br> );<br>}<br> <br></span><span style="color: #FF8000">/**<br> * Implements hook_preprocess_node(). <br> * <br> * Suggest theme hooks for our new view mode so we can use<br> * a template for display. The new view mode can be themed with either<br> * node__example_mlt_view_mode.tpl.php or node__<TYPE>__example_mlt_view_mode.tpl.php<br> */<br></span><span style="color: #007700">function </span><span style="color: #0000BB">example_preprocess_node</span><span style="color: #007700">(&</span><span style="color: #0000BB">$vars</span><span style="color: #007700">) {<br> <br> if (</span><span style="color: #0000BB">$vars</span><span style="color: #007700">[</span><span style="color: #DD0000">'view_mode'</span><span style="color: #007700">] == </span><span style="color: #DD0000">'example_mlt_view_mode'</span><span style="color: #007700">) { <br> </span><span style="color: #0000BB">$vars</span><span style="color: #007700">[</span><span style="color: #DD0000">'theme_hook_suggestions'</span><span style="color: #007700">][] = </span><span style="color: #DD0000">'node__example_mlt_view_mode'</span><span style="color: #007700">;<br> </span><span style="color: #0000BB">$vars</span><span style="color: #007700">[</span><span style="color: #DD0000">'theme_hook_suggestions'</span><span style="color: #007700">][] = </span><span style="color: #DD0000">'node__' </span><span style="color: #007700">. </span><span style="color: #0000BB">$vars</span><span style="color: #007700">[</span><span style="color: #DD0000">'type'</span><span style="color: #007700">] . </span><span style="color: #DD0000">'__example_mlt_view_mode'</span><span style="color: #007700">;<br> }<br>}<br></span><span style="color: #0000BB">?></span></span>
This will provide you with a new view mode to which we can assign fields on each node type.