diff sites/all/modules/entityreference_prepopulate/entityreference_prepopulate.module @ 4:ce11bbd8f642

added modules
author danieleb <danielebarchiesi@me.com>
date Thu, 19 Sep 2013 10:38:44 +0100
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sites/all/modules/entityreference_prepopulate/entityreference_prepopulate.module	Thu Sep 19 10:38:44 2013 +0100
@@ -0,0 +1,429 @@
+<?php
+
+/**
+ * @file
+ * Prepopulate entity reference values from URL.
+ */
+
+/**
+ * Implements hook_ctools_plugin_directory().
+ */
+function entityreference_prepopulate_ctools_plugin_directory($module, $plugin) {
+  if ($module == 'entityreference' || $module == 'ctools') {
+    return 'plugins/' . $plugin;
+  }
+}
+
+/**
+ * Implements hook_field_create_instance().
+ *
+ * Add "default value function" setting to the field instance.
+ * We have to do it from this hook, as we don't have another chance of setting
+ * this option via the hook_field_info().
+ */
+function entityreference_prepopulate_field_create_instance($instance) {
+  if (empty($instance['settings']['behaviors']['prepopulate']['status'])) {
+    return;
+  }
+
+  $instance['default_value_function'] = 'entityreference_prepopulate_field_default_value';
+  field_update_instance($instance);
+}
+
+/**
+ * Implements hook_field_update_instance().
+ */
+function entityreference_prepopulate_field_update_instance($instance, $prior_instance) {
+  if (empty($instance['settings']['behaviors']['prepopulate'])) {
+    return;
+  }
+  if (isset($prior_instance['settings']['behaviors']['prepopulate']['status']) && $instance['settings']['behaviors']['prepopulate']['status'] == $prior_instance['settings']['behaviors']['prepopulate']['status']) {
+    // Nothing changed.
+    return;
+  }
+
+  $instance['default_value_function'] = !empty($instance['settings']['behaviors']['prepopulate']['status']) ? 'entityreference_prepopulate_field_default_value' : '';
+  field_update_instance($instance);
+}
+
+
+/**
+ * Implements hook_field_attach_form().
+ */
+function entityreference_prepopulate_field_attach_form($entity_type, $entity, &$form, &$form_state, $langcode) {
+  list($id,,$bundle) = entity_extract_ids($entity_type, $entity);
+
+  if (!empty($form_state['triggering_element']['#ajax'])) {
+    // We are inside AJAX, so values can't be taken from URL at the
+    // moment.
+    return;
+  }
+
+  // Check if there is a field that needs to be prepopulated attached to the
+  // given entity.
+  $found = FALSE;
+  foreach (field_info_instances($entity_type, $bundle) as $instance) {
+    if (!empty($instance['settings']['behaviors']['prepopulate']['status'])) {
+      $found = TRUE;
+      break;
+    }
+  }
+
+  if (!$found) {
+    return;
+  }
+
+  foreach (element_children($form_state['field']) as $field_name) {
+    foreach ($form_state['field'][$field_name] as $lang => $value) {
+      $instance = $value['instance'];
+      if (empty($instance['settings']['behaviors']['prepopulate']['status'])) {
+        continue;
+      }
+      $settings = $instance['settings']['behaviors']['prepopulate'];
+
+      if ((!empty($settings['skip_perm']) && user_access($settings['skip_perm'])) || ($id && empty($settings['action_on_edit']))) {
+        // User has access to skip the action, or the entity is already
+        // saved, but "Apply action on edit", is disabled.
+        continue;
+      }
+
+      $field = $value['field'];
+
+      // Store prepopulated values in the form state to make them persistent,
+      // in case the form is rebuilt by AJAX requests.
+      $field_name = $field['field_name'];
+
+      if ($ids = entityreference_prepopulate_get_values($field, $instance)) {
+        $form_state['entityreference_prepopulate'][$instance['entity_type']][$instance['bundle']][$field_name] = $ids;
+      }
+
+      if ($ids || ($id && !empty($settings['action_on_edit']))) {
+        // New entity with prepopualte values, or an existing entity,
+        // we might need to disable/ hide the group-audience field.
+        if ($settings['action'] == 'disable') {
+          $form[$field_name][$lang]['#disabled'] = TRUE;
+        }
+        elseif ($settings['action'] == 'hide') {
+          // We don't hide the field via hook_field_access(), as the
+          // default value won't be set.
+          $form[$field_name]['#access'] = FALSE;
+        }
+      }
+      elseif (in_array($settings['fallback'], array('form_error', 'redirect'))) {
+        $message = t('Field @label must be populated via URL.', array('@label' => $instance['label']));
+        if ($settings['fallback'] == 'form_error') {
+          form_error($form, $message);
+        }
+        elseif ($settings['fallback'] == 'redirect') {
+          drupal_set_message($message, 'notice');
+          drupal_goto();
+        }
+      }
+    }
+  }
+}
+
+/**
+ * Implements hook_field_access().
+ */
+function entityreference_prepopulate_field_access($op, $field, $entity_type, $entity, $account) {
+  if ($op != 'edit' || $field['type'] != 'entityreference') {
+    return;
+  }
+
+  if (empty($entity)) {
+    // $entity might be NULL, so return early.
+    // @see field_access().
+    return;
+  }
+
+  list($id,,$bundle) = entity_extract_ids($entity_type, $entity);
+  if ($id) {
+    // Entity is already saved.
+    return;
+  }
+
+  $instance = field_info_instance($entity_type, $field['field_name'], $bundle);
+  if (empty($instance['settings']['behaviors']['prepopulate']['status'])) {
+    return;
+  }
+
+  $settings = $instance['settings']['behaviors']['prepopulate'];
+  if (!empty($settings['skip_perm']) && user_access($settings['skip_perm'])) {
+    return;
+  }
+  $ids = entityreference_prepopulate_get_values($field, $instance);
+
+  if (!$ids && $settings['fallback'] == 'hide') {
+    return FALSE;
+  }
+}
+
+/**
+ * Field default value callback.
+ *
+ * Set the default from the URL context. This works even if the widget is
+ * not shown, e.g. due to restricted field access.
+ *
+ * @todo Check field cardinality.
+ */
+function entityreference_prepopulate_field_default_value($entity_type, $entity, $field, $instance, $langcode) {
+  $items = array();
+  if ($ids = entityreference_prepopulate_get_values($field, $instance)) {
+    $items = array();
+    foreach ($ids as $id) {
+      $items[] = array('target_id' => $id);
+    }
+  }
+  return $items;
+}
+
+/**
+ * Wrapper function to get context (e.g. from URL or OG-context).
+ *
+ * @param $entity_type
+ *   The entity type the entity.
+ * @param $entity
+ *   The entity object that is being checked.
+ * @param $field
+ *   The field info array.
+ * @param $instance
+ *   The instance info array.
+ * @param $validate
+ *   Determine if access validation should be performed. Defaults to TRUE.
+ *
+ * @return
+ *   Array of IDs a user may view.
+ */
+function entityreference_prepopulate_get_values($field, $instance, $validate = TRUE) {
+  if (!$instance['settings']['behaviors']['prepopulate']['status']) {
+    // Do nothing when prepopulate is disabled for this field.
+    return;
+  }
+
+  $field_name = $field['field_name'];
+
+  $cache = &drupal_static(__FUNCTION__, array());
+  $identifier = array(
+    $instance['entity_type'],
+    $instance['bundle'],
+    $field_name,
+    $validate,
+  );
+
+  if (module_exists('og') && og_is_group_audience_field($field_name)) {
+    if (empty($instance['field_mode'])) {
+      // Group audience field, but no field-mode provided.
+      // So we iterate over the "default" and possibly "admin" field-modes,
+      // and return those values together.
+      $ids = array();
+      $field_modes = !user_access('administer group') ? array('default') : array('default', 'admin');
+      foreach ($field_modes as $field_mode) {
+        $instance['field_mode'] = $field_mode;
+        if ($og_ids = entityreference_prepopulate_get_values($field, $instance)) {
+          $ids = array_merge($ids, $og_ids);
+        }
+      }
+
+      // Return the values.
+      return $ids;
+    }
+
+    $identifier[] = $instance['field_mode'];
+  }
+
+  $identifier = implode(':', $identifier);
+
+  if (isset($cache[$identifier])) {
+    return $cache[$identifier];
+  }
+
+  $cache[$identifier] = $ids = array();
+
+  // Check if we have cached values.
+  if (!$ids) {
+    $ids = entityreference_prepopulate_get_values_from_cache($field, $instance);
+  }
+
+  // Check if we have OG-context integration.
+  if (!$ids) {
+    $ids = entityreference_prepopulate_get_values_from_og_context($field, $instance);
+  }
+
+  // Check if there are values in the URL.
+  if (!$ids) {
+    $ids = entityreference_prepopulate_get_values_from_url($field, $instance);
+  }
+
+  if (!$ids || !$validate) {
+    // No IDs found, or no validation is needed.
+    $cache[$identifier] = $ids;
+    return $ids;
+  }
+
+  $handler = entityreference_get_selection_handler($field, $instance);
+  if (!$ids = $handler->validateReferencableEntities($ids)) {
+    $cache[$identifier] = FALSE;
+    return;
+  }
+
+  // Check access to the provided entities.
+  $target_type = $field['settings']['target_type'];
+  entity_load($target_type, $ids);
+  foreach ($ids as $delta => $id) {
+    $entity = entity_load_single($target_type, $id);
+    if (!$entity || !entity_access('view', $target_type, $entity)) {
+      unset($ids[$delta]);
+    }
+  }
+
+  $cache[$identifier] = $ids;
+  return $ids;
+}
+
+/**
+ * Get the values from the cached form.
+ *
+ * @param $field
+ *   The field info array.
+ * @param $instance
+ *   The instance info array.
+ *
+ * @see
+ *   entityreference_prepopulate_get_values()
+ */
+function entityreference_prepopulate_get_values_from_cache($field, $instance) {
+  // Try to get the form out of cache.
+  if (!$form_build_id = isset($_GET['form_build_id']) ? $_GET['form_build_id'] : isset($_POST['form_build_id']) ? $_POST['form_build_id'] : NULL) {
+    return;
+  }
+
+  $field_name = $field['field_name'];
+
+  $form_state = array();
+  form_get_cache($form_build_id, $form_state);
+
+  // If successful, get the value from the form_state.
+  return isset($form_state['entityreference_prepopulate'][$instance['entity_type']][$instance['bundle']][$field_name]) ? $form_state['entityreference_prepopulate'][$instance['entity_type']][$instance['bundle']][$field_name] : FALSE;
+}
+
+/**
+ * Get values for prepopulating fields via URL.
+ *
+ * @param $field
+ *   The field info array.
+ * @param $instance
+ *   The instance info array.
+ *
+ * @see
+ *   entityreference_prepopulate_get_values()
+ */
+function entityreference_prepopulate_get_values_from_url($field, $instance) {
+  $field_name = $field['field_name'];
+  if (!empty($_GET[$field_name]) && is_string($_GET[$field_name])) {
+    return explode(',', $_GET[$field_name]);
+  }
+}
+
+
+/**
+ * Get values for prepopulating fields OG-context.
+ *
+ * @param $field
+ *   The field info array.
+ * @param $instance
+ *   The instance info array.
+ *
+ * @see
+ *   entityreference_prepopulate_get_values()
+ */
+function entityreference_prepopulate_get_values_from_og_context($field, $instance) {
+  $field_name = $field['field_name'];
+
+  if (!module_exists('og_context') || !og_is_group_audience_field($field_name) || !$og_context = og_context()) {
+    return;
+  }
+
+  if ($og_context['group_type'] != $field['settings']['target_type']) {
+    // Context is of invalid group-type.
+    return;
+  }
+
+  return array($og_context['gid']);
+}
+
+
+/**
+ * Return a form element with crafted links to create nodes for a group.
+ *
+ * @param $entity_type
+ *   The entity type of the referenced entity.
+ * @param $entity_id
+ *   The entity ID of the referenced entity.
+ * @param $destination
+ *   Optional; The destination after a node is created. Defaults to the
+ *   destination passed in the URL if exists, otherwise back to the current
+ *   page.
+ * @param $types
+ *   Optional; An array of type names. Restrict the created links to the given
+ *   types.
+ */
+function entityreference_prepopulate_create_node_links($entity_type, $entity_id, $field_name, $destination = NULL, $types = NULL) {
+  $wrapper = entity_metadata_wrapper($entity_type, $entity_id);
+  $field = field_info_field($field_name);
+
+  $entity = entity_load_single($entity_type, $entity_id);
+  list(,, $bundle) = entity_extract_ids($entity_type, $entity);
+
+  $types = isset($types) ? $types : array_keys(node_type_get_types());
+  $names = array();
+  foreach ($types as $type_name) {
+    if ($field['settings']['target_type'] != $entity_type) {
+      // The entity type isn't referenced by the field.
+      continue;
+    }
+
+    if (!empty($field['settings']['handler_settings']['target_bundles']) && !in_array($bundle, $field['settings']['handler_settings']['target_bundles'])) {
+      // The entity bundle isn't referenced by the field.
+      continue;
+    }
+
+    $instance = field_info_instance('node', $field_name, $type_name);
+    if (empty($instance['settings']['behaviors']['prepopulate']['status'])) {
+      // The field doesn't exist on the node type, or doesn't have prepopulate
+      // enabled.
+      continue;
+    }
+
+    if (!node_access('create', $type_name)) {
+      continue;
+    }
+
+    $names[$type_name] = node_type_get_name($type_name);
+  }
+
+  if (empty($names)) {
+    return;
+  }
+
+  // Sort names.
+  asort($names);
+
+  // Build links.
+  $options = array(
+    'query' => array($field_name => $entity_id) + drupal_get_destination(),
+  );
+
+  $items = array();
+  foreach ($names as $type => $name) {
+    $items[] = array('data' => l($name, 'node/add/' . str_replace('_', '-', $type), $options));
+  }
+
+  $element = array();
+  $element['entityreference_prepopulate'] = array(
+    '#theme' => 'item_list',
+    '#items' => $items,
+  );
+
+  return $element;
+}