Mercurial > hg > rr-repo
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; +}