inline_image_saver-1.0.x-dev/src/Plugin/Validation/Constraint/InlineImageSaverConstraintValidator.php
src/Plugin/Validation/Constraint/InlineImageSaverConstraintValidator.php
<?php
declare(strict_types=1);
namespace Drupal\inline_image_saver\Plugin\Validation\Constraint;
use Drupal\Component\Utility\UrlHelper;
use Drupal\Core\DependencyInjection\AutowireTrait;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\inline_image_saver\InlineImageSaverInterface;
use Drupal\inline_image_saver\Struct\InlineImageValidation;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
/**
* Validates the InlineImageSaver constraint.
*/
class InlineImageSaverConstraintValidator extends ConstraintValidator implements ContainerInjectionInterface {
use AutowireTrait;
public function __construct(protected readonly InlineImageSaverInterface $inlineImageSaver) {}
/**
* Checks if the passed value is valid.
*
* @param \Drupal\text\Plugin\Field\FieldType\TextItemBase $value
* The text field item.
* @param \Drupal\inline_image_saver\Plugin\Validation\Constraint\InlineImageSaverConstraint $constraint
* The constraint.
*
* @uses \Drupal\inline_image_saver\Plugin\Validation\Constraint\InlineImageSaverConstraint::$messageUnknown
* @uses \Drupal\inline_image_saver\Plugin\Validation\Constraint\InlineImageSaverConstraint::$messageInvalidDataUriValue
* @uses \Drupal\inline_image_saver\Plugin\Validation\Constraint\InlineImageSaverConstraint::$messageUnsupportedDataUriMimeType
* @uses \Drupal\inline_image_saver\Plugin\Validation\Constraint\InlineImageSaverConstraint::$messageDataUriNotAllowed
* @uses \Drupal\inline_image_saver\Plugin\Validation\Constraint\InlineImageSaverConstraint::$messageEmptyEntityTypeAttribute
* @uses \Drupal\inline_image_saver\Plugin\Validation\Constraint\InlineImageSaverConstraint::$messageUnsupportedEntityTypeAttribute
* @uses \Drupal\inline_image_saver\Plugin\Validation\Constraint\InlineImageSaverConstraint::$messageEmptyEntityUuid
* @uses \Drupal\inline_image_saver\Plugin\Validation\Constraint\InlineImageSaverConstraint::$messageEntityNotFound
* @uses \Drupal\inline_image_saver\Plugin\Validation\Constraint\InlineImageSaverConstraint::$messageFileNotFound
* @uses \Drupal\inline_image_saver\Plugin\Validation\Constraint\InlineImageSaverConstraint::$messageUrlHostMismatch
* @uses \Drupal\inline_image_saver\Plugin\Validation\Constraint\InlineImageSaverConstraint::$messageUrlPathMismatch
* @uses \Drupal\inline_image_saver\Plugin\Validation\Constraint\InlineImageSaverConstraint::$messageUrlQueryMismatch
* @uses \Drupal\inline_image_saver\Plugin\Validation\Constraint\InlineImageSaverConstraint::$messageUnsupportedFileMime
*/
public function validate($value, Constraint $constraint): void {
if (!$dom = $this->inlineImageSaver->parseTextItemDom($value)) {
return;
}
$main_property = $value->getFieldDefinition()->getFieldStorageDefinition()->getMainPropertyName();
$settings = $this->inlineImageSaver->getSettings();
$allow_downloadable = $settings['enable_download'] && $settings['validation_settings']['allow_if_downloadable'];
/** @var \DOMElement $img */
foreach ($dom->getElementsByTagName('img') as $img) {
$validation = $this->inlineImageSaver->validateImage($img);
if (!$error = $validation->error) {
continue;
}
if (!$allow_downloadable || !$this->inlineImageSaver->downloadImage($img)) {
$this->context
->buildViolation($validation->message ?? $constraint->{"message$error->name"}, $this->buildViolationParameters($validation, $constraint))
->atPath($main_property)
->addViolation();
}
}
}
/**
* Builds parameters for image validation error messages.
*
* @param \Drupal\inline_image_saver\Struct\InlineImageValidation $validation
* The validation result.
* @param \Drupal\inline_image_saver\Plugin\Validation\Constraint\InlineImageSaverConstraint $constraint
* The constraint.
*
* @return array<string, string|\Drupal\Core\StringTranslation\TranslatableMarkup>
* The built parameters.
*/
protected function buildViolationParameters(InlineImageValidation $validation, InlineImageSaverConstraint $constraint): array {
$img_name = $validation->img->getAttribute('alt') ?: $validation->img->getAttribute('title') ?: NULL;
if ($img_url = $validation->img->getAttribute('src')) {
if ($validation->isDataUriImage) {
$img_name ??= $this->truncateString($img_url, $constraint->dataUriCharLimit);
$img_url = '#';
}
else {
$parsed_url = parse_url($img_url);
$img_name ??= $this->truncateString(($parsed_url['path'] ?? NULL) ?: $img_url, $constraint->urlPathCharLimit);
if (UrlHelper::isValid($img_url, !empty($parsed_url['host']))) {
$img_target = '_blank';
}
else {
$img_url = '#';
}
}
}
else {
$img_url = '#';
$img_name ??= '""';
}
return [
':url' => $img_url,
'@name' => $img_name,
'@target' => $img_target ?? '_self',
];
}
/**
* Truncates a string to a maximum length, adding ellipsis if needed.
*
* @param string $text
* The string to truncate.
* @param int $max_length
* The maximum allowed length.
*
* @return string
* The processed string.
*/
protected function truncateString(string $text, int $max_length): string {
return strlen($text) > $max_length
? substr($text, 0, $max_length) . '…'
: $text;
}
}
