You are here

class PartyPrimaryFields in Party 7

Helper class for primary fields.

Primary fields provide a means to cache data from potentially multiple data sets and sources into a single field on the party. This can then be used for searching, indexing etc.

An example of this is the party's label. Parties with different hats may have different data sets, for example an individual and organisation. While the individual's name is stored in a name field on the individual profile, the organisation's name could be stored in a text field on the organisation profile. The label primary fields can be set to pull from both and will run through all the potential sources until a valid (non-NULL) value has been found.

In addition, sources can use callbacks to deal with type conversion or rendering. For example, the User's UID has a callback that will convert a UID into the return from format_username().

Primary fields are configured from the 'Manage fields' page for a party. Some properties are provided, such as label and email and other may be added, either by other modules or through the Field UI.

To add a primary field through the Field UI, add a field of the desired type and use the 'Primary field' widget type. This will then allow you to select sources that match the target primary field's type.

Modules can add primary fields using hook_entity_property_info(). Any property with the key 'party primary field' set to TRUE will appear on the party's Manage fields page for configuration. Properties used as primary fields must have a 'setter callback' defined or an Exception will be thrown.

Modules wishing to configure primary fields on install should add their settings to the 'party_primary_fields' variable. See PartyPrimaryFields::$fields for the data structure used. Modules can also implement hook_party_primary_fields_fields_alter() to add primary fields from other sources or to override the configured settings for anything using the built in configuration.

Sources can be added by declaring a property on the party or a data set via hook_entity_property_info(). It is advised that 'type' is set for data type matching. There will need to be a 'getter callback', otherwise an Exception will be thrown.

Callbacks can be added to detected properties using hook_party_primary_fields_sources_alter(). See PartyPrimaryFields::$sources for the data structure.

Hierarchy

Expanded class hierarchy of PartyPrimaryFields

See also

hook_party_primary_fields_fields_alter()

hook_party_primary_fields_sources_alter()

party_field_extra_fields()

File

includes/party.primary_fields.inc, line 59
Primary field related functions and callbacks.

View source
class PartyPrimaryFields {

  /**
   * Cache of primary fields.
   * @var array
   *   An array of primary field information. Outer keys are target properties.
   *   Values are an array of sources each of which are an array of:
   *   - data_set: The data set name the property is on. 'party' is a special case
   *     which allows a party to refer to itself.
   *   - property: The property we are pulling from.
   *   - value: Optionally provide a sub-key of the property to use. The structure
   *     must be described with hook_entity_property_info().
   *   - callback: Optionally the key of a callback to use. The callback must be
   *     defined in the source's callbacks.
   *   - weight: The weight of this source. Lower weights are processed first.
   */
  protected static $fields;

  /**
   * Cache of primary field sources.
   * @var array
   *   An array of all the sources, grouped by data set. Outer keys are the data
   *   set name. Values are an array of:
   *   - All keys from self::$data_sets.
   *   - sources: An array of sources contained in this data set. Keys are
   *     an identifier (normally data_set_name:property[:value] who's values are
   *     arrays of:
   *     - label: The label of the property.
   *     - option label: The label and name of the property, suitable for options.
   *     - type: The data type as known by the entity property info.
   *     - field: Whether this is a field.
   *     - data_set: The data set this property is on.
   *     - property: The property on the data set entity.
   *     - value: The key of the structure of the property. If NULL, the property
   *       is taken as whole.
   *     - callbacks: Array of possible callbacks. Each one should have a unique
   *       key and it's value should be and array of:
   *       - label: Human readable label.
   *       - callback: A callable. It will receive the following arguments:
   *         - value: The value of the source field.
   *         - target: The name of the target property/field.
   *         - info: Metadata about the target property.
   *         - file: A file to include for the callback. This can either be a
   *           a string path relative to DRUPAL_ROOT or an array of (see
   *           module_load_include() arguments for key descriptions):
   *           - type
   *           - module
   *           - name
   *           A recommended location for callbacks is MODULE.party.inc.
   *       - type: The data type this callback returns.
   */
  protected static $sources;

  /**
   * Cache of data set info including our spoofed party.
   * @var array
   *   An array of data set info outer keyed by data set. Key/value pairs are:
   *   - set_name: The name of the data set. 'party' is a special case which
   *     allows a party to refer to itself.
   *   - entity type: The entity type of the data set.
   *   - entity bundle: The bundle of the data set entity.
   *   - label: The label of the data set.
   *   - option label: The label and name of the data set, suitable for options.
   */
  protected static $data_sets;

  /**
   * Clears the field and source cache.
   */
  public static function clearCaches() {

    // Clear our cache.
    cache_clear_all('party:primary_fields:', 'cache', TRUE);

    // Reset our statics.
    self::$fields = NULL;
    self::$sources = NULL;
  }

  /**
   * Get hold of primary field information.
   *
   * Primary fields are used to cache information from multiple potential data set
   * sources into a single property (or field) on the party.
   *
   * The Primary Field widget allows you to create primary fields via the Field UI
   * by adding fields to the party with the Primary Field widget.
   *
   * @param string $target
   *   Optionally provide a target property to retrieve the sources for.
   *
   * @return array
   *   If $target is NULL, outer keys are target properties. See
   *   PartyPrimaryFields::$primary_fields for a description of the structure.
   */
  public static function getFields($target = NULL) {
    if (!isset(self::$fields)) {
      self::buildFields();
    }
    if ($target) {
      return isset(self::$fields[$target]) ? self::$fields[$target] : array();
    }
    return self::$fields;
  }

  /**
   * Get hold of primary field source information.
   *
   * @param string $data_set
   *   Optionally provide a data set retrieve the sources for.
   *
   * @return FALSE||array
   *   Returns source information or FALSE if the requested information is not
   *   available. See PartyPrimaryFields::$sources for the data structure. If
   *   $property is given this will be a single source. Otherwise if $data_set
   *   is given it will be an array of sources. If $data_set is NULL, the entire
   *   source array will be returned.
   */
  public static function getSources($data_set = NULL) {
    if (!isset(self::$sources)) {
      self::buildSources();
    }

    // If no data set is given, return the whole lot.
    if (!isset($data_set)) {
      return self::$sources;
    }
    return isset(self::$sources[$data_set]) ? self::$sources[$data_set]['sources'] : FALSE;
  }

  /**
   * Get hold of primary field sources by type.
   *
   * @param string|array $types
   *   Either a single type or an array of types we want suitable sources for.
   * @param bool $all_types
   *   Indicate whether you want to check against the 'all types' key which
   *   includes callback types Defaults to TRUE.
   *
   * @return array
   *   An array of source information filtered by type. See
   *   PartyPrimaryFields::$sources for the data structure.
   */
  public static function getSourcesByType($types, $all_types = TRUE) {

    // Get our full list of sources.
    $sources = self::getSources();

    // Loop over our sources and remove items we don't want.
    foreach ($sources as &$data_set) {
      foreach ($data_set['sources'] as $key => $info) {
        if (!self::sourceTypeMatch($types, $info, $all_types)) {
          unset($data_set['sources'][$key]);
        }
      }
    }

    // Run our cleanup.
    self::cleanSources($sources);
    return $sources;
  }

  /**
   * Get the info of a particular source.
   *
   * @param string|array $source
   *   Either a data set name or a partial source info array for the required
   *   source. See PartyPrimaryFields::$sources for the data structure.
   *   'data_set' and 'property' are required.
   * @param string $property
   *   Optionally provide a property to retrieve the source info for. $data_set
   *   is required if $property is given. Only used if $source is a data set
   *   string.
   * @param string $value
   *   Optionally provide a value on a property to retrieve the source info for.
   *   $property is required if $value is given. Only used if $source is a data
   *   set string.
   *
   * @return FALSE||array
   *   The full source info for the given partial source or FALSE if not
   *   available.
   */
  public static function getSource($source, $property = NULL, $value = NULL) {
    if (is_string($source)) {
      $source = array(
        'data_set' => $source,
        'property' => $property,
        'value' => $value,
      );
    }

    // Get hold of sources on the data set.
    $sources = self::getSources($source['data_set']);
    if (!$sources) {
      return FALSE;
    }

    // Build our key for returning the source info.
    $key = self::getSourceKey($source);
    return isset($sources[$key]) ? $sources[$key] : FALSE;
  }

  /**
   * Build a key for a given source.
   *
   * @param array $source_info
   *   The source info for the required source. See PartyPrimaryFields::$sources
   *   for the data structure. 'data_set' and 'property' are required.
   * @param bool $ignore_value
   *   Optionally ignore the value key. This can be used to find the parent
   *   property of a source that uses a value key.
   *
   * @return string
   *   A key for the source property.
   */
  public static function getSourceKey($source_info, $ignore_value = FALSE) {

    // Get our information for the key in the right order.
    $key_info = array(
      'data_set' => $source_info['data_set'],
      'property' => $source_info['property'],
    );
    if (!$ignore_value && $source_info['value']) {
      $key_info['value'] = $source_info['value'];
    }

    // Build and return our key.
    return implode(':', $key_info);
  }

  /**
   * Retrieve property information for a specific entity/bundle.
   *
   * @param string $entity_type
   *   The entity type we want information for.
   * @param string $bundle
   *   The bundle we want information for.
   * @param string $property
   *   Optionally only return information for a specific proprety.
   *
   * @return FALSE|array
   *   FALSE if the requested information is not available. If $property is
   *   given, the metadata for that property, otherwise an array of property
   *   metadata keyed by property.
   */
  public static function getPropertyInfo($entity_type, $bundle, $property = NULL) {
    $entity = entity_create_stub_entity($entity_type, array(
      0 => NULL,
      2 => $bundle,
    ));
    $wrapper = entity_metadata_wrapper($entity_type, $entity);
    $info = array();
    foreach (array_keys($wrapper
      ->getPropertyInfo()) as $key) {
      $info[$key] = $wrapper
        ->getPropertyInfo($key);
    }
    if ($property) {
      return isset($info[$property]) ? $info[$property] : FALSE;
    }
    else {
      return $info;
    }
  }

  /**
   * Check whether the types match.
   *
   * @param string|array $types
   *   Either a single type or an array of types we want suitable sources for.
   * @param array $source
   *   The source info for the source we are checking. See
   *   PartyPrimaryFields::$sources for the data structure.
   * @param bool $all_types
   *   Indicate whether you want to check against the 'all types' key which
   *   includes callback types. Defaults to TRUE.
   *
   * @return bool
   *   Whether the source matches the given type(s).
   */
  public static function sourceTypeMatch($types, $source, $all_types = TRUE) {

    // Make sure $types is an array.
    $types = (array) $types;

    // If $all_types we want to check the 'all types' key which is an array.
    if ($all_types) {
      return (bool) array_intersect($types, $source['all types']);
    }
    else {
      return in_array($source['type'], $types);
    }
  }

  /**
   * Get data set info including the spoofed party.
   *
   * @param string $data_set
   *   Optionally return the info for a single data set.
   *
   * @return FALSE|array
   *   Data set info array. If $data_set is not given, it is outer keyed by data
   *   set name. If it is set and it is not available, FALSE is returned.
   */
  public static function getDataSetInfo($data_set = NULL) {
    if (!isset(self::$data_sets)) {
      self::$data_sets = array(
        'party' => array(
          'set_name' => 'party',
          'label' => 'Party',
          'entity type' => 'party',
          'entity bundle' => 'party',
        ),
      );
      self::$data_sets += party_get_data_set_info();
    }
    if ($data_set) {
      return isset(self::$data_sets[$data_set]) ? self::$data_sets[$data_set] : FALSE;
    }
    return self::$data_sets;
  }

  /**
   * Execute a callback on a value.
   */
  public static function executeCallback($value, $source, $target) {

    // Check we want to execute callback.
    if (isset($source['callback'])) {

      // Get our source info and check the callback exists.
      $source_info = self::getSource($source);
      if (isset($source_info['callbacks'][$source['callback']])) {

        // Get the callback info.
        $callback = $source_info['callbacks'][$source['callback']];

        // Load an include if necessary.
        if (isset($callback['file'])) {
          if (is_array($callback['file'])) {
            module_load_include($callback['file']['type'], $callback['file']['module'], $callback['file']['name']);
          }
          else {
            require_once DRUPAL_ROOT . '/' . $callback['file'];
          }
        }

        // If the callback is valid, execute it.
        if (is_callable($callback['callback'])) {
          $target_info = self::getPropertyInfo('party', 'party', $target);
          $value = call_user_func($callback['callback'], $value, $target, $target_info, $source_info);
        }
      }
    }
    return $value;
  }

  /**
   * Set up a source form under the given element.
   *
   * This is typically called on a fieldset.
   *
   * @param array $element
   *   The container or fieldset element or form we are adding the source table
   *   to. In addition to it's normal keys, this element should have:
   *   - #target: The name of the target property.
   *   - #source_types: Optionally provide a filter for source types. If not
   *     provided it will be worked out from the given target property.
   *   - #parents: As this function does not deal with any submission of the
   *     user's input, #parents should be set to indicate where the submitted
   *     data should appear in $form_state['values']. If not set, array() will
   *     be used resulting in $form_state['values'] having 'sources' as a root
   *     key.
   * @param array $form_state
   *   The form state.
   * @param array $form
   *   The whole form.
   */
  public static function sourceForm(&$element, &$form_state, &$form) {

    // Set up our include and submission handler.
    form_load_include($form_state, 'inc', 'party', 'party.admin');
    $form['#submit'][] = 'party_primary_fields_clear_caches';

    // Make sure the element has the required properties.
    $element['#tree'] = TRUE;
    if (!isset($element['#parents'])) {
      $element['#parents'] = array();
    }

    // Get hold of info about the target.
    if (!array_key_exists('#source_types', $element)) {
      $target_info = self::getPropertyInfo('party', 'party', $element['#target']);
      $element['#source_types'] = isset($target_info['type']) ? array(
        $target_info['type'],
      ) : NULL;
    }
    elseif (is_string($element['#source_types'])) {
      $element['#source_types'] = (array) $element['#source_types'];
    }

    // Get hold of the current state of the sources.
    if (isset($form_state['values'])) {
      $sources = drupal_array_get_nested_value($form_state['values'], $element['#parents']);
    }
    if (!isset($sources) || !is_array($sources)) {
      $sources = $element['#default_value'];
    }

    // Make sure the sources are sorted by weight.
    uasort($sources, 'drupal_sort_weight');

    // Construct our draggable table.
    $element['table'] = array(
      '#theme' => 'table',
      '#header' => array(
        'property_desc' => t('Property'),
        'data_set_desc' => t('Data set'),
        'callback' => t('Callback'),
        'weight' => t('Weight'),
        'remove' => t('Remove'),
      ),
      '#empty' => t('No sources are selects.'),
      '#attributes' => array(
        'class' => array(
          'field-ui-overview',
        ),
        'id' => 'field-sources',
      ),
      '#parents' => $element['#parents'],
      '#pre_render' => array(
        'party_primary_fields_source_table_pre_render',
      ),
    );
    drupal_add_tabledrag('field-sources', 'order', 'sibling', 'source-weight');

    // Build our rows which will be put into the table after building.
    foreach ($sources as $key => $source) {

      // Get hold of our source info.
      $data_set_info = self::getDataSetInfo($source['data_set']);
      $source_info = self::getSource($source);
      $property_key = self::getSourceKey($source);
      $property_key = substr($property_key, strpos($property_key, ':') + 1);
      $row = array(
        '#element_validate' => array(
          'party_primary_fields_source_table_source_cleanup',
        ),
        'data_set' => array(
          '#type' => 'value',
          '#value' => $source['data_set'],
        ),
        'property' => array(
          '#type' => 'value',
          '#value' => $source['property'],
        ),
        'value' => array(
          '#type' => 'value',
          '#value' => $source['value'],
        ),
        'property_desc' => array(
          '#markup' => format_string('@label <small>[@name]</small>', array(
            '@label' => $source_info['label'],
            '@name' => $property_key,
          )),
        ),
        'data_set_desc' => array(
          '#markup' => format_string('@label <small>[@name]</small>', array(
            '@label' => $data_set_info['label'],
            '@name' => $data_set_info['set_name'],
          )),
        ),
        'weight' => array(
          '#type' => 'weight',
          '#default_value' => $source['weight'],
          '#delta' => 50,
          '#title_display' => 'invisible',
          '#title' => t('Weight for @label', array(
            '@label' => $source_info['label'],
          )),
          '#attributes' => array(
            'class' => array(
              'source-weight',
            ),
          ),
        ),
        'callback' => array(),
        'remove' => array(
          '#type' => 'submit',
          '#value' => t('Remove'),
          '#name' => 'remove_source:' . $key,
          '#submit' => array(
            'party_primary_fields_source_table_submit',
          ),
        ),
      );

      // Find any valid callbacks.
      $callbacks = array();
      if (!empty($source_info['callbacks'])) {
        foreach ($source_info['callbacks'] as $key => $info) {
          if (!isset($element['#source_types']) || in_array($info['type'], $element['#source_types'])) {
            $callbacks[$key] = $info['label'];
          }
        }
      }

      // If we have valid callbacks, provide options.
      $row['callback'] = array(
        '#type' => 'select',
        '#title' => t('Callback'),
        '#title_display' => 'invisible',
        '#options' => $callbacks,
        '#default_value' => isset($source['callback']) ? $source['callback'] : NULL,
      );

      // If the source is valid on it's own, provide an empty option.
      if (empty($callbacks) || !isset($element['#source_types']) || in_array($source_info['type'], $element['#source_types'])) {
        $row['callback']['#empty_option'] = t('No callback');
      }
      $element['table'][$key] = $row;
    }

    // Find suitable sources.
    $suitable_sources = PartyPrimaryFields::getSourcesByType($element['#source_types']);

    // Build our options list.
    $options = array();
    foreach ($suitable_sources as $data_set) {
      $set_options = array();
      foreach ($data_set['sources'] as $source) {
        $key = $source['data_set'] . ':' . $source['property'];
        if (isset($source['value'])) {
          $key .= ':' . $source['value'];
        }
        $set_options[$key] = $source['option label'];
      }
      $options[$data_set['option label']] = $set_options;
    }
    $element['add_source'] = array(
      '#type' => 'container',
      '#tree' => FALSE,
      '#weight' => 99,
      '#attributes' => array(
        'class' => array(
          'container-inline',
        ),
      ),
      'add_source_property' => array(
        '#type' => 'select',
        '#title' => t('Source property'),
        '#options' => $options,
        '#empty_option' => ' - ' . t('Select property') . ' - ',
      ),
      'add_source_submit' => array(
        '#type' => 'submit',
        '#value' => t('Add source'),
        '#limit_validation_errors' => array(
          array(
            'add_source_property',
          ),
          $element['#parents'],
        ),
        '#validate' => array(
          'party_primary_fields_source_table_validate',
        ),
        '#submit' => array(
          'party_primary_fields_source_table_submit',
        ),
      ),
    );
  }

  /**
   * Build the primary field information.
   *
   * @param bool $reset
   *   Whether the cache should be reset.
   */
  protected static function buildFields($reset = FALSE) {

    // If we are resetting, clear our static cache.
    if ($reset) {
      self::$fields = NULL;
    }
    else {
      if ($cache = cache_get('party:primary_fields:fields')) {
        self::$fields = $cache->data;
      }
    }

    // If we have no information, build it.
    if (!isset(self::$fields)) {

      // Label and email are provided by custom UIs and stored in a variable which
      // other modules could potentially add to.
      self::$fields = variable_get('party_primary_fields', array());

      // Retrieve from primary field widgets.
      foreach (field_info_instances('party', 'party') as $instance) {
        if ($instance['widget']['type'] == 'party_primary_field') {
          self::$fields[$instance['field_name']] = $instance['widget']['settings']['sources'];
        }
      }

      // Allow other modules to alter it.
      drupal_alter('party_primary_fields_fields', self::$fields);

      // Remove any invalid targets.
      $party_property_info = self::getPropertyInfo('party', 'party');
      foreach (array_keys(self::$fields) as $target) {
        if (!isset($party_property_info[$target])) {

          // Remove and log a watchdog warning.
          watchdog('party', 'The target for the primary field %target does not exist.', array(
            '%target' => $target,
          ), WATCHDOG_WARNING);
          unset(self::$fields[$target]);
        }
      }

      // Make sure the sources are valid and sorted by weight.
      $valid_sources = self::getSources();
      foreach (self::$fields as $target => &$sources) {

        // If we don't have any sources, skip it all.
        if (!is_array($sources)) {
          unset(self::$fields[$target]);
          continue;
        }

        // Remove any invalid sources.
        foreach ($sources as $key => &$source) {

          // Make sure our sources have all the keys.
          $source += array(
            'data_set' => NULL,
            'property' => NULL,
            'value' => NULL,
            'callback' => NULL,
            'weight' => 0,
          );

          // Check that the data set exists.
          if (!isset($valid_sources[$source['data_set']])) {
            watchdog('party', 'The source data set %data_set for the primary field %target does not exist.', array(
              '%data_set' => $source['data_set'],
              '%target' => $target,
            ), WATCHDOG_WARNING);
            unset($sources[$key]);
            continue;
          }

          // Check that the property exists.
          $source_key = self::getSourceKey($source, TRUE);
          if (!isset($valid_sources[$source['data_set']]['sources'][$source_key])) {
            watchdog('party', 'The source property %key for the primary field %target does not exist.', array(
              '%key' => $key,
              '%target' => $target,
            ), WATCHDOG_WARNING);
            unset($sources[$key]);
            continue;
          }
          $source_key = self::getSourceKey($source);
          if (!isset($valid_sources[$source['data_set']]['sources'][$source_key])) {
            watchdog('party', 'The source property %key for the primary field %target does not exist. Falling back to %property.', array(
              '%key' => $key,
              '%target' => $target,
              '%property' => $source['property'],
            ), WATCHDOG_WARNING);
            $sources[$key]['value'] = NULL;
            continue;
          }
        }

        // Sort the sources.
        uasort($sources, 'drupal_sort_weight');
      }
    }

    // Store our information to the cache.
    cache_set('party:primary_fields:fields', self::$fields);
  }

  /**
   * Build the primary field source information.
   *
   * @param bool $reset
   *   Whether the cache should be reset.
   */
  protected static function buildSources($reset = FALSE) {

    // If we are resetting, clear our static cache.
    if ($reset) {
      self::$sources = NULL;
    }
    else {
      if ($cache = cache_get('party:primary_fields:sources')) {
        self::$sources = $cache->data;
      }
    }

    // If we have no information, build it.
    if (!isset(self::$sources)) {
      $field_map = field_info_field_map();
      self::$sources = array();

      // Go over our data sets finding potential sources.
      foreach (self::getDataSetInfo() as $data_set_name => $data_set) {

        // Build our data set information.
        self::$sources[$data_set_name] = array(
          'set_name' => $data_set['set_name'],
          'entity type' => $data_set['entity type'],
          'entity bundle' => $data_set['entity bundle'],
          'label' => $data_set['label'],
          'option label' => "{$data_set['label']} ({$data_set['set_name']})",
          'sources' => array(),
        );

        // Go over our property info to get the sources.
        $property_info = self::getPropertyInfo($data_set['entity type'], $data_set['entity bundle']);
        foreach ($property_info as $property => $info) {

          // Build our source info.
          $source_info = array(
            'label' => $info['label'],
            'option label' => "{$info['label']} ({$property})",
            'type' => isset($info['type']) ? $info['type'] : NULL,
            'field_type' => NULL,
            'data_set' => $data_set_name,
            'property' => $property,
            'value' => NULL,
            'callbacks' => array(),
            'all types' => array(),
          );

          // If this is a field we store the field type.
          if (!empty($info['field'])) {
            if (isset($field_map[$property])) {
              $source_info['field_type'] = $field_map[$property]['type'];
            }
          }

          // Get the key and add it to the data set sources.
          $key = self::getSourceKey($source_info);
          self::$sources[$data_set_name]['sources'][$key] = $source_info;

          // Process any values within this property.
          if (isset($info['property info'])) {
            foreach ($info['property info'] as $value => $value_info) {

              // Build our source info.
              $source_info = array(
                'label' => "{$info['label']}: {$value_info['label']}",
                'option label' => "{$info['label']}: {$value_info['label']} ({$property}:{$value})",
                'type' => isset($value_info['type']) ? $value_info['type'] : NULL,
                'field_type' => NULL,
                'data_set' => $data_set_name,
                'property' => $property,
                'value' => $value,
                'callbacks' => array(),
                'all types' => array(),
              );

              // Get the key and add it to the data set sources.
              $key = self::getSourceKey($source_info);
              self::$sources[$data_set_name]['sources'][$key] = $source_info;
            }
          }
        }
      }

      // Allow other modules to alter sources.
      drupal_alter('party_primary_fields_sources', self::$sources);

      // Run our cleanup.
      self::cleanSources(self::$sources);
    }

    // Store our information to the cache.
    cache_set('party:primary_fields:sources', self::$sources);
  }

  /**
   * Clean up source information.
   *
   * Calculate the 'all types' key for properties and removing empty data sets.
   */
  protected static function cleanSources(&$sources) {
    foreach ($sources as $data_set_name => &$data_set) {

      // Remove empty data sets.
      if (empty($data_set['sources'])) {
        unset($sources[$data_set_name]);
        continue;
      }

      // Build a list of all types including callbacks.
      foreach ($sources[$data_set_name]['sources'] as &$source) {

        // Make sure our basic type is included.
        $source['all types'][] = $source['type'];

        // Add any callback types.
        foreach ($source['callbacks'] as $callback) {
          $source['all types'][] = $callback['type'];
        }

        // Filter the list and map it.
        $source['all types'] = drupal_map_assoc(array_unique($source['all types']));
      }
    }
  }

}

Members

Namesort descending Modifiers Type Description Overrides
PartyPrimaryFields::$data_sets protected static property Cache of data set info including our spoofed party. An array of data set info outer keyed by data set. Key/value pairs are:
PartyPrimaryFields::$fields protected static property Cache of primary fields. An array of primary field information. Outer keys are target properties. Values are an array of sources each of which are an array of:
PartyPrimaryFields::$sources protected static property Cache of primary field sources. An array of all the sources, grouped by data set. Outer keys are the data set name. Values are an array of:
PartyPrimaryFields::buildFields protected static function Build the primary field information.
PartyPrimaryFields::buildSources protected static function Build the primary field source information.
PartyPrimaryFields::cleanSources protected static function Clean up source information.
PartyPrimaryFields::clearCaches public static function Clears the field and source cache.
PartyPrimaryFields::executeCallback public static function Execute a callback on a value.
PartyPrimaryFields::getDataSetInfo public static function Get data set info including the spoofed party.
PartyPrimaryFields::getFields public static function Get hold of primary field information.
PartyPrimaryFields::getPropertyInfo public static function Retrieve property information for a specific entity/bundle.
PartyPrimaryFields::getSource public static function Get the info of a particular source.
PartyPrimaryFields::getSourceKey public static function Build a key for a given source.
PartyPrimaryFields::getSources public static function Get hold of primary field source information.
PartyPrimaryFields::getSourcesByType public static function Get hold of primary field sources by type.
PartyPrimaryFields::sourceForm public static function Set up a source form under the given element.
PartyPrimaryFields::sourceTypeMatch public static function Check whether the types match.