diff --git a/includes/commerce.controller.inc b/includes/commerce.controller.inc index b29ddb9..6223903 100644 --- a/includes/commerce.controller.inc +++ b/includes/commerce.controller.inc @@ -57,6 +57,14 @@ interface DrupalCommerceEntityControllerInterface extends EntityAPIControllerInt */ public function releaseLock($entity); + /** + * Register the given entity as to be locked. + * + * @param object $entity + * The entity to lock. + */ + public function setLock($entity); + } /** @@ -153,7 +161,13 @@ class DrupalCommerceEntityController extends DrupalDefaultEntityController imple * The transaction is not necessarily committed immediately. Drupal will * commit it as soon as possible given the state of the transaction stack. */ - protected function releaseLocks() { + protected function releaseLocks($ids = array()) { + if (is_array($ids) && !empty($ids)) { + foreach ($ids as $id) { + unset($this->lockedEntities[$id]); + } + } + if (empty($this->lockedEntities)) { $this->controllerTransaction = NULL; } @@ -170,6 +184,27 @@ class DrupalCommerceEntityController extends DrupalDefaultEntityController imple } /** + * Implements DrupalCommerceEntityControllerInterface::setLock(). + */ + public function setLock($entity) { + $this->setLocks(array($entity->{$this->idKey})); + } + + /** + * Lock the given entities IDs + * + * @param array $ids + * Ids of the entities to be locked. + */ + protected function setLocks($ids) { + foreach ($ids as $id) { + if ($id) { + $this->lockedEntities[$id] = TRUE; + } + } + } + + /** * Overrides DrupalDefaultEntityController::load(). * * Accepts a condition of locking request, may not necessarily take effect @@ -182,15 +217,24 @@ class DrupalCommerceEntityController extends DrupalDefaultEntityController imple $this->requestLocking = $conditions['_lock']; unset($conditions['_lock']); + $require_locking = $this->requireLocking(); + // If locking has been required, then bypass the internal cache for any // entities that are not already locked. - if ($this->requireLocking()) { - foreach (array_diff_key(array_flip($ids), $this->lockedEntities) as $id => $value) { - unset($this->entityCache[$id]); - } + if ($require_locking) { + $non_locked = array_diff_key(array_flip($ids), $this->lockedEntities); + $this->resetCache(array_keys($non_locked)); } - return parent::load($ids, $conditions); + // Load the required entities. + $loaded = parent::load($ids, $conditions); + + // // If locking has been required then lock the loaded entities. + if ($require_locking && $loaded && !empty($loaded)) { + $this->setLocks(array_keys($loaded)); + } + + return $loaded; } /** @@ -210,12 +254,6 @@ class DrupalCommerceEntityController extends DrupalDefaultEntityController imple } $query->forUpdate(); - - // Store the ids of the entities in the lockedEntities array for later - // tracking, flipped for easier management via unset() below. - if (is_array($ids)) { - $this->lockedEntities += array_flip($ids); - } } return $query; @@ -279,11 +317,8 @@ class DrupalCommerceEntityController extends DrupalDefaultEntityController imple // Reset the cache as soon as the changes have been applied. $this->resetCache($ids); - // Maintain the list of locked entities and release the lock if possible. - foreach ($ids as $id) { - unset($this->lockedEntities[$id]); - } - $this->releaseLocks(); + // Release the lock if possible. + $this->releaseLocks($ids); foreach ($entities as $id => $entity) { $this->invoke('delete', $entity); @@ -379,10 +414,9 @@ class DrupalCommerceEntityController extends DrupalDefaultEntityController imple // Update the static cache so that the next entity_load() will return this // newly saved entity. - $this->entityCache[$entity->{$this->idKey}] = $entity; + $this->cacheSet(array($entity->{$this->idKey} => $entity)); - // Maintain the list of locked entities and release the lock if possible. - unset($this->lockedEntities[$entity->{$this->idKey}]); + // Release the lock. $this->releaseLock($entity); $this->invoke($op, $entity);