You are here

visual_select_file.module in Visual select file 7

File

visual_select_file.module
View source
<?php

define('VISUAL_SELECT_FILE_VIEW_TAG', 'visual_select_file');
define('VISUAL_SELECT_FILE_SUBMIT_BUTTON_SELECTOR', 'input[type="submit"]');

/**
 * Implements hook_init().
 */
function visual_select_file_init() {
  if (current_path() == 'admin/visual_select_file') {
    _visual_select_file_suppress_xbars('visual_select_file');
    $path = drupal_get_path('module', 'visual_select_file');
    drupal_add_js($path . '/visual_select_file.js');
    drupal_add_css($path . '/visual_select_file.modal.css');
  }
}

/**
 * Suppress Admin Menu & Navbar, and mark Toolbar for later.
 */
function _visual_select_file_suppress_xbars($source = '') {
  module_invoke('admin_menu', 'suppress');
  module_invoke('navbar', 'suppress');
  $suppress =& drupal_static('vsf_suppress_xbars');
  $suppress = TRUE;
}

/**
 * Implements hook_page_alter().
 *
 * Suppress Toolbar.
 */
function visual_select_file_page_alter(&$page) {
  if (drupal_static('vsf_suppress_xbars') === TRUE) {
    if (isset($page['page_top']['toolbar'])) {
      $page['page_top']['toolbar']['#access'] = FALSE;
    }
  }
}

/**
 * Implements hook_module_implements_alter().
 */
function visual_select_file_module_implements_alter(&$implementations, $hook) {
  $module = 'visual_select_file';

  // These go last.
  if (in_array($hook, array(
    'menu_alter',
    'form_alter',
    'form_field_ui_field_edit_form_alter',
  ))) {
    if (isset($implementations[$module])) {
      $group = $implementations[$module];
      unset($implementations[$module]);
      $implementations[$module] = $group;
    }
  }
}

/**
 * Implements hook_menu().
 */
function visual_select_file_menu() {
  $items['admin/config/media/visual-select-file'] = array(
    'title' => 'Visual select file',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'visual_select_file_settings_form',
    ),
    'file' => 'visual_select_file.admin.inc',
    'access arguments' => array(
      'administer site configuration',
    ),
  );
  return $items;
}

/**
 * Implements hook_menu_alter().
 */
function visual_select_file_menu_alter(&$items) {
  if (isset($items['admin/visual_select_file'])) {
    $items['admin/visual_select_file']['delivery callback'] = 'visual_select_file_return_view';
  }
}

/**
 * Delivery callback for Ajax request.
 */
function visual_select_file_return_view($html) {
  if (isset($_GET['raw'])) {
    echo $html;
    drupal_page_footer();
  }
  else {
    return drupal_deliver_html_page($html);
  }
}

/**
 * Implements hook_permission().
 */
function visual_select_file_permission() {
  return array(
    'visually select files' => array(
      'title' => t('Visually select files'),
      'description' => t('Determines DEFAULT access to the VSF selection grid View, overridable by View access.'),
    ),
  );
}

/**
 * Implements hook_file_download().
 */
function visual_select_file_file_download($uri) {
  if (variable_get('visual_select_file_public_is_public', 0)) {
    if (file_uri_scheme($uri) == 'public') {
      return array(
        'X-Visual-Select-File' => 'Yes',
      );
    }
  }
}

/**
 * Implements template_preprocess_views_view().
 */
function visual_select_file_preprocess_views_view(&$vars) {
  $view = $vars['view'];
  if (_visual_select_file_view_has_tag($view)) {
    $remove_absolute = variable_get('visual_select_file_remove_absolute', TRUE);
    $field = isset($_GET['vsf_field']) ? $_GET['vsf_field'] : '';
    global $base_url;
    $base_url_length = strlen($base_url);
    $fids = array_map(function ($record) {
      return $record->fid;
    }, $view->result);
    $files = file_load_multiple($fids);
    $meta = array();
    foreach ($files as $fid => $file) {
      $path = image_style_url('IMAGESTYLE', $file->uri);
      $path = preg_replace('#\\?itok=[^&]+$#', '', $path);

      // We know for a fact this itok won't work, so remove it for prettiness' sake.
      $original = file_create_url($file->uri);
      if ($remove_absolute) {
        if (substr($path, 0, $base_url_length) == $base_url) {
          $path = substr($path, $base_url_length);
        }
        if (substr($original, 0, $base_url_length) == $base_url) {
          $original = substr($original, $base_url_length);
        }
      }
      $meta[$fid] = array(
        $fid,
        $path,
        $file->filename,
        $original,
      );
    }
    $results = array(
      'results' => $meta,
      'selected_file' => (int) @$_GET['vsf_fid'],
    );
    $context = compact('view', 'files', 'field');
    drupal_alter('visual_select_file_results', $results, $context);
    drupal_add_js(array(
      'visual_select_file' => $results,
    ), 'setting');
  }
}

/**
 * Implements hook_element_info_alter().
 */
function visual_select_file_element_info_alter(&$types) {
  if (isset($types['managed_file']['#process'])) {
    $types['managed_file']['#process'][] = 'visual_select_file_pre_render_filefield_sources_element';
  }
}

/**
 * Add field instance settings for other parts of the machine to pick up.
 */
function visual_select_file_pre_render_filefield_sources_element($element, $form_state) {
  if (!_visual_select_file_user_has_access()) {
    return $element;
  }
  if (isset($element['#field_name']) && ($instance = field_widget_instance($element, $form_state))) {
    $field = $element['#entity_type'] . '.' . $element['#bundle'] . '.' . $element['#field_name'];

    // Add class to hide reference textfield.
    $vsf_hide_textfield = !empty($instance['widget']['settings']['filefield_sources']['source_reference']['vsf_hide_textfield']);
    if ($vsf_hide_textfield) {
      $element['filefield_reference']['autocomplete']['#attributes']['class'][] = 'vsf-hide-reference';
      $element['filefield_reference']['select']['#attributes']['class'][] = 'vsf-hide-reference';
    }

    // Add field's meta data to field.
    $element['filefield_reference']['autocomplete']['#attributes']['data-vsf-field'] = $field;

    // Undo part of file.module's validation.
    $index = array_search('file_managed_file_validate', $element['#element_validate']);
    if ($index !== FALSE) {
      $element['#element_validate'][$index] = 'visual_select_file_managed_file_validate';
    }

    // Load necessary resources for this page/form.
    _visual_select_file_load_resources_filefield();
  }
  return $element;
}

/**
 * Widget validation to replace file.module's file_managed_file_validate.
 */
function visual_select_file_managed_file_validate(&$element, &$form_state) {
  $clicked_button = end($form_state['triggering_element']['#parents']);
  if ($clicked_button != 'remove_button' && !empty($element['fid']['#value'])) {
    if (!file_load($element['fid']['#value'])) {
      form_error($element, t('The file referenced by the !name field does not exist.', array(
        '!name' => $element['#title'],
      )));
    }
  }

  // Check required property based on the FID.
  if ($element['#required'] && empty($element['fid']['#value']) && !in_array($clicked_button, array(
    'upload_button',
    'remove_button',
  ))) {
    form_error($element['upload'], t('!name field is required.', array(
      '!name' => $element['#title'],
    )));
  }

  // Consolidate the array value of this field to a single FID.
  if (!$element['#extended']) {
    form_set_value($element, $element['fid']['#value'], $form_state);
  }
}

/**
 * Helper to load necessary JS and CSS for filefield elements.
 */
function _visual_select_file_load_resources_filefield() {
  static $loaded = 0;
  if (!$loaded) {
    $loaded = 1;
    drupal_add_library('system', 'ui.dialog');
    $path = drupal_get_path('module', 'visual_select_file');
    drupal_add_js($path . '/visual_select_file.js');
    drupal_add_css($path . '/visual_select_file.form.css');
    $selector = variable_get('visual_select_file_submit_button_selector', VISUAL_SELECT_FILE_SUBMIT_BUTTON_SELECTOR);
    drupal_add_js(array(
      'visualSelectFile' => array(
        'submitButtonSelector' => $selector,
      ),
    ), 'setting');
  }
}

/**
 * Helper to determine if a View is one of us.
 */
function _visual_select_file_view_has_tag($view) {
  if (is_object($view)) {
    $tags = explode(' ', $view->tag);
  }
  elseif (is_string($view)) {
    $tags = explode(' ', $view);
  }
  else {
    $tags = $view;
  }
  return in_array(VISUAL_SELECT_FILE_VIEW_TAG, $tags);
}

/**
 * Check if this user has access to the VSF view.
 */
function _visual_select_file_user_has_access($account = NULL) {
  global $user;
  $account or $account = $user;
  $access =& drupal_static(__FUNCTION__ . ':' . $account->uid);
  if ($access === NULL) {
    $menu_item = menu_get_item('admin/visual_select_file');
    $access = (bool) @$menu_item['access'];
  }
  return $access;
}

/**
 * Implements hook_form_FORM_ID_alter() for field_ui_field_edit_form().
 */
function visual_select_file_form_field_ui_field_edit_form_alter(&$form, &$form_state) {
  $instance = $form['#instance'];
  $settings = $instance['widget']['settings'];
  if (isset($form['instance']['widget']['settings']['filefield_sources'])) {
    $element =& $form['instance']['widget']['settings']['filefield_sources'];

    // Extend 'reference' option title to clarify this is what VSF uses.
    $element['filefield_sources']['#options']['reference'] .= ' (' . t('with Visual Select File') . ')';

    // Add option to hide FFS' reference textfield.
    $vsf_hide_textfield = !empty($settings['filefield_sources']['source_reference']['vsf_hide_textfield']);
    $element['source_reference']['vsf_hide_textfield'] = array(
      '#type' => 'checkbox',
      '#title' => t('Hide reference textfield'),
      '#default_value' => $vsf_hide_textfield,
      '#description' => t('Checked, this will hide the textfield & submit button and only show the &quot;Choose file&quot; button.'),
    );
  }
}

/**
 * Implements hook_views_api().
 */
function visual_select_file_views_api() {
  return array(
    'api' => 3,
  );
}

/**
 * Implements hook_query_TAG_alter() for views_visual_select_file.
 */
function visual_select_file_query_views_visual_select_file_alter(QueryAlterableInterface $query) {
  if (isset($_GET['vsf_field'])) {
    list($entity_type, $bundle, $field) = explode('.', $_GET['vsf_field'] . '..');
    if ($entity_type && $bundle && $field) {
      $field_info = field_info_instance($entity_type, $field, $bundle);
      if ($field_info && !empty($field_info['settings']['file_extensions'])) {
        $extensions = explode(' ', $field_info['settings']['file_extensions']);
        $or = db_or();
        foreach ($extensions as $extension) {
          $or
            ->condition('file_managed.uri', '%.' . db_like($extension), 'LIKE');
        }
        $query
          ->condition($or);
      }
    }
  }
}

Functions

Namesort descending Description
visual_select_file_element_info_alter Implements hook_element_info_alter().
visual_select_file_file_download Implements hook_file_download().
visual_select_file_form_field_ui_field_edit_form_alter Implements hook_form_FORM_ID_alter() for field_ui_field_edit_form().
visual_select_file_init Implements hook_init().
visual_select_file_managed_file_validate Widget validation to replace file.module's file_managed_file_validate.
visual_select_file_menu Implements hook_menu().
visual_select_file_menu_alter Implements hook_menu_alter().
visual_select_file_module_implements_alter Implements hook_module_implements_alter().
visual_select_file_page_alter Implements hook_page_alter().
visual_select_file_permission Implements hook_permission().
visual_select_file_preprocess_views_view Implements template_preprocess_views_view().
visual_select_file_pre_render_filefield_sources_element Add field instance settings for other parts of the machine to pick up.
visual_select_file_query_views_visual_select_file_alter Implements hook_query_TAG_alter() for views_visual_select_file.
visual_select_file_return_view Delivery callback for Ajax request.
visual_select_file_views_api Implements hook_views_api().
_visual_select_file_load_resources_filefield Helper to load necessary JS and CSS for filefield elements.
_visual_select_file_suppress_xbars Suppress Admin Menu & Navbar, and mark Toolbar for later.
_visual_select_file_user_has_access Check if this user has access to the VSF view.
_visual_select_file_view_has_tag Helper to determine if a View is one of us.

Constants