You are here

Render.php in Bamboo Twig 8.2

File

bamboo_twig_loader/src/TwigExtension/Render.php
View source
<?php

namespace Drupal\bamboo_twig_loader\TwigExtension;

use Drupal\bamboo_twig\TwigExtension\TwigExtensionBase;
use Drupal\Core\Block\TitleBlockPluginInterface;
use Symfony\Cmf\Component\Routing\RouteObjectInterface;

/**
 * Provides some renderer as Twig Extensions.
 */
class Render extends TwigExtensionBase {

  /**
   * List of all Twig functions.
   */
  public function getFunctions() {
    return [
      new \Twig_SimpleFunction('bamboo_render_block', [
        $this,
        'renderBlock',
      ], [
        'is_safe' => [
          'html',
        ],
      ]),
      new \Twig_SimpleFunction('bamboo_render_form', [
        $this,
        'renderForm',
      ], [
        'is_safe' => [
          'html',
        ],
      ]),
      new \Twig_SimpleFunction('bamboo_render_entity', [
        $this,
        'renderEntity',
      ], [
        'is_safe' => [
          'html',
        ],
      ]),
      new \Twig_SimpleFunction('bamboo_render_region', [
        $this,
        'renderRegion',
      ], [
        'is_safe' => [
          'html',
        ],
      ]),
      new \Twig_SimpleFunction('bamboo_render_field', [
        $this,
        'renderField',
      ], [
        'is_safe' => [
          'html',
        ],
      ]),
      new \Twig_SimpleFunction('bamboo_render_image', [
        $this,
        'renderImage',
      ], [
        'is_safe' => [
          'html',
        ],
      ]),
      new \Twig_SimpleFunction('bamboo_render_image_style', [
        $this,
        'renderImageStyle',
      ], [
        'is_safe' => [
          'html',
        ],
      ]),
      new \Twig_SimpleFunction('bamboo_render_menu', [
        $this,
        'renderMenu',
      ], [
        'is_safe' => [
          'html',
        ],
      ]),
    ];
  }

  /**
   * Unique identifier for this Twig extension.
   */
  public function getName() {
    return 'bamboo_twig_loader.twig.render';
  }

  /**
   * Load a given block with or whitout parameters.
   *
   * @param string $block_id
   *   The ID of the block to render.
   * @param array $params
   *   (optional) An array of parameters passed to the block.
   *
   * @return null|array
   *   A render array for the block or NULL if the block does not exist.
   */
  public function renderBlock($block_id, array $params = []) {
    $instance = $this
      ->getPluginManagerBlock()
      ->createInstance($block_id, $params);
    return $instance
      ->build($params);
  }

  /**
   * Load a given form with or whitout parameters.
   *
   * @param string $module
   *   The module name where the form below.
   * @param string $form
   *   The form class name.
   * @param array $params
   *   (optional) An array of parameters passed to the form.
   *
   * @return null|array
   *   A render array for the form or NULL if the form does not exist.
   */
  public function renderForm($module, $form, array $params = []) {
    return $this
      ->getFormBuilder()
      ->getForm('Drupal\\' . $module . '\\Form\\' . $form, $params);
  }

  /**
   * Returns the render array for an entity.
   *
   * @param string $entity_type
   *   The entity type.
   * @param mixed $id
   *   (optional) The ID of the entity to render.
   * @param string $view_mode
   *   (optional) The view mode that should be used to render the entity.
   * @param string $langcode
   *   (optional) For which language the entity should be rendered, defaults to
   *   the current content language.
   *
   * @return null|array
   *   A render array for the entity or NULL if the entity does not exist.
   */
  public function renderEntity($entity_type, $id = NULL, $view_mode = NULL, $langcode = NULL) {

    // Lazy load the entity type manager only when needed.
    $entityTypeManager = $this
      ->getEntityTypeManager();
    $entity = $id ? $entityTypeManager
      ->getStorage($entity_type)
      ->load($id) : $this
      ->getCurrentRouteMatch()
      ->getParameter($entity_type);
    if ($entity) {
      $render_controller = $entityTypeManager
        ->getViewBuilder($entity_type);
      return $render_controller
        ->view($entity, $view_mode, $langcode);
    }
    return NULL;
  }

  /**
   * Returns the render array for an image style.
   *
   * @param int $id
   *   The image File ID of the entity to render.
   * @param string $style
   *   The image style.
   *
   * @return string
   *   A render array for the image style or NULL if the image does not exist.
   */
  public function renderImage($id, $style) {
    $file = $this
      ->getFileStorage()
      ->load($id);

    // Check the entity exist.
    if ($file) {
      return [
        '#theme' => 'image_style',
        '#style_name' => $style,
        '#uri' => $file
          ->getFileUri(),
      ];
    }
    return NULL;
  }

  /**
   * Returns the URL of this image derivative for an original image path or URI.
   *
   * @param string $path
   *   The path or URI to the original image.
   * @param string $style
   *   The image style.
   * @param bool $preprocess
   *   Bypass the standard Drupal process to pre-generate the image style.
   *
   * @return string|null
   *   The absolute URL where a style image can be downloaded, suitable for use
   *   in an <img> tag.
   *   Requesting the URL will cause the image to be created. Exceptend when
   *   preprocess is enabled, the image will already be available on the fso.
   */
  public function renderImageStyle($path, $style, $preprocess = FALSE) {
    $image_style = $this
      ->getImageStyleStorage()
      ->load($style);

    // Assert the requested style exist, otherwise return null.
    if (!$image_style) {
      return NULL;
    }

    // From an uri or path retrieve an image object.
    $image = $this
      ->getImageFactory()
      ->get($path);

    // Assert the image exist, otherwise return null.
    if (empty($image)) {
      return NULL;
    }

    // Lazy load the fso.
    $fso = $this
      ->getFileSystemObject();

    // Assert the image exist on the file system.
    $image_path = $fso
      ->realpath($image
      ->getSource());
    if (!is_file($image_path)) {
      return NULL;
    }

    // When user want to preprocess the derivated instead of waiting first
    // HTTP call.
    if ($preprocess) {
      $image_style_uri = $image_style
        ->buildUri($path);

      // Assert the image style doesn't already exist.
      $image_style_path = $fso
        ->realpath($image_style_uri);
      if (!is_file($image_style_path)) {

        // createDerivative need an URI so transform none uri.
        if (file_valid_uri($path)) {
          $image_uri = $path;
        }
        else {
          $image_uri = file_build_uri($path);
        }

        // Create the new image derivative.
        $image_style
          ->createDerivative($image_uri, $image_style_uri);
        return file_create_url($image_style_uri);
      }
    }
    return $image_style
      ->buildUrl($path);
  }

  /**
   * Builds the render array of a given region.
   *
   * @param string $region
   *   The region to build.
   * @param string $theme
   *   (optional) The name of the theme to load the region. If it is not
   *   provided then default theme will be used.
   *
   * @return array
   *   A render array to display the region content.
   */
  public function renderRegion($region, $theme = NULL) {
    $blocks = $this
      ->getBlockStorage()
      ->loadByProperties([
      'region' => $region,
      'theme' => $theme ?: $this
        ->getConfigFactory()
        ->get('system.theme')
        ->get('default'),
    ]);
    $view_builder = $this
      ->getEntityTypeManager()
      ->getViewBuilder('block');
    $build = [];

    /* @var $blocks \Drupal\block\BlockInterface[] */
    foreach ($blocks as $id => $block) {
      $block_plugin = $block
        ->getPlugin();
      if ($block_plugin instanceof TitleBlockPluginInterface) {
        $request = $this->requestStack
          ->getCurrentRequest();
        if ($route = $request->attributes
          ->get(RouteObjectInterface::ROUTE_OBJECT)) {
          $block_plugin
            ->setTitle($this->titleResolver
            ->getTitle($request, $route));
        }
      }
      $build[$id] = $view_builder
        ->view($block);
    }
    return $build;
  }

  /**
   * Returns the render array for a single entity field.
   *
   * @param string $field_name
   *   The field name.
   * @param string $entity_type
   *   The entity type.
   * @param mixed $id
   *   (optional) The ID of the entity to render.
   * @param string $langcode
   *   (optional) Language code to load translation.
   * @param string $formatter
   *   (optional) The formatter that should be used to render the field.
   *   Eg. 'text' for textfield or 'url' for linkfield.
   *
   * @return null|array
   *   A render array for the field or NULL if the value does not exist.
   */
  public function renderField($field_name, $entity_type, $id = NULL, $langcode = NULL, $formatter = NULL) {
    $entity = $id ? $this
      ->getEntityTypeManager()
      ->getStorage($entity_type)
      ->load($id) : $this
      ->getCurrentRouteMatch()
      ->getParameter($entity_type);

    // Ensure the entity has the requested field.
    if (!$entity
      ->hasField($field_name)) {
      return NULL;
    }

    // Do not continue if the field is empty.
    if ($entity
      ->get($field_name)
      ->isEmpty()) {
      return NULL;
    }
    if ($langcode && $entity
      ->hasTranslation($langcode)) {
      $entity = $entity
        ->getTranslation($langcode);
    }
    $display_options = [
      'label' => 'hidden',
    ];
    if (!is_null($formatter)) {
      $display_options['type'] = $formatter;
    }
    else {

      // We don't have the formatter view display and should fallback on
      // the default formatter.
      $field_type_definition = $this
        ->getFieldTypeManager()
        ->getDefinition($entity
        ->getFieldDefinition($field_name)
        ->getType());
      $display_options['type'] = $field_type_definition['default_formatter'];
    }
    return $entity
      ->get($field_name)
      ->view($display_options);
  }

  /**
   * Returns the render array for Drupal menu.
   *
   * @param string $menu_name
   *   The name of the menu.
   * @param int $level
   *   (optional) Initial menu level.
   * @param int $depth
   *   (optional) Maximum number of menu levels to display.
   *
   * @return array
   *   A render array for the menu.
   */
  public function renderMenu($menu_name, $level = 1, $depth = 0) {

    // Lazy load the entity type manager only when needed.
    $menuLinkTree = $this
      ->getMenuLinkTree();
    $parameters = $menuLinkTree
      ->getCurrentRouteMenuTreeParameters($menu_name);

    // Adjust the menu tree parameters based on the block's configuration.
    $parameters
      ->setMinDepth($level);

    // When the depth is configured to zero, there is no depth limit. When depth
    // is non-zero, it indicates the number of levels that must be displayed.
    // Hence this is a relative depth that we must convert to an actual
    // (absolute) depth, that may never exceed the maximum depth.
    if ($depth > 0) {
      $parameters
        ->setMaxDepth(min($level + $depth - 1, $menuLinkTree
        ->maxDepth()));
    }
    $parameters
      ->onlyEnabledLinks();
    $parameters->expandedParents = [];
    $tree = $menuLinkTree
      ->load($menu_name, $parameters);
    $manipulators = [
      [
        'callable' => 'menu.default_tree_manipulators:checkAccess',
      ],
      [
        'callable' => 'menu.default_tree_manipulators:generateIndexAndSort',
      ],
    ];
    $tree = $menuLinkTree
      ->transform($tree, $manipulators);
    return $menuLinkTree
      ->build($tree);
  }

}

Classes

Namesort descending Description
Render Provides some renderer as Twig Extensions.