View source
<?php
namespace Drupal\file_entity\Entity;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Entity\FieldableEntityInterface;
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\Core\Site\Settings;
use Drupal\Core\StreamWrapper\StreamWrapperInterface;
use Drupal\Core\StreamWrapper\StreamWrapperManager;
use Drupal\Core\Url;
use Drupal\Component\Utility\Crypt;
use Drupal\file\Entity\File;
use Drupal\file_entity\FileEntityInterface;
class FileEntity extends File implements FileEntityInterface {
protected $metadata = NULL;
protected $metadataChanged = FALSE;
protected function loadMetadata() {
if ($this->metadata === NULL) {
$results = \Drupal::database()
->query("SELECT * FROM {file_metadata} WHERE fid = :fid", array(
':fid' => $this
->id(),
));
foreach ($results as $result) {
$this->metadata[$result->name] = unserialize($result->value);
}
}
}
public function getMetadata($property) {
$this
->loadMetadata();
return isset($this->metadata[$property]) ? $this->metadata[$property] : NULL;
}
public function hasMetadata($property) {
$this
->loadMetadata();
return isset($this->metadata[$property]);
}
public function setMetadata($property, $value) {
$this
->loadMetadata();
$this->metadata[$property] = $value;
$this->metadataChanged = TRUE;
}
public function getAllMetadata() {
$this
->loadMetadata();
return $this->metadata;
}
public static function preCreate(EntityStorageInterface $storage, array &$values) {
parent::preCreate($storage, $values);
$values += array(
'type' => FILE_TYPE_NONE,
);
}
public function __construct(array $values, $entity_type, $bundle = FALSE, $translations = array()) {
if (!$bundle) {
$values['type'] = FILE_TYPE_NONE;
$bundle = FILE_TYPE_NONE;
}
parent::__construct($values, $entity_type, $bundle, $translations);
}
public function url($rel = 'canonical', $options = array()) {
if ($this
->isNew() || !$this
->hasLinkTemplate($rel)) {
return '';
}
$uri = $this
->toUrl($rel);
$options += $uri
->getOptions();
$uri
->setOptions($options);
return $uri
->toString();
}
public function postCreate(EntityStorageInterface $storage) {
parent::postCreate($storage);
if ($this
->bundle() === FILE_TYPE_NONE) {
$this
->updateBundle();
}
}
public function preSave(EntityStorageInterface $storage) {
if (file_exists($this
->getFileUri())) {
$this
->setSize(filesize($this
->getFileUri()));
}
$this
->setMimeType(\Drupal::service('file.mime_type.guesser')
->guess($this
->getFileUri()));
if ($this
->bundle() === FILE_TYPE_NONE) {
$this
->updateBundle();
}
if (!empty($this->original) && $this
->bundle() != $this->original
->bundle()) {
$this->original
->get('type')->target_id = $this
->bundle();
$this->original->fieldDefinitions = NULL;
$this->original->typedData = NULL;
$this->original->entityKeys['bundle'] = $this
->bundle();
}
$this
->fetchImageDimensions();
}
protected function fetchImageDimensions() {
if (!$this
->getSize()) {
return;
}
if ($this
->getMimeTypeType() != 'image') {
return;
}
$image = \Drupal::service('image.factory')
->get($this
->getFileUri());
if ($image) {
$this
->setMetadata('width', $image
->getWidth());
$this
->setMetadata('height', $image
->getHeight());
}
}
public function getMimeTypeType() {
list($type, $subtype) = explode('/', $this
->getMimeType(), 2);
return $type;
}
public function postSave(EntityStorageInterface $storage, $update = TRUE) {
parent::postSave($storage, $update);
if ($this->metadataChanged) {
if ($update) {
\Drupal::database()
->delete('file_metadata')
->condition('fid', $this
->id())
->execute();
}
$query = \Drupal::database()
->insert('file_metadata')
->fields(array(
'fid',
'name',
'value',
));
foreach ($this
->getAllMetadata() as $name => $value) {
$query
->values(array(
'fid' => $this
->id(),
'name' => $name,
'value' => serialize($value),
));
}
$query
->execute();
$this->metadataChanged = FALSE;
}
if ($update) {
if (\Drupal::moduleHandler()
->moduleExists('image') && $this
->getMimeTypeType() == 'image' && $this
->getSize()) {
if ($this->original
->getMetadata('width') && ($this
->getMetadata('width') != $this->original
->getMetadata('width') || $this
->getMetadata('height') != $this->original
->getMetadata('height'))) {
$this
->updateImageFieldDimensions();
}
image_path_flush($this
->getFileUri());
}
}
}
protected function updateImageFieldDimensions() {
if (!$this
->getSize()) {
return;
}
if ($this
->getMimeTypeType() != 'image') {
return;
}
$image_fields = \Drupal::service('entity_field.manager')
->getFieldMapByFieldType('image');
foreach ($image_fields as $entity_type_id => $field_names) {
foreach (array_keys($field_names) as $image_field) {
$ids = \Drupal::entityQuery($entity_type_id)
->condition($image_field . '.target_id', $this
->id())
->execute();
$entities = \Drupal::entityTypeManager()
->getStorage($entity_type_id)
->loadMultiple($ids);
foreach ($entities as $entity) {
$this
->updateImageFieldDimensionsByEntity($entity, $image_field);
}
}
}
}
protected function updateImageFieldDimensionsByEntity(FieldableEntityInterface $entity, $image_field) {
foreach (array_keys($entity
->getTranslationLanguages()) as $langcode) {
$translation = $entity
->getTranslation($langcode);
foreach ($translation->{$image_field} as $item) {
if ($item->target_id == $this
->id()) {
$item->width = $this
->getMetadata('width');
$item->height = $this
->getMetadata('height');
}
}
}
$entity
->save();
}
public static function preDelete(EntityStorageInterface $storage, array $entities) {
parent::preDelete($storage, $entities);
\Drupal::database()
->delete('file_metadata')
->condition('fid', array_keys($entities), 'IN')
->execute();
}
public function updateBundle($type = NULL) {
if (!$type) {
$type = $this
->determineType();
if (!$type) {
return;
}
}
$this
->get('type')->target_id = $type;
$this->fieldDefinitions = NULL;
$this->typedData = NULL;
$this->entityKeys['bundle'] = $type;
}
public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
$fields = parent::baseFieldDefinitions($entity_type);
$fields['type'] = BaseFieldDefinition::create('entity_reference')
->setLabel(t('File type'))
->setDescription(t('The type of the file.'))
->setSetting('target_type', 'file_type');
$fields['filename']
->setDisplayOptions('view', array(
'type' => 'string',
'label' => 'hidden',
'weight' => -5,
))
->setDisplayConfigurable('view', TRUE)
->setDisplayOptions('form', array(
'type' => 'string_textfield',
'weight' => -5,
))
->setDisplayConfigurable('form', TRUE);
$fields['uri']
->setDisplayOptions('view', array(
'type' => 'file_image',
'label' => 'hidden',
'weight' => -5,
))
->setDisplayConfigurable('view', TRUE);
$fields['uid']
->setDisplayOptions('view', array(
'type' => 'uri_link',
'weight' => 1,
))
->setDisplayConfigurable('view', TRUE)
->setDisplayOptions('form', array(
'type' => 'entity_reference_autocomplete',
'weight' => -1,
'settings' => array(
'match_operator' => 'CONTAINS',
'size' => '60',
'autocomplete_type' => 'tags',
'placeholder' => '',
),
));
$fields['filemime']
->setDisplayOptions('view', array(
'type' => 'string',
'weight' => 2,
))
->setDisplayConfigurable('view', TRUE);
$fields['filesize']
->setDisplayOptions('view', array(
'type' => 'file_size',
'weight' => 3,
))
->setDisplayConfigurable('view', TRUE);
return $fields;
}
function isReadable() {
$scheme = StreamWrapperManager::getScheme($this
->getFileUri());
$wrappers = \Drupal::service('stream_wrapper_manager')
->getWrappers(StreamWrapperInterface::READ);
return !empty($wrappers[$scheme]);
}
public function isWritable() {
$scheme = StreamWrapperManager::getScheme($this
->getFileUri());
$wrappers = \Drupal::service('stream_wrapper_manager')
->getWrappers(StreamWrapperInterface::WRITE_VISIBLE);
return !empty($wrappers[$scheme]);
}
public function isPage() {
$page_file = \Drupal::routeMatch()
->getParameter('file');
return !empty($page_file) && $page_file
->id() == $this
->id();
}
public function isLocal() {
$scheme = StreamWrapperManager::getScheme($this->uri);
$wrappers = \Drupal::service('stream_wrapper_manager')
->getWrappers(StreamWrapperInterface::LOCAL);
return !empty($wrappers[$scheme]) && empty($wrappers[$scheme]['remote']);
}
public function downloadUrl($options = array()) {
$url = new Url('file_entity.file_download', array(
'file' => $this
->id(),
), $options);
if (!\Drupal::config('file_entity.settings')
->get('allow_insecure_download')) {
$url
->setOption('query', array(
'token' => $this
->getDownloadToken(),
));
}
return $url;
}
public function getDownloadToken() {
return substr(Crypt::hmacBase64("file/{$this->id()}/download:" . $this
->getFileUri(), \Drupal::service('private_key')
->get() . Settings::getHashSalt()), 0, 8);
}
protected function determineType() {
$types = \Drupal::moduleHandler()
->invokeAll('file_type', array(
$this,
));
\Drupal::moduleHandler()
->alter('file_type', $types, $this);
return empty($types) ? NULL : reset($types);
}
public function getCacheTags() {
return [];
}
public function validate() {
if ($this
->bundle() === FILE_TYPE_NONE) {
$this
->updateBundle();
}
return parent::validate();
}
protected function invalidateTagsOnSave($update) {
$tags = $this
->getEntityType()
->getListCacheTags();
if ($update) {
foreach (\Drupal::service('file.usage')
->listUsage($this) as $module => $module_references) {
foreach ($module_references as $type => $ids) {
if ($this
->entityTypeManager()
->hasDefinition($type)) {
$tags = Cache::mergeTags($tags, Cache::buildTags($type, array_keys($ids)));
}
}
}
}
Cache::invalidateTags($tags);
}
protected static function invalidateTagsOnDelete(EntityTypeInterface $entity_type, array $entities) {
$tags = $entity_type
->getListCacheTags();
Cache::invalidateTags($tags);
}
}