diff --git a/search-api-page-result.tpl.php b/search-api-page-result.tpl.php new file mode 100644 index 0000000..bf56e48 --- /dev/null +++ b/search-api-page-result.tpl.php @@ -0,0 +1,56 @@ +'. check_plain(print_r($info_split, 1)) .''; ?> + * @endcode + * + * @see template_preprocess() + * @see template_preprocess_search_result() + * @see template_process() + */ +?> +> +

+ +

+
+ +

+ + +

+ +
+ diff --git a/search-api-page-results.tpl.php b/search-api-page-results.tpl.php new file mode 100644 index 0000000..9bbf343 --- /dev/null +++ b/search-api-page-results.tpl.php @@ -0,0 +1,53 @@ + + +
+ + + +

+ + + + +
+ item_type, $items, $variables['view_mode'])); ?> +
+ + + +

+ +
+ diff --git a/search_api_page.info b/search_api_page.info index 148c481..263ce24 100644 --- a/search_api_page.info +++ b/search_api_page.info @@ -4,5 +4,6 @@ description = "Create search pages using Search API indexes." dependencies[] = search_api core = 7.x package = Search +stylesheets[all][] = search_api_page.css configure = admin/config/search/search_api/page diff --git a/search_api_page.module b/search_api_page.module index a9a00cb..6e15c45 100755 --- a/search_api_page.module +++ b/search_api_page.module @@ -60,8 +60,12 @@ function search_api_page_theme() { 'items' => array(), 'view_mode' => 'search_api_page_result', 'keys' => '', + 'page_machine_name' => NULL, + 'spellcheck' => NULL, + 'pager' => NULL, ), 'file' => 'search_api_page.pages.inc', + 'template' => 'search-api-page-results', ); $themes['search_api_page_result'] = array( 'variables' => array( @@ -69,14 +73,99 @@ function search_api_page_theme() { 'result' => NULL, 'item' => NULL, 'keys' => '', + 'list_classes' => '', ), 'file' => 'search_api_page.pages.inc', + 'template' => 'search-api-page-result', + ); + $themes['search_performance'] = array( + 'render element' => 'element', + ); + $themes['search_results_list'] = array( + 'render element' => 'element', ); return $themes; } /** + * Implements theme for rendering search-performance + */ +function theme_search_performance($variables) { + $element = array_shift($variables); + + return $element['#markup']; +} + +/** + * Returns HTML for a list of search results. + * Taken from theme_item_list(). + * + * @param $variables + * An associative array containing: + * - items: An array of items to be displayed in the list. If an item is a + * string, then it is used as is. If an item is an array, then the "data" + * element of the array is used as the contents of the list item. If an item + * is an array with a "children" element, those children are displayed in a + * nested list. All other elements are treated as attributes of the list + * item element. + * - type: The type of list to return (e.g. "ul", "ol"). + * - attributes: The attributes applied to the list element. + */ +function theme_search_results_list($variables) { + // Pull Element array from the $variables array. + $variables = $variables['element']; + + $items = $variables['items']; // Full data + $type = $variables['type']; + + // CSS classes for ul + $attributes = (!empty($variables['attributes'])) ? $variables['attributes'] : array(); + $attributes['class'] = array_merge( + array('item-list', 'search-results-list'), + (isset($attributes['class'])) ? $attributes['class'] : array() + ); + + // Render items within a list + if (!empty($items)) { + $output = "<$type" . drupal_attributes($attributes) . '>'; + $num_items = count($items); + + // Parse search results as tokens to access items with full data. + $i = 0; + foreach ($variables['results'] as $result) { + // Set css classes. + $item_attributes = array(); + if ($i == 0) { + $item_attributes['class'][] = 'first'; + } + if ($i == $num_items - 1) { + $item_attributes['class'][] = 'last'; + } + (($i+1)%2) ? $item_attributes['class'][] = 'odd': $item_attributes['class'][] = 'even'; + + // Define render array. + $data = theme( + 'search_api_page_result', array( + 'index' => $variables['index'], // Use full results index. + 'result' => $result, + 'item' => isset($items[$result['id']]) ? + $items[$result['id']] : + NULL, + 'keys' => $variables['keys'], + 'list_classes' => drupal_attributes($item_attributes), + ) + ); + $output .= $data . "\n"; + $i++; + } + $output .= ""; + + return $output; + } +} + +/** * Implements hook_permission(). */ function search_api_page_permission() { diff --git a/search_api_page.pages.inc b/search_api_page.pages.inc index 7b72a0d..c514909 100644 --- a/search_api_page.pages.inc +++ b/search_api_page.pages.inc @@ -33,14 +33,18 @@ function search_api_page_view($id, $keys = NULL) { watchdog('search_api_page', 'An error occurred while executing a search: !msg.', array('!msg' => $e->getMessage()), WATCHDOG_ERROR, l(t('search page'), $_GET['q'])); } - // If spellcheck results are returned then add them to the render array. + // Load spellcheck. if (isset($results['search_api_spellcheck'])) { - $ret['search_api_spellcheck']['#theme'] = 'search_api_spellcheck'; - $ret['search_api_spellcheck']['#spellcheck'] = $results['search_api_spellcheck']; + $ret['results']['#spellcheck'] = array( + '#theme' => 'search_api_spellcheck', + '#spellcheck' => $results['search_api_spellcheck'], // Let the theme function know where the key is stored by passing its arg // number. We can work this out from the number of args in the page path. - $ret['search_api_spellcheck']['#options'] = array( - 'arg' => array(count(arg(NULL, $page->path))), + '#options' => array( + 'arg' => array(count(arg(NULL, $page->path))), + ), + '#prefix' => '

', + '#suffix' => '

', ); } @@ -49,11 +53,12 @@ function search_api_page_view($id, $keys = NULL) { $ret['results']['#results'] = $results; $ret['results']['#view_mode'] = isset($page->options['view_mode']) ? $page->options['view_mode'] : 'search_api_page_result'; $ret['results']['#keys'] = $keys; + $ret['results']['#page_machine_name'] = $page->machine_name; + // Load pager. if ($results['result count'] > $page->options['per_page']) { pager_default_initialize($results['result count'], $page->options['per_page']); - $ret['pager']['#theme'] = 'pager'; - $ret['pager']['#quantity'] = 9; + $ret['results']['#pager'] = theme('pager'); } if (!empty($results['ignored'])) { @@ -108,96 +113,66 @@ function search_api_page_search_execute(Entity $page, $keys) { /** * Function for preprocessing the variables for the search_api_page_results - * theme. + * template. * * @param array $variables * An associative array containing: - * - index: The index this search was executed on. - * - results: An array of search results, as returned by + * - $index: The index this search was executed on. + * - $results: An array of search results, as returned by * SearchApiQueryInterface::execute(). - * - keys: The keywords of the executed search. - */ -function template_preprocess_search_api_page_results(array &$variables) { - if (!empty($variables['results']['results'])) { - $variables['items'] = $variables['index']->loadItems(array_keys($variables['results']['results'])); - } -} - -/** - * Theme function for displaying search results. + * - $keys: The keywords of the executed search. * - * @param array $variables - * An associative array containing: - * - index: The index this search was executed on. - * - results: An array of search results, as returned by - * SearchApiQueryInterface::execute(). - * - items: The loaded items for all results, in an array keyed by ID. - * - view_mode: The view mode to use for displaying the individual results, - * or the special mode "search_api_page_result" to use the theme function - * of the same name. - * - keys: The keywords of the executed search. + * @see search_api_page-results.tpl.php */ -function theme_search_api_page_results(array $variables) { - drupal_add_css(drupal_get_path('module', 'search_api_page') . '/search_api_page.css'); - - $index = $variables['index']; +function template_preprocess_search_api_page_results(array &$variables) { $results = $variables['results']; - $items = $variables['items']; $keys = $variables['keys']; - $output = '

' . format_plural($results['result count'], - 'The search found 1 result in @sec seconds.', - 'The search found @count results in @sec seconds.', - array('@sec' => round($results['performance']['complete'], 3))) . '

'; - - if (!$results['result count']) { - $output .= "\n

" . t('Your search yielded no results') . "

\n"; - return $output; - } - - $output .= "\n

" . t('Search results') . "

\n"; - - if ($variables['view_mode'] == 'search_api_page_result') { - $output .= '
    '; - foreach ($results['results'] as $item) { - $output .= '
  1. ' . theme('search_api_page_result', array('index' => $index, 'result' => $item, 'item' => isset($items[$item['id']]) ? $items[$item['id']] : NULL, 'keys' => $keys)) . '
  2. '; - } - $output .= '
'; - } - else { - // This option can only be set when the items are entities. - $output .= '
'; - $render = entity_view($index->item_type, $items, $variables['view_mode']); - $output .= render($render); - $output .= '
'; - } + $variables['items'] = $variables['index']->loadItems(array_keys($variables['results']['results'])); + $variables['result_count'] = $results['result count']; + $variables['sec'] = round($results['performance']['complete'], 3); + $variables['search_performance'] = array( + '#theme' => 'search_performance', + '#markup' => format_plural( + $results['result count'], + 'The search found 1 result in @sec seconds.', + 'The search found @count results in @sec seconds.', + array('@sec' => $variables['sec']) + ), + '#prefix' => '

', + '#suffix' => '

', + ); - return $output; + $variables['search_results'] = array( + '#theme' => 'search_results_list', + 'results' => $variables['results']['results'], + 'items' => $variables['items'], + 'index' => $variables['index'], + 'type' => 'ul', + ); } /** - * Theme function for displaying search results. + * Process variables for search-result.tpl.php. * - * @param array $variables - * An associative array containing: - * - index: The index this search was executed on. - * - result: One item of the search results, an array containing the keys - * 'id' and 'score'. - * - item: The loaded item corresponding to the result. - * - keys: The keywords of the executed search. + * The $variables array contains the following arguments: + * - $result + * + * @see search_api_page-result.tpl.php */ -function theme_search_api_page_result(array $variables) { +function template_preprocess_search_api_page_result(&$variables) { $index = $variables['index']; - $id = $variables['result']['id']; + $variables['id'] = $variables['result']['id']; + $variables['excerpt'] = $variables['result']['excerpt']; $item = $variables['item']; $wrapper = $index->entityWrapper($item, FALSE); - $url = $index->datasource()->getItemUrl($item); - $name = $index->datasource()->getItemLabel($item); + $variables['url'] = $index->datasource()->getItemUrl($item); + $variables['title'] = $index->datasource()->getItemLabel($item); - if (!empty($variables['result']['excerpt'])) { - $text = $variables['result']['excerpt']; + if (!empty($variables['excerpt'])) { + $text = $variables['excerpt']; } else { $fields = $index->options['fields']; @@ -239,10 +214,24 @@ function theme_search_api_page_result(array $variables) { } } - $output = '

' . ($url ? l($name, $url['path'], $url['options']) : check_plain($name)) . "

\n"; - if ($text) { - $output .= $text; + // Check for existence. User search does not include snippets. + $variables['snippet'] = isset($text) ? $text : ''; + + // Meta information + global $language; + if (isset($item->language) && $item->language != $language->language && $item->language != LANGUAGE_NONE) { + $variables['title_attributes_array']['xml:lang'] = $item->language; + $variables['content_attributes_array']['xml:lang'] = $item->language; } - return $output; + $info = array(); + if (!empty($item->name)) { + $info['user'] = $item->name; + } + if (!empty($item->created)) { + $info['date'] = format_date($item->created, 'short'); + } + // Provide separated and grouped meta information.. + $variables['info_split'] = $info; + $variables['info'] = implode(' - ', $info); }