View source
<?php
namespace Drupal\file_mdm\Plugin\FileMetadata;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\PluginBase;
use Drupal\file_mdm\FileMetadataException;
use Drupal\file_mdm\FileMetadataInterface;
use Drupal\file_mdm\Plugin\FileMetadataPluginInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
abstract class FileMetadataPluginBase extends PluginBase implements FileMetadataPluginInterface {
protected $cache;
protected $configFactory;
protected $uri;
protected $localTempPath;
protected $hash;
protected $metadata = NULL;
protected $isMetadataLoaded = FileMetadataInterface::NOT_LOADED;
protected $hasMetadataChangedFromFileVersion = FALSE;
protected $hasMetadataChangedFromCacheVersion = FALSE;
public function __construct(array $configuration, $plugin_id, array $plugin_definition, CacheBackendInterface $cache_service, ConfigFactoryInterface $config_factory) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->cache = $cache_service;
$this->configFactory = $config_factory;
}
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static($configuration, $plugin_id, $plugin_definition, $container
->get('cache.file_mdm'), $container
->get('config.factory'));
}
public static function defaultConfiguration() {
return [
'cache' => [
'override' => FALSE,
'settings' => [
'enabled' => TRUE,
'expiration' => 172800,
'disallowed_paths' => [],
],
],
];
}
protected function getConfigObject($editable = FALSE) {
$plugin_definition = $this
->getPluginDefinition();
$config_name = $plugin_definition['provider'] . '.file_metadata_plugin.' . $plugin_definition['id'];
return $editable ? $this->configFactory
->getEditable($config_name) : $this->configFactory
->get($config_name);
}
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
$form['override'] = [
'#type' => 'checkbox',
'#title' => $this
->t('Override main caching settings'),
'#default_value' => $this->configuration['cache']['override'],
];
$form['cache_details'] = [
'#type' => 'details',
'#open' => TRUE,
'#collapsible' => FALSE,
'#title' => $this
->t('Metadata caching'),
'#tree' => TRUE,
'#states' => [
'visible' => [
':input[name="' . $this
->getPluginId() . '[override]"]' => [
'checked' => TRUE,
],
],
],
];
$form['cache_details']['settings'] = [
'#type' => 'file_mdm_caching',
'#default_value' => $this->configuration['cache']['settings'],
];
return $form;
}
public function validateConfigurationForm(array &$form, FormStateInterface $form_state) {
}
public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
$this->configuration['cache']['override'] = (bool) $form_state
->getValue([
$this
->getPluginId(),
'override',
]);
$this->configuration['cache']['settings'] = $form_state
->getValue([
$this
->getPluginId(),
'cache_details',
'settings',
]);
$config = $this
->getConfigObject(TRUE);
$config
->set('configuration', $this->configuration);
if ($config
->getOriginal('configuration') != $config
->get('configuration')) {
$config
->save();
}
}
public function setUri($uri) {
if (!$uri) {
throw new FileMetadataException('Missing $uri argument', $this
->getPluginId(), __FUNCTION__);
}
$this->uri = $uri;
return $this;
}
public function getUri() {
return $this->uri;
}
public function setLocalTempPath($temp_path) {
$this->localTempPath = $temp_path;
return $this;
}
public function getLocalTempPath() {
return $this->localTempPath;
}
public function setHash($hash) {
if (!$hash) {
throw new FileMetadataException('Missing $hash argument', $this
->getPluginId(), __FUNCTION__);
}
$this->hash = $hash;
return $this;
}
public function isMetadataLoaded() {
return $this->isMetadataLoaded;
}
public function loadMetadata($metadata) {
$this->metadata = $metadata;
$this->hasMetadataChangedFromFileVersion = TRUE;
$this->hasMetadataChangedFromCacheVersion = TRUE;
$this
->deleteCachedMetadata();
if ($this->metadata === NULL) {
$this->isMetadataLoaded = FileMetadataInterface::NOT_LOADED;
}
else {
$this->isMetadataLoaded = FileMetadataInterface::LOADED_BY_CODE;
$this
->saveMetadataToCache();
}
return (bool) $this->metadata;
}
public function loadMetadataFromFile() {
if (!file_exists($this
->getLocalTempPath())) {
throw new FileMetadataException("File at '{$this->getLocalTempPath()}' does not exist", $this
->getPluginId(), __FUNCTION__);
}
$this->hasMetadataChangedFromFileVersion = FALSE;
if (($this->metadata = $this
->doGetMetadataFromFile()) === NULL) {
$this->isMetadataLoaded = FileMetadataInterface::NOT_LOADED;
$this
->deleteCachedMetadata();
}
else {
$this->isMetadataLoaded = FileMetadataInterface::LOADED_FROM_FILE;
$this
->saveMetadataToCache();
}
return (bool) $this->metadata;
}
protected abstract function doGetMetadataFromFile();
public function loadMetadataFromCache() {
$plugin_id = $this
->getPluginId();
$this->hasMetadataChangedFromFileVersion = FALSE;
$this->hasMetadataChangedFromCacheVersion = FALSE;
if ($this
->isUriFileMetadataCacheable() !== FALSE && ($cache = $this->cache
->get("hash:{$plugin_id}:{$this->hash}"))) {
$this->metadata = $cache->data;
$this->isMetadataLoaded = FileMetadataInterface::LOADED_FROM_CACHE;
}
else {
$this->metadata = NULL;
$this->isMetadataLoaded = FileMetadataInterface::NOT_LOADED;
}
return (bool) $this->metadata;
}
protected function isUriFileMetadataCacheable() {
if ($this->configuration['cache']['override']) {
$settings = $this->configuration['cache']['settings'];
if (!$settings['enabled']) {
return FALSE;
}
}
if (!isset($settings)) {
$settings = $this->configFactory
->get('file_mdm.settings')
->get('metadata_cache');
if (!$settings['enabled']) {
return FALSE;
}
}
if (!file_valid_uri($this
->getUri()) || file_uri_scheme($this
->getUri()) === 'temporary') {
return FALSE;
}
foreach ($settings['disallowed_paths'] as $pattern) {
$p = "#^" . strtr(preg_quote($pattern, '#'), [
'\\*' => '.*',
'\\?' => '.',
]) . "\$#i";
if (preg_match($p, $this
->getUri())) {
return FALSE;
}
}
return $settings;
}
public function getMetadata($key = NULL) {
if (!$this
->getUri()) {
throw new FileMetadataException("No URI specified", $this
->getPluginId(), __FUNCTION__);
}
if (!$this->hash) {
throw new FileMetadataException("No hash specified", $this
->getPluginId(), __FUNCTION__);
}
if ($this->metadata === NULL) {
$this
->loadMetadataFromCache();
}
if ($this->metadata === NULL && $this->isMetadataLoaded !== FileMetadataInterface::LOADED_FROM_FILE) {
$this
->loadMetadataFromFile();
}
return $this
->doGetMetadata($key);
}
protected abstract function doGetMetadata($key = NULL);
public function setMetadata($key, $value) {
if ($key === NULL) {
throw new FileMetadataException("No metadata key specified for file at '{$this->getUri()}'", $this
->getPluginId(), __FUNCTION__);
}
if (!$this->metadata && !$this
->getMetadata()) {
throw new FileMetadataException("No metadata loaded for file at '{$this->getUri()}'", $this
->getPluginId(), __FUNCTION__);
}
if ($this
->doSetMetadata($key, $value)) {
$this->hasMetadataChangedFromFileVersion = TRUE;
if ($this->isMetadataLoaded === FileMetadataInterface::LOADED_FROM_CACHE) {
$this->hasMetadataChangedFromCacheVersion = TRUE;
}
return TRUE;
}
return FALSE;
}
protected abstract function doSetMetadata($key, $value);
public function removeMetadata($key) {
if ($key === NULL) {
throw new FileMetadataException("No metadata key specified for file at '{$this->getUri()}'", $this
->getPluginId(), __FUNCTION__);
}
if (!$this->metadata && !$this
->getMetadata()) {
throw new FileMetadataException("No metadata loaded for file at '{$this->getUri()}'", $this
->getPluginId(), __FUNCTION__);
}
if ($this
->doRemoveMetadata($key)) {
$this->hasMetadataChangedFromFileVersion = TRUE;
if ($this->isMetadataLoaded === FileMetadataInterface::LOADED_FROM_CACHE) {
$this->hasMetadataChangedFromCacheVersion = TRUE;
}
return TRUE;
}
return FALSE;
}
protected abstract function doRemoveMetadata($key);
public function isSaveToFileSupported() {
return FALSE;
}
public function saveMetadataToFile() {
if (!$this
->isSaveToFileSupported()) {
throw new FileMetadataException('Write metadata to file is not supported', $this
->getPluginId(), __FUNCTION__);
}
if ($this->metadata === NULL) {
return FALSE;
}
if ($this->hasMetadataChangedFromFileVersion) {
$this
->deleteCachedMetadata();
return $this
->doSaveMetadataToFile();
}
return FALSE;
}
protected function doSaveMetadataToFile() {
return FALSE;
}
public function saveMetadataToCache(array $tags = []) {
if ($this->metadata === NULL) {
return FALSE;
}
if (($cache_settings = $this
->isUriFileMetadataCacheable()) === FALSE) {
return FALSE;
}
if ($this->isMetadataLoaded !== FileMetadataInterface::LOADED_FROM_CACHE || $this->isMetadataLoaded === FileMetadataInterface::LOADED_FROM_CACHE && $this->hasMetadataChangedFromCacheVersion) {
$tags = Cache::mergeTags($tags, $this
->getConfigObject()
->getCacheTags());
$tags = Cache::mergeTags($tags, $this->configFactory
->get('file_mdm.settings')
->getCacheTags());
$expire = $cache_settings['expiration'] === -1 ? Cache::PERMANENT : time() + $cache_settings['expiration'];
$this->cache
->set("hash:{$this->getPluginId()}:{$this->hash}", $this
->getMetadataToCache(), $expire, $tags);
$this->hasMetadataChangedFromCacheVersion = FALSE;
return TRUE;
}
return FALSE;
}
protected function getMetadataToCache() {
return $this->metadata;
}
public function deleteCachedMetadata() {
if ($this
->isUriFileMetadataCacheable() === FALSE) {
return FALSE;
}
$plugin_id = $this
->getPluginId();
$this->cache
->delete("hash:{$plugin_id}:{$this->hash}");
$this->hasMetadataChangedFromCacheVersion = FALSE;
return TRUE;
}
}