Mercurial > hg > rr-repo
view 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 source
<?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; }