You are here

search_files.module in Search Files 5

Same filename and directory in other branches
  1. 6.2 search_files.module
  2. 7.2 search_files.module

Used to index all files in directory(s) on the server

File

search_files.module
View source
<?php

/**
 * @file
 * Used to index all files in directory(s) on the server
 */

/**
 * Implementation of hook_menu()
 *
 * @return $items = array of menu items
 */
function search_files_menu() {
  $items = array();
  $items[] = array(
    'path' => 'admin/settings/search_files',
    'title' => t('Search Files'),
    'description' => t('Manage files search'),
    //'page callback' => 'drupal_get_form',
    'callback' => 'drupal_get_form',
    //'page arguments' => array('search_files_settings'),
    'callback arguments' => array(
      'search_files_settings',
    ),
    //'access arguments' => array('administer search_files configuration'),
    'access' => user_access('administer search_files configuration'),
    'type' => MENU_NORMAL_ITEM,
  );
  $items[] = array(
    'path' => 'admin/settings/search_files/settings',
    'title' => t('Settings'),
    'description' => t('Change settings for Search Files Module'),
    //'page callback' => 'drupal_get_form',
    'callback' => 'drupal_get_form',
    //'page arguments' => array('search_files_settings'),
    'callback arguments' => array(
      'search_files_settings',
    ),
    //'access arguments' => array('administer search_files configuration'),
    'access' => user_access('administer search_files configuration'),
    'type' => MENU_DEFAULT_LOCAL_TASK,
  );
  $items[] = array(
    'path' => 'admin/settings/search_files/helpers',
    'title' => t('Helpers'),
    'description' => t('List Helper Apps for Search Files'),
    //'page callback' => 'search_files_helper_list',
    'callback' => 'search_files_helper_list',
    //'access arguments' => array('administer search_files configuration'),
    'access' => user_access('administer search_files configuration'),
    'type' => MENU_LOCAL_TASK,
  );
  $items[] = array(
    'path' => 'admin/settings/search_files/helpers/list',
    'title' => t('List'),
    'description' => t('List Helper Apps for Search Files'),
    //'page callback' => 'search_files_helper_list',
    'callback' => 'search_files_helper_list',
    //'access arguments' => array('administer search_files configuration'),
    'access' => user_access('administer search_files configuration'),
    'type' => MENU_DEFAULT_LOCAL_TASK,
  );
  $items[] = array(
    'path' => 'admin/settings/search_files/helpers/add',
    'title' => t('Add'),
    'description' => t('Add Helper Apps for Search Files'),
    //'page callback' => 'drupal_get_form',
    'callback' => 'drupal_get_form',
    //'page arguments' => array('search_files_helper_add'),
    'callback arguments' => array(
      'search_files_helper_add',
    ),
    //'access arguments' => array('administer search_files configuration'),
    'access' => user_access('administer search_files configuration'),
    'type' => MENU_LOCAL_TASK,
  );
  $items[] = array(
    'path' => 'admin/settings/search_files/directories',
    'title' => t('Directories'),
    'description' => t('list directories that will be searched'),
    //'page callback' => 'search_files_directories_list',
    'callback' => 'search_files_directories_list',
    //'access arguments' => array('administer search_files configuration'),
    'access' => user_access('administer search_files configuration'),
    'type' => MENU_LOCAL_TASK,
  );
  $items[] = array(
    'path' => 'admin/settings/search_files/directories/list',
    'title' => t('List'),
    'description' => t('list directories that will be searched'),
    //'page callback' => 'search_files_directories_list',
    'callback' => 'search_files_directories_list',
    //'access arguments' => array('administer search_files configuration'),
    'access' => user_access('administer search_files configuration'),
    'type' => MENU_DEFAULT_LOCAL_TASK,
  );
  $items[] = array(
    'path' => 'admin/settings/search_files/directories/add',
    'title' => t('Add'),
    'description' => t('Add a directory that will be searched'),
    //'page callback' => 'drupal_get_form',
    'callback' => 'drupal_get_form',
    //'page arguments' => array('search_files_directories_add'),
    'callback arguments' => array(
      'search_files_directories_add',
    ),
    //'access arguments' => array('administer search_files configuration'),
    'access' => user_access('administer search_files configuration'),
    'type' => MENU_LOCAL_TASK,
  );
  $items[] = array(
    'path' => 'admin/settings/search_files/directory/delete',
    'title' => t('Delete Directory'),
    'description' => t('Delete Searchable Driectory'),
    //'page callback' => 'search_files_directory_confirm_delete',
    'callback' => 'search_files_directory_confirm_delete',
    //'access arguments' => array('administer search_files configuration'),
    'access' => user_access('administer search_files configuration'),
    'type' => MENU_CALLBACK,
  );
  $items[] = array(
    'path' => 'admin/settings/search_files/directory/edit',
    'title' => t('Edit Directory'),
    'description' => t('Edit directory path'),
    //'page callback' => 'drupal_get_form',
    'callback' => 'drupal_get_form',
    //'page arguments' => array('search_files_directory_edit'),
    'callback arguments' => array(
      'search_files_directory_edit',
    ),
    //'access arguments' => array('administer search_files configuration'),
    'access' => user_access('administer search_files configuration'),
    'type' => MENU_CALLBACK,
  );
  $items[] = array(
    'path' => 'admin/settings/search_files/helpers/edit',
    'title' => t('Edit Helper'),
    'description' => t('Edit a Helper App'),
    //'page callback' => 'drupal_get_form',
    'callback' => 'drupal_get_form',
    //'page arguments' => array('search_files_helper_edit'),
    'callback arguments' => array(
      'search_files_helper_edit',
    ),
    //'access arguments' => array('administer search_files configuration'),
    'access' => user_access('administer search_files configuration'),
    'type' => MENU_CALLBACK,
  );
  $items[] = array(
    'path' => 'admin/settings/search_files/helpers/delete',
    'title' => t('Delete Helper'),
    'description' => t('Delete a Helper App'),
    //'page callback' => 'search_files_helper_confirm_delete',
    'callback' => 'search_files_helper_confirm_delete',
    //'access arguments' => array('administer search_files configuration'),
    'access' => user_access('administer search_files configuration'),
    'type' => MENU_CALLBACK,
  );
  $items[] = array(
    'path' => 'admin/settings/search_files/update_index',
    'title' => t('Up date the index'),
    'description' => t('manually run hook_upate_index'),
    //'page callback' => 'search_files_update_index',
    'callback' => 'search_files_update_index',
    //'access arguments' => array('administer search_files configuration'),
    'access' => array(
      'administer search_files configuration',
    ),
    'type' => MENU_CALLBACK,
  );
  return $items;
}

/**
 * get an array of helper programs
 *
 * @return $helpers = array($helper->extension => $helper->helper_path);
 */
function search_files_get_helpers() {

  // Get all the registered helper applications and put them in static variable to elimiate unnecessary db queries
  // in search_files_nodeapi(). The query log feature of the dev module pointed out that this query was done
  // many times instead of once. Making $helpers a static variable reduced the number of queries by 25%.
  static $helpers = array();
  $result = db_query('SELECT * FROM {search_files_helpers}');
  while ($helper = db_fetch_object($result)) {
    $helpers[$helper->extension] = $helper->helper_path;
  }
  return $helpers;
}

/**
 * check to make sure the directory the user wants to delete is a 
 * valid directory id number, then call the function to generate 
 * the confirmation form 
 *
 * @return $output = html of the form
 */
function search_files_directory_confirm_delete() {
  $directory_id = arg(5);
  if ($directory_id > 0 && is_numeric($directory_id)) {
    return drupal_get_form('search_files_directory_confirm_delete_form', $directory_id);
  }
}

/**
 * get the confirmation form to confirm deletion of a directory 
 * from the search_files_directories table
 *
 * @param (array) $form_state
 * @param (int) $directory_id
 * @return $output = html of the form
 */
function search_files_directory_confirm_delete_form(&$form_state, $directory_id = NULL) {
  if ($directory_id == NULL) {
    $directory_id = arg(5);
  }

  // Drupal 5.x
  $directory_path = db_result(db_query("SELECT directory FROM {search_files_directories} WHERE id = '%s'", $directory_id));
  $form = array();
  $form['search_files_directory_id'] = array(
    '#type' => 'hidden',
    '#value' => $directory_id,
  );
  $form['search_files_directory_path'] = array(
    '#type' => 'hidden',
    '#value' => $directory_path,
  );
  return confirm_form($form, t('Are you sure you want to delete the %directory directory? The text extracted from this directory be removed from the search index.', array(
    '%directory' => $directory_path,
  )), 'admin/settings/search_files/directories/list', t('This action cannot be undone.'), t('Delete'), t('Cancel'));
}

/**
 * deletes the directory from the search_files_directories table after 
 * confirmation from the user, also deletes the files from the 
 * search_files_files table and removes the data from the search_dataset 
 * table
 *
 * @param unknown_type $form_id
 * @param unknown_type $form_values
 */
function search_files_directory_confirm_delete_form_submit($form_id, $form_values) {

  //drupal_set_message('form_values = <pre>'.print_r($form_values, true).'</pre>');
  $sql = "DELETE FROM {search_files_directories} WHERE id='%s'";
  $result = db_query($sql, $form_values['search_files_directory_id']);
  if ($result) {
    drupal_set_message(t('Directory %directory removed from search index', array(
      '%directory' => $form_values['search_files_directory_path'],
    )));
    $sql = "SELECT * FROM {search_files_files} WHERE id='%s'";
    $files_result = db_query($sql, $form_values['search_files_directory_id']);
    while ($file = db_fetch_object($files_result)) {
      $sql = "DELETE FROM {search_dataset} WHERE type='search_files' AND sid='%s'";
      $dataset_result = db_query($sql, $file->id);
      if (dataset_result) {
        $sql = "DELETE FROM {search_files_files} WHERE id='%s'";
        db_query($sql, $file->id);
      }
    }
    drupal_set_message(t('You still need to write the code to remove the files from the removed directory from the "search_files_files" table and the "search_dataset" table'));
    drupal_goto('admin/settings/search_files/directories/list');
  }
}

/**
 * generates the directory edit form, it does this by grabbing the 
 * directory add form and populates the #default_value fields for 
 * the directory in question
 *
 * @return (array) $form
 */
function search_files_directory_edit() {

  //drupal_set_message('arg5 = <pre>'.print_r(arg(5), true).'</pre>');
  $sql = "SELECT * FROM {search_files_directories} WHERE ID = '%s'";
  $result = db_fetch_object(db_query($sql, arg(5)));
  $form = array();
  $form = search_files_directories_add();
  $form['search_files_directory']['#default_value'] = $result->directory;
  $form['search_files_id'] = array(
    '#type' => 'value',
    '#value' => $result->id,
  );
  return $form;
}

/**
 * Updates the directory row in the serach_files_directories table from 
 * data given by the search_files_directory_edit form
 *
 * @param (array) $form_id
 * @param (array) $form_values
 */
function search_files_directory_edit_submit($form_id, $form_values) {

  //drupal_set_message('form_values= <pre>'.print_r($form_values, true).'</pre>');
  $sql = "UPDATE {search_files_directories} SET directory='%s' WHERE id='%s'";
  $result = db_query($sql, $form_values['search_files_directory'], $form_values['search_files_id']);
  if ($result) {
    drupal_set_message(t('Directory %directory has been updated', array(
      '%directory' => $form_values['search_files_directory'],
    )));
    drupal_goto('admin/settings/search_files/directories/list');
  }
}

/**
 * gets a list of directories to inde from the search_files_directories 
 * table and themes the list in a table
 *
 * @return (string) $output = themed table of directories
 *
 * 5.x --> OK - ivazquez
 *
 */
function search_files_directories_list() {
  $result = db_query('SELECT * FROM {search_files_directories}');
  $directories[] = array();
  $destination = drupal_get_destination();
  while ($directory = db_fetch_object($result)) {
    $directories[] = array(
      $directory->directory,
      l(t('Edit'), 'admin/settings/search_files/directory/edit/' . $directory->id),
      l(t('Delete'), 'admin/settings/search_files/directory/delete/' . $directory->id),
      array(
        $destination,
      ),
    );
  }
  $header = array(
    'Directory',
    array(
      'data' => t('Operations'),
      'colspan' => '3',
    ),
  );
  $output .= theme('table', $header, $directories);
  return $output;
}

/**
 * generates the form to add a directory to search_files_directories table
 *
 * @return (array) $form
 *
 * 5.x --> OK - ivazquez
 *
 */
function search_files_directories_add() {
  $form = array();
  $form['instructions'] = array(
    '#type' => 'markup',
    '#value' => t('Make sure the directory is readable by the web server, i.e. apache.'),
  );
  $form['search_files_directory'] = array(
    '#type' => 'textfield',
    '#title' => t('Directory Path'),
    '#size' => 80,
    '#maxlength' => 150,
    '#required' => TRUE,
    '#description' => t('The path of the directory to search. Do not end with a trailing \'/\''),
  );
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => 'Submit',
  );
  return $form;
}

/**
 * adds a row to the search_files directories table with  the 
 * information provided by the search_files_directory_add_form.
 *
 * @param unknown_type $form_id
 * @param unknown_type $form_values
 *
 *
 * 5.x --> OK - ivazquez
 */
function search_files_directories_add_submit($form_id, $form_values) {
  $sql = "INSERT INTO {search_files_directories} (directory) VALUES ('%s')";

  //$result = db_query($sql, $form_values['values']['search_files_directory'], $form_values['values']['search_files_label']); //pepe
  $result = db_query($sql, $form_values['search_files_directory']);
  if ($result) {
    drupal_set_message(t('Directory %directory has been added. I may take up to 1 day to start indexing this directory.', array(
      '%directory' => $form_values['search_files_directory'],
    )));
    drupal_goto('admin/settings/search_files/directories/list');
  }
}

/**
 * check to make sure the $helper_id is valid (a number greater 
 * than zero) then it fetches the deletion confirmation form, 
 * then returns it 
 *
 * @return (array) $form
 */
function search_files_helper_confirm_delete() {
  $helper_id = arg(5);
  if ($helper_id > 0 && is_numeric($helper_id)) {
    return drupal_get_form('search_files_helper_confirm_delete_form', 'nnn', $helper_id);
  }
}

/**
 * generate the deletion confirmation form for helper apps and return the form
 *
 * @param unknown_type $form_state
 * @param (int) $helper_id
 * @return (array) $form
 */
function search_files_helper_confirm_delete_form(&$form_state, $helper_id) {
  $helper_name = db_result(db_query("SELECT name FROM {search_files_helpers} WHERE id = '%s'", $helper_id));
  $form = array();
  $form['search_files_helper_id'] = array(
    '#type' => 'hidden',
    '#value' => $helper_id,
  );
  $form['search_files_helper_name'] = array(
    '#type' => 'hidden',
    '#value' => $helper_name,
  );
  return confirm_form($form, t('Are you sure you want to delete the %name helper? The text extracted by this helper will remain in the search index until the directory is reindexed.', array(
    '%name' => $helper_name,
  )), 'admin/settings/search_files/helpers/list', t('This action cannot be undone.'), t('Delete'), t('Cancel'));
}

/**
 * remove row for the helper app from the search_files_helpers table
 *
 * @param unknown_type $form_id
 * @param (array) $form_values
 */
function search_files_helper_confirm_delete_form_submit($form_id, $form_values) {

  //drupal_set_message('form_values = <pre>'.print_r($form_values, true).'</pre>');
  $sql = "DELETE FROM {search_files_helpers} WHERE id='%s'";
  $result = db_query($sql, $form_values['search_files_helper_id']);
  drupal_goto('admin/settings/search_files/helpers/list');
}

/**
 * display a themes table of the current helper apps set up in the system
 *
 * @return (string) html table
 */
function search_files_helper_list() {
  $sql = "SELECT * FROM {search_files_helpers} ORDER BY extension";
  $result = db_query($sql);
  $helpers[] = array();
  $destination = drupal_get_destination();
  while ($helper = db_fetch_object($result)) {
    $helpers[] = array(
      $helper->name,
      $helper->extension,
      l(t('Edit'), 'admin/settings/search_files/helpers/edit/' . $helper->id),
      l(t('Delete'), 'admin/settings/search_files/helpers/delete/' . $helper->id),
      array(
        $destination,
      ),
    );
  }
  $header = array(
    t('Helper name'),
    t('Extension'),
    array(
      'data' => t('Operations'),
      'colspan' => '3',
    ),
  );
  $output .= theme('table', $header, $helpers);
  return $output;
}

/**
 * Implementation of hook_perm()
 *
 * @return (array) permissions
 */
function search_files_perm() {
  return array(
    'administer search_files configuration',
    'view search_files results',
  );
}

/**
 * generate form to add a helper app to the system
 *
 * @return (array) $form
 */
function search_files_helper_add() {
  $form['instructions'] = array(
    '#type' => 'markup',
    '#value' => $instruction_text,
  );
  $form['search_files_name'] = array(
    '#type' => 'textfield',
    '#title' => t('Helper name'),
    '#size' => 50,
    '#maxlength' => 50,
    '#required' => TRUE,
    '#description' => t('A name for this helper configuration.'),
  );
  $form['search_files_extension'] = array(
    '#type' => 'textfield',
    '#title' => t('Extension'),
    '#size' => 10,
    '#maxlength' => 10,
    '#required' => TRUE,
    '#description' => t('Enter the extension for the files that you want the helper application to process. Do not include the period.'),
  );
  $form['search_files_helper_path'] = array(
    '#type' => 'textfield',
    '#title' => t('Helper path'),
    '#size' => 100,
    '#maxlength' => 100,
    '#default_value' => '/path/to/helper/command %file%',
    '#validate' => array(
      'search_files_helpers_validate_add_edit' => array(),
    ),
    '#required' => TRUE,
    '#description' => t('Enter the path to the helper application installed on your server. "%file%" is a placeholder for the path of the attachment file and is required. Include any command-line parameters as well (for example, pdftotext requires a - after the file to be processed).'),
  );
  $form['submit_done'] = array(
    '#type' => 'submit',
    '#value' => 'Save and Done',
  );
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => 'Save add another',
  );
  return $form;
}

/**
 * validate the existence of the helper app supplied by the 
 * helper_add or helper_edit form
 *
 * @param unknown_type $field
 */
function search_files_helpers_validate_add_edit($field) {
  if (!preg_match('/%file%/', $field['#value'])) {
    form_set_error($field['#title'], t('"%field" must contain the token %file%', array(
      '%field' => $field['#title'],
    )));
  }

  // Check to see if helper app can be found
  $helper_file = preg_replace('/\\s.+$/', '', $field['#value']);
  if (!file_exists($helper_file)) {
    form_set_error($field['#title'], t("Can't find helper app %helper -- please verify it is installed.", array(
      '%helper' => $helper_file,
    )));
  }
}

/**
 * fetch the helper add form, alter the form for use as an edit form, 
 * populate the #default_values fields and return the form
 *
 * @return unknown
 */
function search_files_helper_edit() {
  $sql = "SELECT * FROM {search_files_helpers} WHERE ID = '%s'";
  $result = db_fetch_object(db_query($sql, arg(5)));
  $form = search_files_helper_add();
  $form['search_file_id'] = array(
    '#type' => 'value',
    '#value' => $result->id,
  );
  $form['search_files_helper_path']['#default_value'] = $result->helper_path;
  $form['search_files_extension']['#default_value'] = $result->extension;
  $form['search_files_name']['#default_value'] = $result->name;
  unset($form['submit_done']);
  $form['submit'] = array(
    '#value' => 'Update',
    '#type' => 'submit',
  );
  return $form;
}

/**
 * update the row in the table search_files_helpers for the given helper app
 *
 * @param unknown_type $form_id
 * @param unknown_type $form_values
 */
function search_files_helper_edit_submit($form_id, $form_values) {

  //drupal_set_message('form_values = <pre>'.print_r($form_values, true).'</pre>');
  $sql = "\n    UPDATE\n      {search_files_helpers}\n    SET\n      name='%s',\n      extension='%s',\n      helper_path='%s'\n    WHERE\n      id='%s'\n  ";
  $result = db_query($sql, $form_values['search_files_name'], $form_values['search_files_extension'], $form_values['search_files_helper_path'], $form_values['search_file_id']);
  if ($result) {
    drupal_set_message(t('Helper app %helper_name has been updated', array(
      '%helper_name' => $form_values['search_files_name'],
    )));
    drupal_goto('admin/settings/search_files/helpers/list');
  }
}

/**
 * insert a row in the search_files_helpers table for the helper 
 * app given by the form
 *
 * @param unknown_type $form_id
 * @param unknown_type $form_values
 */
function search_files_helper_add_submit($form_id, $form_values) {

  //drupal_set_message('form_values = <pre>'.print_r($form_values, true).'</pre>');
  $sql = "\n    INSERT INTO\n     {search_files_helpers}\n   SET\n    name='%s',\n    extension='%s',\n    helper_path='%s'\n  ";
  $result = db_query($sql, $form_values['search_files_name'], $form_values['search_files_extension'], $form_values['search_files_helper_path']);
  if ($result) {
    drupal_set_message(t('%helper helper added', array(
      '%helper' => $form_values['search_files_name'],
    )));
  }
  if ($form_values['clicked_button']['#id'] == 'edit-submit-done') {
    drupal_goto('admin/settings/search_files/helpers/list');
  }
}

/**
 * generate the settings form for the search_files module using the 
 * system_settings_form()funciton
 *
 * @return unknown
 */
function search_files_settings() {
  $form = array();
  $form['search_files_label'] = array(
    '#title' => 'Search Label',
    '#type' => 'textfield',
    '#description' => 'What do you want the Search tab to be labeled?',
    '#default_value' => variable_get('search_files_label', 'Server Files'),
  );
  return system_settings_form($form);
}

/**
 * Implementation of hook_update_index()
 * 
 * lists all the files in the director(y/ies) and puts the files 
 * into the "search_files_files" table
 *
 * then indexes X(configurable) number of these files
 */
function search_files_update_index() {
  $helpers = search_files_get_helpers();

  // only update the list of files in the directories once per day
  if (variable_get('search_files_last_index', 0) < time() - 86400) {
    variable_set('search_files_last_index', time());
    $result = db_query('SELECT * FROM {search_files_directories}');
    while ($directory = db_fetch_object($result)) {
      search_files_list_directory($directory->directory, $directory->id);
    }
  }
  $index_number = (int) variable_get('search_cron_limit', 100);
  $sql = "\n      SELECT \n        *\n      FROM \n        {search_files_files}\n      LEFT JOIN \n      (\n        SELECT \n          {search_dataset}.sid sid ,type,data,{search_files_reindex}.reindex reindex\n        FROM\n          {search_dataset},{search_files_reindex}\n        WHERE \n          type = 'search_files'\n        AND\n          {search_dataset}.sid = {search_files_reindex}.sid\n      ) AS dataset ON {search_files_files}.id = dataset.sid \n      WHERE\n      (\n        dataset.reindex IS NULL OR\n        dataset.reindex != 0\n      ) AND {search_files_files}.index_attempts <= 5\n      LIMIT %s\n    ";
  $result = db_query($sql, $index_number);
  while ($file = db_fetch_object($result)) {
    $full_path = $file->full_path;
    $file_name = explode('/', $full_path);
    $file_name = $file_name[count($file_name) - 1];
    $file_extension = explode('.', $file_name);
    $file_extension = $file_extension[count($file_extension) - 1];
    if (in_array($file_extension, array_keys($helpers))) {

      // record that we are attempting to index the file in case it hangs
      $increment_sql = "\n        UPDATE\n          {search_files_files}\n        SET\n          index_attempts = index_attempts + 1\n        WHERE\n          id = '%s'\n      ";
      $increment_result = db_query($increment_sql, $file->id);
      if ($file->index_attempts >= 5) {

        // indexind failed too many times, record this to the log and continue
        watchdog('Search Files', t('failed to index %full_path after %attempts attempts', array(
          '%full_path' => $file->full_path,
          '%attempts' => $file->index_attempts,
        )), array(), WATCHDOG_ERROR);
        continue;
      }

      // %file% is a token that is placed in the helper's parameter list to represent the file path to the attachment.
      // We need to put the filename in quotes in case it contains spaces.
      $quoted_file_path = '"' . escapeshellcmd($full_path) . '"';
      $helper_command = preg_replace('/%file%/', $quoted_file_path, $helpers[$file_extension]);
      $file_text = shell_exec($helper_command);
      $file_text = search_files_convert_to_utf8($file_text);
      search_index($file->id, 'search_files', 'file name: ' . $quoted_file_path . ', text: ' . $file_text);

      /* DRUPAL 5 @ivazquez: */
      db_query("UPDATE {search_files_reindex} set reindex = 0 where sid=%d", $file->id);
      if (!db_affected_rows()) {
        db_query("INSERT INTO {search_files_reindex} (sid, reindex) values (%d,'%s') ", $file->id, 0);
      }
    }
    else {
      search_index($file->id, 'search_files', '');

      /* DRUPAL 5 @ivazquez: */
      db_query("UPDATE {search_files_reindex} set reindex = 0 where sid=%d", $file->id);
      if (!db_affected_rows()) {
        db_query("INSERT INTO {search_files_reindex} (sid, reindex) values (%d,'%s') ", $file->id, 0);
      }
    }
  }
}

/**
 * Get the host system's character encoding and convert text from it to UTF-8,
 * Drupal's default HTTP and database character encoding.
 */
function search_files_convert_to_utf8($text) {
  $encoding = iconv_get_encoding("output_encoding");
  $text = drupal_convert_to_utf8($text, $encoding);
  return $text;
}

/**
 * search_files_list_directory($directory, $id) will be called recursively
 * to traverse the directory tree and list all the files in the given 
 * directory, it will take the files it find and put them into the 
 * search_files_files table
 *
 * @param (string) $directory
 * @param (int) $id
 */
function search_files_list_directory($directory, $id) {
  if (!is_dir($directory)) {
    return;
  }
  watchdog('Search Files', 'Starting to list files in %directory', array(
    '%directory' => $directory,
  ));
  $file_count = 0;
  $dir_count = 0;
  if ($dir = opendir($directory)) {
    while ($file = readdir($dir)) {
      $type = filetype($directory . '/' . $file);
      $full_path = escapeshellcmd(search_files_convert_to_utf8($directory . '/' . $file));
      if ($type == 'dir') {

        // make sure we don't retreverse the current or parent directory
        if ($file != '.' && $file != '..') {
          $dir_count++;
          search_files_list_directory($directory . '/' . $file, $id);
        }
      }
      else {
        if ($type == 'file') {

          // Check to see if the file is already in the table,
          $sql = "\n          SELECT\n            id\n          FROM\n            {search_files_files}\n          WHERE\n            full_path='%s'\n        ";
          $result = db_result(db_query($sql, $full_path));

          // If the file is not in the table, insert it
          if (!$result) {
            $file_count++;
            $insert_sql = "\n            INSERT INTO\n              {search_files_files}\n            SET\n              full_path=\"%s\",\n              directory_id='%s'\n          ";

            //echo "filename: ". escapeshellcmd($file) ." - filetype: {$type}<br/>\n";

            // MySQL keeps throwing errors because of some file names that it doesn't like, this needs fixed
            $insert_result = db_query($insert_sql, $full_path, $id);
          }
        }
      }
    }
  }
  watchdog('Search Files', 'Finished Listing files in %directory, found %file_count new file(s)', array(
    '%directory' => $directory,
    '%file_count' => $file_count,
  ));
}

/**
 * implementation of hook_search()
 *
 * @param (string) $op
 * @param (string) $keywords
 * @return (mixed)
 */
function search_files_search($op = 'search', $keywords = null) {

  // drupal_set_message('FUNCTION = <pre>search_files_search</pre>');
  switch ($op) {
    case 'name':
      return variable_get('search_files_label', 'Server Files');
    case 'reset':

      /*  $sql="
            UPDATE
              {search_dataset}
            SET
              `reindex`='%s'
            WHERE
              `type`='search_files'
          "; */

      //MIGRACION A VERSION 5 @ivazquez:
      $sql = "\n            UPDATE \n              {search_files_reindex}\n            SET\n              reindex='%s'\n           ";
      $result = db_query($sql, time());
      db_query("UPDATE {search_files_files} SET index_attempts='0' WHERE 1=1");
      break;
    case 'status':
      $return = array();
      $sql = "SELECT COUNT(*) as count FROM {search_files_files}";
      $return['total'] = db_result(db_query($sql));

      /*$sql = "
          SELECT
            COUNT(*) AS `count`
          FROM
            {search_files_files}
          LEFT JOIN
          (
            SELECT
              *
            FROM
              {search_dataset}
            WHERE
              `type` = 'search_files'
          ) AS `dataset` ON {search_files_files}.`id` = `dataset`.`sid`
          WHERE
          (
            `dataset`.`reindex` IS NULL OR
            `dataset`.`reindex` != 0
          )
        ";*/
      $sql = "\n          SELECT \n          COUNT(*) AS count\n          FROM \n            {search_files_files}\n          LEFT JOIN \n          (\n              SELECT \n                {search_dataset}.sid sid ,type,data,{search_files_reindex}.reindex reindex\n              FROM\n                {search_dataset},{search_files_reindex}\n              WHERE \n                type = 'search_files'\n              AND\n                {search_dataset}.sid = {search_files_reindex}.sid\n          ) AS dataset ON {search_files_files}.id = dataset.sid \n          WHERE\n          (\n            dataset.reindex IS NULL OR\n            dataset.reindex != 0\n          )\n          ";
      $return['remaining'] = db_result(db_query($sql));
      return $return;
      break;
    case 'search':

      //drupal_set_message('$keywords = '.$keywords);
      if (!user_access('view search_files results')) {
        return null;
      }
      $doc_root = $_SERVER['DOCUMENT_ROOT'];

      //drupal_set_message($doc_root);
      $file_extensions = search_files_get_file_extensions();
      $results = array();
      $find = do_search($keywords, 'search_files');

      //drupal_set_message('find = <pre>'.var_export($find, true).'</pre>');

      //      date_default_timezone_set('GMT');
      foreach ($find as $item) {

        //drupal_set_message('item = <pre>'. var_export($item, true).'</pre>');
        $sql = "\n          SELECT\n            *\n          FROM\n            {search_files_files}\n          WHERE\n            id='%s'\n        ";
        $result = db_fetch_object(db_query($sql, $item->sid));
        $search_results = db_query("SELECT * FROM {search_dataset} s WHERE sid = %d AND type = '%s'", $item->sid, 'search_files');
        if ($dataset = db_fetch_object($search_results)) {

          //drupal_set_message('result = <pre>'.print_r($result, true).'</pre>');
          $file_name = explode('/', $result->full_path);
          $file_name = $file_name[count($file_name) - 1];
          $file_extension = explode('.', $file_name);
          $file_extension = $file_extension[count($file_extension) - 1];
          $link = str_replace($doc_root, '', $result->full_path);

          // we have had a problem where some links were returned relative to the search page,
          // not the document root, basically there was no beginning forward slash '/' in the
          // path
          if (strpos($link, '/') !== 0) {
            $link = '/' . $link;
          }
          $results[] = array(
            'link' => $link,
            'date' => filectime($result->full_path),
            'type' => $file_extensions[$file_extension] . ' file',
            'title' => $file_name . ' (' . format_size(filesize($result->full_path)) . ')',
            'snippet' => search_excerpt($keywords, $dataset->data),
          );
        }

        //date_default_timezone_set('MST');
      }

      //drupal_set_message('results = <pre>'.var_export($results, true).'</pre>');
      return $results;
      break;
  }
}

/**
 * generate the results page
 *
 * @param (array) $results
 * @param (string) $type
 * @return (string) $output
 */
function search_files_search_page($results, $type = 'search_files') {

  //drupal_set_message('FUNCTION = <pre>search_files_search_page</pre>');
  $output = '<dl class="search-results">';
  foreach ($results as $entry) {
    $output .= search_files_search_item_format($entry, $type);
  }
  $output .= '</dl>';
  $output .= theme('pager', NULL, 20, 0);
  return $output;
}

/**
 * format the result items before that are displayed
 *
 * @param (array) $item
 * @param (string) $type
 * @return (string) $output formatted string
 */
function search_files_search_item_format($item, $type) {

  //drupal_set_message('entry = <pre>'.var_export($item, true).'</pre>');
  $output = ' <dt class="title"><a href="' . check_url($item['link']) . '">' . check_plain($item['title']) . '</a></dt>';
  $info = array();
  if ($item['type']) {
    $info[] = check_plain($item['type']);
  }
  if ($item['user']) {

    // Add this here so the user name appears at the end of the output
    $item['extra'][] = $item['user'];
  }
  if ($item['date']) {
    $info[] = format_date($item['date'], 'small');
  }
  if (is_array($item['extra'])) {
    $info = array_merge($info, $item['extra']);
  }
  $output .= ' <dd>' . ($item['snippet'] ? '<p>' . $item['snippet'] . '</p>' : '') . '<p class="search-info">' . implode(' - ', $info) . '</p></dd>';
  return $output;
}

/**
 * returns an array of the file extensions with the extension as 
 * the key and the name of the file type as the value, this data 
 * is retrieved from the search_files_helpers table
 *
 * @return (array)
 */
function search_files_get_file_extensions() {
  $extensions = array();
  $result = db_query('SELECT extension, name FROM {search_files_helpers}');
  while ($helper = db_fetch_object($result)) {
    $extensions[$helper->extension] = $helper->name;
  }
  return $extensions;
}

Functions

Namesort descending Description
search_files_convert_to_utf8 Get the host system's character encoding and convert text from it to UTF-8, Drupal's default HTTP and database character encoding.
search_files_directories_add generates the form to add a directory to search_files_directories table
search_files_directories_add_submit adds a row to the search_files directories table with the information provided by the search_files_directory_add_form.
search_files_directories_list gets a list of directories to inde from the search_files_directories table and themes the list in a table
search_files_directory_confirm_delete check to make sure the directory the user wants to delete is a valid directory id number, then call the function to generate the confirmation form
search_files_directory_confirm_delete_form get the confirmation form to confirm deletion of a directory from the search_files_directories table
search_files_directory_confirm_delete_form_submit deletes the directory from the search_files_directories table after confirmation from the user, also deletes the files from the search_files_files table and removes the data from the search_dataset table
search_files_directory_edit generates the directory edit form, it does this by grabbing the directory add form and populates the #default_value fields for the directory in question
search_files_directory_edit_submit Updates the directory row in the serach_files_directories table from data given by the search_files_directory_edit form
search_files_get_file_extensions returns an array of the file extensions with the extension as the key and the name of the file type as the value, this data is retrieved from the search_files_helpers table
search_files_get_helpers get an array of helper programs
search_files_helpers_validate_add_edit validate the existence of the helper app supplied by the helper_add or helper_edit form
search_files_helper_add generate form to add a helper app to the system
search_files_helper_add_submit insert a row in the search_files_helpers table for the helper app given by the form
search_files_helper_confirm_delete check to make sure the $helper_id is valid (a number greater than zero) then it fetches the deletion confirmation form, then returns it
search_files_helper_confirm_delete_form generate the deletion confirmation form for helper apps and return the form
search_files_helper_confirm_delete_form_submit remove row for the helper app from the search_files_helpers table
search_files_helper_edit fetch the helper add form, alter the form for use as an edit form, populate the #default_values fields and return the form
search_files_helper_edit_submit update the row in the table search_files_helpers for the given helper app
search_files_helper_list display a themes table of the current helper apps set up in the system
search_files_list_directory search_files_list_directory($directory, $id) will be called recursively to traverse the directory tree and list all the files in the given directory, it will take the files it find and put them into the search_files_files table
search_files_menu Implementation of hook_menu()
search_files_perm Implementation of hook_perm()
search_files_search implementation of hook_search()
search_files_search_item_format format the result items before that are displayed
search_files_search_page generate the results page
search_files_settings generate the settings form for the search_files module using the system_settings_form()funciton
search_files_update_index Implementation of hook_update_index()