Commit 3b00f30d authored by catch's avatar catch

Issue #2073033 by claudiu.cristea, netsensei: Optimize file usage updates in file/image fields.

parent b014ce1c
......@@ -2,7 +2,7 @@
/**
* @file
* Contains \Drupal\file\Plugin\field\field_type\FileField.
* Contains \Drupal\file\Plugin\field\field_type\FileFieldItemList.
*/
namespace Drupal\file\Plugin\field\field_type;
......@@ -22,50 +22,105 @@ public function defaultValuesForm(array &$form, array &$form_state) { }
/**
* {@inheritdoc}
*/
public function update() {
parent::update();
$this->updateFileUsage();
public function insert() {
parent::insert();
$entity = $this->getEntity();
// Add a new usage for newly uploaded files.
foreach ($this->targetEntities() as $file) {
\Drupal::service('file.usage')->add($file, 'file', $entity->entityType(), $entity->id());
}
}
/**
* Updates the file usage.
* {@inheritdoc}
*/
protected function updateFileUsage() {
$entity = $this->getRoot();
public function update() {
parent::update();
$entity = $this->getEntity();
// Get current target file entities and file IDs.
$files = $this->targetEntities();
$fids = array_keys($files);
// On new revisions, all files are considered to be a new usage and no
// deletion of previous file usages are necessary.
if (!empty($entity->original) && $entity->getRevisionId() != $entity->original->getRevisionId()) {
foreach ($this->list as $item) {
file_usage()->add($item->entity, 'file', $entity->entityType(), $entity->id());
foreach ($files as $file) {
\Drupal::service('file.usage')->add($file, 'file', $entity->entityType(), $entity->id());
}
return;
}
// Build a list of the current target IDs.
$fids = array();
foreach ($this->list as $item) {
$fids[] = $item->target_id;
}
// Compare the original field values with the ones that are being saved.
// Get the file IDs attached to the field before this update.
$field_name = $this->getFieldDefinition()->getFieldName();
$original_fids = array();
$original_items = $entity->original->getTranslation($this->getLangcode())->$field_name;
foreach ($original_items as $item) {
$original_fids[] = $item->target_id;
if ($item->target_id && !in_array($item->target_id, $fids)) {
// Decrement the file usage count by 1.
file_usage()->delete($item->entity, 'file', $entity->entityType(), $entity->id());
}
}
// Decrement file usage by 1 for files that were removed from the field.
$removed_fids = array_filter(array_diff($original_fids, $fids));
$removed_files = \Drupal::entityManager()->getStorageController('file')->loadMultiple($removed_fids);
foreach ($removed_files as $file) {
\Drupal::service('file.usage')->delete($file, 'file', $entity->entityType(), $entity->id());
}
// Add new usage entries for newly added files.
foreach ($this->list as $item) {
if ($item->target_id && !in_array($item->target_id, $original_fids)) {
file_usage()->add($item->entity, 'file', $entity->entityType(), $entity->id());
foreach ($files as $fid => $file) {
if (!in_array($fid, $original_fids)) {
\Drupal::service('file.usage')->add($file, 'file', $entity->entityType(), $entity->id());
}
}
}
/**
* {@inheritdoc}
*/
public function delete() {
parent::delete();
$entity = $this->getEntity();
// Delete all file usages within this entity.
foreach ($this->targetEntities() as $file) {
\Drupal::service('file.usage')->delete($file, 'file', $entity->entityType(), $entity->id(), 0);
}
}
/**
* {@inheritdoc}
*/
public function deleteRevision() {
parent::deleteRevision();
$entity = $this->getEntity();
// Decrement the file usage by 1.
foreach ($this->targetEntities() as $file) {
\Drupal::service('file.usage')->delete($file, 'file', $entity->entityType(), $entity->id());
}
}
/**
* Collects target file entities for this field.
*
* @return array
* An array with the list of target file entities keyed by file ID.
*
* @todo Drop this when https://drupal.org/node/2073661 lands.
*/
protected function targetEntities() {
if (!isset($this->list)) {
return array();
}
$ids = array();
foreach ($this->list as $item) {
$ids[] = $item->target_id;
}
// Prevent NULLs as target IDs.
$ids = array_filter($ids);
return $ids ? \Drupal::entityManager()->getStorageController('file')->loadMultiple($ids) : array();
}
}
......@@ -200,39 +200,6 @@ public function instanceSettingsForm(array $form, array &$form_state) {
return $element;
}
/**
* {@inheritdoc}
*/
public function insert() {
// @todo Move in FileField in https://drupal.org/node/2073033.
$entity = $this->getRoot();
// Add a new usage for this new uploaded file.
file_usage()->add($this->entity, 'file', $entity->entityType(), $entity->id());
}
/**
* {@inheritdoc}
*/
public function delete() {
// @todo Move in FileField in https://drupal.org/node/2073033.
$entity = $this->getRoot();
// Delete all file usages within this entity.
file_usage()->delete($this->entity, 'file', $entity->entityType(), $entity->id(), 0);
}
/**
* {@inheritdoc}
*/
public function deleteRevision() {
// @todo Move in FileField in https://drupal.org/node/2073033.
$entity = $this->getRoot();
// Decrement the file usage count by 1.
file_usage()->delete($this->entity, 'file', $entity->entityType(), $entity->id());
}
/**
* {@inheritdoc}
*/
......
......@@ -94,6 +94,11 @@ public function testFileItem() {
$entity->file_test->target_id = $file2->id();
$this->assertEqual($entity->file_test->entity->id(), $file2->id());
$this->assertEqual($entity->file_test->entity->getFileUri(), $file2->getFileUri());
// Test the deletion of an entity having an entity reference field targeting
// a non-existing entity.
$file2->delete();
$entity->delete();
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment