salesforce-8.x-4.x-dev/modules/salesforce_mapping_ui/src/Form/MappedObjectForm.php
modules/salesforce_mapping_ui/src/Form/MappedObjectForm.php
<?php
namespace Drupal\salesforce_mapping_ui\Form;
use Drupal\Component\Datetime\TimeInterface;
use Drupal\Core\Entity\ContentEntityForm;
use Drupal\Core\Entity\EntityRepositoryInterface;
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\salesforce\Event\SalesforceErrorEvent;
use Drupal\salesforce\Event\SalesforceEvents;
use Drupal\salesforce\SFID;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\RequestStack;
/**
* Salesforce Mapping Form base.
*/
class MappedObjectForm extends ContentEntityForm {
/**
* Mapping entity storage service.
*
* @var \Drupal\salesforce_mapping\SalesforceMappingStorage
*/
protected $mappingStorage;
/**
* Mapped object storage service.
*
* @var \Drupal\salesforce_mapping\MappedObjectStorage
*/
protected $mappedObjectStorage;
/**
* Event dispatcher service.
*
* @var \Symfony\Component\EventDispatcher\EventDispatcherInterface
*/
protected $eventDispatcher;
/**
* Route matching service.
*
* @var \Symfony\Component\HttpFoundation\RequestStack
*/
protected $request;
/**
* Entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* MappedObjectForm constructor.
*
* @param \Drupal\Core\Entity\EntityRepositoryInterface $entityRepository
* Entity repository service.
* @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $entityTypeBundleInfo
* Bundle info service.
* @param \Drupal\Component\Datetime\TimeInterface $time
* Time service.
* @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher
* Event dispatcher service.
* @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
* Request stack.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $etm
* Entity manager service.
*
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
*/
public function __construct(EntityRepositoryInterface $entityRepository, EntityTypeBundleInfoInterface $entityTypeBundleInfo, TimeInterface $time, EventDispatcherInterface $event_dispatcher, RequestStack $request_stack, EntityTypeManagerInterface $etm) {
parent::__construct($entityRepository, $entityTypeBundleInfo, $time);
$this->eventDispatcher = $event_dispatcher;
$this->request = $request_stack->getCurrentRequest();
$this->entityTypeManager = $etm;
$this->mappingStorage = $etm->getStorage('salesforce_mapping');
$this->mappedObjectStorage = $etm->getStorage('salesforce_mapped_object');
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('entity.repository'),
$container->get('entity_type.bundle.info'),
$container->get('datetime.time'),
$container->get('event_dispatcher'),
$container->get('request_stack'),
$container->get('entity_type.manager')
);
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {
// Include the parent entity on the form.
$form = parent::buildForm($form, $form_state);
if ($this->entity->isNew()) {
if ($drupal_entity = $this->getDrupalEntityFromUrl()) {
$form['drupal_entity']['widget'][0]['target_type']['#default_value'] = $drupal_entity->getEntityTypeId();
$form['drupal_entity']['widget'][0]['target_id']['#default_value'] = $drupal_entity;
}
}
// Allow exception to bubble up here, because we shouldn't have got here if
// there isn't a mapping.
// If entity is not set, entity types are dependent on available mappings.
$mappings = $this
->mappingStorage
->loadMultiple();
// @todo #states for entity-type + salesforce mapping dependency
if ($mappings) {
$options = array_keys($mappings);
// Filter options based on drupal entity type.
$form['salesforce_mapping']['widget']['#options'] = array_intersect_key($form['salesforce_mapping']['widget']['#options'], array_flip($options));
}
$form['actions']['push'] = [
'#type' => 'submit',
'#value' => $this->t('Push'),
'#weight' => 5,
'#submit' => [[$this, 'submitPush']],
'#validate' => [[$this, 'validateForm'], [$this, 'validatePush']],
];
$form['actions']['pull'] = [
'#type' => 'submit',
'#value' => $this->t('Pull'),
'#weight' => 6,
'#submit' => [[$this, 'submitPull']],
'#validate' => [[$this, 'validateForm'], [$this, 'validatePull']],
];
return $form;
}
/**
* Verify that entity type and mapping agree.
*/
public function validatePush(array &$form, FormStateInterface $form_state) {
$drupal_entity_array = $form_state->getValue(['drupal_entity', 0]);
// Verify entity was given - required for push.
if (empty($drupal_entity_array['target_id'])) {
$form_state->setErrorByName('drupal_entity][0][target_id', $this->t('Please specify an entity to push.'));
return;
}
}
/**
* Salesforce ID is required for a pull.
*/
public function validatePull(array &$form, FormStateInterface $form_state) {
// Verify SFID was given - required for pull.
$sfid = $form_state->getValue(['salesforce_id', 0, 'value'], FALSE);
if (!$sfid) {
$form_state->setErrorByName('salesforce_id', $this->t('Please specify a Salesforce ID to pull.'));
return;
}
}
/**
* Submit handler for "push" button.
*/
public function submitPush(array &$form, FormStateInterface $form_state) {
$drupal_entity_array = $form_state->getValue(['drupal_entity', 0]);
$mapped_object = $this->entity;
$mapped_object
->set('drupal_entity', $drupal_entity_array)
->set('salesforce_mapping', $form_state->getValue([
'salesforce_mapping',
0,
'target_id',
]));
if ($sfid = $form_state->getValue(['salesforce_id', 0, 'value'], FALSE)) {
$mapped_object->set('salesforce_id', (string) new SFID($sfid));
}
else {
$mapped_object->set('salesforce_id', '');
}
// Push to SF.
try {
// Push calls save(), so this is all we need to do:
$mapped_object->push();
}
catch (\Exception $e) {
$mapped_object->delete();
$this->eventDispatcher->dispatch(new SalesforceErrorEvent($e), SalesforceEvents::ERROR);
$this->messenger()
->addError($this->t('Push failed with an exception: %exception', ['%exception' => $e->getMessage()]));
$form_state->setRebuild();
return;
}
// @todo more verbose feedback for successful push.
$this->messenger()->addStatus('Push successful.');
$form_state->setRedirect('entity.salesforce_mapped_object.canonical', ['salesforce_mapped_object' => $mapped_object->id()]);
}
/**
* Submit handler for "pull" button.
*/
public function submitPull(array &$form, FormStateInterface $form_state) {
$mapping_id = $form_state->getValue(['salesforce_mapping', 0, 'target_id']);
$sfid = new SFID($form_state->getValue(['salesforce_id', 0, 'value']));
$mapped_object = $this->entity
->set('salesforce_id', (string) $sfid)
->set('salesforce_mapping', $mapping_id);
// Create stub entity.
$drupal_entity_array = $form_state->getValue(['drupal_entity', 0]);
if ($drupal_entity_array['target_id']) {
$drupal_entity = $this->entityTypeManager
->getStorage($drupal_entity_array['target_type'])
->load($drupal_entity_array['target_id']);
$mapped_object->set('drupal_entity', $drupal_entity);
}
else {
$drupal_entity = $this->entityTypeManager
->getStorage($drupal_entity_array['target_type'])
->create(['salesforce_pull' => TRUE]);
$mapped_object->set('drupal_entity', NULL);
$mapped_object->setDrupalEntityStub($drupal_entity);
}
try {
// Pull from SF. Save first to pass local validation.
$mapped_object->save();
$mapped_object->pull();
}
catch (\Exception $e) {
$this->eventDispatcher->dispatch(new SalesforceErrorEvent($e), SalesforceEvents::ERROR);
$this->messenger()
->addError($this->t('Pull failed with an exception: %exception', ['%exception' => $e->getMessage()]));
$form_state->setRebuild();
return;
}
// @todo more verbose feedback for successful pull.
$this->messenger()->addStatus('Pull successful.');
$form_state->setRedirect('entity.salesforce_mapped_object.canonical', ['salesforce_mapped_object' => $mapped_object->id()]);
}
/**
* {@inheritdoc}
*/
public function save(array $form, FormStateInterface $form_state) {
$ret = $this->getEntity()->save();
$this->messenger()
->addStatus($this->t('The mapping has been successfully saved.'));
$form_state->setRedirect('entity.salesforce_mapped_object.canonical', [
'salesforce_mapped_object' => $this->getEntity()
->id(),
]);
return $ret;
}
/**
* Helper to fetch the contextual Drupal entity.
*/
private function getDrupalEntityFromUrl() {
// Fetch the current entity from context.
// @todo what if there's more than one entity in route params?
$entity_type_id = $this->request->query->get('entity_type_id');
$entity_id = $this->request->query->get('entity_id');
if (empty($entity_id) || empty($entity_type_id)) {
return FALSE;
}
return $this->entityTypeManager
->getStorage($entity_type_id)
->load($entity_id);
}
}
