inline_image_saver-1.0.x-dev/src/Form/InlineImageSaverSettingsForm.php

src/Form/InlineImageSaverSettingsForm.php
<?php

declare(strict_types=1);

namespace Drupal\inline_image_saver\Form;

use Drupal\Component\Plugin\PluginManagerInterface;
use Drupal\Component\Utility\Xss;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Config\TypedConfigManagerInterface;
use Drupal\Core\DependencyInjection\AutowireTrait;
use Drupal\Core\Entity\SynchronizableInterface;
use Drupal\Core\Form\ConfigFormBase;
use Drupal\Core\Form\ConfigTarget;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Form\RedundantEditableConfigNamesTrait;
use Drupal\Core\Render\Element\Checkboxes;
use Drupal\filter\FilterFormatInterface;
use Drupal\inline_image_saver\InlineImageMimeInterface;
use Symfony\Component\DependencyInjection\Attribute\Autowire;

/**
 * Configures inline_image_saver.settings for this site.
 */
class InlineImageSaverSettingsForm extends ConfigFormBase {

  use AutowireTrait;
  use RedundantEditableConfigNamesTrait;

  /**
   * The module config name.
   *
   * @var string
   */
  public const CONFIG_NAME = 'inline_image_saver.settings';

  public function __construct(
    ConfigFactoryInterface $configFactory,
    TypedConfigManagerInterface $typedConfigManager,
    protected InlineImageMimeInterface $inlineImageMime,
    #[Autowire('@plugin.manager.filter')]
    protected PluginManagerInterface $filterPluginManager,
  ) {
    parent::__construct($configFactory, $typedConfigManager);
  }

  /**
   * {@inheritdoc}
   */
  public function getFormId(): string {
    return 'inline_image_saver_settings_form';
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state): array {
    $form['processable_formats'] = [
      '#type' => 'checkboxes',
      '#title' => $this->t('Processable formats'),
      '#options' => array_map(fn (FilterFormatInterface $format) => $format->label(), filter_formats()),
      '#description' => $this->t('Select which text formats should be processed. If none are selected, all available formats will be processed.'),
      '#config_target' => new ConfigTarget(
        static::CONFIG_NAME,
        'processable_formats',
        toConfig: Checkboxes::getCheckedCheckboxes(...),
      ),
    ];

    $form['validation'] = [
      '#type' => 'fieldset',
      '#title' => $this->t('Image validation'),
    ];
    $form['validation']['enable_validation'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Enable image validation'),
      '#description' => $this->t('Validates inline images in text fields and prevents use of external images (not stored on your site).'),
      '#config_target' => static::CONFIG_NAME . ':enable_validation',
    ];
    $form['validation']['settings'] = [
      '#type' => 'container',
      '#states' => [
        'visible' => [
          ':input[name="enable_validation"]' => ['checked' => TRUE],
        ],
      ],
    ];
    $form['validation']['settings']['allow_if_downloadable'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Allow downloadable external images'),
      '#description' => $this->t('Only applies if image downloading is enabled below. Skips validation for external images that can be downloaded and stored locally. These images will be saved and replace the original source.'),
      '#states' => [
        'enabled' => [
          ':input[name="enable_download"]' => ['checked' => TRUE],
        ],
      ],
      '#config_target' => static::CONFIG_NAME . ':validation_settings.allow_if_downloadable',
    ];
    $form['validation']['settings']['allow_data_uri'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Allow data URI images'),
      '#description' => $this->t('Allows inline base64-encoded images like <code>&lt;img src="data:image/..."&gt;</code> to pass validation.'),
      '#config_target' => static::CONFIG_NAME . ':validation_settings.allow_data_uri',
    ];
    $form['validation']['settings']['check_file_exists'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Check image file exists'),
      '#description' => $this->t('Additionally verifies that the referenced image file exists on the file system. Improves validation reliability but may slow down performance. By default, only entity references via <code>data-entity-*</code> attributes are checked.'),
      '#config_target' => static::CONFIG_NAME . ':validation_settings.check_file_exists',
    ];
    $form['validation']['settings']['check_file_mime'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Check image file MIME type'),
      '#description' => $this->t('Check if the image file has a valid and supported MIME type.'),
      '#config_target' => static::CONFIG_NAME . ':validation_settings.check_file_mime',
    ];
    $this->disableIfNoMimeResolver($form['validation']['settings']['check_file_mime']);
    $form['validation']['settings']['validate_url'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Validate image URL'),
      '#description' => $this->t('Validates that the image URL matches the expected file entity URL (host and path only). Usually unnecessary - "@editor_file_reference" filter handles this automatically.', [
        '@editor_file_reference' => $this->filterPluginManager->getDefinition('editor_file_reference')['title'],
      ]),
      '#config_target' => static::CONFIG_NAME . ':validation_settings.validate_url',
    ];
    $form['validation']['settings']['validate_url_query'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Include query parameters in URL validation'),
      '#description' => $this->t('Also checks query parameters in image URLs. May cause issues with dynamic parameters such as tokens from the <a href=":module_url">Private File Token</a> module. Not recommended for most sites.', [
        ':module_url' => 'https://www.drupal.org/project/private_file_token',
      ]),
      '#states' => [
        'enabled' => [
          ':input[name="validate_url"]' => ['checked' => TRUE],
        ],
      ],
      '#config_target' => static::CONFIG_NAME . ':validation_settings.validate_url_query',
    ];

    $form['download'] = [
      '#type' => 'fieldset',
      '#title' => $this->t('Image download'),
    ];
    $form['download']['enable_download'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Download external images'),
      '#description' => $this->t('Automatically downloads external images when saving an entity to prevent broken image links. The downloaded image replaces the original external source.'),
      '#config_target' => static::CONFIG_NAME . ':enable_download',
    ];
    $this->disableIfNoMimeResolver($form['download']['enable_download']);
    $form['download']['settings'] = [
      '#type' => 'container',
      '#access' => !$form['download']['enable_download']['#disabled'],
      '#states' => [
        'visible' => [
          ':input[name="enable_download"]' => ['checked' => TRUE],
        ],
      ],
    ];
    $form['download']['settings']['prefer_reuse_files'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Prefer reusing existing files'),
      '#description' => $this->t('If enabled, the module searches for an existing file entity with identical content (based on file hash) and reuses it instead of saving a new one. Reduces duplication and saves disk space. Supports <a href=":module_url">File Hash</a> module for improved matching.', [
        ':module_url' => 'https://www.drupal.org/project/filehash',
      ]),
      '#config_target' => static::CONFIG_NAME . ':prefer_reuse_files',
    ];

    $form['replace'] = [
      '#type' => 'fieldset',
      '#title' => $this->t('Replace broken images'),
    ];
    $form['replace']['enable_replace'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Replace broken images'),
      '#description' => $this->t('Replaces broken inline images with fallback markup. An image is considered broken if it does not exist on the file system and cannot be downloaded.'),
      '#config_target' => static::CONFIG_NAME . ':enable_replace',
    ];
    $form['replace']['settings'] = [
      '#type' => 'container',
      '#states' => [
        'visible' => [
          ':input[name="enable_replace"]' => ['checked' => TRUE],
        ],
      ],
    ];
    $form['replace']['settings']['fallback_markup'] = [
      '#type' => 'textarea',
      '#title' => $this->t('Fallback markup'),
      '#placeholder' => $this->t('[image not found: @src]'),
      '#description' => $this->t('Available placeholders: <code>@src</code>, <code>@alt</code> and other image attributes. You may include the following allowed HTML tags: <code>@tags</code>', [
        '@tags' => '<' . implode('> <', Xss::getAdminTagList()) . '>',
      ]),
      '#config_target' => new ConfigTarget(
        static::CONFIG_NAME,
        'fallback_markup',
        toConfig: Xss::filterAdmin(...),
      ),
    ];

    $form['revision_group'] = [
      '#type' => 'fieldset',
      '#title' => $this->t('Create new revision'),
    ];
    $form['revision_group']['create_revision'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Create revision'),
      '#description' => $this->t('Creates a new revision if an external image is replaced with a downloaded image or fallback markup.'),
      '#config_target' => static::CONFIG_NAME . ':create_revision',
    ];
    $form['revision_group']['settings'] = [
      '#type' => 'container',
      '#states' => [
        'visible' => [
          ':input[name="create_revision"]' => ['checked' => TRUE],
        ],
      ],
    ];
    $form['revision_group']['settings']['revision_log'] = [
      '#type' => 'textarea',
      '#title' => $this->t('Revision log message'),
      '#placeholder' => $this->t('External images have been replaced.'),
      '#config_target' => static::CONFIG_NAME . ':revision_log',
    ];

    $form['skip_on_sync'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Skip processing on sync'),
      '#description' => $this->t('Skips processing images when an entity is being synchronized programmatically. Useful for batch updates. See <code>@interface</code>.', [
        '@interface' => SynchronizableInterface::class,
      ]),
      '#config_target' => static::CONFIG_NAME . ':skip_on_sync',
    ];

    return parent::buildForm($form, $form_state);
  }

  /**
   * Disables the element if MIME type detection is not supported.
   *
   * @param array $element
   *   The form element to be modified.
   */
  protected function disableIfNoMimeResolver(array &$element): void {
    if ($this->inlineImageMime->isSupported($reason)) {
      $element['#disabled'] = FALSE;
      return;
    }
    if ($description = &$element['#description']) {
      $description = "<s>$description</s><br>";
    }
    $description = $this->t('MIME type detection is not available.');
    if ($reason) {
      $description .= " $reason";
    }
    $element['#disabled'] = TRUE;
  }

}

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

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