View source
<?php
namespace Drupal\webform\Entity;
use Drupal\Component\Render\PlainTextOutput;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Serialization\Yaml;
use Drupal\Component\Utility\Crypt;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\Core\Entity\ContentEntityBase;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Entity\EntityChangedTrait;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Site\Settings;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\user\Entity\User;
use Drupal\user\UserInterface;
use Drupal\webform\WebformInterface;
use Drupal\webform\WebformSubmissionInterface;
class WebformSubmission extends ContentEntityBase implements WebformSubmissionInterface {
use EntityChangedTrait;
use StringTranslationTrait;
protected static $webform;
protected $data = [];
protected $originalData = [];
protected $computedData = [];
protected $dataHash;
protected $converting = FALSE;
public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
$fields['serial'] = BaseFieldDefinition::create('integer')
->setLabel(t('Serial number'))
->setDescription(t('The serial number of the webform submission entity.'))
->setReadOnly(TRUE);
$fields['sid'] = BaseFieldDefinition::create('integer')
->setLabel(t('Submission ID'))
->setDescription(t('The ID of the webform submission entity.'))
->setReadOnly(TRUE);
$fields['uuid'] = BaseFieldDefinition::create('uuid')
->setLabel(t('Submission UUID'))
->setDescription(t('The UUID of the webform submission entity.'))
->setReadOnly(TRUE);
$fields['token'] = BaseFieldDefinition::create('string')
->setLabel(t('Token'))
->setDescription(t('A secure token used to look up a submission.'))
->setSetting('max_length', 255)
->setReadOnly(TRUE);
$fields['uri'] = BaseFieldDefinition::create('string')
->setLabel(t('Submission URI'))
->setDescription(t('The URI the user submitted the webform.'))
->setSetting('max_length', 2000)
->setReadOnly(TRUE);
$fields['created'] = BaseFieldDefinition::create('created')
->setLabel(t('Created'))
->setDescription(t('The time that the webform submission was first saved as draft or submitted.'));
$fields['completed'] = BaseFieldDefinition::create('timestamp')
->setLabel(t('Completed'))
->setDescription(t('The time that the webform submission was submitted as complete (not draft).'));
$fields['changed'] = BaseFieldDefinition::create('changed')
->setLabel(t('Changed'))
->setDescription(t('The time that the webform submission was last saved (complete or draft).'));
$fields['in_draft'] = BaseFieldDefinition::create('boolean')
->setLabel(t('Is draft'))
->setDescription(t('Is this a draft of the submission?'))
->setDefaultValue(FALSE);
$fields['current_page'] = BaseFieldDefinition::create('string')
->setLabel(t('Current page'))
->setDescription(t('The current wizard page.'))
->setSetting('max_length', 128);
$fields['remote_addr'] = BaseFieldDefinition::create('string')
->setLabel(t('Remote IP address'))
->setDescription(t('The IP address of the user that submitted the webform.'))
->setSetting('max_length', 128);
$fields['uid'] = BaseFieldDefinition::create('entity_reference')
->setLabel(t('Submitted by'))
->setDescription(t('The username of the user that submitted the webform.'))
->setSetting('target_type', 'user')
->setDefaultValueCallback('Drupal\\webform\\Entity\\WebformSubmission::getCurrentUserId');
$fields['langcode'] = BaseFieldDefinition::create('language')
->setLabel(t('Language'))
->setDescription(t('The submission language code.'));
$fields['webform_id'] = BaseFieldDefinition::create('entity_reference')
->setLabel(t('Webform'))
->setDescription(t('The associated webform.'))
->setSetting('target_type', 'webform');
$fields['entity_type'] = BaseFieldDefinition::create('string')
->setLabel(t('Submitted to: Entity type'))
->setDescription(t('The entity type to which this submission was submitted from.'))
->setSetting('is_ascii', TRUE)
->setSetting('max_length', EntityTypeInterface::ID_MAX_LENGTH);
$fields['entity_id'] = BaseFieldDefinition::create('string')
->setLabel(t('Submitted to: Entity ID'))
->setDescription(t('The ID of the entity of which this webform submission was submitted from.'))
->setSetting('max_length', 255);
$fields['locked'] = BaseFieldDefinition::create('boolean')
->setLabel(t('Locked'))
->setDescription(t('A flag that indicates a locked webform submission.'))
->setDefaultValue(FALSE);
$fields['sticky'] = BaseFieldDefinition::create('boolean')
->setLabel(t('Sticky'))
->setDescription(t('A flag that indicate the status of the webform submission.'))
->setDefaultValue(FALSE);
$fields['notes'] = BaseFieldDefinition::create('string_long')
->setLabel(t('Notes'))
->setDescription(t('Administrative notes about the webform submission.'))
->setDefaultValue('');
return $fields;
}
public function serial() {
return $this
->get('serial')->value;
}
public function label() {
$submission_label = $this
->getWebform()
->getSetting('submission_label') ?: \Drupal::config('webform.settings')
->get('settings.default_submission_label');
$token_manager = \Drupal::service('webform.token_manager');
return PlainTextOutput::renderFromHtml($token_manager
->replaceNoRenderContext($submission_label, $this));
}
public function getLangcode() {
return $this
->get('langcode')->value;
}
public function setLangcode($langcode) {
$this
->set('langcode', $langcode);
return $this;
}
public function getCreatedTime() {
if (isset($this
->get('created')->value)) {
return $this
->get('created')->value;
}
return NULL;
}
public function setCreatedTime($created) {
$this
->set('created', $created);
return $this;
}
public function getChangedTime() {
return $this
->get('changed')->value;
}
public function setChangedTime($timestamp) {
$this
->set('changed', $timestamp);
return $this;
}
public function getCompletedTime() {
return $this
->get('completed')->value;
}
public function setCompletedTime($timestamp) {
$this
->set('completed', $timestamp);
return $this;
}
public function getNotes() {
return $this
->get('notes')->value;
}
public function setNotes($notes) {
$this
->set('notes', $notes);
return $this;
}
public function getSticky() {
return $this
->get('sticky')->value;
}
public function setSticky($sticky) {
$this
->set('sticky', $sticky);
return $this;
}
public function setLocked($locked) {
$this
->set('locked', $locked);
return $this;
}
public function getRemoteAddr() {
return $this
->get('remote_addr')->value ?: $this
->t('(unknown)');
}
public function setRemoteAddr($ip_address) {
$this
->set('remote_addr', $ip_address);
return $this;
}
public function getCurrentPage() {
return $this
->get('current_page')->value;
}
public function setCurrentPage($current_page) {
$this
->set('current_page', $current_page);
return $this;
}
public function getCurrentPageTitle() {
$current_page = $this
->getCurrentPage();
$page = $this
->getWebform()
->getPage('default', $current_page);
return $page && isset($page['#title']) ? $page['#title'] : $current_page;
}
public function getElementData($key) {
$data = $this
->getData();
return isset($data[$key]) ? $data[$key] : NULL;
}
public function setElementData($key, $value) {
if ($this
->getWebform()
->getElement($key)) {
$this->data[$key] = $value;
$this->computedData = NULL;
$this->dataHash = NULL;
}
return $this;
}
public function getRawData() {
return $this->data;
}
public function getData() {
if (isset($this->computedData)) {
return $this->computedData;
}
$theme_manager = \Drupal::service('webform.theme_manager');
if (!$theme_manager
->hasActiveTheme()) {
return $this->data;
}
$this->computedData = $this->data;
$webform = $this
->getWebform();
if ($webform
->hasComputed()) {
$element_manager = \Drupal::service('plugin.manager.webform.element');
$computed_elements = $webform
->getElementsComputed();
foreach ($computed_elements as $computed_element_name) {
$computed_element = $webform
->getElement($computed_element_name);
$element_plugin = $element_manager
->getElementInstance($computed_element);
$this->computedData[$computed_element_name] = $element_plugin
->computeValue($computed_element, $this);
}
}
return $this->computedData;
}
public function setData(array $data) {
$this->data = $data;
$this->computedData = NULL;
$this->dataHash = NULL;
return $this;
}
public function getOriginalData() {
return $this->originalData;
}
public function setOriginalData(array $data) {
$this->originalData = $data;
return $this;
}
public function getElementOriginalData($key) {
return isset($this->originalData[$key]) ? $this->originalData[$key] : NULL;
}
public function getDataHash() {
if (isset($this->dataHash)) {
return $this->dataHash;
}
$this->dataHash = Crypt::hmacBase64(serialize($this
->getRawData()), Settings::getHashSalt());
return $this->dataHash;
}
public function getToken() {
return $this->token->value;
}
public function getWebform() {
if (isset($this->webform_id->entity)) {
return $this->webform_id->entity;
}
else {
return static::$webform;
}
}
public function getSourceEntity($translate = FALSE) {
if ($this->entity_type->value && $this->entity_id->value) {
$entity_type = $this->entity_type->value;
$entity_id = $this->entity_id->value;
$source_entity = $this
->entityTypeManager()
->getStorage($entity_type)
->load($entity_id);
if ($translate && $source_entity instanceof ContentEntityInterface) {
$langcode = $this
->language()
->getId();
if ($source_entity
->hasTranslation($langcode)) {
$source_entity = $source_entity
->getTranslation($langcode);
}
}
return $source_entity;
}
else {
return NULL;
}
}
public function getSourceUrl() {
$uri = $this->uri->value;
if ($uri !== NULL && ($url = \Drupal::pathValidator()
->getUrlIfValid($uri))) {
return $url
->setOption('absolute', TRUE);
}
elseif (($entity = $this
->getSourceEntity()) && $entity
->hasLinkTemplate('canonical')) {
return $entity
->toUrl()
->setOption('absolute', TRUE);
}
else {
return $this
->getWebform()
->toUrl()
->setOption('absolute', TRUE);
}
}
public function getTokenUrl($operation = 'update') {
switch ($operation) {
case 'view':
$request_handler = \Drupal::service('webform.request');
$url = $request_handler
->getUrl($this, $this
->getSourceEntity(), 'webform.user.submission');
break;
case 'update':
$url = $this
->getSourceUrl();
break;
case 'delete':
$request_handler = \Drupal::service('webform.request');
$url = $request_handler
->getUrl($this, $this
->getSourceEntity(), 'webform.user.submission.delete');
break;
default:
throw new \Exception("Token URL operation {$operation} is not supported");
}
$options = $url
->setAbsolute()
->getOptions();
$options['query']['token'] = $this
->getToken();
return $url
->setOptions($options);
}
public function invokeWebformHandlers($method, &$context1 = NULL, &$context2 = NULL, &$context3 = NULL) {
if ($webform = $this
->getWebform()) {
return $webform
->invokeHandlers($method, $this, $context1, $context2, $context3);
}
}
public function invokeWebformElements($method, &$context1 = NULL, &$context2 = NULL, &$context3 = NULL) {
if ($webform = $this
->getWebform()) {
$webform
->invokeElements($method, $this, $context1, $context2, $context3);
}
}
public function getOwner() {
$user = $this
->get('uid')->entity;
if (!$user || $user
->isAnonymous()) {
$user = User::getAnonymousUser();
}
return $user;
}
public function getOwnerId() {
return $this
->get('uid')->target_id;
}
public function setOwnerId($uid) {
$this
->set('uid', $uid);
return $this;
}
public function setOwner(UserInterface $account) {
$this
->set('uid', $account
->id());
return $this;
}
public function isDraft() {
return $this
->get('in_draft')->value ? TRUE : FALSE;
}
public function isConverting() {
return $this->converting;
}
public function isCompleted() {
return $this
->get('completed')->value ? TRUE : FALSE;
}
public function isLocked() {
return $this
->get('locked')->value ? TRUE : FALSE;
}
public function isSticky() {
return (bool) $this
->get('sticky')->value;
}
public function isOwner(AccountInterface $account) {
if ($account
->isAnonymous()) {
return !empty($_SESSION['webform_submissions']) && isset($_SESSION['webform_submissions'][$this
->id()]);
}
else {
return $account
->id() === $this
->getOwnerId();
}
}
public function hasNotes() {
return $this->notes ? TRUE : FALSE;
}
public function getState() {
if (!$this
->id()) {
return WebformSubmissionInterface::STATE_UNSAVED;
}
elseif ($this
->isConverting()) {
return WebformSubmissionInterface::STATE_CONVERTED;
}
elseif ($this
->isDraft()) {
return $this->created->value === $this->changed->value ? WebformSubmissionInterface::STATE_DRAFT_CREATED : WebformSubmissionInterface::STATE_DRAFT_UPDATED;
}
elseif ($this
->isLocked()) {
return WebformSubmissionInterface::STATE_LOCKED;
}
elseif ($this->completed->value === $this->changed->value) {
return WebformSubmissionInterface::STATE_COMPLETED;
}
else {
return WebformSubmissionInterface::STATE_UPDATED;
}
}
protected function urlRouteParameters($rel) {
$uri_route_parameters = parent::urlRouteParameters($rel);
$webform = $this
->getWebform();
if ($webform) {
$uri_route_parameters['webform'] = $webform
->id();
}
return $uri_route_parameters;
}
public function createDuplicate() {
$duplicate = parent::createDuplicate();
$duplicate
->set('serial', NULL);
$duplicate
->set('token', Crypt::randomBytesBase64());
$duplicate
->set('in_draft', FALSE);
$duplicate
->set('current_page', NULL);
$duplicate
->set('created', NULL);
$duplicate
->set('changed', NULL);
$duplicate
->set('completed', NULL);
$duplicate
->set('notes', '');
$duplicate
->set('sticky', FALSE);
$duplicate
->set('locked', FALSE);
return $duplicate;
}
public static function preCreate(EntityStorageInterface $storage, array &$values) {
if (empty($values['webform_id']) && empty($values['webform'])) {
if (empty($values['webform_id'])) {
throw new \Exception('Webform id (webform_id) is required to create a webform submission.');
}
elseif (empty($values['webform'])) {
throw new \Exception('Webform (webform) is required to create a webform submission.');
}
}
if (isset($values['webform']) && $values['webform'] instanceof WebformInterface) {
$webform = $values['webform'];
static::$webform = $values['webform'];
$values['webform_id'] = $values['webform']
->id();
}
else {
$webform = Webform::load($values['webform_id']);
static::$webform = NULL;
}
$request_handler = \Drupal::service('webform.request');
$source_entity = $request_handler
->getCurrentSourceEntity('webform');
$values += [
'entity_type' => $source_entity ? $source_entity
->getEntityTypeId() : NULL,
'entity_id' => $source_entity ? $source_entity
->id() : NULL,
];
if (empty($values['data'])) {
$values['data'] = [];
}
elseif (is_string($values['data'])) {
$values['data'] = Yaml::decode($values['data']);
}
if ($values['entity_type'] && $values['entity_id']) {
$source_entity = \Drupal::entityTypeManager()
->getStorage($values['entity_type'])
->load($values['entity_id']);
$entity_reference_manager = \Drupal::service('webform.entity_reference_manager');
if ($webform_field_name = $entity_reference_manager
->getFieldName($source_entity)) {
if ($source_entity->{$webform_field_name}->target_id === $webform
->id() && $source_entity->{$webform_field_name}->default_data) {
$values['data'] += Yaml::decode($source_entity->{$webform_field_name}->default_data);
}
}
}
$current_request = \Drupal::requestStack()
->getCurrentRequest();
$values += [
'in_draft' => FALSE,
'uid' => \Drupal::currentUser()
->id(),
'langcode' => \Drupal::languageManager()
->getCurrentLanguage()
->getId(),
'token' => Crypt::randomBytesBase64(),
'uri' => preg_replace('#^' . base_path() . '#', '/', $current_request
->getRequestUri()),
'remote_addr' => $webform && $webform
->hasRemoteAddr() ? $current_request
->getClientIp() : '',
];
$webform
->invokeHandlers(__FUNCTION__, $values);
$webform
->invokeElements(__FUNCTION__, $values);
}
public function preSave(EntityStorageInterface $storage) {
if (isset($this->original)) {
$this->original
->setData($this->originalData);
$this->original
->setOriginalData($this->original
->getData());
}
$request_time = \Drupal::time()
->getRequestTime();
if (!$this->created->value) {
$this->created->value = $request_time;
}
$this->changed->value = $request_time;
if ($this
->isDraft()) {
$this->completed->value = NULL;
}
elseif (!$this
->isCompleted()) {
$this->completed->value = $request_time;
}
parent::preSave($storage);
}
public function postSave(EntityStorageInterface $storage, $update = TRUE) {
parent::postSave($storage, $update);
}
public function save() {
if (!$this
->getWebform()
->hasRemoteAddr()) {
$this
->get('remote_addr')->value = '';
}
return parent::save();
}
public function resave() {
return $this
->entityTypeManager()
->getStorage($this->entityTypeId)
->resave($this);
}
public function access($operation, AccountInterface $account = NULL, $return_as_object = FALSE) {
$access = parent::access($operation, $account, TRUE)
->orIf($this
->invokeWebformHandlers('access', $operation, $account));
return $return_as_object ? $access : $access
->isAllowed();
}
public function convert(UserInterface $account) {
$this->converting = TRUE;
$this
->setOwner($account);
$this
->save();
$this->converting = FALSE;
}
public function toArray($custom = FALSE, $check_access = FALSE) {
if ($custom === FALSE) {
return parent::toArray();
}
else {
$values = parent::toArray();
foreach ($values as $key => $item) {
if (empty($item)) {
$values[$key] = '';
}
else {
$value = reset($item);
$values[$key] = reset($value);
}
}
$values['data'] = $this
->getData();
if ($check_access) {
$submission_storage = \Drupal::entityTypeManager()
->getStorage('webform_submission');
$field_definitions = $submission_storage
->getFieldDefinitions();
$field_definitions = $submission_storage
->checkFieldDefinitionAccess($this
->getWebform(), $field_definitions + [
'data' => TRUE,
]);
$values = array_intersect_key($values, $field_definitions);
$elements = $this
->getWebform()
->getElementsInitializedFlattenedAndHasValue('view');
$values['data'] = array_intersect_key($values['data'], $elements);
}
return $values;
}
}
public static function getCurrentUserId() {
return [
\Drupal::currentUser()
->id(),
];
}
}