You are here

slickgrid.module in Slickgrid 7.2

Same filename and directory in other branches
  1. 6 slickgrid.module
  2. 7 slickgrid.module

File

slickgrid.module
View source
<?php

/** 
 * Implements hook_menu().
 */
function slickgrid_menu() {
  return array(
    'slickgrid/callback/add' => array(
      'page callback' => 'slickgrid_callback_add',
      'access arguments' => array(
        'access content',
      ),
      'type' => MENU_CALLBACK,
      'file' => 'includes/slickgrid.callbacks.inc',
    ),
    'slickgrid/callback/update' => array(
      'page callback' => 'slickgrid_callback_update',
      'access arguments' => array(
        'access content',
      ),
      'type' => MENU_CALLBACK,
      'file' => 'includes/slickgrid.callbacks.inc',
    ),
    'slickgrid/get/form/%' => array(
      'page callback' => 'slickgrid_get_form',
      'page arguments' => array(
        3,
      ),
      'access arguments' => array(
        'access content',
      ),
      'delivery callback' => 'ajax_deliver',
      'type' => MENU_CALLBACK,
      'file' => 'includes/slickgrid.form.inc',
    ),
    'slickgrid/get/data/%/%/%' => array(
      'page callback' => 'slickgrid_get_data',
      'page arguments' => array(
        3,
        4,
        5,
      ),
      'access arguments' => array(
        'access content',
      ),
      'type' => MENU_CALLBACK,
      'file' => 'includes/slickgrid.getdata.inc',
    ),
  );
}

/**
 * Implementation of hook_views_api
 */
function slickgrid_views_api() {
  $path = drupal_get_path('module', 'slickgrid');
  return array(
    'api' => '3',
    'path' => $path . '/includes',
    'template path' => $path . '/theme',
  );
}

/** 
 * Implementation of hook_theme(). 
 */
function slickgrid_theme() {
  $path = drupal_get_path('module', 'slickgrid');
  return array(
    // slickgrid theme function
    'slickgrid' => array(
      'arguments' => array(
        'view' => array(),
      ),
      'path' => $path . '/theme',
      'file' => 'theme.inc',
    ),
    // slickgrid controls theme function
    'slickgrid_controls' => array(
      'arguments' => array(
        'view' => array(),
      ),
      'path' => $path . '/theme',
      'file' => 'theme.inc',
    ),
    // Theme individual control
    'slickgrid_control' => array(
      'arguments' => array(
        'type' => null,
        'view' => array(),
      ),
      'path' => $path . '/theme',
      'file' => 'theme.inc',
    ),
    // Theme add control differently
    'slickgrid_control__add' => array(
      'arguments' => array(
        'type' => null,
        'view' => array(),
      ),
      'path' => $path . '/theme',
      'file' => 'theme.inc',
    ),
    // slickgrid tabs theme function
    'slickgrid_tabs' => array(
      'arguments' => array(
        'view' => array(),
      ),
    ),
    // Theme the views plugin form table
    'slickgrid_views_plugin_table' => array(
      'render element' => 'form',
      'path' => $path . '/theme',
      'file' => 'theme.inc',
    ),
  );
}

/** 
 * Implementation of hook_library(). 
 */
function slickgrid_library() {
  $path = libraries_get_path('slickgrid');

  // Slickgrid core library
  return array(
    'slickgrid' => array(
      'title' => 'Slickgrid',
      'website' => 'https://github.com/mleibman/SlickGrid/',
      'version' => 'Master',
      'js' => array(
        $path . '/lib/firebugx.js' => array(),
        $path . '/lib/jquery.event.drag-2.2.js' => array(),
        $path . '/slick.core.js' => array(),
        $path . '/slick.dataview.js' => array(),
        $path . '/slick.grid.js' => array(),
        $path . '/plugins/slick.checkboxselectcolumn.js' => array(),
        $path . '/plugins/slick.rowselectionmodel.js' => array(),
        $path . '/controls/slick.columnpicker.js' => array(),
      ),
      'css' => array(
        $path . '/slick.grid.css' => array(),
        $path . '/controls/slick.columnpicker.css' => array(),
      ),
      'dependencies' => array(
        array(
          'system',
          'ui.sortable',
        ),
        array(
          'system',
          'ui.resizable',
        ),
        array(
          'system',
          'effects.highlight',
        ),
      ),
    ),
  );
}

/**
 * Implements hook_views_post_build
 */
function slickgrid_views_post_build(&$view) {
  if (get_class($view->style_plugin) == 'slickgrid_views_plugin') {
    if (substr($_GET['q'], 0, 18) == 'slickgrid/get/data') {
      $view->build_info['query']
        ->range(arg(4), arg(5));
    }
    else {
      $view->build_info['query']
        ->range(0, 1);
    }
  }
}

/**
 * Implementation of hook_views_pre_view
 * @param object $view 
 * @return void
 */
function slickgrid_views_pre_view(&$view, $display_id, $args) {

  // TODO - Check this isn't running for all views
  global $user;
  if (isset($display_id)) {
    $view->slickgrid_settings = slickgrid_get_settings(array(
      'uid' => $user->uid,
      'view_name' => $view->name,
      'display_id' => $display_id,
    ));
  }

  // FIXME - The following code is used to remove hidden columns from export
  // data.  This was also being run on standard slickgrid views which prevent
  // re-enabling of hidden columns

  /*
  // If there are hidden columns
  if(isset($view->slickgrid_settings['hidden_columns']) && !empty($view->slickgrid_settings['hidden_columns'])){
    // Remove them from the exported file
    foreach($view->slickgrid_settings['hidden_columns'] as $hidden_column){
      $view->set_item($display_id, 'field', $hidden_column, null);
    }
  }
  */

  // If row selection checkboxes are enabled, allow users to only export selected nodes.
  if (isset($_POST['export_selected_rows']) && isset($_POST['entity_ids'])) {

    // Remove all existing arguments - we'll limit result set by entity ID only
    foreach ($view
      ->get_items('argument') as $id => $arg) {
      $view
        ->set_item($display_id, 'argument', $id, NULL);
    }

    // Add an argument to limit the view to only nids being updated
    $options = array(
      'table' => $view->base_table,
      'field' => $view->base_field,
      'break_phrase' => 1,
    );
    $view
      ->add_item($display_id, 'argument', $view->base_table, $view->base_field, $options);
    $view
      ->set_arguments(array(
      implode('+', $_POST['entity_ids']),
    ));
  }

  // Collapsible tree stuff
  $plugins = array();

  // Is this a slickgrid?
  if ($view->display_handler
    ->get_option('style_plugin') == 'slickgrid') {
    $style_options = $view->display_handler
      ->get_option('style_options');
    if (isset($style_options['columns'])) {
      foreach ($style_options['columns'] as $field_id => $column) {

        // Get all plugin types
        foreach (array_keys(slickgrid_get_plugin_types()) as $plugin_type) {

          // Has the plugin been set for this column?
          if (!empty($column[$plugin_type])) {
            if (!isset($plugins[$plugin_type])) {
              $plugins[$plugin_type] = slickgrid_get_plugins($plugin_type);
            }

            // Plugins can define callbacks for views+pre_view
            if (isset($plugins[$plugin_type][$column[$plugin_type]]['hooks']['views_pre_view'])) {

              //Load the plugin file if there's a callback function
              require_once DRUPAL_ROOT . '/' . $plugins[$plugin_type][$column[$plugin_type]]['path'] . '/' . $plugins[$plugin_type][$column[$plugin_type]]['file'];

              // Get & call the function
              $func = $plugins[$plugin_type][$column[$plugin_type]]['hooks']['views_pre_view'];
              $func($view, $field_id, $display_id);
            }
          }
        }
      }
    }
  }
}

/**
 * Implements hook_user_delete()
 */
function slickgrid_user_delete($account) {
  $query = db_delete('slickgrid')
    ->condition('uid', $account->uid)
    ->execute();
}

/**
 * Implements hook_ctools_plugin_api().
 */
function slickgrid_ctools_plugin_api($owner, $api) {
  if ($owner == 'slickgrid') {
    return array(
      'version' => 1,
    );
  }
}

/**
 * Implementation of hook_ctools_plugin_directory() to let the system know
 * we implement task and task_handler plugins.
 */
function slickgrid_ctools_plugin_directory($module, $plugin) {
  if ($module == 'slickgrid') {
    return 'plugins/' . $plugin . 's';
  }
}

/**
 * Implements hook_ctools_plugin_type().
 */
function slickgrid_ctools_plugin_type() {
  return array(
    'filter' => array(
      'cache' => TRUE,
      'title' => t("Filter"),
    ),
    'editor' => array(
      'cache' => TRUE,
      'title' => t("Editor"),
    ),
    'formatter' => array(
      'cache' => TRUE,
      'title' => t("Formatter"),
    ),
    'validator' => array(
      'cache' => TRUE,
      'title' => t("Validator"),
    ),
  );
}
function slickgrid_get_plugins($plugin_type) {
  ctools_include('plugins');
  $plugins = ctools_get_plugins('slickgrid', $plugin_type);
  return $plugins;
}
function slickgrid_get_plugin_types() {
  return array_map(create_function('$type', 'return $type["title"];'), slickgrid_ctools_plugin_type());
}
function slickgrid_get_plugin_options_for_field($plugin_type, $field_type) {
  $options = array();
  $plugins = slickgrid_get_plugins($plugin_type);
  foreach ($plugins as $type => $plugin) {
    if (!isset($plugin['field_types'])) {
      $options[$type] = $plugin['title'];
    }
    elseif (in_array($field_type, $plugin['field_types'])) {
      $options[$type] = $plugin['title'];
    }
  }
  if (count($options)) {
    $options = array_merge(array(
      '' => '<none>',
    ), $options);
  }
  return $options;
}
function slickgrid_plugin_load_class($type, $id, $class_name) {
  ctools_include('plugins');
  $plugin_definition = ctools_get_plugins('slickgrid', $type, $id);
  require_once DRUPAL_ROOT . '/' . $plugin_definition['path'] . "/{$class_name}.class.php";
  $class = ctools_plugin_get_class($plugin_definition, $class_name);
  return $class;
}
function slickgrid_set_settings($uid, $view_name, $display_id, $settings) {
  $record = new stdClass();
  $record->uid = $uid;
  $record->view_name = $view_name;
  $record->display_id = $display_id;
  if ($record->settings = slickgrid_get_settings(array(
    'uid' => $uid,
    'view_name' => $view_name,
    'display_id' => $display_id,
  ))) {
    $update = array(
      'uid',
      'view_name',
      'display_id',
    );
  }
  else {
    $update = array();
  }
  foreach ($settings as $setting => $value) {
    $record->settings[$setting] = $value;
  }
  $record->settings = serialize($record->settings);
  drupal_write_record('slickgrid', $record, $update);
}

/**
 * 
 * Get settings from the DB
 * Pass in $setting to retrieve a particular setting, NULL to get akll for a UID / View
 * @param string $uid
 * @param string $view_name
 * @param string $setting
 */
function slickgrid_get_settings($conditions = array(), $setting = null) {
  $query = db_select('slickgrid', 'sg');
  foreach ($conditions as $field => $condition) {
    $query
      ->condition($field, $condition);
  }
  $query
    ->fields('sg', array(
    'settings',
  ));
  $result = $query
    ->execute();
  $settings = unserialize($result
    ->fetchField());
  if ($setting) {
    return $settings[$setting];
  }
  else {
    return $settings;
  }
}

/**
 * 
 * Get a views filtered by NIDs 
 * @param string $view_name
 * @param string $display_id
 * @param array $nids
 */
function slickgrid_get_view($view_name, $display_id, $entity_ids = array(), $args = array()) {
  $view = views_get_view($view_name);
  $view
    ->set_display($display_id);

  // If there are entity IDs specified, add arguments to return only these ones
  if (count($entity_ids)) {

    // Remove all existing arguments
    foreach ($view
      ->get_items('argument') as $id => $arg) {
      $view
        ->set_item($display_id, 'argument', $id, NULL);
    }

    // Add an argument to limit the view to only nids being updated
    $options = array(
      'table' => $view->base_table,
      'field' => $view->base_field,
      'break_phrase' => 1,
    );
    $view
      ->add_item($display_id, 'argument', $view->base_table, $view->base_field, $options);
    $args = array(
      implode('+', $entity_ids),
    );
  }
  $view
    ->pre_execute($args);
  $view
    ->execute();
  $view
    ->render();
  return $view;
}

/**
 * Get all fields of a aprticular type
 * @param string $type
 * @param string $entity_type
 */
function slickgrid_get_fields_of_type($type, $entity_type = null) {
  $query = db_select('field_config', 'fc');
  $query
    ->fields('fc', array(
    'field_name',
  ));
  $query
    ->condition('type', $type, '=');
  if (!is_null($entity_type)) {
    $query
      ->join('field_config_instance', 'fci', 'fci.field_id = fc.field_id');

    //JOIN node with users
    $query
      ->condition('entity_type', $entity_type);
  }
  $result = $query
    ->execute();
  return $result
    ->fetchAllKeyed();
}

/**
 * 
 * Default form used for editors
 * @param array $form
 * @param array $form_state
 */
function slickgrid_editor_form($form, &$form_state) {
  $editor = $form_state['editor'];

  // Use the first entity - this will be used as the default value for all selected entities
  foreach ($editor->entities as $entity) {
    list($id, $vid, $bundle_name) = entity_extract_ids($editor->entity_type, $entity);
    $info = entity_get_info($editor->entity_type);
    $label_key = $info['entity keys']['label'];

    // Is this the label we're editing?
    if ($editor->field_id == $label_key) {
      $form[$editor->field_id] = array(
        '#type' => 'textfield',
        '#title' => ucfirst($label_key),
        '#default_value' => $entity->{$label_key},
        '#size' => 60,
        '#maxlength' => 128,
        '#required' => TRUE,
      );
      $form['#entity_property'] = true;

      // Create an instance of the field
    }
    elseif (!($instance = field_info_instance($editor->entity_type, $editor->field_id, $bundle_name))) {
      $editor
        ->set_error($id, t('Field doesn\'t exist'), 'form');
      return;
    }
    elseif ($instance['required']) {

      // If any field instance is required, set required to true
      $required = true;
    }

    // have we retrieved the form field yet?
    if (!count($form)) {

      // file_field_widget_form() requires parents to be an array so ensure it is
      $form['#parents'] = array();

      // Invoke & return the field form
      $form = _field_invoke_default('form', $editor->entity_type, $entity, $form, $form_state, array(
        'field_id' => $editor->field_id,
        'field_name' => $editor->field_id,
      ));
    }
  }

  // If any of the bundles have the field as required, make the form field required
  if ($required) {
    $langcode = $form[$editor->field_id]['#language'];
    $form[$editor->field_id][$langcode][0]['#required'] = $required;
  }

  // Ensure values passed in from the slickgrid are persistent across the form rebuild
  foreach (array(
    'field_name',
    'field_id',
    'view',
    'display_id',
    'plugin',
    'revision',
    'entity_type',
    'entity_ids',
  ) as $element_name) {
    if (is_array($form_state['values'][$element_name])) {

      // entity ids will be passed as an array
      foreach ($form_state['values'][$element_name] as $element_value) {
        $form[$element_name][] = array(
          '#type' => 'hidden',
          '#value' => $element_value,
          '#parents' => array(
            $element_name,
            '',
          ),
        );
      }
    }
    else {
      $form[$element_name] = array(
        '#type' => 'hidden',
        '#value' => $form_state['values'][$element_name],
      );
    }
  }
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Save'),
    '#weight' => 100,
  );
  return $form;
}

/**
 * Implements hook_module_implements_alter()
 * 
 * Move this module's hook_file_presave to the top.
 */
function slickgrid_module_implements_alter(&$implementations, $hook) {
  if ($hook == 'file_presave') {
    if (isset($implementations['slickgrid'])) {
      $move = $implementations['slickgrid'];
      unset($implementations['slickgrid']);
      $new_implementations = array(
        'slickgrid' => $move,
      );
      foreach ($implementations as $key => $move) {
        $new_implementations[$key] = $move;
      }
      $implementations = $new_implementations;
    }
  }
}

/**
 * Due to the fact that we validate all forms at once, and then submit all forms
 * at once, we can end up with multiple new terms, when only one is required.
 * This function helps remedy that issue.
 */
function slickgrid_prevent_duplicate_terms($entity) {

  // Get the names of all taxonomy fields
  $field_names = db_select('field_config', 'f')
    ->fields('f', array(
    'field_name',
  ))
    ->condition('module', 'taxonomy')
    ->execute()
    ->fetchCol();
  foreach ($field_names as $field_name) {
    if (isset($entity->{$field_name})) {
      foreach (array_keys($entity->{$field_name}) as $lang) {
        foreach ($entity->{$field_name}[$lang] as $key => $value) {
          if (isset($value['tid']) && $value['tid'] == 'autocreate') {

            // We try and load the term, as it may now exist.
            $new = db_select('taxonomy_term_data', 'td')
              ->fields('td', array(
              'tid',
            ))
              ->condition('name', $value['name'])
              ->condition('vid', $value['vid'])
              ->execute()
              ->fetchField();
            if ($new) {
              $entity->{$field_name}[$lang][$key] = (array) taxonomy_term_load($new);
            }
          }
        }
      }
    }
  }
}
function slickgrid_editor_form_submit($form, &$form_state) {
  $editor =& $form_state['editor'];
  foreach ($editor->entities as $entity) {

    // Get the entity ids
    list($id, $vid, $bundle_name) = entity_extract_ids($editor->entity_type, $entity);

    // Create an instance of the field
    if (!isset($form['#entity_property'])) {
      if (!($instance = field_info_instance($editor->entity_type, $editor->field_id, $bundle_name))) {

        // Add entity to the editor's error array
        $editor
          ->set_error($id, t('Field does not exist for this bundle'), 'submit');
        continue;
      }
    }

    // Populate the entity with the submitted values
    entity_form_submit_build_entity($editor->entity_type, $entity, $form, $form_state);

    // Try to save the entity
    try {
      slickgrid_prevent_duplicate_terms($entity);
      entity_save($editor->entity_type, $entity);

      // Add entity to the editor's updated array
      $editor->updated[$id] = array(
        'vid' => $vid,
      );
    } catch (Exception $e) {

      // Add entity to the editor's error array
      $editor
        ->set_error($id, t('Error trying to update entity'), 'submit');
    }
  }
}

/**
 * 
 * Validate the slickgrid editor form
 * If multiple items are being edited, need to ensure all are validated properly 
 * @param unknown_type $form
 * @param unknown_type $form_state
 */
function slickgrid_editor_form_validate($form, &$form_state) {
  $editor =& $form_state['editor'];

  // Loop through all of the entities
  foreach ($editor->entities as $entity) {
    list($id, $vid, $bundle_name) = entity_extract_ids($editor->entity_type, $entity);

    // Check access
    if ($editor->entity_type == 'file' && !file_entity_access('update') || $editor->entity_type != 'file' && !entity_access('update', $editor->entity_type, $entity)) {

      // User doesn't have access to edit
      $error = t('You do not have access to update this @type', array(
        '@type' => isset($entity->type) ? $entity->type : $editor->entity_type,
      ));
    }
    elseif ($instance = field_info_instance($editor->entity_type, $editor->field_id, $bundle_name)) {
      _field_invoke_default('extract_form_values', $editor->entity_type, $entity, $form, $form_state);
      try {
        field_attach_validate($editor->entity_type, $entity);

        // If reached here, validation has passed
        continue;
      } catch (FieldValidationException $e) {
        foreach ($e->errors as $field_name => $field_errors) {
          $error .= strip_tags(_slickgrid_editor_get_form_error_message($field_errors));
        }
      }
    }
    elseif (!isset($form['#entity_property'])) {
      $error = t('Field doesn\'t exist');
    }
    if (isset($error)) {

      // If got to this point the bundle failed validation
      $editor
        ->set_error($id, $error);

      // Set form error to prevent form submission
      form_set_error($editor->field_id, t('Validation error'));
    }
  }
}

/**
 * Helper function to recurse into an error to get the actual text.
 */
function _slickgrid_editor_get_form_error_message($error) {
  if (is_array($error)) {
    if (isset($error['message'])) {
      return $error['message'];
    }
    else {
      $error = array_pop($error);
      return _slickgrid_editor_get_form_error_message($error);
    }
  }
  else {
    return t('Unknown error');
  }
}

/**
 * Implements hook_field_attach_validate().
 * 
 * This is simply here to prevent errors when editing an entity that was 
 * associated with a term that has been deleted.
 * 
 * This error is to prevent errors being thrown under the following situation:
 * - Create term
 * - Associate term with entity
 * - Delete term
 * - Edit term in slickgrid, but editing a different field.
 * These would normally be prevented because the values in a taxonomy field do
 * not include links to terms that have been deleted.
 */
function slickgrid_field_attach_validate($entity_type, $entity, &$errors) {
  if ($_GET['q'] == 'slickgrid/callback/update') {
    foreach ($errors as $key => $value) {

      // Check if the $key is a taxonomy field, and if it is, we remove the
      // error.
      $field = field_info_field($key);
      if ($field['type'] == 'taxonomy_term_reference') {
        unset($errors[$key]);
      }
    }
  }
}

/**
 * Implentats hook_form_alter
 * 
 * Add an after build function to supress redirecting forms when used in the slickgrid callback
 */
function slickgrid_form_alter(&$form, &$form_state, $form_id) {
  if (arg(0) == 'slickgrid' && arg(1) == 'callback') {
    $form['#after_build'][] = 'slickgrid_form_redirect_handler';
  }
}

/**
 * Implement hook_form_FORM_ID_alter().
 * 
 * The "Edit" user form.  This needs to be able to handle both login and 
 * loginless changes.
 */
function slickgrid_form_user_profile_form_alter(&$form, &$form_state) {
  if ($form['#user']->uid && !arg(3)) {
    $disabled = db_select('slickgrid', 's')
      ->fields('s')
      ->condition('uid', $form['#user']->uid)
      ->countQuery()
      ->execute()
      ->fetchCol();
    $form['slickgrid'] = array(
      '#type' => 'fieldset',
      '#title' => t('Slickgrid'),
      '#collapsed' => TRUE,
      '#collapsible' => TRUE,
    );
    if ($disabled[0]) {
      $form['slickgrid']['scratchpads_messages_reset_tips'] = array(
        '#type' => 'submit',
        '#value' => t('Reset Slickgrid settings'),
        '#submit' => array(
          'slickgrid_reset_user',
        ),
        '#limit_validation_errors' => array(),
      );
    }
    else {
      $form['slickgrid']['scratchpads_messages_reset_tips'] = array(
        '#markup' => '<p>' . t('You do not currently have any custom settings.') . '</p>',
      );
    }
  }
}

/**
 * Reset the viewed status of all messages related to a specific user.
 */
function slickgrid_reset_user($form, &$form_state) {
  if (@isset($form_state['complete form']['#user']->uid)) {
    db_delete('slickgrid')
      ->condition('uid', $form_state['complete form']['#user']->uid)
      ->execute();
  }
}

/**
 * After build form function - set no redirect
 */
function slickgrid_form_redirect_handler(&$form, &$form_state) {
  $form_state['no_redirect'] = true;
  return $form;
}
function slickgrid_list_addable_entities() {
  $entities = array();
  foreach ($entities_info = entity_get_info() as $entity_type => $entity_info) {
    if (isset($entity_info['form callback'])) {
      foreach ($entity_info['bundles'] as $bundle_name => $bundle) {
        $entities[$entity_type . '/' . $bundle_name] = $entity_info['label'] . ': ' . $bundle['label'];
      }
    }
  }
  return $entities;
}

Functions

Namesort descending Description
slickgrid_ctools_plugin_api Implements hook_ctools_plugin_api().
slickgrid_ctools_plugin_directory Implementation of hook_ctools_plugin_directory() to let the system know we implement task and task_handler plugins.
slickgrid_ctools_plugin_type Implements hook_ctools_plugin_type().
slickgrid_editor_form Default form used for editors
slickgrid_editor_form_submit
slickgrid_editor_form_validate Validate the slickgrid editor form If multiple items are being edited, need to ensure all are validated properly
slickgrid_field_attach_validate Implements hook_field_attach_validate().
slickgrid_form_alter Implentats hook_form_alter
slickgrid_form_redirect_handler After build form function - set no redirect
slickgrid_form_user_profile_form_alter Implement hook_form_FORM_ID_alter().
slickgrid_get_fields_of_type Get all fields of a aprticular type
slickgrid_get_plugins
slickgrid_get_plugin_options_for_field
slickgrid_get_plugin_types
slickgrid_get_settings Get settings from the DB Pass in $setting to retrieve a particular setting, NULL to get akll for a UID / View
slickgrid_get_view Get a views filtered by NIDs
slickgrid_library Implementation of hook_library().
slickgrid_list_addable_entities
slickgrid_menu Implements hook_menu().
slickgrid_module_implements_alter Implements hook_module_implements_alter()
slickgrid_plugin_load_class
slickgrid_prevent_duplicate_terms Due to the fact that we validate all forms at once, and then submit all forms at once, we can end up with multiple new terms, when only one is required. This function helps remedy that issue.
slickgrid_reset_user Reset the viewed status of all messages related to a specific user.
slickgrid_set_settings
slickgrid_theme Implementation of hook_theme().
slickgrid_user_delete Implements hook_user_delete()
slickgrid_views_api Implementation of hook_views_api
slickgrid_views_post_build Implements hook_views_post_build
slickgrid_views_pre_view Implementation of hook_views_pre_view
_slickgrid_editor_get_form_error_message Helper function to recurse into an error to get the actual text.