protected function satisfyDependencies($dependencies) { $required = array(); foreach ($dependencies as $dependency) { $entity = Entity::loadByUUID($dependency['uuid'], $dependency['entity_type']); if (!$entity || array_key_exists('force', $dependency) && $dependency['force'] === true) { $dependency['need revision'] = $dependency['vuuid']; $dependency['have revision'] = ''; $dependency['have your revision'] = ''; $dependency['required_from_remote'] = true; $required[] = $dependency; } else { // Check the entity tracking table. $status = publisher_entity_tracking_get_status($entity->uuid(), $entity->type(), $this->remote->name); $dependency['required'] = false; $dependency['need revision'] = $dependency['vuuid']; $dependency['have revision'] = $entity->vuuid(); // Get the revision from their end that we have. $dependency['have your revision'] = false; if ($entity->supportsRevisions() && is_array($dependency['revisions'])) { $dependency['have your revision'] = self::findMatchingRevision($dependency['revisions'], $entity); } if (!$status) { // If the revision information we have matches, create an entry // in the tracking table and skip it. if (!$this->compareRevisions($dependency['have revision'], $dependency['need revision'])) { // Get the last time the entity was modified. $entity->setRevision($dependency['have revision']); $date = $this->getModificationDate($dependency['have revision']); if (!$date) { if ($entity->supportsRevisions()) { $entity->setRevision(Entity::getLatestRevisionID($entity->id(), $entity->type())); } $date = $entity->getModified(); } publisher_entity_tracking_create_status($entity, $this->remote, array('date_synced' => REQUEST_TIME, 'changed' => $date)); continue; } // Assume that we don't require the latest version by default. $dependency['required_from_remote'] = array_key_exists('requires_latest', $dependency) ? $dependency['requires_latest'] : false; $required[] = $dependency; } else { if (!$status->date_synced || $this->compareRevisions($status->vuuid, $dependency['need revision']) && $dependency['have your revision'] != $dependency['need revision'] || array_key_exists('source_required', $dependency) && $dependency['source_required']) { // If the entity has an entry in the entity tracking table, but changes have // been made to it since the last sync, mark it as changed. $dependency['required_from_remote'] = array_key_exists('requires_latest', $dependency) ? $dependency['requires_latest'] : false; $required[] = $dependency; } } } } return $required; }
protected function applyRevision(Entity &$entity, $revision_payload) { global $user; // Preserve the original entity. $original_entity = clone $entity; // Apply changes to the entity. $entity->definition = (object) array_replace_recursive((array) $entity->definition, (array) $revision_payload['additions']); // Apply deletions to the entity. $deletions_definition = (array) $entity->definition; $keys_to_delete = array(); $this->applyRevisionDeletions($deletions_definition, $revision_payload['deletions'], $keys_to_delete); $entity->definition = (object) $deletions_definition; // Run the beforeDependencies preparer. $preparer_registry = new PreparerRegistry(); $preparer_registry->beforeDependencies($entity); // Revert references. $unresolver = new Unresolver($entity); $entity->definition = $unresolver->unresolvedDefinition(); // Check to see if there were any errors reverting references. if ($errors = $unresolver->errors()) { $this->transaction->addErrors($errors); return false; // Stop processing this entity if there were errors. } // Unset the node VID and the user ID. $entity->definition->revision = true; if (isset($entity->definition->revision_uid)) { $user->uid = $entity->definition->revision_uid; } elseif (isset($entity->definition->uid)) { $user->uid = $entity->definition->uid; } // Get the old stuff for the node. $old_revision_information = array('uid' => $user->uid, 'vuuid' => $entity->vuuid()); // Set unchanging properties to the node that was sent. $unchanging_properties = publisher_get_unchanging_properties($entity->type()); foreach ($unchanging_properties as $property) { if (!isset($revision_payload['additions'][$property])) { continue; } $entity->definition->{$property} = $revision_payload['additions'][$property]; } // Get the revision table for the entity. $entity_info = entity_get_info($entity->type()); if (array_key_exists('revision table', $entity_info)) { $revision_table = $entity_info['revision table']; $revision_key = $entity_info['entity keys']['revision']; $revision_uuid_key = $entity_info['entity keys']['revision uuid']; } // Update the VID to an existing revision. if ($entity->supportsRevisions() && isset($revision_key)) { $this->setEntityRevisionID($entity->vuuid(), $entity); } // Run the preparers beforeSave. $preparer_registry->beforeSave($entity); // Run the entity handlers with the metadata. foreach (EntityHandlerRegistry::getEntityHandlers($entity) as $handler) { if (!$handler instanceof EntityHandlerBase) { continue; } $handler->entity =& $entity; $handler->original_entity = $original_entity; $handler->unhandleRevision($this->getEntityFromMetadata($entity->uuid())); } // Save the entity. try { $entity->save(); } catch (\Exception $ex) { // ...and try to catch any exceptions thrown by this (sometimes, the exceptions still aren't caught). $this->transaction->addError($ex); return false; } if (isset($revision_table) && isset($revision_key)) { // Reset the UID and VUUID for the revision. $cloned_definition = clone $entity->definition; $cloned_definition->uid = $old_revision_information['uid']; $cloned_definition->{$revision_uuid_key} = $old_revision_information['vuuid']; drupal_write_record($revision_table, $cloned_definition, $revision_key); // Delete duplicate revisions that no longer apply. $this->checkForDuplicateRevisions($cloned_definition, $entity); // Reset the revision cache in the entity class. Entity::getLatestRevisionID($entity->id(), $entity->type(), true); } // Run the preparers afterSave events. $preparer_registry->afterSave($entity); return true; }