Currently, if you are using this module with Facet API and apachesolr, after clicking on a facet link to filter search, the search keys change to include the facet pretty paths segment. For instance, if you searched for "headphones", the path you are on would be something like "/search/site/headphones". Then, if you clicked on a facet to get Klipsch headphones, your path would be something like "/search/site/headphones/brands/Klipsch-4915". The menu callback for apachesolr then grabs everything after "/search/site/" as the search key. So the search box would then say "headphones/brands/Kipsch-4915" (which is likely to return no results).

A related issue for this in apachesolr is here: http://drupal.org/node/1433080

I've attached a patch (for apachesolr) that will get pretty paths to work with apachesolr at the expense of breaking queries with "/" in them. I am unsure whether this is the best solution, but it makes Facet API Pretty Paths testable with apachesolr. A better solution may be to use some kind of menu alter hook from within Facet API Pretty Paths (so that if queries with "/" are broken, at least it's only if this module is active).

The plot thickens now because this issue needs to be handled in a way that supports both Search API and apachesolr (if Facet API Pretty Paths is to support both). With this patch applied to apachesolr, when you are at "/search/site/headphones/brands/Klipsch-4915", the initial value of $item['#path'] within postProcessItem would be "/search/site/headphones". However (if I understand the discussion in this thread correctly) for sites that are using Search API instead of apachesolr, the initial value of $item['#path'] would be "/search/site/headphones/brands/Klipsch-4915" because, for a site using Search API, when this initial value is set in FacetapiFacetProcessor::initializeBuild the call to $this->facet->getAdapter()->getSearchPath() returns the entire path.

Ideally, getSearchPath should return the search path without the facet path segments and be consistent for sites using either apachesolr or Search API. This would allow postProcessItem to sort the facet path segments and produce canonicalized urls, which is super important from an SEO standpoint.

I categorized this as a critical bug because it seems to be behind so many other issues and working out the support of both apachesolr and Search API seems to have a significant effect on how the rest of the code will be put together. Solving this early on, before adding other features to this module will likely make things easier in the long run.

CommentFileSizeAuthor
#19 1434462-19.patch2.93 KBnick_vh
apachesolr_pretty_paths.patch1.36 KBvrc3

Comments

dasjo’s picture

Ideally, getSearchPath should return the search path without the facet path segments and be consistent for sites using either apachesolr or Search API

this is the point.

search_api currently has a rather dumb implementation, which leads to getSearchPath including path pretty path segments at the moment

  /**
   * Overrides FacetapiAdapter::getSearchPath().
   */
  public function getSearchPath() {
    $search = $this->getCurrentSearch();
    if ($search && $search[0]->getOption('search_api_base_path')) {
      return $search[0]->getOption('search_api_base_path');
    }
    return $_GET['q'];
  }

how does apachesolr handle this?

vrc3’s picture

how does apachesolr handle this?

Here is the snippet of code from apachesolr

  /**
   * Returns the search path.
   *
   * @return string
   *   A string containing the search path.
   *
   * @todo D8 should provide an API function for this.
   */
  public function getSearchPath() {
    $env_id = $this->info['instance'];
    $query = apachesolr_current_query($env_id);
    if (!$query || (NULL === $this->searchPath && NULL === $query->getPath())) {
      if ($path = module_invoke($this->info['module'] . '_search', 'search_info')) {
        $this->searchPath = 'search/' . $path['path'];
        if (!isset($_GET['keys']) && ($keys = $this->getSearchKeys())) {
          $this->searchPath .= '/' . $keys;
        }
      }
    }
    if (!$query || NULL === $query->getPath()) {
      return $this->searchPath;
    }
    else {
      return $query->getPath();
    }

  }

The return value of apachesolr_current_query is ultimately set from the arguments to the menu callback for the search page, which, without my patch, grabs the entire path including the facet segments. Perhaps the right functions in apachesolr/Search API can be overridden to set the correct search path, but I'd really appreciate some input from the apachesolr / Search API people...

dasjo’s picture

Category: bug » task
Priority: Critical » Major
Status: Active » Needs review

i have just pushed changes to calculate basePath and use it.
basically it implements the changes proposed in vrc3's patch.

note: as mentioned here, with the recent update, the required facetapi patch changed! use http://drupal.org/files/facetapi-prettypaths-integration-draft.patch

as always, tested with search_api, please review to see what we need to make this work with the apachesolr module.

the current $basePath approach is "locally" for the pretty paths module, while cpliakas pointed out that, "ideally there should also be a getFacetPath() API method". as i'm currently investigating how to #1431676: Integrate with facetapi current_search module.

dasjo’s picture

Status: Needs review » Needs work

currently basePath won't work for pages that are different than the search page.
for example if facets are displayed on the frontpage, they normally link to the associated search page, but the current basePath "override" is not aware of this

dasjo’s picture

Status: Needs work » Fixed

should be fixed now, reopen if necessary

dasjo’s picture

Status: Fixed » Active

i'm reopening as the current implementation is kind of hackish.
described at http://drupal.org/node/1375104#comment-5613602

and cpliakas lists some input in the following comment
http://drupal.org/node/1375104#comment-5615842

dasjo’s picture

i'm using menu_get_item() now to override the base path, if fetchParams finds pretty path segments.

it is still a bit hacky as the url-processor gets fired in many occasions and i have to circumvent facetapi admin pages being processed that way:

    // Skip pretty paths logic for admin pages, as
    // for pretty paths, we have to manipulate $_GET['q].
    // @todo: Fix this workaround?
    if (strpos($_GET['q'], 'admin/') === 0) {
      return $_GET;
    }
dasjo’s picture

regarding apachesolr integration: #1433080: Play nice with the new Facet API Pretty Paths module

i think the described behavior should be fixed already, as fetchParams() now sets the base path.

    // Mock default parameters for facetapi & related search modules.
    if (!empty($params)) {
      // Set search base path.
      $_GET['q'] = $menu_item['path'];
..
    }

but it needs some testing to figure out the details...

vrc3, would you like to try?

vrc3’s picture

I will try sometime in the next few days. But based on the closing of the apachesolr issue, supporting apachesolr may be lost cause unless the right menu alter hook can be written.

The problem is that the menu callback that sets the search keys that are passed into apache solr fires before fetchParams does, so setting the base path there doesn't (if I understand it correctly) help keep the facet path segments out of the search keys.

dasjo’s picture

(edit) i removed some comments, as i might not have read carefully enough what you mentioned about the apachesolr menu callback

you asked

Any insight into which functions can be overridden or which menu alter hook could be implemented in the pretty paths module to make this work?

if resetting the $_GET['q'] in fetchParams isn't enough, we might have to try
http://api.drupal.org/api/drupal/modules%21system%21system.api.php/funct...

vrc3’s picture

if resetting the $_GET['q'] in fetchParams isn't enough, we might have to try
http://api.drupal.org/api/drupal/modules%21system%21system.api.php/funct...

Would this hook fire before the apachesolr menu item grabs the argument?

dasjo’s picture

i guess so

dasjo’s picture

Title: Keeping the search keys out of the facet paths and vice versa » ApacheSolr module integration - Keep search keys out of facet paths

renaming & waiting for some input

vrc3’s picture

Hi dasjo,

I tested the alpha with apachesolr and found that I still needed my modification to apachesolr to get it to work. I also found that I had to modify the condition in encodePathSegment that detects whether the facet is a taxonomy term in order to create a pretty path that contains the actual term. I changed it to: if ($facet['map callback'] == 'facetapi_map_taxonomy_terms') { to get it to work for me. There was a corresponding change in decodePathSegmentValue.

dasjo’s picture

see #1468922: URL aliases require workaround on how to use hook_url_inbound_alter / hook_url_outbound_alter

vrc3’s picture

I did try out hook_url_inbound_alter, and the problem is that it hides the facet paths from both apachesolr AND facetapi. Kind of defeats the purpose.

dasjo’s picture

hook_url_inbound_alter runs before apachesolr & pretty paths, so we could only use it to map a pretty path in a way that it is useable by apachesolr & pretty paths, if necessary.

lets consider an input path like "search/url/segment1/segment2"
an approach might be: map it directly to search/url?q=.... as the fetchParams implementation of the facetapi pretty paths module does

unfortunately, hook_url_inbound_alter runs on every request, while fetchParams does only run when facets are active.

without a clear understanding of how apachesolr vs search_api behave with facetapi regarding the path handling, it seems hard for me to solve this issue.

dasjo’s picture

just to be clear: facetapi_pretty_paths is designed to be generic for any search implementation, but i did only test it with the search_api module.
the above discussion shows, that the apachesolr takes different assumptions and currently it appears just to be broken therefore, though i haven't tested it personally.

i'm willing to review / commit valid patches :)

nick_vh’s picture

StatusFileSize
new2.93 KB

So, I've been hacking away at this module during Drupal Dev Days in Barcelona and got a proof of concept working.
This is the patch that is required in facetapi_pretty_paths to allow apachesolr + facetapi + pretty paths working.

The magic recipe is that there are also some tweaks needed in Apachesolr but I'll post with a link to that issue as soon as I have written down that issue

Edit : Here is the apachesolr patch #1642140: Make the search query also escape the slash and move away from menu_tail to just 1 argument

dasjo’s picture

hi Nick_vh,

thanks a lot for working on this!

i have just committed a clean way to get the args that sun showed me. that should also work for apachesolr.

what do you think? should we re-roll your patch based on that?

nick_vh’s picture

Status: Active » Needs work

That way of replacing the search path + query is awesome and I'm hitting my head because we weren't able to come up with something like this. However, two other changes still need to be incorporated in the module

+++ b/facetapi_pretty_paths.moduleundefined
@@ -152,8 +152,15 @@ function facetapi_pretty_paths_facetapi_pretty_paths_coders() {
-    if ($facet['field type'] == 'taxonomy_term') {
+    // Check for Apache Solr Taxonomy Term fields
+    if(!empty($facet_info['map options']['module_name']) && $facet_info['map options']['module_name'] == 'Taxonomy') {
       $facet['facetapi pretty paths coder'] = 'taxonomy';
+      continue;
+    }
+    // Check for Search API Taxonomy Term fields
+    if (!empty($facet['field type']) && $facet['field type'] == 'taxonomy_term') {
+      $facet['facetapi pretty paths coder'] = 'taxonomy';
+      continue;

This is still needed to get support for both

+++ b/plugins/coders/facetapi_pretty_paths_coder_taxonomy.incundefined
@@ -28,7 +28,8 @@ class FacetApiPrettyPathsCoderTaxonomy extends FacetApiPrettyPathsCoderDefault {
-    $args['value'] = array_pop(explode('-', $args['value']));
+    $exploded = explode('-', $args['value']);
+    $args['value'] = array_pop($exploded);

This should be rerolled and submitted as a different patch

dasjo’s picture

thanks! committed both changes to the 7.x-1.x branch. please tell me if it works for you, so we might be able to roll a new alpha with apachesolr support soon, yeah!

btw the i hadn't used the if continue style within loops that way instead of using select / if elseifs before. interesting

dasjo’s picture

Title: ApacheSolr module integration - Keep search keys out of facet paths » ApacheSolr module integration
Status: Needs work » Needs review
nick_vh’s picture

nick_vh’s picture

Status: Needs review » Fixed
dasjo’s picture

glad to see that in the end it was that easy to fix :)
thank you

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.