1<?php 2 3namespace Drupal\file\Plugin\Field\FieldType; 4 5use Drupal\Core\Field\EntityReferenceFieldItemList; 6use Drupal\Core\Form\FormStateInterface; 7 8/** 9 * Represents a configurable entity file field. 10 */ 11class FileFieldItemList extends EntityReferenceFieldItemList { 12 13 /** 14 * {@inheritdoc} 15 */ 16 public function defaultValuesForm(array &$form, FormStateInterface $form_state) {} 17 18 /** 19 * {@inheritdoc} 20 */ 21 public function postSave($update) { 22 $entity = $this->getEntity(); 23 24 if (!$update) { 25 // Add a new usage for newly uploaded files. 26 foreach ($this->referencedEntities() as $file) { 27 \Drupal::service('file.usage')->add($file, 'file', $entity->getEntityTypeId(), $entity->id()); 28 } 29 } 30 else { 31 // Get current target file entities and file IDs. 32 $files = $this->referencedEntities(); 33 $ids = []; 34 35 /** @var \Drupal\file\FileInterface $file */ 36 foreach ($files as $file) { 37 $ids[] = $file->id(); 38 } 39 40 // On new revisions, all files are considered to be a new usage and no 41 // deletion of previous file usages are necessary. 42 if (!empty($entity->original) && $entity->getRevisionId() != $entity->original->getRevisionId()) { 43 foreach ($files as $file) { 44 \Drupal::service('file.usage')->add($file, 'file', $entity->getEntityTypeId(), $entity->id()); 45 } 46 return; 47 } 48 49 // Get the file IDs attached to the field before this update. 50 $field_name = $this->getFieldDefinition()->getName(); 51 $original_ids = []; 52 $langcode = $this->getLangcode(); 53 $original = $entity->original; 54 if ($original->hasTranslation($langcode)) { 55 $original_items = $original->getTranslation($langcode)->{$field_name}; 56 foreach ($original_items as $item) { 57 $original_ids[] = $item->target_id; 58 } 59 } 60 61 // Decrement file usage by 1 for files that were removed from the field. 62 $removed_ids = array_filter(array_diff($original_ids, $ids)); 63 $removed_files = \Drupal::entityTypeManager()->getStorage('file')->loadMultiple($removed_ids); 64 foreach ($removed_files as $file) { 65 \Drupal::service('file.usage')->delete($file, 'file', $entity->getEntityTypeId(), $entity->id()); 66 } 67 68 // Add new usage entries for newly added files. 69 foreach ($files as $file) { 70 if (!in_array($file->id(), $original_ids)) { 71 \Drupal::service('file.usage')->add($file, 'file', $entity->getEntityTypeId(), $entity->id()); 72 } 73 } 74 } 75 } 76 77 /** 78 * {@inheritdoc} 79 */ 80 public function delete() { 81 parent::delete(); 82 $entity = $this->getEntity(); 83 84 // If a translation is deleted only decrement the file usage by one. If the 85 // default translation is deleted remove all file usages within this entity. 86 $count = $entity->isDefaultTranslation() ? 0 : 1; 87 foreach ($this->referencedEntities() as $file) { 88 \Drupal::service('file.usage')->delete($file, 'file', $entity->getEntityTypeId(), $entity->id(), $count); 89 } 90 } 91 92 /** 93 * {@inheritdoc} 94 */ 95 public function deleteRevision() { 96 parent::deleteRevision(); 97 $entity = $this->getEntity(); 98 99 // Decrement the file usage by 1. 100 foreach ($this->referencedEntities() as $file) { 101 \Drupal::service('file.usage')->delete($file, 'file', $entity->getEntityTypeId(), $entity->id()); 102 } 103 } 104 105} 106