View source
<?php
namespace Drupal\restful\Plugin\resource\Decorators;
use Drupal\restful\Http\HttpHeader;
use Drupal\restful\Plugin\resource\DataProvider\CacheDecoratedDataProvider;
use Drupal\restful\Plugin\resource\DataProvider\DataProviderInterface;
use Drupal\restful\Plugin\resource\ResourceInterface;
use Drupal\restful\RenderCache\Entity\CacheFragmentController;
use Drupal\restful\RenderCache\RenderCache;
use Drupal\restful\Resource\ResourceManager;
class CacheDecoratedResource extends ResourceDecoratorBase implements CacheDecoratedResourceInterface {
const CACHE_PAIR_SEPARATOR = '#';
protected $cacheController;
protected $dataProvider;
public function __construct(ResourceInterface $subject, \DrupalCacheInterface $cache_controller = NULL) {
$this->subject = $subject;
$this->cacheController = $cache_controller ? $cache_controller : $this
->newCacheObject();
$cache_info = $this
->defaultCacheInfo();
$this->pluginDefinition['renderCache'] = $cache_info;
}
public function getCacheController() {
return $this->cacheController;
}
protected function newCacheObject() {
static $cache_object;
if (isset($cache_object)) {
return $cache_object;
}
$cache_info = $this
->defaultCacheInfo();
$class_name = empty($cache_info['class']) ? NULL : $cache_info['class'];
if (empty($class_name)) {
$class_name = variable_get('cache_class_' . $cache_info['bin']);
}
if (empty($class_name)) {
$class_name = variable_get('cache_default_class', 'DrupalDatabaseCache');
}
$cache_object = new $class_name($cache_info['bin']);
return $cache_object;
}
public function dataProviderFactory() {
if ($this->dataProvider && $this->dataProvider instanceof CacheDecoratedDataProvider) {
return $this->dataProvider;
}
$decorated_provider = $this->subject
->dataProviderFactory();
$this->dataProvider = new CacheDecoratedDataProvider($decorated_provider, $this
->getCacheController());
$plugin_definition = $this
->getPluginDefinition();
$this->dataProvider
->addOptions(array(
'renderCache' => $this
->defaultCacheInfo(),
'resource' => array(
'version' => array(
'major' => $plugin_definition['majorVersion'],
'minor' => $plugin_definition['minorVersion'],
),
'name' => $plugin_definition['resource'],
),
));
return $this->dataProvider;
}
public function getPath() {
return $this->subject
->getPath();
}
public function setPath($path) {
$this->subject
->setPath($path);
}
public function getFieldDefinitions() {
return $this->subject
->getFieldDefinitions();
}
public function getDataProvider() {
if (isset($this->dataProvider)) {
return $this->dataProvider;
}
$this->dataProvider = $this
->dataProviderFactory();
return $this->dataProvider;
}
public function setDataProvider(DataProviderInterface $data_provider = NULL) {
$this->dataProvider = $data_provider;
}
public function process() {
$path = $this
->getPath();
return ResourceManager::executeCallback($this
->getControllerFromPath($path), array(
$path,
));
}
public function view($path) {
$ids = explode(static::IDS_SEPARATOR, $path);
$canonical_path = $this
->getDataProvider()
->canonicalPath($path);
$this
->getRequest()
->getHeaders()
->add(HttpHeader::create('Link', $this
->versionedUrl($canonical_path, array(), FALSE) . '; rel="canonical"'));
if (count($ids) == 1) {
return array(
$this
->getDataProvider()
->view($ids[0]),
);
}
else {
return $this
->getDataProvider()
->viewMultiple($ids);
}
}
public function index($path) {
return $this
->getDataProvider()
->index();
}
public function update($path) {
$this
->invalidateResourceCache($path);
return $this->subject
->update($path);
}
public function replace($path) {
$this
->invalidateResourceCache($path);
return $this->subject
->replace($path);
}
public function remove($path) {
$this
->invalidateResourceCache($path);
$this->subject
->remove($path);
}
protected function defaultCacheInfo() {
$plugin_definition = $this
->getPluginDefinition();
$cache_info = empty($plugin_definition['renderCache']) ? array() : $plugin_definition['renderCache'];
$cache_info += array(
'render' => variable_get('restful_render_cache', FALSE),
'class' => NULL,
'bin' => RenderCache::CACHE_BIN,
'expire' => CACHE_PERMANENT,
'simpleInvalidate' => TRUE,
'granularity' => DRUPAL_CACHE_PER_USER,
);
return $cache_info;
}
public function getResourceMachineName() {
return $this->subject
->getResourceMachineName();
}
public function getPluginDefinition() {
return $this->subject
->getPluginDefinition();
}
public function enable() {
$this->subject
->enable();
}
public function disable() {
$this->subject
->disable();
}
public function isEnabled() {
return $this->subject
->isEnabled();
}
public function hasSimpleInvalidation() {
$data_provider = $this
->getDataProvider();
$options = $data_provider
->getOptions();
$cache_info = $options['renderCache'];
return !empty($cache_info['simpleInvalidate']);
}
protected function invalidateResourceCache($id) {
$query = new \EntityFieldQuery();
$canonical_id = $this
->getDataProvider()
->canonicalPath($id);
$query
->entityCondition('entity_type', 'cache_fragment')
->propertyCondition('type', 'resource')
->propertyCondition('value', $this::serializeKeyValue($this
->getResourceName(), $canonical_id));
foreach (CacheFragmentController::lookUpHashes($query) as $hash) {
$this
->getCacheController()
->clear($hash);
}
}
public static function serializeKeyValue($key, $value) {
return sprintf('%s%s%s', $key, static::CACHE_PAIR_SEPARATOR, $value);
}
}