class CerPresetHandler in Corresponding Entity References 7.3
@class Contains the logic for performing CER operations on a single entity, using a single preset.
Hierarchy
- class \CerPresetHandler
Expanded class hierarchy of CerPresetHandler
File
- includes/
CerPresetHandler.inc, line 13 - Contains CerPresetHandler.
View source
class CerPresetHandler {
/**
* @var CerFieldChain
*/
protected $left;
/**
* @var CerFieldChain
*/
protected $right;
/**
* @var EntityDrupalWrapper
*/
protected $entity;
/**
* @var array
*/
protected $refIDs;
public function __construct(CerPreset $preset, EntityDrupalWrapper $entity) {
$this->left = $preset->wrapper->cer_left->chain
->value();
$this->right = $preset->wrapper->cer_right->chain
->value();
$this->entity = $entity;
// Store the current set of reference IDs so that we only need to instantiate
// the left handler once.
$this->refIDs = $this->left
->getHandler($entity)
->getIDs();
}
/**
* Process an entity insert. This loops through the referenced entity $IDs and
* adds a reference to this entity if the reference doesn't already have one.
*/
public function insert(array $IDs = array()) {
// If no IDs were passed in, use the current reference set.
$IDs = $IDs ? $IDs : $this->refIDs;
// Get this entity's ID right now, so we don't have to keep calling
// $this->entity->cer->owner->getIdentifier(). Hooray for micro-optimization!
$myID = $this->entity->cer->owner
->getIdentifier();
foreach ($this
->load($IDs) as $ref) {
$handler = $this->right
->getHandler($ref);
// Only create the backreference if the reference doesn't already reference
// this entity (which it might, if there is more than one preset that references
// a single field instance).
if (!in_array($myID, $handler
->getIDs())) {
$handler
->add($this->entity->cer->owner);
}
}
}
/**
* Process an entity update. This could be either a normal update done by a user,
* or a bulk update.
*/
public function update() {
// Get the previous set of reference IDs. $entity->cer->original will return either
// $entity->original, if it exists, or the current entity. So, if this is a bulk
// update, $originalIDs will be identical to $this->refIDs.
$originalIDs = $this->left
->getHandler($this->entity->cer->original)
->getIDs();
// If there are any references that were in the previous set but not the current
// set, delete those backreferences. Under normal circumstances, there will be
// nothing to delete during a bulk update, since the previous set and current
// set should be identical.
$deleted = array_diff($originalIDs, $this->refIDs);
if ($deleted) {
$this
->delete($deleted);
}
// If the previous set is identical to the current set, we'll be processing
// all existing references (see the first line of $this->insert()).
$added = array_diff($this->refIDs, $originalIDs);
$this
->insert($added);
}
/**
* Process an entity delete. Loops through the referenced entity IDs and clears
* their references to this entity.
*/
public function delete(array $IDs = array()) {
// As with $this->insert(), we can process a specific set of references or
// everything in the current set.
$IDs = $IDs ? $IDs : $this->refIDs;
foreach ($this
->load($IDs) as $ref) {
$this->right
->getHandler($ref)
->delete($this->entity->cer->owner);
}
}
/**
* Loads referenced entities. This might seem like a convenience method, but it
* is a critical part CER's core logic.
*
* @param array $IDs
* Array of entity IDs to load.
*
* @return array
* The requested entities, wrapped by EntityDrupalWrapper. If nothing could be
* loaded, an empty array is returned.
*/
protected function load(array $IDs) {
if (empty($IDs)) {
return array();
}
$this->right
->rewind();
$right = $this->right
->current();
$entity_type = $right->entityType;
$query = new EntityFieldQuery();
$query
->entityCondition('entity_type', $entity_type);
$query
->entityCondition('entity_id', $IDs);
// If the right entity type has bundles, we need to filter by that too. If we don't,
// we could run into a bug where, if the left field can reference multiple bundles,
// we might try to modify the wrong entity. Essentially, the loading of referenced
// entities should be as targeted as possible to prevent ambiguities and buggery.
if ($right->isBundleable) {
$query
->entityCondition('bundle', $right->bundle);
}
$result = $query
->execute();
if (isset($result[$entity_type])) {
$result[$entity_type] = entity_load($entity_type, array_keys($result[$entity_type]));
foreach ($result[$entity_type] as $id => $entity) {
$result[$entity_type][$id] = new EntityDrupalWrapper($entity_type, $entity);
}
return $result[$entity_type];
}
else {
return array();
}
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
CerPresetHandler:: |
protected | property | ||
CerPresetHandler:: |
protected | property | ||
CerPresetHandler:: |
protected | property | ||
CerPresetHandler:: |
protected | property | ||
CerPresetHandler:: |
public | function | Process an entity delete. Loops through the referenced entity IDs and clears their references to this entity. | |
CerPresetHandler:: |
public | function | Process an entity insert. This loops through the referenced entity $IDs and adds a reference to this entity if the reference doesn't already have one. | |
CerPresetHandler:: |
protected | function | Loads referenced entities. This might seem like a convenience method, but it is a critical part CER's core logic. | |
CerPresetHandler:: |
public | function | Process an entity update. This could be either a normal update done by a user, or a bulk update. | |
CerPresetHandler:: |
public | function |