Skip to content
This repository has been archived by the owner on Jan 5, 2018. It is now read-only.

Adds EntityEmbedPostRenderCache service class. #38

Merged
merged 5 commits into from Jun 14, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions entity_embed.services.yml
Expand Up @@ -2,3 +2,6 @@ services:
plugin.manager.entity_embed.display:
class: Drupal\entity_embed\EntityEmbedDisplay\EntityEmbedDisplayManager
arguments: ['@container.namespaces', '@cache.discovery', '@module_handler']
entity_embed.post_render_cache:
class: Drupal\entity_embed\EntityEmbedPostRenderCache
arguments: ['@entity.manager', '@module_handler', '@plugin.manager.entity_embed.display']
90 changes: 90 additions & 0 deletions src/EntityEmbedPostRenderCache.php
@@ -0,0 +1,90 @@
<?php

/**
* @file Contains Drupal\entity_embed\EntityEmbedPostRenderCache.
*/

namespace Drupal\entity_embed;

use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\entity_embed\EntityEmbedDisplay\EntityEmbedDisplayManager;

/**
* Defines a service for embedded entity post render cache callbacks.
*/
class EntityEmbedPostRenderCache {
use EntityHelperTrait;

/**
* Constructs a EntityEmbedPostRenderCache object.
*
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
* The entity manager service.
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
* The Module Handler.
* @param \Drupal\entity_embed\EntityEmbedDisplay\EntityEmbedDisplayManager $plugin_manager
* The Module Handler.
*/
public function __construct(EntityManagerInterface $entity_manager, ModuleHandlerInterface $module_handler, EntityEmbedDisplayManager $plugin_manager) {
$this->setEntityManager($entity_manager);
$this->setModuleHandler($module_handler);
$this->setDisplayPluginManager($plugin_manager);
}

/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('entity.manager'),
$container->get('module_handler'),
$container->get('plugin.manager.entity_embed.display')
);
}

/**
* #post_render_cache callback; renders an embedded entity.
*
* Replaces the #post_render_cache placeholder with an embedded entity.
*
* @param array $element
* The renderable array that contains the to be replaced placeholder.
* @param array $context
* An array with the following keys:
* - entity-type: The entity type.
* - entity-id: The entity ID.
* - token: The placeholder token generated in buildPlaceholder().
*
* @return array
* A renderable array representing the placeholder replaced with the
* rendered entity.
*/
public function renderEmbed(array $element, array $context) {
$callback = 'entity_embed.post_render_cache:renderEmbed';
$placeholder = drupal_render_cache_generate_placeholder($callback, $context);

// Do not bother rendering the entity if the placeholder cannot be found.
if (strpos($element['#markup'], $placeholder) === FALSE) {
return $element;
}

$entity_output = '';
try {
if ($entity = $this->loadEntity($context['entity-type'], $context['entity-id'])) {
$entity_output = $this->renderEntityEmbedDisplayPlugin(
$entity,
$context['entity-embed-display'],
$context['entity-embed-settings'],
$context
);
}
}
catch (\Exception $e) {
watchdog_exception('entity_embed', $e);
}

$element['#markup'] = str_replace($placeholder, $entity_output, $element['#markup']);
return $element;
}
}
126 changes: 122 additions & 4 deletions src/EntityHelperTrait.php
Expand Up @@ -10,7 +10,9 @@
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\Entity\EntityStorageException;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\entity_embed\EntityEmbedDisplay\EntityEmbedDisplayManager;

/**
* Wrapper methods for entity loading and rendering.
Expand All @@ -29,6 +31,20 @@ trait EntityHelperTrait {
*/
protected $entityManager;

/**
* The module handler service.
*
* @var \Drupal\Core\Extension\ModuleHandlerInterface.
*/
protected $moduleHandler;

/**
* The display plugin manager.
*
* @var \Drupal\entity_embed\EntityEmbedDisplay\EntityEmbedDisplayManager.
*/
protected $displayPluginManager;

/**
* Loads an entity from the database.
*
Expand Down Expand Up @@ -112,6 +128,56 @@ protected function renderEntity(EntityInterface $entity, $view_mode, $langcode =
return $render_controller->view($entity, $view_mode, $langcode);
}

/**
* Renders an entity using an EntityEmbedDisplay plugin.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity to be rendered.
* @param string $plugin_id
* The EntityEmbedDisplay plugin ID.
* @param array $plugin_configuration
* (optional) Array of plugin configuration values.
* @param array $context
* (optional) Array of additional context values, usually the embed HTML
* tag's attributes.
*
* @return string
* The HTML of the entity rendered with the display plugin.
*
* @throws \Drupal\entity_embed\RecursiveRenderingException;
*/
protected function renderEntityEmbedDisplayPlugin(EntityInterface $entity, $plugin_id, array $plugin_configuration = array(), array $context = array()) {
// Protect ourselves from recursive rendering.
static $depth = 0;
$depth++;
if ($depth > 20) {
throw new RecursiveRenderingException(format_string('Recursive rendering detected when rendering entity @entity_type(@entity_id). Aborting rendering.', array('@entity_type' => $entity->getEntityTypeId(), '@entity_id' => $entity->id())));
}

// Allow modules to alter the entity prior to display rendering.
$this->moduleHandler()->invokeAll('entity_preembed', array($entity, $context));

// Build the display plugin.
$display = $this->displayPluginManager()->createInstance($plugin_id, $plugin_configuration);
$display->setContextValue('entity', $entity);
$display->setAttributes($context);

// Check if the display plugin is accessible. This also checks entity
// access, which is why we never call $entity->access() here.
if (!$display->access()) {
return '';
}

// Build and render the display plugin, allowing modules to alter the
// result before rendering.
$build = $display->build();
$this->moduleHandler()->alter('entity_embed', $build, $display);
$entity_output = drupal_render($build);

$depth--;
return $entity_output;
}

/**
* Check access to an entity.
*
Expand All @@ -126,7 +192,7 @@ protected function renderEntity(EntityInterface $entity, $view_mode, $langcode =
* @return bool|null
* self::ALLOW, self::DENY, or self::KILL.
*/
protected function accessEntity(EntityInterface $entity, $operation = 'view', AccountInterface $account = NULL) {
protected function accessEntity(EntityInterface $entity, $op = 'view', AccountInterface $account = NULL) {
switch ($entity->getEntityTypeId()) {
case 'file':
// Due to issues with access checking with file entities in core,
Expand All @@ -142,7 +208,7 @@ protected function accessEntity(EntityInterface $entity, $operation = 'view', Ac

case 'private':
case 'temporary':
$headers = \Drupal::moduleHandler()->invokeAll('file_download', array($uri));
$headers = $this->moduleHandler()->invokeAll('file_download', array($uri));
foreach ($headers as $result) {
if ($result == -1) {
return FALSE;
Expand All @@ -156,7 +222,7 @@ protected function accessEntity(EntityInterface $entity, $operation = 'view', Ac
}

default:
return $entity->access('view', $account);
return $entity->access($op, $account);
}
}

Expand All @@ -168,7 +234,7 @@ protected function accessEntity(EntityInterface $entity, $operation = 'view', Ac
*/
protected function entityManager() {
if (!isset($this->entityManager)) {
$this->entityManager = \Drupal::service('entity.manager');
$this->entityManager = \Drupal::entityManager();
}
return $this->entityManager;
}
Expand All @@ -185,4 +251,56 @@ public function setEntityManager(EntityManagerInterface $entityManager) {
$this->entityManager = $entityManager;
return $this;
}

/**
* Returns the module handler.
*
* @return \Drupal\Core\Extension\ModuleHandlerInterface
* The module handler.
*/
protected function moduleHandler() {
if (!isset($this->moduleHandler)) {
$this->moduleHandler = \Drupal::moduleHandler();
}
return $this->moduleHandler;
}

/**
* Sets the module handler service.
*
* @param \Drupal\Core\Extension\ModuleHandlerInterface $moduleHandler
* The module handler service.
*
* @return self
*/
public function setModuleHandler(ModuleHandlerInterface $moduleHandler) {
$this->moduleHandler = $moduleHandler;
return $this;
}

/**
* Returns the display plugin manager.
*
* @return \Drupal\entity_embed\EntityEmbedDisplay\EntityEmbedDisplayManager
* The display plugin manager.
*/
protected function displayPluginManager() {
if (!isset($this->displayPluginManager)) {
$this->displayPluginManager = \Drupal::service('plugin.manager.entity_embed.display');
}
return $this->displayPluginManager;
}

/**
* Sets the display plugin manager service.
*
* @param \Drupal\entity_embed\EntityEmbedDisplay\EntityEmbedDisplayManager $displayPluginManager
* The display plugin manager service.
*
* @return self
*/
public function setDisplayPluginManager(EntityEmbedDisplayManager $displayPluginManager) {
$this->displayPluginManager = $displayPluginManager;
return $this;
}
}