rdf_sync-1.x-dev/src/RdfSyncUriFieldItemList.php
src/RdfSyncUriFieldItemList.php
<?php
declare(strict_types=1);
namespace Drupal\rdf_sync;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Field\FieldItemList;
use Drupal\Core\TypedData\ComputedItemListTrait;
/**
* Field item list class for RDF URI fields.
*/
class RdfSyncUriFieldItemList extends FieldItemList {
use ComputedItemListTrait;
/**
* {@inheritdoc}
*/
protected function computeValue(): void {
$entity = $this->getEntity();
$uri = \Drupal::database()
->select('rdf_sync_uri', 'u')
->fields('u', ['uri'])
->condition('u.entity_type', $entity->getEntityTypeId())
->condition('u.entity_id', $entity->id())
->execute()
->fetchField();
if ($uri) {
$this->list[0] = $this->createItem(0, $uri);
}
}
// @todo Re-enable this feature when https://www.drupal.org/i/3425226 lands.
// @see https://www.drupal.org/i/3425226
// phpcs:disable
// /**
// * {@inheritdoc}
// */
// public function setValue($values, $notify = TRUE): void {
// if (!$this->getEntity()->isNew()) {
// @trigger_error("Setting the '{$this->getName()}' field is possible only for new entities. Original value is preserved", E_USER_NOTICE);
// return;
// }
// parent::setValue($values, $notify);
// }
// phpcs:enable
/**
* {@inheritdoc}
*/
public function postSave($update): bool {
$update ? $this->updateUri() : $this->assignUri();
return parent::postSave($update);
}
/**
* {@inheritdoc}
*/
public function getEntity(): ContentEntityInterface {
$entity = parent::getEntity();
assert(\Drupal::service('rdf_sync.mapper')->isMappedEntity($entity));
return $entity;
}
/**
* Generates a new URI for the entity based on the generator plugin.
*/
protected function assignUri(): void {
$entity = $this->getEntity();
// The following empty check allows the URI to be set manually during the
// entity creation process.
if (empty($this->list)) {
// No entity ID has been explicitly set in creation. Use the URI
// generator plugin to create a URI.
$pluginId = \Drupal::service('rdf_sync.mapper')->getRdfUriPluginId($entity->getEntityTypeId(), $entity->bundle());
/** @var \Drupal\rdf_sync\RdfUriGeneratorPluginInterface $plugin */
$plugin = \Drupal::getContainer()->get('plugin.manager.rdf_sync.uri_generator')->createInstance($pluginId);
$uri = $plugin->setEntity($entity)->generate();
// Set the value in case it is needed immediately i.e. database operations
// before the transaction is committed.
$this->appendItem($uri);
}
$uri = $this->first()->getValue()['value'];
// Add the record in {rdf_sync_uri} table.
\Drupal::database()
->insert('rdf_sync_uri')
->fields(['entity_type', 'entity_id', 'uri', 'bundle'])
->values([
'entity_type' => $entity->getEntityTypeId(),
'entity_id' => $entity->id(),
'uri' => $uri,
'bundle' => $entity->bundle(),
])->execute();
}
/**
* Updates the URI in the database.
*
* The URI is a non-revisionable field. It's only added once, on entity
* creation, and cannot be changed during the lifetime of an entity -
* except for the case where the URI has changed slightly by changing the
* case of some characters.
*
* @throws \LogicException
* Thrown when the URI is changed after creation.
*/
protected function updateUri(): void {
$entity = $this->getEntity();
$uri = $this->first()->getValue()['value'];
$database = \Drupal::database();
$originalUri = $database->select('rdf_sync_uri', 'u')
->fields('u', ['uri'])
->condition('u.entity_type', $entity->getEntityTypeId())
->condition('u.entity_id', $entity->id())
->execute()
->fetchField();
if (strtolower($uri) !== strtolower($originalUri)) {
throw new \LogicException('The RDF URI cannot be changed after creation.');
}
elseif ($uri !== $originalUri) {
$database->update('rdf_sync_uri')
->fields(['uri' => $uri])
->condition('entity_type', $entity->getEntityTypeId())
->condition('entity_id', $entity->id())
->execute();
}
}
}
