View source
<?php
namespace Drupal\mongodb\Entity;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\ContentEntityStorageBase;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Entity\Query\QueryInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\Language\LanguageInterface;
use Drupal\mongodb\MongoCollectionFactory;
use Symfony\Component\DependencyInjection\ContainerInterface;
class ContentEntityStorage extends ContentEntityStorageBase {
protected $mongo;
protected $entityManager;
public function __construct(EntityTypeInterface $entity_type, MongoCollectionFactory $mongo, EntityManagerInterface $entity_manager) {
parent::__construct($entity_type);
$this->mongo = $mongo;
$this->entityManager = $entity_manager;
}
public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) {
return new static($entity_type, $container
->get('mongo'), $container
->get('entity.manager'));
}
public function loadRevision($revision_id) {
$revisions = $this
->loadFromMongo('entity_revision', [
'_id' => (int) $revision_id,
]);
return isset($revisions[$revision_id]) ? $revisions[$revision_id] : FALSE;
}
protected function loadFromMongo($prefix, array $find) {
$collection = $this->mongo
->get($prefix . '.' . $this->entityType
->id());
$return = array();
$langcode_key = $this->entityType
->getKey('langcode');
$default_langcode_key = $this->entityType
->getKey('default_langcode');
$revision_key = $this->entityType
->getKey('revision');
$translatable = $this->entityType
->isTranslatable();
foreach ($collection
->find($find) as $record) {
$data = array();
$definitions = $this->entityManager
->getFieldDefinitions($this->entityTypeId, $record['bundle']);
$this
->mongoToEntityData($data, $record, $definitions, $translatable, $default_langcode_key, $langcode_key);
if ($prefix == 'entity_revision') {
$entity_record = $this->mongo
->get('entity.' . $this->entityType
->id())
->findOne([
'_id' => $record['entity_id'],
]);
$definitions = array_filter($this->entityManager
->getFieldStorageDefinitions($this->entityTypeId), function (FieldStorageDefinitionInterface $definition) use ($revision_key) {
return !$definition
->isRevisionable() && $definition
->getName() != $revision_key;
});
$this
->mongoToEntityData($data, $entity_record, $definitions, $translatable, $default_langcode_key, $langcode_key);
if ($entity_record['values'][0][$this->entityType
->getKey('revision')][0]['value'] != $record['_id']) {
$data['isDefaultRevision'][LanguageInterface::LANGCODE_DEFAULT] = FALSE;
}
}
$return[$record['_id']] = new $this->entityClass($data, $this->entityTypeId, $record['bundle'], $record['translations']);
}
return $return;
}
protected function mongoToEntityData(array &$data, array $record, array $definitions, $translatable, $default_langcode_key, $langcode_key) {
foreach ($record['values'] as $translation) {
foreach ($definitions as $field_name => $definition) {
if (isset($translation[$field_name])) {
$index = $translatable && !$translation[$default_langcode_key][0]['value'] ? $translation[$langcode_key][0]['value'] : LanguageInterface::LANGCODE_DEFAULT;
$data[$field_name][$index] = $translation[$field_name];
}
}
}
}
public function deleteRevision($revision_id) {
$this->mongo
->get('entity_revision.' . $this->entityType
->id())
->remove(array(
'_id' => $revision_id,
));
}
public function doDelete($entities) {
if (!$entities) {
return;
}
$ids = array(
'$in' => array_keys($entities),
);
$this->mongo
->get('entity.' . $this->entityType
->id())
->remove(array(
'_id' => $ids,
));
$this->mongo
->get('entity_revision.' . $this->entityType
->id())
->remove(array(
'entity_id' => $ids,
));
}
protected function doSave($id, EntityInterface $entity) {
$id = $entity
->id();
$is_new = FALSE;
if ($entity
->isNew() || $id === NULL || $id === '') {
$is_new = TRUE;
if ($id === NULL || $id === '') {
$entity
->get($this->entityType
->getKey('id'))->value = $this
->nextId('entity', $id);
}
}
if ($this->entityType
->isRevisionable()) {
$revision_key = $this->entityType
->getKey('revision');
if ($entity
->isNewRevision() && !$entity
->getRevisionId()) {
$entity
->get($revision_key)->value = $this
->nextId('entity_revision');
}
}
$this
->invokeFieldMethod($is_new ? 'insert' : 'update', $entity);
$data = $this
->getDataToSave($entity);
if ($entity
->isDefaultRevision()) {
$criteria['_id'] = $entity
->id();
if ($this->entityType
->isRevisionable()) {
$data['revision_id'] = $entity
->get($revision_key)->value;
}
$collection = $this
->mongoCollection($entity, 'entity');
$collection
->update($criteria, $criteria + $data, [
'upsert' => TRUE,
]);
$return = $collection->db
->lastError();
}
if ($this->entityType
->isRevisionable()) {
$criteria['_id'] = $entity
->getRevisionId();
$criteria['entity_id'] = $entity
->id();
$collection = $this
->mongoCollection($entity, 'entity_revision');
$collection
->update($criteria, $criteria + $data, [
'upsert' => TRUE,
]);
$entity
->setNewRevision(FALSE);
if (!isset($return)) {
$return = $collection->db
->lastError();
}
}
if (!$is_new) {
$this
->invokeTranslationHooks($entity);
}
if (isset($collection) && empty($return['err'])) {
return $return['updatedExisting'] ? SAVED_UPDATED : SAVED_NEW;
}
return FALSE;
}
protected function nextId($prefix, $existing_id = 0) {
return $this->mongo
->nextId("{$prefix}.{$this->entityTypeId}", (int) $existing_id);
}
protected function getDataToSave(ContentEntityInterface $entity) {
$default_langcode = $entity
->getUntranslated()
->language()
->getId();
$values = array();
$langcodes = [];
$languages = $entity
->getTranslationLanguages();
foreach ($languages as $langcode => $language) {
$translation = $entity
->getTranslation($langcode);
$translated_values = [];
$langcodes[] = $langcode;
foreach ($translation as $field_name => $items) {
$field_storage_definition = $items
->getFieldDefinition()
->getFieldStorageDefinition();
$columns = $field_storage_definition
->getSchema()['columns'];
$cardinality = $field_storage_definition
->getCardinality();
if (!$items
->isEmpty()) {
foreach ($items as $delta => $item) {
if ($delta == $cardinality) {
break;
}
foreach ($item
->toArray() as $column => $value) {
if (isset($columns[$column])) {
$translated_values[$field_name][$delta][$column] = MongoCollectionFactory::castValue($columns[$column]['type'], $value);
}
}
}
}
}
if ($default_langcode == $langcode) {
array_unshift($values, $this
->denormalize($translated_values));
}
else {
$values[] = $this
->denormalize($translated_values);
}
}
$data = array(
'bundle' => $entity
->bundle(),
'translations' => $langcodes,
'values' => $values,
);
$this
->entityToData($entity, $data);
return $data;
}
protected function entityToData(ContentEntityInterface $entity, &$data) {
}
public function getQueryServicename() {
return 'entity.query.mongodb';
}
protected function denormalize(array $translated_values) {
return $translated_values;
}
protected function doLoadFieldItems($entities, $age) {
}
protected function doSaveFieldItems(EntityInterface $entity, $update) {
}
protected function doDeleteFieldItems(EntityInterface $entity) {
}
protected function doDeleteFieldItemsRevision(EntityInterface $entity) {
}
protected function readFieldItemsToPurge(FieldDefinitionInterface $field_definition, $batch_size) {
return [];
}
protected function purgeFieldItems(ContentEntityInterface $entity, FieldDefinitionInterface $field_definition) {
}
protected function doLoadMultiple(array $ids = NULL) {
$find = array();
if ($ids !== NULL) {
$find['_id']['$in'] = array_values(array_map('intval', $ids));
}
return $this
->loadFromMongo('entity', $find);
}
protected function has($id, EntityInterface $entity) {
return !$entity
->isNew();
}
public function countFieldData($storage_definition, $as_bool = FALSE) {
}
protected function mongoCollection(ContentEntityInterface $entity, $prefix) {
return $this->mongo
->get($prefix . '.' . $this->entityTypeId);
}
protected function buildPropertyQuery(QueryInterface $entity_query, array $values) {
$default_langcode_key = $this->entityType
->getKey('default_langcode');
if ($default_langcode_key) {
if (!array_key_exists($default_langcode_key, $values)) {
if ($this->entityType
->isTranslatable()) {
$values[$default_langcode_key] = 1;
}
}
elseif ($values[$default_langcode_key] === NULL) {
unset($values[$default_langcode_key]);
}
}
parent::buildPropertyQuery($entity_query, $values);
}
}