You are here

oa_files.module in Open Atrium Files 7.2

File

oa_files.module
View source
<?php

/**
 * @file
 * Code for the Open Atrium Files feature.
 */
include_once 'oa_files.features.inc';

/**
 * Implements hook_menu().
 */
function oa_files_menu() {
  $items = array();
  if (module_exists('devel')) {
    $items['oa-files/ctools-test'] = array(
      'access arguments' => array(
        'access devel information',
      ),
      'page callback' => 'oa_files_ctools_test',
      'page title' => 'Test Ctools Modal',
      'type' => MENU_CALLBACK,
    );
  }
  $items['oa-files/upload/multi/%oa_files_upload_multi'] = array(
    'title' => 'Create & Update Documents',
    'page callback' => 'oa_files_upload_create_documents_form_page',
    'page arguments' => array(
      3,
    ),
    'access callback' => 'node_access',
    'access arguments' => array(
      'create',
      'oa_wiki_page',
    ),
    'theme callback' => 'media_dialog_get_theme_name',
  );
  $items['api/oa/files-addterm'] = array(
    'page callback' => 'oa_files_addterm_callback',
    'access arguments' => array(
      'access content',
    ),
  );
  $items['api/oa/files-addmenu'] = array(
    'page callback' => 'oa_files_addmenu_callback',
    'access arguments' => array(
      'access content',
    ),
  );
  $items['api/oa/files-addmenu/%node'] = array(
    'page callback' => 'oa_files_addmenu_callback',
    'page arguments' => array(
      3,
    ),
    'access arguments' => array(
      'access content',
    ),
  );
  return $items;
}

/**
 * Implements hook_menu_alter().
 */
function oa_files_menu_alter(&$items) {
  if (!empty($items['media/browser'])) {
    $items['oa-files/upload'] = $items['media/browser'];
    $items['oa-files/upload']['access callback'] = 'node_access';
    $items['oa-files/upload']['access arguments'] = array(
      'create',
      'oa_wiki_page',
    );
  }
}

/**
 * Implements hook_ctools_plugin_directory().
 */
function oa_files_ctools_plugin_directory($owner, $plugin_type) {
  if ($owner == 'ctools' && $plugin_type == 'content_types') {
    return 'plugins/content_types';
  }
}

/**
 * Implements hook_theme().
 */
function oa_files_theme() {
  $path = drupal_get_path('module', 'oa_files') . '/templates';
  return array(
    'oa_files' => array(
      'template' => 'oa-files',
      'variables' => array(),
      'path' => $path,
    ),
    'oa_files_dialog_page' => array(
      'render element' => 'page',
      'template' => 'templates/oa-files-dialog-page',
    ),
  );
}

/**
 * Load callback for %media_multi placeholder in menu paths.
 *
 * @param string $fids
 *   Separated by space (e.g., "3 6 12 99"). This often appears as "+" within
 *   URLs (e.g., "3+6+12+99"), but sometimes changes these to spaces.
 *
 * @return array
 *   An array of corresponding file entities.
 */
function oa_files_upload_multi_load($fids) {
  return file_load_multiple(explode(' ', str_replace('+', ' ', $fids)));
}

/**
 * Helper function to get options for redirect.
 */
function _oa_files_get_redirect_options() {
  $options = array();
  if (isset($_GET['destination'])) {
    $destination = drupal_get_destination();
    unset($_GET['destination']);
    if ($destination) {
      $options['query']['destinations'] = $destination;
    }
  }
  $keep = array(
    'oa_section_ref',
    'menu_parent',
    'term_parent',
  );
  foreach ($keep as $query_param) {
    if (isset($_GET[$query_param])) {
      $options['query'][$query_param] = $_GET[$query_param];
    }
  }
  return $options;
}

/**
 * Page callback to return the create documents.
 */
function oa_files_upload_create_documents_form_page($files) {
  ctools_include('modal');
  ctools_include('ajax');
  $form_state = array(
    'title' => t('Add files'),
    'build_info' => array(
      'args' => array(
        $files,
      ),
    ),
    'no_redirect' => TRUE,
  );
  $output = ctools_modal_form_wrapper('oa_files_upload_create_documents_form', $form_state);
  if ($form_state['executed']) {
    $commands = array();
    $commands[0] = ctools_modal_command_dismiss(t('Addition Success'));
    $commands[1] = array(
      // The command will be used in our JavaScript file (see next section)
      'command' => 'oaFilesAdded',
      // We pass the value that the user selected in the select element to our
      // JavaScript function:
      'files' => oa_files_prepare_files_from_files($form_state['build_info']['args'][0]),
    );
    $commands[2] = ajax_command_insert('#main-wrapper', theme('status_messages'));
    $commands[2]['method'] = 'prepend';
    $commands[2]['effect'] = 'none';
    print '<div id="json-encode" style="display:none;">';
    print ajax_render($commands);
    print '</div>';
    print t('Processing...');
    exit;
  }
  $render = drupal_render($output);

  // The responsive table class causes a scrollbar, remove.
  return str_replace('table-responsive', '', $render);
}

/**
 * Form callback; Create multiple documents.
 */
function oa_files_upload_create_documents_form($form, &$form_state, $files) {
  $form = array();
  $form['documents'] = array(
    '#tree' => TRUE,
    '#theme' => 'table',
    '#header' => array(
      t('File Name'),
      t('Update'),
      t('Title'),
    ),
    '#rows' => array(),
    '#sticky' => FALSE,
  );
  $form['#files'] = $files;

  // Get the group/section to look for the file in.
  $gid = $sid = NULL;
  if (($context = og_context()) && og_user_access($context['group_type'], $context['gid'], "create oa_wiki_page content")) {
    $gid = $context['gid'];
    $section_id = !empty($_GET['oa_section_ref']) ? $_GET['oa_section_ref'] : oa_section_get_section_context();
    if ($section_id && node_access('view', node_load($section_id))) {
      $sid = $section_id;
    }
  }
  $form['#gid'] = $gid;
  $form['#sid'] = $sid;
  if (empty($sid) && module_exists('oa_sections')) {

    // Figure out best Section to create document page.
    // And prompt user to select section.
    $sid = oa_sections_get_best_section('oa_wiki_page', NULL, $gid);
    $form['oa_files_section'] = array(
      '#type' => 'oa_section_ref',
      '#title' => 'Section',
      '#default_value' => $sid,
      '#og_group_ref' => '',
    );
  }
  $has_update = FALSE;
  foreach ($files as $fid => $file) {

    // Just be sure they have access in case URL manipulation.
    if (!file_entity_access('view', $file)) {
      continue;
    }
    $form['documents'][$file->fid]['title'] = array(
      '#type' => 'textfield',
      '#title' => t('Title'),
      '#default_value' => $file->filename,
      '#weight' => $fid,
    );
    $form['documents'][$file->fid]['title'] = array(
      '#type' => 'textfield',
      '#title' => t('Title'),
      '#default_value' => $file->filename,
      '#weight' => $fid,
      '#attributes' => array(
        'style' => 'width:auto;',
      ),
    );
    $form['documents'][$file->fid]['update'] = array(
      '#access' => FALSE,
    );
    if ($node = oa_files_find_document_for_existing_document($file, $gid, $sid)) {
      $has_update = TRUE;
      $form['documents'][$file->fid]['update'] = array(
        '#type' => 'checkbox',
        '#title' => t('Document <a href="@url">@title</a> already contains @filename, make a new copy?', array(
          '@url' => url('node/' . $node->nid),
          '@title' => $node->title,
          '@filename' => $file->filename,
        )),
        '#default_value' => 0,
        '#weight' => $fid - 0.5,
      );
      $form['documents'][$file->fid]['title']['#states'] = array(
        'invisible' => array(
          ':input[name="documents[' . $file->fid . '][update]"]' => array(
            'checked' => FALSE,
          ),
        ),
      );
      $form['#files'][$file->fid]->node = $node;
      $form['#files'][$file->fid]->existing_document = TRUE;
    }
    elseif ($node = oa_files_find_document($file, $gid)) {
      $has_update = TRUE;
      $form['#files'][$file->fid]->node = $node;
      $form['documents'][$file->fid]['update'] = array(
        '#type' => 'checkbox',
        '#title' => t('Update Document <a href="@url">@title</a> to file @filename?', array(
          '@url' => url('node/' . $node->nid),
          '@title' => $node->title,
          '@filename' => $file->filename,
        )),
        '#default_value' => 1,
        '#weight' => $fid - 0.5,
      );
      $form['documents'][$file->fid]['title']['#states'] = array(
        'invisible' => array(
          ':input[name="documents[' . $file->fid . '][update]"]' => array(
            'checked' => TRUE,
          ),
        ),
      );
    }
    $form['documents']['#rows'][$file->fid] = array(
      array(
        'data' => check_plain($file->filename),
      ),
      array(
        'data' => &$form['documents'][$file->fid]['update'],
      ),
      array(
        'data' => &$form['documents'][$file->fid]['title'],
      ),
    );
  }

  // Remove update row if none are filled in.
  if (!$has_update) {
    foreach ($form['documents']['#rows'] as $fid => $row) {
      unset($form['documents']['#rows'][$fid][1]);
    }
    unset($form['documents']['#header'][1]);
  }
  $form['create'] = array(
    '#value' => t('Process'),
    '#type' => 'submit',
  );
  return $form;
}

/**
 * Submit callback that creates or updates documents.
 */
function oa_files_upload_create_documents_form_submit($form, &$form_state) {
  $sid = !empty($form_state['values']['oa_files_section']) ? $form_state['values']['oa_files_section'] : $form['#sid'];
  foreach ($form_state['values']['documents'] as $fid => $values) {
    if (!empty($form['#files'][$fid])) {
      $file = $form['#files'][$fid];

      // If the document exists already in gid/section.
      $existing_document = !empty($form['#files'][$file->fid]->existing_document);

      // If existing document: whether to create a new document (FALSE for create)
      // otherwise, document with same path exists, update to new file.
      $update = !empty($values['update']);
      if (!empty($file->node->nid) && !$existing_document && $update) {
        oa_files_update_document(node_load($file->node->nid), $file->node->oa_files_row, $file);
      }
      elseif (!$existing_document || $update) {
        $node = oa_files_create_document($file, $values['title'], $form['#gid'], $sid);
        $form['#files'][$fid]->node = $node;
      }
      else {
        unset($form['#files'][$fid]);
      }
    }
  }
}

/**
 * Creates a document from a file.
 *
 * @param $file
 *   A file object.
 * @param $title
 *   The title of document.
 * Returns the created document node
 */
function oa_files_create_document($file, $title, $gid = NULL, $sid = NULL) {
  global $user;
  $node = (object) array(
    // Create oa_files.
    'type' => 'oa_wiki_page',
    'uid' => $user->uid,
    'name' => $user->name,
    // Add the file to the oa_media attachment field.
    'field_oa_media' => array(
      LANGUAGE_NONE => array(
        0 => array(
          'fid' => $file->fid,
          'display' => 1,
          'description' => $title,
        ),
      ),
    ),
    'language' => LANGUAGE_NONE,
    // Set the Title of the Document node to the same title.
    'title' => $title,
    'is_new' => TRUE,
  );

  // Set the Space (og_group_ref) to the current Space Context.
  // Set the Section (oa_section_ref) to the current Section Context.
  if ($gid) {
    $node->og_group_ref = array(
      LANGUAGE_NONE => array(
        0 => array(
          'target_id' => $gid,
        ),
      ),
    );
    if ($sid) {
      $node->oa_section_ref = array(
        LANGUAGE_NONE => array(
          0 => array(
            'target_id' => $sid,
          ),
        ),
      );
    }
    if (isset($_GET['menu_parent']) || $sid) {
      $pid = !empty($_GET['menu_parent']) ? $_GET['menu_parent'] : $sid;
      if (($parent = node_load($pid)) && node_access('view', $parent) && ($mlid = og_menu_single_get_link_mlid('node', $pid))) {
        $is_in_group = FALSE;
        foreach (field_get_items('node', $parent, 'og_group_ref') as $value) {
          if ($value['target_id'] == $gid) {
            $is_in_group = TRUE;
            break;
          }
        }
        if ($is_in_group) {
          $node->menu = array(
            'plid' => $mlid,
            'link_title' => $title,
            'enabled' => TRUE,
            'description' => '',
          );
          if ($parent->type == 'oa_section') {
            $node->oa_section_ref = array(
              LANGUAGE_NONE => array(
                0 => array(
                  'target_id' => $parent->nid,
                ),
              ),
            );
          }
        }
      }
    }
    if (!empty($_GET['term_parent']) && ($term = taxonomy_term_load($_GET['term_parent']))) {

      // if using og_vocab, grab the valid vocab ids.
      $fieldname = '';
      $propname = '';
      if (module_exists('og_vocab')) {
        $vids = og_vocab_get_accessible_vocabs('node', $node->type, OG_VOCAB_FIELD);
        if (in_array($term->vid, $vids)) {
          $fieldname = 'og_vocabulary';
          $propname = 'target_id';
        }
      }
      if (empty($fieldname)) {

        // did not find og vocab, so check for global taxonomy reference fields
        $vocab = taxonomy_vocabulary_load($term->vid);
        $field_info = field_info_fields();
        $fields = field_info_instances('node', $node->type);
        foreach ($fields as $key => $field) {
          $info = $field_info[$key];
          if ($info['module'] == 'taxonomy') {
            foreach ($info['settings']['allowed_values'] as $index => $item) {
              if ($item['vocabulary'] == $vocab->machine_name) {
                $fieldname = $info['field_name'];
                $propname = 'tid';
                break;
              }
            }
          }
        }
      }
      if (!empty($fieldname)) {
        $node->{$fieldname}[LANGUAGE_NONE][] = array(
          $propname => $term->tid,
        );
      }
    }
    if (module_exists('workbench_moderation')) {
      $node->workbench_moderation_state_new = variable_get('workbench_moderation_default_state_' . $node->type, workbench_moderation_state_none());
    }
    node_save($node);
    drupal_set_message(t('Document <a href="@url">@title</a> created.', array(
      '@title' => $node->title,
      '@url' => url('node/' . $node->nid),
    )));
  }
  return $node;
}

/**
 * Update a document to a new file.
 *
 * @param $mode
 *   The node to update
 * @param $row
 *   The row in the database to update (with delta and language).
 * @param $file
 *   The file object
 */
function oa_files_update_document($node, $row, $file) {
  $node->field_oa_media[$row->language][$row->delta]['fid'] = $file->fid;
  $node->revision = 1;
  $node->log = 'Update file via upload.';
  node_save($node);
  if (module_exists('oa_workbench')) {
    drupal_set_message(t('New draft of <a href="@url">@title</a> created.', array(
      '@title' => $node->title,
      '@url' => url('node/' . $node->nid),
    )));
  }
  else {
    drupal_set_message(t('Document <a href="@url">@title</a> updated.', array(
      '@title' => $node->title,
      '@url' => url('node/' . $node->nid),
    )));
  }
}

/**
 * Find the documents that reference current file.
 *
 * @param $file
 *   The file object to find.
 */
function oa_files_find_document_for_existing_document($file, $gid = NULL, $sid = NULL) {
  $query = db_select('file_managed', 'f');
  $query
    ->innerJoin('field_data_field_oa_media', 'm', 'm.field_oa_media_fid = f.fid AND m.entity_type = :type', array(
    ':type' => 'node',
  ));
  $query
    ->addField('m', 'entity_id', 'nid');
  $query
    ->condition('f.fid', $file->fid);
  $query
    ->orderBy('f.fid', 'ASC');
  $query
    ->innerJoin('node', 'n', 'n.nid = m.entity_id');
  $query
    ->condition('n.type', 'oa_wiki_page');
  if ($gid) {
    $query
      ->innerJoin('og_membership', 'om', 'm.entity_id = om.etid AND om.entity_type = :type AND om.group_type = :type AND om.gid = :id', array(
      ':type' => 'node',
      ':id' => $gid,
    ));
    if ($sid) {
      $query
        ->innerJoin('field_data_oa_section_ref', 'sf', 'm.entity_id = sf.entity_id AND sf.entity_type = :type', array(
        ':type' => 'node',
      ));
      $query
        ->condition('sf.oa_section_ref_target_id', $sid);
    }
  }
  foreach ($query
    ->execute()
    ->fetchCol() as $nid) {
    if (($node = node_load($nid)) && node_access('view', $node)) {
      return $node;
    }
  }
}

/**
 * Find the document that may correspond to a given file.
 *
 * @param $file
 *   The file object to find.
 */
function oa_files_find_document($file, $gid = NULL, $sid = NULL) {
  $uri = strtolower($file->uri);
  $uri_ext = substr($uri, strrpos($uri, '.'));
  $uri_sans_ext = substr($uri, 0, strrpos($uri, '.'));
  $uri_after_underscore = substr($uri_sans_ext, strrpos($uri_sans_ext, '_') + 1);
  $uri_before_underscore = substr($uri_sans_ext, 0, strrpos($uri_sans_ext, '_'));
  $test_alt = $uri_before_underscore && strlen($uri_after_underscore) && is_numeric($uri_after_underscore);

  // This is not a renamed file, no existing document matches.
  if (!$test_alt) {
    return FALSE;
  }

  // We want to find all files on document with the same uri or prefix.
  $query = db_select('file_managed', 'f');
  $query
    ->innerJoin('field_data_field_oa_media', 'm', 'm.field_oa_media_fid = f.fid AND m.entity_type = :type', array(
    ':type' => 'node',
  ));
  $query
    ->fields('m', array(
    'delta',
    'language',
  ));
  $query
    ->addField('f', 'uri');
  $query
    ->addField('m', 'entity_id', 'nid');
  $query
    ->innerJoin('node', 'n', 'n.nid = m.entity_id');
  $query
    ->condition('n.type', 'oa_wiki_page');
  $query
    ->condition(db_or()
    ->condition('f.uri', db_like($uri), 'LIKE')
    ->condition('f.uri', db_like($uri_before_underscore) . '%', 'LIKE'));
  $query
    ->orderBy('f.fid', 'ASC');
  if ($gid) {
    $query
      ->innerJoin('og_membership', 'om', 'm.entity_id = om.etid AND om.entity_type = :type AND om.group_type = :type AND om.gid = :id', array(
      ':type' => 'node',
      ':id' => $gid,
    ));
    if ($sid) {
      $query
        ->innerJoin('field_data_oa_section_ref', 'sf', 'm.entity_id = sf.entity_id AND sf.entity_type = :type AND sf.oa_section_ref_target_id = :id', array(
        ':type' => 'node',
        ':id' => $sid,
      ));
    }
  }
  if ($rows = $query
    ->execute()
    ->fetchAll()) {
    foreach ($rows as $row) {

      // Test if the db one is [uri].[ext] or [uri]_[numeric].[ext].
      $row_uri = strtolower($row->uri);
      $db_uri_ext = substr($row_uri, strrpos($row_uri, '.'));
      $db_uri_sans_ext = substr($row_uri, 0, strrpos($row_uri, '.'));
      $db_uri_after_underscore = NULL;
      if ($pos = strrpos($db_uri_sans_ext, '_')) {
        $db_uri_before_underscore = substr($db_uri_sans_ext, 0, $pos);
        $db_uri_after_underscore = substr($db_uri_sans_ext, strrpos($db_uri_sans_ext, '_') + 1);
      }
      if ($db_uri_after_underscore !== '0' && !$db_uri_after_underscore || !is_numeric($db_uri_after_underscore)) {
        $db_uri_before_underscore = $db_uri_sans_ext;
        $db_uri_after_underscore = FALSE;
      }
      if ($db_uri_before_underscore == $uri_before_underscore && $db_uri_ext == $uri_ext && (!$db_uri_after_underscore || is_numeric($db_uri_after_underscore))) {
        if (($node = node_load($row->nid)) && $node->type == 'oa_wiki_page' && node_access('update', $node)) {
          $node->oa_files_row = $row;
          return $node;
        }
      }
    }
  }
  return FALSE;
}

/**
 * Test page callback to display add files ctools link.
 */
function oa_files_ctools_test() {
  oa_files_include_js();
  return l(t('Create Files'), 'oa-files/upload/ajax', array(
    'query' => array(
      'menu_parent' => 0,
    ),
  ));
}

/**
 * Implements hook_page_alter().
 *
 * This is used to use our alternate template when ?render=media-popup is passed
 * in the URL.
 */
function oa_files_page_alter(&$page) {
  if (variable_get('oa_files_include_js', TRUE)) {
    oa_files_include_js();
  }
  if (isset($_GET['render']) && $_GET['render'] == 'oa-files-popup') {
    drupal_add_css(drupal_get_path('module', 'oa_files') . '/css/oa_files.media.css', array(
      'basename' => 'seven_style',
      'group' => CSS_THEME,
    ));
    $page['#theme'] = 'oa_files_dialog_page';

    // Disable administration modules from adding output to the popup.
    // @see http://drupal.org/node/914786
    module_invoke_all('suppress', TRUE);
    foreach (element_children($page) as $key) {
      if ($key != 'content') {
        unset($page[$key]);
      }
    }
  }
}

/**
 * Add messages to the page.
 */
function template_preprocess_oa_files_dialog_page(&$variables) {
  $variables['messages'] = theme('status_messages');
}

/**
 * Include JS.
 */
function oa_files_include_js() {
  $included =& drupal_static(__FUNCTION__, FALSE);
  if (!$included) {
    $included = TRUE;
    $field = field_info_field('field_oa_media');
    $instance = field_info_instance('node', 'field_oa_media', 'oa_wiki_page');
    $widget_settings = $instance['widget']['settings'];
    $field_settings = $field['settings'];
    $multiselect = module_exists('plupload');
    $options = array(
      'types' => array_filter($widget_settings['allowed_types']),
      'enabledPlugins' => array_filter($instance['widget']['settings']['browser_plugins']),
      'schemes' => array_filter($widget_settings['allowed_schemes']),
      'file_directory' => isset($field_settings['file_directory']) ? $field_settings['file_directory'] : '',
      'file_extensions' => isset($field_settings['file_extensions']) ? $field_settings['file_extensions'] : variable_get('file_entity_default_allowed_extensions', OA_FILE_EXTENSIONS_DEFAULT),
      'max_filesize' => isset($field_settings['max_filesize']) ? $field_settings['max_filesize'] : 0,
      'uri_scheme' => !empty($field['settings']['uri_scheme']) ? $field['settings']['uri_scheme'] : file_default_scheme(),
      'multiselect' => $multiselect,
    );
    drupal_load('module', 'media_wysiwyg');
    if (function_exists('media_wysiwyg_include_browser_js')) {

      // older versions of Media
      media_wysiwyg_include_browser_js();
    }
    else {
      drupal_add_library('media', 'media_browser');
      drupal_add_library('media', 'media_browser_settings');
    }
    drupal_add_library('system', 'drupal.ajax');
    drupal_add_js(drupal_get_path('module', 'oa_files') . '/js/upload.js');
    drupal_add_js(array(
      'oa_files_media_options' => array(
        'global' => $options,
      ),
      'oa_files_upload_url' => url('oa-files/upload/multi'),
    ), 'setting');
  }
}

/**
 * Implements hook_admin_paths().
 */
function oa_files_admin_paths() {
  $paths = array();
  $dialog_theme = variable_get('media_dialog_theme', '');
  if (empty($dialog_theme) || $dialog_theme == variable_get('admin_theme')) {
    $paths['oa-files/upload'] = TRUE;
    $paths['oa-files/upload/*'] = TRUE;
  }
  return $paths;
}

/**
 * Return a file download link with token
 * Copied from file_entity but we don't want to load a full file node
 * @param $fid
 * @param $uri
 */
function oa_files_download_uri($fid, $file_uri) {
  $uri = array(
    'path' => "file/{$fid}/download",
    'options' => array(),
  );
  if (!variable_get('file_entity_allow_insecure_download', FALSE)) {

    //    $uri['options']['query']['token'] = file_entity_get_download_token($file);
    $uri['options']['query']['token'] = substr(drupal_hmac_base64("file/{$fid}/download:" . $file_uri, drupal_get_private_key() . drupal_get_hash_salt()), 0, 8);
  }
  return url($uri['path'], $uri['options']);
}

/**
 * Helper function to create files array needed by angular app from an array of Drupal files
 * @param $files
 */
function oa_files_prepare_files_from_files($files) {
  $result = array();
  foreach ($files as $fid => $file) {
    if (isset($file->node->nid)) {
      $node = $file->node;
      $nid = $node->nid;
      $icon = file_icon_url($file);

      // Determine parent of item.
      // Mostly this comes from the term_parent or menu_parent in URL.
      if (isset($_GET['term_parent'])) {
        $parent = 'tid' . $_GET['term_parent'];
      }
      elseif (isset($_GET['menu_parent']) && ($mlid = og_menu_single_get_link_mlid('node', $nid))) {
        $menu_link = menu_link_load($mlid);
        $parent_link = menu_link_load($menu_link['plid']);
        if (preg_match('#^node/(\\d+)#', $parent_link['link_path'], $matches)) {
          $parent = $matches[1];
        }
      }
      elseif (isset($_GET['menu_parent'])) {
        $parent = $_GET['menu_parent'];
      }
      else {
        $parent = 0;
      }
      $result[$nid] = array(
        'id' => $nid,
        'nid' => $nid,
        "name" => $node->title,
        "parent" => array(
          $parent,
        ),
        "date" => format_date($node->created, 'short'),
        "modified" => format_date($node->changed, 'short'),
        "editor" => node_access("update", $node),
        "url" => 'node/' . $nid,
        'filesize' => format_size($file->filesize),
        'downloadurl' => oa_files_download_uri($fid, $file->uri),
        'filename' => $file->filename,
        'icon' => $icon,
        'mimetype' => $file->filemime,
      );
    }
  }
  return $result;
}

/**
 * Ajax Callback for adding a new taxonomy term (folder)
 * @param $node
 */
function oa_files_addterm_callback($parent_tid = 0, $parent_vid = 0) {
  $new_term = $_POST['node'];
  $node_type = !empty($_POST['type']) ? str_replace('-', '_', $_POST['type']) : 'oa_wiki_page';
  $parent_term = null;
  $vid = $parent_vid;
  if ($parent_tid) {
    $parent_term = taxonomy_term_load($parent_term);
    if ($parent_term) {
      $vid = $parent_term->vid;
    }
  }
  if (!($vocab = taxonomy_vocabulary_load($vid))) {
    ajax_deliver(MENU_ACCESS_DENIED);
    return FALSE;
  }
  if (empty($_REQUEST['token']) || !drupal_valid_token($_REQUEST['token'], 'add-term-' . $vid)) {
    return MENU_ACCESS_DENIED;
  }
  $space_id = oa_core_get_space_context();
  $allownew = FALSE;
  if (module_exists('og_vocab')) {
    $vids = og_vocab_get_accessible_vocabs('node', $node_type, OG_VOCAB_FIELD);
    if (in_array($vid, $vids)) {

      // check OG access for editing vocab terms
      $allownew = og_user_access('node', $space_id, "edit terms");
    }
  }
  if (!$allownew) {

    // otherwise check global permission for vocab
    $allownew = user_access('edit terms in ' . $vid);
  }
  if (!$allownew) {
    ajax_deliver(MENU_ACCESS_DENIED);
    return FALSE;
  }
  $term = new stdClass();
  $term->name = $new_term['name'];
  $term->vid = $vid;
  if (!empty($new_term['parent'])) {
    $term->parent = $new_term['parent'][0];
  }
  taxonomy_term_save($term);
  $return = array(
    'id' => 'tid' . $term->tid,
    'tid' => $term->tid,
  );
  print drupal_json_output($return);
}

/**
 * Ajax Callback for adding a new document within a menu (folder)
 * @param $node
 */
function oa_files_addmenu_callback($parent = NULL) {
  global $user;
  if (empty($_REQUEST['token']) || !drupal_valid_token($_REQUEST['token'], 'add-node-' . ($parent ? $parent->nid : 'undefined'))) {
    return MENU_ACCESS_DENIED;
  }
  $new_node = $_POST['node'];
  $title = $new_node['name'];
  $node = (object) array(
    // Create oa_files.
    'type' => 'oa_wiki_page',
    'uid' => $user->uid,
    'name' => $user->name,
    'language' => LANGUAGE_NONE,
    // Set the Title of the Document node to the same title.
    'title' => $title,
    'is_new' => TRUE,
  );
  if (($context = og_context()) && og_user_access($context['group_type'], $context['gid'], "create oa_wiki_page content")) {

    // @todo check access, e.g. can add to group/section.
    $node->og_group_ref = array(
      LANGUAGE_NONE => array(
        0 => array(
          'target_id' => $context['gid'],
        ),
      ),
    );
    if (($section_id = oa_section_get_section_context()) && node_access('view', node_load($section_id))) {
      $node->oa_section_ref = array(
        LANGUAGE_NONE => array(
          0 => array(
            'target_id' => $section_id,
          ),
        ),
      );
    }
    if (empty($parent)) {
      $parent = node_load($section_id);
    }
    if ($parent && node_access('view', $parent) && ($mlid = og_menu_single_get_link_mlid('node', $parent->nid))) {
      $is_in_group = FALSE;
      foreach (field_get_items('node', $parent, 'og_group_ref') as $value) {
        if ($value['target_id'] == $context['gid']) {
          $is_in_group = TRUE;
          break;
        }
      }
      if ($is_in_group) {
        $node->menu = array(
          'plid' => $mlid,
          'link_title' => $title,
          'enabled' => TRUE,
          'description' => '',
        );
        if ($parent->type == 'oa_section') {
          $node->oa_section_ref = array(
            LANGUAGE_NONE => array(
              0 => array(
                'target_id' => $parent->nid,
              ),
            ),
          );
        }
      }
    }
    node_save($node);
    $return = array(
      'oa_files' => array(
        'node_token' => array(
          'node:' . $node->nid => drupal_get_token('add-node-' . $node->nid),
        ),
      ),
      'id' => $node->nid,
      'additions' => array(
        'date' => format_date($node->created, 'short'),
        'modified' => format_date($node->changed, 'short'),
        'editor' => node_access("update", $node),
      ),
    );
    print drupal_json_output($return);
  }
  else {
    ajax_deliver(MENU_ACCESS_DENIED);
    return FALSE;
  }
}

/**
 * Implements hook_form_alter().
 */
function oa_files_form_alter(&$form, &$form_state, $form_id) {

  // We are creating a new node from the Add button in the files/folder widget
  if (isset($_GET['menu_parent']) || isset($_GET['term_parent'])) {

    // Check if this matches the content type being created.
    if (preg_match('#(.+)_node_form#', $form_id, $matches)) {
      $type = isset($_GET['type']) ? str_replace('-', '_', $_GET['type']) : 'oa_wiki_page';
      if ($matches[1] == $type) {
        $node =& $form['#node'];
        $menu_parent = isset($_GET['menu_parent']) ? $_GET['menu_parent'] : NULL;

        // When creating document nodes from files widget, auto-fill menu parent or taxonomy from URL.
        // Check "Show node instead of file" option by default.
        if (isset($form['field_oa_wiki_page_no_redirect'][LANGUAGE_NONE])) {
          $form['field_oa_wiki_page_no_redirect'][LANGUAGE_NONE]['#default_value'] = 1;
        }
        if (isset($form[OA_SECTION_FIELD][LANGUAGE_NONE])) {

          // Figure out best Section to create document page.
          $section = module_exists('oa_sections') ? oa_sections_get_best_section($node->type, $form[OA_SECTION_FIELD][LANGUAGE_NONE]['#options']) : NULL;
          if (!empty($section)) {
            $form[OA_SECTION_FIELD][LANGUAGE_NONE]['#default_value'] = $section;

            // when creating first item, menu_parent is zero, so change it to actual section
            if (empty($menu_parent)) {
              $menu_parent = $section;
            }
          }

          // move Section selection to top of node form so user can confirm it
          $form[OA_SECTION_FIELD]['#weight'] = $form['body']['#weight'] - 0.5;

          // and move the field out of any field group
          if (isset($form['#group_children'])) {
            unset($form['#group_children'][OA_SECTION_FIELD]);
          }
        }
        if (isset($menu_parent) && empty($form['menu']['link']['parent']['#default_value'])) {
          $pid = $menu_parent;
          if (module_exists('og_menu_single') && ($parent = node_load($pid)) && node_access('view', $parent) && ($mlid = og_menu_single_get_link_mlid('node', $pid))) {
            if (!isset($form['menu'])) {

              // If we got called before menu item was added, force it to be added now.
              og_menu_single_form_node_form_alter($form, $form_state);
            }
            $form['menu']['enabled']['#default_value'] = 1;
            $form['menu']['link']['parent']['#default_value'] = OG_MENU_SINGLE_MENU_NAME . ':' . $mlid;
          }
        }
        if (!empty($_GET['term_parent']) && ($term = taxonomy_term_load($_GET['term_parent']))) {

          // if using og_vocab, grab the valid vocab ids.
          $fieldname = '';
          $propname = '';
          if (module_exists('og_vocab')) {
            $vids = og_vocab_get_accessible_vocabs('node', $node->type, OG_VOCAB_FIELD);
            if (in_array($term->vid, $vids)) {
              $fieldname = 'og_vocabulary';
              $propname = 'target_id';
            }
          }
          if (empty($fieldname)) {

            // did not find og vocab, so check for global taxonomy reference fields
            $vocab = taxonomy_vocabulary_load($term->vid);
            $field_info = field_info_fields();
            $fields = field_info_instances('node', $node->type);
            foreach ($fields as $key => $field) {
              $info = $field_info[$key];
              if ($info['module'] == 'taxonomy') {
                foreach ($info['settings']['allowed_values'] as $index => $item) {
                  if ($item['vocabulary'] == $vocab->machine_name) {
                    $fieldname = $info['field_name'];
                    $propname = 'tid';
                    break;
                  }
                }
              }
            }
          }
          if (!empty($fieldname) && isset($form[$fieldname][LANGUAGE_NONE][0][$term->vid])) {
            if (is_array($form[$fieldname][LANGUAGE_NONE][0][$term->vid]['#default_value'])) {

              // Set default term when field is an array of ids.
              if (!in_array($term->tid, $form[$fieldname][LANGUAGE_NONE][0][$term->vid]['#default_value'])) {
                $form[$fieldname][LANGUAGE_NONE][0][$term->vid]['#default_value'][] = $term->tid;
              }
            }
            else {

              // Set default term when field is a string.
              if (strpos($form[$fieldname][LANGUAGE_NONE][0][$term->vid]['#default_value'], '(' . $term->tid . ')') === FALSE) {
                $form[$fieldname][LANGUAGE_NONE][0][$term->vid]['#default_value'] = $term->name . ' (' . $term->tid . ')';
                $form[$fieldname][LANGUAGE_NONE][0][$term->vid]['#init'][$term->tid] = $form[$fieldname][LANGUAGE_NONE][0][$term->vid]['#default_value'];
              }
            }
          }
        }
      }
    }
  }
}

/**
 * Submit handler for saving wiki node when a ?destination=xyz is set in the creation URL.
 * @param $form
 * @param $form_state
 */
function oa_files_redirect_submit($form, &$form_state) {
  if (!empty($form['#custom_redirect'])) {
    $options = drupal_parse_url($form['#custom_redirect']);
    $form_state['redirect'] = array(
      $options['path'],
      array(
        'query' => $options['query'],
        'fragment' => $options['fragment'],
      ),
    );
  }
}

Functions

Namesort descending Description
oa_files_addmenu_callback Ajax Callback for adding a new document within a menu (folder)
oa_files_addterm_callback Ajax Callback for adding a new taxonomy term (folder)
oa_files_admin_paths Implements hook_admin_paths().
oa_files_create_document Creates a document from a file.
oa_files_ctools_plugin_directory Implements hook_ctools_plugin_directory().
oa_files_ctools_test Test page callback to display add files ctools link.
oa_files_download_uri Return a file download link with token Copied from file_entity but we don't want to load a full file node
oa_files_find_document Find the document that may correspond to a given file.
oa_files_find_document_for_existing_document Find the documents that reference current file.
oa_files_form_alter Implements hook_form_alter().
oa_files_include_js Include JS.
oa_files_menu Implements hook_menu().
oa_files_menu_alter Implements hook_menu_alter().
oa_files_page_alter Implements hook_page_alter().
oa_files_prepare_files_from_files Helper function to create files array needed by angular app from an array of Drupal files
oa_files_redirect_submit Submit handler for saving wiki node when a ?destination=xyz is set in the creation URL.
oa_files_theme Implements hook_theme().
oa_files_update_document Update a document to a new file.
oa_files_upload_create_documents_form Form callback; Create multiple documents.
oa_files_upload_create_documents_form_page Page callback to return the create documents.
oa_files_upload_create_documents_form_submit Submit callback that creates or updates documents.
oa_files_upload_multi_load Load callback for %media_multi placeholder in menu paths.
template_preprocess_oa_files_dialog_page Add messages to the page.
_oa_files_get_redirect_options Helper function to get options for redirect.