diff --git entity.install entity.install
index 65cec65..02bf122 100644
--- entity.install
+++ entity.install
@@ -7,6 +7,28 @@
*/
/**
+ * Defines schema fields required for exportable entities.
+ * To be utilized by modules defining exportable entities.
+ */
+function entity_exportable_schema_fields($module_col = 'module', $status_col = 'status') {
+ return array(
+ $module_col => array(
+ 'description' => 'The name of the providing module if the entity has been defined in code.',
+ 'type' => 'varchar',
+ 'length' => 255,
+ 'not null' => FALSE,
+ ),
+ $status_col => array(
+ 'type' => 'int',
+ 'not null' => TRUE,
+ 'default' => ENTITY_CUSTOM,
+ 'size' => 'tiny',
+ 'description' => 'The exportable status of the entity.',
+ ),
+ );
+}
+
+/**
* The entity API modules have been merged into a single module.
*/
function entity_update_7000() {
diff --git entity.module entity.module
index 83da48f..4da1828 100644
--- entity.module
+++ entity.module
@@ -17,6 +17,16 @@ module_load_include('inc', 'entity', 'includes/entity.property');
/**
* A bit flag used to let us know if an entity is in the database.
*/
+
+
+/**
+ * A bit flag used to let us know if an entity has been customly defined.
+ */
+define('ENTITY_CUSTOM', 0x01);
+
+/**
+ * Deprecated, but still here for backward compatibility.
+ */
define('ENTITY_IN_DB', 0x01);
/**
@@ -35,7 +45,7 @@ define('ENTITY_OVERRIDDEN', 0x03);
* A bit flag used to mark entities as fixed, thus not changeable for any
* user.
*/
-define('ENTITY_FIXED', 0x04);
+define('ENTITY_FIXED', 0x04 | 0x02);
@@ -343,7 +353,7 @@ function entity_crud_get_info() {
* @param $entity
* The entity to check the status on.
* @param $status
- * The constant status like ENTITY_IN_DB, ENTITY_IN_CODE, ENTITY_OVERRIDDEN
+ * The constant status like ENTITY_CUSTOM, ENTITY_IN_CODE, ENTITY_OVERRIDDEN
* or ENTITY_FIXED.
*
* @return
@@ -429,63 +439,145 @@ function entity_var_json_export($var, $prefix = '') {
}
/**
- * Implements hook_modules_enabled().
+ * Rebuild the default entities provided in code.
+ *
+ * @todo: describe.
*
- * Invokes hook_entity_enabled() for new default entities.
+ * @param $entity_types
+ * (optional) If specified, only the defaults of the given entity types are
+ * rebuilt.
*/
-function entity_modules_enabled($modules) {
- foreach (entity_crud_get_info() as $entity_type => $info) {
- if (!empty($info['exportable']) && $entities = _entity_modules_get_defaults($entity_type, $modules)) {
- module_invoke_all($entity_type . '_enabled', $entities);
- module_invoke_all('entity_enabled', $entities, $entity_type);
+function entity_defaults_rebuild($entity_types = NULL) {
+ if (isset($entity_types)) {
+ $rebuild = variable_get('entity_defaults_built', array());
+ variable_set('entity_defaults_built', array_diff_key($rebuild, array_flip($entity_types)));
+ }
+ else {
+ variable_set('entity_defaults_built', array());
+ }
+}
+
+/**
+ * Actually rebuild the defaults, triggered by entity_load().
+ */
+function _entity_defaults_rebuild($entity_type) {
+ if (lock_acquire('entity_rebuild_' . $entity_type)) {
+ $built = variable_get('entity_defaults_built', array());
+ $built[$entity_type] = TRUE;
+ variable_set('entity_defaults_built', $built);
+
+ $info = entity_get_info($entity_type);
+ $hook = isset($info['export']['default hook']) ? $info['export']['default hook'] : 'default_' . $entity_type;
+ $keys = $info['entity keys'] + array('module' => 'module', 'status' => 'status', 'name' => $info['entity keys']['id']);
+
+ // Invoke the hook and collect default entities.
+ $entities = array();
+ foreach (module_implements($hook) as $module) {
+ foreach ((array) module_invoke($module, $hook) as $name => $entity) {
+ $entity->{$keys['name']} = $name;
+ $entity->{$keys['module']} = $module;
+ $entities[$name] = $entity;
+ }
+ }
+ drupal_alter($hook, $entities);
+
+ // Remove defaults which are already overridden.
+ $overridden_entities = entity_load($entity_type, array_keys($entities), array($keys['status'] => ENTITY_OVERRIDDEN));
+ $entities = array_diff_key($entities, $overridden_entities);
+
+ // Determine already existing, custom entities and mark them as overridden.
+ $existing_entities = entity_load($entity_type, array_keys($entities), array($keys['status'] => ENTITY_CUSTOM));
+ foreach ($existing_entities as $name => $entity) {
+ $entity->{$keys['status']} |= ENTITY_OVERRIDDEN;
+ $entity->{$keys['module']} = $entities[$name]->{$keys['module']};
+ entity_save($entity_type, $entity);
+ }
+
+ // Save the defaults being not overridden to the db, possible over-writing
+ // previous defaults already saved in the db.
+ foreach (array_diff_key($entities, $existing_entities) as $name => $entity) {
+ $entity->{$keys['status']} |= ENTITY_IN_CODE;
+ // For updating the numeric db identifier has to be set.
+ if ($entity->original = entity_load_unchanged($entity_type, $name)) {
+ $entity->{$keys['id']} = $entity->original->{$keys['id']};
+ unset($entity->is_new);
+ }
+ $entity->is_rebuild = TRUE;
+ entity_save($entity_type, $entity);
}
+
+ lock_release('entity_rebuild_' . $entity_type);
+ }
+}
+
+/**
+ * Implements hook_modules_enabled().
+ */
+function entity_modules_enabled($modules) {
+ if ($entity_types = _entity_modules_get_default_types($modules)) {
+ entity_defaults_rebuild($entity_types);
}
}
/**
* Implements hook_modules_disabled().
- *
- * Invokes hook_entity_disabled() for new default entities.
*/
function entity_modules_disabled($modules) {
- foreach (entity_crud_get_info() as $entity_type => $info) {
- if (!empty($info['exportable']) && $entities = _entity_modules_get_defaults($entity_type, $modules)) {
- module_invoke_all($entity_type . '_disabled', $entities);
- module_invoke_all('entity_disabled', $entities, $entity_type);
- // Make sure the cache is cleared afterwards, so removed default entities
- // are not left there.
- entity_get_controller($entity_type)->resetCache();
+ foreach (_entity_modules_get_default_types($modules) as $entity_type) {
+ $info = entity_get_info($entity_type);
+ $keys = $info['entity keys'] + array('module' => 'module', 'status' => 'status', 'name' => $info['entity keys']['id']);
+ // Remove entities provided in code.
+ $query = new EntityFieldQuery();
+ $query->entityCondition('entity_type', $entity_type, '=')
+ ->propertyCondition($keys['module'], $modules, 'IN')
+ ->propertyCondition($keys['status'], array(ENTITY_IN_CODE, ENTITY_FIXED), 'IN');
+ $result = $query->execute();
+ if (isset($result[$entity_type])) {
+ $entities = entity_load($entity_type, array_keys($result[$entity_type]));
+ entity_delete_multiple($entity_type, array_keys($entities));
}
- }
-}
-function _entity_modules_get_defaults($entity_type, $modules) {
- $info = entity_get_info($entity_type);
- $entities = array();
- $hook = isset($info['export']['default hook']) ? $info['export']['default hook'] : 'default_' . $entity_type;
- $module_key = isset($info['entity keys']['module']) ? $info['entity keys']['module'] : 'module';
- // Collect the ids of all new entities.
- foreach ($modules as $module) {
- if (module_hook($module, $hook)) {
- $result = module_invoke($module, $hook);
- if ($result && is_array($result)) {
- $entities += $result;
+ // Update overridden entities to be now custom.
+ $query = new EntityFieldQuery();
+ $query->entityCondition('entity_type', $entity_type, '=')
+ ->propertyCondition($keys['module'], $modules, 'IN')
+ ->propertyCondition($keys['status'], ENTITY_OVERRIDDEN, '=');
+ $result = $query->execute();
+ if (isset($result[$entity_type])) {
+ foreach (entity_load($entity_type, array_keys($result[$entity_type])) as $name => $entity) {
+ $entity->{$keys['status']} = ENTITY_CUSTOM;
+ $entity->{$keys['module']} = NULL;
+ entity_save($entity_type, $entity);
}
}
}
- if ($ids = array_keys($entities)) {
- // To make sure the new default entities are retrieved, make sure the cache
- // is cleared.
- entity_get_controller($entity_type)->resetCache();
- // Check whether some of the new entities are already overridden.
- $entities = array();
- foreach (entity_load($entity_type, $ids) as $id => $entity) {
- if (!entity_has_status($entity_type, $entity, ENTITY_OVERRIDDEN)) {
- $entities[$id] = $entity;
+
+}
+
+/**
+ * Gets all entity types for which defaults are provided by the $modules.
+ */
+function _entity_modules_get_default_types($modules) {
+ $types = array();
+ foreach (entity_crud_get_info() as $entity_type => $info) {
+ if (!empty($info['exportable'])) {
+ $hook = isset($info['export']['default hook']) ? $info['export']['default hook'] : 'default_' . $entity_type;
+ foreach ($modules as $module) {
+ if (module_hook($module, $hook) || module_hook($module, $hook . '_alter')) {
+ $types[] = $entity_type;
+ }
}
}
- return $entities;
}
+ return $types;
+}
+
+/**
+ * Implements hook_flush_caches().
+ */
+function entity_flush_caches() {
+ entity_property_info_cache_clear();
+ entity_defaults_rebuild();
}
/**
@@ -528,7 +620,7 @@ function theme_entity_status($variables) {
$help = t('A module provides this configuration.');
return $html ? "" . $label . "" : $label;
}
- elseif ($status & ENTITY_IN_DB) {
+ elseif ($status & ENTITY_CUSTOM) {
$label = t('Custom');
$help = t('A custom configuration by a user.');
return $html ? "" . $label . "" : $label;
diff --git entity.test entity.test
index 3673c37..cb48b5e 100644
--- entity.test
+++ entity.test
@@ -109,7 +109,7 @@ class EntityAPITestCase extends DrupalWebTestCase {
$types = entity_load('entity_test_type', array('test', 'test2'));
$this->assertEqual($types['test']->label, 'label', 'Default type loaded.');
- $this->assertTrue($types['test']->status & ENTITY_IN_CODE && !($types['test']->status & ENTITY_IN_DB), 'Default type status is correct.');
+ $this->assertTrue($types['test']->status & ENTITY_IN_CODE && !($types['test']->status & ENTITY_CUSTOM), 'Default type status is correct.');
// Test using a condition, which has to be applied on the defaults.
$types = entity_load('entity_test_type', FALSE, array('label' => 'label'));
@@ -136,7 +136,18 @@ class EntityAPITestCase extends DrupalWebTestCase {
$types = entity_load('entity_test_type', array('test', 'test2'));
$this->assertEqual($types['test']->label, 'modified', 'Modified default type loaded by id.');
- $this->assertTrue($types['test']->status & ENTITY_IN_CODE && $types['test']->status & ENTITY_IN_DB, 'Status of modified type is correct.');
+ $this->assertTrue(entity_has_status('entity_test_type', $types['test'], ENTITY_OVERRIDDEN), 'Status of overridden type is correct.');
+
+ // Test rebuilding the defaults and make sure overridden entities stay.
+ entity_defaults_rebuild();
+ $types = entity_load('entity_test_type', array('test', 'test2'));
+ $this->assertEqual($types['test']->label, 'modified', 'Overridden entity is still overridden.');
+ $this->assertTrue(entity_has_status('entity_test_type', $types['test'], ENTITY_OVERRIDDEN), 'Status of overridden type is correct.');
+
+ // Test reverting.
+ $types['test']->delete();
+ $types = entity_load('entity_test_type', array('test', 'test2'));
+ $this->assertEqual($types['test']->label, 'label', 'Entity has been reverted.');
// Test loading an exportable by its numeric id.
$result = entity_load('entity_test_type', array($types['test']->id));
@@ -152,17 +163,17 @@ class EntityAPITestCase extends DrupalWebTestCase {
}
/**
- * Tests hook_entity_enabled() and hook_entity_disabled().
+ * Make sure insert() and update() hooks for exportables are invoked.
*/
- function testExportablesActivation() {
+ function testExportableHooks() {
$_SESSION['entity_hook_test'] = array();
// Enabling the module should invoke the enabled hook for the other
// entities provided in code.
module_enable(array('entity_feature'));
- $all = array('main', 'test', 'test2');
- $this->assertTrue($_SESSION['entity_hook_test']['entity_enabled'] == array($all), 'Hook entity_enabled has been invoked.');
- $this->assertTrue($_SESSION['entity_hook_test']['entity_test_type_enabled'] == array($all), 'Hook entity_test_type_enabled has been invoked.');
+ $insert = array('main', 'test', 'test2');
+ $this->assertTrue($_SESSION['entity_hook_test']['entity_insert'] == $insert, 'Hook entity_insert has been invoked.');
+ $this->assertTrue($_SESSION['entity_hook_test']['entity_test_type_insert'] == $insert, 'Hook entity_test_type_insert has been invoked.');
// Add a new test entity in DB and make sure the hook is invoked too.
$test3 = entity_create('entity_test_type', array(
@@ -171,35 +182,37 @@ class EntityAPITestCase extends DrupalWebTestCase {
'weight' => 0,
));
$test3->save();
- $this->assertTrue($_SESSION['entity_hook_test']['entity_enabled'] == array($all, array('test3')), 'Hook entity_enabled has been invoked.');
- $this->assertTrue($_SESSION['entity_hook_test']['entity_test_type_enabled'] == array($all, array('test3')), 'Hook entity_test_type_enabled has been invoked.');
- // Now override the 'test' entity and make sure it doesn't invoke the
- // enabling hook as it is already enabled. Then make sure it stays enabled
- // when the feature module is disabled.
+ $insert[] = 'test3';
+ $this->assertTrue($_SESSION['entity_hook_test']['entity_insert'] == $insert, 'Hook entity_insert has been invoked.');
+ $this->assertTrue($_SESSION['entity_hook_test']['entity_test_type_insert'] == $insert, 'Hook entity_test_type_insert has been invoked.');
+
+ // Now override the 'test' entity and make sure it invokes the update hook.
$result = entity_load('entity_test_type', array('test'));
$result['test']->label = 'modified';
$result['test']->save();
- $this->assertTrue($_SESSION['entity_hook_test']['entity_enabled'] == array($all, array('test3')), 'Hook entity_enabled has been invoked.');
- $this->assertTrue($_SESSION['entity_hook_test']['entity_test_type_enabled'] == array($all, array('test3')), 'Hook entity_test_type_enabled has been invoked.');
+ $this->assertTrue($_SESSION['entity_hook_test']['entity_update'] == array('test'), 'Hook entity_update has been invoked.');
+ $this->assertTrue($_SESSION['entity_hook_test']['entity_test_type_update'] == array('test'), 'Hook entity_test_type_update has been invoked.');
// 'test' has to remain enabled, as it has been overridden.
- $all = array('main', 'test2');
+ $delete = array('main', 'test2');
module_disable(array('entity_feature'));
- $this->assertTrue($_SESSION['entity_hook_test']['entity_disabled'] == array($all), 'Hook entity_disabled has been invoked.');
- $this->assertTrue($_SESSION['entity_hook_test']['entity_test_type_disabled'] == array($all), 'Hook entity_test_type_disabled has been invoked.');
+ $this->assertTrue($_SESSION['entity_hook_test']['entity_delete'] == $delete, 'Hook entity_deleted has been invoked.');
+ $this->assertTrue($_SESSION['entity_hook_test']['entity_test_type_delete'] == $delete, 'Hook entity_test_type_deleted has been invoked.');
// Now make sure 'test' is not overridden any more, but custom.
$result = entity_load('entity_test_type', array('test'));
$this->assertTrue(!entity_has_status('entity_test_type', $result['test'], ENTITY_OVERRIDDEN), 'Entity is not marked as overridden any more.');
+ $this->assertTrue(entity_has_status('entity_test_type', $result['test'], ENTITY_CUSTOM), 'Entity is marked as custom.');
- // Test disabled hook for deleting the remaining entities from DB.
+ // Test deleting the remaining entities from DB.
entity_delete_multiple('entity_test_type', array('test', 'test3'));
- $all2 = array('test', 'test3');
- $this->assertTrue($_SESSION['entity_hook_test']['entity_disabled'] == array($all, $all2), 'Hook entity_disabled has been invoked.');
- $this->assertTrue($_SESSION['entity_hook_test']['entity_test_type_disabled'] == array($all, $all2), 'Hook entity_test_type_disabled has been invoked.');
+ $delete[] = 'test';
+ $delete[] = 'test3';
+ $this->assertTrue($_SESSION['entity_hook_test']['entity_delete'] == $delete, 'Hook entity_deleted has been invoked.');
+ $this->assertTrue($_SESSION['entity_hook_test']['entity_test_type_delete'] == $delete, 'Hook entity_test_type_deleted has been invoked.');
}
/**
diff --git includes/entity.controller.inc includes/entity.controller.inc
index d7a1b85..f9df6a2 100644
--- includes/entity.controller.inc
+++ includes/entity.controller.inc
@@ -118,8 +118,8 @@ interface EntityAPIControllerInterface extends DrupalEntityControllerInterface {
*/
class EntityAPIController extends DrupalDefaultEntityController implements EntityAPIControllerInterface {
- protected $defaultEntities, $cacheComplete = FALSE;
- protected $nameKey, $statusKey, $bundleKey, $moduleKey;
+ protected $cacheComplete = FALSE;
+ protected $nameKey, $statusKey, $bundleKey;
/**
* Overridden.
@@ -133,9 +133,7 @@ class EntityAPIController extends DrupalDefaultEntityController implements Entit
// Use the name key as primary identifier.
$this->nameKey = isset($this->entityInfo['entity keys']['name']) ? $this->entityInfo['entity keys']['name'] : $this->idKey;
if (!empty($this->entityInfo['exportable'])) {
- $this->entityInfo['entity keys'] += array('module' => 'module', 'status' => 'status');
- $this->statusKey = $this->entityInfo['entity keys']['status'];
- $this->moduleKey = $this->entityInfo['entity keys']['module'];
+ $this->statusKey = isset($this->entityInfo['entity keys']['status']) ? $this->entityInfo['entity keys']['status'] : 'status';
}
// If this is the bundle of another entity, set the bundle key.
if (isset($this->entityInfo['bundle of'])) {
@@ -181,6 +179,11 @@ class EntityAPIController extends DrupalDefaultEntityController implements Entit
public function load($ids = array(), $conditions = array()) {
$entities = array();
+ // For exportable entities, make sure the defaults have been built.
+ if (!empty($this->entityInfo['exportable']) && empty($GLOBALS['conf']['entity_defaults_built'][$this->entityType])) {
+ _entity_defaults_rebuild($this->entityType);
+ }
+
// Revisions are not statically cached, and require a different query to
// other conditions, so separate the revision id into its own variable.
if ($this->revisionKey && isset($conditions[$this->revisionKey])) {
@@ -198,10 +201,6 @@ class EntityAPIController extends DrupalDefaultEntityController implements Entit
// database when all requested entities are loaded from cache.
$passed_ids = !empty($ids) ? array_flip($ids) : FALSE;
- // Add default entities defined in code to the cache.
- if (!empty($this->entityInfo['exportable']) && !isset($this->defaultEntities)) {
- $this->getDefaults();
- }
// Try to load entities from the static cache.
if (!$revision_id) {
$entities = $this->cacheGet($ids, $conditions);
@@ -213,9 +212,8 @@ class EntityAPIController extends DrupalDefaultEntityController implements Entit
// Load any remaining entities from the database. This is the case if $ids
// is set to FALSE (so we load all entities), if there are any ids left to
- // load, if loading a revision, or if $conditions was passed without $ids.
- if (!$this->cacheComplete && ($ids === FALSE || $ids || $revision_id || ($conditions && !$passed_ids))) {
- $schema = drupal_get_schema($this->entityInfo['base table']);
+ // load or if loading a revision.
+ if (!$this->cacheComplete && ($ids === FALSE || $ids || $revision_id)) {
$queried_entities = array();
foreach ($this->query($ids, $conditions, $revision_id) as $record) {
// Skip entities already retrieved from cache.
@@ -224,7 +222,7 @@ class EntityAPIController extends DrupalDefaultEntityController implements Entit
}
// Care for serialized columns.
- foreach ($schema['fields'] as $field => $info) {
+ foreach ($this->entityInfo['schema_fields_sql']['base table'] as $field => $info) {
if (!empty($info['serialize']) && isset($record->$field)) {
$record->$field = unserialize($record->$field);
// Support automatic merging of 'data' fields into the entity.
@@ -236,15 +234,7 @@ class EntityAPIController extends DrupalDefaultEntityController implements Entit
}
}
}
- if (isset($this->statusKey)) {
- // Care for setting the status key properly.
- $record->{$this->statusKey} |= ENTITY_IN_DB;
- $id = $record->{$this->nameKey};
- if (isset($this->defaultEntities[$id])) {
- $record->{$this->statusKey} |= ENTITY_IN_CODE;
- $record->{$this->moduleKey} = $this->defaultEntities[$id]->{$this->moduleKey};
- }
- }
+
$queried_entities[$record->{$this->nameKey}] = $record;
}
}
@@ -279,30 +269,6 @@ class EntityAPIController extends DrupalDefaultEntityController implements Entit
return $entities;
}
- /**
- * For exportables, incorporate defaults into the cache.
- */
- protected function getDefaults() {
- $this->defaultEntities = array();
- $hook = isset($this->entityInfo['export']['default hook']) ? $this->entityInfo['export']['default hook'] : 'default_' . $this->entityType;
- // Invoke the hook and collect default entities.
- foreach (module_implements($hook) as $module) {
- foreach ((array) module_invoke($module, $hook) as $id => $entity) {
- $entity->{$this->statusKey} |= ENTITY_IN_CODE;
- $entity->{$this->nameKey} = $id;
- $entity->{$this->moduleKey} = $module;
- $this->defaultEntities[$id] = $entity;
- }
- }
- drupal_alter($hook, $this->defaultEntities);
- // Remove any default entities that have been overridden.
- foreach ($this->query(array_keys($this->defaultEntities), array()) as $record) {
- $overridden[$record->{$this->nameKey}] = TRUE;
- }
- // Handle fetching defaults via the cache.
- $this->cacheSet(isset($overridden) ? array_diff_key($this->defaultEntities, $overridden) : $this->defaultEntities);
- }
-
protected function applyConditions($entities, $conditions = array()) {
if ($conditions) {
foreach ($entities as $key => $entity) {
@@ -373,16 +339,8 @@ class EntityAPIController extends DrupalDefaultEntityController implements Entit
}
public function resetCache(array $ids = NULL) {
- unset($this->defaultEntities);
$this->cacheComplete = FALSE;
- if (isset($ids)) {
- foreach ($ids as $id) {
- unset($this->entityCache[$id]);
- }
- }
- else {
- $this->entityCache = array();
- }
+ parent::resetCache($ids);
}
/**
@@ -392,6 +350,7 @@ class EntityAPIController extends DrupalDefaultEntityController implements Entit
if (!empty($this->entityInfo['fieldable']) && function_exists($function = 'field_attach_' . $hook)) {
$function($this->entityType, $entity);
}
+
if (isset($this->entityInfo['bundle of']) && $type = $this->entityInfo['bundle of']) {
// Call field API bundle attachers for the entity we are a bundle of.
if ($hook == 'insert') {
@@ -441,14 +400,10 @@ class EntityAPIController extends DrupalDefaultEntityController implements Entit
foreach ($entities as $id => $entity) {
$this->invoke('delete', $entity);
- if (!empty($this->entityInfo['exportable']) && !($entity->{$this->statusKey} & ENTITY_IN_CODE)) {
- $disabled_entities[$id] = $entity;
+ if (entity_has_status($this->entityType, $entity, ENTITY_IN_CODE)) {
+ $rebuild = TRUE;
}
}
- if (!empty($disabled_entities)) {
- module_invoke_all($this->entityType . '_disabled', $disabled_entities);
- module_invoke_all('entity_disabled', $disabled_entities, $this->entityType);
- }
// Ignore slave server temporarily.
db_ignore_slave();
}
@@ -457,6 +412,13 @@ class EntityAPIController extends DrupalDefaultEntityController implements Entit
watchdog_exception($this->entityType, $e);
throw $e;
}
+ // We have to postpone rebuilding defaults until the transaction has been
+ // committed. This is as variable_set() triggers a merge query and dies with
+ // a savepoint exception if it is inside a transaction.
+ if (!empty($rebuild)) {
+ $transaction = NULL;
+ entity_defaults_rebuild(array($this->entityType));
+ }
}
/**
@@ -473,6 +435,10 @@ class EntityAPIController extends DrupalDefaultEntityController implements Entit
if (!empty($entity->{$this->nameKey}) && !isset($entity->original)) {
$entity->original = entity_load_unchanged($this->entityType, $entity->{$this->nameKey});
}
+ // Update the status for entities getting overridden.
+ if (entity_has_status($this->entityType, $entity, ENTITY_IN_CODE) && empty($entity->is_rebuild)) {
+ $entity->{$this->statusKey} |= ENTITY_CUSTOM;
+ }
$this->invoke('presave', $entity);
@@ -484,16 +450,6 @@ class EntityAPIController extends DrupalDefaultEntityController implements Entit
else {
$return = drupal_write_record($this->entityInfo['base table'], $entity);
$this->invoke('insert', $entity);
-
- if (!empty($this->entityInfo['exportable'])) {
- $entity->{$this->statusKey} |= ENTITY_IN_DB;
- $this->resetCache(array($entity->{$this->nameKey}));
- if (!entity_has_status($this->entityType, $entity, ENTITY_IN_CODE)) {
- $entities = array($entity->{$this->nameKey} => $entity);
- module_invoke_all($this->entityType . '_enabled', $entities);
- module_invoke_all('entity_enabled', $entities, $this->entityType);
- }
- }
}
// Ignore slave server temporarily.
db_ignore_slave();
diff --git tests/entity_test.install tests/entity_test.install
index a879864..43dbd84 100644
--- tests/entity_test.install
+++ tests/entity_test.install
@@ -113,7 +113,7 @@ function entity_test_schema() {
'description' => 'A serialized array of additional data related to this entity_test type.',
'merge' => TRUE,
),
- ),
+ ) + entity_exportable_schema_fields(),
'primary key' => array('id'),
'unique keys' => array(
'name' => array('name'),
diff --git tests/entity_test.module tests/entity_test.module
index 2e3d896..6aed96a 100644
--- tests/entity_test.module
+++ tests/entity_test.module
@@ -147,54 +147,62 @@ class EntityClass extends Entity {
/**
- * Implements hook_entity_enabled().
+ * Implements hook_entity_insert().
*/
-function entity_test_entity_enabled($entities) {
- $_SESSION['entity_hook_test']['entity_enabled'][] = array_keys($entities);
+function entity_test_entity_insert($entity, $entity_type) {
+ $_SESSION['entity_hook_test']['entity_insert'][] = entity_id($entity_type, $entity);
}
/**
- * Implements hook_entity_disabled().
+ * Implements hook_entity_update().
*/
-function entity_test_entity_disabled($entities) {
- $_SESSION['entity_hook_test']['entity_disabled'][] = array_keys($entities);
+function entity_test_entity_update($entity, $entity_type) {
+ $_SESSION['entity_hook_test']['entity_update'][] = entity_id($entity_type, $entity);
}
/**
- * Implements hook_entity_test_type_enabled().
+ * Implements hook_entity_delete().
*/
-function entity_test_entity_test_type_enabled($entities) {
- $_SESSION['entity_hook_test']['entity_test_type_enabled'][] = array_keys($entities);
+function entity_test_entity_delete($entity, $entity_type) {
+ $_SESSION['entity_hook_test']['entity_delete'][] = entity_id($entity_type, $entity);
}
/**
- * Implements hook_entity_test_type_disabled().
+ * Implements hook_entity_test_type_insert().
*/
-function entity_test_entity_test_type_disabled($entities) {
- $_SESSION['entity_hook_test']['entity_test_type_disabled'][] = array_keys($entities);
+function entity_test_entity_test_type_insert($entity) {
+ $_SESSION['entity_hook_test']['entity_test_type_insert'][] = $entity->identifier();
}
-
/**
- * Implements hook_entity_test_type_presave().
+ * Implements hook_entity_test_type_update().
*/
-function entity_test_entity_test_type_presave($entity) {
- // Determine changes.
+function entity_test_entity_test_type_update($entity) {
+ $_SESSION['entity_hook_test']['entity_test_type_update'][] = $entity->identifier();
+
+ // Determine changes on update.
if (!empty($entity->original) && $entity->original->label == 'test_changes') {
if ($entity->original->label != $entity->label) {
- $entity->label .= '_presave';
+ $entity->label .= '_update';
}
}
}
/**
- * Implements hook_entity_test_type_update().
+ * Implements hook_entity_test_type_delete().
*/
-function entity_test_entity_test_type_update($entity) {
- // Determine changes on update.
+function entity_test_entity_test_type_delete($entity) {
+ $_SESSION['entity_hook_test']['entity_test_type_delete'][] = $entity->identifier();
+}
+
+/**
+ * Implements hook_entity_test_type_presave().
+ */
+function entity_test_entity_test_type_presave($entity) {
+ // Determine changes.
if (!empty($entity->original) && $entity->original->label == 'test_changes') {
if ($entity->original->label != $entity->label) {
- $entity->label .= '_update';
+ $entity->label .= '_presave';
}
}
}