class WebformSubmissionStorage in Webform 6.x
Same name and namespace in other branches
- 8.5 src/WebformSubmissionStorage.php \Drupal\webform\WebformSubmissionStorage
Defines the webform submission storage.
Hierarchy
- class \Drupal\Core\Entity\EntityHandlerBase uses DependencySerializationTrait, StringTranslationTrait
- class \Drupal\Core\Entity\EntityStorageBase implements EntityHandlerInterface, EntityStorageInterface
- class \Drupal\Core\Entity\ContentEntityStorageBase implements ContentEntityStorageInterface, DynamicallyFieldableEntityStorageInterface
- class \Drupal\Core\Entity\Sql\SqlContentEntityStorage implements EntityBundleListenerInterface, DynamicallyFieldableEntityStorageSchemaInterface, SqlEntityStorageInterface
- class \Drupal\webform\WebformSubmissionStorage implements WebformSubmissionStorageInterface uses WebformEntityStorageTrait
- class \Drupal\Core\Entity\Sql\SqlContentEntityStorage implements EntityBundleListenerInterface, DynamicallyFieldableEntityStorageSchemaInterface, SqlEntityStorageInterface
- class \Drupal\Core\Entity\ContentEntityStorageBase implements ContentEntityStorageInterface, DynamicallyFieldableEntityStorageInterface
- class \Drupal\Core\Entity\EntityStorageBase implements EntityHandlerInterface, EntityStorageInterface
Expanded class hierarchy of WebformSubmissionStorage
File
- src/
WebformSubmissionStorage.php, line 22
Namespace
Drupal\webformView source
class WebformSubmissionStorage extends SqlContentEntityStorage implements WebformSubmissionStorageInterface {
use WebformEntityStorageTrait;
/**
* Array used to element data schema.
*
* @var array
*/
protected $elementDataSchema = [];
/**
* The time service.
*
* @var \Drupal\Component\Datetime\TimeInterface
*/
protected $time;
/**
* The current user.
*
* @var \Drupal\Core\Session\AccountProxyInterface
*/
protected $currentUser;
/**
* The replica kill switch.
*
* @var \Drupal\Core\Database\ReplicaKillSwitch
*/
protected $replicaKillSwitch;
/**
* The file system service.
*
* @var \Drupal\Core\File\FileSystemInterface
*/
protected $fileSystem;
/**
* The stream wrapper manager.
*
* @var \Drupal\Core\StreamWrapper\StreamWrapperManagerInterface
*/
protected $streamWrapperManager;
/**
* The logger factory.
*
* @var \Drupal\Core\Logger\LoggerChannelFactoryInterface
*/
protected $loggerFactory;
/**
* The entity type repository.
*
* @var \Drupal\Core\Entity\EntityTypeRepositoryInterface
*/
protected $entityTypeRepository;
/**
* The webform access rules manager service.
*
* @var \Drupal\webform\WebformAccessRulesManagerInterface
*/
protected $accessRulesManager;
/**
* The webform element plugin manager.
*
* @var \Drupal\webform\Plugin\WebformElementManagerInterface
*/
protected $elementManager;
/**
* {@inheritdoc}
*/
public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) {
$instance = parent::createInstance($container, $entity_type);
$instance->time = $container
->get('datetime.time');
$instance->replicaKillSwitch = $container
->get('database.replica_kill_switch');
$instance->currentUser = $container
->get('current_user');
$instance->fileSystem = $container
->get('file_system');
$instance->streamWrapperManager = $container
->get('stream_wrapper_manager');
$instance->loggerFactory = $container
->get('logger.factory');
$instance->entityTypeRepository = $container
->get('entity_type.repository');
$instance->accessRulesManager = $container
->get('webform.access_rules_manager');
$instance->elementManager = $container
->get('plugin.manager.webform.element');
return $instance;
}
/**
* {@inheritdoc}
*/
public function getFieldDefinitions() {
/** @var \Drupal\Core\Field\BaseFieldDefinition[] $definitions */
$field_definitions = $this->entityFieldManager
->getBaseFieldDefinitions('webform_submission');
// For now never let any see or export the serialize YAML data field.
unset($field_definitions['data']);
$definitions = [];
foreach ($field_definitions as $field_name => $field_definition) {
// Exclude the 'map' field type which is used by the metatag.module.
if ($field_definition
->getType() === 'map') {
continue;
}
$definitions[$field_name] = [
'title' => $field_definition
->getLabel(),
'name' => $field_name,
'type' => $field_definition
->getType(),
'target_type' => $field_definition
->getSetting('target_type'),
];
}
return $definitions;
}
/**
* {@inheritdoc}
*/
public function checkFieldDefinitionAccess(WebformInterface $webform, array $definitions) {
if (!$webform
->access('submission_update_any')) {
unset($definitions['token']);
}
return $definitions;
}
/**
* {@inheritdoc}
*/
protected function doCreate(array $values) {
/** @var \Drupal\webform\WebformSubmissionInterface $entity */
$entity = parent::doCreate($values);
if (!empty($values['data'])) {
$data = is_array($values['data']) ? $values['data'] : Yaml::decode($values['data']);
$entity
->setData($data);
}
return $entity;
}
/**
* {@inheritdoc}
*/
protected function doLoadMultiple(array $ids = NULL) {
/** @var \Drupal\webform\WebformSubmissionInterface[] $webform_submissions */
$webform_submissions = parent::doLoadMultiple($ids);
$this
->loadData($webform_submissions);
return $webform_submissions;
}
/**
* {@inheritdoc}
*/
public function loadByEntities(WebformInterface $webform = NULL, EntityInterface $source_entity = NULL, AccountInterface $account = NULL) {
$properties = [];
if ($webform) {
$properties['webform_id'] = $webform
->id();
}
if ($source_entity) {
$properties['entity_type'] = $source_entity
->getEntityTypeId();
$properties['entity_id'] = $source_entity
->id();
}
if ($account) {
$properties['uid'] = $account
->id();
}
return $this
->loadByProperties($properties);
}
/**
* {@inheritdoc}
*/
public function loadFromToken($token, WebformInterface $webform, EntityInterface $source_entity = NULL, AccountInterface $account = NULL) {
// Check token.
if (!$token) {
return NULL;
}
// Check that (secure) tokens are enabled for the webform.
if (!$account && !$webform
->getSetting('token_update')) {
return NULL;
}
// Attempt to load the submission using the token.
$properties = [
'token' => $token,
];
// Add optional source entity to properties.
if ($source_entity) {
$properties['entity_type'] = $source_entity
->getEntityTypeId();
$properties['entity_id'] = $source_entity
->id();
}
// Add optional user account to properties.
if ($account) {
$properties['uid'] = $account
->id();
}
$entities = $this
->loadByProperties($properties);
if (empty($entities)) {
return NULL;
}
/** @var \Drupal\webform\WebformSubmissionInterface $entity */
$entity = reset($entities);
// Make sure the submission is associated with the webform.
if ($entity
->getWebform()
->id() !== $webform
->id()) {
return NULL;
}
return $entity;
}
/**
* {@inheritdoc}
*/
protected function buildPropertyQuery(QueryInterface $entity_query, array $values) {
// Add account query when ever filtered by uid.
if (isset($values['uid'])) {
$uids = (array) $values['uid'];
$accounts = User::loadMultiple($uids);
$or_condition_group = $entity_query
->orConditionGroup();
foreach ($accounts as $account) {
$this
->addQueryConditions($or_condition_group, NULL, NULL, $account);
}
$entity_query
->condition($or_condition_group);
unset($values['uid']);
}
parent::buildPropertyQuery($entity_query, $values);
}
/**
* {@inheritdoc}
*/
public function deleteAll(WebformInterface $webform = NULL, EntityInterface $source_entity = NULL, $limit = NULL, $max_sid = NULL) {
$query = $this
->getQuery();
$query
->accessCheck(FALSE);
$this
->addQueryConditions($query, $webform, $source_entity, NULL);
if ($max_sid) {
$query
->condition('sid', $max_sid, '<=');
}
$query
->sort('sid');
if ($limit) {
$query
->range(0, $limit);
}
$entity_ids = $query
->execute();
$entities = $this
->loadMultiple($entity_ids);
$this
->delete($entities);
return count($entities);
}
/**
* {@inheritdoc}
*/
public function getTotal(WebformInterface $webform = NULL, EntityInterface $source_entity = NULL, AccountInterface $account = NULL, array $options = []) {
// Default total to only look at completed submissions.
$options += [
'in_draft' => FALSE,
];
$query = $this
->getQuery();
$query
->accessCheck(FALSE);
$this
->addQueryConditions($query, $webform, $source_entity, $account, $options);
$query
->count();
return $query
->execute();
}
/**
* {@inheritdoc}
*/
public function getMaxSubmissionId(WebformInterface $webform = NULL, EntityInterface $source_entity = NULL, AccountInterface $account = NULL) {
$query = $this
->getQuery();
$query
->accessCheck(FALSE);
$this
->addQueryConditions($query, $webform, $source_entity, $account);
$query
->sort('sid', 'DESC');
$query
->range(0, 1);
$result = $query
->execute();
return reset($result);
}
/**
* {@inheritdoc}
*/
public function hasSubmissionValue(WebformInterface $webform, $element_key) {
/** @var \Drupal\Core\Database\StatementInterface $result */
$result = $this->database
->select('webform_submission_data', 'sd')
->fields('sd', [
'sid',
])
->condition('sd.webform_id', $webform
->id())
->condition('sd.name', $element_key)
->range(0, 1)
->execute();
return $result
->fetchAssoc() ? TRUE : FALSE;
}
/****************************************************************************/
// Source entity methods.
/****************************************************************************/
/**
* {@inheritdoc}
*/
public function getSourceEntitiesTotal(WebformInterface $webform) {
$query = $this->database
->select('webform_submission', 's')
->fields('s', [
'entity_type',
'entity_id',
])
->condition('webform_id', $webform
->id())
->condition('entity_type', '', '<>')
->isNotNull('entity_type')
->condition('entity_id', '', '<>')
->isNotNull('entity_id')
->distinct();
return (int) $query
->countQuery()
->execute()
->fetchField();
}
/**
* {@inheritdoc}
*/
public function getSourceEntities(WebformInterface $webform) {
/** @var \Drupal\Core\Database\StatementInterface $result */
$result = $this->database
->select('webform_submission', 's')
->fields('s', [
'entity_type',
'entity_id',
])
->condition('webform_id', $webform
->id())
->condition('entity_type', '', '<>')
->isNotNull('entity_type')
->condition('entity_id', '', '<>')
->isNotNull('entity_id')
->distinct()
->execute();
$source_entities = [];
while ($record = $result
->fetchAssoc()) {
$source_entities[$record['entity_type']][$record['entity_id']] = $record['entity_id'];
}
return $source_entities;
}
/**
* {@inheritdoc}
*/
public function getSourceEntitiesAsOptions(WebformInterface $webform) {
$options = [];
$source_entities = $this
->getSourceEntities($webform);
foreach ($source_entities as $entity_type => $entity_ids) {
$optgroup = (string) $this->entityTypeManager
->getDefinition($entity_type)
->getCollectionLabel();
$entities = $this->entityTypeManager
->getStorage($entity_type)
->loadMultiple($entity_ids);
foreach ($entities as $entity_id => $entity) {
if ($entity instanceof TranslatableInterface && $entity
->hasTranslation($this->languageManager
->getCurrentLanguage()
->getId())) {
$entity = $entity
->getTranslation($this->languageManager
->getCurrentLanguage()
->getId());
}
$option_value = "{$entity_type}:{$entity_id}";
$option_text = $entity
->label();
$options[$optgroup][$option_value] = $option_text;
}
if (isset($options[$optgroup])) {
asort($options[$optgroup]);
}
}
return count($options) === 1 ? reset($options) : $options;
}
/****************************************************************************/
// Query methods.
/****************************************************************************/
/**
* Add condition to submission query.
*
* @param \Drupal\Core\Database\Query\AlterableInterface|\Drupal\Core\Entity\Query\ConditionInterface $query
* A SQL query or entity conditions.
* @param \Drupal\webform\WebformInterface $webform
* (optional) A webform.
* @param \Drupal\Core\Entity\EntityInterface|null $source_entity
* (optional) A webform submission source entity.
* @param \Drupal\Core\Session\AccountInterface $account
* (optional) The current user account.
* @param array $options
* (optional) Additional options and query conditions.
* Options/conditions include:
* - in_draft (boolean): NULL will return all saved submissions and drafts.
* Defaults to NULL
* - check_source_entity (boolean): Check that a source entity is defined.
* - interval (int): Limit total within an seconds interval.
* - check_access (boolean): Check access to the submission.
*/
public function addQueryConditions($query, WebformInterface $webform = NULL, EntityInterface $source_entity = NULL, AccountInterface $account = NULL, array $options = []) {
// Set default options/conditions.
$options += [
'check_source_entity' => FALSE,
'in_draft' => NULL,
'interval' => NULL,
'access_check' => TRUE,
];
if ($webform) {
$query
->condition('webform_id', $webform
->id());
}
if ($source_entity) {
$query
->condition('entity_type', $source_entity
->getEntityTypeId());
$query
->condition('entity_id', $source_entity
->id());
}
elseif ($options['check_source_entity']) {
$query
->notExists('entity_type');
$query
->notExists('entity_id');
}
if ($account) {
$query
->condition('uid', $account
->id());
// Add anonymous submission ids stored in $_SESSION.
if ($account
->isAnonymous() && (int) $account
->id() === (int) $this->currentUser
->id()) {
$sids = $this
->getAnonymousSubmissionIds($account);
if (empty($sids)) {
// Look for NULL sid to force returning no results.
$query
->condition('sid', NULL);
}
else {
$query
->condition('sid', $sids, 'IN');
}
}
}
if ($options['in_draft'] !== NULL) {
// Cast boolean to integer to support SQLite.
$query
->condition('in_draft', (int) $options['in_draft']);
}
if ($options['interval']) {
$query
->condition('completed', $this->time
->getRequestTime() - $options['interval'], '>');
}
if ($options['access_check'] === FALSE) {
$query
->accessCheck(FALSE);
}
}
/****************************************************************************/
// Paging methods.
/****************************************************************************/
/**
* {@inheritdoc}
*/
public function getFirstSubmission(WebformInterface $webform, EntityInterface $source_entity = NULL, AccountInterface $account = NULL, array $options = []) {
return $this
->getTerminusSubmission($webform, $source_entity, $account, $options, 'first');
}
/**
* {@inheritdoc}
*/
public function getLastSubmission(WebformInterface $webform, EntityInterface $source_entity = NULL, AccountInterface $account = NULL, array $options = []) {
return $this
->getTerminusSubmission($webform, $source_entity, $account, $options, 'last');
}
/**
* {@inheritdoc}
*/
public function getPreviousSubmission(WebformSubmissionInterface $webform_submission, EntityInterface $source_entity = NULL, AccountInterface $account = NULL, array $options = []) {
return $this
->getSiblingSubmission($webform_submission, $source_entity, $account, $options, 'previous');
}
/**
* {@inheritdoc}
*/
public function getNextSubmission(WebformSubmissionInterface $webform_submission, EntityInterface $source_entity = NULL, AccountInterface $account = NULL, array $options = []) {
return $this
->getSiblingSubmission($webform_submission, $source_entity, $account, $options, 'next');
}
/**
* {@inheritdoc}
*/
public function getSourceEntityTypes(WebformInterface $webform) {
$entity_types = Database::getConnection()
->select('webform_submission', 's')
->distinct()
->fields('s', [
'entity_type',
])
->condition('s.webform_id', $webform
->id())
->condition('s.entity_type', 'webform', '<>')
->orderBy('s.entity_type', 'ASC')
->execute()
->fetchCol();
$entity_type_labels = $this->entityTypeRepository
->getEntityTypeLabels();
ksort($entity_type_labels);
return array_intersect_key($entity_type_labels, array_flip($entity_types));
}
/**
* {@inheritdoc}
*/
public function getSourceEntityAsOptions(WebformInterface $webform, $entity_type) {
$entity_ids = Database::getConnection()
->select('webform_submission', 's')
->fields('s', [
'entity_id',
])
->condition('s.webform_id', $webform
->id())
->condition('s.entity_type', $entity_type)
->execute()
->fetchCol();
// Limit the number of source entities loaded to 100.
if (empty($entity_ids) || count($entity_ids) > 100) {
return [];
}
$entities = $this->entityTypeManager
->getStorage($entity_type)
->loadMultiple($entity_ids);
$options = [];
foreach ($entities as $entity_id => $entity) {
$options[$entity_id] = $entity
->label();
}
asort($options);
return $options;
}
/**
* Get a webform submission's terminus (aka first or last).
*
* @param \Drupal\webform\WebformInterface $webform
* A webform.
* @param \Drupal\Core\Entity\EntityInterface|null $source_entity
* (optional) A webform submission source entity.
* @param \Drupal\Core\Session\AccountInterface $account
* The current user account.
* @param array $options
* (optional) Additional options and query conditions.
* @param string $terminus
* Submission terminus, first or last.
*
* @return \Drupal\webform\WebformSubmissionInterface|null
* The webform submission's terminus (aka first or last).
*/
protected function getTerminusSubmission(WebformInterface $webform, EntityInterface $source_entity = NULL, AccountInterface $account = NULL, array $options = [], $terminus = 'first') {
$options += [
'in_draft' => FALSE,
];
$query = $this
->getQuery();
$this
->addQueryConditions($query, $webform, $source_entity, $account, $options);
$query
->sort('sid', $terminus === 'first' ? 'ASC' : 'DESC');
$query
->range(0, 1);
return ($entity_ids = $query
->execute()) ? $this
->load(reset($entity_ids)) : NULL;
}
/**
* Get a webform submission's sibling.
*
* @param \Drupal\webform\WebformSubmissionInterface $webform_submission
* A webform submission.
* @param \Drupal\Core\Entity\EntityInterface|null $source_entity
* (optional) A webform submission source entity.
* @param \Drupal\Core\Session\AccountInterface $account
* The current user account.
* @param array $options
* (optional) Additional options and query conditions.
* @param string $direction
* Direction of the sibling.
*
* @return \Drupal\webform\WebformSubmissionInterface|null
* The webform submission's sibling.
*/
protected function getSiblingSubmission(WebformSubmissionInterface $webform_submission, EntityInterface $source_entity = NULL, AccountInterface $account = NULL, array $options = [], $direction = 'previous') {
$webform = $webform_submission
->getWebform();
$query = $this
->getQuery();
$this
->addQueryConditions($query, $webform, $source_entity, $account, $options);
if ($direction === 'previous') {
$query
->condition('sid', $webform_submission
->id(), '<');
$query
->sort('sid', 'DESC');
}
else {
$query
->condition('sid', $webform_submission
->id(), '>');
$query
->sort('sid', 'ASC');
}
$query
->range(0, 1);
$submission = ($entity_ids = $query
->execute()) ? $this
->load(reset($entity_ids)) : NULL;
// If account is specified, we need make sure the user can view the submission.
if ($submission && $account && !$submission
->access('view', $account)) {
return NULL;
}
return $submission;
}
/****************************************************************************/
// WebformSubmissionEntityList methods.
/****************************************************************************/
/**
* {@inheritdoc}
*/
public function getCustomColumns(WebformInterface $webform = NULL, EntityInterface $source_entity = NULL, AccountInterface $account = NULL, $include_elements = TRUE) {
$column_names = $this
->getCustomSetting('columns', [], $webform, $source_entity) ?: $this
->getDefaultColumnNames($webform, $source_entity, $account, $include_elements);
$columns = $this
->getColumns($webform, $source_entity, $account, $include_elements);
return $this
->filterColumns($column_names, $columns);
}
/**
* {@inheritdoc}
*/
public function getUserColumns(WebformInterface $webform = NULL, EntityInterface $source_entity = NULL, AccountInterface $account = NULL, $include_elements = TRUE) {
$column_names = $webform ? $webform
->getSetting('submission_user_columns', []) : [];
$column_names = $column_names ?: $this
->getUserDefaultColumnNames($webform, $source_entity, $account, $include_elements);
$columns = $this
->getColumns($webform, $source_entity, $account, $include_elements);
unset($columns['sid']);
return $this
->filterColumns($column_names, $columns);
}
/**
* {@inheritdoc}
*/
public function getDefaultColumns(WebformInterface $webform = NULL, EntityInterface $source_entity = NULL, AccountInterface $account = NULL, $include_elements = TRUE) {
$columns = $this
->getColumns($webform, $source_entity, $account, $include_elements);
// Unset columns.
unset($columns['sid'], $columns['label'], $columns['uuid'], $columns['in_draft'], $columns['completed'], $columns['changed']);
// Hide certain unnecessary columns, that have default set to FALSE.
foreach ($columns as $column_name => $column) {
if (isset($column['default']) && $column['default'] === FALSE) {
unset($columns[$column_name]);
}
}
return $columns;
}
/**
* {@inheritdoc}
*/
public function getSubmissionsColumns() {
$columns = $this
->getColumns(NULL, NULL, NULL, FALSE);
// Unset columns.
// Note: 'serial' is displayed instead of 'sid'.
unset($columns['serial'], $columns['label'], $columns['uuid'], $columns['in_draft'], $columns['completed'], $columns['changed'], $columns['sticky'], $columns['locked'], $columns['notes'], $columns['uid']);
return $columns;
}
/**
* {@inheritdoc}
*/
public function getUsersSubmissionsColumns() {
$columns = $this
->getColumns(NULL, NULL, NULL, FALSE);
// Unset columns.
// Note: Displaying 'label' instead of 'serial' or 'sid'.
unset($columns['sid'], $columns['serial'], $columns['uuid'], $columns['in_draft'], $columns['completed'], $columns['changed'], $columns['sticky'], $columns['locked'], $columns['notes'], $columns['uid'], $columns['webform_id'], $columns['entity'], $columns['operations']);
return $columns;
}
/**
* {@inheritdoc}
*/
public function getColumns(WebformInterface $webform = NULL, EntityInterface $source_entity = NULL, AccountInterface $account = NULL, $include_elements = TRUE) {
$view_any = $webform && $webform
->access('submission_view_any') ? TRUE : FALSE;
$columns = [];
// Serial number.
$columns['serial'] = [
'title' => $this
->t('#'),
];
// Submission ID.
$columns['sid'] = [
'title' => $this
->t('SID'),
];
// Submission label.
$columns['label'] = [
'title' => $this
->t('Submission title'),
'sort' => FALSE,
];
// UUID.
$columns['uuid'] = [
'title' => $this
->t('UUID'),
];
// Draft.
$columns['in_draft'] = [
'title' => $this
->t('In draft'),
];
if (empty($account)) {
// Sticky (Starred/Unstarred).
$columns['sticky'] = [
'title' => $this
->t('Starred'),
];
// Locked.
$columns['locked'] = [
'title' => $this
->t('Locked'),
];
// Notes.
$columns['notes'] = [
'title' => $this
->t('Notes'),
];
}
// Created.
$columns['created'] = [
'title' => $this
->t('Created'),
];
// Completed.
$columns['completed'] = [
'title' => $this
->t('Completed'),
];
// Changed.
$columns['changed'] = [
'title' => $this
->t('Changed'),
];
// Source entity.
if ($view_any && empty($source_entity)) {
$columns['entity'] = [
'title' => $this
->t('Submitted to'),
'sort' => FALSE,
];
}
// Submitted by.
if (empty($account)) {
$columns['uid'] = [
'title' => $this
->t('User'),
];
}
// Submission language.
if ($view_any && $this->moduleHandler
->moduleExists('language')) {
$columns['langcode'] = [
'title' => $this
->t('Language'),
];
}
// Remote address.
$columns['remote_addr'] = [
'title' => $this
->t('IP address'),
];
// Webform and source entity for entity.webform_submission.collection.
// @see /admin/structure/webform/submissions/manage
if (empty($webform) && empty($source_entity)) {
$columns['webform_id'] = [
'title' => $this
->t('Webform'),
];
$columns['entity'] = [
'title' => $this
->t('Submitted to'),
'sort' => FALSE,
];
}
// Webform elements.
if ($webform && $include_elements) {
$elements = $webform
->getElementsInitializedFlattenedAndHasValue('view');
foreach ($elements as $element) {
/** @var \Drupal\webform\Plugin\WebformElementInterface $element_plugin */
$element_plugin = $this->elementManager
->createInstance($element['#type']);
// Replace tokens which can be used in an element's #title.
$element_plugin
->replaceTokens($element, $webform);
$columns += $element_plugin
->getTableColumn($element);
}
}
// Operations.
$columns['operations'] = [
'title' => $this
->t('Operations'),
'sort' => FALSE,
];
// Add name and format to all columns.
foreach ($columns as $name => &$column) {
$column['name'] = $name;
$column['format'] = 'value';
}
return $columns;
}
/**
* {@inheritdoc}
*/
public function getUserDefaultColumnNames(WebformInterface $webform = NULL, EntityInterface $source_entity = NULL, AccountInterface $account = NULL, $include_elements = TRUE) {
return [
'serial',
'created',
'remote_addr',
];
}
/**
* {@inheritdoc}
*/
public function getDefaultColumnNames(WebformInterface $webform = NULL, EntityInterface $source_entity = NULL, AccountInterface $account = NULL, $include_elements = TRUE) {
$columns = $this
->getDefaultColumns($webform, $source_entity, $account, $include_elements);
return array_keys($columns);
}
/**
* Get specified columns in specified order.
*
* @param array $column_names
* An associative array of column names.
* @param array $columns
* An associative array containing all available columns.
*
* @return array
* An associative array containing all specified columns.
*/
protected function filterColumns(array $column_names, array $columns) {
$filtered_columns = [];
foreach ($column_names as $column_name) {
if (isset($columns[$column_name])) {
$filtered_columns[$column_name] = $columns[$column_name];
}
}
return $filtered_columns;
}
/****************************************************************************/
// Custom settings methods.
/****************************************************************************/
/**
* {@inheritdoc}
*/
public function getCustomSetting($name, $default, WebformInterface $webform = NULL, EntityInterface $source_entity = NULL) {
// Return the default value is webform and source entity is not defined.
if (!$webform && !$source_entity) {
return $default;
}
$results_customize = $webform
->getSetting('results_customize', TRUE);
$key = "results.custom.{$name}";
if (!$source_entity) {
if ($results_customize && $webform
->hasUserData($key)) {
return $webform
->getUserData($key);
}
elseif ($webform
->hasState($key)) {
return $webform
->getState($key);
}
else {
return $default;
}
}
$source_entity_key = $key . '.' . $source_entity
->getEntityTypeId() . '.' . $source_entity
->id();
if ($results_customize && $webform
->hasUserData($source_entity_key)) {
return $webform
->getUserData($source_entity_key);
}
elseif ($webform
->hasState($source_entity_key)) {
return $webform
->getState($source_entity_key);
}
elseif ($webform
->getState('results.custom.default', FALSE)) {
return $webform
->getState($key, $default);
}
else {
return $default;
}
}
/****************************************************************************/
// Invoke WebformElement and WebformHandler plugin methods.
/****************************************************************************/
/**
* {@inheritdoc}
*/
public function create(array $values = []) {
/** @var \Drupal\webform\WebformSubmissionInterface $entity */
// Pre create is called via the WebformSubmission entity.
// @see: \Drupal\webform\Entity\WebformSubmission::preCreate
$entity = parent::create($values);
$this
->invokeWebformElements('postCreate', $entity);
$this
->invokeWebformHandlers('postCreate', $entity);
return $entity;
}
/**
* {@inheritdoc}
*/
protected function postLoad(array &$entities) {
/** @var \Drupal\webform\WebformSubmissionInterface $entity */
$return = parent::postLoad($entities);
foreach ($entities as $entity) {
$this
->invokeWebformElements('postLoad', $entity);
$this
->invokeWebformHandlers('postLoad', $entity);
// If this is an anonymous draft.
// We must add $SESSION to the submission's cache context.
// @see \Drupal\webform\WebformSubmissionStorage::loadDraft
// @todo Add support for 'view own submission' permission.
if ($entity
->isDraft() && $entity
->getOwner()
->isAnonymous()) {
$entity
->addCacheContexts([
'session',
]);
}
}
return $return;
}
/**
* {@inheritdoc}
*/
protected function doPreSave(EntityInterface $entity) {
/** @var \Drupal\webform\WebformSubmissionInterface $entity */
$id = parent::doPreSave($entity);
$this
->invokeWebformElements('preSave', $entity);
$this
->invokeWebformHandlers('preSave', $entity);
return $id;
}
/**
* {@inheritdoc}
*/
public function save(EntityInterface $entity) {
// Set serial number using the webform table, this is done outside of the
// main transaction initialized in parent::save() to reduce blocking
// concurrent webform submissions for as little time as possible.
if (!$entity
->serial() && !$entity
->getWebform()
->getSetting('serial_disabled')) {
$next_serial = $this
->getWebformStorage()
->getSerial($entity
->getWebform());
$entity
->set('serial', $next_serial);
}
return parent::save($entity);
}
/**
* {@inheritdoc}
*/
protected function doSave($id, EntityInterface $entity) {
/** @var \Drupal\webform\WebformSubmissionInterface $entity */
if ($entity
->getWebform()
->getSetting('results_disabled')) {
return WebformSubmissionStorageInterface::SAVED_DISABLED;
}
$is_new = $entity
->isNew();
$result = parent::doSave($id, $entity);
// Save data.
$this
->saveData($entity, !$is_new);
// Set serial number to the submission id.
if (!$entity
->serial() && $entity
->getWebform()
->getSetting('serial_disabled')) {
$this->database
->update('webform_submission')
->fields([
'serial' => $entity
->id(),
])
->condition('sid', $entity
->id())
->execute();
$entity
->set('serial', $entity
->id());
}
// Set anonymous draft token.
// This only needs to be called for new anonymous submissions.
if ($is_new) {
$this
->setAnonymousSubmission($entity);
}
return $result;
}
/**
* {@inheritdoc}
*/
protected function doPostSave(EntityInterface $entity, $update) {
/** @var \Drupal\webform\WebformSubmissionInterface $entity */
parent::doPostSave($entity, $update);
$webform = $entity
->getWebform();
if ($webform
->hasSubmissionLog()) {
// Log webform submission events to the 'webform_submission' log.
$context = [
'@title' => $entity
->label(),
'link' => $entity
->id() ? $entity
->toLink($this
->t('Edit'), 'edit-form')
->toString() : NULL,
'webform_submission' => $entity,
];
switch ($entity
->getState()) {
case WebformSubmissionInterface::STATE_DRAFT_UPDATED:
case WebformSubmissionInterface::STATE_DRAFT_CREATED:
if ($update) {
$message = '@title draft updated.';
$context['operation'] = 'draft updated';
}
else {
$message = '@title draft created.';
$context['operation'] = 'draft created';
}
break;
case WebformSubmissionInterface::STATE_COMPLETED:
if ($update) {
$message = '@title completed using saved draft.';
$context['operation'] = 'submission completed';
}
else {
$message = '@title created.';
$context['operation'] = 'submission created';
}
break;
case WebformSubmissionInterface::STATE_CONVERTED:
$message = '@title converted from anonymous to @user.';
$context['operation'] = 'submission converted';
$context['@user'] = $entity
->getOwner()
->label();
break;
case WebformSubmissionInterface::STATE_UPDATED:
$message = '@title updated.';
$context['operation'] = 'submission updated';
break;
case WebformSubmissionInterface::STATE_UNSAVED:
$message = '@title submitted.';
$context['operation'] = 'submission submitted';
break;
case WebformSubmissionInterface::STATE_LOCKED:
$message = '@title locked.';
$context['operation'] = 'submission locked';
break;
default:
throw new \Exception('Unexpected webform submission state');
}
$this->loggerFactory
->get('webform_submission')
->notice($message, $context);
}
elseif (!$webform
->getSetting('results_disabled')) {
// Log general events to the 'webform'.
switch ($entity
->getState()) {
case WebformSubmissionInterface::STATE_DRAFT_CREATED:
$message = '@title draft created.';
break;
case WebformSubmissionInterface::STATE_DRAFT_UPDATED:
$message = '@title draft updated.';
break;
case WebformSubmissionInterface::STATE_UPDATED:
$message = '@title updated.';
break;
case WebformSubmissionInterface::STATE_COMPLETED:
$message = $update ? '@title completed.' : '@title created.';
break;
default:
$message = NULL;
break;
}
if ($message) {
$context = [
'@id' => $entity
->id(),
'@title' => $entity
->label(),
'link' => $entity
->id() ? $entity
->toLink($this
->t('Edit'), 'edit-form')
->toString() : NULL,
];
$this->loggerFactory
->get('webform')
->notice($message, $context);
}
}
$this
->invokeWebformElements('postSave', $entity, $update);
$this
->invokeWebformHandlers('postSave', $entity, $update);
}
/**
* {@inheritdoc}
*/
public function resave(EntityInterface $entity) {
/** @var \Drupal\webform\WebformSubmissionInterface $entity */
$transaction = $this->database
->startTransaction();
try {
$return = $this
->doSave($entity
->id(), $entity);
// Ignore replica server temporarily.
$this->replicaKillSwitch
->trigger();
return $return;
} catch (\Exception $e) {
$transaction
->rollBack();
watchdog_exception($this->entityTypeId, $e);
throw new EntityStorageException($e
->getMessage(), $e
->getCode(), $e);
}
}
/**
* {@inheritdoc}
*/
public function delete(array $entities) {
/** @var \Drupal\webform\WebformSubmissionInterface $entity */
if (!$entities) {
// If no entities were passed, do nothing.
return;
}
foreach ($entities as $entity) {
$this
->invokeWebformElements('preDelete', $entity);
$this
->invokeWebformHandlers('preDelete', $entity);
}
$return = parent::delete($entities);
$this
->deleteData($entities);
foreach ($entities as $entity) {
$this
->invokeWebformElements('postDelete', $entity);
$this
->invokeWebformHandlers('postDelete', $entity);
WebformManagedFileBase::deleteFiles($entity);
}
// Remove empty webform submission specific file directory
// for all stream wrappers.
// @see \Drupal\webform\Plugin\WebformElement\WebformManagedFileBase
// @see \Drupal\webform\Plugin\WebformElement\WebformSignature
foreach ($entities as $entity) {
$webform = $entity
->getWebform();
if ($webform) {
$stream_wrappers = array_keys($this->streamWrapperManager
->getNames(StreamWrapperInterface::WRITE_VISIBLE));
foreach ($stream_wrappers as $stream_wrapper) {
$file_directory = $stream_wrapper . '://webform/' . $webform
->id() . '/' . $entity
->id();
// Clear empty webform submission directory.
if (file_exists($file_directory) && empty($this->fileSystem
->scanDirectory($file_directory, '/.*/'))) {
$this->fileSystem
->deleteRecursive($file_directory);
}
}
}
}
// Log deleted.
foreach ($entities as $entity) {
$webform = $entity
->getWebform();
$this->loggerFactory
->get('webform')
->notice('Deleted @form: Submission #@id.', [
'@id' => $entity
->id(),
'@form' => $webform ? $webform
->label() : '[' . t('Webform') . ']',
]);
}
return $return;
}
/****************************************************************************/
// Invoke methods.
/****************************************************************************/
/**
* {@inheritdoc}
*/
public function invokeWebformHandlers($method, WebformSubmissionInterface $webform_submission, &$context1 = NULL, &$context2 = NULL) {
$webform = $webform_submission
->getWebform();
if ($webform) {
return $webform
->invokeHandlers($method, $webform_submission, $context1, $context2);
}
}
/**
* {@inheritdoc}
*/
public function invokeWebformElements($method, WebformSubmissionInterface $webform_submission, &$context1 = NULL, &$context2 = NULL) {
$webform = $webform_submission
->getWebform();
if ($webform) {
$webform
->invokeElements($method, $webform_submission, $context1, $context2);
}
}
/****************************************************************************/
// Purge methods.
/****************************************************************************/
/**
* {@inheritdoc}
*/
public function purge($count) {
$days_to_seconds = 60 * 60 * 24;
$query = $this
->getWebformStorage()
->getQuery();
$query
->accessCheck(FALSE);
$query
->condition('settings.purge', [
WebformSubmissionStorageInterface::PURGE_DRAFT,
WebformSubmissionStorageInterface::PURGE_COMPLETED,
WebformSubmissionStorageInterface::PURGE_ALL,
], 'IN');
$query
->condition('settings.purge_days', 0, '>');
$webform_ids = array_values($query
->execute());
$remaining = $count;
if (!empty($webform_ids)) {
$webforms = $this
->getWebformStorage()
->loadMultiple($webform_ids);
foreach ($webforms as $webform) {
$query = $this
->getQuery();
// Since results of this query are never displayed to the user and we
// actually need to query the entire dataset of webform submissions, we
// are disabling access check.
$query
->accessCheck(FALSE);
$query
->condition('created', $this->time
->getRequestTime() - $webform
->getSetting('purge_days') * $days_to_seconds, '<');
$query
->condition('webform_id', $webform
->id());
switch ($webform
->getSetting('purge')) {
case WebformSubmissionStorageInterface::PURGE_DRAFT:
$query
->condition('in_draft', 1);
break;
case WebformSubmissionStorageInterface::PURGE_COMPLETED:
$query
->condition('in_draft', 0);
break;
}
$query
->range(0, $remaining);
$sids = array_values($query
->execute());
if (empty($sids)) {
continue;
}
$remaining -= count($sids);
$webform_submissions = $this
->loadMultiple($sids);
$webform
->invokeHandlers('prePurge', $webform_submissions);
$this
->moduleHandler()
->invokeAll('webform_submissions_pre_purge', [
$webform_submissions,
]);
$this
->delete($webform_submissions);
$webform
->invokeHandlers('postPurge', $webform_submissions);
$this
->moduleHandler()
->invokeAll('webform_submissions_post_purge', [
$webform_submissions,
]);
if ($remaining === 0) {
// We've collected enough webform submissions for purging in this run.
break;
}
}
}
}
/****************************************************************************/
// Data handlers.
/****************************************************************************/
/**
* {@inheritdoc}
*/
public function saveData(WebformSubmissionInterface $webform_submission, $delete_first = TRUE) {
// Get submission data rows.
$data = $webform_submission
->getData();
$webform_id = $webform_submission
->getWebform()
->id();
$sid = $webform_submission
->id();
$elements = $webform_submission
->getWebform()
->getElementsInitializedFlattenedAndHasValue();
$computed_elements = $webform_submission
->getWebform()
->getElementsComputed();
$rows = [];
foreach ($data as $name => $item) {
$element = isset($elements[$name]) ? $elements[$name] : [
'#webform_multiple' => FALSE,
'#webform_composite' => FALSE,
];
// Check if this is a computed element which is not
// stored in the database.
$is_computed_element = isset($computed_elements[$name]) ? TRUE : FALSE;
if ($is_computed_element && empty($element['#store'])) {
continue;
}
if ($element['#webform_composite']) {
if (is_array($item)) {
$composite_items = empty($element['#webform_multiple']) ? [
$item,
] : $item;
foreach ($composite_items as $delta => $composite_item) {
foreach ($composite_item as $property => $value) {
$rows[] = [
'webform_id' => $webform_id,
'sid' => $sid,
'name' => $name,
'property' => $property,
'delta' => $delta,
'value' => (string) $value,
];
}
}
}
}
elseif ($element['#webform_multiple']) {
if (is_array($item)) {
foreach ($item as $delta => $value) {
$rows[] = [
'webform_id' => $webform_id,
'sid' => $sid,
'name' => $name,
'property' => '',
'delta' => $delta,
'value' => (string) $value,
];
}
}
}
else {
$rows[] = [
'webform_id' => $webform_id,
'sid' => $sid,
'name' => $name,
'property' => '',
'delta' => 0,
'value' => (string) $item,
];
}
}
if ($delete_first) {
// Delete existing submission data rows.
$this->database
->delete('webform_submission_data')
->condition('sid', $sid)
->execute();
}
// Insert new submission data rows.
$query = $this->database
->insert('webform_submission_data')
->fields([
'webform_id',
'sid',
'name',
'property',
'delta',
'value',
]);
foreach ($rows as $row) {
$query
->values($row);
}
$query
->execute();
}
/**
* Save webform submission data from the 'webform_submission_data' table.
*
* @param array $webform_submissions
* An array of webform submissions.
*/
protected function loadData(array &$webform_submissions) {
// Load webform submission data.
if ($sids = array_keys($webform_submissions)) {
/** @var \Drupal\Core\Database\StatementInterface $result */
$result = $this->database
->select('webform_submission_data', 'sd')
->fields('sd', [
'webform_id',
'sid',
'name',
'property',
'delta',
'value',
])
->condition('sd.sid', $sids, 'IN')
->orderBy('sd.sid', 'ASC')
->orderBy('sd.name', 'ASC')
->orderBy('sd.property', 'ASC')
->orderBy('sd.delta', 'ASC')
->execute();
$submissions_data = [];
while ($record = $result
->fetchAssoc()) {
$sid = $record['sid'];
$name = $record['name'];
/** @var \Drupal\webform\WebformInterface $webform */
$webform = $webform_submissions[$sid]
->getWebform();
$elements = $webform ? $webform
->getElementsInitializedFlattenedAndHasValue() : [];
$element = isset($elements[$name]) ? $elements[$name] : [
'#webform_multiple' => FALSE,
'#webform_composite' => FALSE,
];
if ($element['#webform_composite']) {
if ($element['#webform_multiple']) {
$submissions_data[$sid][$name][$record['delta']][$record['property']] = $record['value'];
}
else {
$submissions_data[$sid][$name][$record['property']] = $record['value'];
}
}
elseif ($element['#webform_multiple']) {
$submissions_data[$sid][$name][$record['delta']] = $record['value'];
}
else {
$submissions_data[$sid][$name] = $record['value'];
}
}
// Set webform submission data via setData().
foreach ($submissions_data as $sid => $submission_data) {
$webform_submission = $webform_submissions[$sid];
$webform_submission
->setData($submission_data);
$webform_submission
->setOriginalData($webform_submission
->getData());
}
}
}
/**
* Delete webform submission data from the 'webform_submission_data' table.
*
* @param array $webform_submissions
* An array of webform submissions.
*/
protected function deleteData(array $webform_submissions) {
$sids = [];
foreach ($webform_submissions as $webform_submission) {
$sids[$webform_submission
->id()] = $webform_submission
->id();
}
$this->database
->delete('webform_submission_data')
->condition('sid', $sids, 'IN')
->execute();
}
/****************************************************************************/
// Draft methods.
/****************************************************************************/
/**
* {@inheritdoc}
*/
public function loadDraft(WebformInterface $webform, EntityInterface $source_entity = NULL, AccountInterface $account = NULL) {
$options = [
'check_source_entity' => TRUE,
'in_draft' => TRUE,
];
$query = $this
->getQuery();
// Because draft is somewhat different from a complete webform submission,
// we allow to bypass access check. Moreover, draft here is enforced to be
// authored by the $account user. Thus we hardly open any security breach
// here.
$query
->accessCheck(FALSE);
$this
->addQueryConditions($query, $webform, $source_entity, $account, $options);
// Only load the most recent draft.
$query
->sort('sid', 'DESC');
return ($sids = $query
->execute()) ? $this
->load(reset($sids)) : NULL;
}
/****************************************************************************/
// Anonymous submission methods.
/****************************************************************************/
/**
* {@inheritdoc}
*/
public function userLogin(UserInterface $account) {
if (empty($_SESSION['webform_submissions'])) {
return;
}
// Move all anonymous submissions to UID of this account.
$query = $this
->getQuery();
$query
->accessCheck(FALSE);
$query
->condition('uid', 0);
$query
->condition('sid', $_SESSION['webform_submissions'], 'IN');
$query
->sort('sid');
if ($sids = $query
->execute()) {
$webform_submissions = $this
->loadMultiple($sids);
foreach ($webform_submissions as $sid => $webform_submission) {
$webform = $webform_submission
->getWebform();
// Do not convert confidential submissions and check for convert
// anonymous setting.
if ($webform
->isConfidential() || empty($webform
->getSetting('form_convert_anonymous'))) {
continue;
}
unset($_SESSION['webform_submissions'][$sid]);
$webform_submission
->convert($account);
}
}
// Now that the user has logged in because when the log out $_SESSION is
// completely reset.
unset($_SESSION['webform_submissions']);
}
/**
* {@inheritdoc}
*/
public function getAnonymousSubmissionIds(AccountInterface $account) {
// Make sure the account and current user are identical.
if ((int) $account
->id() !== (int) $this->currentUser
->id()) {
return NULL;
}
if (empty($_SESSION['webform_submissions'])) {
return NULL;
}
// Cleanup sids because drafts could have been purged or the webform
// submission could have been deleted.
$_SESSION['webform_submissions'] = $this
->getQuery()
->accessCheck(FALSE)
->condition('sid', $_SESSION['webform_submissions'], 'IN')
->sort('sid')
->execute();
if (empty($_SESSION['webform_submissions'])) {
unset($_SESSION['webform_submissions']);
return NULL;
}
return $_SESSION['webform_submissions'];
}
/**
* {@inheritdoc}
*/
public function hasAnonymousSubmissionTracking(WebformSubmissionInterface $webform_submission) {
$webform = $webform_submission
->getWebform();
if ($webform
->isResultsDisabled()) {
return FALSE;
}
if ($this->currentUser
->hasPermission('view own webform submission')) {
return TRUE;
}
elseif ($this->accessRulesManager
->checkWebformSubmissionAccess('view_own', $this->currentUser, $webform_submission)
->isAllowed()) {
return TRUE;
}
elseif ($webform
->getSetting('limit_user') || $webform
->getSetting('entity_limit_user') && $webform_submission
->getSourceEntity()) {
return TRUE;
}
elseif ($webform
->getSetting('form_convert_anonymous')) {
return TRUE;
}
elseif ($webform
->getSetting('draft') === WebformInterface::DRAFT_ALL) {
return TRUE;
}
elseif ($webform
->hasAnonymousSubmissionTrackingHandler()) {
return TRUE;
}
else {
return FALSE;
}
}
/**
* Track anonymous submissions.
*
* Anonymous submission are tracked so that they can be assigned to the user
* if they login.
*
* We use session for storing draft tokens. So we can only do it for the
* current user.
*
* We do not use PrivateTempStore because it utilizes session ID as the key in
* key-value hash map where it stores its data. During user login the session
* ID is regenerated (see user_login_finalize()) so it is not suitable for us
* since we need to "carry" the draft tokens from anonymous session to the
* logged in one.
*
* @param \Drupal\webform\WebformSubmissionInterface $webform_submission
* A webform submission.
*
* @see WebformSubmissionStorage::loadDraft
* @see WebformSubmissionStorage::userLogin
*/
protected function setAnonymousSubmission(WebformSubmissionInterface $webform_submission) {
// Make sure the account and current user are identical.
if ((int) $webform_submission
->getOwnerId() !== (int) $this->currentUser
->id()) {
return;
}
// Make sure the submission is anonymous.
if (!$webform_submission
->getOwner()
->isAnonymous()) {
return;
}
// Check if anonymous users are allowed to save submission using $_SESSION.
if ($this
->hasAnonymousSubmissionTracking($webform_submission)) {
$_SESSION['webform_submissions'][$webform_submission
->id()] = $webform_submission
->id();
}
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
ContentEntityStorageBase:: |
protected | property | The entity bundle key. | |
ContentEntityStorageBase:: |
protected | property | Cache backend. | |
ContentEntityStorageBase:: |
protected | property | The entity field manager service. | |
ContentEntityStorageBase:: |
protected | property | The entity bundle info. | |
ContentEntityStorageBase:: |
protected | property | Stores the latest revision IDs for entities. | |
ContentEntityStorageBase:: |
protected | function | Ensures integer entity key values are valid. | |
ContentEntityStorageBase:: |
public | function |
Creates a new revision starting off from the specified entity object. Overrides TranslatableRevisionableStorageInterface:: |
|
ContentEntityStorageBase:: |
public | function |
Constructs a new entity translation object, without permanently saving it. Overrides TranslatableStorageInterface:: |
|
ContentEntityStorageBase:: |
public | function |
Creates an entity with sample field values. Overrides ContentEntityStorageInterface:: |
1 |
ContentEntityStorageBase:: |
public | function |
Delete a specific entity revision. Overrides EntityStorageInterface:: |
1 |
ContentEntityStorageBase:: |
protected | function |
Performs storage-specific entity deletion. Overrides EntityStorageBase:: |
1 |
ContentEntityStorageBase:: |
protected | function | Gets entities from the persistent cache backend. | |
ContentEntityStorageBase:: |
public | function |
Returns the latest revision identifier for an entity. Overrides RevisionableStorageInterface:: |
|
ContentEntityStorageBase:: |
public | function |
Returns the latest revision affecting the specified translation. Overrides TranslatableRevisionableStorageInterface:: |
|
ContentEntityStorageBase:: |
protected | function | Returns an array of field names to skip when merging revision translations. | |
ContentEntityStorageBase:: |
protected | function | Checks whether the field values changed compared to the original entity. | |
ContentEntityStorageBase:: |
protected | function | Initializes field values. | |
ContentEntityStorageBase:: |
protected | function | Invokes a method on the Field objects within an entity. | |
ContentEntityStorageBase:: |
protected | function | Invokes the post save method on the Field objects within an entity. | |
ContentEntityStorageBase:: |
protected | function |
Invokes a hook on behalf of the entity. Overrides EntityStorageBase:: |
|
ContentEntityStorageBase:: |
protected | function | Invokes hook_entity_storage_load(). | |
ContentEntityStorageBase:: |
protected | function | Checks translation statuses and invoke the related hooks if needed. | |
ContentEntityStorageBase:: |
protected | function | Checks whether any entity revision is translated. | |
ContentEntityStorageBase:: |
protected | function | Checks whether any stored entity revision is translated. | |
ContentEntityStorageBase:: |
public | function |
Loads multiple entity revisions. Overrides RevisionableStorageInterface:: |
1 |
ContentEntityStorageBase:: |
public | function |
Load a specific entity revision. Overrides EntityStorageInterface:: |
1 |
ContentEntityStorageBase:: |
public | function |
Loads an unchanged entity from the database. Overrides EntityStorageBase:: |
|
ContentEntityStorageBase:: |
public | function |
Reacts to the creation of a field. Overrides FieldDefinitionListenerInterface:: |
|
ContentEntityStorageBase:: |
public | function |
Reacts to the update of a field. Overrides FieldDefinitionListenerInterface:: |
|
ContentEntityStorageBase:: |
protected | function | Populates the affected flag for all the revision translations. | |
ContentEntityStorageBase:: |
protected | function |
Gathers entities from a 'preload' step. Overrides EntityStorageBase:: |
|
ContentEntityStorageBase:: |
public | function |
Purges a batch of field data. Overrides FieldableEntityStorageInterface:: |
|
ContentEntityStorageBase:: |
public | function |
Resets the entity cache. Overrides EntityStorageBase:: |
1 |
ContentEntityStorageBase:: |
protected | function | Stores entities in the persistent cache backend. | |
DependencySerializationTrait:: |
protected | property | ||
DependencySerializationTrait:: |
protected | property | ||
DependencySerializationTrait:: |
public | function | 2 | |
DependencySerializationTrait:: |
public | function | 2 | |
EntityHandlerBase:: |
protected | property | The module handler to invoke hooks on. | 5 |
EntityHandlerBase:: |
protected | function | Gets the module handler. | 5 |
EntityHandlerBase:: |
public | function | Sets the module handler for this handler. | |
EntityStorageBase:: |
protected | property | Name of the entity class. | |
EntityStorageBase:: |
protected | property | Information about the entity type. | |
EntityStorageBase:: |
protected | property | Entity type ID for this storage. | |
EntityStorageBase:: |
protected | property | Name of the entity's ID field in the entity database table. | |
EntityStorageBase:: |
protected | property | The memory cache. | |
EntityStorageBase:: |
protected | property | The memory cache cache tag. | |
EntityStorageBase:: |
protected | property | Name of entity's UUID database table field, if it supports UUIDs. | 1 |
EntityStorageBase:: |
protected | property | The UUID service. | 1 |
EntityStorageBase:: |
protected | function | Builds the cache ID for the passed in entity ID. | 1 |
EntityStorageBase:: |
public | function |
Gets an aggregated query instance. Overrides EntityStorageInterface:: |
|
EntityStorageBase:: |
public | function |
Gets the entity type definition. Overrides EntityStorageInterface:: |
|
EntityStorageBase:: |
public | function |
Gets the entity type ID. Overrides EntityStorageInterface:: |
|
EntityStorageBase:: |
protected | function | Gets entities from the static cache. | |
EntityStorageBase:: |
public | function |
Gets an entity query instance. Overrides EntityStorageInterface:: |
|
EntityStorageBase:: |
public | function |
Determines if the storage contains any data. Overrides EntityStorageInterface:: |
3 |
EntityStorageBase:: |
public | function |
Loads one entity. Overrides EntityStorageInterface:: |
2 |
EntityStorageBase:: |
public | function |
Load entities by their property values. Overrides EntityStorageInterface:: |
3 |
EntityStorageBase:: |
public | function |
Loads one or more entities. Overrides EntityStorageInterface:: |
1 |
EntityStorageBase:: |
protected | function | Stores entities in the static entity cache. | |
EntityStorageInterface:: |
constant | Load the most recent version of an entity's field data. | ||
EntityStorageInterface:: |
constant | Load the version of an entity's field data specified in the entity. | ||
SqlContentEntityStorage:: |
protected | property | The base table of the entity. | |
SqlContentEntityStorage:: |
protected | property | Active database connection. | |
SqlContentEntityStorage:: |
protected | property | The table that stores properties, if the entity has multilingual support. | |
SqlContentEntityStorage:: |
protected | property | The default language entity key. | |
SqlContentEntityStorage:: |
protected | property | The entity type's field storage definitions. | |
SqlContentEntityStorage:: |
protected | property |
The entity langcode key. Overrides EntityStorageBase:: |
|
SqlContentEntityStorage:: |
protected | property | The language manager. | |
SqlContentEntityStorage:: |
protected | property | The table that stores revision field data if the entity supports revisions. | |
SqlContentEntityStorage:: |
protected | property | Name of entity's revision database table field, if it supports revisions. | |
SqlContentEntityStorage:: |
protected | property | The table that stores revisions, if the entity supports revisions. | |
SqlContentEntityStorage:: |
protected | property | The entity type's storage schema object. | |
SqlContentEntityStorage:: |
protected | property | The mapping of field columns to SQL tables. | |
SqlContentEntityStorage:: |
protected | property | Whether this storage should use the temporary table mapping. | |
SqlContentEntityStorage:: |
protected | function | Builds the query to load the entity. | |
SqlContentEntityStorage:: |
public | function |
Determines the number of entities with values for a given field. Overrides FieldableEntityStorageInterface:: |
|
SqlContentEntityStorage:: |
protected | function | Deletes values of fields in dedicated tables for all revisions. | |
SqlContentEntityStorage:: |
protected | function | Deletes values of fields in dedicated tables for all revisions. | |
SqlContentEntityStorage:: |
protected | function |
Deletes entity field values from the storage. Overrides ContentEntityStorageBase:: |
|
SqlContentEntityStorage:: |
protected | function |
Deletes field values of an entity revision from the storage. Overrides ContentEntityStorageBase:: |
|
SqlContentEntityStorage:: |
protected | function |
Actually loads revision field item values from the storage. Overrides ContentEntityStorageBase:: |
|
SqlContentEntityStorage:: |
protected | function |
Writes entity field values to the storage. Overrides ContentEntityStorageBase:: |
1 |
SqlContentEntityStorage:: |
public | function |
Performs final cleanup after all data of a field has been purged. Overrides ContentEntityStorageBase:: |
|
SqlContentEntityStorage:: |
public | function | Gets the base table name. | |
SqlContentEntityStorage:: |
public | function | Gets a table mapping for the specified entity type and storage definitions. | |
SqlContentEntityStorage:: |
public | function | Gets the data table name. | |
SqlContentEntityStorage:: |
protected | function | Gets entities from the storage. | |
SqlContentEntityStorage:: |
protected | function |
Gets the name of the service for the query for this entity storage. Overrides EntityStorageBase:: |
|
SqlContentEntityStorage:: |
public | function | Gets the revision data table name. | |
SqlContentEntityStorage:: |
public | function | Gets the revision table name. | |
SqlContentEntityStorage:: |
protected | function | Gets the entity type's storage schema object. | |
SqlContentEntityStorage:: |
public | function |
Gets a table mapping for the entity's SQL tables. Overrides SqlEntityStorageInterface:: |
|
SqlContentEntityStorage:: |
protected | function |
Determines if this entity already exists in storage. Overrides EntityStorageBase:: |
|
SqlContentEntityStorage:: |
protected | function | Initializes table name variables. | |
SqlContentEntityStorage:: |
protected | function | Checks whether a field column should be treated as serial. | |
SqlContentEntityStorage:: |
protected | function | Loads values of fields stored in dedicated tables for a group of entities. | |
SqlContentEntityStorage:: |
protected | function | Loads values for fields stored in the shared data tables. | |
SqlContentEntityStorage:: |
protected | function |
Maps from storage records to entity objects, and attaches fields. Overrides EntityStorageBase:: |
|
SqlContentEntityStorage:: |
protected | function | Maps from an entity object to the storage record of the field data. | |
SqlContentEntityStorage:: |
protected | function | Maps from an entity object to the storage record. | |
SqlContentEntityStorage:: |
public | function |
Reacts to a bundle being created. Overrides EntityBundleListenerInterface:: |
|
SqlContentEntityStorage:: |
public | function |
Reacts to a bundle being deleted. Overrides EntityBundleListenerInterface:: |
|
SqlContentEntityStorage:: |
public | function |
Reacts to the creation of the entity type. Overrides EntityTypeListenerInterface:: |
|
SqlContentEntityStorage:: |
public | function |
Reacts to the deletion of the entity type. Overrides EntityTypeListenerInterface:: |
|
SqlContentEntityStorage:: |
public | function |
Reacts to the update of the entity type. Overrides EntityTypeListenerInterface:: |
|
SqlContentEntityStorage:: |
public | function |
Reacts to the creation of the fieldable entity type. Overrides EntityTypeListenerInterface:: |
|
SqlContentEntityStorage:: |
public | function |
Reacts to the update of a fieldable entity type. Overrides EntityTypeListenerInterface:: |
|
SqlContentEntityStorage:: |
public | function |
Reacts to the deletion of a field. Overrides ContentEntityStorageBase:: |
|
SqlContentEntityStorage:: |
public | function |
Reacts to the creation of a field storage definition. Overrides ContentEntityStorageBase:: |
|
SqlContentEntityStorage:: |
public | function |
Reacts to the deletion of a field storage definition. Overrides ContentEntityStorageBase:: |
|
SqlContentEntityStorage:: |
public | function |
Reacts to the update of a field storage definition. Overrides ContentEntityStorageBase:: |
|
SqlContentEntityStorage:: |
protected | function |
Removes field items from storage per entity during purge. Overrides ContentEntityStorageBase:: |
|
SqlContentEntityStorage:: |
protected | function |
Reads values to be purged for a single field. Overrides ContentEntityStorageBase:: |
|
SqlContentEntityStorage:: |
public | function |
Checks if existing data would be lost if the schema changes were applied. Overrides EntityStorageSchemaInterface:: |
|
SqlContentEntityStorage:: |
public | function |
Checks if the changes to the entity type requires storage schema changes. Overrides EntityStorageSchemaInterface:: |
|
SqlContentEntityStorage:: |
public | function |
Checks if existing data would be lost if the schema changes were applied. Overrides DynamicallyFieldableEntityStorageSchemaInterface:: |
|
SqlContentEntityStorage:: |
public | function |
Checks if the changes to the storage definition requires schema changes. Overrides DynamicallyFieldableEntityStorageSchemaInterface:: |
|
SqlContentEntityStorage:: |
public | function |
Restores a previously saved entity. Overrides EntityStorageBase:: |
|
SqlContentEntityStorage:: |
protected | function | Saves an entity revision. | |
SqlContentEntityStorage:: |
protected | function | Saves values of fields that use dedicated tables. | 1 |
SqlContentEntityStorage:: |
protected | function | Saves fields that use the shared tables. | |
SqlContentEntityStorage:: |
public | function | Updates the wrapped entity type definition. | |
SqlContentEntityStorage:: |
public | function | Updates the internal list of field storage definitions. | |
SqlContentEntityStorage:: |
public | function | Sets the wrapped table mapping definition. | |
SqlContentEntityStorage:: |
public | function | Changes the temporary state of the storage. | |
SqlContentEntityStorage:: |
protected | function | Wraps a database schema exception into an entity storage exception. | |
SqlContentEntityStorage:: |
public | function |
Constructs a SqlContentEntityStorage object. Overrides ContentEntityStorageBase:: |
1 |
StringTranslationTrait:: |
protected | property | The string translation service. | 4 |
StringTranslationTrait:: |
protected | function | Formats a string containing a count of items. | |
StringTranslationTrait:: |
protected | function | Returns the number of plurals supported by a given language. | |
StringTranslationTrait:: |
protected | function | Gets the string translation service. | |
StringTranslationTrait:: |
public | function | Sets the string translation service to use. | 2 |
StringTranslationTrait:: |
protected | function | Translates a string to the current language or to a given language. | |
WebformEntityStorageTrait:: |
protected | property | An associate array of entity type storage aliases. | |
WebformEntityStorageTrait:: |
protected | property | The entity type manager. | 5 |
WebformEntityStorageTrait:: |
protected | function | Retrieves the entity storage. | |
WebformEntityStorageTrait:: |
protected | function | Retrieves the webform submission storage. | |
WebformEntityStorageTrait:: |
protected | function | Retrieves the webform storage. | |
WebformEntityStorageTrait:: |
public | function | Implements the magic __get() method. | |
WebformSubmissionStorage:: |
protected | property | The webform access rules manager service. | |
WebformSubmissionStorage:: |
protected | property | The current user. | |
WebformSubmissionStorage:: |
protected | property | Array used to element data schema. | |
WebformSubmissionStorage:: |
protected | property | The webform element plugin manager. | |
WebformSubmissionStorage:: |
protected | property | The entity type repository. | |
WebformSubmissionStorage:: |
protected | property | The file system service. | |
WebformSubmissionStorage:: |
protected | property | The logger factory. | |
WebformSubmissionStorage:: |
protected | property | The replica kill switch. | |
WebformSubmissionStorage:: |
protected | property | The stream wrapper manager. | |
WebformSubmissionStorage:: |
protected | property | The time service. | |
WebformSubmissionStorage:: |
public | function |
Add condition to submission query. Overrides WebformSubmissionStorageInterface:: |
|
WebformSubmissionStorage:: |
protected | function |
Builds an entity query. Overrides SqlContentEntityStorage:: |
|
WebformSubmissionStorage:: |
public | function |
Check field definition access. Overrides WebformSubmissionStorageInterface:: |
|
WebformSubmissionStorage:: |
public | function |
Constructs a new entity object, without permanently saving it. Overrides EntityStorageBase:: |
|
WebformSubmissionStorage:: |
public static | function |
Instantiates a new instance of this entity handler. Overrides SqlContentEntityStorage:: |
|
WebformSubmissionStorage:: |
public | function |
Deletes permanently saved entities. Overrides SqlContentEntityStorage:: |
|
WebformSubmissionStorage:: |
public | function |
Delete all webform submissions. Overrides WebformSubmissionStorageInterface:: |
|
WebformSubmissionStorage:: |
protected | function | Delete webform submission data from the 'webform_submission_data' table. | |
WebformSubmissionStorage:: |
protected | function |
Performs storage-specific creation of entities. Overrides ContentEntityStorageBase:: |
|
WebformSubmissionStorage:: |
protected | function |
Performs storage-specific loading of entities. Overrides SqlContentEntityStorage:: |
|
WebformSubmissionStorage:: |
protected | function |
Performs post save entity processing. Overrides ContentEntityStorageBase:: |
|
WebformSubmissionStorage:: |
protected | function |
Performs presave entity processing. Overrides ContentEntityStorageBase:: |
|
WebformSubmissionStorage:: |
protected | function |
Performs storage-specific saving of the entity. Overrides ContentEntityStorageBase:: |
|
WebformSubmissionStorage:: |
protected | function | Get specified columns in specified order. | |
WebformSubmissionStorage:: |
public | function |
Get anonymous user's submission ids. Overrides WebformSubmissionStorageInterface:: |
|
WebformSubmissionStorage:: |
public | function |
Get submission columns used to display results table. Overrides WebformSubmissionStorageInterface:: |
|
WebformSubmissionStorage:: |
public | function |
Get customized submission columns used to display custom table. Overrides WebformSubmissionStorageInterface:: |
|
WebformSubmissionStorage:: |
public | function |
Get customize setting. Overrides WebformSubmissionStorageInterface:: |
|
WebformSubmissionStorage:: |
public | function |
Get default submission columns used to display results. Overrides WebformSubmissionStorageInterface:: |
|
WebformSubmissionStorage:: |
public | function |
Get default submission columns used to display results. Overrides WebformSubmissionStorageInterface:: |
|
WebformSubmissionStorage:: |
public | function |
Get webform submission entity field definitions. Overrides WebformSubmissionStorageInterface:: |
|
WebformSubmissionStorage:: |
public | function |
Get a webform's first submission. Overrides WebformSubmissionStorageInterface:: |
|
WebformSubmissionStorage:: |
public | function |
Get a webform's last submission. Overrides WebformSubmissionStorageInterface:: |
|
WebformSubmissionStorage:: |
public | function |
Get the maximum sid. Overrides WebformSubmissionStorageInterface:: |
|
WebformSubmissionStorage:: |
public | function |
Get a webform submission's next sibling. Overrides WebformSubmissionStorageInterface:: |
|
WebformSubmissionStorage:: |
public | function |
Get a webform submission's previous sibling. Overrides WebformSubmissionStorageInterface:: |
|
WebformSubmissionStorage:: |
protected | function | Get a webform submission's sibling. | |
WebformSubmissionStorage:: |
public | function |
Get source entities associated for a specified webform. Overrides WebformSubmissionStorageInterface:: |
|
WebformSubmissionStorage:: |
public | function |
Get source entities as options for a specified webform. Overrides WebformSubmissionStorageInterface:: |
|
WebformSubmissionStorage:: |
public | function |
Get total number of source entities. Overrides WebformSubmissionStorageInterface:: |
|
WebformSubmissionStorage:: |
public | function |
Get webform submission source entities as options. Overrides WebformSubmissionStorageInterface:: |
|
WebformSubmissionStorage:: |
public | function |
Get webform submission source entity types. Overrides WebformSubmissionStorageInterface:: |
|
WebformSubmissionStorage:: |
public | function |
Get submissions columns. Overrides WebformSubmissionStorageInterface:: |
|
WebformSubmissionStorage:: |
protected | function | Get a webform submission's terminus (aka first or last). | |
WebformSubmissionStorage:: |
public | function |
Get the total number of submissions. Overrides WebformSubmissionStorageInterface:: |
|
WebformSubmissionStorage:: |
public | function |
Get user submission columns used to display results. Overrides WebformSubmissionStorageInterface:: |
|
WebformSubmissionStorage:: |
public | function |
Get user default submission columns used to display results. Overrides WebformSubmissionStorageInterface:: |
|
WebformSubmissionStorage:: |
public | function |
Get user submissions columns. Overrides WebformSubmissionStorageInterface:: |
|
WebformSubmissionStorage:: |
public | function |
Check if anonymous users submission are tracked using $_SESSION. Overrides WebformSubmissionStorageInterface:: |
|
WebformSubmissionStorage:: |
public | function |
Determine if a webform element has submission values. Overrides WebformSubmissionStorageInterface:: |
|
WebformSubmissionStorage:: |
public | function |
Invoke a webform submission's webform's elements method. Overrides WebformSubmissionStorageInterface:: |
|
WebformSubmissionStorage:: |
public | function |
Invoke a webform submission's webform's handlers method. Overrides WebformSubmissionStorageInterface:: |
|
WebformSubmissionStorage:: |
public | function |
Load webform submissions by their related entity references. Overrides WebformSubmissionStorageInterface:: |
|
WebformSubmissionStorage:: |
protected | function | Save webform submission data from the 'webform_submission_data' table. | |
WebformSubmissionStorage:: |
public | function |
Get webform submission draft. Overrides WebformSubmissionStorageInterface:: |
|
WebformSubmissionStorage:: |
public | function |
Load submission using webform (secure) token. Overrides WebformSubmissionStorageInterface:: |
|
WebformSubmissionStorage:: |
protected | function |
Attaches data to entities upon loading. Overrides EntityStorageBase:: |
|
WebformSubmissionStorage:: |
public | function |
Purge webform submissions. Overrides WebformSubmissionStorageInterface:: |
|
WebformSubmissionStorage:: |
public | function |
Resaves the entity without triggering any hooks or handlers. Overrides WebformSubmissionStorageInterface:: |
|
WebformSubmissionStorage:: |
public | function |
Saves the entity permanently. Overrides SqlContentEntityStorage:: |
|
WebformSubmissionStorage:: |
public | function |
Save webform submission data to the 'webform_submission_data' table. Overrides WebformSubmissionStorageInterface:: |
|
WebformSubmissionStorage:: |
protected | function | Track anonymous submissions. | |
WebformSubmissionStorage:: |
public | function |
React to an event when a user logs in. Overrides WebformSubmissionStorageInterface:: |
|
WebformSubmissionStorageInterface:: |
constant | Denote to purge automatically all submissions. | ||
WebformSubmissionStorageInterface:: |
constant | Denote to purge automatically only completed submissions. | ||
WebformSubmissionStorageInterface:: |
constant | Denote to purge automatically only drafts. | ||
WebformSubmissionStorageInterface:: |
constant | Denote not to purge automatically anything at all. | ||
WebformSubmissionStorageInterface:: |
constant | Return status for saving of webform submission when saving results is disabled. |