ispim-1.0.x-dev/ispim.module

ispim.module
<?php

/**
 * @file
 * ISPIM related functions.
 */

declare(strict_types=1);

use Drupal\Component\Utility\Html;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element;
use Drupal\file\FileInterface;
use Drupal\image\ImageStyleInterface;
use Drupal\ispim\Entity\IspimPreviewImageInterface;

/**
 * Implements hook_theme().
 *
 * @phpstan-param array<string, array<string, mixed>> $existing
 *
 * @phpstan-return array<string, array<string, mixed>>
 */
function ispim_theme(array $existing, string $type, string $theme, string $path): array {
  return [
    'ispim_preview_image' => [
      'render element' => 'elements',
      'template' => 'ispim.ispim-preview-image',
    ],
    'ispim_preview_image_selector' => [
      'template' => 'ispim-preview-image-selector',
      'variables' => [
        'previewImages' => [],
        'thumbnailImageStyleId' => NULL,
        'imageStyleIds' => [],
        // CSS selectors.
        'imageSelectors' => NULL,
      ],
    ],
  ];
}

/**
 * Implements hook_form_FORM_ID_alter().
 *
 * @phpstan-param array<string, mixed> $form
 */
function ispim_form_image_style_edit_form_alter(array &$form, FormStateInterface $formState): void {
  $container = \Drupal::getContainer();

  /** @var null|\Drupal\Core\Entity\EntityFormInterface $entityForm*/
  $entityForm = $formState->getBuildInfo()['callback_object'];
  $style = $entityForm?->getEntity();
  if (!($style instanceof ImageStyleInterface)) {
    return;
  }

  /* @noinspection PhpUnhandledExceptionInspection */
  $previewImageStorage = $container
    ->get('entity_type.manager')
    ->getStorage('ispim_preview_image');

  $previewImageIds = $previewImageStorage
    ->getQuery()
    ->accessCheck()
    ->condition('status', TRUE)
    ->sort('weight')
    ->execute();

  if (!$previewImageIds) {
    return;
  }

  /** @var \Drupal\ispim\Entity\IspimPreviewImageInterface[] $previewImages */
  $previewImages = $previewImageStorage->loadMultiple($previewImageIds);
  $imageSettings = $container->get('config.factory')->get('image.settings');

  $htmlId = Html::getUniqueId('ispim-preview-image');
  $form['ispim_preview_image'] = [
    '#type' => 'select',
    '#title' => t('Preview image'),
    '#default_value' => $imageSettings->get('preview_image'),
    '#options' => [],
    '#weight' => -999,
    '#id' => $htmlId,
    '#wrapper_attributes' => [
      'class' => [
        'container-inline',
      ],
    ],
    '#attributes' => [
      'class' => ['ispim-preview-image-selector'],
    ],
    '#attached' => [
      'library' => [
        'ispim/preview_image',
      ],
      'drupalSettings' => [
        'ispim' => [
          'previewImageSelectors' => [
            $htmlId => [
              'imageSelector' => '.image-style-preview .preview-image img',
            ],
          ],
        ],
      ],
    ],
  ];

  $fileUrlGenerator = $container->get('file_url_generator');
  $now = $container->get('datetime.time')->getRequestTime();
  $drupalSettings =& $form['ispim_preview_image']['#attached']['drupalSettings']['ispim'];
  /** @var \Drupal\image\ImageStyleInterface[] $styles */
  $styles = [$style];
  foreach ($previewImages as $previewImage) {
    $file = $previewImage->getImageFile();

    $form['ispim_preview_image']['#options'][$file->getFileUri()] = $previewImage->label();

    $drupalSettings['previewImages'][$file->getFileUri()]['original'] = $fileUrlGenerator->generateString($file->getFileUri());
    foreach ($styles as $style) {
      $url = $style->buildUrl($file->getFileUri());
      $url .= (str_contains($url, '?') ? '&' : '?') . "cache_bypass=$now";
      $drupalSettings['previewImages'][$file->getFileUri()]['imageStyles'][$style->id()] = $url;
    }
  }
}

/**
 * Implements hook_theme_suggestions_HOOK().
 *
 * @phpstan-param array<string, mixed> $variables
 *
 * @phpstan-return array<string>
 */
function ispim_theme_suggestions_ispim_preview_image(array $variables): array {
  $entityTypeId = $variables['elements']['#entity_type'];
  /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
  $entity = $variables['elements']["#{$entityTypeId}"];
  $view_mode = strtr($variables['elements']['#view_mode'], '.', '_');
  $bundle = $entity->bundle();
  $id = $entity->id();

  return [
    "{$entityTypeId}__{$view_mode}",
    "{$entityTypeId}__{$bundle}",
    "{$entityTypeId}__{$bundle}__{$view_mode}",
    "{$entityTypeId}__{$id}",
    "{$entityTypeId}__{$id}__{$view_mode}",
  ];
}

/**
 * Prepares variables for Ispim Preview Image templates.
 *
 * Default template: ispim_preview_image.html.twig.
 *
 * Most themes use their own copy of ispim_preview_image.html.twig. The default is located
 * inside "/.../ispim/templates/ispim.ispim_preview_image.html.twig".
 * Look in there for the full list of variables.
 *
 * @param array $variables
 *   An associative array containing:
 *   - elements: An array of elements to display in view mode.
 *   - ispim_preview_image: Ispim Preview Image object.
 *   - url: The Url object.
 *
 * @phpstan-param array<string, mixed> $variables
 *
 * @throws \Drupal\Core\Entity\EntityMalformedException
 */
function template_preprocess_ispim_preview_image(array &$variables): void {
  $variables['view_mode'] = $variables['elements']['#view_mode'];
  $variables['ispim_preview_image'] = $variables['elements']['#ispim_preview_image'];

  /** @var \Drupal\ispim\Entity\IspimPreviewImageInterface $ispim_preview_image */
  $ispim_preview_image = $variables['ispim_preview_image'];

  $variables['url'] = $ispim_preview_image->toUrl(
    'canonical',
    [
      'language' => $ispim_preview_image->language(),
    ],
  );

  $variables['linkRelationshipType'] = ispim_is_entity_page($ispim_preview_image)
    ? 'canonical'
    : NULL;

  $variables += ['content' => []];
  foreach (Element::children($variables['elements']) as $key) {
    $variables['content'][$key] = $variables['elements'][$key];
  }

  $variables['attributes']['role'] = 'article';
}

/**
 * Implements hook_ENTITY_TYPE_update().
 */
function ispim_ispim_preview_image_update(IspimPreviewImageInterface $entity): void {
  ispim_ensure_image_settings($entity->isPublished() ? NULL : $entity->id());
}

/**
 * Implements hook_ENTITY_TYPE_delete().
 */
function ispim_ispim_preview_image_delete(IspimPreviewImageInterface $entity): void {
  ispim_ensure_image_settings($entity->id());
}

function ispim_ensure_image_settings(null|int|string $ignore): void {
  $config = \Drupal::configFactory()->getEditable('image.settings');
  $actual = $config->get('preview_image');
  if ($actual === IspimPreviewImageInterface::DEFAULT_PREVIEW_IMAGE) {
    return;
  }

  /* @noinspection PhpUnhandledExceptionInspection */
  /** @var \Drupal\file\FileStorageInterface $fileStorage */
  $fileStorage = \Drupal::entityTypeManager()->getStorage('file');
  $files = $fileStorage->loadByProperties(['uri' => $actual]);
  /** @var null|\Drupal\file\FileInterface $file */
  $file = reset($files);
  if (!($file instanceof FileInterface)) {
    $config
      ->set('preview_image', IspimPreviewImageInterface::DEFAULT_PREVIEW_IMAGE)
      ->save();

    return;
  }

  // The file referenced in the config is still exists.
  // This runs in an entity operation (update, delete) transaction,
  // maybe the file will be deleted, because before the update|delete this
  // entity was the last referer, but after the transaction won't be any referer.
  // Orphan files don't get deleted immediately.
  // I don't want to check the file_usage service, because I don't know if
  // this usage was already decremented or not.
  /* @noinspection PhpUnhandledExceptionInspection */
  $query = \Drupal::entityTypeManager()
    ->getStorage('ispim_preview_image')
    ->getQuery()
    ->accessCheck(FALSE)
    ->condition('image', $file->id())
    ->count();
  if ($ignore) {
    $query->condition('id', $ignore, '<>');
  }

  $numOfReferer = $query->execute();
  if (!$numOfReferer) {
    $config
      ->set('preview_image', IspimPreviewImageInterface::DEFAULT_PREVIEW_IMAGE)
      ->save();
  }
}

/**
 * Checks whether the current page is the full page view of the passed-in entity.
 *
 * @param \Drupal\Core\Entity\EntityInterface $entity
 *   An entity.
 *
 * @return bool
 *   Returns TRUE if the current page is the canonical page of the $entity.
 */
function ispim_is_entity_page(EntityInterface $entity): bool {
  $entityTypeId = $entity->getEntityTypeId();
  $routeMatch = \Drupal::routeMatch();
  $pageEntity = ($routeMatch->getRouteName() === "entity.$entityTypeId.canonical")
    ? $routeMatch->getParameter($entityTypeId)
    : NULL;

  return !empty($pageEntity) && $pageEntity->id() === $entity->id();
}

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

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