Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog][keepachangelog] and this project adheres to [Semantic Versioning][semver].

## Unreleased

### Changed

- Rules of `vin_code`, `body_code` and `chassis_code` validators
- In `vin_code`, `body_code` and `chassis_code` validators added type validation

## v5.0.0

### Added
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ FROM php:8.3-alpine

ENV COMPOSER_HOME="/tmp/composer"

COPY --from=composer:2.8.9 /usr/bin/composer /usr/bin/composer
COPY --from=composer:2.8 /usr/bin/composer /usr/bin/composer

RUN set -x \
&& apk add --no-cache binutils git \
Expand Down
2 changes: 0 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
version: '3.2'

volumes:
composer-data:

Expand Down
56 changes: 30 additions & 26 deletions src/Extensions/BodyCodeValidatorExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,23 @@

namespace AvtoDev\ExtendedLaravelValidator\Extensions;

use Illuminate\Support\Str;
use AvtoDev\ExtendedLaravelValidator\Helpers\Strings;
use AvtoDev\ExtendedLaravelValidator\AbstractValidatorExtension;

/**
* Правило валидации номера кузова транспортного средства.
* Правило валидации Номера Кузова (Body) транспортного средства.
*
* Конкретные данные о стандарте номера не были найдены на момент написания данных строк.
*
* @see https://ru.wikipedia.org/wiki/Паспорт_транспортного_средства
* 1. Длина от 7 до 15 символов
* 2. Верхний регистр
* 3. Набор символов — латиница, кириллица, цифры
* 4. Хотя бы одна цифра != 0
* 5. Все буквы из одного алфавита
*/
class BodyCodeValidatorExtension extends AbstractValidatorExtension
{
private const LENGTH_MIN = 7;
private const LENGTH_MAX = 15;

/**
* {@inheritdoc}
*/
Expand All @@ -31,28 +36,27 @@ public function name(): string
*/
public function passes(string $attribute, $value): bool
{
// Статический стек для хранения результатов валидации (для быстродействия)
static $stack = [];

// Если значение в стеке уже есть - то просто возвращаем его
if (! isset($stack[$value])) {
// Разрешенные кириллические символы
static $kyr_chars = 'А-ЯЁ';

// Значение в верхнем регистре
$uppercase = Str::upper($value);

// Вычисляем длину строки
$length = Str::length($uppercase);

$stack[$value] = (
$length >= 8 && $length <= 15 // Проверяем соответствие минимальной и максимальной длине
&& \preg_match('~\d~', $value) === 1 // Содержит числа
// Соответствует ли шаблону
&& \preg_match("~^[{$kyr_chars}A-Z\d]{2,}(\-|\s|)[{$kyr_chars}A-Z\d]{2,9}$~iu", $uppercase) === 1
);
if (!\is_string($value)) {
return false;
}

return $stack[$value];
$length = \mb_strlen($value, 'UTF-8');

return $length >= self::LENGTH_MIN && $length <= self::LENGTH_MAX
&& Strings::hasOnlyUppercaseLetters($value)
&& Strings::hasOnlyUpperLettersAndDigits($value)
&& Strings::hasAtLeastOneNotZeroDigit($value)
&& !$this->hasBothAlphabets($value);
}

/**
* Определяет содержание в строке символов из латинского и кириллического Алфавитов.
*
* @param string $value
* @return bool
*/
private function hasBothAlphabets(string $value): bool
{
return Strings::hasAtLeastOneLatinUpperLetter($value) && Strings::hasAtLeastOneCyrUpperLetter($value);
}
}
8 changes: 1 addition & 7 deletions src/Extensions/ChassisCodeValidatorExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,7 @@
namespace AvtoDev\ExtendedLaravelValidator\Extensions;

/**
* Правило валидации номера шасси транспортного средства.
*
* Конкретные данные о стандарте номера не были найдены на момент написания данных строк.
*
* По всей видимости правило валидации аналогичное правилу валидации номера кузова.
*
* @see https://ru.wikipedia.org/wiki/Рама_(автомобиль)
* Правило валидации номера Шасси (Chassis) транспортного средства.
*/
class ChassisCodeValidatorExtension extends BodyCodeValidatorExtension
{
Expand Down
53 changes: 22 additions & 31 deletions src/Extensions/VinCodeValidatorExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,18 @@

namespace AvtoDev\ExtendedLaravelValidator\Extensions;

use Illuminate\Support\Str;
use AvtoDev\ExtendedLaravelValidator\Helpers\Strings;
use AvtoDev\ExtendedLaravelValidator\AbstractValidatorExtension;

/**
* Правило валидации VIN-кодов.
* Правила валидации VIN транспортного средства.
*
* Структура кода основана на стандартах ISO 3779-1983 и ISO 3780.
* В VIN разрешено использовать только следующие символы латинского алфавита и арабские цифры:
* 0 1 2 3 4 5 6 7 8 9 A B C D E F G H J K L M N P R S T U V W X Y Z
*
* Использовать буквы I, O, Q запрещено, так как они сходны по начертанию с цифрами 1, 0, а также между
* собой.
*
* @see <http://goo.gl/xlDFCk>
* 1. Длина 17 символов
* 2. Верхний регистр
* 3. Набор символов — цифры и латиница за исключением символов `Q`, `I`, `O`
* 4. Последние четыре символа — цифры
* 5. Хотя бы одна буква
* 6. Хотя бы одна цифра != 0
*/
class VinCodeValidatorExtension extends AbstractValidatorExtension
{
Expand All @@ -36,27 +34,20 @@ public function name(): string
*/
public function passes(string $attribute, $value): bool
{
// Статический стек для хранения результатов валидации (для быстродействия)
static $stack = [];

// Если значение в стеке уже есть - то просто возвращаем его
if (! isset($stack[$value])) {
// Значение в верхнем регистре
$uppercase = Str::upper($value);

// Удаляем все символы, кроме разрешенных
$cleared = \preg_replace('~[^0-9ABCDEFGHJKLMNPRSTUVWXYZ]~', '', $uppercase);

$stack[$value] = (
Str::length($value) === 17 // Длинна соответствует
&& $uppercase === $cleared // После удаления запрещенных символов - значение не изменилось
&& \preg_match('~[A-Z]~', $uppercase) === 1 // Содержит символы
&& \preg_match('~\d~', $value) === 1 // Содержит числа
&& ! Str::contains($uppercase, ['I', 'O', 'Q']) // Не содержит запрещенные символы
&& \is_numeric(Str::substr($uppercase, -4, 4)) // Последние четыре символа обязательно числа
);
}
return \is_string($value)
&& $this->hasVinCodeFormat($value)
&& Strings::hasAtLeastOneLatinUpperLetter($value)
&& Strings::hasAtLeastOneNotZeroDigit($value);
}

return $stack[$value];
/**
* Определяет соответствие общему формату VIN транспортного средства.
*
* @param string $value
* @return bool
*/
private function hasVinCodeFormat(string $value): bool
{
return preg_match('/^[A-HJ-NPR-Z0-9]{13}[0-9]{4}$/', $value) === 1;
}
}
55 changes: 55 additions & 0 deletions src/Helpers/Strings.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php
declare(strict_types=1);

namespace AvtoDev\ExtendedLaravelValidator\Helpers;

/**
* @internal
*/
class Strings
{
/**
* @param string $value
* @return bool
*/
public static function hasAtLeastOneNotZeroDigit(string $value): bool
{
return \preg_match('/[1-9]/', $value) === 1;
}

/**
* @param string $value
* @return bool
*/
public static function hasAtLeastOneLatinUpperLetter(string $value): bool
{
return \preg_match('/[A-Z]/', $value) === 1;
}

/**
* @param string $value
* @return bool
*/
public static function hasAtLeastOneCyrUpperLetter(string $value): bool
{
return \preg_match('/[А-ЯЁ]/u', $value) === 1;
}

/**
* @param string $value
* @return bool
*/
public static function hasOnlyUppercaseLetters(string $value): bool
{
return \preg_match('/[a-zа-яё]/u', $value) === 0;
}

/**
* @param string $value
* @return bool
*/
public static function hasOnlyUpperLettersAndDigits(string $value): bool
{
return \preg_match('/^[A-ZА-ЯЁ0-9]+$/u', $value) === 1;
}
}
Loading