Skip to content
Snippets Groups Projects
Commit 54360936 authored by Dries Buytaert's avatar Dries Buytaert
Browse files

- Patch #1658712 by plach, Gábor Hojtsy: Refactor test_entity() schema to be multilingual.

parent 9b7ac70b
No related branches found
No related tags found
2 merge requests!7452Issue #1797438. HTML5 validation is preventing form submit and not fully...,!789Issue #3210310: Adjust Database API to remove deprecated Drupal 9 code in Drupal 10
<?php
/**
* @file
* Definition of Drupal\entity_test\EntityTest.
*/
namespace Drupal\entity_test;
use InvalidArgumentException;
use Drupal\entity\Entity;
/**
* Defines the test entity class.
*/
class EntityTest extends Entity {
/**
* An array keyed by language code where the entity properties are stored.
*
* @var array
*/
protected $properties;
/**
* An array of allowed language codes.
*
* @var array
*/
protected static $langcodes;
/**
* Constructs a new entity object.
*/
public function __construct(array $values, $entity_type) {
parent::__construct($values, $entity_type);
if (!isset(self::$langcodes)) {
// The allowed languages are simply all the available ones in the system.
self::$langcodes = drupal_map_assoc(array_keys(language_list(LANGUAGE_ALL)));
}
// Initialize the original entity language with the provided value or fall
// back to LANGUAGE_NOT_SPECIFIED if none was specified. We do not check
// against allowed languages here, since throwing an exception would make an
// entity created in a subsequently uninstalled language not instantiable.
$this->langcode = !empty($values['langcode']) ? $values['langcode'] : LANGUAGE_NOT_SPECIFIED;
// Set initial values ensuring that only real properties are stored.
// @todo For now we have no way to mark a property as multlingual hence we
// just assume that all of them are.
unset($values['id'], $values['uuid'], $values['default_langcode']);
$this->setProperties($values, $this->langcode);
}
/**
* Sets the entity original langcode.
*
* @param $langcode
*/
public function setLangcode($langcode) {
// If the original language is changed the related properties must change
// their language accordingly.
$prev_langcode = $this->langcode;
if (isset($this->properties[$prev_langcode])) {
$this->properties[$langcode] = $this->properties[$prev_langcode];
unset($this->properties[$prev_langcode]);
}
$this->langcode = $langcode;
}
/**
* Overrides EntityInterface::get().
*/
public function get($property_name, $langcode = NULL) {
$langcode = !empty($langcode) ? $langcode : $this->langcode;
$entity_info = $this->entityInfo();
if ($entity_info['fieldable'] && field_info_instance($this->entityType, $property_name, $this->bundle())) {
return parent::get($property_name, $langcode);
}
elseif (isset($this->properties[$langcode][$property_name])) {
return $this->properties[$langcode][$property_name];
}
else {
// @todo Remove this. All properties should be stored in the $properties
// array once we have a Property API in place.
return property_exists($this, $property_name) ? $this->{$property_name} : NULL;
}
}
/**
* Overrides EntityInterface::set().
*/
public function set($property_name, $value, $langcode = NULL) {
$langcode = !empty($langcode) ? $langcode : $this->langcode;
if (!isset(self::$langcodes[$langcode])) {
throw new InvalidArgumentException("Detected an invalid language '$langcode' while setting '$property_name' to '$value'.");
}
$entity_info = $this->entityInfo();
if ($entity_info['fieldable'] && field_info_instance($this->entityType, $property_name, $this->bundle())) {
parent::set($property_name, $value, $langcode);
}
else {
$this->properties[$langcode][$property_name] = $value;
}
}
/**
* Overrides EntityInterface::translations().
*/
public function translations() {
$translations = !empty($this->properties) ? $this->properties : array();
$languages = array_intersect_key(self::$langcodes, $translations);
unset($languages[$this->langcode]);
return $languages + parent::translations();
}
/**
* Returns the property array for the given language.
*
* @param string $langcode
* (optional) The language code to be used to retrieve the properties.
*/
public function getProperties($langcode = NULL) {
$langcode = !empty($langcode) ? $langcode : $this->langcode;
return isset($this->properties[$langcode]) ? $this->properties[$langcode] : array();
}
/**
* Sets the property array for the given language.
*
* @param array $properties
* A keyed array of properties to be set with their 'langcode' as one of the
* keys. If no language is provided the entity language is used.
* @param string $langcode
* (optional) The language code to be used to set the properties.
*/
public function setProperties(array $properties, $langcode = NULL) {
$langcode = !empty($langcode) ? $langcode : $this->langcode;
$this->properties[$langcode] = $properties;
}
}
<?php
/**
* @file
* Definition of Drupal\entity_test\EntityTestStorageController.
*/
namespace Drupal\entity_test;
use PDO;
use Drupal\entity\EntityInterface;
use Drupal\entity\DatabaseStorageController;
/**
* Defines the controller class for the test entity.
*
* This extends the Drupal\entity\DatabaseStorageController class, adding
* required special handling for test entities.
*/
class EntityTestStorageController extends DatabaseStorageController {
/**
* Overrides Drupal\entity\DatabaseStorageController::buildQuery().
*/
protected function buildQuery($ids, $conditions = array(), $revision_id = FALSE) {
$query = parent::buildQuery($ids, $conditions, $revision_id);
if ($conditions) {
// Reset conditions as the default storage controller applies them to the
// base table.
$query_conditions = &$query->conditions();
$query_conditions = array('#conjunction' => 'AND');
// Restore id conditions.
if ($ids) {
$query->condition("base.{$this->idKey}", $ids, 'IN');
}
// Conditions need to be applied the property data table.
$query->addJoin('inner', 'entity_test_property_data', 'data', "base.{$this->idKey} = data.{$this->idKey}");
$query->distinct(TRUE);
// @todo We should not be using a condition to specify whether conditions
// apply to the default language or not. We need to move this to a
// separate parameter during the following API refactoring.
// Default to the original entity language if not explicitly specified
// otherwise.
if (!array_key_exists('default_langcode', $conditions)) {
$conditions['default_langcode'] = 1;
}
// If the 'default_langcode' flag is esplicitly not set, we do not care
// whether the queried values are in the original entity language or not.
elseif ($conditions['default_langcode'] === NULL) {
unset($conditions['default_langcode']);
}
foreach ($conditions as $field => $value) {
$query->condition('data.' . $field, $value);
}
}
return $query;
}
/**
* Overrides Drupal\entity\DatabaseStorageController::attachLoad().
*/
protected function attachLoad(&$queried_entities, $revision_id = FALSE) {
$data = db_select('entity_test_property_data', 'data', array('fetch' => PDO::FETCH_ASSOC))
->fields('data')
->condition('id', array_keys($queried_entities))
->orderBy('data.id')
->execute();
foreach ($data as $values) {
$entity = $queried_entities[$values['id']];
$langcode = $values['langcode'];
if (!empty($values['default_langcode'])) {
$entity->setLangcode($langcode);
}
// Make sure only real properties are stored.
unset($values['id'], $values['default_langcode']);
$entity->setProperties($values, $langcode);
}
parent::attachLoad($queried_entities, $revision_id);
}
/**
* Overrides Drupal\entity\DatabaseStorageController::postSave().
*/
protected function postSave(EntityInterface $entity, $update) {
$default_langcode = ($language = $entity->language()) ? $language->langcode : LANGUAGE_NOT_SPECIFIED;
$langcodes = array_keys($entity->translations());
$langcodes[] = $default_langcode;
foreach ($langcodes as $langcode) {
$properties = $entity->getProperties($langcode);
$values = array(
'id' => $entity->id(),
'langcode' => $langcode,
'default_langcode' => intval($default_langcode == $langcode),
) + $properties;
db_merge('entity_test_property_data')
->fields($values)
->condition('id', $values['id'])
->condition('langcode', $values['langcode'])
->execute();
}
}
/**
* Overrides Drupal\entity\DatabaseStorageController::postDelete().
*/
protected function postDelete($entities) {
db_delete('entity_test_property_data')
->condition('id', array_keys($entities))
->execute();
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment