mirror of
https://github.com/wiosna-dev/common-library.git
synced 2026-03-12 01:31:45 +01:00
755 lines
21 KiB
PHP
755 lines
21 KiB
PHP
<?php
|
|
|
|
/**
|
|
* (c) Meritoo.pl, http://www.meritoo.pl
|
|
* For the full copyright and license information, please view the LICENSE
|
|
* file that was distributed with this source code.
|
|
*/
|
|
|
|
namespace Meritoo\Common\Utilities;
|
|
|
|
use Meritoo\Common\Exception\Regex\IncorrectColorHexLengthException;
|
|
use Meritoo\Common\Exception\Regex\InvalidColorHexValueException;
|
|
|
|
/**
|
|
* Useful regular expressions methods
|
|
*
|
|
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl>
|
|
* @copyright Meritoo.pl
|
|
*/
|
|
class Regex
|
|
{
|
|
/**
|
|
* Patterns used to validate / verify values
|
|
*
|
|
* @var array
|
|
*/
|
|
private static $patterns = [
|
|
'email' => '/[\w-]{2,}@[\w-]+\.[\w]{2,}+/',
|
|
'phone' => '/^\+?[0-9 ]+$/',
|
|
'camelCasePart' => '/([a-z]|[A-Z]){1}[a-z]*/',
|
|
'urlProtocol' => '/^([a-z]+:\/\/)',
|
|
'urlDomain' => '([\da-z\.-]+)\.([a-z\.]{2,6})(\/)?([\w\.\-]*)?(\?)?([\w \.\-\/=&]*)\/?$/i',
|
|
'letterOrDigit' => '/[a-zA-Z0-9]+/',
|
|
'htmlEntity' => '/&[a-z0-9]+;/',
|
|
'fileName' => '/.+\.\w+$/',
|
|
'isQuoted' => '/^[\'"]{1}.+[\'"]{1}$/',
|
|
'windowsBasedPath' => '/^[A-Z]{1}:\\\.*$/',
|
|
'money' => '/^[-+]?\d+([\.,]{1}\d*)?$/',
|
|
'color' => '/^[a-f0-9]{6}$/i',
|
|
'bundleName' => '/^(([A-Z]{1}[a-z0-9]+)((?2))*)(Bundle)$/',
|
|
];
|
|
|
|
/**
|
|
* Returns information if given e-mail address is valid
|
|
*
|
|
* @param string $email E-mail address to validate / verify
|
|
* @return bool
|
|
*
|
|
* Examples:
|
|
* a) valid e-mails:
|
|
* - ni@g-m.pl
|
|
* - ni@gm.pl
|
|
* - ni@g_m.pl
|
|
* b) invalid e-mails:
|
|
* - ni@g-m.p
|
|
* - n@g-m.pl
|
|
*/
|
|
public static function isValidEmail($email)
|
|
{
|
|
$pattern = self::getEmailPattern();
|
|
|
|
return (bool)preg_match($pattern, $email);
|
|
}
|
|
|
|
/**
|
|
* Returns information if given tax ID is valid (in Poland it's named "NIP")
|
|
*
|
|
* @param string $taxIdString Tax ID (NIP) string
|
|
* @return bool
|
|
*/
|
|
public static function isValidTaxId($taxIdString)
|
|
{
|
|
if (!empty($taxIdString)) {
|
|
$weights = [
|
|
6,
|
|
5,
|
|
7,
|
|
2,
|
|
3,
|
|
4,
|
|
5,
|
|
6,
|
|
7,
|
|
];
|
|
$taxId = preg_replace('/[\s-]/', '', $taxIdString);
|
|
$sum = 0;
|
|
|
|
if (10 == strlen($taxId) && is_numeric($taxId)) {
|
|
for ($x = 0; $x <= 8; ++$x) {
|
|
$sum += $taxId[$x] * $weights[$x];
|
|
}
|
|
|
|
if ((($sum % 11) % 10) == $taxId[9]) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Returns information if given url address is valid
|
|
*
|
|
* @param string $url The url to validate / verify
|
|
* @param bool $requireProtocol (optional) If is set to true, the protocol is required to be passed in the url.
|
|
* Otherwise - not.
|
|
* @return bool
|
|
*/
|
|
public static function isValidUrl($url, $requireProtocol = false)
|
|
{
|
|
$pattern = self::getUrlPattern($requireProtocol);
|
|
|
|
return (bool)preg_match($pattern, $url);
|
|
}
|
|
|
|
/**
|
|
* Returns information if given phone number is valid
|
|
*
|
|
* @param string $phoneNumber The phone number to validate / verify
|
|
* @return bool
|
|
*/
|
|
public static function isValidPhoneNumber($phoneNumber)
|
|
{
|
|
$pattern = self::getPhoneNumberPattern();
|
|
|
|
return (bool)preg_match($pattern, $phoneNumber);
|
|
}
|
|
|
|
/**
|
|
* Returns array values that matches given pattern (or values that keys matches)
|
|
*
|
|
* @param string $pattern Pattern to match
|
|
* @param array $dataArray The array
|
|
* @param bool $itsKeyPattern (optional) If is set to true, keys are checks if they match pattern. Otherwise -
|
|
* values are checks.
|
|
* @return array
|
|
*/
|
|
public static function getArrayValuesByPattern($pattern, $dataArray, $itsKeyPattern = false)
|
|
{
|
|
if ($itsKeyPattern) {
|
|
$effect = [];
|
|
|
|
if (!empty($dataArray)) {
|
|
$matches = [];
|
|
|
|
foreach ($dataArray as $key => $value) {
|
|
if (preg_match($pattern, $key, $matches)) {
|
|
$effect[$key] = $value;
|
|
}
|
|
}
|
|
}
|
|
|
|
return $effect;
|
|
}
|
|
|
|
return preg_grep($pattern, $dataArray);
|
|
}
|
|
|
|
/**
|
|
* Filters array by given expression and column
|
|
*
|
|
* Expression can be simple compare expression, like ' == 2', or regular expression.
|
|
* Returns filtered array.
|
|
*
|
|
* @param array $array The array that should be filtered
|
|
* @param string $arrayColumnKey Column name
|
|
* @param string $filterExpression Filter expression, e.g. '== 2' or '!= \'home\''
|
|
* @param bool $itsRegularExpression (optional) If is set to true, means that filter expression is a
|
|
* regular expression
|
|
* @return array
|
|
*/
|
|
public static function arrayFilter($array, $arrayColumnKey, $filterExpression, $itsRegularExpression = false)
|
|
{
|
|
$effect = [];
|
|
|
|
if (!empty($array)) {
|
|
$effect = $array;
|
|
|
|
foreach ($effect as $key => &$item) {
|
|
if (isset($item[$arrayColumnKey])) {
|
|
$value = $item[$arrayColumnKey];
|
|
|
|
if ($itsRegularExpression) {
|
|
$matches = [];
|
|
$pattern = '|' . $filterExpression . '|';
|
|
$matchesCount = preg_match($pattern, $value, $matches);
|
|
|
|
$remove = 0 == $matchesCount;
|
|
} else {
|
|
if ('' == $value) {
|
|
$value = '\'\'';
|
|
} elseif (is_string($value)) {
|
|
$value = '\'' . $value . '\'';
|
|
}
|
|
|
|
eval('$isTrue = ' . $value . $filterExpression . ';');
|
|
|
|
/* @var bool $isTrue */
|
|
$remove = !$isTrue;
|
|
}
|
|
|
|
if ($remove) {
|
|
unset($effect[$key]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return $effect;
|
|
}
|
|
|
|
/**
|
|
* Perform regular expression match with many given patterns.
|
|
* Returns information if given $subject matches one or all given $patterns.
|
|
*
|
|
* @param array|string $patterns The patterns to match
|
|
* @param string $subject The string to check
|
|
* @param bool $mustAllMatch (optional) If is set to true, $subject must match all $patterns. Otherwise -
|
|
* not.
|
|
* @return bool
|
|
*/
|
|
public static function pregMultiMatch($patterns, $subject, $mustAllMatch = false)
|
|
{
|
|
$effect = false;
|
|
$patterns = Arrays::makeArray($patterns);
|
|
|
|
if (!empty($patterns)) {
|
|
if ($mustAllMatch) {
|
|
$effect = true;
|
|
}
|
|
|
|
foreach ($patterns as $pattern) {
|
|
$matches = [];
|
|
$matched = (bool)preg_match_all($pattern, $subject, $matches);
|
|
|
|
if ($mustAllMatch) {
|
|
$effect = $effect && $matched;
|
|
} else {
|
|
if ($matched) {
|
|
$effect = $matched;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return $effect;
|
|
}
|
|
|
|
/**
|
|
* Returns string in human readable style generated from given camel case string / text
|
|
*
|
|
* @param string $string The string / text to convert
|
|
* @param bool $applyUpperCaseFirst (optional) If is set to true, first word / element from the converted
|
|
* string is uppercased. Otherwise - not.
|
|
* @return string
|
|
*/
|
|
public static function camelCase2humanReadable($string, $applyUpperCaseFirst = false)
|
|
{
|
|
$parts = self::getCamelCaseParts($string);
|
|
|
|
if (!empty($parts)) {
|
|
$elements = [];
|
|
|
|
foreach ($parts as $part) {
|
|
$elements[] = strtolower($part);
|
|
}
|
|
|
|
$string = implode(' ', $elements);
|
|
|
|
if ($applyUpperCaseFirst) {
|
|
$string = ucfirst($string);
|
|
}
|
|
}
|
|
|
|
return $string;
|
|
}
|
|
|
|
/**
|
|
* Returns parts of given camel case string / text
|
|
*
|
|
* @param string $string The string / text to retrieve parts
|
|
* @return array
|
|
*/
|
|
public static function getCamelCaseParts($string)
|
|
{
|
|
$pattern = self::getCamelCasePartPattern();
|
|
$matches = [];
|
|
preg_match_all($pattern, $string, $matches);
|
|
|
|
return $matches[0];
|
|
}
|
|
|
|
/**
|
|
* Returns simple, lowercase string generated from given camel case string / text
|
|
*
|
|
* @param string $string The string / text to convert
|
|
* @param string $separator (optional) Separator used to concatenate parts of the string, e.g. '-' or '_'
|
|
* @param bool $applyLowercase (optional) If is set to true, returned string will be lowercased. Otherwise - not.
|
|
* @return string
|
|
*/
|
|
public static function camelCase2simpleLowercase($string, $separator = '', $applyLowercase = true)
|
|
{
|
|
$parts = self::getCamelCaseParts($string);
|
|
|
|
if (!empty($parts)) {
|
|
$string = implode($separator, $parts);
|
|
|
|
if ($applyLowercase) {
|
|
$string = strtolower($string);
|
|
}
|
|
}
|
|
|
|
return $string;
|
|
}
|
|
|
|
/**
|
|
* Returns pattern used to validate / verify or get e-mail address
|
|
*
|
|
* @return string
|
|
*/
|
|
public static function getEmailPattern()
|
|
{
|
|
return self::$patterns['email'];
|
|
}
|
|
|
|
/**
|
|
* Returns pattern used to validate / verify or get phone number
|
|
*
|
|
* @return string
|
|
*/
|
|
public static function getPhoneNumberPattern()
|
|
{
|
|
return self::$patterns['phone'];
|
|
}
|
|
|
|
/**
|
|
* Returns pattern used to validate / verify or get camel case parts of string
|
|
*
|
|
* @return string
|
|
*/
|
|
public static function getCamelCasePartPattern()
|
|
{
|
|
return self::$patterns['camelCasePart'];
|
|
}
|
|
|
|
/**
|
|
* Returns pattern used to validate / verify or get url address
|
|
*
|
|
* @param bool $requireProtocol (optional) If is set to true, the protocol is required to be passed in the url.
|
|
* Otherwise - not.
|
|
* @return string
|
|
*/
|
|
public static function getUrlPattern($requireProtocol = false)
|
|
{
|
|
$urlProtocol = self::$patterns['urlProtocol'];
|
|
$urlDomain = self::$patterns['urlDomain'];
|
|
$protocolPatternPart = '?';
|
|
|
|
if ($requireProtocol) {
|
|
$protocolPatternPart = '';
|
|
}
|
|
|
|
return sprintf('%s%s%s', $urlProtocol, $protocolPatternPart, $urlDomain);
|
|
}
|
|
|
|
/**
|
|
* Returns information if given path is sub-path of another path, e.g. path file is owned by path of directory
|
|
*
|
|
* @param string $subPath Path to verify, probably sub-path
|
|
* @param string $path Main / parent path
|
|
* @return bool
|
|
*/
|
|
public static function isSubPathOf($subPath, $path)
|
|
{
|
|
/*
|
|
* Empty path?
|
|
* Nothing to do
|
|
*/
|
|
if (empty($path) || empty($subPath)) {
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
* I have to escape all slashes (directory separators): "/" -> "\/"
|
|
*/
|
|
$prepared = preg_quote($path, '/');
|
|
|
|
/*
|
|
* Slash at the ending is optional
|
|
*/
|
|
if (self::endsWith($path, '/')) {
|
|
$prepared .= '?';
|
|
}
|
|
|
|
$pattern = sprintf('/^%s.*/', $prepared);
|
|
|
|
return (bool)preg_match($pattern, $subPath);
|
|
}
|
|
|
|
/**
|
|
* Returns pattern used to validate / verify letter or digit
|
|
*
|
|
* @return string
|
|
*/
|
|
public static function getLetterOrDigitPattern()
|
|
{
|
|
return self::$patterns['letterOrDigit'];
|
|
}
|
|
|
|
/**
|
|
* Returns information if given character is a letter or digit
|
|
*
|
|
* @param string $char Character to check
|
|
* @return bool
|
|
*/
|
|
public static function isLetterOrDigit($char)
|
|
{
|
|
$pattern = self::getLetterOrDigitPattern();
|
|
|
|
return is_scalar($char) && (bool)preg_match($pattern, $char);
|
|
}
|
|
|
|
/**
|
|
* Returns information if the string starts with given beginning / characters
|
|
*
|
|
* @param string $string String to check
|
|
* @param string $beginning The beginning of string, one or more characters
|
|
* @return bool
|
|
*/
|
|
public static function startsWith($string, $beginning)
|
|
{
|
|
if (!empty($string) && !empty($beginning)) {
|
|
if (1 == strlen($beginning) && !self::isLetterOrDigit($beginning)) {
|
|
$beginning = '\\' . $beginning;
|
|
}
|
|
|
|
$pattern = sprintf('|^%s|', $beginning);
|
|
|
|
return (bool)preg_match($pattern, $string);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Returns information if the string ends with given ending / characters
|
|
*
|
|
* @param string $string String to check
|
|
* @param string $ending The ending of string, one or more characters
|
|
* @return bool
|
|
*/
|
|
public static function endsWith($string, $ending)
|
|
{
|
|
if (1 == strlen($ending) && !self::isLetterOrDigit($ending)) {
|
|
$ending = '\\' . $ending;
|
|
}
|
|
|
|
return (bool)preg_match('|' . $ending . '$|', $string);
|
|
}
|
|
|
|
/**
|
|
* Returns information if the string starts with directory's separator
|
|
*
|
|
* @param string $string String that may contain a directory's separator at the start / beginning
|
|
* @param string $separator (optional) The directory's separator, e.g. "/". If is empty (not provided), system's
|
|
* separator is used.
|
|
* @return bool
|
|
*/
|
|
public static function startsWithDirectorySeparator($string, $separator = '')
|
|
{
|
|
if (empty($separator)) {
|
|
$separator = DIRECTORY_SEPARATOR;
|
|
}
|
|
|
|
return self::startsWith($string, $separator);
|
|
}
|
|
|
|
/**
|
|
* Returns information if the string ends with directory's separator
|
|
*
|
|
* @param string $text String that may contain a directory's separator at the end
|
|
* @param string $separator (optional) The directory's separator, e.g. "/". If is empty (not provided), system's
|
|
* separator is used.
|
|
* @return string
|
|
*/
|
|
public static function endsWithDirectorySeparator($text, $separator = '')
|
|
{
|
|
if (empty($separator)) {
|
|
$separator = DIRECTORY_SEPARATOR;
|
|
}
|
|
|
|
return self::endsWith($text, $separator);
|
|
}
|
|
|
|
/**
|
|
* Returns information if uri contains parameter
|
|
*
|
|
* @param string $uri Uri string (e.g. $_SERVER['REQUEST_URI'])
|
|
* @param string $parameterName Uri parameter name
|
|
* @return bool
|
|
*/
|
|
public static function isSetUriParameter($uri, $parameterName)
|
|
{
|
|
return (bool)preg_match('|[?&]{1}' . $parameterName . '=|', $uri); // e.g. ?name=phil&type=4 -> '$type='
|
|
}
|
|
|
|
/**
|
|
* Returns pattern used to validate / verify html entity
|
|
*
|
|
* @return string
|
|
*/
|
|
public static function getHtmlEntityPattern()
|
|
{
|
|
return self::$patterns['htmlEntity'];
|
|
}
|
|
|
|
/**
|
|
* Returns information if the string contains html entities
|
|
*
|
|
* @param string $string String to check
|
|
* @return bool
|
|
*/
|
|
public static function containsEntities($string)
|
|
{
|
|
$pattern = self::getHtmlEntityPattern();
|
|
|
|
return (bool)preg_match_all($pattern, $string);
|
|
}
|
|
|
|
/**
|
|
* Returns information if one string contains another string
|
|
*
|
|
* @param string $haystack The string to search in
|
|
* @param string $needle The string to be search for
|
|
* @return bool
|
|
*/
|
|
public static function contains($haystack, $needle)
|
|
{
|
|
if (1 == strlen($needle) && !self::isLetterOrDigit($needle)) {
|
|
$needle = '\\' . $needle;
|
|
}
|
|
|
|
return (bool)preg_match('|.*' . $needle . '.*|', $haystack);
|
|
}
|
|
|
|
/**
|
|
* Returns pattern used to validate / verify name of file
|
|
*
|
|
* @return string
|
|
*/
|
|
public static function getFileNamePattern()
|
|
{
|
|
return self::$patterns['fileName'];
|
|
}
|
|
|
|
/**
|
|
* Returns information if given name of file is a really name of file.
|
|
* Verifies if given name contains a dot and an extension, e.g. "My File 001.jpg".
|
|
*
|
|
* @param string $fileName Name of file to check. It may be path of file also.
|
|
* @return bool
|
|
*/
|
|
public static function isFileName($fileName)
|
|
{
|
|
$pattern = self::getFileNamePattern();
|
|
|
|
return (bool)preg_match($pattern, $fileName);
|
|
}
|
|
|
|
/**
|
|
* Returns pattern used to validate / verify if value is quoted (by apostrophes or quotation marks)
|
|
*
|
|
* @return string
|
|
*/
|
|
public static function getIsQuotedPattern()
|
|
{
|
|
return self::$patterns['isQuoted'];
|
|
}
|
|
|
|
/**
|
|
* Returns information if given value is quoted (by apostrophes or quotation marks)
|
|
*
|
|
* @param mixed $value The value to check
|
|
* @return bool
|
|
*/
|
|
public static function isQuoted($value)
|
|
{
|
|
$pattern = self::getIsQuotedPattern();
|
|
|
|
return is_scalar($value) && (bool)preg_match($pattern, $value);
|
|
}
|
|
|
|
/**
|
|
* Returns pattern used to validate / verify if given path is a Windows-based path, e.g. "C:\path\to\file.jpg"
|
|
*
|
|
* @return string
|
|
*/
|
|
public static function getWindowsBasedPathPattern()
|
|
{
|
|
return self::$patterns['windowsBasedPath'];
|
|
}
|
|
|
|
/**
|
|
* Returns information if given path is a Windows-based path, e.g. "C:\path\to\file.jpg"
|
|
*
|
|
* @param string $path The path to verify
|
|
* @return bool
|
|
*/
|
|
public static function isWindowsBasedPath($path)
|
|
{
|
|
$pattern = self::getWindowsBasedPathPattern();
|
|
|
|
return (bool)preg_match($pattern, $path);
|
|
}
|
|
|
|
/**
|
|
* Returns information if given NIP number is valid
|
|
*
|
|
* @param string $nip A given NIP number
|
|
* @return bool
|
|
*
|
|
* @see https://pl.wikipedia.org/wiki/NIP#Znaczenie_numeru
|
|
*/
|
|
public static function isValidNip($nip)
|
|
{
|
|
$nip = preg_replace('/[^0-9]/', '', $nip);
|
|
|
|
$invalidNips = [
|
|
'1234567890',
|
|
'0000000000',
|
|
];
|
|
|
|
if (!preg_match('/^[0-9]{10}$/', $nip) || in_array($nip, $invalidNips)) {
|
|
return false;
|
|
}
|
|
|
|
$sum = 0;
|
|
$weights = [
|
|
6,
|
|
5,
|
|
7,
|
|
2,
|
|
3,
|
|
4,
|
|
5,
|
|
6,
|
|
7,
|
|
];
|
|
|
|
for ($i = 0; $i < 9; ++$i) {
|
|
$sum += $weights[$i] * $nip[$i];
|
|
}
|
|
|
|
$modulo = $sum % 11;
|
|
$numberControl = (10 == $modulo) ? 0 : $modulo;
|
|
|
|
return $numberControl == $nip[9];
|
|
}
|
|
|
|
/**
|
|
* Returns pattern used to validate / verify if given value is money-related value
|
|
*
|
|
* @return string
|
|
*/
|
|
public static function getMoneyPattern()
|
|
{
|
|
return self::$patterns['money'];
|
|
}
|
|
|
|
/**
|
|
* Returns information if given value is valid money-related value
|
|
*
|
|
* @param mixed $value Value to verify
|
|
* @return bool
|
|
*/
|
|
public static function isValidMoneyValue($value)
|
|
{
|
|
$pattern = self::getMoneyPattern();
|
|
|
|
return (bool)preg_match($pattern, $value);
|
|
}
|
|
|
|
/**
|
|
* Returns valid given hexadecimal value of color.
|
|
* If the value is invalid, throws an exception or returns false.
|
|
*
|
|
* @param string $color Color to verify
|
|
* @param bool $throwException (optional) If is set to true, throws an exception if given color is invalid
|
|
* (default behaviour). Otherwise - not.
|
|
* @return string|bool
|
|
*
|
|
* @throws IncorrectColorHexLengthException
|
|
* @throws InvalidColorHexValueException
|
|
*/
|
|
public static function getValidColorHexValue($color, $throwException = true)
|
|
{
|
|
$color = Miscellaneous::replace($color, '/#/', '');
|
|
$length = strlen($color);
|
|
|
|
if (3 === $length) {
|
|
$color = Miscellaneous::replace($color, '/(.)(.)(.)/', '$1$1$2$2$3$3');
|
|
} else {
|
|
if (6 !== $length) {
|
|
if ($throwException) {
|
|
throw new IncorrectColorHexLengthException($color);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}
|
|
|
|
$pattern = self::$patterns['color'];
|
|
$match = (bool)preg_match($pattern, $color);
|
|
|
|
if (!$match) {
|
|
if ($throwException) {
|
|
throw new InvalidColorHexValueException($color);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
return strtolower($color);
|
|
}
|
|
|
|
/**
|
|
* Returns information if given name of bundle is valid
|
|
*
|
|
* @param string $bundleName Full name of bundle to verify, e.g. "MyExtraBundle"
|
|
* @return bool
|
|
*/
|
|
public static function isValidBundleName($bundleName)
|
|
{
|
|
if (!is_string($bundleName)) {
|
|
return false;
|
|
}
|
|
|
|
$pattern = self::getBundleNamePattern();
|
|
|
|
return (bool)preg_match($pattern, $bundleName);
|
|
}
|
|
|
|
/**
|
|
* Returns pattern used to validate / verify name of bundle
|
|
*
|
|
* @return string
|
|
*/
|
|
public static function getBundleNamePattern()
|
|
{
|
|
return self::$patterns['bundleName'];
|
|
}
|
|
}
|