1

I am really wondered to know how I can move my designed view's Contextual Filter default value which is being provided by my written code as PHP Code, to a module code or a hook.

Is there any possibilities?

Moreover, I am not really interested in exporting view and putting it inside some hooks and ... (as it's again using eval for that PHP Code). I really like to move the Contextual Filter default value which is being provided by my written code as PHP Code, to a module code or a hook.

Even if you can provide me a way to access&manipulate the designed view inside the Drupal, by a module hook/code, it can be really helpful for me.

  • Yes, you'll need to write a custom views filter handler. If you install the advanced help module and look under views, you should find code samples – Clive Oct 8 '14 at 9:11
  • Thank you, there was some notes about making a view and ... but I will try to figure out how the PHP filter module works beside the Views module, and write my own code for the View. – Ehsan Oct 8 '14 at 9:26
  • Do you know any ways to manipulate designed View inside the Drupal by a module hook/code? (I'll add it to my post either) – Ehsan Oct 8 '14 at 9:27
  • Yes Views has loads of hooks you can use. Exactly which one you'd need and the exact code you need to write will obviously depend on your needs – Clive Oct 8 '14 at 9:30
2

This tutorial shows goes through exactly what you're wanting to do http://www.undpaul.de/en/blog/2013/04/04/contextual-content-flag-module-and-custom-views-default-argument-handler

You're definitely going to want to look at the module code in its entirety on his github linked in the article because in the blog post he left out some crucial code (like how to define the views_argument_default_flag handler as class that extends from views_plugin_argument_default.

In my own experience, I needed a custom argument validator instead of a default argument handler, so I followed this tutorial http://www.joetsuihk.com/en/en/custom_views_argument_validator_views_plugin_argument_validate and came up with the following working result.

The need for this custom argument validator arose from needing nested or hierarchical taxonomy term names in the URL instead of the taxonomy term IDs, like /parent-category/child-category/grandchild-category. I tried to use the contextual filter validation method of converting the term name in the URL into its corresponding term id and replace spaces with dashes, but my category names have special characters like /, &, +, and -, which meant decoding the URL didn't always match the original term name.

So, the following custom views contextual filter (argument) validator correctly parses the term name out of the URL and figures out the corresponding term id by querying the url_alias table. After querying a particular path once, the result is cached for better performance. To get these hierarchical paths stored in the url_alias table, I set up a pathauto pattern for my taxonomy vocabulary, like store/[term:parents:join-path]/[term:name]

The info file:

name = Example Module
package = "Example"
description = Example Module custom views argument validator
core = 7.x

files[] = plugins/example_module_plugin_argument_validate_url.inc

The module:

/**
 * @file example_module/example_module.module
 * Implement hook_views_api - load up the custom views include files
 */
function example_module_views_api() {
  return array(
    'api' => 3.0,
    'path' => drupal_get_path('module', 'example_module'),
  );
}

The views include file:

/**
 * @file example_module/example_module.views.inc
 * Defines a custom contextual filter validator
 */
function example_module_views_plugins() {
  return array(
    'argument validator' => array(
      'taxonomy_url_alias' => array(
        'title' => t('Taxonomy URL Alias'),
        'handler' => 'example_module_plugin_argument_validate_url',
        'path' => drupal_get_path('module', 'example_module') . '/plugins',
      ),
    ),
  );
}

The contextual filter handler:

/**
 * @file example_module/plugins/example_module_plugin_argument_validate_url.inc
 * Contains the taxonomy url alias contextual filter validation plugin.
 */

/**
 * Validate whether an argument (contextual filter) is a valid
 * @ingroup views_argument_validate_plugins
 */
class example_module_plugin_argument_validate_url extends views_plugin_argument_validate {

  private $intAddUnixTime = 604800;
  private $error = FALSE;

  function validate_argument($argument) {
    $view = &$this->view;
    $handler = &$this->argument;

    if (!empty($view->args)) {
      //reconstruct the url from the views argument array
      $strPath = implode("/", $view->args);

      //get the taxonomy term id based on the url, not the term name
      $objAlias = $this->getTermId($strPath);

      //split the url_alias's source column up into an array.
      //the source column contains the term id at the end of a path like 'taxonomy/term/123'.
      $arrTermData = explode("/", $objAlias->source);
      $tid = end($arrTermData);
      $term = taxonomy_term_load($tid);

      //manually assign the term id to be the view's argument
      $handler->argument = $term->tid;
      return true;
    }
    else {
      return false;
    }
  }

  /**
   * Get the taxonomy term id from either the url_alias table or from persistent cache
   * @param string $strPath like 'parent-category/child-category/grandchild-category'
   * @return object containing the result of the url_alias table or persistent cache lookup
   */
  private function getTermId($strPath) {
    $objReturn = NULL;
    //attempt to get the taxonomy term id from cached url_alias table result object
    $objReturn = $this->getCache($strPath);

    //if cache is not set, do a select query
    if ($objReturn == NULL) {
      try {
        if(!$this->error) {
          $objReturn = $this->_dbSelect($strPath);
          //cache the response
          $this->setCache($strPath, $objReturn);
        }
        else {
          //log some error because $this->error was true
        }
      }
      catch (Exception $ex) {
        $this->error = TRUE;
        //log an exception
      }
    }

    return $objReturn;
  }

  /**
   * Run a query to look up the taxonomy term id based on the url alias path
   * @param string $strPath url alias like 'parent-category/child-category/grandchild-category'
   * @return object results of the query
   */
  private function _dbSelect($strPath) {
    $result = NULL;
    try {
      //The alias stored in the url_alias table is going to be prepended with 'store/' because of my pathauto taxonomy pattern
      $result = db_select("url_alias", "ua")
        ->fields('ua', array('pid','source','alias'))
        ->condition('alias', 'store/'.$strPath, '=')
        ->condition('source', 'taxonomy/term%', 'LIKE')
        ->range(0,1)
        ->execute()
        ->fetchObject();
    }
    catch(Exception $ex) {
      //log an exception
    }

    //$result is an object like:
    //$result->pid //'12345'
    //$result->source //'taxonomy/term/123'
    //$result->alias //'store/parent-category/child-category/grandchild-category'
    //$result->uid //1
    return $result;
  }

   /**
   * Get an object from cache
   * @param  string $strPath used as part of the cache id
   * 'cache_taxonomy_url_alias' is a custom cache bin
   * @return object data from the persistent cache
   */
  private function getCache($strPath) {
    $objCache = cache_get('example_module_plugin_argument_validate_url' . '::' . 'store/'.$strPath, 'cache_taxonomy_url_alias');
    if (isset($objCache->data)) {
      return $objCache->data;
    }
    else {
      return NULL;
    }
  }

  /**
   * Store an object in cache
   * @param  string $strPath used as part of the cache id
   * @param  object $objData contains the url alias table results
   * @return void
   */
  private function setCache($strPath, $objData) {
    cache_set('example_module_plugin_argument_validate_url' . '::' . 'store/'.$strPath, $objData, 'cache_taxonomy_url_alias', time() + $this->intAddUnixTime);
  }
}

After that I selected my custom contextual filter validator:

using custom views argument validator

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.