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

Commit

Permalink
Merge pull request #38 from drupal-media/2247779-post-render-callback…
Browse files Browse the repository at this point in the history
…-service

Added an EntityEmbedPostRenderCache service class in response to https://drupal.org/project/2247779 committed to core.
  • Loading branch information
davereid committed Jun 14, 2014
2 parents cae1577 + 84f01a4 commit 64e4c39
Show file tree
Hide file tree
Showing 4 changed files with 218 additions and 81 deletions.
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;
}
}

0 comments on commit 64e4c39

Please sign in to comment.