We really want to move to using pretty facet paths, and for the most part this module does exactly what we need. There are a couple of issues though. One is that the breadcrumb links don't use the pretty paths which I think is covered in #1514980: Support for breadcrumb. The other problem is getting them to work on node pages. For example. Currently in one of our views, we do some manipulation to allow us to carry the active facets over from a views search result page to a node view page. It's a bit of a hack, done directly in a views field template override:


// Add in a facet for gender
$query = drupal_get_query_parameters();
$query['f'] = !empty($query['f'])? $query['f'] : array();
if (isset($query['f'])) {
  if (isset($view->filter['field_product_field_optics_audience']->value)) {
    array_unshift($query['f'], 'field_product%3Afield_optics_audience:' . $view->filter['field_product_field_optics_audience']->value);
  }
  if (isset($view->filter['field_product_field_optics_frame_function']->value)) {
    array_unshift($query['f'], 'field_product%3Afield_optics_frame_function:' . $view->filter['field_product_field_optics_frame_function']->value);
  }
  $query['search_path'] = $_GET['q'];
}
$output = l($output, 'node/' . $nid, array('query' => $query, 'html' => TRUE));

print $output;
?>

What this does is it concatinates the active facets, plus one additional facet to the link as generated bu views. The result is is that instead of linking directly through to the product at http://www.example.com/frames/flex-mx929 you actually get links that go to something like http://www.example.com/frames/flex-mx929?f[0]=field_product%253Afield_op.... Which ensure that when you view the product, the previously selected facets are still active.

I'm trying to understand how we can do the same thing but using pretty facet paths instead.

In my testing I can see that I can actually view a node at http://ks.example/node/1216/brand/Anna%20Sui/brand/Burberry which has 2 active 'brand' facets. But as soon as I swap out node/1216 for the node's alias that no longer works. I wonder if this aliasing problem is related to #1468922: URL aliases require workaround?

Comments

dasjo’s picture

In my testing I can see that I can actually view a node at http://ks.example/node/1216/brand/Anna%20Sui/brand/Burberry which has 2 active 'brand' facets. But as soon as I swap out node/1216 for the node's alias that no longer works. I wonder if this aliasing problem is related to #1468922: URL aliases require workaround?

yes, i would recommend trying to do the url alias workaround. as drupal doesn't have a path alias set for http://ks.example/your-node-alias/brand/Anna%20Sui/brand/Burberry you will need to have hook_url_inbound_alter map it to http://ks.example/node/1216/brand/Anna%20Sui/brand/Burberry

mrfelton’s picture

Hm.. That would mean I would need to map every single node alias?!

dasjo’s picture

i would try implementing a hook_url_inbound_alter the following way:
- url is http://ks.example/your-node-alias/brand/Anna%20Sui/brand/Burberry
- implement some logic to get your "base path"
- do a drupal path alias lookup for the "base path" http://ks.example/your-node-alias, this should return http://ks.example/node/1216
- replace the base_path with it's source.

would be something like this:

split_my_url($path, $base_path, $pretty_path_part);
$source = drupal_lookup_path('source', $base_path);
$path = $source . $pretty_path_part;
mrfelton’s picture

That could work. But a simple test of the inbound_alter workaround makes me think its not going to work as intended anyway. For example:

  if (preg_match('|^frame/flex-mx929/(.*)|', $path, $matches)) {
    $path = 'node/1065/' . $matches[1];
  }

This works, to an extent. I can access /frame/flex-mx929/brand/Flex and it redirects to node/1065/brand/Flex showing me the node with the facets applied. So it means I can access the nodes at their aliased urls with pretty facet paths appended. But instead of showing me the content at that aliased URL, the path in the URL bar gets rewritten to the node/[nid] base form where really, I want the alias to be retained otherwise it kinda defeats the point.

mrfelton’s picture

Ahh, wait. It will work, but there is an issue with globalredirect #774950: Incompatible with hook_url_inbound_alter(). If I disable globalredirect it works as intended.

mrfelton’s picture

For the record, this works for my use case:

  // Allow facetapi_pretty_paths to work on aliased node view pages.
  // See http://drupal.org/node/1519680 for conversation.
  if (preg_match('|^(frames/.*?)(/.*)|', $path, $matches)) {
    $source = drupal_lookup_path('source', $matches[1]);
    $pretty_path_part = $matches[2];
    $path = $source . $pretty_path_part;
  }
mrfelton’s picture

Title: Applying pretty facet paths on node view pages » Applying pretty facet paths on node view pages (make constructPath() a public method)
Category: support » feature

So... I have managed to do what I needed to do, by replacing the original code as per my original post above, with some slightly more complex looking code (although should also be a little more robust) that does the same things, but using pretty paths.

In order to make this work, I needed to be able to call facetapi_pretty_paths' constructPath() method externally (see below). Is there any specific reason why this is a protected method? And, would you consider making it public so that it could be used for use cases like my own?

// Get handler on the facetapi adapter, processor, and facet definitions.
$adapter = facetapi_adapter_load('search_api@optics_node_index');
$processor = new FacetapiUrlProcessorPrettyPaths($adapter);
$facets = $adapter->getEnabledFacets();

$nid = isset($row->_entity_properties['nid'])? $row->_entity_properties['nid'] : '';
$title = isset($row->_entity_properties['title'])? $row->_entity_properties['title'] : '';

$params = $processor->fetchParams();

$segments = array();

// Add in a facet for function (optical / suns)
if (isset($view->filter['field_product_field_optics_function']->value)) {
  if (isset($facets['field_product:field_optics_function'])) {
    $facet_path = $processor->getFacetPath($facets['field_product:field_optics_function'], array(), NULL);
    $alias = $processor->getFacetPrettyPathsAlias($facets['field_product:field_optics_function']);
    $segments[] = array(
      'alias' => $alias,
      'value' => $view->filter['field_product_field_optics_function']->value,
      'facet' => $facets['field_product:field_optics_function'],
    );
  }
}

// Add in a facet for gender
if (isset($view->filter['field_product_field_optics_audience']->value)) {
  if (isset($facets['field_product:field_optics_audience'])) {
    $facet_path = $processor->getFacetPath($facets['field_product:field_optics_audience'], array(), NULL);
    $alias = $processor->getFacetPrettyPathsAlias($facets['field_product:field_optics_audience']);
    $segments[] = array(
      'alias' => $alias,
      'value' => $view->filter['field_product_field_optics_audience']->value,
      'facet' => $facets['field_product:field_optics_audience'],
    );
  }
}

$path = $processor->constructPath('node/' . $nid, $segments);

// Add additional facets from the views arguments.
// convert views args into facetapi_pretty_paths style url.
$facetapi_pretty_path = implode('/', $view->args);
$path .= '/' . $facetapi_pretty_path;

// Add the base path of the original search as a paramater that we can use
// later to add a 'back to search' link.
$query = drupal_get_query_parameters(NULL, array('q', 'f'));
$query['search_path'] = $params['q'];

$output = l($output, $path, array('query' => $query, 'html' => TRUE));
mrfelton’s picture

Status: Active » Needs review
StatusFileSize
new994 bytes

If so, here is a patch to that effect.

dasjo’s picture

Status: Needs review » Fixed

in 9d8a50d i've just commited #8 - "make constructPath() a public method", thanks!

maybe others can learn from your approach to "Applying pretty facet paths on node view pages".
feel free to reopen, if you want to discuss this part of this issue in more detail.

Status: Fixed » Closed (fixed)

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