bee_hotel-1.x-dev/src/Controller/GuestMessages.php

src/Controller/GuestMessages.php
<?php

namespace Drupal\bee_hotel\Controller;

use Drupal\bee_hotel\BeeHotelGuestMessageTokens;
use Drupal\beehotel_utils\BeeHotelCommerce;
use Drupal\Component\Utility\UrlHelper;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\Core\Link;
use Drupal\Core\Render\Markup;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\Url;
use Drupal\node\Entity\Node;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Provides route responses for BeeHotel module.
 */
class GuestMessages extends ControllerBase {

  use StringTranslationTrait;

  /**
   * The Guest Message tokens object.
   *
   * @var \Drupal\bee_hotel\BeeHotelGuestMessageTokens
   */
  protected $guestMessageTokens;

  /**
   * The language manager service.
   *
   * @var \Drupal\Core\Language\LanguageManagerInterface
   */
  protected $languageManager;

  /**
   * The BeeHotel commerce Util.
   *
   * @var \Drupal\beehotel_utils\BeeHotelCommerce
   */
  protected $beehotelCommerce;

  /**
   * Constructs a new GuestMessages object.
   *
   * @param \Drupal\bee_hotel\BeeHotelGuestMessageTokens $guest_message_tokens
   *   The tokens object.
   * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
   *   The language manager.
   * @param \Drupal\beehotel_utils\BeeHotelCommerce $beehotel_commerce
   *   BeeHotel Commerce Utils.
   */
  public function __construct(BeeHotelGuestMessageTokens $guest_message_tokens, LanguageManagerInterface $language_manager, BeeHotelCommerce $beehotel_commerce) {
    $this->guestMessageTokens = $guest_message_tokens;
    $this->languageManager = $language_manager;
    $this->beehotelCommerce = $beehotel_commerce;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('beehotel.guest_message_tokens'),
      $container->get('language_manager'),
      $container->get('beehotel_utils.beehotelcommerce')
    );
  }

  /**
   * Produces search result.
   *
   * @param object $commerce_order
   *   The commerce order object.
   * @param string $type
   *   The message type.
   *
   * @return array
   *   Render array for the result.
   */
  public function result($commerce_order, $type) {
    $tmp = [];
    $data = [];
    $data['language'] = \Drupal::languageManager()->getCurrentLanguage()->getId();
    $data['language_switcher'] = $this->customLanguageSwitcher();
    $data['commerce_order'] = $commerce_order;

    $data['guest'] = $this->beehotelCommerce->getGuestInfoFromReservatation($data['commerce_order']);

    $query = \Drupal::entityQuery('node')
      ->accessCheck(TRUE)
      ->condition('status', 1)
      ->condition('type', 'guest_message')
      ->sort('changed', 'DESC');
    $data['nids'] = $query->execute();

    foreach ($data['nids'] as $nid) {
      $data['node'] = Node::load($nid);
      $data['message'] = $data['node'];

      if ($data['node']->hasTranslation($data['language'])) {
        $data['message'] = $data['node']->getTranslation($data['language']);
      }

      $data['attachments'] = $this->getAttachments($data['message']);
      $data['links'] = $this->getLinks($data['message']);
      $tmp['message'] = $this->messageFormat(
        $data['message']->get('field_message')->value,
        [
          'commerce_order' => $data['commerce_order'],
          'node_title' => $data['message']->get("title")->value,
          'node_nid' => $data['message']->id(),
          'attachments' => $data['attachments']['string'],
          'links' => $data['links'],
          'guest' => $data['guest'],
        ]
      );
      $data['items'][] = $tmp['message'];
    }

    $data['prefix'] = \Drupal::service('renderer')->render($data['language_switcher']);
    $data['prefix'] .= "<div id='tokens-list'>";
    $data['prefix'] .= "</div>";

    return [
      '#theme' => 'item_list',
      '#list_type' => 'ul',
      '#items' => $data['items'],
      '#attributes' => ['id' => 'guest-messages'],
      '#wrapper_attributes' => ['class' => 'container'],
      '#prefix' => Markup::create($data['prefix']),
      '#suffix' => Markup::create("<a href='/node/add/guest_message'>" . $this->t("Add a message") . "</a>"),
    ];
  }

  /**
   * Apply available tokens.
   *
   * @param string $value
   *   The string value to process.
   * @param object $commerce_order
   *   The commerce order object.
   *
   * @return string|null
   *   The processed string with tokens replaced.
   */
  private function applyTokens($value, $commerce_order) {
    $data = [];
    $data['commerce_order'] = $commerce_order;
    $data['value'] = $value;
    $data['setting']['token_prefix'] = "[";
    $data['setting']['token_suffix'] = "]";
    $data['tokens'] = $this->guestMessageTokens->get($commerce_order);

    if (!isset($data['value'])) {
      return NULL;
    }

    // Replace string with token.
    foreach ($data['tokens'] as $k => $v) {
      if (isset($k) && isset($v)) {
        if (isset($v['value'])) {
          $data['value'] = str_replace(
            $data['setting']['token_prefix'] . $k . $data['setting']['token_suffix'],
            "<span class='token'>" . $v['value'] . "</span>",
            $data['value']
          );
        }
      }
    }
    return $data['value'];
  }

  /**
   * Format message output.
   *
   * @param string $value
   *   The message value.
   * @param array $options
   *   Formatting options.
   *
   * @return \Drupal\Component\Render\MarkupInterface|string|null
   *   Formatted message markup.
   */
  private function messageFormat($value, array $options) {
    $data = [];

    $data['value'] = $value;
    $data['options'] = $options;

    if (!isset($data['value'])) {
      return NULL;
    }

    // A). replace tokens.
    $data['value'] = $this->applyTokens($data['value'], $data['options']['commerce_order']);

    // B). add line break BR.
    $data['value'] = str_replace(["\r\n'", "\n\r", "\n", "\r"], "<br/>", $data['value']);

    // C). Add title + edit link.
    $url = Url::fromRoute('entity.node.edit_form', ['node' => $data['options']['node_nid']]);
    $link_options = [
      'attributes' => [
        'class' => [
          'message-edit',
        ],
      ],
    ];
    $url->setOptions($link_options);
    $link = Link::fromTextAndUrl('edit', $url);
    $data['build'] = ['link' => $link->toRenderable()];
    $data['edit_link'] = \Drupal::service('renderer')->render($data['build']);

    // D) Send mail link.
    $url = Url::fromRoute('beehotel.guest_messages.mail.preview', [
      'node' => $data['options']['node_nid'],
      'commerce_order' => $data['options']['commerce_order']->id(),
    ]);
    $link_options = [
      'attributes' => [
        'class' => [
          'mail-preview',
        ],
      ],
    ];

    $url->setOptions($link_options);
    $link = Link::fromTextAndUrl('mail: ' . $data['options']['commerce_order']->get('mail')->value . "]", $url);
    $data['build'] = ['link' => $link->toRenderable()];
    $data['mail_link'] = \Drupal::service('renderer')->render($data['build']);

    $data['copy_to_clipboard'] = "<a href='#' data-id='" . $data['options']['node_nid'];
    $data['copy_to_clipboard'] .= "' class='message-copier' ";
    $data['copy_to_clipboard'] .= "id='message-copier-" . $data['options']['node_nid'] . "'>" . $this->t("copy") . "</a>";

    // W) Add link for whatsapp.
    if (isset($data['options']['guest']['field_telephone'])) {
      $data['whatsapp_message'] = UrlHelper::encodePath($data['value']);
      $data['whatsapp_link'] = $this->generateWhatsAppLink($data['options']['guest']['field_telephone'], $data['value']);
    }

    $data['tmp'] = "<h4>" . $data['options']['node_title'] . "<span style='font-size:0.6em'>";

    $data['tmp'] .= "<ul class='actions'>";
    $data['tmp'] .= "<li>" . $data['mail_link'];
    $data['tmp'] .= "<li>" . $data['edit_link'];
    $data['tmp'] .= "<li>" . $data['copy_to_clipboard'];
    if (isset($data['whatsapp_link'])) {
      $data['tmp'] .= "<li>" . \Drupal::service('renderer')->render($data['whatsapp_link']);
    }
    $data['tmp'] .= "</ul>";
    $data['tmp'] .= "</span></h4>";
    $data['tmp'] .= "<div class='message' id='message-" . $data['options']['node_nid'] . "'>";

    $data['tmp'] .= $data['value'] . "</div>";

    $data['value'] = $data['tmp'];

    $data['footer'] = "<div>";
    if (isset($data['options']['attachments'])) {
      $data['footer'] .= "<div class='attachments'> Attachments: " .
        $data['options']['attachments'] .
        "</div>";
    }
    if (isset($data['options']['links'])) {
      $data['footer'] .= "<div class='links'> Links: " . $data['options']['links'] . "</div>";
    }
    $data['footer'] .= "</div>";
    $data['value'] = Markup::create($data['value'] . $data['footer']);
    return $data['value'];
  }

  /**
   * Generates a WhatsApp share link render array for Drupal.
   *
   * This function creates a properly formatted WhatsApp link that opens
   * in a new window with security attributes. The phone number is cleaned
   * and the message text is URL encoded for proper WhatsApp API usage.
   *
   * @param string $phone
   *   The phone number in any format (will be cleaned to digits only).
   *   Example: "+1 (555) 123-4567" or "15551234567".
   * @param string $text
   *   (Optional) Pre-filled message for WhatsApp. Default empty string.
   *
   * @return array
   *   A Drupal render array for a link element with the following properties:
   *   - Opens WhatsApp chat in new tab
   *   - Includes Font Awesome WhatsApp icon
   *   - Has security attributes (noopener, noreferrer)
   *   - Applies CSS class for styling
   */
  private function generateWhatsAppLink($phone, $text = '') {
    // Clean phone number (remove non-numeric characters).
    $cleaned_phone = preg_replace('/[^0-9]/', '', $phone);

    $encoded_text = UrlHelper::encodePath($text);

    return [
      '#type' => 'link',
      '#title' => [
        '#markup' => '<i class="fab fa-whatsapp"></i> WhatsApp',
      ],
      '#url' => Url::fromUri("https://wa.me/+{$cleaned_phone}?text={$encoded_text}"),
      '#attributes' => [
        'target' => '_blank',
        'rel' => 'noopener noreferrer',
        'class' => ['whatsapp-link'],
      ],
    ];
  }

  /**
   * Get attachments for a given guest_message.
   *
   * @param \Drupal\node\Entity\Node $node
   *   The node entity.
   *
   * @return array
   *   Array of attachment data.
   *
   * @todo themed output.
   */
  private function getAttachments(Node $node) {
    $data = [];
    $data['referenced_entities'] = $node->get('field_attachments')->referencedEntities();
    $data['attachments']['string'] = "";
    foreach ($data['referenced_entities'] as $entity) {
      $tmp = $entity->get("uri")->url;
      $tmp = explode("/", $tmp);
      $end = end($tmp);
      $data['attachments']['array'][] = [
        'url' => $entity->get("uri")->url,
        'label' => $end,
      ];
      $data['attachments']['string'] .= "<a href='" . $entity->get("uri")->url . "'>" . $end . "</a> | ";
    }
    return $data['attachments'];
  }

  /**
   * Get links for a given guest_message.
   *
   * @param \Drupal\node\Entity\Node $node
   *   The node entity.
   *
   * @return string
   *   HTML string of links.
   */
  private function getLinks(Node $node) {
    $data = [];
    $data['referenced_entities'] = $node->get('field_links');
    $data['links']['items'] = [];
    foreach ($node->field_links as $item) {
      $data['links']['items'][] = "<a href='" . $item->uri . "'>" . $item->uri . "</a>";
    }
    $data['links']['string'] = implode("|", $data['links']['items']);
    return $data['links']['string'];
  }

  /**
   * Custom language switcher.
   *
   * @return array
   *   Render array for language switcher.
   */
  public function customLanguageSwitcher() {
    $languages = $this->languageManager->getLanguages();
    $current_language = $this->languageManager->getCurrentLanguage();
    $links = [];

    foreach ($languages as $language) {
      $links[] = [
        'title' => $language->getName(),
        'url' => Url::fromRoute('<current>', [], ['language' => $language]),
        'language' => $language,
        'attributes' => [
          'class' => ['language-link', 'language-link-' . $language->getId()],
        ],
      ];
    }

    return [
      '#theme' => 'links__language_switcher',
      '#links' => $links,
      '#attributes' => [
        'class' => ['language-switcher'],
      ],
      '#set_active_class' => TRUE,
    ];
  }

}

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

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