You are here

sbp_paths.module in Search by Page 7

Same filename and directory in other branches
  1. 6 sbp_paths.module

Module file for Search by Page Paths, a sub-module for Search by Page.

Allows you to add Drupal pages, such as Views pages, to Search by Page.

File

sbp_paths.module
View source
<?php

/**
 * @file
 * Module file for Search by Page Paths, a sub-module for Search by Page.
 *
 * Allows you to add Drupal pages, such as Views pages, to Search by Page.
 * @ingroup search_by_page
 */

/**
 * Implements Search by Page hook_sbp_paths().
 *
 * Reads path information stored in the database, and returns it.
 */
function sbp_paths_sbp_paths($environment) {
  $min_time = search_by_page_setting_get('sbp_paths_min_time', $environment, 1);
  $max_time = search_by_page_setting_get('sbp_paths_max_time', $environment, 0);
  $res = db_query('SELECT * FROM {sbpp_path} p WHERE p.environment=:env', array(
    ':env' => $environment,
  ))
    ->fetchAll();
  $ret = array();
  foreach ($res as $item) {

    // This comes from checkboxes, so it looks like 'en' => 'en', 'es' => 0,
    // etc.
    $languages = @unserialize($item->languages);
    $langs = array();
    if (is_array($languages)) {
      foreach ($languages as $lang => $val) {
        if ($val) {
          $langs[] = $lang;
        }
      }
    }
    $ret[$item->page_path] = array(
      'id' => $item->pid,
      'role' => $item->role,
      'languages' => $langs,
      'min_time' => $min_time,
      'max_time' => $max_time,
    );
  }
  return $ret;
}

/**
 * Implements Search by Page hook_sbp_query_modify().
 *
 * Adds an access permission check to the search query.
 */
function sbp_paths_sbp_query_modify($environment, $query) {

  // Unfortunately, we don't have a wholesale way to check access permissions.
  // So we have to go through all the paths in our table, and check whether the
  // user has permission to see each one, by querying the menu system.
  // Hopefully, there aren't too many! We store them in a temporary table.
  // Create temporary table
  $table = db_query_temporary('SELECT p.pid, 1 as perm FROM {sbpp_path} p WHERE p.environment=:env', array(
    ':env' => $environment,
  ));

  // Check permissions on each path, store in temporary table
  $res = db_query('SELECT p.pid, p.page_path FROM {sbpp_path} p WHERE p.environment=:env', array(
    ':env' => $environment,
  ))
    ->fetchAll();
  foreach ($res as $item) {
    $parts = search_by_page_path_parts($item->page_path);
    $mitem = menu_get_item($parts[0]);
    if (!$mitem['access']) {
      db_delete($table)
        ->condition('pid', $item->pid)
        ->execute();
    }
  }

  // Join to our temporary table
  $query
    ->leftJoin($table, 'sbpp_p', 'sbpp_p.pid = sp.modid');
  $cond = db_and();
  $cond
    ->condition('sbpp_p.perm', 1);
  return $cond;
}

/**
 * Implements Search by Page hook_sbp_details().
 *
 * Reads details information stored in the database, extracts snippet
 * if necessary, and returns it.
 */
function sbp_paths_sbp_details($id, $environment, $keys = NULL) {

  // Get info from DB
  $item = db_query('SELECT p.pid, p.title, p.page_path, p.page_type, p.snippet FROM {sbpp_path} p WHERE p.pid = :pid', array(
    ':pid' => $id,
  ))
    ->fetchObject();
  if (!$item->pid) {
    return NULL;
  }

  // Translate if necessary
  if (module_exists('i18n_string')) {
    $code = 'sbp_paths:path:' . $item->pid . ':';
    $item->title = i18n_string_translate($code . 'title', $item->title);
    $item->page_type = i18n_string_translate($code . 'type', $item->page_type);
    $snip = drupal_strtolower($item->snippet);
    if ($snip != 'yes' && $snip != 'no' && $keys) {
      $item->snippet = i18n_string_translate($code . 'snippet', $item->snippet);
    }
  }

  // Basic page info
  $ret = array(
    'type' => $item->page_type,
    'title' => search_by_page_strip_tags($item->title, $environment),
  );

  // Snippet -- DB either stores "yes", "no", or a custom snippet to use
  $code = drupal_strtolower($item->snippet);
  if ($code == 'yes' && $keys) {
    $content = search_by_page_stored_page_content('sbp_paths', $id, $environment);
    if ($content) {
      $ret['snippet'] = search_by_page_excerpt($keys, $content);
    }
  }
  elseif ($code != 'no' && $keys) {

    // User-supplied custom snippet
    $ret['snippet'] = search_by_page_strip_tags($item->snippet, $environment);
  }
  return $ret;
}

/**
 * Implements Search by Page hook_sbp_settings().
 *
 * Adds a few settings to the Search by Page settings page.
 */
function sbp_paths_sbp_settings($environment) {
  $form = array();
  $form['sbp_paths'] = array(
    '#type' => 'fieldset',
    '#collapsible' => TRUE,
    '#weight' => -80,
    '#title' => t('Paths'),
  );
  $times = array(
    '1' => t('1 second'),
    '3600' => t('1 hour'),
    '86400' => t('1 day'),
    '604800' => t('1 week'),
    '31449600' => t('1 year'),
    '0' => t('Never'),
  );
  $form['sbp_paths']['sbp_paths_min_time'] = array(
    '#type' => 'select',
    '#title' => t('Minimum reindexing time'),
    '#options' => $times,
    '#default_value' => search_by_page_setting_get('sbp_paths_min_time', $environment, 1),
    '#weight' => 5,
    '#description' => t("After indexing any new pages added to the environment, Search by Page also cycles through previously-indexed pages, in case the rendered view of the page has changed. On some sites, you may want to limit the amount of reindexing, by setting a minimum time -- the page will not be reindexed until this time has passed."),
  );
  $form['sbp_paths']['sbp_paths_max_time'] = array(
    '#type' => 'select',
    '#title' => t('Maximum reindexing time'),
    '#options' => $times,
    '#default_value' => search_by_page_setting_get('sbp_paths_max_time', $environment, 0),
    '#weight' => 6,
    '#description' => t("Conversely to the minimum reindexing time (see above), Search by Page can be set to prioritize reindexing each page (by marking it as needing immediate reindexing) after this amount of time has passed. This has higher priority than the cycle-through reindexing of the setting above.") . ' ' . t('But be careful with this setting! If you set it too small, it can interfere with new content being indexed, because the reindexed content will have equal priority to content that has never been indexed. So make sure your settings allow for enough time for new content to be indexed before forcing reindexing.'),
  );
  return $form;
}

/**
 * Implements hook_menu().
 *
 * Defines a tab on Search by Page environment edit that lists the paths
 * to be indexed, with ability to add, edit, and delete them.
 */
function sbp_paths_menu() {
  $items = array();
  $items['admin/config/search/search_by_page/edit/%/paths'] = array(
    'title' => 'Paths',
    'type' => MENU_LOCAL_TASK,
    'weight' => 0,
    'page callback' => '_sbp_paths_list_page',
    'page arguments' => array(
      5,
    ),
    'access arguments' => array(
      'administer search by page',
    ),
  );
  $items['admin/config/search/search_by_page/edit/%/paths/edit'] = array(
    'title' => 'Edit path',
    'type' => MENU_CALLBACK,
    'page callback' => '_sbp_paths_edit',
    'page arguments' => array(
      5,
    ),
    'access arguments' => array(
      'administer search by page',
    ),
  );
  $items['admin/config/search/search_by_page/edit/%/paths/add'] = array(
    'title' => 'Add path',
    'type' => MENU_CALLBACK,
    'page callback' => '_sbp_paths_edit',
    'page arguments' => array(
      5,
    ),
    'access arguments' => array(
      'administer search by page',
    ),
  );
  $items['admin/config/search/search_by_page/edit/%/paths/delete'] = array(
    'title' => 'Delete path',
    'type' => MENU_CALLBACK,
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'sbp_paths_delete_confirm',
      5,
    ),
    'access arguments' => array(
      'administer search by page',
    ),
  );
  return $items;
}

/**
 * Implements hook_i18n_string_info().
 */
function sbp_paths_i18n_string_info() {
  $groups = array();
  $groups['sbp_paths'] = array(
    'title' => t('Search by Page Paths'),
    'description' => t('Path setting text for Search by Page Paths'),
    'format' => FALSE,
    'list' => FALSE,
    'refresh callback' => '_sbp_paths_refresh_all_translations',
  );
  return $groups;
}

/**
 * Refreshes all path info translations.
 */
function _sbp_paths_refresh_all_translations() {
  if (module_exists('i18n_string')) {
    $res = db_query('SELECT * FROM {sbpp_path} p')
      ->fetchAll();
    foreach ($res as $vals) {
      $arr = array(
        'pid' => $vals->pid,
        'title' => $vals->title,
        'type' => $vals->page_type,
        'snippet' => $vals->snippet,
      );
      _sbp_paths_update_translation($arr);
    }
  }
}

/**
 * Page callback for path listings page.
 *
 * Builds a page that lists existing paths to index, with links to edit,
 * delete, and add new.
 */
function _sbp_paths_list_page($environment) {
  $output = '';
  $environment = intval($environment);

  // Overview
  $output .= '<p>' . t('This page allows you to define pages on your site to be indexed by the Search by Page module in this environment.') . '</p>' . "\n";

  // Link to add a new path
  $basepath = 'admin/config/search/search_by_page/edit/' . $environment . '/paths/';
  $output .= '<p>' . l(t('Add new path'), $basepath . 'add') . '</p>' . "\n";

  // List existing paths in a table, with edit/delete links
  // and use a pager
  $query = db_select('sbpp_path', 'p')
    ->extend('PagerDefault');
  $query
    ->addField('p', 'pid');
  $query
    ->addField('p', 'page_path');
  $query
    ->addField('p', 'title');
  $query
    ->condition('environment', $environment)
    ->limit(50)
    ->orderBy('page_path');
  $result = $query
    ->execute()
    ->fetchAll();
  $headers = array(
    t('Path'),
    t('Title'),
    array(
      'data' => t('Operations'),
      'colspan' => 2,
    ),
  );
  $rows = array();
  foreach ($result as $data) {
    $rows[] = array(
      check_plain($data->page_path),
      check_plain($data->title),
      l(t('edit'), $basepath . 'edit/' . $data->pid),
      l(t('delete'), $basepath . 'delete/' . $data->pid),
    );
  }
  $output .= theme('table', array(
    'header' => $headers,
    'rows' => $rows,
  ));
  $output .= theme('pager', array(
    'tags' => NULL,
  ));
  return $output;
}

/**
 * Edits or adds new path.
 */
function _sbp_paths_edit($environment, $pid = 0) {
  if ($pid) {
    $values = db_query('SELECT * FROM {sbpp_path} p WHERE p.pid = :pid', array(
      ':pid' => $pid,
    ))
      ->fetchAssoc();
    $values['languages'] = @unserialize($values['languages']);
    if (!$values['languages']) {
      $values['languages'] = array();
    }
    return drupal_get_form('sbp_paths_edit_form', $values);
  }
  else {
    return drupal_get_form('sbp_paths_edit_form', array(
      'environment' => $environment,
    ));
  }
}

/**
 * Returns a form for editing a path item.
 *
 * @ingroup forms
 * @see sbp_paths_edit_form_submit()
 */
function sbp_paths_edit_form($form, &$form_state, $edit = array()) {
  global $language;
  $edit = array_merge(array(
    'pid' => 0,
    'page_path' => '',
    'title' => '',
    'page_type' => 'Page',
    'snippet' => 'yes',
    'environment' => 0,
    'role' => DRUPAL_ANONYMOUS_RID,
    'languages' => array(),
  ), $edit);
  $edit['environment'] = intval($edit['environment']);
  $form['path'] = array(
    '#type' => 'textfield',
    '#title' => t('Page to index'),
    '#default_value' => $edit['page_path'],
    '#size' => 45,
    '#description' => t('Specify a page on your site that you want to index. Do not include the language prefix, if any. To index the home page, enter its native path, as it is entered on the Site Information settings page.'),
    '#field_prefix' => search_by_page_path_field_prefix(),
    '#required' => TRUE,
  );
  $form['title'] = array(
    '#type' => 'textfield',
    '#title' => t('Title of page'),
    '#default_value' => $edit['title'],
    '#size' => 45,
    '#description' => t('Title to display in search results for this page'),
    '#required' => TRUE,
  );
  $form['type'] = array(
    '#type' => 'textfield',
    '#title' => t('Type of page'),
    '#default_value' => $edit['page_type'],
    '#size' => 45,
    '#description' => t('Type to display in search results for this page, if the theme displays item types'),
    '#required' => TRUE,
  );
  $form['snippet'] = array(
    '#type' => 'textarea',
    '#title' => t('Snippet'),
    '#default_value' => $edit['snippet'],
    '#cols' => 45,
    '#rows' => 5,
    '#description' => t('Enter "yes" (without the quotes, in English) to show a "snippet" of this page in search results, extracted from the page (it should show a portion of the page that contains the search results). Enter "no" (without the quotes, in English) to omit the snippet entirely. Or, enter any other text to use that custom text as the snippet for search results display.'),
    '#required' => TRUE,
  );
  if (module_exists('locale')) {
    $form['texthelp'] = array(
      '#type' => 'markup',
      '#markup' => '<p>' . t("Enter the title, type, and snippet above in your site's default language. If you have a multi-lingual site with the Internationalization project's String Translation module installed and enabled, you can use Drupal's translation interface to translate them.") . '</p>',
    );
    $form['languages'] = array(
      '#type' => 'checkboxes',
      '#title' => t('Languages'),
      '#description' => t('Indicate which languages this page can be viewed in. It will be indexed in each language for searching.'),
      '#options' => locale_language_list('name'),
      '#default_value' => $edit['languages'],
    );
  }
  else {
    $form['languages'] = array(
      '#type' => 'value',
      '#value' => array(
        $language->language => TRUE,
      ),
    );
  }
  $form['role'] = array(
    '#type' => 'radios',
    '#title' => t('Role for indexing'),
    '#options' => user_roles(),
    '#default_value' => $edit['role'],
    '#weight' => 4,
    '#description' => t("When Search by Page indexes this page for searching, the page will be viewed from the perspective and permissions of a user with this role."),
  );
  if ($edit['pid']) {
    $form['pid'] = array(
      '#type' => 'value',
      '#value' => $edit['pid'],
    );
    $form['submit'] = array(
      '#type' => 'submit',
      '#value' => t('Update indexed page'),
    );
  }
  else {
    $form['submit'] = array(
      '#type' => 'submit',
      '#value' => t('Create new indexed page'),
    );
  }
  $form['submit']['#weight'] = 5;
  $form['environment'] = array(
    '#type' => 'value',
    '#value' => $edit['environment'],
  );
  $form['cancel'] = array(
    '#type' => 'markup',
    '#markup' => "<p>" . l(t('Cancel'), 'admin/config/search/search_by_page/edit/' . $edit['environment'] . '/paths') . "</p>",
    '#weight' => 6,
  );
  return $form;
}

/**
 * Submit callback for sbp_paths_edit_form().
 *
 * Adds/edits the path to be indexed, and updates database of paths.
 */
function sbp_paths_edit_form_submit($form, &$form_state) {
  $vals = $form_state['values'];
  $langs = serialize($vals['languages']);
  $envid = intval($vals['environment']);

  // Save the new information
  if (isset($vals['pid']) && $vals['pid']) {
    db_update('sbpp_path')
      ->fields(array(
      'environment' => $envid,
      'page_path' => $vals['path'],
      'title' => $vals['title'],
      'page_type' => $vals['type'],
      'snippet' => $vals['snippet'],
      'role' => $vals['role'],
      'languages' => $langs,
    ))
      ->condition('pid', $vals['pid'])
      ->execute();

    // Force this to be reindexed
    search_by_page_force_reindex('sbp_paths', $vals['pid'], $envid);
  }
  else {
    $vals['pid'] = db_insert('sbpp_path')
      ->fields(array(
      'environment' => $envid,
      'page_path' => $vals['path'],
      'title' => $vals['title'],
      'page_type' => $vals['type'],
      'snippet' => $vals['snippet'],
      'role' => $vals['role'],
      'languages' => $langs,
    ))
      ->execute();
  }

  // Update the translation strings
  _sbp_paths_update_translation($vals);

  // Go back to the paths list
  drupal_set_message(t('The page to index has been saved'));
  $form_state['redirect'] = 'admin/config/search/search_by_page/edit/' . $envid . '/paths';
}

/**
 * Returns a form confirming deletion a path to be indexed.
 *
 * @ingroup forms
 * @see sbp_paths_delete_confirm_submit()
 */
function sbp_paths_delete_confirm($form, &$form_state, $environment, $pid) {
  $item = db_query('SELECT p.page_path FROM {sbpp_path} p WHERE p.pid = :pid', array(
    ':pid' => $pid,
  ))
    ->fetchObject();
  $environment = intval($environment);
  $form['pid'] = array(
    '#type' => 'value',
    '#value' => $pid,
  );
  $form['environment'] = array(
    '#type' => 'value',
    '#value' => $environment,
  );
  return confirm_form($form, t('Are you sure you want to stop indexing %path in this environment?', array(
    '%path' => $item->page_path,
  )), 'admin/config/search/search_by_page/edit/' . $environment . '/paths');
}

/**
 * Submit callback for sbp_paths_delete_confirm().
 *
 * Actually deletes the path.
 */
function sbp_paths_delete_confirm_submit($form, &$form_state) {
  if (!$form_state['values']['confirm']) {
    return;
  }
  $pid = $form_state['values']['pid'];
  if (!$pid) {
    return;
  }

  // Remove it from our database, and also from current search index
  db_delete('sbpp_path')
    ->condition('pid', $pid)
    ->execute();
  $environment = intval($form_state['values']['environment']);
  search_by_page_force_remove('sbp_paths', $pid, $environment);

  // Go back to paths page
  $form_state['redirect'] = 'admin/config/search/search_by_page/edit/' . $environment . '/paths';
}

/**
 * Implements hook_sbp_delete_environment().
 *
 * Removes the environment from paths database table.
 */
function sbp_paths_sbp_delete_environment($environment) {
  $envid = intval($environment);
  db_delete('sbpp_path')
    ->condition('environment', $envid)
    ->execute();
}

/**
 * Updates the strings to be translated for one path record.
 *
 * @param $vals
 *    Associative array of information from sbpp_path table.
 */
function _sbp_paths_update_translation($vals) {
  if (module_exists('i18n_string') && $vals['pid']) {
    $code = 'sbp_paths:path:' . $vals['pid'] . ':';
    i18n_string_update($code . 'title', $vals['title']);
    i18n_string_update($code . 'type', $vals['type']);
    $snip = drupal_strtolower($vals['snippet']);
    if ($snip != 'yes' && $snip != 'no') {
      i18n_string_update($code . 'snippet', $vals['snippet']);
    }
  }
}

Related topics

Functions

Namesort descending Description
sbp_paths_delete_confirm Returns a form confirming deletion a path to be indexed.
sbp_paths_delete_confirm_submit Submit callback for sbp_paths_delete_confirm().
sbp_paths_edit_form Returns a form for editing a path item.
sbp_paths_edit_form_submit Submit callback for sbp_paths_edit_form().
sbp_paths_i18n_string_info Implements hook_i18n_string_info().
sbp_paths_menu Implements hook_menu().
sbp_paths_sbp_delete_environment Implements hook_sbp_delete_environment().
sbp_paths_sbp_details Implements Search by Page hook_sbp_details().
sbp_paths_sbp_paths Implements Search by Page hook_sbp_paths().
sbp_paths_sbp_query_modify Implements Search by Page hook_sbp_query_modify().
sbp_paths_sbp_settings Implements Search by Page hook_sbp_settings().
_sbp_paths_edit Edits or adds new path.
_sbp_paths_list_page Page callback for path listings page.
_sbp_paths_refresh_all_translations Refreshes all path info translations.
_sbp_paths_update_translation Updates the strings to be translated for one path record.