Skip to content

Commit

Permalink
Merge branch 'main' into dependabot/composer/drupal/views_conditional…
Browse files Browse the repository at this point in the history
…-1.9.0
  • Loading branch information
tonytaylor authored Nov 13, 2023
2 parents 5033291 + 21325fc commit a9c620d
Show file tree
Hide file tree
Showing 6 changed files with 265 additions and 20 deletions.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@
"symfony/phpunit-bridge": "^5.1",
"symfony/process": "^4.0",
"symfony/routing": "^4.0",
"va-gov/content-build": "^0.0.3383",
"va-gov/content-build": "^0.0.3384",
"vlucas/phpdotenv": "^5.3",
"webflo/drupal-finder": "^1.0.0",
"webmozart/path-util": "^2.3",
Expand Down
38 changes: 19 additions & 19 deletions composer.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "a4aad9828ce96200f58c79b8835f2dbe",
"content-hash": "46324568c25bb0d608f02a155642e0e0",
"packages": [
{
"name": "alchemy/zippy",
Expand Down Expand Up @@ -16275,37 +16275,37 @@
},
{
"name": "mglaman/phpstan-drupal",
"version": "1.2.1",
"version": "1.2.2",
"source": {
"type": "git",
"url": "https://github.com/mglaman/phpstan-drupal.git",
"reference": "920c6b972a832046327f66dc6ff7448e3b5d6e4c"
"reference": "bde6445d8102954d94e88492c60206a499c21889"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/mglaman/phpstan-drupal/zipball/920c6b972a832046327f66dc6ff7448e3b5d6e4c",
"reference": "920c6b972a832046327f66dc6ff7448e3b5d6e4c",
"url": "https://api.github.com/repos/mglaman/phpstan-drupal/zipball/bde6445d8102954d94e88492c60206a499c21889",
"reference": "bde6445d8102954d94e88492c60206a499c21889",
"shasum": ""
},
"require": {
"php": "^7.4 || ^8.0",
"phpstan/phpstan": "^1.10.1",
"phpstan/phpstan-deprecation-rules": "^1.1.4",
"symfony/finder": "~3.4.5 ||^4.2 || ^5.0 || ^6.0",
"symfony/yaml": "~3.4.5 || ^4.2|| ^5.0 || ^6.0",
"symfony/finder": "^4.2 || ^5.0 || ^6.0",
"symfony/yaml": "^4.2|| ^5.0 || ^6.0",
"webflo/drupal-finder": "^1.2"
},
"require-dev": {
"behat/mink": "^1.8",
"composer/installers": "^1.9",
"drupal/core-recommended": "^8.8@alpha || ^9.0",
"drush/drush": "^9.6 || ^10.0 || ^11",
"drupal/core-recommended": "^9.0",
"drush/drush": "^10.0 || ^11 || ^12",
"phpstan/extension-installer": "^1.1",
"phpstan/phpstan-strict-rules": "^1.0",
"phpunit/phpunit": "^6.5 || ^7.5 || ^8.0 || ^9",
"phpunit/phpunit": "^8.5 || ^9",
"slevomat/coding-standard": "^7.1",
"squizlabs/php_codesniffer": "^3.3",
"symfony/phpunit-bridge": "^3.4.3 || ^4.4 || ^5.4 || ^6.0"
"symfony/phpunit-bridge": "^4.4 || ^5.4 || ^6.0"
},
"suggest": {
"jangregor/phpstan-prophecy": "Provides a prophecy/prophecy extension for phpstan/phpstan.",
Expand Down Expand Up @@ -16359,7 +16359,7 @@
"description": "Drupal extension and rules for PHPStan",
"support": {
"issues": "https://github.com/mglaman/phpstan-drupal/issues",
"source": "https://github.com/mglaman/phpstan-drupal/tree/1.2.1"
"source": "https://github.com/mglaman/phpstan-drupal/tree/1.2.2"
},
"funding": [
{
Expand All @@ -16375,7 +16375,7 @@
"type": "tidelift"
}
],
"time": "2023-11-03T13:17:28+00:00"
"time": "2023-11-09T23:13:46+00:00"
},
{
"name": "michelf/php-markdown",
Expand Down Expand Up @@ -26911,16 +26911,16 @@
},
{
"name": "va-gov/content-build",
"version": "v0.0.3383",
"version": "v0.0.3384",
"source": {
"type": "git",
"url": "https://github.com/department-of-veterans-affairs/content-build.git",
"reference": "ec4aa8360e1e4fc028a17c29408c6aad1ace4e26"
"reference": "6fd752b56a7291cbf380805ae90a0d60dc468535"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/department-of-veterans-affairs/content-build/zipball/ec4aa8360e1e4fc028a17c29408c6aad1ace4e26",
"reference": "ec4aa8360e1e4fc028a17c29408c6aad1ace4e26",
"url": "https://api.github.com/repos/department-of-veterans-affairs/content-build/zipball/6fd752b56a7291cbf380805ae90a0d60dc468535",
"reference": "6fd752b56a7291cbf380805ae90a0d60dc468535",
"shasum": ""
},
"type": "node-project",
Expand All @@ -26947,9 +26947,9 @@
"description": "Front-end for VA.gov. This repository contains the code that generates the www.va.gov website. It contains a Metalsmith static site builder that uses a Drupal CMS for content. This file is here to publish releases to https://packagist.org/packages/va-gov/content-build, so that the CMS CI system can install it and update it using standard composer processes, and so that we can run tests across both systems. See https://github.com/department-of-veterans-affairs/va.gov-cms for the CMS repo, and stand by for more documentation.",
"support": {
"issues": "https://github.com/department-of-veterans-affairs/content-build/issues",
"source": "https://github.com/department-of-veterans-affairs/content-build/tree/v0.0.3383"
"source": "https://github.com/department-of-veterans-affairs/content-build/tree/v0.0.3384"
},
"time": "2023-11-07T23:50:06+00:00"
"time": "2023-11-09T20:58:42+00:00"
},
{
"name": "vlucas/phpdotenv",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

namespace Drupal\va_gov_backend\Plugin\Validation\Constraint;

use Symfony\Component\Validator\Constraint;

/**
* Checks that the text does not use any preview URL links.
*
* In other words, we want to avoid things like this:
*
* `<a href="https://preview-staging.vfs.va.gov/path/to/content/">VA.gov</a>`
*
* @Constraint(
* id = "PreventPreviewUrlLinks",
* label = @Translation("Prevent Preview URL Links", context = "Validation"),
* type = { "string_long", "text_long" }
* )
*/
class PreventPreviewUrlLinks extends Constraint {

/**
* The error message for plain text fields.
*
* @var string
* @see \Drupal\va_gov_backend\Plugin\Validation\Constraint\PreventPreviewUrlLinksValidator
*/
public $plainTextMessage = 'Replace the preview URL ":url" with a public URL.';

/**
* The error message for rich text fields.
*
* @var string
* @see \Drupal\va_gov_backend\Plugin\Validation\Constraint\PreventPreviewUrlLinksValidator
*/
public $richTextMessage = 'Review the linked text ":link" (:url) and replace the preview URL with a public URL.';

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<?php

namespace Drupal\va_gov_backend\Plugin\Validation\Constraint;

use Drupal\Component\Utility\Html;
use Drupal\va_gov_backend\Plugin\Validation\Constraint\Traits\TextValidatorTrait;
use Drupal\va_gov_backend\Plugin\Validation\Constraint\Traits\ValidatorContextAccessTrait;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

/**
* Validates the PreventPreviewUrlLinks constraint.
*/
class PreventPreviewUrlLinksValidator extends ConstraintValidator {

use TextValidatorTrait;
use ValidatorContextAccessTrait;

/**
* {@inheritdoc}
*/
public function validateText(string $text, Constraint $constraint, int $delta) {
/*
* Regular expression explanation:
*
* # Begin delimiter (replace '/', since we're mucking about
* with URLs, which contain slashes.)
* ( Open capture group. We capture the entire URL so that
* we can refer to it in the error message.
* https? Match either 'http' or 'https' ...
* :// ... followed by a colon and two slashes ...
* preview-(staging|prod)
* .vfs.va.gov ... followed by a preview servers for prod|staging ...
* [^\s]+ ... and any non-whitespace characters that follow.
* ) Close capture group.
* # End delimiter (replace '/')
*
* In other words, we look for a string that looks like a preview URL.
*/
/** @var \Drupal\va_gov_backend\Plugin\Validation\Constraint\PreventPreviewUrlLinks $constraint */
if (preg_match('#(https?://preview-(staging|prod).vfs.va.gov[^\s]+)#', $text, $matches)) {
$this->addViolation($delta, $constraint->plainTextMessage, [
':url' => $matches[1],
]);
}
}

/**
* {@inheritdoc}
*/
public function validateHtml(string $html, Constraint $constraint, int $delta) {
/** @var \Drupal\va_gov_backend\Plugin\Validation\Constraint\PreventPreviewUrlLinks $constraint */
$dom = Html::load($html);
$xpath = new \DOMXPath($dom);
foreach ($xpath->query('//a[contains(@href, "preview-staging.vfs.va.gov") or contains(@href, "preview-prod.vfs.va.gov")]') as $element) {
// Ignore non-element nodes.
if (!($element instanceof \DOMElement)) {
continue;
}
$url = $element->getAttribute('href');
$firstChild = $element->hasChildNodes() ? $element->childNodes[0] : NULL;
$link = $element->ownerDocument->saveHTML($firstChild ?? $element);
$this->getContext()
->buildViolation($constraint->richTextMessage, [
':link' => $link,
':url' => $url,
])
->atPath((string) $delta . '.value')
->addViolation();
return;
}
}

}
2 changes: 2 additions & 0 deletions docroot/modules/custom/va_gov_backend/va_gov_backend.module
Original file line number Diff line number Diff line change
Expand Up @@ -1323,6 +1323,7 @@ function va_gov_backend_entity_bundle_field_info_alter(&$fields, EntityTypeInter
$field->addConstraint('PreventAbsoluteUrlsAsPathsInLinks');
$field->addConstraint('PreventVaGovDomainsAsPathsInLinks');
$field->addConstraint('PreventDomainsAsPathsInLinks');
$field->addConstraint('PreventPreviewUrlLinks');
}
elseif ($field->getType() === 'text_long') {
$field->addConstraint('PreventAbsoluteCmsLinks');
Expand All @@ -1332,6 +1333,7 @@ function va_gov_backend_entity_bundle_field_info_alter(&$fields, EntityTypeInter
$field->addConstraint('PreventAbsoluteUrlsAsPathsInLinks');
$field->addConstraint('PreventVaGovDomainsAsPathsInLinks');
$field->addConstraint('PreventDomainsAsPathsInLinks');
$field->addConstraint('PreventPreviewUrlLinks');
}
}
// Add paragraph checks on clp panels.
Expand Down
131 changes: 131 additions & 0 deletions tests/phpunit/Content/PreventPreviewUrlLinksValidatorTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
<?php

namespace tests\phpunit\Content;

use Drupal\va_gov_backend\Plugin\Validation\Constraint\PreventPreviewUrlLinks;
use Drupal\va_gov_backend\Plugin\Validation\Constraint\PreventPreviewUrlLinksValidator;
use Tests\Support\Classes\VaGovUnitTestBase;
use Tests\Support\Traits\ValidatorTestTrait;

/**
* A test to confirm the proper functioning of this validator.
*
* @group unit
* @group all
* @group validation
*
* @coversDefaultClass \Drupal\va_gov_backend\Plugin\Validation\Constraint\PreventProtocolRelativeLinksValidator
*/
class PreventPreviewUrlLinksValidatorTest extends VaGovUnitTestBase {

use ValidatorTestTrait;

/**
* Test ::addViolation().
*
* @covers ::addViolation
*/
public function testAddViolation() {
$validator = new PreventPreviewUrlLinksValidator();
$this->prepareValidator($validator, FALSE);
$validator->addViolation(3, 'Test violation');
}

/**
* Test ::validate().
*
* @param bool $willValidate
* TRUE if the test string should validate, otherwise FALSE.
* @param string $testString
* Some test string to attempt to validate.
* @param string $fieldType
* The type of the text field, e.g. 'text_long' or 'string_long'.
* @param string $format
* An optional format, like 'plain_text' or 'rich_text'.
*
* @covers validate
* @covers validateText
* @covers validateHtml
* @dataProvider validateDataProvider
*/
public function testValidate(bool $willValidate, string $testString, string $fieldType = 'string_long', string $format = NULL) {
$value = [
'value' => $testString,
];
if ($fieldType !== 'string_long') {
$value['format'] = $format;
}
$items = $this->getFieldItemList([
$this->getFieldItem($value, $fieldType),
]);
$validator = new PreventPreviewUrlLinksValidator();
$this->prepareValidator($validator, $willValidate);
$validator->validate($items, new PreventPreviewUrlLinks());
}

/**
* Data provider.
*/
public function validateDataProvider() {
return [
[
TRUE,
'Normal string_long text should not fail validation.',
],
[
TRUE,
'Normal string_long text with the occasional // scattered throughout should not // fail validation.',
],
[
FALSE,
'However, string_long text with http://preview-staging.vfs.va.gov/path/to/content that consists of an Preview URL should fail validation.',
],
[
FALSE,
'However, string_long text with http://preview-prod.vfs.va.gov/path/to/content that consists of an Preview URL should fail validation.',
],
[
TRUE,
'Normal text_long text should not fail validation.',
'text_long',
],
[
FALSE,
'Something with a http://preview-staging.vfs.va.gov/path/to/content looks like it contains an Preview URL and should fail.',
'text_long',
'plain_text',
],
[
FALSE,
'Something with a https://preview-prod.vfs.va.gov/path/to/content looks like it contains an Preview URL and should fail.',
'text_long',
'plain_text',
],
[
FALSE,
'This contains a <a href="https://preview-staging.vfs.va.gov/path/to/content">path consisting of an Preview URL</a> inside a tag and should fail.',
'text_long',
'plain_text',
],
[
FALSE,
'This contains a <a href="https://preview-prod.vfs.va.gov/path/to/content">path consisting of an Preview URL</a> inside a tag and should fail.',
'text_long',
'plain_text',
],
[
TRUE,
'http://preview-staging.vfs.va.gov/path/to/content outside of <a href="https://www.example.org/">anchor tags</a> should not trigger the validator.',
'text_long',
'rich_text',
],
[
TRUE,
'http://preview-prod.vfs.va.gov/path/to/content outside of <a href="https://www.example.org/">anchor tags</a> should not trigger the validator.',
'text_long',
'rich_text',
],
];
}

}

0 comments on commit a9c620d

Please sign in to comment.