mustache_templates-8.x-1.0-beta4/modules/mustache_magic/src/Plugin/mustache/Magic/Javascript.php

modules/mustache_magic/src/Plugin/mustache/Magic/Javascript.php
<?php

namespace Drupal\mustache_magic\Plugin\mustache\Magic;

use Drupal\Component\Utility\Html;
use Drupal\Core\Render\BubbleableMetadata;
use Drupal\Core\Render\RenderContext;
use Drupal\mustache\Helpers\MustacheRenderTemplate;
use Drupal\mustache\Render\Markup;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Write aggregateable Javascript.
 *
 * Usage:
 *
 * Use the {{#js.<name>}} section variable to define an aggregateable JS block.
 * You can refer to this aggregated asset using {{><name>.js}}.
 * The code will be automatically wrapped by a closure, to prevent naming
 * collisions with other global variables.
 *
 * Available variables:
 * - "sync": The global mustacheSync object that holds registered
 *   synchronization items, data providers and templates.
 * - "Drupal": The global Drupal object.
 * - "settings": The global drupalSettings object.
 *
 * @code
 *  {{#js.myalert}}alert('Hello!');{{/js.myalert}}
 *  // You may reuse this asset like this:
 * {{>myalert.js}}
 * @endcode
 *
 * @MustacheMagic(
 *   id = "js",
 *   label = @Translation("JS (Javascript)"),
 *   description = @Translation("Use the {{#js.<b>&lt;name&gt;</b>}} section variable to define an aggregateable JS block. You can refer to this aggregated asset using {{&gt;<b>&lt;name&gt;</b>.js}}. The code will be automatically wrapped by a closure, to prevent naming collisions with other global variables. Available variables:<ul><li><b>sync</b>: The global mustacheSync object that holds registered synchronization items, data providers and templates.</li><li><b>Drupal</b>: The global Drupal object.</li><li><b>settings</b>: The global drupalSettings object.</li></ul>Example:<p>{{#js.myalert}}alert('Hello!');{{/js.myalert}}<br/>// You may reuse this asset like this:<br/>{{&gt;myalert.js}}</p>")
 * )
 */
class Javascript extends Template {

  /**
   * The asset type extension.
   *
   * @var string
   */
  public static $assetType = 'js';

  /**
   * A list of keywords to exclude as possible name.
   *
   * @var array
   */
  public static $excludes = ['id', 'name', 'content', 'js', 'css', 'asset'];

  /**
   * The renderer.
   *
   * @var \Drupal\Core\Render\RendererInterface
   */
  protected $renderer;

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    $instance = parent::create($container, $configuration, $plugin_id, $plugin_definition);
    $instance->renderer = $container->get('renderer');
    return $instance;
  }

  /**
   * {@inheritdoc}
   */
  public function __isset($name): bool {
    return !is_null($name) && is_scalar($name) && (trim((string) $name) !== '') && !in_array($name, static::$excludes);
  }

  /**
   * {@inheritdoc}
   */
  public function __invoke($template_content = NULL, $render = NULL) {
    if (!isset($template_content, $render)) {
      return;
    }

    if (!isset($this->templateName)) {
      return $render($template_content);
    }

    $renderer = $this->renderer;
    $bubbleable_metadata = BubbleableMetadata::createFromRenderArray($this->element);
    $template_name = $this->templateName ?? hash('md4', $template_content);
    $template_name .= '.' . static::$assetType;

    // Use the magic JS template as a wrapper to embed the user-defined script.
    $build = MustacheRenderTemplate::build('mustache_magic_' . static::$assetType);
    $build->usingData($this->templateData($template_name, $template_content));
    $build_render_array = &$build->toRenderArray();
    $template_content = (string) $renderer->executeInRenderContext(new RenderContext(), function () use ($renderer, &$build_render_array) {
      return $renderer->render($build_render_array);
    });
    $bubbleable_metadata
      ->addCacheableDependency(BubbleableMetadata::createFromRenderArray($build_render_array))
      ->applyTo($this->element);
    unset($build_render_array);

    // Now that we have wrapped the script, register it as template.
    $this->templateStorage->registerTemplate($template_name, $template_content);

    // Load the user-defined script as sync item.
    $build = MustacheRenderTemplate::build($template_name);
    $build->withPlaceholder(['#markup' => ''])
      ->usingData([static::$assetType => TRUE])
      ->exposeData(TRUE)
      ->withClientSynchronization()
      ->executesInnerScripts(TRUE)
      ->once();
    $build_render_array = &$build->toRenderArray();
    $build_render_array['#sync']['wrapper_tag'] = NULL;
    $sync_item = $renderer->executeInRenderContext(new RenderContext(), function () use ($renderer, &$build_render_array) {
      return $renderer->render($build_render_array);
    });
    $bubbleable_metadata
      ->addCacheableDependency(BubbleableMetadata::createFromRenderArray($build_render_array))
      ->applyTo($this->element);

    // We need to replace the opening curly brackets, so that Mustache.php's
    // lambda helper cannot chime in and would try to replace Mustache
    // variables within the inline template with current context values.
    return Markup::create(str_replace('{{', '\{\{', (string) $sync_item));
  }

  /**
   * Builds up the array that is passed as data to the magic wrapper template.
   *
   * @param string $name
   *   The template name.
   * @param string $content
   *   The template content.
   */
  protected function templateData($name, $content) {
    return [
      'id' => Html::getUniqueId($name),
      'name' => $name,
      'content' => $content,
    ];
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc