mirror of
https://github.com/retailcrm/url-validator.git
synced 2024-11-21 20:56:07 +03:00
Init (#1)
This commit is contained in:
parent
4169bc254c
commit
59b034425f
15
.editorconfig
Normal file
15
.editorconfig
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
end_of_line = lf
|
||||||
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
|
[*.{less,css,yml,json}]
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
[*.md]
|
||||||
|
trim_trailing_whitespace = false
|
38
.github/workflows/ci.yml
vendored
Normal file
38
.github/workflows/ci.yml
vendored
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
name: CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- '**'
|
||||||
|
tags-ignore:
|
||||||
|
- '*.*'
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
name: "PHPUnit"
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
php-version: ['7.3', '7.4']
|
||||||
|
steps:
|
||||||
|
- name: Check out code into the workspace
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
- name: Setup PHP ${{ matrix.php-version }}
|
||||||
|
uses: shivammathur/setup-php@v2
|
||||||
|
with:
|
||||||
|
php-version: ${{ matrix.php-version }}
|
||||||
|
coverage: pcov
|
||||||
|
- name: Composer cache
|
||||||
|
uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: ${{ env.HOME }}/.composer/cache
|
||||||
|
key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: composer install -o
|
||||||
|
- name: Configure matchers
|
||||||
|
uses: mheap/phpunit-matcher-action@v1
|
||||||
|
- name: Run tests
|
||||||
|
run: composer run-script phpunit-ci
|
||||||
|
- name: Coverage
|
||||||
|
run: bash <(curl -s https://codecov.io/bash)
|
42
.github/workflows/code_quality.yml
vendored
Normal file
42
.github/workflows/code_quality.yml
vendored
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
name: "Code Quality Check"
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- "**.php"
|
||||||
|
- "phpcs.xml"
|
||||||
|
- ".github/workflows/code_quality.yml"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
phpcs:
|
||||||
|
name: "PHP CodeSniffer"
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Check out code into the workspace
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
- name: Run PHPCS
|
||||||
|
uses: chekalsky/phpcs-action@v1
|
||||||
|
phpmd:
|
||||||
|
name: "PHP MessDetector"
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Check out code into the workspace
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
- name: Run PHPMD
|
||||||
|
uses: GeneaLabs/action-reviewdog-phpmd@1.0.0
|
||||||
|
with:
|
||||||
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
level: 'warning'
|
||||||
|
reporter: github-pr-check
|
||||||
|
standard: './phpmd.xml'
|
||||||
|
target_directory: 'src'
|
||||||
|
phpstan:
|
||||||
|
name: PHPStan
|
||||||
|
runs-on: ubuntu-18.04
|
||||||
|
steps:
|
||||||
|
- name: Check out code into the workspace
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
- name: Run PHPStan
|
||||||
|
uses: docker://oskarstark/phpstan-ga:0.12.88
|
||||||
|
with:
|
||||||
|
args: analyse src -c phpstan.neon --memory-limit=1G --no-progress
|
21
.gitignore
vendored
Normal file
21
.gitignore
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# Composer files.
|
||||||
|
/vendor
|
||||||
|
composer.lock
|
||||||
|
composer.phar
|
||||||
|
|
||||||
|
# Code Quality tools artifacts.
|
||||||
|
coverage.xml
|
||||||
|
test-report.xml
|
||||||
|
phpunit.xml
|
||||||
|
.php_cs.cache
|
||||||
|
.phpunit.result.cache
|
||||||
|
|
||||||
|
# Different environment-related files.
|
||||||
|
.idea
|
||||||
|
.DS_Store
|
||||||
|
.settings
|
||||||
|
.buildpath
|
||||||
|
.project
|
||||||
|
.swp
|
||||||
|
/nbproject
|
||||||
|
.env
|
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2015-2021 RetailDriver LLC
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
53
composer.json
Normal file
53
composer.json
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
{
|
||||||
|
"name": "retailcrm/validator",
|
||||||
|
"description": "Validator for symfony projects",
|
||||||
|
"type": "library",
|
||||||
|
"keywords": ["Validator", "RetailCRM"],
|
||||||
|
"homepage": "https://www.retailcrm.ru/",
|
||||||
|
"license": "MIT",
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "RetailCRM",
|
||||||
|
"email": "support@retailcrm.ru"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"require": {
|
||||||
|
"php": ">=7.3",
|
||||||
|
"ext-json": "*",
|
||||||
|
"symfony/validator": "^5.3"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": "^9.5.7",
|
||||||
|
"squizlabs/php_codesniffer": "3.*",
|
||||||
|
"phpstan/phpstan": "^0.12.92",
|
||||||
|
"phpmd/phpmd": "^2.10"
|
||||||
|
},
|
||||||
|
"support": {
|
||||||
|
"email": "support@retailcrm.ru"
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": { "RetailCrm\\": "src/" }
|
||||||
|
},
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "0.1-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"bin-dir": "vendor/bin",
|
||||||
|
"process-timeout": 600
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"phpunit": "./vendor/bin/phpunit -c phpunit.xml.dist --coverage-text",
|
||||||
|
"phpunit-ci": "@php -dpcov.enabled=1 -dpcov.directory=. -dpcov.exclude=\"~vendor~\" ./vendor/bin/phpunit --teamcity -c phpunit.xml.dist",
|
||||||
|
"phpmd": "./vendor/bin/phpmd src text ./phpmd.xml",
|
||||||
|
"phpcs": "./vendor/bin/phpcs -p src --runtime-set testVersion 7.3-8.0 && ./vendor/bin/phpcs -p tests --runtime-set testVersion 7.3-8.0 --warning-severity=0",
|
||||||
|
"phpstan": "./vendor/bin/phpstan analyse -c phpstan.neon src --memory-limit=-1",
|
||||||
|
"verify": [
|
||||||
|
"@phpcs",
|
||||||
|
"@phpmd",
|
||||||
|
"@phpstan",
|
||||||
|
"@phpunit"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
13
phpcs.xml.dist
Normal file
13
phpcs.xml.dist
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ruleset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:noNamespaceSchemaLocation="vendor/squizlabs/php_codesniffer/phpcs.xsd">
|
||||||
|
<arg name="basepath" value="."/>
|
||||||
|
<arg name="cache" value=".php_cs.cache"/>
|
||||||
|
<arg name="colors"/>
|
||||||
|
<arg name="extensions" value="php"/>
|
||||||
|
|
||||||
|
<rule ref="PSR12"/>
|
||||||
|
|
||||||
|
<file>src/</file>
|
||||||
|
<file>tests/</file>
|
||||||
|
</ruleset>
|
47
phpmd.xml
Normal file
47
phpmd.xml
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ruleset name="Ruleset"
|
||||||
|
xmlns="http://pmd.sf.net/ruleset/1.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd"
|
||||||
|
xsi:noNamespaceSchemaLocation="http://pmd.sf.net/ruleset_xml_schema.xsd">
|
||||||
|
<description>Ruleset</description>
|
||||||
|
<rule ref="rulesets/controversial.xml" />
|
||||||
|
<rule ref="rulesets/unusedcode.xml" />
|
||||||
|
|
||||||
|
<rule ref="rulesets/design.xml">
|
||||||
|
<exclude name="CouplingBetweenObjects" />
|
||||||
|
</rule>
|
||||||
|
<rule ref="rulesets/cleancode.xml">
|
||||||
|
<exclude name="StaticAccess" />
|
||||||
|
</rule>
|
||||||
|
<rule ref="rulesets/codesize.xml">
|
||||||
|
<exclude name="TooManyPublicMethods" />
|
||||||
|
<exclude name="TooManyFields" />
|
||||||
|
</rule>
|
||||||
|
<rule ref="rulesets/naming.xml">
|
||||||
|
<exclude name="ShortVariable" />
|
||||||
|
</rule>
|
||||||
|
|
||||||
|
<rule ref="rulesets/naming.xml/ShortVariable">
|
||||||
|
<properties>
|
||||||
|
<property name="minimum" value="2" />
|
||||||
|
</properties>
|
||||||
|
</rule>
|
||||||
|
<rule ref="rulesets/codesize.xml/TooManyPublicMethods">
|
||||||
|
<properties>
|
||||||
|
<property name="maxmethods" value="20" />
|
||||||
|
</properties>
|
||||||
|
</rule>
|
||||||
|
<rule ref="rulesets/codesize.xml/TooManyFields">
|
||||||
|
<properties>
|
||||||
|
<property name="maxfields" value="30" />
|
||||||
|
</properties>
|
||||||
|
</rule>
|
||||||
|
<rule ref="rulesets/design.xml/CouplingBetweenObjects">
|
||||||
|
<properties>
|
||||||
|
<property name="maximum" value="15" />
|
||||||
|
</properties>
|
||||||
|
</rule>
|
||||||
|
|
||||||
|
<exclude-pattern>tests/*</exclude-pattern>
|
||||||
|
</ruleset>
|
52
phpstan-baseline.neon
Normal file
52
phpstan-baseline.neon
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
parameters:
|
||||||
|
ignoreErrors:
|
||||||
|
-
|
||||||
|
message: "#^Access to an undefined property Symfony\\\\Component\\\\Validator\\\\Constraint\\:\\:\\$authFail\\.$#"
|
||||||
|
count: 1
|
||||||
|
path: src/Validator/CrmUrlValidator.php
|
||||||
|
|
||||||
|
-
|
||||||
|
message: "#^Access to an undefined property Symfony\\\\Component\\\\Validator\\\\Constraint\\:\\:\\$domainFail\\.$#"
|
||||||
|
count: 1
|
||||||
|
path: src/Validator/CrmUrlValidator.php
|
||||||
|
|
||||||
|
-
|
||||||
|
message: "#^Access to an undefined property Symfony\\\\Component\\\\Validator\\\\Constraint\\:\\:\\$fragmentFail\\.$#"
|
||||||
|
count: 1
|
||||||
|
path: src/Validator/CrmUrlValidator.php
|
||||||
|
|
||||||
|
-
|
||||||
|
message: "#^Access to an undefined property Symfony\\\\Component\\\\Validator\\\\Constraint\\:\\:\\$getFileError\\.$#"
|
||||||
|
count: 1
|
||||||
|
path: src/Validator/CrmUrlValidator.php
|
||||||
|
|
||||||
|
-
|
||||||
|
message: "#^Access to an undefined property Symfony\\\\Component\\\\Validator\\\\Constraint\\:\\:\\$noValidUrl\\.$#"
|
||||||
|
count: 1
|
||||||
|
path: src/Validator/CrmUrlValidator.php
|
||||||
|
|
||||||
|
-
|
||||||
|
message: "#^Access to an undefined property Symfony\\\\Component\\\\Validator\\\\Constraint\\:\\:\\$noValidUrlHost\\.$#"
|
||||||
|
count: 1
|
||||||
|
path: src/Validator/CrmUrlValidator.php
|
||||||
|
|
||||||
|
-
|
||||||
|
message: "#^Access to an undefined property Symfony\\\\Component\\\\Validator\\\\Constraint\\:\\:\\$pathFail\\.$#"
|
||||||
|
count: 1
|
||||||
|
path: src/Validator/CrmUrlValidator.php
|
||||||
|
|
||||||
|
-
|
||||||
|
message: "#^Access to an undefined property Symfony\\\\Component\\\\Validator\\\\Constraint\\:\\:\\$portFail\\.$#"
|
||||||
|
count: 1
|
||||||
|
path: src/Validator/CrmUrlValidator.php
|
||||||
|
|
||||||
|
-
|
||||||
|
message: "#^Access to an undefined property Symfony\\\\Component\\\\Validator\\\\Constraint\\:\\:\\$queryFail\\.$#"
|
||||||
|
count: 1
|
||||||
|
path: src/Validator/CrmUrlValidator.php
|
||||||
|
|
||||||
|
-
|
||||||
|
message: "#^Access to an undefined property Symfony\\\\Component\\\\Validator\\\\Constraint\\:\\:\\$schemeFail\\.$#"
|
||||||
|
count: 1
|
||||||
|
path: src/Validator/CrmUrlValidator.php
|
||||||
|
|
8
phpstan.neon
Normal file
8
phpstan.neon
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
includes:
|
||||||
|
- phpstan-baseline.neon
|
||||||
|
|
||||||
|
parameters:
|
||||||
|
level: 5
|
||||||
|
paths:
|
||||||
|
- src
|
||||||
|
- tests
|
36
phpunit.xml.dist
Normal file
36
phpunit.xml.dist
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!-- https://phpunit.de/manual/current/en/appendixes.configuration.html -->
|
||||||
|
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd"
|
||||||
|
backupGlobals="false"
|
||||||
|
colors="false"
|
||||||
|
bootstrap="tests/bootstrap.php"
|
||||||
|
backupStaticAttributes="false"
|
||||||
|
convertErrorsToExceptions="true"
|
||||||
|
convertNoticesToExceptions="false"
|
||||||
|
convertWarningsToExceptions="false"
|
||||||
|
processIsolation="true"
|
||||||
|
stopOnError="false"
|
||||||
|
stopOnFailure="false"
|
||||||
|
stopOnIncomplete="false"
|
||||||
|
stopOnSkipped="false"
|
||||||
|
stopOnRisky="false"
|
||||||
|
>
|
||||||
|
<coverage>
|
||||||
|
<include>
|
||||||
|
<directory>src</directory>
|
||||||
|
<directory>dev</directory>
|
||||||
|
</include>
|
||||||
|
<report>
|
||||||
|
<clover outputFile="coverage.xml"/>
|
||||||
|
</report>
|
||||||
|
</coverage>
|
||||||
|
<testsuites>
|
||||||
|
<testsuite name="Project Test Suite">
|
||||||
|
<directory>tests</directory>
|
||||||
|
</testsuite>
|
||||||
|
</testsuites>
|
||||||
|
<logging>
|
||||||
|
<junit outputFile="test-report.xml"/>
|
||||||
|
</logging>
|
||||||
|
</phpunit>
|
70
src/Validator/CrmUrl.php
Normal file
70
src/Validator/CrmUrl.php
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace RetailCrm\Validator;
|
||||||
|
|
||||||
|
use Symfony\Component\Validator\Constraint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class CrmUrl
|
||||||
|
*
|
||||||
|
* @Annotation
|
||||||
|
* @Target({"PROPERTY"})
|
||||||
|
* @package Retailcrm\Validator
|
||||||
|
*/
|
||||||
|
class CrmUrl extends Constraint
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $schemeFail = 'Incorrect protocol. Only https is allowed.';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $pathFail = 'The domain path must be empty.';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $portFail = 'The port does not need to be specified.';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $domainFail = 'An invalid domain is specified.';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $noValidUrlHost = 'Incorrect Host URL.';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $noValidUrl = 'Incorrect URL.';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $queryFail = 'The query must be blank.';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $fragmentFail = 'The fragment should be blank.';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $authFail = 'No need to provide authorization data.';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $getFileError = 'Unable to obtain reference values.';
|
||||||
|
|
||||||
|
public function getTargets()
|
||||||
|
{
|
||||||
|
return self::PROPERTY_CONSTRAINT;
|
||||||
|
}
|
||||||
|
}
|
241
src/Validator/CrmUrlValidator.php
Normal file
241
src/Validator/CrmUrlValidator.php
Normal file
@ -0,0 +1,241 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace RetailCrm\Validator;
|
||||||
|
|
||||||
|
use JsonException;
|
||||||
|
use Symfony\Component\Validator\Constraint;
|
||||||
|
use Symfony\Component\Validator\ConstraintValidator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class CrmUrlValidator
|
||||||
|
*
|
||||||
|
* @package Retailcrm\Validator
|
||||||
|
*/
|
||||||
|
class CrmUrlValidator extends ConstraintValidator
|
||||||
|
{
|
||||||
|
public const BOX_DOMAINS_URL = "https://infra-data.retailcrm.tech/box-domains.json";
|
||||||
|
public const CRM_DOMAINS_URL = "https://infra-data.retailcrm.tech/crm-domains.json";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \Symfony\Component\Validator\Constraint
|
||||||
|
*/
|
||||||
|
private $constraint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate CRM URL
|
||||||
|
*
|
||||||
|
* @param mixed $value URL from form
|
||||||
|
* @param Constraint $constraint Restriction for validation
|
||||||
|
*/
|
||||||
|
public function validate($value, Constraint $constraint): void
|
||||||
|
{
|
||||||
|
$this->constraint = $constraint;
|
||||||
|
$filteredUrl = filter_var($value, FILTER_VALIDATE_URL);
|
||||||
|
|
||||||
|
if (false === $filteredUrl) {
|
||||||
|
$this->context->buildViolation($constraint->noValidUrl)->addViolation();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$urlArray = parse_url($filteredUrl);
|
||||||
|
|
||||||
|
if ($this->checkUrlFormat($urlArray)) {
|
||||||
|
$mainDomain = $this->getMainDomain($urlArray['host']);
|
||||||
|
$existInCrm = $this->checkDomains(self::CRM_DOMAINS_URL, $mainDomain);
|
||||||
|
$existInBox = $this->checkDomains(self::BOX_DOMAINS_URL, $urlArray['host']);
|
||||||
|
|
||||||
|
if (false === $existInCrm && false === $existInBox) {
|
||||||
|
$this->context->buildViolation($constraint->domainFail)->addViolation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $crmUrl
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function checkUrlFormat(array $crmUrl): bool
|
||||||
|
{
|
||||||
|
$checkResult = true;
|
||||||
|
$checkAuth = $this->checkAuth($crmUrl);
|
||||||
|
$checkFragment = $this->checkFragment($crmUrl);
|
||||||
|
$checkHost = $this->checkHost($crmUrl);
|
||||||
|
$checkPath = $this->checkPath($crmUrl);
|
||||||
|
$checkPort = $this->checkPort($crmUrl);
|
||||||
|
$checkQuery = $this->checkQuery($crmUrl);
|
||||||
|
$checkScheme = $this->checkScheme($crmUrl);
|
||||||
|
|
||||||
|
if (
|
||||||
|
!$checkAuth
|
||||||
|
|| !$checkFragment
|
||||||
|
|| !$checkHost
|
||||||
|
|| !$checkPath
|
||||||
|
|| !$checkPort
|
||||||
|
|| !$checkQuery
|
||||||
|
|| !$checkScheme
|
||||||
|
) {
|
||||||
|
$checkResult = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $checkResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $crmUrl
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function checkHost(array $crmUrl): bool
|
||||||
|
{
|
||||||
|
if (!isset($crmUrl['host'])) {
|
||||||
|
$this->context->buildViolation($this->constraint->noValidUrlHost)->addViolation();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $crmUrl
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function checkQuery(array $crmUrl): bool
|
||||||
|
{
|
||||||
|
if (isset($crmUrl['query']) && !empty($crmUrl['query'])) {
|
||||||
|
$this->context->buildViolation($this->constraint->queryFail)->addViolation();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $crmUrl
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function checkAuth(array $crmUrl): bool
|
||||||
|
{
|
||||||
|
if (
|
||||||
|
(isset($crmUrl['pass']) && !empty($crmUrl['pass']))
|
||||||
|
|| (isset($crmUrl['user']) && !empty($crmUrl['user']))
|
||||||
|
) {
|
||||||
|
$this->context->buildViolation($this->constraint->authFail)->addViolation();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $crmUrl
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function checkFragment(array $crmUrl): bool
|
||||||
|
{
|
||||||
|
if (isset($crmUrl['fragment']) && !empty($crmUrl['fragment'])) {
|
||||||
|
$this->context->buildViolation($this->constraint->fragmentFail)->addViolation();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $crmUrl
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function checkScheme(array $crmUrl): bool
|
||||||
|
{
|
||||||
|
if (isset($crmUrl['scheme']) && $crmUrl['scheme'] !== 'https') {
|
||||||
|
$this->context->buildViolation($this->constraint->schemeFail)->addViolation();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $crmUrl
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function checkPath(array $crmUrl): bool
|
||||||
|
{
|
||||||
|
if (isset($crmUrl['path']) && $crmUrl['path'] !== '/' && $crmUrl['path'] !== '') {
|
||||||
|
$this->context->buildViolation($this->constraint->pathFail)->addViolation();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $crmUrl
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function checkPort(array $crmUrl): bool
|
||||||
|
{
|
||||||
|
if (isset($crmUrl['port']) && !empty($crmUrl['port'])) {
|
||||||
|
$this->context->buildViolation($this->constraint->portFail)->addViolation();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $domainUrl
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function getValidDomains(string $domainUrl): array
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$content = json_decode(file_get_contents($domainUrl), true, 512, JSON_THROW_ON_ERROR);
|
||||||
|
|
||||||
|
return array_column($content['domains'], 'domain');
|
||||||
|
} catch (JsonException $exception) {
|
||||||
|
$this->context->buildViolation($this->constraint->getFileError)->addViolation();
|
||||||
|
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $host
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private function getMainDomain(string $host): string
|
||||||
|
{
|
||||||
|
$hostArray = explode('.', $host);
|
||||||
|
unset($hostArray[0]);
|
||||||
|
|
||||||
|
return implode('.', $hostArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $crmDomainsUrl
|
||||||
|
* @param string $domainHost
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function checkDomains(string $crmDomainsUrl, string $domainHost): bool
|
||||||
|
{
|
||||||
|
return in_array($domainHost, $this->getValidDomains($crmDomainsUrl), true);
|
||||||
|
}
|
||||||
|
}
|
20
tests/Validator/CrmUrlTest.php
Normal file
20
tests/Validator/CrmUrlTest.php
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace RetailCrm\Tests\Validator;
|
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
use RetailCrm\Validator\CrmUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class CrmUrlTest
|
||||||
|
*
|
||||||
|
* @package RetailCrm\Tests\Validator
|
||||||
|
*/
|
||||||
|
class CrmUrlTest extends TestCase
|
||||||
|
{
|
||||||
|
public function testGetTargets(): void
|
||||||
|
{
|
||||||
|
$crmUrl = new CrmUrl();
|
||||||
|
self::assertEquals('property', $crmUrl->getTargets());
|
||||||
|
}
|
||||||
|
}
|
138
tests/Validator/CrmUrlValidatorTest.php
Normal file
138
tests/Validator/CrmUrlValidatorTest.php
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace RetailCrm\Tests\Validator;
|
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
use RetailCrm\Validator\CrmUrl;
|
||||||
|
use RetailCrm\Validator\CrmUrlValidator;
|
||||||
|
use Symfony\Component\Validator\Constraint;
|
||||||
|
use Symfony\Component\Validator\ConstraintValidatorFactory;
|
||||||
|
use Symfony\Component\Validator\Context\ExecutionContext;
|
||||||
|
use Symfony\Component\Validator\Context\ExecutionContextFactory;
|
||||||
|
use Symfony\Component\Validator\Mapping\Factory\LazyLoadingMetadataFactory;
|
||||||
|
use Symfony\Component\Validator\Validation;
|
||||||
|
use Symfony\Component\Validator\Validator\RecursiveValidator;
|
||||||
|
use Symfony\Contracts\Translation\LocaleAwareInterface;
|
||||||
|
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||||
|
use Symfony\Contracts\Translation\TranslatorTrait;
|
||||||
|
|
||||||
|
class CrmUrlValidatorTest extends TestCase
|
||||||
|
{
|
||||||
|
public function testValidateSuccess(): void
|
||||||
|
{
|
||||||
|
$validCrms = [
|
||||||
|
'https://asd.retailcrm.ru',
|
||||||
|
'https://test.retailcrm.pro',
|
||||||
|
'https://raisa.retailcrm.es',
|
||||||
|
'https://blabla.simla.com',
|
||||||
|
'https://blabla.simlachat.com',
|
||||||
|
'https://blabla.simlachat.ru',
|
||||||
|
'https://blabla.ecomlogic.com',
|
||||||
|
'https://retailcrm.inventive.ru',
|
||||||
|
'https://crm.baucenter.ru',
|
||||||
|
'https://crm.holodilnik.ru',
|
||||||
|
'https://crm.eco.lanit.ru',
|
||||||
|
'https://ecom.inventive.ru',
|
||||||
|
'https://retailcrm.tvoydom.ru',
|
||||||
|
];
|
||||||
|
|
||||||
|
$translator = new class () implements TranslatorInterface, LocaleAwareInterface {
|
||||||
|
use TranslatorTrait;
|
||||||
|
};
|
||||||
|
|
||||||
|
$metadata = new LazyLoadingMetadataFactory();
|
||||||
|
$factory = new ExecutionContextFactory($translator);
|
||||||
|
$validator = new CrmUrlValidator();
|
||||||
|
|
||||||
|
foreach ($validCrms as $validCrm) {
|
||||||
|
$context = new ExecutionContext(
|
||||||
|
new RecursiveValidator($factory, $metadata, new ConstraintValidatorFactory()),
|
||||||
|
CrmUrl::class,
|
||||||
|
$translator
|
||||||
|
);
|
||||||
|
|
||||||
|
$context->setConstraint(new CrmUrl());
|
||||||
|
$validator->initialize($context);
|
||||||
|
$validator->validate($validCrm, new CrmUrl());
|
||||||
|
|
||||||
|
self::assertEmpty($context->getViolations());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testValidateFailed(): void
|
||||||
|
{
|
||||||
|
$failedUrls = [
|
||||||
|
[
|
||||||
|
'url' => 'http://asd.retailcrm.ru',
|
||||||
|
'errors' => ['Incorrect protocol. Only https is allowed.'],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'url' => 'https://test.retailcrm.pro:8080',
|
||||||
|
'errors' => ['The port does not need to be specified.'],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'url' => 'https://raisa.retailcrm.ess',
|
||||||
|
'errors' => ['An invalid domain is specified.'],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'url' => 'https://blabla.simlla.com',
|
||||||
|
'errors' => ['An invalid domain is specified.'],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'url' => 'https:/blabla.simlachat.ru',
|
||||||
|
'errors' => [
|
||||||
|
'Incorrect URL.',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'url' => 'htttps://blabla.ecomlogic.com',
|
||||||
|
'errors' => ['Incorrect protocol. Only https is allowed.'],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'url' => 'https://blabla.ecomlogic.com/test',
|
||||||
|
'errors' => ['The domain path must be empty.'],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'url' => 'htttps://blabla.eecomlogic.com/test',
|
||||||
|
'errors' => [
|
||||||
|
'The domain path must be empty.',
|
||||||
|
'Incorrect protocol. Only https is allowed.',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'url' => 'https://test:test@blabla.eecomlogic.com/test?test=test#fragment',
|
||||||
|
'errors' => [
|
||||||
|
'No need to provide authorization data.',
|
||||||
|
'The fragment should be blank.',
|
||||||
|
'The domain path must be empty.',
|
||||||
|
'The query must be blank.',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
$translator = new class () implements TranslatorInterface, LocaleAwareInterface {
|
||||||
|
use TranslatorTrait;
|
||||||
|
};
|
||||||
|
|
||||||
|
$metadata = new LazyLoadingMetadataFactory();
|
||||||
|
$factory = new ExecutionContextFactory($translator);
|
||||||
|
$validator = new CrmUrlValidator();
|
||||||
|
|
||||||
|
foreach ($failedUrls as $failedUrl) {
|
||||||
|
$context = new ExecutionContext(
|
||||||
|
new RecursiveValidator($factory, $metadata, new ConstraintValidatorFactory()),
|
||||||
|
CrmUrl::class,
|
||||||
|
$translator
|
||||||
|
);
|
||||||
|
$context->setConstraint(new CrmUrl());
|
||||||
|
$validator->initialize($context);
|
||||||
|
$validator->validate($failedUrl['url'], new CrmUrl());
|
||||||
|
|
||||||
|
foreach ($failedUrl['errors'] as $key => $error) {
|
||||||
|
self::assertEquals($context->getViolations()->get($key)->getMessage(), $failedUrl['errors'][$key]);
|
||||||
|
}
|
||||||
|
|
||||||
|
self::assertCount($context->getViolations()->count(), $failedUrl['errors']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1
tests/bootstrap.php
Normal file
1
tests/bootstrap.php
Normal file
@ -0,0 +1 @@
|
|||||||
|
<?php
|
Loading…
Reference in New Issue
Block a user