You are here

scald_file.module in Scald File Provider 7

Scald File is a Scald Atom Provider for Files.

File

scald_file.module
View source
<?php

/**
 * @file
 * Scald File is a Scald Atom Provider for Files.
 */

/*******************************************************************************
 * SCALD HOOK IMPLEMENTATIONS
 */

/**
 * Implements hook_scald_wysiwyg_context_list_alter().
 */
function scald_file_scald_wysiwyg_context_list_alter(&$contexts) {
  drupal_add_js(drupal_get_path('module', 'scald_file') . '/scald_file.js');
  drupal_add_js(array(
    'scaldFile' => array(
      'path' => drupal_get_path('module', 'scald_file') . '/scald_file.css',
    ),
  ), 'setting');
}

/**
 * Implements hook_scald_atom_providers().
 */
function scald_file_scald_atom_providers() {
  return array(
    'file' => 'File upload',
  );
}

/**
 * Implements hook_scald_add_form().
 */
function scald_file_scald_add_form(&$form, &$form_state) {
  $defaults = scald_atom_defaults('file');
  $field = field_info_field('scald_file');
  $instance = field_info_instance('scald_atom', 'scald_file', 'file');
  $validators = array(
    'file_validate_extensions' => array(
      0 => 'ppt pptx xls xlsx doc docx odt pdf txt csv odg sxw ods rtf zip rar gz 7z tar',
    ),
  );
  $location = 'public://atoms/files';
  if ($field && $instance) {
    $validators = file_field_widget_upload_validators($field, $instance);
    $directory = file_field_widget_uri($field, $instance);
    if (file_prepare_directory($directory, FILE_CREATE_DIRECTORY)) {
      $location = $directory;
    }
  }
  $form['file'] = array(
    '#type' => $defaults->upload_type,
    '#title' => t('File'),
    '#upload_location' => $location,
    '#upload_validators' => $validators,
  );
}

/**
 * Implements hook_scald_add_atom_count().
 */
function scald_file_scald_add_atom_count(&$form, &$form_state) {
  if (is_array($form_state['values']['file'])) {
    return max(count($form_state['values']['file']), 1);
  }
  return 1;
}

/**
 * Implements hook_scald_add_form_fill().
 */
function scald_file_scald_add_form_fill(&$atoms, $form, $form_state) {
  foreach ($atoms as $delta => $atom) {
    if (is_array($form_state['values']['file']) && module_exists('plupload')) {
      module_load_include('inc', 'scald', 'includes/scald.plupload');
      $destination = $form['file']['#upload_location'] . '/' . $form_state['values']['file'][$delta]['name'];
      $file = scald_plupload_save_file($form_state['values']['file'][$delta]['tmppath'], $destination);
    }
    else {
      $file = file_load($form_state['values']['file']);
    }
    foreach (array(
      'author',
      'tag',
    ) as $name) {

      // hacky, because variable and field name do not really match.
      $field_name = 'scald_' . $name . 's';
      $langcode = field_language('scald_atom', $atom, $field_name);
      if (empty($form_state['values'][$field_name])) {
        continue;
      }

      // Borrowed from taxonomy_autocomplete_validate().
      $typed_terms = drupal_explode_tags($form_state['values'][$field_name]);
      $vocabulary = taxonomy_vocabulary_machine_name_load(variable_get('scald_' . $name . '_vocabulary', $field_name));
      foreach ($typed_terms as $typed_term) {
        if ($possibilities = taxonomy_term_load_multiple(array(), array(
          'name' => trim($typed_term),
          'vid' => $vocabulary->vid,
        ))) {
          $term = array_pop($possibilities);
        }
        else {
          $term = (object) array(
            'vid' => $vocabulary->vid,
            'name' => $typed_term,
            'vocabulary_machine_name' => $vocabulary->machine_name,
          );
          taxonomy_term_save($term);
        }
        $atom->{$field_name}[$langcode][] = array(
          'tid' => $term->tid,
        );
      }
    }
    $atom->title = $file->filename;
    $langcode = field_language('scald_atom', $atom, 'scald_file');
    $atom->scald_file[$langcode][0] = (array) $file;
  }
}

/**
 * Implements hook_form_FORM_ID_alter().
 */
function scald_file_form_scald_atom_add_form_options_alter(&$form, &$form_state, $form_id) {
  $scald = $form_state['scald'];
  if (isset($scald['type'])) {
    $type = $scald['type']->type;
  }
  else {
    $type = $scald['atoms'][0]->type;
  }
  if ($type !== 'file') {
    return;
  }
  foreach ($form as $key => $data) {
    if (strpos($key, 'atom') === 0) {
      $index = intval(substr($key, 4));
      if (isset($scald['atoms'][$index]->data['scald_thumbnail_default'])) {
        $scald_thumbnail_default = $scald['atoms'][$index]->data['scald_thumbnail_default'];
      }
      else {
        $scald_thumbnail_default = TRUE;
      }
      $form[$key]['scald_thumbnail_default'] = array(
        '#type' => 'checkbox',
        '#default_value' => $scald_thumbnail_default,
        '#title' => t('Automatically generate thumbnail'),
        '#description' => t('A thumbnail will be generated automatically, if possible, if the thumbnail field is empty.'),
        '#weight' => $form[$key]['scald_thumbnail']['#weight'] + 0.5,
        '#tree' => TRUE,
        '#parents' => array(
          $key,
          'scald_thumbnail_default',
        ),
      );
    }
  }
  $form['#attached']['js'][drupal_get_path('module', 'scald_file') . '/scald_file_edit_form.js'] = array(
    'type' => 'file',
  );
  array_unshift($form['#submit'], 'scald_file_default_thumbnail_handler');
}

/**
 * Handler to store the default thumbnail generation option in the atom Entity.
 */
function scald_file_default_thumbnail_handler(&$form, &$form_state) {
  foreach ($form as $key => $data) {
    if (strpos($key, 'atom') === 0) {
      $index = intval(substr($key, 4));
      $form_state['scald']['atoms'][$index]->data['scald_thumbnail_default'] = $form_state['values'][$key]['scald_thumbnail_default'];
    }
  }
}

/**
 * Generate a thumbnail for a pdf file.
 */
function _scald_file_pdf_thumbnail($atom, $file) {
  if ($file->filemime === 'application/pdf') {
    $uri = drupal_realpath($file->uri);
    if (file_exists($uri)) {
      $temp = file_directory_temp() . '/pdf_thumb.png';
      if (scald_file_is_exec_available() && (scald_file_command_exists('pdfdraw') || scald_file_command_exists('mudraw') || scald_file_command_exists('convert'))) {
        if (scald_file_command_exists('pdfdraw')) {
          exec('pdfdraw -o ' . escapeshellarg($temp) . ' ' . escapeshellarg($uri) . ' 1');
        }
        elseif (scald_file_command_exists('mudraw')) {
          exec('mudraw -o ' . escapeshellarg($temp) . ' ' . escapeshellarg($uri) . ' 1');
        }
        elseif (scald_file_command_exists('convert')) {
          $uri = $uri . '[0]';
          exec('convert ' . escapeshellarg($uri) . ' ' . escapeshellarg($temp));
        }
      }
      elseif (extension_loaded('imagick') && class_exists("Imagick")) {
        $im = new Imagick($uri . '[0]');
        $im = $im
          ->flattenImages();
        $im
          ->setImageFormat("png");
        $im
          ->thumbnailImage(400, 0);
        $im
          ->writeImage($temp);
      }
      if (file_exists($temp)) {
        $handle = fopen($temp, 'r');
        if ($directory = ScaldAtomController::getThumbnailPath('file')) {
          $dest = $directory . '/file-' . $file->fid . '.png';
          $thumb = file_save_data($handle, $dest);
          $langcode = field_language('scald_atom', $atom, 'scald_thumbnail');
          $atom->scald_thumbnail[$langcode][0] = (array) $thumb;
        }
        fclose($handle);
        unlink($temp);
      }
    }
  }
}

/**
 * Implements hook_scald_fetch().
 */
function scald_file_scald_fetch($atom, $type) {
  if ($type == 'atom') {
    $file = file_load($atom->base_id);
    $atom->base_entity = $file;
    $atom->file_source = $file->uri;
    $scald_thumbnail = field_get_items('scald_atom', $atom, 'scald_thumbnail');
    if (!empty($scald_thumbnail)) {
      $thumbnail = file_load($scald_thumbnail[0]['fid']);
      $atom->thumbnail_source = $thumbnail->uri;
    }
    else {
      $atom->thumbnail_source = _scald_file_get_default_icon($file);
    }
  }
}

/**
 * Get the default icon.
 *
 * @param object $file
 *   The file.
 *
 * @return string
 *   The file's path.
 */
function _scald_file_get_default_icon($file) {
  $name = str_replace(array(
    '/',
    '-',
  ), array(
    '_',
    '_',
  ), $file->filemime);
  $path = drupal_get_path('module', 'scald_file') . '/icons/' . $name . '.png';
  drupal_alter('scald_file_icon', $path, $name, $file);
  return $path;
}

/**
 * Synchronisation of scald_file field with base_id.
 *
 * The scald_file field is also the base entity. We keep them in synchronisation
 * when user updates that field.
 *
 * @param object $atom
 *   Atom.
 */
function _scald_file_sync_file($atom) {
  if (!empty($atom->scald_file)) {
    $items = field_get_items('scald_atom', $atom, 'scald_file');
    $atom->base_id = $items[0]['fid'];
  }
}

/**
 * Implements hook_scald_update_atom().
 */
function scald_file_scald_update_atom($atom, $mode) {
  if ($mode == 'atom') {
    _scald_file_sync_file($atom);
  }
}

/**
 * Implements hook_scald_register_atom().
 */
function scald_file_scald_register_atom($atom, $mode) {
  if ($mode == 'atom') {
    _scald_file_sync_file($atom);
  }
}

/**
 * Implements hook_scald_atom_presave().
 */
function scald_file_scald_atom_presave($atom) {
  if ($atom->type == 'file' && !empty($atom->data['scald_thumbnail_default'])) {
    $scald_thumbnail = field_get_items('scald_atom', $atom, 'scald_thumbnail');
    if (!$scald_thumbnail) {
      $langcode = field_language('scald_atom', $atom, 'scald_file');
      $file = file_load($atom->scald_file[$langcode][0]['fid']);
      _scald_file_pdf_thumbnail($atom, $file);
    }
  }
}

/**
 * Implements hook_scald_prerender().
 */
function scald_file_scald_prerender($atom, $context, $options, $mode) {
  if ($mode == 'atom') {
    if ($context === 'sdl_library_item') {
      $scald_thumbnail = field_get_items('scald_atom', $atom, 'scald_thumbnail');
      if (empty($scald_thumbnail)) {
        $atom->rendered->thumbnail_transcoded_url = file_create_url($atom->thumbnail_source);
      }
    }
    else {
      $config = scald_context_config_load($context);
      $file = isset($atom->base_entity) ? $atom->base_entity : file_load($atom->base_id);
      $transcoder = '';
      if (isset($config->transcoder[$atom->type]['*'])) {
        $transcoder = $config->transcoder[$atom->type]['*'];
      }
      if (module_exists('pdf') && !empty($transcoder) && strpos($transcoder, 'pdf') !== FALSE && $file->filemime === 'application/pdf') {
        $theme = preg_match('/^file_field_pdf_/', $transcoder) ? str_replace('file_field_pdf_', 'pdf_formatter_', $transcoder) : 'pdf_formatter_default';
        $atom->rendered->player = theme($theme, array(
          'file' => $file,
        ));
      }
      else {
        $scald_thumbnail = field_get_items('scald_atom', $atom, 'scald_thumbnail');
        if (!empty($transcoder) && !empty($scald_thumbnail) && preg_match('/^style-(.*)$/', $transcoder, $match)) {
          $style_name = $match[1];
          $preset = image_style_load($style_name);
          $thumbnail_source = image_style_url($preset['name'], $atom->thumbnail_source);
        }
        else {
          $thumbnail_source = $atom->thumbnail_source;
        }
        $atom->rendered->player = theme('scald_file_render', array(
          'vars' => array(
            'context' => $context,
            'file_source' => $atom->file_source,
            'file_size' => format_size($atom->base_entity->filesize),
            'thumbnail_source' => $thumbnail_source,
            'file_title' => check_plain($atom->title),
          ),
        ));
      }
    }
  }
}

/**
 * Implements hook_theme().
 */
function scald_file_theme() {
  return array(
    'scald_file_render' => array(
      'variables' => array(
        'vars' => NULL,
      ),
      'template' => 'scald-file-render',
    ),
  );
}

/**
 * Processes variables for scald_file_render.tpl.php.
 *
 * Defines theme hook suggestions to be able to overwrite
 * the template by context.
 */
function template_preprocess_scald_file_render(&$variables) {
  $variables['theme_hook_suggestions'][] = 'scald_file_render';
  $variables['theme_hook_suggestions'][] = 'scald_file_render__' . $variables['vars']['context'];
}

/**
 * Implements hook_views_api().
 */
function scald_file_views_api() {
  return array(
    'api' => 2,
    'path' => drupal_get_path('module', 'scald_file') . '/includes/',
  );
}

/**
 * Implements hook_scald_transcoders().
 */
function scald_file_scald_transcoders() {
  $transcoders = array();
  if (module_exists('pdf')) {
    $info = module_invoke_all('field_formatter_info');
    foreach ($info as $name => $formatter) {
      if (!preg_match('/^pdf_/', $name)) {
        continue;
      }
      $transcoders[$name] = array(
        'title' => $formatter['label'],
        'description' => $formatter['label'],
        'formats' => array(
          'file' => 'passthrough',
        ),
      );
    }
  }
  return $transcoders;
}

/**
 * Implements hook_scald_contexts().
 *
 * Defines a representation that can be used when an atom reference field
 * or views contains both images and files.
 */
function scald_file_scald_contexts() {
  $contexts['file_representation'] = array(
    'title' => t('File Representation'),
    'description' => t('The File Representation'),
    'render_language' => 'XHTML',
    'parseable' => TRUE,
    'formats' => array(
      'image' => array(
        'passthrough',
      ),
      'file' => array(
        'passthrough',
      ),
    ),
  );
  return $contexts;
}

/**
 * Implements hook_scald_render().
 *
 * Renders a representation that can be used when an atom reference field
 * or views contains both images and files.
 */
function scald_file_scald_render($atom, $context, $options = array()) {
  if ($context == 'file_representation') {
    $config = scald_context_config_load($context);
    if ('default' != $config->player['file']['*']) {
      return $atom->rendered->player;
    }
    else {
      return theme('scald_file_render', array(
        'vars' => array(
          'context' => $context,
          'file_source' => $atom->file_source,
          'file_size' => format_size($atom->base_entity->filesize),
          'thumbnail_source' => $atom->type == 'image' ? drupal_get_path('module', 'scald_file') . '/icons/image_jpeg2000.png' : $atom->thumbnail_source,
          'file_title' => check_plain($atom->title),
        ),
      ));
    }
  }
}

/**
 * Implements hook_action_info().
 */
function scald_file_action_info() {
  return array(
    'scald_file_generate_thumbnail' => array(
      'type' => 'scald_atom',
      'label' => t('Generate Thumbnail'),
      'configurable' => FALSE,
      'behavior' => array(
        'changes_property',
      ),
      'triggers' => array(
        'any',
      ),
    ),
  );
}

/**
 * Action callback for the thumbnail generation action.
 */
function scald_file_generate_thumbnail($entity, $context) {
  if ($entity->provider === 'scald_file') {
    $entity->data['scald_thumbnail_default'] = TRUE;
    scald_atom_save($entity);
  }
}

/**
 * Determines if a command exists on the current environment.
 *
 * @param string $command
 *    The command to check.
 *
 * @return bool
 *    True if the command has been found ; otherwise, false.
 *
 * @codingStandardsIgnoreStart
 *
 * Source: http://stackoverflow.com/questions/12424787/how-to-check-if-a-shell-command-exists-from-php
 */
function scald_file_command_exists($command) {
  $whereIsCommand = PHP_OS == 'WINNT' ? 'where' : 'which';

  // @codingStandardsIgnoreEnd
  $process = proc_open("{$whereIsCommand} {$command}", array(
    // STDIN.
    0 => array(
      "pipe",
      "r",
    ),
    // STDOUT.
    1 => array(
      "pipe",
      "w",
    ),
    // STDERR.
    2 => array(
      "pipe",
      "w",
    ),
  ), $pipes);
  if ($process !== FALSE) {
    $stdout = stream_get_contents($pipes[1]);
    $stderr = stream_get_contents($pipes[2]);
    fclose($pipes[1]);
    fclose($pipes[2]);
    proc_close($process);
    return $stdout != '';
  }
  return FALSE;
}

/**
 * Determines if exec is available.
 *
 * Source: http://stackoverflow.com/questions/3938120/check-if-exec-is-disabled.
 */
function scald_file_is_exec_available() {
  static $available;
  if (!isset($available)) {
    $available = TRUE;
    if (ini_get('safe_mode')) {
      $available = FALSE;
    }
    else {
      $d = ini_get('disable_functions');
      $s = ini_get('suhosin.executor.func.blacklist');
      if ("{$d}{$s}") {
        $array = preg_split('/,\\s*/', "{$d},{$s}");
        if (in_array('exec', $array)) {
          $available = FALSE;
        }
      }
    }
  }
  return $available;
}

Functions

Namesort descending Description
scald_file_action_info Implements hook_action_info().
scald_file_command_exists Determines if a command exists on the current environment.
scald_file_default_thumbnail_handler Handler to store the default thumbnail generation option in the atom Entity.
scald_file_form_scald_atom_add_form_options_alter Implements hook_form_FORM_ID_alter().
scald_file_generate_thumbnail Action callback for the thumbnail generation action.
scald_file_is_exec_available Determines if exec is available.
scald_file_scald_add_atom_count Implements hook_scald_add_atom_count().
scald_file_scald_add_form Implements hook_scald_add_form().
scald_file_scald_add_form_fill Implements hook_scald_add_form_fill().
scald_file_scald_atom_presave Implements hook_scald_atom_presave().
scald_file_scald_atom_providers Implements hook_scald_atom_providers().
scald_file_scald_contexts Implements hook_scald_contexts().
scald_file_scald_fetch Implements hook_scald_fetch().
scald_file_scald_prerender Implements hook_scald_prerender().
scald_file_scald_register_atom Implements hook_scald_register_atom().
scald_file_scald_render Implements hook_scald_render().
scald_file_scald_transcoders Implements hook_scald_transcoders().
scald_file_scald_update_atom Implements hook_scald_update_atom().
scald_file_scald_wysiwyg_context_list_alter Implements hook_scald_wysiwyg_context_list_alter().
scald_file_theme Implements hook_theme().
scald_file_views_api Implements hook_views_api().
template_preprocess_scald_file_render Processes variables for scald_file_render.tpl.php.
_scald_file_get_default_icon Get the default icon.
_scald_file_pdf_thumbnail Generate a thumbnail for a pdf file.
_scald_file_sync_file Synchronisation of scald_file field with base_id.