You are here

recommender.module in Recommender API 6.3

Providing generic recommender system algorithms.

File

recommender.module
View source
<?php

/**
 * @file
 * Providing generic recommender system algorithms.
 */
define('TOP_N_LIMIT', 100);

///////////////////////    Helper functions    /////////////////////

/**
 * Get the application id from the application name.
 * @param $app_name
 * @return the recommender application object.
 */
function recommender_app_load($app_name, $idonly = FALSE) {
  if (!isset($app_name) || empty($app_name)) {
    return NULL;

    // should throw an exception.
  }
  if ($idonly) {
    $sql = "SELECT id FROM {recommender_app} WHERE name = '%s'";
  }
  else {
    $sql = "SELECT * FROM {recommender_app} WHERE name = '%s'";
  }
  $result = db_query($sql, $app_name);
  $app = db_fetch_array($result);
  if (!$app) {
    return NULL;
  }
  if (!$idonly) {
    $app['params'] = unserialize($app['params']);
    return $app;
  }
  else {
    return $app['id'];
  }
}

/**
 * Register a recommender application. The most important function you would use.
 * @param  $apps See documentation for the parameters.
 * @return void
 */
function recommender_app_register($apps) {
  foreach ($apps as $name => $app) {
    $params = serialize($app['params']);
    if (recommender_app_load($name, TRUE)) {

      // app exists, then update
      db_query("UPDATE {recommender_app} SET title = '%s', params = '%s' WHERE name = '%s'", $app['title'], $params, $name);
    }
    else {

      // app not exists, just insert
      db_query("INSERT INTO {recommender_app}(name, title, params) VALUE('%s', '%s', '%s')", $name, $app['title'], $params);
    }
  }
}
function recommender_app_update($app_name, $params) {
  $app = recommender_app_load($app_name);
  $new_params = array_merge($app['params'], $params);
  db_query("UPDATE {recommender_app} SET params = '%s' WHERE id = %d", serialize($new_params), $app['id']);
}

/**
 * Remove the application. Usually used in calling module's hook_uninstall()
 * @param $apps the application name to be removed.
 * @return null
 */
function recommender_app_unregister($apps) {
  if (func_num_args() > 1) {
    $apps = func_get_args();

    // if used as recommender_app_unregister('app1', 'app2', ...);
  }
  elseif (!is_array($apps)) {
    $apps = array(
      $apps,
    );

    // if used as recommender_app_unregister('app');
  }

  // finally, used as recommender_app_unregister(array('app1', 'app2', ...);
  foreach ($apps as $app) {
    $app_id = recommender_app_load($app, TRUE);
    db_query('DELETE FROM {recommender_similarity} WHERE app_id = %d', $app_id);
    db_query('DELETE FROM {recommender_prediction} WHERE app_id = %d', $app_id);
    db_query('DELETE FROM {recommender_app} WHERE id = %d', $app_id);
  }
}

/**
 * Return a list of items that are top similar with $id
 * @param $app_name The $app_name for the depending modules
 * @param $id usually the $node_id of the target item.
 * @param $top_n how many similar items to return
 * @param $test_func optional function to test whether an item satisfy some conditions
 * @return an array of the most similar items to $id.
 */
function recommender_top_similarity($app_name, $id, $top_n, $test_func = NULL) {
  return _recommender_generic_top($app_name, $id, $top_n, '{recommender_similarity}');
}

/**
 * Return a list of items that are top prediction for $id
 * @param $app_name The $app_name for the depending modules
 * @param $id usually the $node_id of the target item.
 * @param $top_n how many predictions to return
 * @param $test_func optional function to test whether an item satisfy some conditions
 * @return an array of the most similar items to $id.
 */
function recommender_top_prediction($app_name, $id, $top_n, $test_func = NULL) {
  return _recommender_generic_top($app_name, $id, $top_n, '{recommender_prediction}');
}
function _recommender_generic_top($app_name, $id, $top_n, $table, $test_func = NULL) {
  $app_id = recommender_app_load($app_name, TRUE);
  $list = array();
  $result = db_query_range("SELECT target_eid id, score FROM {$table} WHERE app_id = %d AND source_eid = %d\n    ORDER BY score DESC, updated DESC, target_eid ASC", 0, TOP_N_LIMIT, $app_id, $id);
  while (($item = db_fetch_array($result)) && count($list) < $top_n) {
    if ($test_func === NULL || call_user_func($test_func, $item)) {
      $list[] = $item;
    }
  }
  return $list;
}
function recommender_create_command($app_name) {
  $command = "runRecommender()";
  $app_id = recommender_app_load($app_name, TRUE);
  $execution_id = async_command_create_command('recommender', $command, array(
    'eid' => $app_id,
  ));
  if ($execution_id) {
    db_query("UPDATE {recommender_app} SET execution_id = %d WHERE name = '%s'", $execution_id, $app_name);
  }
  drupal_set_message(t('Your request "@command" in the queue. It will be executed asynchronously. Please refresh the page to see the update.', array(
    '@command' => $command,
  )));
}

////////////////////////////       DRUPAL RELATED FUNCTIONS          //////////////////////////

// Implements hook_perm().
function recommender_perm() {
  return array(
    "administer recommender",
  );
}

// Implements hook_menu().
function recommender_menu() {
  $items = array();
  $items['admin/settings/recommender'] = array(
    'title' => 'Recommender',
    'description' => 'Configuration and trigger recommender modules',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'recommender_settings_form',
    ),
    'access arguments' => array(
      'administer recommender',
    ),
    'file' => 'recommender.admin.inc',
  );
  return $items;
}
function recommender_cron() {

  // if cron is null, then never run cron for the app.
  // else if recommender never get executed (execution_id=null), then run it.
  // otherwise, run only when last command (c.created) is before current time minus cron.
  $result = db_query('SELECT a.name FROM {recommender_app} a LEFT OUTER JOIN {async_command} c ON a.execution_id = c.id
  		WHERE cron IS NOT NULL AND (a.execution_id IS NULL OR c.created + a.cron < %d)', time());
  while ($row = db_fetch_array($result)) {
    recommender_create_command($row->name);
  }
}

/**
 * Implements hook_views_api().
 */
function recommender_views_api() {
  return array(
    'api' => 2,
    'path' => drupal_get_path('module', 'recommender') . '/views',
  );
}

/**
 * Provide default views template for helper modules.
 * Helper modules can choose either to use "export views" or use this function to generate default views.
 *
 * @param $view_name
 * @param $view_description
 * @param $base_table   either recommender_similarity or recommender_prediction.
 * @param $base_entity_type   usually either 'node' or 'users'
 * @param $base_entity_field  if 'node' then 'title', if 'users' then 'name'
 * @param $argument_type  either 'node' or 'current_user'
 * @param $app_name
 * @return \view
 */
function recommender_default_view_template($view_name, $view_description, $base_table, $base_entity_type, $base_entity_field, $argument_type, $app_name) {
  $view = new view();
  $view->name = $view_name;
  $view->description = $view_description;
  $view->tag = 'recommendation';
  $view->view_php = '';
  $view->base_table = $base_table;
  $view->is_cacheable = TRUE;
  $view->api_version = 2;
  $view->disabled = FALSE;

  /* Edit this to true to make a default view disabled initially */
  $handler = $view
    ->new_display('default', 'Defaults', 'default');
  $handler
    ->override_option('relationships', array(
    'target_eid' => array(
      'label' => 'Recommended entity',
      'required' => 1,
      'base_entity_type' => $base_entity_type,
      'id' => 'target_eid',
      'table' => $base_table,
      'field' => 'target_eid',
      'relationship' => 'none',
    ),
  ));
  $handler
    ->override_option('fields', array(
    'title' => array(
      'label' => '',
      'alter' => array(
        'alter_text' => 0,
        'text' => '',
        'make_link' => 0,
        'path' => '',
        'link_class' => '',
        'alt' => '',
        'prefix' => '',
        'suffix' => '',
        'target' => '',
        'help' => '',
        'trim' => 0,
        'max_length' => '',
        'word_boundary' => 1,
        'ellipsis' => 1,
        'html' => 0,
        'strip_tags' => 0,
      ),
      'empty' => '',
      'hide_empty' => 1,
      'empty_zero' => 0,
      'link_to_node' => 1,
      'exclude' => 0,
      'id' => $base_entity_field,
      'table' => $base_entity_type,
      'field' => $base_entity_field,
      'relationship' => 'target_eid',
    ),
  ));
  $handler
    ->override_option('sorts', array(
    'score' => array(
      'order' => 'DESC',
      'id' => 'score',
      'table' => $base_table,
      'field' => 'score',
      'relationship' => 'none',
    ),
  ));
  $handler
    ->override_option('arguments', array(
    'source_eid' => array(
      'default_action' => 'default',
      'style_plugin' => 'default_summary',
      'style_options' => array(),
      'wildcard' => 'all',
      'wildcard_substitution' => 'All',
      'title' => '',
      'breadcrumb' => '',
      'default_argument_type' => $argument_type,
      'default_argument' => '',
      'validate_type' => 'none',
      'validate_fail' => 'not found',
      'break_phrase' => 0,
      'not' => 0,
      'id' => 'source_eid',
      'table' => $base_table,
      'field' => 'source_eid',
      'validate_user_argument_type' => 'uid',
      'validate_user_roles' => array(
        '2' => 0,
      ),
      'relationship' => 'none',
      'default_options_div_prefix' => '',
      'default_argument_fixed' => '',
      'default_argument_user' => 0,
      'default_argument_php' => '',
      'validate_argument_node_type' => array(
        'example_node_type_1' => 0,
        'page' => 0,
        'story' => 0,
      ),
      'validate_argument_node_access' => 0,
      'validate_argument_nid_type' => 'nid',
      'validate_argument_vocabulary' => array(),
      'validate_argument_type' => 'tid',
      'validate_argument_transform' => 0,
      'validate_user_restrict_roles' => 0,
      'validate_argument_php' => '',
    ),
  ));
  $handler
    ->override_option('filters', array(
    'name' => array(
      'operator' => 'in',
      'value' => array(
        $app_name => $app_name,
      ),
      'group' => '0',
      'exposed' => FALSE,
      'expose' => array(
        'operator' => FALSE,
        'label' => '',
      ),
      'id' => 'name',
      'table' => 'recommender_app',
      'field' => 'name',
      'relationship' => 'none',
    ),
    'score' => array(
      'operator' => '>',
      'value' => array(
        'value' => '0',
        'min' => '',
        'max' => '',
      ),
      'group' => '0',
      'exposed' => FALSE,
      'expose' => array(
        'operator' => FALSE,
        'label' => '',
      ),
      'id' => 'score',
      'table' => $base_table,
      'field' => 'score',
      'relationship' => 'none',
    ),
  ));
  $handler
    ->override_option('access', array(
    'type' => 'none',
  ));
  $handler
    ->override_option('cache', array(
    'type' => 'none',
  ));
  $handler
    ->override_option('items_per_page', 5);
  $handler
    ->override_option('distinct', 1);
  $handler
    ->override_option('style_plugin', 'list');
  $handler
    ->override_option('style_options', array(
    'grouping' => '',
    'type' => 'ul',
  ));
  return $view;
}

Functions

Namesort descending Description
recommender_app_load Get the application id from the application name.
recommender_app_register Register a recommender application. The most important function you would use.
recommender_app_unregister Remove the application. Usually used in calling module's hook_uninstall()
recommender_app_update
recommender_create_command
recommender_cron
recommender_default_view_template Provide default views template for helper modules. Helper modules can choose either to use "export views" or use this function to generate default views.
recommender_menu
recommender_perm
recommender_top_prediction Return a list of items that are top prediction for $id
recommender_top_similarity Return a list of items that are top similar with $id
recommender_views_api Implements hook_views_api().
_recommender_generic_top

Constants

Namesort descending Description
TOP_N_LIMIT @file Providing generic recommender system algorithms.