View source
<?php
namespace Drupal\search_api_saved_searches\Entity;
use Drupal\Component\Utility\Crypt;
use Drupal\Core\Entity\ContentEntityBase;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\Core\Site\Settings;
use Drupal\search_api\Query\QueryInterface;
use Drupal\search_api_saved_searches\SavedSearchesException;
use Drupal\search_api_saved_searches\SavedSearchInterface;
use Drupal\user\UserInterface;
class SavedSearch extends ContentEntityBase implements SavedSearchInterface {
protected $cachedProperties = [];
public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
$fields = parent::baseFieldDefinitions($entity_type);
$fields['langcode']
->setDisplayConfigurable('form', TRUE);
$fields['label'] = BaseFieldDefinition::create('string')
->setLabel(t('Label'))
->setDescription(t('The label for the saved search.'))
->setRequired(TRUE)
->setSetting('max_length', 255)
->setDisplayOptions('view', [
'label' => 'hidden',
'type' => 'string',
'weight' => -5,
])
->setDisplayOptions('form', [
'type' => 'string_textfield',
'weight' => -5,
])
->setDisplayConfigurable('form', TRUE);
$fields['uid'] = BaseFieldDefinition::create('entity_reference')
->setLabel(t('Created by'))
->setDescription(t('The user who owns the saved search.'))
->setSetting('target_type', 'user')
->setDefaultValueCallback('Drupal\\search_api_saved_searches\\Entity\\SavedSearch::getCurrentUserId')
->setDisplayOptions('view', [
'label' => 'hidden',
'type' => 'author',
'weight' => 0,
])
->setDisplayOptions('form', [
'type' => 'entity_reference_autocomplete',
'weight' => 5,
'settings' => [
'match_operator' => 'CONTAINS',
'size' => '60',
'placeholder' => '',
],
])
->setDisplayConfigurable('form', TRUE);
$fields['status'] = BaseFieldDefinition::create('boolean')
->setLabel(t('Activated'))
->setDescription(t('Whether the saved search has been activated.'))
->setDefaultValue(TRUE)
->setDisplayOptions('view', [
'type' => 'boolean',
'weight' => 0,
'settings' => [
'on_label' => t('Activated'),
'off_label' => t('Activation pending'),
],
])
->setDisplayOptions('form', [
'type' => 'boolean_checkbox',
'weight' => 0,
])
->setDisplayConfigurable('form', TRUE);
$fields['created'] = BaseFieldDefinition::create('created')
->setLabel(t('Created on'))
->setDescription(t('The time that the saved search was created.'))
->setDisplayOptions('view', [
'type' => 'timestamp',
'weight' => 0,
])
->setDisplayOptions('form', [
'type' => 'datetime_timestamp',
'weight' => 10,
])
->setDisplayConfigurable('form', TRUE);
$fields['last_executed'] = BaseFieldDefinition::create('created')
->setLabel(t('Last executed'))
->setDescription(t('The time that the saved search was last checked for new results.'))
->setDisplayOptions('view', [
'type' => 'timestamp',
'weight' => 0,
])
->setDisplayOptions('form', [
'type' => 'datetime_timestamp',
'weight' => 10,
])
->setDisplayConfigurable('form', TRUE);
$fields['next_execution'] = BaseFieldDefinition::create('timestamp')
->setLabel(t('Next execution'))
->setDescription(t('The next time this saved search should be executed.'))
->setDisplayOptions('view', [
'type' => 'timestamp',
'weight' => 0,
])
->setDisplayOptions('form', [
'type' => 'datetime_timestamp',
'weight' => 10,
])
->setDisplayConfigurable('form', TRUE);
$fields['notify_interval'] = BaseFieldDefinition::create('list_integer')
->setLabel(t('Notification interval'))
->setDescription(t('The interval in which you want to receive notifications of new results for this saved search.'))
->setRequired(TRUE)
->setSetting('allowed_values', [
3600 => t('Hourly'),
86400 => t('Daily'),
604800 => t('Weekly'),
-1 => t('Never'),
])
->setDefaultValue(-1)
->setDisplayOptions('view', [
'type' => 'list_default',
'weight' => 0,
])
->setDisplayOptions('form', [
'type' => 'options_select',
'weight' => 0,
])
->setDisplayConfigurable('form', TRUE);
$fields['index_id'] = BaseFieldDefinition::create('string')
->setLabel(t('Index ID'))
->setSetting('max_length', 50);
$fields['query'] = BaseFieldDefinition::create('string_long')
->setLabel(t('Search query'))
->setDescription(t('The saved search query.'))
->setSetting('case_sensitive', TRUE)
->setDisplayOptions('view', [
'region' => 'hidden',
])
->setDisplayOptions('form', [
'region' => 'hidden',
]);
$fields['path'] = BaseFieldDefinition::create('string_long')
->setLabel(t('Path'))
->setDescription(t("The path to this saved search's query."))
->setSetting('case_sensitive', TRUE)
->setDisplayOptions('view', [
'region' => 'hidden',
])
->setDisplayOptions('form', [
'region' => 'hidden',
])
->setDisplayConfigurable('form', TRUE);
return $fields;
}
public static function bundleFieldDefinitions(EntityTypeInterface $entity_type, $bundle, array $base_field_definitions) {
$fields = parent::bundleFieldDefinitions($entity_type, $bundle, $base_field_definitions);
$type = \Drupal::entityTypeManager()
->getStorage('search_api_saved_search_type')
->load($bundle);
if ($type) {
$fields += $type
->getNotificationPluginFieldDefinitions();
}
return $fields;
}
public static function getCurrentUserId() {
return [
\Drupal::currentUser()
->id(),
];
}
public static function preCreate(EntityStorageInterface $storage, array &$values) {
parent::preCreate($storage, $values);
if (isset($values['query']) && $values['query'] instanceof QueryInterface) {
$query = $values['query'];
$values['cachedProperties']['executed query'] = $query;
$query = static::getCleanQueryForStorage($query);
$options =& $query
->getOptions();
unset($options['search_api_view']);
$values['cachedProperties']['query'] = $query;
$values['query'] = serialize($query);
}
}
protected static function getCleanQueryForStorage(QueryInterface $query) {
$query = clone $query;
$options =& $query
->getOptions();
unset($options['search_api_view']);
$results = $query
->getResults();
$results
->setResultCount(0);
$results
->setResultItems([]);
$data =& $results
->getAllExtraData();
$data = [];
unset($data);
return $query;
}
public function postCreate(EntityStorageInterface $storage) {
parent::postCreate($storage);
if (isset($this->values['cachedProperties'])) {
foreach ($this->values['cachedProperties'] as $key => $value) {
$this->cachedProperties[$key] = $value;
}
unset($this->values['cachedProperties']);
}
if (empty($this
->get('label')->value)) {
$label = NULL;
$query = $this
->getQuery();
if ($query && is_string($query
->getOriginalKeys())) {
$label = $query
->getOriginalKeys();
}
$this
->set('label', $label ?: t('Saved search'));
}
}
public function preSave(EntityStorageInterface $storage) {
parent::preSave($storage);
$notify_interval = $this
->get('notify_interval')->value;
if ($notify_interval >= 0) {
$last_executed = $this
->get('last_executed')->value;
$this
->set('next_execution', $last_executed + $notify_interval);
}
else {
$this
->set('next_execution', NULL);
}
if ($this
->isNew() && !$this
->get('index_id')->value) {
$query = $this
->getQuery();
if ($query) {
$this
->set('index_id', $query
->getIndex()
->id());
}
}
}
public function postSave(EntityStorageInterface $storage, $update = TRUE) {
parent::postSave($storage, $update);
if (!$update) {
try {
$type = $this
->getType();
} catch (SavedSearchesException $e) {
return;
}
$query = $this
->getQuery();
if (!$query) {
return;
}
$index_id = $query
->getIndex()
->id();
$date_field = $type
->getOption("date_field.{$index_id}");
if ($date_field) {
return;
}
$new_results_check = \Drupal::getContainer()
->get('search_api_saved_searches.new_results_check');
if (!empty($this->cachedProperties['executed query'])) {
$query = $this->cachedProperties['executed query'];
$items = $query
->getResults()
->getResultItems();
$new_results_check
->saveKnownResults($this, $items);
}
else {
$new_results_check
->getNewResults($this);
}
}
}
public static function postDelete(EntityStorageInterface $storage, array $entities) {
parent::postDelete($storage, $entities);
\Drupal::database()
->delete('search_api_saved_searches_old_results')
->condition('search_id', array_keys($entities), 'IN')
->execute();
}
protected function urlRouteParameters($rel) {
$params = parent::urlRouteParameters($rel);
if ($rel === 'activate' || (string) $this
->getOwnerId() === '0') {
$operations = [
'canonical' => 'view',
'activate' => 'activate',
'edit-form' => 'edit',
'delete-form' => 'delete',
];
if (isset($operations[$rel])) {
$params['token'] = $this
->getAccessToken($operations[$rel]);
}
}
return $params;
}
public function getOwner() {
return $this
->get('uid')->entity;
}
public function setOwner(UserInterface $account) {
$this
->set('uid', $account
->id());
return $this;
}
public function getOwnerId() {
return $this
->get('uid')->target_id;
}
public function setOwnerId($uid) {
$this
->set('uid', $uid);
return $this;
}
public function getType() {
if (!isset($this->cachedProperties['type'])) {
$type = \Drupal::entityTypeManager()
->getStorage('search_api_saved_search_type')
->load($this
->bundle());
$this->cachedProperties['type'] = $type ?: FALSE;
}
if (!$this->cachedProperties['type']) {
throw new SavedSearchesException("Saved search #{$this->id()} does not have a valid type set");
}
return $this->cachedProperties['type'];
}
public function getQuery() {
if (!isset($this->cachedProperties['query'])) {
$this->cachedProperties['query'] = FALSE;
$query = $this
->get('query')->value;
if ($query) {
$this->cachedProperties['query'] = unserialize($query);
}
}
return $this->cachedProperties['query'] ?: NULL;
}
public function setQuery(QueryInterface $query) {
$this->cachedProperties['query'] = $query;
$this
->set('query', serialize($query));
return $this;
}
public function getPath() {
return $this
->get('path')->value;
}
public function getAccessToken($operation) {
$key = $this
->getEntityTypeId() . ':' . $this
->id() . ':' . $operation;
return Crypt::hmacBase64($key, Settings::getHashSalt());
}
}