View source  
  <?php
module_load_include('inc', 'eck', 'eck.classes');
function eck__bundle__menu($entity_type) {
  
  $path = eck__entity_type__path();
  $menu = array();
  
  $menu["{$path}/{$entity_type->name}/edit"] = array(
    'title' => "Edit",
    'description' => "Edit the '{$entity_type->label}' entity type",
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      "eck__entity_type__form",
      $entity_type->name,
    ),
    'access callback' => 'eck_access',
    'access arguments' => array(
      'update',
      'entity_type',
      $entity_type,
    ),
    'file' => 'eck.entity_type.inc',
    'type' => MENU_LOCAL_TASK,
    'weight' => 2,
  );
  
  $menu["{$path}/{$entity_type->name}/delete"] = array(
    'title' => "Delete",
    'description' => "Delete the '{$entity_type->label}' Entity Type",
    
    'page callback' => "drupal_get_form",
    'page arguments' => array(
      "eck__entity_type__delete_form",
      $entity_type->name,
    ),
    'access callback' => 'eck_access',
    'access arguments' => array(
      "delete",
      "entity_type",
      $entity_type,
    ),
    'file' => 'eck.entity_type.inc',
    'type' => MENU_LOCAL_TASK,
    'weight' => 3,
  );
  
  $menu["{$path}/{$entity_type->name}/property"] = array(
    'title' => "Manage properties",
    'description' => "Manage the properties of the {$entity_type->label} entity type",
    'page callback' => "eck__properties",
    'page arguments' => array(
      $entity_type->name,
    ),
    'access callback' => 'eck_access',
    'access arguments' => array(
      "update",
      "property",
    ),
    'file' => 'eck.properties.inc',
    'type' => MENU_LOCAL_TASK,
    'weight' => 4,
  );
  
  $menu["{$path}/{$entity_type->name}/property/add"] = array(
    'title' => "Add property",
    'description' => "Add a property of the {$entity_type->label} entity type",
    'page callback' => "drupal_get_form",
    'page arguments' => array(
      "eck__property_add__form",
      $entity_type->name,
    ),
    'access callback' => 'eck_access',
    'access arguments' => array(
      "update",
      "property",
    ),
    'file' => 'eck.properties.inc',
    'type' => MENU_LOCAL_ACTION,
    'weight' => 4,
  );
  
  $menu["{$path}/{$entity_type->name}/property/%/activate"] = array(
    'title' => "Activate default property",
    'page callback' => "eck__activate_default_property",
    'page arguments' => array(
      $entity_type->name,
      5,
    ),
    'access callback' => 'eck_access',
    'access arguments' => array(
      "update",
      "property",
    ),
    'file' => 'eck.default_properties.inc',
  );
  
  $menu["{$path}/{$entity_type->name}/property/%/deactivate"] = array(
    'title' => "Activate default property",
    'page callback' => "eck__deactivate_default_property",
    'page arguments' => array(
      $entity_type->name,
      5,
    ),
    'access callback' => 'eck_access',
    'access arguments' => array(
      "update",
      "property",
    ),
    'file' => 'eck.default_properties.inc',
  );
  
  $menu["{$path}/{$entity_type->name}/property/%/edit"] = array(
    'title' => "Edit property",
    'description' => "Edit a property of the {$entity_type->label} entity type",
    'page callback' => "drupal_get_form",
    'page arguments' => array(
      "eck__property_edit__form",
      $entity_type->name,
      5,
    ),
    'access callback' => 'eck_access',
    'access arguments' => array(
      "update",
      "property",
    ),
    'file' => 'eck.properties.inc',
  );
  
  $menu["{$path}/{$entity_type->name}/property/%/delete"] = array(
    'title' => "Delete property",
    'description' => "Delete a property of the {$entity_type->label} entity type",
    'page callback' => "drupal_get_form",
    'page arguments' => array(
      "eck__property_delete__form",
      $entity_type->name,
      5,
    ),
    'access callback' => 'eck_access',
    'access arguments' => array(
      "update",
      "property",
    ),
    'file' => 'eck.properties.inc',
  );
  
  $menu["{$path}/{$entity_type->name}/property/%/behavior"] = array(
    'title' => "Edit property",
    'description' => "Modify the behavior of a property of the {$entity_type->label} entity type",
    'page callback' => "drupal_get_form",
    'page arguments' => array(
      "eck__property_behavior__form",
      $entity_type->name,
      5,
    ),
    'access callback' => 'eck_access',
    'access arguments' => array(
      "update",
      "property",
    ),
    'file' => 'eck.properties.inc',
  );
  
  $menu["{$path}/{$entity_type->name}"] = array(
    'title' => "{$entity_type->label}",
    'description' => "View all the bundles for '{$entity_type->label}'",
    'page callback' => "eck__bundle__list",
    'page arguments' => array(
      3,
    ),
    'access callback' => 'eck_access',
    'access arguments' => array(
      'list',
      'bundle',
      $entity_type,
    ),
    'file' => 'eck.bundle.inc',
  );
  $menu["{$path}/{$entity_type->name}/list"] = array(
    'title' => 'Bundle List',
    'type' => MENU_DEFAULT_LOCAL_TASK,
    'weight' => 100,
  );
  
  $menu["{$path}/{$entity_type->name}/add"] = array(
    'title' => "Add bundle ",
    'description' => "Add a(n) new '{$entity_type->label} Bundle'",
    'page callback' => "drupal_get_form",
    'page arguments' => array(
      'eck__bundle__add',
      3,
    ),
    'access callback' => 'eck_access',
    'access arguments' => array(
      'create',
      'bundle',
      $entity_type,
    ),
    'type' => MENU_LOCAL_ACTION,
    'weight' => 0,
    'file' => 'eck.bundle.inc',
  );
  module_load_include('inc', 'eck', 'eck.entity');
  foreach (Bundle::loadByEntityType($entity_type) as $bundle) {
    $menu = array_merge($menu, eck__entity__menu($entity_type, $bundle));
  }
  return $menu;
}
function eck__bundle__list($entity_type) {
  $path = eck__entity_type__path();
  $entity_type = entity_type_load($entity_type);
  
  if (eck_access('list', 'bundle') || eck_access('list', "bundle", $entity_type)) {
    $header = array(
      t('Type'),
      array(
        'data' => t('Operations'),
        'colspan' => '1',
      ),
    );
    $rows = array();
    $bundles = Bundle::loadByEntityType($entity_type);
    usort($bundles, 'eck_alphabetical_cmp');
    foreach ($bundles as $bundle) {
      $bundle_label = $bundle->label;
      $admin_info = get_bundle_admin_info($entity_type->name, $bundle->name);
      $uri = $admin_info['path'];
      $allowed_operations = '';
      
      if (eck_access('delete', 'bundle', $bundle)) {
        $allowed_operations = l(t('delete'), $uri . "/delete");
      }
      if (eck_access('list', 'entity') || eck_access('list', 'entity', $bundle)) {
        $rows[] = array(
          l($bundle_label, url($uri, array(
            'absolute' => TRUE,
          ))),
          $allowed_operations,
        );
      }
      else {
        $rows[] = array(
          $bundle_label,
          $allowed_operations,
        );
      }
    }
    $build['bundle_table'] = array(
      '#theme' => 'table',
      '#header' => $header,
      '#rows' => $rows,
    );
  }
  return $build;
}
function eck__bundle__add($form, &$form_state, $entity_type) {
  $entity_type = entity_type_load($entity_type);
  $form['entity_type'] = array(
    '#type' => 'value',
    '#value' => $entity_type,
  );
  $form['bundle_label'] = array(
    '#type' => 'textfield',
    '#title' => t('Type'),
    '#description' => "A Human readable name for the bundle",
  );
  $form['bundle_name'] = array(
    '#type' => 'machine_name',
    '#required' => FALSE,
    '#machine_name' => array(
      'exists' => '_eck_fake_exists',
      'source' => array(
        'bundle_label',
      ),
    ),
  );
  $form['#validate'][] = 'eck__bundle__add_validate';
  $form['submit'] = array(
    '#type' => 'submit',
    '#weight' => 10000,
    '#value' => t('Save'),
  );
  return $form;
}
function eck__bundle__add_validate($form, &$form_state) {
  $entity_type = $form_state['values']['entity_type'];
  
  foreach (Bundle::loadByEntityType($entity_type) as $bundle) {
    if ($bundle->name == $form_state['values']['bundle_name']) {
      form_set_error('bundle', t("bundle @bundle_name already exists for this entity type", array(
        "@bundle_name" => $bundle->name,
      )));
    }
  }
}
function eck__bundle__add_submit($form, &$form_state) {
  $path = eck__entity_type__path();
  $entity_type = $form_state['values']['entity_type'];
  $bundle_name = $form_state['values']['bundle_name'];
  $bundle_label = $form_state['values']['bundle_label'];
  $bundle = new Bundle();
  $bundle->name = $bundle_name;
  $bundle->label = $bundle_label;
  $bundle->entity_type = $entity_type->name;
  $bundle
    ->save();
  drupal_set_message(t('the bundle %bundle for entity type %entity_type has been created.', array(
    '%bundle' => $bundle->label,
    '%entity_type' => $entity_type->label,
  )));
  Bundle::loadAll(NULL, TRUE);
  drupal_get_schema(NULL, TRUE);
  entity_info_cache_clear();
  variable_set('menu_rebuild_needed', TRUE);
  $form_state['redirect'] = "{$path}/{$entity_type->name}";
}
function eck__bundle__edit_form($form, &$form_state, $entity_type_name, $bundle_name) {
  $path = eck__entity_type__path();
  $entity_type = entity_type_load($entity_type_name);
  $bundle = bundle_load($entity_type_name, $bundle_name);
  $form = array();
  $form['entity_type'] = array(
    '#type' => 'value',
    '#value' => $entity_type,
  );
  $form['bundle'] = array(
    '#type' => 'value',
    '#value' => $bundle,
  );
  
  $vars = eck_property_behavior_invoke_plugin_alter($entity_type, 'bundle_form', array(
    'form' => $form,
    'form_state' => $form_state,
  ));
  $form = $vars['form'];
  $form_state = $vars['form_state'];
  $form['actions'] = array(
    '#type' => 'actions',
  );
  $form['actions']['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Save bundle'),
    '#weight' => 40,
  );
  return $form;
}
function eck__bundle__edit_form_submit($form, &$form_state) {
  $entity_type = $form_state['values']['entity_type'];
  $bundle = $form_state['values']['bundle'];
  
  $bundle_config = array();
  foreach ($form_state['values'] as $name => $value) {
    if (strpos($name, 'config_') === 0) {
      
      $bundle_config[substr($name, 7)] = $form_state['values'][$name];
    }
  }
  $bundle->config = $bundle_config;
  
  $bundle
    ->save();
  drupal_set_message(t('the bundle %bundle for entity type %entity_type has been updated.', array(
    '%bundle' => $bundle->label,
    '%entity_type' => $entity_type->label,
  )));
}
function eck__bundle__delete($entity_type, $bundle) {
  
  $bundle
    ->delete();
  drupal_get_schema(NULL, TRUE);
  variable_set('menu_rebuild_needed', TRUE);
  drupal_flush_all_caches();
  drupal_set_message(t('The bundle %bundle from the entity type %entity_type has been deleted.', array(
    '%bundle' => $bundle->label,
    '%entity_type' => $entity_type->label,
  )));
}
function eck__bundle__delete_form($form, &$form_state, $entity_type_name, $bundle_name) {
  $path = eck__entity_type__path();
  $entity_type = entity_type_load($entity_type_name);
  $bundle = bundle_load($entity_type_name, $bundle_name);
  $form['entity_type'] = array(
    '#type' => 'value',
    '#value' => $entity_type,
  );
  $form['bundle'] = array(
    '#type' => 'value',
    '#value' => $bundle,
  );
  $form['submit_redirect'] = array(
    '#type' => 'value',
    '#value' => "{$path}/{$entity_type->name}",
  );
  $message = t('Are you sure that you want to delete the bundle %bundle?', array(
    '%bundle' => $bundle->label,
  ));
  $caption = t("All of the data (entities) associated with this bundle\n  will be deleted. This action cannot be undone.");
  return confirm_form($form, $message, "{$path}/{$entity_type->name}", $caption, t('Delete'));
}
function eck__bundle__delete_form_submit($form, &$form_state) {
  $entity_type = $form_state['values']['entity_type'];
  $bundle = $form_state['values']['bundle'];
  $submit_redirect = $form_state['values']['submit_redirect'];
  eck__bundle__delete($entity_type, $bundle);
  
  $form_state['redirect'] = $submit_redirect;
}
function eck__bundle__field_autocomplete($entity_type, $bundle, $string = "") {
  $field_label = get_bundle_field_label_info($entity_type, $bundle);
  $matches = array();
  if ($field_label) {
    $field = $field_label['field'];
    $language = $field_label['language'];
    $delta = $field_label['delta'];
    $column = $field_label['column'];
    $query = new EntityFieldQuery();
    
    $query
      ->addMetadata('account', user_load(1));
    $query
      ->entityCondition('entity_type', $entity_type->name, '=')
      ->entityCondition('bundle', $bundle->name, '=')
      ->fieldCondition($field, $column, $string, 'CONTAINS');
    $results = $query
      ->execute();
    $entities = entity_load($entity_type->name, array_keys($results[$entity_type->name]));
    foreach ($entities as $id => $entity) {
      $matches[$id] = $entity->{$field}[$language][$delta][$column];
    }
  }
  drupal_json_output($matches);
}
function get_bundle_field_label_info($entity_type, $bundle) {
  $info = entity_get_info();
  if (array_key_exists('field label', $info[$entity_type->name]['bundles'][$bundle->name])) {
    return $info[$entity_type->name]['bundles'][$bundle->name]['field label'];
  }
  else {
    return NULL;
  }
}
function eck__manage_extra_field_form($form, &$form_state, $entity_type_name, $bundle_type, $property_name) {
  $entity_type = entity_type_load($entity_type_name);
  $bundle = bundle_load($entity_type_name, $bundle_type);
  drupal_set_title($bundle->config['extra_fields'][$property_name]['form']['label']);
  if (empty($bundle->config['extra_fields'][$property_name]['form'])) {
    $form_state['redirect'] = 'admin/structure/entity-type/' . $entity_type_name . '/' . $bundle->name . '/fields';
    return array();
  }
  $bundle_property_config = $bundle->config['extra_fields'][$property_name]['form'];
  $widget_type = eck_property_info_widget_types($bundle_property_config['widget']['type']);
  $form = array(
    '#entity_type' => $entity_type,
    '#bundle' => $bundle,
    '#property_name' => $property_name,
  );
  
  $form['label'] = array(
    '#type' => 'textfield',
    '#title' => t('Label'),
    '#default_value' => !empty($bundle_property_config['label']) ? $bundle_property_config['label'] : $property_name,
    '#required' => TRUE,
    '#weight' => -20,
  );
  $form['required'] = array(
    '#type' => 'checkbox',
    '#title' => t('Required field'),
    '#default_value' => !empty($bundle_property_config['required']),
    '#weight' => -10,
  );
  $form['description'] = array(
    '#type' => 'textarea',
    '#title' => t('Help text'),
    '#default_value' => !empty($bundle_property_config['description']) ? $bundle_property_config['description'] : '',
    '#rows' => 5,
    '#description' => t('Instructions to present to the user below this property field on the editing form.<br />Allowed HTML tags: @tags', array(
      '@tags' => _field_filter_xss_display_allowed_tags(),
    )),
    '#weight' => -5,
  );
  
  if (function_exists('drupal_get_path') && $widget_type['file']) {
    form_load_include($form_state, $widget_type['file type'], $widget_type['module'], $widget_type['file']);
  }
  
  $additions = module_invoke($widget_type['module'], 'eck_property_widget_settings_form', $entity_type, $bundle, $property_name, $bundle_property_config);
  if (is_array($additions)) {
    $form['widget'] = array(
      '#tree' => TRUE,
      '#type' => 'fieldset',
      '#title' => t('%type widget settings', array(
        '%type' => $widget_type['label'],
      )),
    );
    $form['widget']['settings'] = $additions;
  }
  
  if (empty($bundle_property_config['default_value_function'])) {
    $function = $widget_type['module'] . '_eck_property_widget_form';
    if (function_exists($function)) {
      $form['default_value_widget'] = array(
        '#type' => 'fieldset',
        '#title' => t('Default value'),
        '#collapsible' => FALSE,
        '#tree' => TRUE,
        '#description' => t('The default value for this property field, used when creating new content.'),
        
        '#parents' => array(),
      );
      $element = array(
        '#entity' => NULL,
        '#entity_type' => $entity_type,
        '#bundle' => $bundle,
        '#property_name' => $property_name,
        '#widget_type' => $widget_type,
        '#language' => LANGUAGE_NONE,
        '#title' => check_plain($bundle_property_config['label']),
        '#description' => field_filter_xss($bundle_property_config['description']),
        '#required' => !empty($bundle_property_config['required']),
      );
      
      if ($element = $function($form, $form_state, $property_name, $bundle_property_config, LANGUAGE_NONE, $bundle_property_config['default_value'], $element)) {
        
        $context = array(
          'form' => $form,
          'property_name' => $property_name,
          'bundle_property_config' => $bundle->config['extra_fields'][$property_name],
          'langcode' => LANGUAGE_NONE,
          'value' => $bundle_property_config['default_value'],
        );
        drupal_alter(array(
          'eck_property_widget_form',
          'eck_property_widget_' . $bundle_property_config['widget']['type'] . '_form',
        ), $element, $form_state, $context);
      }
      $form['default_value_widget'][$property_name] = $element;
    }
  }
  $form['actions'] = array(
    '#type' => 'actions',
  );
  $form['actions']['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Continue'),
  );
  return $form;
}
function eck__manage_extra_field_form_submit($form, &$form_state) {
  
  $entity_type = entity_type_load($form['#entity_type']->name);
  $bundle = bundle_load($entity_type->name, $form['#bundle']->name);
  
  if (isset($bundle->config['extra_fields'][$form['#property_name']]['form'])) {
    $property_settings = $bundle->config['extra_fields'][$form['#property_name']];
    $widget_info = eck_property_info_widget_types($property_settings['form']['widget']['type']);
    $property_settings['form']['required'] = !empty($form_state['values']['required']);
    $property_settings['form']['label'] = $form_state['values']['label'];
    $property_settings['form']['description'] = $form_state['values']['description'];
    
    if (isset($form['widget']['settings'])) {
      $property_settings['form']['widget']['settings'] = $form_state['values']['widget']['settings'];
    }
    
    if (isset($form['default_value_widget'])) {
      $property_settings['form']['default_value'] = eck_property_widget_extract_value($entity_type, $bundle, $form['#property_name'], $widget_info, $form, $form_state);
    }
    
    $config = $bundle->config;
    $config['extra_fields'][$form['#property_name']] = $property_settings;
    $bundle->config = $config;
    
    $bundle
      ->save();
    Bundle::loadAll(NULL, TRUE);
  }
  else {
    
    drupal_set_message(t('Could not edit the property field settings. The property %name on the %bundle bundle is no selected for management.', array(
      '%name' => $form['#property_name'],
      '%bundle' => $bundle->label,
    )), 'error');
  }
  $form_state['redirect'] = 'admin/structure/entity-type/' . $entity_type->name . '/' . $bundle->name . '/fields';
}
function eck_property_widget_extract_value($entity_type, $bundle, $property_name, $widget, $form, &$form_state) {
  $value = NULL;
  
  if (!empty($widget['value callback']) && function_exists($widget['value callback'])) {
    $value = $widget['value callback']($entity_type, $bundle, $property_name, $widget, $form, $form_state);
  }
  else {
    
    if (isset($form_state['values'][$property_name])) {
      $value = $form_state['values'][$property_name];
    }
  }
  return $value;
}
function eck__extra_field_widget_form($form, &$form_state, $entity_type_name, $bundle_type, $property_name) {
  $entity_type = entity_type_load($entity_type_name);
  $bundle = bundle_load($entity_type_name, $bundle_type);
  drupal_set_title($bundle->config['extra_fields'][$property_name]['form']['label']);
  $default_widget = !empty($bundle->config['extra_fields'][$property_name]['form']['widget']['type']) ? $bundle->config['extra_fields'][$property_name]['form']['widget']['type'] : '';
  $form = array(
    '#entity_type' => $entity_type,
    '#bundle' => $bundle,
    '#property_name' => $property_name,
    '#default_widget' => $default_widget,
  );
  $form['widget'] = array(
    '#type' => 'fieldset',
    '#title' => t('Change Widget'),
    '#weight' => 5,
    '#collapsible' => FALSE,
  );
  $form['widget']['widget_type'] = array(
    '#type' => 'select',
    '#title' => t('Widget for managed property'),
    '#options' => eck_property_widget_type_options($entity_type->properties[$property_name]['type']),
    '#empty_option' => t('- Select a widget -'),
    '#description' => t('The type of form element you would like to present to the user when managing this property for the %bundle type.', array(
      '%type' => $bundle->label,
    )),
    '#default_value' => $default_widget,
  );
  $form['actions'] = array(
    '#type' => 'actions',
  );
  $form['actions']['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Continue'),
  );
  return $form;
}
function eck__extra_field_widget_form_validate($form, &$form_state) {
  
  if (empty($form_state['values']['widget_type'])) {
    form_set_error('widget_type', t('You need to select a widget.'));
  }
  else {
    $entity_type = entity_type_load($form['#bundle']->name);
    $widget_types = eck_property_widget_type_options($entity_type->properties[$form['#property_name']]['type']);
    if (!isset($widget_types[$form_state['values']['widget_type']])) {
      form_set_error('widget_type', t('Invalid widget.'));
    }
  }
}
function eck__extra_field_widget_form_submit($form, &$form_state) {
  
  $entity_type = entity_type_load($form['#entity_type']->name);
  $bundle = bundle_load($entity_type->name, $form['#bundle']->name);
  
  if ($form['#default_widget'] != $form_state['values']['widget_type']) {
    
    $config = !empty($bundle->config) ? $bundle->config : array();
    if (isset($config['extra_fields'][$form['#property_name']]['form'])) {
      $widget_info = eck_property_info_widget_types($form_state['values']['widget_type']);
      
      $widget = array(
        'type' => $form_state['values']['widget_type'],
        'settings' => $widget_info['default settings'],
      );
      $config['extra_fields'][$form['#property_name']]['form']['widget'] = $widget;
      $bundle->config = $config;
      
      $bundle
        ->save();
      Bundle::loadAll(NULL, TRUE);
    }
    else {
      
      drupal_set_message(t('Could not change the property widget. The property %name on the %bundle bundle is no selected for management.', array(
        '%name' => $form['#property_name'],
        '%bundle' => $bundle->label,
      )), 'error');
    }
  }
  $form_state['redirect'] = 'admin/structure/entity-type/' . $entity_type->name . '/' . $bundle->name . '/fields';
}
function eck__remove_extra_field_form($form, &$form_state, $entity_type, $bundle_type, $property_name) {
  $bundle = bundle_load($entity_type, $bundle_type);
  $form = array(
    '#entity_type' => $entity_type,
    '#bundle' => $bundle,
    '#property_name' => $property_name,
  );
  return confirm_form($form, t('Are you sure you want to remove %title as a property field for the %bundle bundle?', array(
    '%title' => $property_name,
    '%bundle' => $bundle->label,
  )), 'admin/structure/entity-type/' . $entity_type . '/' . $bundle_type . '/properties/' . $property_name, t("This will remove the property as an extra field on the %bundle bundle's field management page, but it does not delete the property from the entity type. This cannot be undone.", array(
    '%bundle' => $bundle->label,
  )), t('Remove'), t('Cancel'));
}
function eck__remove_extra_field_form_submit($form, &$form_state) {
  if ($form_state['values']['confirm']) {
    $property_name = $form['#property_name'];
    $entity_type = $form['#entity_type'];
    $bundle = bundle_load($entity_type, $form['#bundle']->name);
    if (!empty($bundle->config['extra_fields'][$property_name]['form'])) {
      $config = $bundle->config;
      
      unset($config['extra_fields'][$property_name]['form']);
      $bundle->config = $config;
      
      $bundle
        ->save();
      Bundle::loadAll(NULL, TRUE);
    }
  }
  $form_state['redirect'] = 'admin/structure/entity-type/' . $entity_type . '/' . $bundle->name . '/fields';
}