1 <?php 2 3 /** 4 * Assert 5 * 6 * LICENSE 7 * 8 * This source file is subject to the MIT license that is bundled 9 * with this package in the file LICENSE.txt. 10 * If you did not receive a copy of the license and are unable to 11 * obtain it through the world-wide-web, please send an email 12 * to kontakt@beberlei.de so I can send you a copy immediately. 13 */ 14 15 namespace Assert; 16 17 use ArrayAccess; 18 use BadMethodCallException; 19 use Countable; 20 use DateTime; 21 use ReflectionClass; 22 use ReflectionException; 23 use ResourceBundle; 24 use SimpleXMLElement; 25 use Throwable; 26 use Traversable; 27 28 /** 29 * Assert library. 30 * 31 * @author Benjamin Eberlei <kontakt@beberlei.de> 32 * 33 * @method static bool allAlnum(mixed $value, string|callable $message = null, string $propertyPath = null) Assert that value is alphanumeric for all values. 34 * @method static bool allBase64(string $value, string|callable $message = null, string $propertyPath = null) Assert that a constant is defined for all values. 35 * @method static bool allBetween(mixed $value, mixed $lowerLimit, mixed $upperLimit, string|callable $message = null, string $propertyPath = null) Assert that a value is greater or equal than a lower limit, and less than or equal to an upper limit for all values. 36 * @method static bool allBetweenExclusive(mixed $value, mixed $lowerLimit, mixed $upperLimit, string|callable $message = null, string $propertyPath = null) Assert that a value is greater than a lower limit, and less than an upper limit for all values. 37 * @method static bool allBetweenLength(mixed $value, int $minLength, int $maxLength, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string length is between min and max lengths for all values. 38 * @method static bool allBoolean(mixed $value, string|callable $message = null, string $propertyPath = null) Assert that value is php boolean for all values. 39 * @method static bool allChoice(mixed $value, array $choices, string|callable $message = null, string $propertyPath = null) Assert that value is in array of choices for all values. 40 * @method static bool allChoicesNotEmpty(array $values, array $choices, string|callable $message = null, string $propertyPath = null) Determines if the values array has every choice as key and that this choice has content for all values. 41 * @method static bool allClassExists(mixed $value, string|callable $message = null, string $propertyPath = null) Assert that the class exists for all values. 42 * @method static bool allContains(mixed $string, string $needle, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string contains a sequence of chars for all values. 43 * @method static bool allCount(array|Countable|ResourceBundle|SimpleXMLElement $countable, int $count, string|callable $message = null, string $propertyPath = null) Assert that the count of countable is equal to count for all values. 44 * @method static bool allDate(string $value, string $format, string|callable $message = null, string $propertyPath = null) Assert that date is valid and corresponds to the given format for all values. 45 * @method static bool allDefined(mixed $constant, string|callable $message = null, string $propertyPath = null) Assert that a constant is defined for all values. 46 * @method static bool allDigit(mixed $value, string|callable $message = null, string $propertyPath = null) Validates if an integer or integerish is a digit for all values. 47 * @method static bool allDirectory(string $value, string|callable $message = null, string $propertyPath = null) Assert that a directory exists for all values. 48 * @method static bool allE164(string $value, string|callable $message = null, string $propertyPath = null) Assert that the given string is a valid E164 Phone Number for all values. 49 * @method static bool allEmail(mixed $value, string|callable $message = null, string $propertyPath = null) Assert that value is an email address (using input_filter/FILTER_VALIDATE_EMAIL) for all values. 50 * @method static bool allEndsWith(mixed $string, string $needle, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string ends with a sequence of chars for all values. 51 * @method static bool allEq(mixed $value, mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that two values are equal (using ==) for all values. 52 * @method static bool allEqArraySubset(mixed $value, mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that the array contains the subset for all values. 53 * @method static bool allExtensionLoaded(mixed $value, string|callable $message = null, string $propertyPath = null) Assert that extension is loaded for all values. 54 * @method static bool allExtensionVersion(string $extension, string $operator, mixed $version, string|callable $message = null, string $propertyPath = null) Assert that extension is loaded and a specific version is installed for all values. 55 * @method static bool allFalse(mixed $value, string|callable $message = null, string $propertyPath = null) Assert that the value is boolean False for all values. 56 * @method static bool allFile(string $value, string|callable $message = null, string $propertyPath = null) Assert that a file exists for all values. 57 * @method static bool allFloat(mixed $value, string|callable $message = null, string $propertyPath = null) Assert that value is a php float for all values. 58 * @method static bool allGreaterOrEqualThan(mixed $value, mixed $limit, string|callable $message = null, string $propertyPath = null) Determines if the value is greater or equal than given limit for all values. 59 * @method static bool allGreaterThan(mixed $value, mixed $limit, string|callable $message = null, string $propertyPath = null) Determines if the value is greater than given limit for all values. 60 * @method static bool allImplementsInterface(mixed $class, string $interfaceName, string|callable $message = null, string $propertyPath = null) Assert that the class implements the interface for all values. 61 * @method static bool allInArray(mixed $value, array $choices, string|callable $message = null, string $propertyPath = null) Assert that value is in array of choices. This is an alias of Assertion::choice() for all values. 62 * @method static bool allInteger(mixed $value, string|callable $message = null, string $propertyPath = null) Assert that value is a php integer for all values. 63 * @method static bool allIntegerish(mixed $value, string|callable $message = null, string $propertyPath = null) Assert that value is a php integer'ish for all values. 64 * @method static bool allInterfaceExists(mixed $value, string|callable $message = null, string $propertyPath = null) Assert that the interface exists for all values. 65 * @method static bool allIp(string $value, int $flag = null, string|callable $message = null, string $propertyPath = null) Assert that value is an IPv4 or IPv6 address for all values. 66 * @method static bool allIpv4(string $value, int $flag = null, string|callable $message = null, string $propertyPath = null) Assert that value is an IPv4 address for all values. 67 * @method static bool allIpv6(string $value, int $flag = null, string|callable $message = null, string $propertyPath = null) Assert that value is an IPv6 address for all values. 68 * @method static bool allIsArray(mixed $value, string|callable $message = null, string $propertyPath = null) Assert that value is an array for all values. 69 * @method static bool allIsArrayAccessible(mixed $value, string|callable $message = null, string $propertyPath = null) Assert that value is an array or an array-accessible object for all values. 70 * @method static bool allIsCallable(mixed $value, string|callable $message = null, string $propertyPath = null) Determines that the provided value is callable for all values. 71 * @method static bool allIsCountable(array|Countable|ResourceBundle|SimpleXMLElement $value, string|callable $message = null, string $propertyPath = null) Assert that value is countable for all values. 72 * @method static bool allIsInstanceOf(mixed $value, string $className, string|callable $message = null, string $propertyPath = null) Assert that value is instance of given class-name for all values. 73 * @method static bool allIsJsonString(mixed $value, string|callable $message = null, string $propertyPath = null) Assert that the given string is a valid json string for all values. 74 * @method static bool allIsObject(mixed $value, string|callable $message = null, string $propertyPath = null) Determines that the provided value is an object for all values. 75 * @method static bool allIsResource(mixed $value, string|callable $message = null, string $propertyPath = null) Assert that value is a resource for all values. 76 * @method static bool allIsTraversable(mixed $value, string|callable $message = null, string $propertyPath = null) Assert that value is an array or a traversable object for all values. 77 * @method static bool allKeyExists(mixed $value, string|int $key, string|callable $message = null, string $propertyPath = null) Assert that key exists in an array for all values. 78 * @method static bool allKeyIsset(mixed $value, string|int $key, string|callable $message = null, string $propertyPath = null) Assert that key exists in an array/array-accessible object using isset() for all values. 79 * @method static bool allKeyNotExists(mixed $value, string|int $key, string|callable $message = null, string $propertyPath = null) Assert that key does not exist in an array for all values. 80 * @method static bool allLength(mixed $value, int $length, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string has a given length for all values. 81 * @method static bool allLessOrEqualThan(mixed $value, mixed $limit, string|callable $message = null, string $propertyPath = null) Determines if the value is less or equal than given limit for all values. 82 * @method static bool allLessThan(mixed $value, mixed $limit, string|callable $message = null, string $propertyPath = null) Determines if the value is less than given limit for all values. 83 * @method static bool allMax(mixed $value, mixed $maxValue, string|callable $message = null, string $propertyPath = null) Assert that a number is smaller as a given limit for all values. 84 * @method static bool allMaxCount(array|Countable|ResourceBundle|SimpleXMLElement $countable, int $count, string|callable $message = null, string $propertyPath = null) Assert that the countable have at most $count elements for all values. 85 * @method static bool allMaxLength(mixed $value, int $maxLength, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string value is not longer than $maxLength chars for all values. 86 * @method static bool allMethodExists(string $value, mixed $object, string|callable $message = null, string $propertyPath = null) Determines that the named method is defined in the provided object for all values. 87 * @method static bool allMin(mixed $value, mixed $minValue, string|callable $message = null, string $propertyPath = null) Assert that a value is at least as big as a given limit for all values. 88 * @method static bool allMinCount(array|Countable|ResourceBundle|SimpleXMLElement $countable, int $count, string|callable $message = null, string $propertyPath = null) Assert that the countable have at least $count elements for all values. 89 * @method static bool allMinLength(mixed $value, int $minLength, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that a string is at least $minLength chars long for all values. 90 * @method static bool allNoContent(mixed $value, string|callable $message = null, string $propertyPath = null) Assert that value is empty for all values. 91 * @method static bool allNotBlank(mixed $value, string|callable $message = null, string $propertyPath = null) Assert that value is not blank for all values. 92 * @method static bool allNotContains(mixed $string, string $needle, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string does not contains a sequence of chars for all values. 93 * @method static bool allNotEmpty(mixed $value, string|callable $message = null, string $propertyPath = null) Assert that value is not empty for all values. 94 * @method static bool allNotEmptyKey(mixed $value, string|int $key, string|callable $message = null, string $propertyPath = null) Assert that key exists in an array/array-accessible object and its value is not empty for all values. 95 * @method static bool allNotEq(mixed $value1, mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that two values are not equal (using ==) for all values. 96 * @method static bool allNotInArray(mixed $value, array $choices, string|callable $message = null, string $propertyPath = null) Assert that value is not in array of choices for all values. 97 * @method static bool allNotIsInstanceOf(mixed $value, string $className, string|callable $message = null, string $propertyPath = null) Assert that value is not instance of given class-name for all values. 98 * @method static bool allNotNull(mixed $value, string|callable $message = null, string $propertyPath = null) Assert that value is not null for all values. 99 * @method static bool allNotRegex(mixed $value, string $pattern, string|callable $message = null, string $propertyPath = null) Assert that value does not match a regex for all values. 100 * @method static bool allNotSame(mixed $value1, mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that two values are not the same (using ===) for all values. 101 * @method static bool allNull(mixed $value, string|callable $message = null, string $propertyPath = null) Assert that value is null for all values. 102 * @method static bool allNumeric(mixed $value, string|callable $message = null, string $propertyPath = null) Assert that value is numeric for all values. 103 * @method static bool allObjectOrClass(mixed $value, string|callable $message = null, string $propertyPath = null) Assert that the value is an object, or a class that exists for all values. 104 * @method static bool allPhpVersion(string $operator, mixed $version, string|callable $message = null, string $propertyPath = null) Assert on PHP version for all values. 105 * @method static bool allPropertiesExist(mixed $value, array $properties, string|callable $message = null, string $propertyPath = null) Assert that the value is an object or class, and that the properties all exist for all values. 106 * @method static bool allPropertyExists(mixed $value, string $property, string|callable $message = null, string $propertyPath = null) Assert that the value is an object or class, and that the property exists for all values. 107 * @method static bool allRange(mixed $value, mixed $minValue, mixed $maxValue, string|callable $message = null, string $propertyPath = null) Assert that value is in range of numbers for all values. 108 * @method static bool allReadable(string $value, string|callable $message = null, string $propertyPath = null) Assert that the value is something readable for all values. 109 * @method static bool allRegex(mixed $value, string $pattern, string|callable $message = null, string $propertyPath = null) Assert that value matches a regex for all values. 110 * @method static bool allSame(mixed $value, mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that two values are the same (using ===) for all values. 111 * @method static bool allSatisfy(mixed $value, callable $callback, string|callable $message = null, string $propertyPath = null) Assert that the provided value is valid according to a callback for all values. 112 * @method static bool allScalar(mixed $value, string|callable $message = null, string $propertyPath = null) Assert that value is a PHP scalar for all values. 113 * @method static bool allStartsWith(mixed $string, string $needle, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string starts with a sequence of chars for all values. 114 * @method static bool allString(mixed $value, string|callable $message = null, string $propertyPath = null) Assert that value is a string for all values. 115 * @method static bool allSubclassOf(mixed $value, string $className, string|callable $message = null, string $propertyPath = null) Assert that value is subclass of given class-name for all values. 116 * @method static bool allTrue(mixed $value, string|callable $message = null, string $propertyPath = null) Assert that the value is boolean True for all values. 117 * @method static bool allUrl(mixed $value, string|callable $message = null, string $propertyPath = null) Assert that value is an URL for all values. 118 * @method static bool allUuid(string $value, string|callable $message = null, string $propertyPath = null) Assert that the given string is a valid UUID for all values. 119 * @method static bool allVersion(string $version1, string $operator, string $version2, string|callable $message = null, string $propertyPath = null) Assert comparison of two versions for all values. 120 * @method static bool allWriteable(string $value, string|callable $message = null, string $propertyPath = null) Assert that the value is something writeable for all values. 121 * @method static bool nullOrAlnum(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is alphanumeric or that the value is null. 122 * @method static bool nullOrBase64(string|null $value, string|callable $message = null, string $propertyPath = null) Assert that a constant is defined or that the value is null. 123 * @method static bool nullOrBetween(mixed|null $value, mixed $lowerLimit, mixed $upperLimit, string|callable $message = null, string $propertyPath = null) Assert that a value is greater or equal than a lower limit, and less than or equal to an upper limit or that the value is null. 124 * @method static bool nullOrBetweenExclusive(mixed|null $value, mixed $lowerLimit, mixed $upperLimit, string|callable $message = null, string $propertyPath = null) Assert that a value is greater than a lower limit, and less than an upper limit or that the value is null. 125 * @method static bool nullOrBetweenLength(mixed|null $value, int $minLength, int $maxLength, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string length is between min and max lengths or that the value is null. 126 * @method static bool nullOrBoolean(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is php boolean or that the value is null. 127 * @method static bool nullOrChoice(mixed|null $value, array $choices, string|callable $message = null, string $propertyPath = null) Assert that value is in array of choices or that the value is null. 128 * @method static bool nullOrChoicesNotEmpty(array|null $values, array $choices, string|callable $message = null, string $propertyPath = null) Determines if the values array has every choice as key and that this choice has content or that the value is null. 129 * @method static bool nullOrClassExists(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that the class exists or that the value is null. 130 * @method static bool nullOrContains(mixed|null $string, string $needle, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string contains a sequence of chars or that the value is null. 131 * @method static bool nullOrCount(array|Countable|ResourceBundle|SimpleXMLElement|null $countable, int $count, string|callable $message = null, string $propertyPath = null) Assert that the count of countable is equal to count or that the value is null. 132 * @method static bool nullOrDate(string|null $value, string $format, string|callable $message = null, string $propertyPath = null) Assert that date is valid and corresponds to the given format or that the value is null. 133 * @method static bool nullOrDefined(mixed|null $constant, string|callable $message = null, string $propertyPath = null) Assert that a constant is defined or that the value is null. 134 * @method static bool nullOrDigit(mixed|null $value, string|callable $message = null, string $propertyPath = null) Validates if an integer or integerish is a digit or that the value is null. 135 * @method static bool nullOrDirectory(string|null $value, string|callable $message = null, string $propertyPath = null) Assert that a directory exists or that the value is null. 136 * @method static bool nullOrE164(string|null $value, string|callable $message = null, string $propertyPath = null) Assert that the given string is a valid E164 Phone Number or that the value is null. 137 * @method static bool nullOrEmail(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is an email address (using input_filter/FILTER_VALIDATE_EMAIL) or that the value is null. 138 * @method static bool nullOrEndsWith(mixed|null $string, string $needle, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string ends with a sequence of chars or that the value is null. 139 * @method static bool nullOrEq(mixed|null $value, mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that two values are equal (using ==) or that the value is null. 140 * @method static bool nullOrEqArraySubset(mixed|null $value, mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that the array contains the subset or that the value is null. 141 * @method static bool nullOrExtensionLoaded(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that extension is loaded or that the value is null. 142 * @method static bool nullOrExtensionVersion(string|null $extension, string $operator, mixed $version, string|callable $message = null, string $propertyPath = null) Assert that extension is loaded and a specific version is installed or that the value is null. 143 * @method static bool nullOrFalse(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that the value is boolean False or that the value is null. 144 * @method static bool nullOrFile(string|null $value, string|callable $message = null, string $propertyPath = null) Assert that a file exists or that the value is null. 145 * @method static bool nullOrFloat(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is a php float or that the value is null. 146 * @method static bool nullOrGreaterOrEqualThan(mixed|null $value, mixed $limit, string|callable $message = null, string $propertyPath = null) Determines if the value is greater or equal than given limit or that the value is null. 147 * @method static bool nullOrGreaterThan(mixed|null $value, mixed $limit, string|callable $message = null, string $propertyPath = null) Determines if the value is greater than given limit or that the value is null. 148 * @method static bool nullOrImplementsInterface(mixed|null $class, string $interfaceName, string|callable $message = null, string $propertyPath = null) Assert that the class implements the interface or that the value is null. 149 * @method static bool nullOrInArray(mixed|null $value, array $choices, string|callable $message = null, string $propertyPath = null) Assert that value is in array of choices. This is an alias of Assertion::choice() or that the value is null. 150 * @method static bool nullOrInteger(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is a php integer or that the value is null. 151 * @method static bool nullOrIntegerish(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is a php integer'ish or that the value is null. 152 * @method static bool nullOrInterfaceExists(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that the interface exists or that the value is null. 153 * @method static bool nullOrIp(string|null $value, int $flag = null, string|callable $message = null, string $propertyPath = null) Assert that value is an IPv4 or IPv6 address or that the value is null. 154 * @method static bool nullOrIpv4(string|null $value, int $flag = null, string|callable $message = null, string $propertyPath = null) Assert that value is an IPv4 address or that the value is null. 155 * @method static bool nullOrIpv6(string|null $value, int $flag = null, string|callable $message = null, string $propertyPath = null) Assert that value is an IPv6 address or that the value is null. 156 * @method static bool nullOrIsArray(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is an array or that the value is null. 157 * @method static bool nullOrIsArrayAccessible(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is an array or an array-accessible object or that the value is null. 158 * @method static bool nullOrIsCallable(mixed|null $value, string|callable $message = null, string $propertyPath = null) Determines that the provided value is callable or that the value is null. 159 * @method static bool nullOrIsCountable(array|Countable|ResourceBundle|SimpleXMLElement|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is countable or that the value is null. 160 * @method static bool nullOrIsInstanceOf(mixed|null $value, string $className, string|callable $message = null, string $propertyPath = null) Assert that value is instance of given class-name or that the value is null. 161 * @method static bool nullOrIsJsonString(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that the given string is a valid json string or that the value is null. 162 * @method static bool nullOrIsObject(mixed|null $value, string|callable $message = null, string $propertyPath = null) Determines that the provided value is an object or that the value is null. 163 * @method static bool nullOrIsResource(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is a resource or that the value is null. 164 * @method static bool nullOrIsTraversable(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is an array or a traversable object or that the value is null. 165 * @method static bool nullOrKeyExists(mixed|null $value, string|int $key, string|callable $message = null, string $propertyPath = null) Assert that key exists in an array or that the value is null. 166 * @method static bool nullOrKeyIsset(mixed|null $value, string|int $key, string|callable $message = null, string $propertyPath = null) Assert that key exists in an array/array-accessible object using isset() or that the value is null. 167 * @method static bool nullOrKeyNotExists(mixed|null $value, string|int $key, string|callable $message = null, string $propertyPath = null) Assert that key does not exist in an array or that the value is null. 168 * @method static bool nullOrLength(mixed|null $value, int $length, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string has a given length or that the value is null. 169 * @method static bool nullOrLessOrEqualThan(mixed|null $value, mixed $limit, string|callable $message = null, string $propertyPath = null) Determines if the value is less or equal than given limit or that the value is null. 170 * @method static bool nullOrLessThan(mixed|null $value, mixed $limit, string|callable $message = null, string $propertyPath = null) Determines if the value is less than given limit or that the value is null. 171 * @method static bool nullOrMax(mixed|null $value, mixed $maxValue, string|callable $message = null, string $propertyPath = null) Assert that a number is smaller as a given limit or that the value is null. 172 * @method static bool nullOrMaxCount(array|Countable|ResourceBundle|SimpleXMLElement|null $countable, int $count, string|callable $message = null, string $propertyPath = null) Assert that the countable have at most $count elements or that the value is null. 173 * @method static bool nullOrMaxLength(mixed|null $value, int $maxLength, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string value is not longer than $maxLength chars or that the value is null. 174 * @method static bool nullOrMethodExists(string|null $value, mixed $object, string|callable $message = null, string $propertyPath = null) Determines that the named method is defined in the provided object or that the value is null. 175 * @method static bool nullOrMin(mixed|null $value, mixed $minValue, string|callable $message = null, string $propertyPath = null) Assert that a value is at least as big as a given limit or that the value is null. 176 * @method static bool nullOrMinCount(array|Countable|ResourceBundle|SimpleXMLElement|null $countable, int $count, string|callable $message = null, string $propertyPath = null) Assert that the countable have at least $count elements or that the value is null. 177 * @method static bool nullOrMinLength(mixed|null $value, int $minLength, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that a string is at least $minLength chars long or that the value is null. 178 * @method static bool nullOrNoContent(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is empty or that the value is null. 179 * @method static bool nullOrNotBlank(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is not blank or that the value is null. 180 * @method static bool nullOrNotContains(mixed|null $string, string $needle, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string does not contains a sequence of chars or that the value is null. 181 * @method static bool nullOrNotEmpty(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is not empty or that the value is null. 182 * @method static bool nullOrNotEmptyKey(mixed|null $value, string|int $key, string|callable $message = null, string $propertyPath = null) Assert that key exists in an array/array-accessible object and its value is not empty or that the value is null. 183 * @method static bool nullOrNotEq(mixed|null $value1, mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that two values are not equal (using ==) or that the value is null. 184 * @method static bool nullOrNotInArray(mixed|null $value, array $choices, string|callable $message = null, string $propertyPath = null) Assert that value is not in array of choices or that the value is null. 185 * @method static bool nullOrNotIsInstanceOf(mixed|null $value, string $className, string|callable $message = null, string $propertyPath = null) Assert that value is not instance of given class-name or that the value is null. 186 * @method static bool nullOrNotNull(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is not null or that the value is null. 187 * @method static bool nullOrNotRegex(mixed|null $value, string $pattern, string|callable $message = null, string $propertyPath = null) Assert that value does not match a regex or that the value is null. 188 * @method static bool nullOrNotSame(mixed|null $value1, mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that two values are not the same (using ===) or that the value is null. 189 * @method static bool nullOrNull(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is null or that the value is null. 190 * @method static bool nullOrNumeric(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is numeric or that the value is null. 191 * @method static bool nullOrObjectOrClass(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that the value is an object, or a class that exists or that the value is null. 192 * @method static bool nullOrPhpVersion(string|null $operator, mixed $version, string|callable $message = null, string $propertyPath = null) Assert on PHP version or that the value is null. 193 * @method static bool nullOrPropertiesExist(mixed|null $value, array $properties, string|callable $message = null, string $propertyPath = null) Assert that the value is an object or class, and that the properties all exist or that the value is null. 194 * @method static bool nullOrPropertyExists(mixed|null $value, string $property, string|callable $message = null, string $propertyPath = null) Assert that the value is an object or class, and that the property exists or that the value is null. 195 * @method static bool nullOrRange(mixed|null $value, mixed $minValue, mixed $maxValue, string|callable $message = null, string $propertyPath = null) Assert that value is in range of numbers or that the value is null. 196 * @method static bool nullOrReadable(string|null $value, string|callable $message = null, string $propertyPath = null) Assert that the value is something readable or that the value is null. 197 * @method static bool nullOrRegex(mixed|null $value, string $pattern, string|callable $message = null, string $propertyPath = null) Assert that value matches a regex or that the value is null. 198 * @method static bool nullOrSame(mixed|null $value, mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that two values are the same (using ===) or that the value is null. 199 * @method static bool nullOrSatisfy(mixed|null $value, callable $callback, string|callable $message = null, string $propertyPath = null) Assert that the provided value is valid according to a callback or that the value is null. 200 * @method static bool nullOrScalar(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is a PHP scalar or that the value is null. 201 * @method static bool nullOrStartsWith(mixed|null $string, string $needle, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string starts with a sequence of chars or that the value is null. 202 * @method static bool nullOrString(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is a string or that the value is null. 203 * @method static bool nullOrSubclassOf(mixed|null $value, string $className, string|callable $message = null, string $propertyPath = null) Assert that value is subclass of given class-name or that the value is null. 204 * @method static bool nullOrTrue(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that the value is boolean True or that the value is null. 205 * @method static bool nullOrUrl(mixed|null $value, string|callable $message = null, string $propertyPath = null) Assert that value is an URL or that the value is null. 206 * @method static bool nullOrUuid(string|null $value, string|callable $message = null, string $propertyPath = null) Assert that the given string is a valid UUID or that the value is null. 207 * @method static bool nullOrVersion(string|null $version1, string $operator, string $version2, string|callable $message = null, string $propertyPath = null) Assert comparison of two versions or that the value is null. 208 * @method static bool nullOrWriteable(string|null $value, string|callable $message = null, string $propertyPath = null) Assert that the value is something writeable or that the value is null. 209 */ 210 class Assertion 211 { 212 const INVALID_FLOAT = 9; 213 const INVALID_INTEGER = 10; 214 const INVALID_DIGIT = 11; 215 const INVALID_INTEGERISH = 12; 216 const INVALID_BOOLEAN = 13; 217 const VALUE_EMPTY = 14; 218 const VALUE_NULL = 15; 219 const VALUE_NOT_NULL = 25; 220 const INVALID_STRING = 16; 221 const INVALID_REGEX = 17; 222 const INVALID_MIN_LENGTH = 18; 223 const INVALID_MAX_LENGTH = 19; 224 const INVALID_STRING_START = 20; 225 const INVALID_STRING_CONTAINS = 21; 226 const INVALID_CHOICE = 22; 227 const INVALID_NUMERIC = 23; 228 const INVALID_ARRAY = 24; 229 const INVALID_KEY_EXISTS = 26; 230 const INVALID_NOT_BLANK = 27; 231 const INVALID_INSTANCE_OF = 28; 232 const INVALID_SUBCLASS_OF = 29; 233 const INVALID_RANGE = 30; 234 const INVALID_ALNUM = 31; 235 const INVALID_TRUE = 32; 236 const INVALID_EQ = 33; 237 const INVALID_SAME = 34; 238 const INVALID_MIN = 35; 239 const INVALID_MAX = 36; 240 const INVALID_LENGTH = 37; 241 const INVALID_FALSE = 38; 242 const INVALID_STRING_END = 39; 243 const INVALID_UUID = 40; 244 const INVALID_COUNT = 41; 245 const INVALID_NOT_EQ = 42; 246 const INVALID_NOT_SAME = 43; 247 const INVALID_TRAVERSABLE = 44; 248 const INVALID_ARRAY_ACCESSIBLE = 45; 249 const INVALID_KEY_ISSET = 46; 250 const INVALID_VALUE_IN_ARRAY = 47; 251 const INVALID_E164 = 48; 252 const INVALID_BASE64 = 49; 253 const INVALID_NOT_REGEX = 50; 254 const INVALID_DIRECTORY = 101; 255 const INVALID_FILE = 102; 256 const INVALID_READABLE = 103; 257 const INVALID_WRITEABLE = 104; 258 const INVALID_CLASS = 105; 259 const INVALID_INTERFACE = 106; 260 const INVALID_FILE_NOT_EXISTS = 107; 261 const INVALID_EMAIL = 201; 262 const INTERFACE_NOT_IMPLEMENTED = 202; 263 const INVALID_URL = 203; 264 const INVALID_NOT_INSTANCE_OF = 204; 265 const VALUE_NOT_EMPTY = 205; 266 const INVALID_JSON_STRING = 206; 267 const INVALID_OBJECT = 207; 268 const INVALID_METHOD = 208; 269 const INVALID_SCALAR = 209; 270 const INVALID_LESS = 210; 271 const INVALID_LESS_OR_EQUAL = 211; 272 const INVALID_GREATER = 212; 273 const INVALID_GREATER_OR_EQUAL = 213; 274 const INVALID_DATE = 214; 275 const INVALID_CALLABLE = 215; 276 const INVALID_KEY_NOT_EXISTS = 216; 277 const INVALID_SATISFY = 217; 278 const INVALID_IP = 218; 279 const INVALID_BETWEEN = 219; 280 const INVALID_BETWEEN_EXCLUSIVE = 220; 281 const INVALID_EXTENSION = 222; 282 const INVALID_CONSTANT = 221; 283 const INVALID_VERSION = 223; 284 const INVALID_PROPERTY = 224; 285 const INVALID_RESOURCE = 225; 286 const INVALID_COUNTABLE = 226; 287 const INVALID_MIN_COUNT = 227; 288 const INVALID_MAX_COUNT = 228; 289 const INVALID_STRING_NOT_CONTAINS = 229; 290 291 /** 292 * Exception to throw when an assertion failed. 293 * 294 * @var string 295 */ 296 protected static $exceptionClass = InvalidArgumentException::class; 297 298 /** 299 * Assert that two values are equal (using ==). 300 * 301 * @param mixed $value 302 * @param mixed $value2 303 * @param string|callable|null $message 304 * @param string|null $propertyPath 305 * 306 * @return bool 307 * 308 * @throws AssertionFailedException 309 */ 310 public static function eq($value, $value2, $message = null, string $propertyPath = null): bool 311 { 312 if ($value != $value2) { 313 $message = \sprintf( 314 static::generateMessage($message ?: 'Value "%s" does not equal expected value "%s".'), 315 static::stringify($value), 316 static::stringify($value2) 317 ); 318 319 throw static::createException($value, $message, static::INVALID_EQ, $propertyPath, ['expected' => $value2]); 320 } 321 322 return true; 323 } 324 325 /** 326 * Assert that the array contains the subset. 327 * 328 * @param mixed $value 329 * @param mixed $value2 330 * @param string|callable|null $message 331 * @param string|null $propertyPath 332 * 333 * @return bool 334 * 335 * @throws AssertionFailedException 336 */ 337 public static function eqArraySubset($value, $value2, $message = null, string $propertyPath = null): bool 338 { 339 static::isArray($value, $message, $propertyPath); 340 static::isArray($value2, $message, $propertyPath); 341 342 $patched = \array_replace_recursive($value, $value2); 343 static::eq($patched, $value, $message, $propertyPath); 344 345 return true; 346 } 347 348 /** 349 * Assert that two values are the same (using ===). 350 * 351 * @param mixed $value 352 * @param mixed $value2 353 * @param string|callable|null $message 354 * @param string|null $propertyPath 355 * 356 * @return bool 357 * 358 * @throws AssertionFailedException 359 */ 360 public static function same($value, $value2, $message = null, string $propertyPath = null): bool 361 { 362 if ($value !== $value2) { 363 $message = \sprintf( 364 static::generateMessage($message ?: 'Value "%s" is not the same as expected value "%s".'), 365 static::stringify($value), 366 static::stringify($value2) 367 ); 368 369 throw static::createException($value, $message, static::INVALID_SAME, $propertyPath, ['expected' => $value2]); 370 } 371 372 return true; 373 } 374 375 /** 376 * Assert that two values are not equal (using ==). 377 * 378 * @param mixed $value1 379 * @param mixed $value2 380 * @param string|callable|null $message 381 * @param string|null $propertyPath 382 * 383 * @return bool 384 * 385 * @throws AssertionFailedException 386 */ 387 public static function notEq($value1, $value2, $message = null, string $propertyPath = null): bool 388 { 389 if ($value1 == $value2) { 390 $message = \sprintf( 391 static::generateMessage($message ?: 'Value "%s" was not expected to be equal to value "%s".'), 392 static::stringify($value1), 393 static::stringify($value2) 394 ); 395 throw static::createException($value1, $message, static::INVALID_NOT_EQ, $propertyPath, ['expected' => $value2]); 396 } 397 398 return true; 399 } 400 401 /** 402 * Assert that two values are not the same (using ===). 403 * 404 * @param mixed $value1 405 * @param mixed $value2 406 * @param string|callable|null $message 407 * @param string|null $propertyPath 408 * 409 * @return bool 410 * 411 * @throws AssertionFailedException 412 */ 413 public static function notSame($value1, $value2, $message = null, string $propertyPath = null): bool 414 { 415 if ($value1 === $value2) { 416 $message = \sprintf( 417 static::generateMessage($message ?: 'Value "%s" was not expected to be the same as value "%s".'), 418 static::stringify($value1), 419 static::stringify($value2) 420 ); 421 throw static::createException($value1, $message, static::INVALID_NOT_SAME, $propertyPath, ['expected' => $value2]); 422 } 423 424 return true; 425 } 426 427 /** 428 * Assert that value is not in array of choices. 429 * 430 * @param mixed $value 431 * @param array $choices 432 * @param string|callable|null $message 433 * @param string|null $propertyPath 434 * 435 * @return bool 436 * 437 * @throws AssertionFailedException 438 */ 439 public static function notInArray($value, array $choices, $message = null, string $propertyPath = null): bool 440 { 441 if (true === \in_array($value, $choices)) { 442 $message = \sprintf( 443 static::generateMessage($message ?: 'Value "%s" was not expected to be an element of the values: %s'), 444 static::stringify($value), 445 static::stringify($choices) 446 ); 447 throw static::createException($value, $message, static::INVALID_VALUE_IN_ARRAY, $propertyPath, ['choices' => $choices]); 448 } 449 450 return true; 451 } 452 453 /** 454 * Assert that value is a php integer. 455 * 456 * @param mixed $value 457 * @param string|callable|null $message 458 * @param string|null $propertyPath 459 * 460 * @return bool 461 * 462 * @throws AssertionFailedException 463 */ 464 public static function integer($value, $message = null, string $propertyPath = null): bool 465 { 466 if (!\is_int($value)) { 467 $message = \sprintf( 468 static::generateMessage($message ?: 'Value "%s" is not an integer.'), 469 static::stringify($value) 470 ); 471 472 throw static::createException($value, $message, static::INVALID_INTEGER, $propertyPath); 473 } 474 475 return true; 476 } 477 478 /** 479 * Assert that value is a php float. 480 * 481 * @param mixed $value 482 * @param string|callable|null $message 483 * @param string|null $propertyPath 484 * 485 * @return bool 486 * 487 * @throws AssertionFailedException 488 */ 489 public static function float($value, $message = null, string $propertyPath = null): bool 490 { 491 if (!\is_float($value)) { 492 $message = \sprintf( 493 static::generateMessage($message ?: 'Value "%s" is not a float.'), 494 static::stringify($value) 495 ); 496 497 throw static::createException($value, $message, static::INVALID_FLOAT, $propertyPath); 498 } 499 500 return true; 501 } 502 503 /** 504 * Validates if an integer or integerish is a digit. 505 * 506 * @param mixed $value 507 * @param string|callable|null $message 508 * @param string|null $propertyPath 509 * 510 * @return bool 511 * 512 * @throws AssertionFailedException 513 */ 514 public static function digit($value, $message = null, string $propertyPath = null): bool 515 { 516 if (!\ctype_digit((string)$value)) { 517 $message = \sprintf( 518 static::generateMessage($message ?: 'Value "%s" is not a digit.'), 519 static::stringify($value) 520 ); 521 522 throw static::createException($value, $message, static::INVALID_DIGIT, $propertyPath); 523 } 524 525 return true; 526 } 527 528 /** 529 * Assert that value is a php integer'ish. 530 * 531 * @param mixed $value 532 * @param string|callable|null $message 533 * @param string|null $propertyPath 534 * 535 * @return bool 536 * 537 * @throws AssertionFailedException 538 */ 539 public static function integerish($value, $message = null, string $propertyPath = null): bool 540 { 541 if ( 542 \is_resource($value) || 543 \is_object($value) || 544 \is_bool($value) || 545 \is_null($value) || 546 \is_array($value) || 547 (\is_string($value) && '' == $value) || 548 ( 549 \strval(\intval($value)) !== \strval($value) && 550 \strval(\intval($value)) !== \strval(\ltrim($value, '0')) && 551 '' !== \strval(\intval($value)) && 552 '' !== \strval(\ltrim($value, '0')) 553 ) 554 ) { 555 $message = \sprintf( 556 static::generateMessage($message ?: 'Value "%s" is not an integer or a number castable to integer.'), 557 static::stringify($value) 558 ); 559 560 throw static::createException($value, $message, static::INVALID_INTEGERISH, $propertyPath); 561 } 562 563 return true; 564 } 565 566 /** 567 * Assert that value is php boolean. 568 * 569 * @param mixed $value 570 * @param string|callable|null $message 571 * @param string|null $propertyPath 572 * 573 * @return bool 574 * 575 * @throws AssertionFailedException 576 */ 577 public static function boolean($value, $message = null, string $propertyPath = null): bool 578 { 579 if (!\is_bool($value)) { 580 $message = \sprintf( 581 static::generateMessage($message ?: 'Value "%s" is not a boolean.'), 582 static::stringify($value) 583 ); 584 585 throw static::createException($value, $message, static::INVALID_BOOLEAN, $propertyPath); 586 } 587 588 return true; 589 } 590 591 /** 592 * Assert that value is a PHP scalar. 593 * 594 * @param mixed $value 595 * @param string|callable|null $message 596 * @param string|null $propertyPath 597 * 598 * @return bool 599 * 600 * @throws AssertionFailedException 601 */ 602 public static function scalar($value, $message = null, string $propertyPath = null): bool 603 { 604 if (!\is_scalar($value)) { 605 $message = \sprintf( 606 static::generateMessage($message ?: 'Value "%s" is not a scalar.'), 607 static::stringify($value) 608 ); 609 610 throw static::createException($value, $message, static::INVALID_SCALAR, $propertyPath); 611 } 612 613 return true; 614 } 615 616 /** 617 * Assert that value is not empty. 618 * 619 * @param mixed $value 620 * @param string|callable|null $message 621 * @param string|null $propertyPath 622 * 623 * @return bool 624 * 625 * @throws AssertionFailedException 626 */ 627 public static function notEmpty($value, $message = null, string $propertyPath = null): bool 628 { 629 if (empty($value)) { 630 $message = \sprintf( 631 static::generateMessage($message ?: 'Value "%s" is empty, but non empty value was expected.'), 632 static::stringify($value) 633 ); 634 635 throw static::createException($value, $message, static::VALUE_EMPTY, $propertyPath); 636 } 637 638 return true; 639 } 640 641 /** 642 * Assert that value is empty. 643 * 644 * @param mixed $value 645 * @param string|callable|null $message 646 * @param string|null $propertyPath 647 * 648 * @return bool 649 * 650 * @throws AssertionFailedException 651 */ 652 public static function noContent($value, $message = null, string $propertyPath = null): bool 653 { 654 if (!empty($value)) { 655 $message = \sprintf( 656 static::generateMessage($message ?: 'Value "%s" is not empty, but empty value was expected.'), 657 static::stringify($value) 658 ); 659 660 throw static::createException($value, $message, static::VALUE_NOT_EMPTY, $propertyPath); 661 } 662 663 return true; 664 } 665 666 /** 667 * Assert that value is null. 668 * 669 * @param mixed $value 670 * @param string|callable|null $message 671 * @param string|null $propertyPath 672 * 673 * @return bool 674 */ 675 public static function null($value, $message = null, string $propertyPath = null): bool 676 { 677 if (null !== $value) { 678 $message = \sprintf( 679 static::generateMessage($message ?: 'Value "%s" is not null, but null value was expected.'), 680 static::stringify($value) 681 ); 682 683 throw static::createException($value, $message, static::VALUE_NOT_NULL, $propertyPath); 684 } 685 686 return true; 687 } 688 689 /** 690 * Assert that value is not null. 691 * 692 * @param mixed $value 693 * @param string|callable|null $message 694 * @param string|null $propertyPath 695 * 696 * @return bool 697 * 698 * @throws AssertionFailedException 699 */ 700 public static function notNull($value, $message = null, string $propertyPath = null): bool 701 { 702 if (null === $value) { 703 $message = \sprintf( 704 static::generateMessage($message ?: 'Value "%s" is null, but non null value was expected.'), 705 static::stringify($value) 706 ); 707 708 throw static::createException($value, $message, static::VALUE_NULL, $propertyPath); 709 } 710 711 return true; 712 } 713 714 /** 715 * Assert that value is a string. 716 * 717 * @param mixed $value 718 * @param string|callable|null $message 719 * @param string|null $propertyPath 720 * 721 * @return bool 722 * 723 * @throws AssertionFailedException 724 */ 725 public static function string($value, $message = null, string $propertyPath = null) 726 { 727 if (!\is_string($value)) { 728 $message = \sprintf( 729 static::generateMessage($message ?: 'Value "%s" expected to be string, type %s given.'), 730 static::stringify($value), 731 \gettype($value) 732 ); 733 734 throw static::createException($value, $message, static::INVALID_STRING, $propertyPath); 735 } 736 737 return true; 738 } 739 740 /** 741 * Assert that value matches a regex. 742 * 743 * @param mixed $value 744 * @param string $pattern 745 * @param string|callable|null $message 746 * @param string|null $propertyPath 747 * 748 * @return bool 749 * 750 * @throws AssertionFailedException 751 */ 752 public static function regex($value, $pattern, $message = null, string $propertyPath = null): bool 753 { 754 static::string($value, $message, $propertyPath); 755 756 if (!\preg_match($pattern, $value)) { 757 $message = \sprintf( 758 static::generateMessage($message ?: 'Value "%s" does not match expression.'), 759 static::stringify($value) 760 ); 761 762 throw static::createException($value, $message, static::INVALID_REGEX, $propertyPath, ['pattern' => $pattern]); 763 } 764 765 return true; 766 } 767 768 /** 769 * Assert that value does not match a regex. 770 * 771 * @param mixed $value 772 * @param string $pattern 773 * @param string|callable|null $message 774 * @param string|null $propertyPath 775 * 776 * @return bool 777 * 778 * @throws AssertionFailedException 779 */ 780 public static function notRegex($value, $pattern, $message = null, string $propertyPath = null): bool 781 { 782 static::string($value, $message, $propertyPath); 783 784 if (\preg_match($pattern, $value)) { 785 $message = \sprintf( 786 static::generateMessage($message ?: 'Value "%s" matches expression.'), 787 static::stringify($value) 788 ); 789 790 throw static::createException($value, $message, static::INVALID_NOT_REGEX, $propertyPath, ['pattern' => $pattern]); 791 } 792 793 return true; 794 } 795 796 /** 797 * Assert that string has a given length. 798 * 799 * @param mixed $value 800 * @param int $length 801 * @param string|callable|null $message 802 * @param string|null $propertyPath 803 * @param string $encoding 804 * 805 * @return bool 806 * 807 * @throws AssertionFailedException 808 */ 809 public static function length($value, $length, $message = null, string $propertyPath = null, $encoding = 'utf8'): bool 810 { 811 static::string($value, $message, $propertyPath); 812 813 if (\mb_strlen($value, $encoding) !== $length) { 814 $message = \sprintf( 815 static::generateMessage($message ?: 'Value "%s" has to be %d exactly characters long, but length is %d.'), 816 static::stringify($value), 817 $length, 818 \mb_strlen($value, $encoding) 819 ); 820 821 throw static::createException($value, $message, static::INVALID_LENGTH, $propertyPath, ['length' => $length, 'encoding' => $encoding]); 822 } 823 824 return true; 825 } 826 827 /** 828 * Assert that a string is at least $minLength chars long. 829 * 830 * @param mixed $value 831 * @param int $minLength 832 * @param string|callable|null $message 833 * @param string|null $propertyPath 834 * @param string $encoding 835 * 836 * @return bool 837 * 838 * @throws AssertionFailedException 839 */ 840 public static function minLength($value, $minLength, $message = null, string $propertyPath = null, $encoding = 'utf8'): bool 841 { 842 static::string($value, $message, $propertyPath); 843 844 if (\mb_strlen($value, $encoding) < $minLength) { 845 $message = \sprintf( 846 static::generateMessage($message ?: 'Value "%s" is too short, it should have at least %d characters, but only has %d characters.'), 847 static::stringify($value), 848 $minLength, 849 \mb_strlen($value, $encoding) 850 ); 851 852 throw static::createException($value, $message, static::INVALID_MIN_LENGTH, $propertyPath, ['min_length' => $minLength, 'encoding' => $encoding]); 853 } 854 855 return true; 856 } 857 858 /** 859 * Assert that string value is not longer than $maxLength chars. 860 * 861 * @param mixed $value 862 * @param int $maxLength 863 * @param string|callable|null $message 864 * @param string|null $propertyPath 865 * @param string $encoding 866 * 867 * @return bool 868 * 869 * @throws AssertionFailedException 870 */ 871 public static function maxLength($value, $maxLength, $message = null, string $propertyPath = null, $encoding = 'utf8'): bool 872 { 873 static::string($value, $message, $propertyPath); 874 875 if (\mb_strlen($value, $encoding) > $maxLength) { 876 $message = \sprintf( 877 static::generateMessage($message ?: 'Value "%s" is too long, it should have no more than %d characters, but has %d characters.'), 878 static::stringify($value), 879 $maxLength, 880 \mb_strlen($value, $encoding) 881 ); 882 883 throw static::createException($value, $message, static::INVALID_MAX_LENGTH, $propertyPath, ['max_length' => $maxLength, 'encoding' => $encoding]); 884 } 885 886 return true; 887 } 888 889 /** 890 * Assert that string length is between min and max lengths. 891 * 892 * @param mixed $value 893 * @param int $minLength 894 * @param int $maxLength 895 * @param string|callable|null $message 896 * @param string|null $propertyPath 897 * @param string $encoding 898 * 899 * @return bool 900 * 901 * @throws AssertionFailedException 902 */ 903 public static function betweenLength($value, $minLength, $maxLength, $message = null, string $propertyPath = null, $encoding = 'utf8'): bool 904 { 905 static::string($value, $message, $propertyPath); 906 static::minLength($value, $minLength, $message, $propertyPath, $encoding); 907 static::maxLength($value, $maxLength, $message, $propertyPath, $encoding); 908 909 return true; 910 } 911 912 /** 913 * Assert that string starts with a sequence of chars. 914 * 915 * @param mixed $string 916 * @param string $needle 917 * @param string|callable|null $message 918 * @param string|null $propertyPath 919 * @param string $encoding 920 * 921 * @return bool 922 * 923 * @throws AssertionFailedException 924 */ 925 public static function startsWith($string, $needle, $message = null, string $propertyPath = null, $encoding = 'utf8'): bool 926 { 927 static::string($string, $message, $propertyPath); 928 929 if (0 !== \mb_strpos($string, $needle, null, $encoding)) { 930 $message = \sprintf( 931 static::generateMessage($message ?: 'Value "%s" does not start with "%s".'), 932 static::stringify($string), 933 static::stringify($needle) 934 ); 935 936 throw static::createException($string, $message, static::INVALID_STRING_START, $propertyPath, ['needle' => $needle, 'encoding' => $encoding]); 937 } 938 939 return true; 940 } 941 942 /** 943 * Assert that string ends with a sequence of chars. 944 * 945 * @param mixed $string 946 * @param string $needle 947 * @param string|callable|null $message 948 * @param string|null $propertyPath 949 * @param string $encoding 950 * 951 * @return bool 952 * 953 * @throws AssertionFailedException 954 */ 955 public static function endsWith($string, $needle, $message = null, string $propertyPath = null, $encoding = 'utf8'): bool 956 { 957 static::string($string, $message, $propertyPath); 958 959 $stringPosition = \mb_strlen($string, $encoding) - \mb_strlen($needle, $encoding); 960 961 if (\mb_strripos($string, $needle, null, $encoding) !== $stringPosition) { 962 $message = \sprintf( 963 static::generateMessage($message ?: 'Value "%s" does not end with "%s".'), 964 static::stringify($string), 965 static::stringify($needle) 966 ); 967 968 throw static::createException($string, $message, static::INVALID_STRING_END, $propertyPath, ['needle' => $needle, 'encoding' => $encoding]); 969 } 970 971 return true; 972 } 973 974 /** 975 * Assert that string contains a sequence of chars. 976 * 977 * @param mixed $string 978 * @param string $needle 979 * @param string|callable|null $message 980 * @param string|null $propertyPath 981 * @param string $encoding 982 * 983 * @return bool 984 * 985 * @throws AssertionFailedException 986 */ 987 public static function contains($string, $needle, $message = null, string $propertyPath = null, $encoding = 'utf8'): bool 988 { 989 static::string($string, $message, $propertyPath); 990 991 if (false === \mb_strpos($string, $needle, null, $encoding)) { 992 $message = \sprintf( 993 static::generateMessage($message ?: 'Value "%s" does not contain "%s".'), 994 static::stringify($string), 995 static::stringify($needle) 996 ); 997 998 throw static::createException($string, $message, static::INVALID_STRING_CONTAINS, $propertyPath, ['needle' => $needle, 'encoding' => $encoding]); 999 } 1000 1001 return true; 1002 } 1003 1004 /** 1005 * Assert that string does not contains a sequence of chars. 1006 * 1007 * @param mixed $string 1008 * @param string $needle 1009 * @param string|callable|null $message 1010 * @param string|null $propertyPath 1011 * @param string $encoding 1012 * 1013 * @return bool 1014 * 1015 * @throws AssertionFailedException 1016 */ 1017 public static function notContains($string, $needle, $message = null, string $propertyPath = null, $encoding = 'utf8'): bool 1018 { 1019 static::string($string, $message, $propertyPath); 1020 1021 if (false !== \mb_strpos($string, $needle, null, $encoding)) { 1022 $message = \sprintf( 1023 static::generateMessage($message ?: 'Value "%s" contains "%s".'), 1024 static::stringify($string), 1025 static::stringify($needle) 1026 ); 1027 1028 throw static::createException($string, $message, static::INVALID_STRING_NOT_CONTAINS, $propertyPath, ['needle' => $needle, 'encoding' => $encoding]); 1029 } 1030 1031 return true; 1032 } 1033 1034 /** 1035 * Assert that value is in array of choices. 1036 * 1037 * @param mixed $value 1038 * @param array $choices 1039 * @param string|callable|null $message 1040 * @param string|null $propertyPath 1041 * 1042 * @return bool 1043 * 1044 * @throws AssertionFailedException 1045 */ 1046 public static function choice($value, array $choices, $message = null, string $propertyPath = null): bool 1047 { 1048 if (!\in_array($value, $choices, true)) { 1049 $message = \sprintf( 1050 static::generateMessage($message ?: 'Value "%s" is not an element of the valid values: %s'), 1051 static::stringify($value), 1052 \implode(', ', \array_map([\get_called_class(), 'stringify'], $choices)) 1053 ); 1054 1055 throw static::createException($value, $message, static::INVALID_CHOICE, $propertyPath, ['choices' => $choices]); 1056 } 1057 1058 return true; 1059 } 1060 1061 /** 1062 * Assert that value is in array of choices. 1063 * 1064 * This is an alias of {@see choice()}. 1065 * 1066 * @param mixed $value 1067 * @param array $choices 1068 * @param string|callable|null $message 1069 * @param string|null $propertyPath 1070 * 1071 * @return bool 1072 * 1073 * @throws AssertionFailedException 1074 */ 1075 public static function inArray($value, array $choices, $message = null, string $propertyPath = null): bool 1076 { 1077 return static::choice($value, $choices, $message, $propertyPath); 1078 } 1079 1080 /** 1081 * Assert that value is numeric. 1082 * 1083 * @param mixed $value 1084 * @param string|callable|null $message 1085 * @param string|null $propertyPath 1086 * 1087 * @return bool 1088 * 1089 * @throws AssertionFailedException 1090 */ 1091 public static function numeric($value, $message = null, string $propertyPath = null): bool 1092 { 1093 if (!\is_numeric($value)) { 1094 $message = \sprintf( 1095 static::generateMessage($message ?: 'Value "%s" is not numeric.'), 1096 static::stringify($value) 1097 ); 1098 1099 throw static::createException($value, $message, static::INVALID_NUMERIC, $propertyPath); 1100 } 1101 1102 return true; 1103 } 1104 1105 /** 1106 * Assert that value is a resource. 1107 * 1108 * @param mixed $value 1109 * @param string|callable|null $message 1110 * @param string|null $propertyPath 1111 * 1112 * @return bool 1113 */ 1114 public static function isResource($value, $message = null, string $propertyPath = null): bool 1115 { 1116 if (!\is_resource($value)) { 1117 $message = \sprintf( 1118 static::generateMessage($message ?: 'Value "%s" is not a resource.'), 1119 static::stringify($value) 1120 ); 1121 1122 throw static::createException($value, $message, static::INVALID_RESOURCE, $propertyPath); 1123 } 1124 1125 return true; 1126 } 1127 1128 /** 1129 * Assert that value is an array. 1130 * 1131 * @param mixed $value 1132 * @param string|callable|null $message 1133 * @param string|null $propertyPath 1134 * 1135 * @return bool 1136 * 1137 * @throws AssertionFailedException 1138 */ 1139 public static function isArray($value, $message = null, string $propertyPath = null): bool 1140 { 1141 if (!\is_array($value)) { 1142 $message = \sprintf( 1143 static::generateMessage($message ?: 'Value "%s" is not an array.'), 1144 static::stringify($value) 1145 ); 1146 1147 throw static::createException($value, $message, static::INVALID_ARRAY, $propertyPath); 1148 } 1149 1150 return true; 1151 } 1152 1153 /** 1154 * Assert that value is an array or a traversable object. 1155 * 1156 * @param mixed $value 1157 * @param string|callable|null $message 1158 * @param string|null $propertyPath 1159 * 1160 * @return bool 1161 * 1162 * @throws AssertionFailedException 1163 */ 1164 public static function isTraversable($value, $message = null, string $propertyPath = null): bool 1165 { 1166 if (!\is_array($value) && !$value instanceof Traversable) { 1167 $message = \sprintf( 1168 static::generateMessage($message ?: 'Value "%s" is not an array and does not implement Traversable.'), 1169 static::stringify($value) 1170 ); 1171 1172 throw static::createException($value, $message, static::INVALID_TRAVERSABLE, $propertyPath); 1173 } 1174 1175 return true; 1176 } 1177 1178 /** 1179 * Assert that value is an array or an array-accessible object. 1180 * 1181 * @param mixed $value 1182 * @param string|callable|null $message 1183 * @param string|null $propertyPath 1184 * 1185 * @return bool 1186 * 1187 * @throws AssertionFailedException 1188 */ 1189 public static function isArrayAccessible($value, $message = null, string $propertyPath = null): bool 1190 { 1191 if (!\is_array($value) && !$value instanceof ArrayAccess) { 1192 $message = \sprintf( 1193 static::generateMessage($message ?: 'Value "%s" is not an array and does not implement ArrayAccess.'), 1194 static::stringify($value) 1195 ); 1196 1197 throw static::createException($value, $message, static::INVALID_ARRAY_ACCESSIBLE, $propertyPath); 1198 } 1199 1200 return true; 1201 } 1202 1203 /** 1204 * Assert that value is countable. 1205 * 1206 * @param array|Countable|ResourceBundle|SimpleXMLElement $value 1207 * @param string|callable|null $message 1208 * @param string|null $propertyPath 1209 * 1210 * @return bool 1211 * 1212 * @throws AssertionFailedException 1213 */ 1214 public static function isCountable($value, $message = null, string $propertyPath = null): bool 1215 { 1216 if (\function_exists('is_countable')) { 1217 $assert = \is_countable($value); 1218 } else { 1219 $assert = \is_array($value) || $value instanceof Countable || $value instanceof ResourceBundle || $value instanceof SimpleXMLElement; 1220 } 1221 1222 if (!$assert) { 1223 $message = \sprintf( 1224 static::generateMessage($message ?: 'Value "%s" is not an array and does not implement Countable.'), 1225 static::stringify($value) 1226 ); 1227 1228 throw static::createException($value, $message, static::INVALID_COUNTABLE, $propertyPath); 1229 } 1230 1231 return true; 1232 } 1233 1234 /** 1235 * Assert that key exists in an array. 1236 * 1237 * @param mixed $value 1238 * @param string|int $key 1239 * @param string|callable|null $message 1240 * @param string|null $propertyPath 1241 * 1242 * @return bool 1243 * 1244 * @throws AssertionFailedException 1245 */ 1246 public static function keyExists($value, $key, $message = null, string $propertyPath = null): bool 1247 { 1248 static::isArray($value, $message, $propertyPath); 1249 1250 if (!\array_key_exists($key, $value)) { 1251 $message = \sprintf( 1252 static::generateMessage($message ?: 'Array does not contain an element with key "%s"'), 1253 static::stringify($key) 1254 ); 1255 1256 throw static::createException($value, $message, static::INVALID_KEY_EXISTS, $propertyPath, ['key' => $key]); 1257 } 1258 1259 return true; 1260 } 1261 1262 /** 1263 * Assert that key does not exist in an array. 1264 * 1265 * @param mixed $value 1266 * @param string|int $key 1267 * @param string|callable|null $message 1268 * @param string|null $propertyPath 1269 * 1270 * @return bool 1271 * 1272 * @throws AssertionFailedException 1273 */ 1274 public static function keyNotExists($value, $key, $message = null, string $propertyPath = null): bool 1275 { 1276 static::isArray($value, $message, $propertyPath); 1277 1278 if (\array_key_exists($key, $value)) { 1279 $message = \sprintf( 1280 static::generateMessage($message ?: 'Array contains an element with key "%s"'), 1281 static::stringify($key) 1282 ); 1283 1284 throw static::createException($value, $message, static::INVALID_KEY_NOT_EXISTS, $propertyPath, ['key' => $key]); 1285 } 1286 1287 return true; 1288 } 1289 1290 /** 1291 * Assert that key exists in an array/array-accessible object using isset(). 1292 * 1293 * @param mixed $value 1294 * @param string|int $key 1295 * @param string|callable|null $message 1296 * @param string|null $propertyPath 1297 * 1298 * @return bool 1299 * 1300 * @throws AssertionFailedException 1301 */ 1302 public static function keyIsset($value, $key, $message = null, string $propertyPath = null): bool 1303 { 1304 static::isArrayAccessible($value, $message, $propertyPath); 1305 1306 if (!isset($value[$key])) { 1307 $message = \sprintf( 1308 static::generateMessage($message ?: 'The element with key "%s" was not found'), 1309 static::stringify($key) 1310 ); 1311 1312 throw static::createException($value, $message, static::INVALID_KEY_ISSET, $propertyPath, ['key' => $key]); 1313 } 1314 1315 return true; 1316 } 1317 1318 /** 1319 * Assert that key exists in an array/array-accessible object and its value is not empty. 1320 * 1321 * @param mixed $value 1322 * @param string|int $key 1323 * @param string|callable|null $message 1324 * @param string|null $propertyPath 1325 * 1326 * @return bool 1327 * 1328 * @throws AssertionFailedException 1329 */ 1330 public static function notEmptyKey($value, $key, $message = null, string $propertyPath = null): bool 1331 { 1332 static::keyIsset($value, $key, $message, $propertyPath); 1333 static::notEmpty($value[$key], $message, $propertyPath); 1334 1335 return true; 1336 } 1337 1338 /** 1339 * Assert that value is not blank. 1340 * 1341 * @param mixed $value 1342 * @param string|callable|null $message 1343 * @param string|null $propertyPath 1344 * 1345 * @return bool 1346 * 1347 * @throws AssertionFailedException 1348 */ 1349 public static function notBlank($value, $message = null, string $propertyPath = null): bool 1350 { 1351 if (false === $value || (empty($value) && '0' != $value) || (\is_string($value) && '' === \trim($value))) { 1352 $message = \sprintf( 1353 static::generateMessage($message ?: 'Value "%s" is blank, but was expected to contain a value.'), 1354 static::stringify($value) 1355 ); 1356 1357 throw static::createException($value, $message, static::INVALID_NOT_BLANK, $propertyPath); 1358 } 1359 1360 return true; 1361 } 1362 1363 /** 1364 * Assert that value is instance of given class-name. 1365 * 1366 * @param mixed $value 1367 * @param string $className 1368 * @param string|callable|null $message 1369 * @param string|null $propertyPath 1370 * 1371 * @return bool 1372 * 1373 * @throws AssertionFailedException 1374 */ 1375 public static function isInstanceOf($value, $className, $message = null, string $propertyPath = null): bool 1376 { 1377 if (!($value instanceof $className)) { 1378 $message = \sprintf( 1379 static::generateMessage($message ?: 'Class "%s" was expected to be instanceof of "%s" but is not.'), 1380 static::stringify($value), 1381 $className 1382 ); 1383 1384 throw static::createException($value, $message, static::INVALID_INSTANCE_OF, $propertyPath, ['class' => $className]); 1385 } 1386 1387 return true; 1388 } 1389 1390 /** 1391 * Assert that value is not instance of given class-name. 1392 * 1393 * @param mixed $value 1394 * @param string $className 1395 * @param string|callable|null $message 1396 * @param string|null $propertyPath 1397 * 1398 * @return bool 1399 * 1400 * @throws AssertionFailedException 1401 */ 1402 public static function notIsInstanceOf($value, $className, $message = null, string $propertyPath = null): bool 1403 { 1404 if ($value instanceof $className) { 1405 $message = \sprintf( 1406 static::generateMessage($message ?: 'Class "%s" was not expected to be instanceof of "%s".'), 1407 static::stringify($value), 1408 $className 1409 ); 1410 1411 throw static::createException($value, $message, static::INVALID_NOT_INSTANCE_OF, $propertyPath, ['class' => $className]); 1412 } 1413 1414 return true; 1415 } 1416 1417 /** 1418 * Assert that value is subclass of given class-name. 1419 * 1420 * @param mixed $value 1421 * @param string $className 1422 * @param string|callable|null $message 1423 * @param string|null $propertyPath 1424 * 1425 * @return bool 1426 * 1427 * @throws AssertionFailedException 1428 */ 1429 public static function subclassOf($value, $className, $message = null, string $propertyPath = null): bool 1430 { 1431 if (!\is_subclass_of($value, $className)) { 1432 $message = \sprintf( 1433 static::generateMessage($message ?: 'Class "%s" was expected to be subclass of "%s".'), 1434 static::stringify($value), 1435 $className 1436 ); 1437 1438 throw static::createException($value, $message, static::INVALID_SUBCLASS_OF, $propertyPath, ['class' => $className]); 1439 } 1440 1441 return true; 1442 } 1443 1444 /** 1445 * Assert that value is in range of numbers. 1446 * 1447 * @param mixed $value 1448 * @param mixed $minValue 1449 * @param mixed $maxValue 1450 * @param string|callable|null $message 1451 * @param string|null $propertyPath 1452 * 1453 * @return bool 1454 * 1455 * @throws AssertionFailedException 1456 */ 1457 public static function range($value, $minValue, $maxValue, $message = null, string $propertyPath = null): bool 1458 { 1459 static::numeric($value, $message, $propertyPath); 1460 1461 if ($value < $minValue || $value > $maxValue) { 1462 $message = \sprintf( 1463 static::generateMessage($message ?: 'Number "%s" was expected to be at least "%d" and at most "%d".'), 1464 static::stringify($value), 1465 static::stringify($minValue), 1466 static::stringify($maxValue) 1467 ); 1468 1469 throw static::createException($value, $message, static::INVALID_RANGE, $propertyPath, ['min' => $minValue, 'max' => $maxValue]); 1470 } 1471 1472 return true; 1473 } 1474 1475 /** 1476 * Assert that a value is at least as big as a given limit. 1477 * 1478 * @param mixed $value 1479 * @param mixed $minValue 1480 * @param string|callable|null $message 1481 * @param string|null $propertyPath 1482 * 1483 * @return bool 1484 * 1485 * @throws AssertionFailedException 1486 */ 1487 public static function min($value, $minValue, $message = null, string $propertyPath = null): bool 1488 { 1489 static::numeric($value, $message, $propertyPath); 1490 1491 if ($value < $minValue) { 1492 $message = \sprintf( 1493 static::generateMessage($message ?: 'Number "%s" was expected to be at least "%s".'), 1494 static::stringify($value), 1495 static::stringify($minValue) 1496 ); 1497 1498 throw static::createException($value, $message, static::INVALID_MIN, $propertyPath, ['min' => $minValue]); 1499 } 1500 1501 return true; 1502 } 1503 1504 /** 1505 * Assert that a number is smaller as a given limit. 1506 * 1507 * @param mixed $value 1508 * @param mixed $maxValue 1509 * @param string|callable|null $message 1510 * @param string|null $propertyPath 1511 * 1512 * @return bool 1513 * 1514 * @throws AssertionFailedException 1515 */ 1516 public static function max($value, $maxValue, $message = null, string $propertyPath = null): bool 1517 { 1518 static::numeric($value, $message, $propertyPath); 1519 1520 if ($value > $maxValue) { 1521 $message = \sprintf( 1522 static::generateMessage($message ?: 'Number "%s" was expected to be at most "%s".'), 1523 static::stringify($value), 1524 static::stringify($maxValue) 1525 ); 1526 1527 throw static::createException($value, $message, static::INVALID_MAX, $propertyPath, ['max' => $maxValue]); 1528 } 1529 1530 return true; 1531 } 1532 1533 /** 1534 * Assert that a file exists. 1535 * 1536 * @param string $value 1537 * @param string|callable|null $message 1538 * @param string|null $propertyPath 1539 * 1540 * @return bool 1541 * 1542 * @throws AssertionFailedException 1543 */ 1544 public static function file($value, $message = null, string $propertyPath = null): bool 1545 { 1546 static::string($value, $message, $propertyPath); 1547 static::notEmpty($value, $message, $propertyPath); 1548 1549 if (!\is_file($value)) { 1550 $message = \sprintf( 1551 static::generateMessage($message ?: 'File "%s" was expected to exist.'), 1552 static::stringify($value) 1553 ); 1554 1555 throw static::createException($value, $message, static::INVALID_FILE, $propertyPath); 1556 } 1557 1558 return true; 1559 } 1560 1561 /** 1562 * Assert that a directory exists. 1563 * 1564 * @param string $value 1565 * @param string|callable|null $message 1566 * @param string|null $propertyPath 1567 * 1568 * @return bool 1569 * 1570 * @throws AssertionFailedException 1571 */ 1572 public static function directory($value, $message = null, string $propertyPath = null): bool 1573 { 1574 static::string($value, $message, $propertyPath); 1575 1576 if (!\is_dir($value)) { 1577 $message = \sprintf( 1578 static::generateMessage($message ?: 'Path "%s" was expected to be a directory.'), 1579 static::stringify($value) 1580 ); 1581 1582 throw static::createException($value, $message, static::INVALID_DIRECTORY, $propertyPath); 1583 } 1584 1585 return true; 1586 } 1587 1588 /** 1589 * Assert that the value is something readable. 1590 * 1591 * @param string $value 1592 * @param string|callable|null $message 1593 * @param string|null $propertyPath 1594 * 1595 * @return bool 1596 * 1597 * @throws AssertionFailedException 1598 */ 1599 public static function readable($value, $message = null, string $propertyPath = null): bool 1600 { 1601 static::string($value, $message, $propertyPath); 1602 1603 if (!\is_readable($value)) { 1604 $message = \sprintf( 1605 static::generateMessage($message ?: 'Path "%s" was expected to be readable.'), 1606 static::stringify($value) 1607 ); 1608 1609 throw static::createException($value, $message, static::INVALID_READABLE, $propertyPath); 1610 } 1611 1612 return true; 1613 } 1614 1615 /** 1616 * Assert that the value is something writeable. 1617 * 1618 * @param string $value 1619 * @param string|callable|null $message 1620 * @param string|null $propertyPath 1621 * 1622 * @return bool 1623 * 1624 * @throws AssertionFailedException 1625 */ 1626 public static function writeable($value, $message = null, string $propertyPath = null): bool 1627 { 1628 static::string($value, $message, $propertyPath); 1629 1630 if (!\is_writable($value)) { 1631 $message = \sprintf( 1632 static::generateMessage($message ?: 'Path "%s" was expected to be writeable.'), 1633 static::stringify($value) 1634 ); 1635 1636 throw static::createException($value, $message, static::INVALID_WRITEABLE, $propertyPath); 1637 } 1638 1639 return true; 1640 } 1641 1642 /** 1643 * Assert that value is an email address (using input_filter/FILTER_VALIDATE_EMAIL). 1644 * 1645 * @param mixed $value 1646 * @param string|callable|null $message 1647 * @param string|null $propertyPath 1648 * 1649 * @return bool 1650 * 1651 * @throws AssertionFailedException 1652 */ 1653 public static function email($value, $message = null, string $propertyPath = null): bool 1654 { 1655 static::string($value, $message, $propertyPath); 1656 1657 if (!\filter_var($value, FILTER_VALIDATE_EMAIL)) { 1658 $message = \sprintf( 1659 static::generateMessage($message ?: 'Value "%s" was expected to be a valid e-mail address.'), 1660 static::stringify($value) 1661 ); 1662 1663 throw static::createException($value, $message, static::INVALID_EMAIL, $propertyPath); 1664 } 1665 1666 return true; 1667 } 1668 1669 /** 1670 * Assert that value is an URL. 1671 * 1672 * This code snipped was taken from the Symfony project and modified to the special demands of this method. 1673 * 1674 * @param mixed $value 1675 * @param string|callable|null $message 1676 * @param string|null $propertyPath 1677 * 1678 * @return bool 1679 * 1680 * @throws AssertionFailedException 1681 * 1682 * @see https://github.com/symfony/Validator/blob/master/Constraints/UrlValidator.php 1683 * @see https://github.com/symfony/Validator/blob/master/Constraints/Url.php 1684 */ 1685 public static function url($value, $message = null, string $propertyPath = null): bool 1686 { 1687 static::string($value, $message, $propertyPath); 1688 1689 $protocols = ['http', 'https']; 1690 1691 $pattern = '~^ 1692 (%s):// # protocol 1693 (([\.\pL\pN-]+:)?([\.\pL\pN-]+)@)? # basic auth 1694 ( 1695 ([\pL\pN\pS\-\.])+(\.?([\pL\pN]|xn\-\-[\pL\pN-]+)+\.?) # a domain name 1696 | # or 1697 \d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3} # an IP address 1698 | # or 1699 \[ 1700 (?:(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){6})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:::(?:(?:(?:[0-9a-f]{1,4})):){5})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:[0-9a-f]{1,4})))?::(?:(?:(?:[0-9a-f]{1,4})):){4})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,1}(?:(?:[0-9a-f]{1,4})))?::(?:(?:(?:[0-9a-f]{1,4})):){3})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,2}(?:(?:[0-9a-f]{1,4})))?::(?:(?:(?:[0-9a-f]{1,4})):){2})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,3}(?:(?:[0-9a-f]{1,4})))?::(?:(?:[0-9a-f]{1,4})):)(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,4}(?:(?:[0-9a-f]{1,4})))?::)(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,5}(?:(?:[0-9a-f]{1,4})))?::)(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,6}(?:(?:[0-9a-f]{1,4})))?::)))) 1701 \] # an IPv6 address 1702 ) 1703 (:[0-9]+)? # a port (optional) 1704 (?:/ (?:[\pL\pN\-._\~!$&\'()*+,;=:@]|%%[0-9A-Fa-f]{2})* )* # a path 1705 (?:\? (?:[\pL\pN\-._\~!$&\'\[\]()*+,;=:@/?]|%%[0-9A-Fa-f]{2})* )? # a query (optional) 1706 (?:\# (?:[\pL\pN\-._\~!$&\'()*+,;=:@/?]|%%[0-9A-Fa-f]{2})* )? # a fragment (optional) 1707 $~ixu'; 1708 1709 $pattern = \sprintf($pattern, \implode('|', $protocols)); 1710 1711 if (!\preg_match($pattern, $value)) { 1712 $message = \sprintf( 1713 static::generateMessage($message ?: 'Value "%s" was expected to be a valid URL starting with http or https'), 1714 static::stringify($value) 1715 ); 1716 1717 throw static::createException($value, $message, static::INVALID_URL, $propertyPath); 1718 } 1719 1720 return true; 1721 } 1722 1723 /** 1724 * Assert that value is alphanumeric. 1725 * 1726 * @param mixed $value 1727 * @param string|callable|null $message 1728 * @param string|null $propertyPath 1729 * 1730 * @return bool 1731 * 1732 * @throws AssertionFailedException 1733 */ 1734 public static function alnum($value, $message = null, string $propertyPath = null): bool 1735 { 1736 try { 1737 static::regex($value, '(^([a-zA-Z]{1}[a-zA-Z0-9]*)$)', $message, $propertyPath); 1738 } catch (Throwable $e) { 1739 $message = \sprintf( 1740 static::generateMessage($message ?: 'Value "%s" is not alphanumeric, starting with letters and containing only letters and numbers.'), 1741 static::stringify($value) 1742 ); 1743 1744 throw static::createException($value, $message, static::INVALID_ALNUM, $propertyPath); 1745 } 1746 1747 return true; 1748 } 1749 1750 /** 1751 * Assert that the value is boolean True. 1752 * 1753 * @param mixed $value 1754 * @param string|callable|null $message 1755 * @param string|null $propertyPath 1756 * 1757 * @return bool 1758 * 1759 * @throws AssertionFailedException 1760 */ 1761 public static function true($value, $message = null, string $propertyPath = null): bool 1762 { 1763 if (true !== $value) { 1764 $message = \sprintf( 1765 static::generateMessage($message ?: 'Value "%s" is not TRUE.'), 1766 static::stringify($value) 1767 ); 1768 1769 throw static::createException($value, $message, static::INVALID_TRUE, $propertyPath); 1770 } 1771 1772 return true; 1773 } 1774 1775 /** 1776 * Assert that the value is boolean False. 1777 * 1778 * @param mixed $value 1779 * @param string|callable|null $message 1780 * @param string|null $propertyPath 1781 * 1782 * @return bool 1783 * 1784 * @throws AssertionFailedException 1785 */ 1786 public static function false($value, $message = null, string $propertyPath = null): bool 1787 { 1788 if (false !== $value) { 1789 $message = \sprintf( 1790 static::generateMessage($message ?: 'Value "%s" is not FALSE.'), 1791 static::stringify($value) 1792 ); 1793 1794 throw static::createException($value, $message, static::INVALID_FALSE, $propertyPath); 1795 } 1796 1797 return true; 1798 } 1799 1800 /** 1801 * Assert that the class exists. 1802 * 1803 * @param mixed $value 1804 * @param string|callable|null $message 1805 * @param string|null $propertyPath 1806 * 1807 * @return bool 1808 * 1809 * @throws AssertionFailedException 1810 */ 1811 public static function classExists($value, $message = null, string $propertyPath = null): bool 1812 { 1813 if (!\class_exists($value)) { 1814 $message = \sprintf( 1815 static::generateMessage($message ?: 'Class "%s" does not exist.'), 1816 static::stringify($value) 1817 ); 1818 1819 throw static::createException($value, $message, static::INVALID_CLASS, $propertyPath); 1820 } 1821 1822 return true; 1823 } 1824 1825 /** 1826 * Assert that the interface exists. 1827 * 1828 * @param mixed $value 1829 * @param string|callable|null $message 1830 * @param string|null $propertyPath 1831 * 1832 * @return bool 1833 * 1834 * @throws AssertionFailedException 1835 */ 1836 public static function interfaceExists($value, $message = null, string $propertyPath = null): bool 1837 { 1838 if (!\interface_exists($value)) { 1839 $message = \sprintf( 1840 static::generateMessage($message ?: 'Interface "%s" does not exist.'), 1841 static::stringify($value) 1842 ); 1843 1844 throw static::createException($value, $message, static::INVALID_INTERFACE, $propertyPath); 1845 } 1846 1847 return true; 1848 } 1849 1850 /** 1851 * Assert that the class implements the interface. 1852 * 1853 * @param mixed $class 1854 * @param string $interfaceName 1855 * @param string|callable|null $message 1856 * @param string|null $propertyPath 1857 * 1858 * @return bool 1859 * 1860 * @throws AssertionFailedException 1861 */ 1862 public static function implementsInterface($class, $interfaceName, $message = null, string $propertyPath = null): bool 1863 { 1864 try { 1865 $reflection = new ReflectionClass($class); 1866 if (!$reflection->implementsInterface($interfaceName)) { 1867 $message = \sprintf( 1868 static::generateMessage($message ?: 'Class "%s" does not implement interface "%s".'), 1869 static::stringify($class), 1870 static::stringify($interfaceName) 1871 ); 1872 1873 throw static::createException($class, $message, static::INTERFACE_NOT_IMPLEMENTED, $propertyPath, ['interface' => $interfaceName]); 1874 } 1875 } catch (ReflectionException $e) { 1876 $message = \sprintf( 1877 static::generateMessage($message ?: 'Class "%s" failed reflection.'), 1878 static::stringify($class) 1879 ); 1880 throw static::createException($class, $message, static::INTERFACE_NOT_IMPLEMENTED, $propertyPath, ['interface' => $interfaceName]); 1881 } 1882 1883 return true; 1884 } 1885 1886 /** 1887 * Assert that the given string is a valid json string. 1888 * 1889 * NOTICE: 1890 * Since this does a json_decode to determine its validity 1891 * you probably should consider, when using the variable 1892 * content afterwards, just to decode and check for yourself instead 1893 * of using this assertion. 1894 * 1895 * @param mixed $value 1896 * @param string|callable|null $message 1897 * @param string|null $propertyPath 1898 * 1899 * @return bool 1900 * 1901 * @throws AssertionFailedException 1902 */ 1903 public static function isJsonString($value, $message = null, string $propertyPath = null): bool 1904 { 1905 if (null === \json_decode($value) && JSON_ERROR_NONE !== \json_last_error()) { 1906 $message = \sprintf( 1907 static::generateMessage($message ?: 'Value "%s" is not a valid JSON string.'), 1908 static::stringify($value) 1909 ); 1910 1911 throw static::createException($value, $message, static::INVALID_JSON_STRING, $propertyPath); 1912 } 1913 1914 return true; 1915 } 1916 1917 /** 1918 * Assert that the given string is a valid UUID. 1919 * 1920 * Uses code from {@link https://github.com/ramsey/uuid} that is MIT licensed. 1921 * 1922 * @param string $value 1923 * @param string|callable|null $message 1924 * @param string|null $propertyPath 1925 * 1926 * @return bool 1927 * 1928 * @throws AssertionFailedException 1929 */ 1930 public static function uuid($value, $message = null, string $propertyPath = null): bool 1931 { 1932 $value = \str_replace(['urn:', 'uuid:', '{', '}'], '', $value); 1933 1934 if ('00000000-0000-0000-0000-000000000000' === $value) { 1935 return true; 1936 } 1937 1938 if (!\preg_match('/^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}$/', $value)) { 1939 $message = \sprintf( 1940 static::generateMessage($message ?: 'Value "%s" is not a valid UUID.'), 1941 static::stringify($value) 1942 ); 1943 1944 throw static::createException($value, $message, static::INVALID_UUID, $propertyPath); 1945 } 1946 1947 return true; 1948 } 1949 1950 /** 1951 * Assert that the given string is a valid E164 Phone Number. 1952 * 1953 * @see https://en.wikipedia.org/wiki/E.164 1954 * 1955 * @param string $value 1956 * @param string|callable|null $message 1957 * @param string|null $propertyPath 1958 * 1959 * @return bool 1960 * 1961 * @throws AssertionFailedException 1962 */ 1963 public static function e164($value, $message = null, string $propertyPath = null): bool 1964 { 1965 if (!\preg_match('/^\+?[1-9]\d{1,14}$/', $value)) { 1966 $message = \sprintf( 1967 static::generateMessage($message ?: 'Value "%s" is not a valid E164.'), 1968 static::stringify($value) 1969 ); 1970 1971 throw static::createException($value, $message, static::INVALID_E164, $propertyPath); 1972 } 1973 1974 return true; 1975 } 1976 1977 /** 1978 * Assert that the count of countable is equal to count. 1979 * 1980 * @param array|Countable|ResourceBundle|SimpleXMLElement $countable 1981 * @param int $count 1982 * @param string|callable|null $message 1983 * @param string|null $propertyPath 1984 * 1985 * @return bool 1986 * 1987 * @throws AssertionFailedException 1988 */ 1989 public static function count($countable, $count, $message = null, string $propertyPath = null): bool 1990 { 1991 if ($count !== \count($countable)) { 1992 $message = \sprintf( 1993 static::generateMessage($message ?: 'List does not contain exactly %d elements (%d given).'), 1994 static::stringify($count), 1995 static::stringify(\count($countable)) 1996 ); 1997 1998 throw static::createException($countable, $message, static::INVALID_COUNT, $propertyPath, ['count' => $count]); 1999 } 2000 2001 return true; 2002 } 2003 2004 /** 2005 * Assert that the countable have at least $count elements. 2006 * 2007 * @param array|Countable|ResourceBundle|SimpleXMLElement $countable 2008 * @param int $count 2009 * @param string|callable|null $message 2010 * @param string|null $propertyPath 2011 * 2012 * @return bool 2013 * 2014 * @throws AssertionFailedException 2015 */ 2016 public static function minCount($countable, $count, $message = null, string $propertyPath = null): bool 2017 { 2018 if ($count > \count($countable)) { 2019 $message = \sprintf( 2020 static::generateMessage($message ?: 'List should have at least %d elements, but has %d elements.'), 2021 static::stringify($count), 2022 static::stringify(\count($countable)) 2023 ); 2024 2025 throw static::createException($countable, $message, static::INVALID_MIN_COUNT, $propertyPath, ['count' => $count]); 2026 } 2027 2028 return true; 2029 } 2030 2031 /** 2032 * Assert that the countable have at most $count elements. 2033 * 2034 * @param array|Countable|ResourceBundle|SimpleXMLElement $countable 2035 * @param int $count 2036 * @param string|callable|null $message 2037 * @param string|null $propertyPath 2038 * 2039 * @return bool 2040 * 2041 * @throws AssertionFailedException 2042 */ 2043 public static function maxCount($countable, $count, $message = null, string $propertyPath = null): bool 2044 { 2045 if ($count < \count($countable)) { 2046 $message = \sprintf( 2047 static::generateMessage($message ?: 'List should have at most %d elements, but has %d elements.'), 2048 static::stringify($count), 2049 static::stringify(\count($countable)) 2050 ); 2051 2052 throw static::createException($countable, $message, static::INVALID_MAX_COUNT, $propertyPath, ['count' => $count]); 2053 } 2054 2055 return true; 2056 } 2057 2058 /** 2059 * static call handler to implement: 2060 * - "null or assertion" delegation 2061 * - "all" delegation. 2062 * 2063 * @param string $method 2064 * @param array $args 2065 * 2066 * @return bool|mixed 2067 * 2068 * @throws AssertionFailedException 2069 */ 2070 public static function __callStatic($method, $args) 2071 { 2072 if (0 === \strpos($method, 'nullOr')) { 2073 if (!\array_key_exists(0, $args)) { 2074 throw new BadMethodCallException('Missing the first argument.'); 2075 } 2076 2077 if (null === $args[0]) { 2078 return true; 2079 } 2080 2081 $method = \substr($method, 6); 2082 2083 return \call_user_func_array([\get_called_class(), $method], $args); 2084 } 2085 2086 if (0 === \strpos($method, 'all')) { 2087 if (!\array_key_exists(0, $args)) { 2088 throw new BadMethodCallException('Missing the first argument.'); 2089 } 2090 2091 static::isTraversable($args[0]); 2092 2093 $method = \substr($method, 3); 2094 $values = \array_shift($args); 2095 $calledClass = \get_called_class(); 2096 2097 foreach ($values as $value) { 2098 \call_user_func_array([$calledClass, $method], \array_merge([$value], $args)); 2099 } 2100 2101 return true; 2102 } 2103 2104 throw new BadMethodCallException('No assertion Assertion#'.$method.' exists.'); 2105 } 2106 2107 /** 2108 * Determines if the values array has every choice as key and that this choice has content. 2109 * 2110 * @param array $values 2111 * @param array $choices 2112 * @param string|callable|null $message 2113 * @param string|null $propertyPath 2114 * 2115 * @return bool 2116 * 2117 * @throws AssertionFailedException 2118 */ 2119 public static function choicesNotEmpty(array $values, array $choices, $message = null, string $propertyPath = null): bool 2120 { 2121 static::notEmpty($values, $message, $propertyPath); 2122 2123 foreach ($choices as $choice) { 2124 static::notEmptyKey($values, $choice, $message, $propertyPath); 2125 } 2126 2127 return true; 2128 } 2129 2130 /** 2131 * Determines that the named method is defined in the provided object. 2132 * 2133 * @param string $value 2134 * @param mixed $object 2135 * @param string|callable|null $message 2136 * @param string|null $propertyPath 2137 * 2138 * @return bool 2139 * 2140 * @throws AssertionFailedException 2141 */ 2142 public static function methodExists($value, $object, $message = null, string $propertyPath = null): bool 2143 { 2144 static::isObject($object, $message, $propertyPath); 2145 2146 if (!\method_exists($object, $value)) { 2147 $message = \sprintf( 2148 static::generateMessage($message ?: 'Expected "%s" does not exist in provided object.'), 2149 static::stringify($value) 2150 ); 2151 2152 throw static::createException($value, $message, static::INVALID_METHOD, $propertyPath, ['object' => \get_class($object)]); 2153 } 2154 2155 return true; 2156 } 2157 2158 /** 2159 * Determines that the provided value is an object. 2160 * 2161 * @param mixed $value 2162 * @param string|callable|null $message 2163 * @param string|null $propertyPath 2164 * 2165 * @return bool 2166 * 2167 * @throws AssertionFailedException 2168 */ 2169 public static function isObject($value, $message = null, string $propertyPath = null): bool 2170 { 2171 if (!\is_object($value)) { 2172 $message = \sprintf( 2173 static::generateMessage($message ?: 'Provided "%s" is not a valid object.'), 2174 static::stringify($value) 2175 ); 2176 2177 throw static::createException($value, $message, static::INVALID_OBJECT, $propertyPath); 2178 } 2179 2180 return true; 2181 } 2182 2183 /** 2184 * Determines if the value is less than given limit. 2185 * 2186 * @param mixed $value 2187 * @param mixed $limit 2188 * @param string|callable|null $message 2189 * @param string|null $propertyPath 2190 * 2191 * @return bool 2192 * 2193 * @throws AssertionFailedException 2194 */ 2195 public static function lessThan($value, $limit, $message = null, string $propertyPath = null): bool 2196 { 2197 if ($value >= $limit) { 2198 $message = \sprintf( 2199 static::generateMessage($message ?: 'Provided "%s" is not less than "%s".'), 2200 static::stringify($value), 2201 static::stringify($limit) 2202 ); 2203 2204 throw static::createException($value, $message, static::INVALID_LESS, $propertyPath, ['limit' => $limit]); 2205 } 2206 2207 return true; 2208 } 2209 2210 /** 2211 * Determines if the value is less or equal than given limit. 2212 * 2213 * @param mixed $value 2214 * @param mixed $limit 2215 * @param string|callable|null $message 2216 * @param string|null $propertyPath 2217 * 2218 * @return bool 2219 * 2220 * @throws AssertionFailedException 2221 */ 2222 public static function lessOrEqualThan($value, $limit, $message = null, string $propertyPath = null): bool 2223 { 2224 if ($value > $limit) { 2225 $message = \sprintf( 2226 static::generateMessage($message ?: 'Provided "%s" is not less or equal than "%s".'), 2227 static::stringify($value), 2228 static::stringify($limit) 2229 ); 2230 2231 throw static::createException($value, $message, static::INVALID_LESS_OR_EQUAL, $propertyPath, ['limit' => $limit]); 2232 } 2233 2234 return true; 2235 } 2236 2237 /** 2238 * Determines if the value is greater than given limit. 2239 * 2240 * @param mixed $value 2241 * @param mixed $limit 2242 * @param string|callable|null $message 2243 * @param string|null $propertyPath 2244 * 2245 * @return bool 2246 * 2247 * @throws AssertionFailedException 2248 */ 2249 public static function greaterThan($value, $limit, $message = null, string $propertyPath = null): bool 2250 { 2251 if ($value <= $limit) { 2252 $message = \sprintf( 2253 static::generateMessage($message ?: 'Provided "%s" is not greater than "%s".'), 2254 static::stringify($value), 2255 static::stringify($limit) 2256 ); 2257 2258 throw static::createException($value, $message, static::INVALID_GREATER, $propertyPath, ['limit' => $limit]); 2259 } 2260 2261 return true; 2262 } 2263 2264 /** 2265 * Determines if the value is greater or equal than given limit. 2266 * 2267 * @param mixed $value 2268 * @param mixed $limit 2269 * @param string|callable|null $message 2270 * @param string|null $propertyPath 2271 * 2272 * @return bool 2273 * 2274 * @throws AssertionFailedException 2275 */ 2276 public static function greaterOrEqualThan($value, $limit, $message = null, string $propertyPath = null): bool 2277 { 2278 if ($value < $limit) { 2279 $message = \sprintf( 2280 static::generateMessage($message ?: 'Provided "%s" is not greater or equal than "%s".'), 2281 static::stringify($value), 2282 static::stringify($limit) 2283 ); 2284 2285 throw static::createException($value, $message, static::INVALID_GREATER_OR_EQUAL, $propertyPath, ['limit' => $limit]); 2286 } 2287 2288 return true; 2289 } 2290 2291 /** 2292 * Assert that a value is greater or equal than a lower limit, and less than or equal to an upper limit. 2293 * 2294 * @param mixed $value 2295 * @param mixed $lowerLimit 2296 * @param mixed $upperLimit 2297 * @param string|callable|null $message 2298 * @param string $propertyPath 2299 * 2300 * @return bool 2301 * 2302 * @throws AssertionFailedException 2303 */ 2304 public static function between($value, $lowerLimit, $upperLimit, $message = null, string $propertyPath = null): bool 2305 { 2306 if ($lowerLimit > $value || $value > $upperLimit) { 2307 $message = \sprintf( 2308 static::generateMessage($message ?: 'Provided "%s" is neither greater than or equal to "%s" nor less than or equal to "%s".'), 2309 static::stringify($value), 2310 static::stringify($lowerLimit), 2311 static::stringify($upperLimit) 2312 ); 2313 2314 throw static::createException($value, $message, static::INVALID_BETWEEN, $propertyPath, ['lower' => $lowerLimit, 'upper' => $upperLimit]); 2315 } 2316 2317 return true; 2318 } 2319 2320 /** 2321 * Assert that a value is greater than a lower limit, and less than an upper limit. 2322 * 2323 * @param mixed $value 2324 * @param mixed $lowerLimit 2325 * @param mixed $upperLimit 2326 * @param string|callable|null $message 2327 * @param string $propertyPath 2328 * 2329 * @return bool 2330 * 2331 * @throws AssertionFailedException 2332 */ 2333 public static function betweenExclusive($value, $lowerLimit, $upperLimit, $message = null, string $propertyPath = null): bool 2334 { 2335 if ($lowerLimit >= $value || $value >= $upperLimit) { 2336 $message = \sprintf( 2337 static::generateMessage($message ?: 'Provided "%s" is neither greater than "%s" nor less than "%s".'), 2338 static::stringify($value), 2339 static::stringify($lowerLimit), 2340 static::stringify($upperLimit) 2341 ); 2342 2343 throw static::createException($value, $message, static::INVALID_BETWEEN_EXCLUSIVE, $propertyPath, ['lower' => $lowerLimit, 'upper' => $upperLimit]); 2344 } 2345 2346 return true; 2347 } 2348 2349 /** 2350 * Assert that extension is loaded. 2351 * 2352 * @param mixed $value 2353 * @param string|callable|null $message 2354 * @param string|null $propertyPath 2355 * 2356 * @return bool 2357 * 2358 * @throws AssertionFailedException 2359 */ 2360 public static function extensionLoaded($value, $message = null, string $propertyPath = null): bool 2361 { 2362 if (!\extension_loaded($value)) { 2363 $message = \sprintf( 2364 static::generateMessage($message ?: 'Extension "%s" is required.'), 2365 static::stringify($value) 2366 ); 2367 2368 throw static::createException($value, $message, static::INVALID_EXTENSION, $propertyPath); 2369 } 2370 2371 return true; 2372 } 2373 2374 /** 2375 * Assert that date is valid and corresponds to the given format. 2376 * 2377 * @param string $value 2378 * @param string $format supports all of the options date(), except for the following: 2379 * N, w, W, t, L, o, B, a, A, g, h, I, O, P, Z, c, r 2380 * @param string|callable|null $message 2381 * @param string|null $propertyPath 2382 * 2383 * @return bool 2384 * 2385 * @throws AssertionFailedException 2386 * 2387 * @see http://php.net/manual/function.date.php#refsect1-function.date-parameters 2388 */ 2389 public static function date($value, $format, $message = null, string $propertyPath = null): bool 2390 { 2391 static::string($value, $message, $propertyPath); 2392 static::string($format, $message, $propertyPath); 2393 2394 $dateTime = DateTime::createFromFormat('!'.$format, $value); 2395 2396 if (false === $dateTime || $value !== $dateTime->format($format)) { 2397 $message = \sprintf( 2398 static::generateMessage($message ?: 'Date "%s" is invalid or does not match format "%s".'), 2399 static::stringify($value), 2400 static::stringify($format) 2401 ); 2402 2403 throw static::createException($value, $message, static::INVALID_DATE, $propertyPath, ['format' => $format]); 2404 } 2405 2406 return true; 2407 } 2408 2409 /** 2410 * Assert that the value is an object, or a class that exists. 2411 * 2412 * @param mixed $value 2413 * @param string|callable|null $message 2414 * @param string|null $propertyPath 2415 * 2416 * @return bool 2417 * 2418 * @throws AssertionFailedException 2419 */ 2420 public static function objectOrClass($value, $message = null, string $propertyPath = null): bool 2421 { 2422 if (!\is_object($value)) { 2423 static::classExists($value, $message, $propertyPath); 2424 } 2425 2426 return true; 2427 } 2428 2429 /** 2430 * Assert that the value is an object or class, and that the property exists. 2431 * 2432 * @param mixed $value 2433 * @param string $property 2434 * @param string|callable|null $message 2435 * @param string|null $propertyPath 2436 * 2437 * @return bool 2438 * 2439 * @throws AssertionFailedException 2440 */ 2441 public static function propertyExists($value, $property, $message = null, string $propertyPath = null): bool 2442 { 2443 static::objectOrClass($value); 2444 2445 if (!\property_exists($value, $property)) { 2446 $message = \sprintf( 2447 static::generateMessage($message ?: 'Class "%s" does not have property "%s".'), 2448 static::stringify($value), 2449 static::stringify($property) 2450 ); 2451 2452 throw static::createException($value, $message, static::INVALID_PROPERTY, $propertyPath, ['property' => $property]); 2453 } 2454 2455 return true; 2456 } 2457 2458 /** 2459 * Assert that the value is an object or class, and that the properties all exist. 2460 * 2461 * @param mixed $value 2462 * @param array $properties 2463 * @param string|callable|null $message 2464 * @param string|null $propertyPath 2465 * 2466 * @return bool 2467 * 2468 * @throws AssertionFailedException 2469 */ 2470 public static function propertiesExist($value, array $properties, $message = null, string $propertyPath = null): bool 2471 { 2472 static::objectOrClass($value); 2473 static::allString($properties, $message, $propertyPath); 2474 2475 $invalidProperties = []; 2476 foreach ($properties as $property) { 2477 if (!\property_exists($value, $property)) { 2478 $invalidProperties[] = $property; 2479 } 2480 } 2481 2482 if ($invalidProperties) { 2483 $message = \sprintf( 2484 static::generateMessage($message ?: 'Class "%s" does not have these properties: %s.'), 2485 static::stringify($value), 2486 static::stringify(\implode(', ', $invalidProperties)) 2487 ); 2488 2489 throw static::createException($value, $message, static::INVALID_PROPERTY, $propertyPath, ['properties' => $properties]); 2490 } 2491 2492 return true; 2493 } 2494 2495 /** 2496 * Assert comparison of two versions. 2497 * 2498 * @param string $version1 2499 * @param string $operator 2500 * @param string $version2 2501 * @param string|callable|null $message 2502 * @param string|null $propertyPath 2503 * 2504 * @return bool 2505 * 2506 * @throws AssertionFailedException 2507 */ 2508 public static function version($version1, $operator, $version2, $message = null, string $propertyPath = null): bool 2509 { 2510 static::notEmpty($operator, 'versionCompare operator is required and cannot be empty.'); 2511 2512 if (true !== \version_compare($version1, $version2, $operator)) { 2513 $message = \sprintf( 2514 static::generateMessage($message ?: 'Version "%s" is not "%s" version "%s".'), 2515 static::stringify($version1), 2516 static::stringify($operator), 2517 static::stringify($version2) 2518 ); 2519 2520 throw static::createException($version1, $message, static::INVALID_VERSION, $propertyPath, ['operator' => $operator, 'version' => $version2]); 2521 } 2522 2523 return true; 2524 } 2525 2526 /** 2527 * Assert on PHP version. 2528 * 2529 * @param string $operator 2530 * @param mixed $version 2531 * @param string|callable|null $message 2532 * @param string|null $propertyPath 2533 * 2534 * @return bool 2535 * 2536 * @throws AssertionFailedException 2537 */ 2538 public static function phpVersion($operator, $version, $message = null, string $propertyPath = null): bool 2539 { 2540 static::defined('PHP_VERSION'); 2541 2542 return static::version(PHP_VERSION, $operator, $version, $message, $propertyPath); 2543 } 2544 2545 /** 2546 * Assert that extension is loaded and a specific version is installed. 2547 * 2548 * @param string $extension 2549 * @param string $operator 2550 * @param mixed $version 2551 * @param string|callable|null $message 2552 * @param string|null $propertyPath 2553 * 2554 * @return bool 2555 * 2556 * @throws AssertionFailedException 2557 */ 2558 public static function extensionVersion($extension, $operator, $version, $message = null, string $propertyPath = null): bool 2559 { 2560 static::extensionLoaded($extension, $message, $propertyPath); 2561 2562 return static::version(\phpversion($extension), $operator, $version, $message, $propertyPath); 2563 } 2564 2565 /** 2566 * Determines that the provided value is callable. 2567 * 2568 * @param mixed $value 2569 * @param string|callable|null $message 2570 * @param string|null $propertyPath 2571 * 2572 * @return bool 2573 * 2574 * @throws AssertionFailedException 2575 */ 2576 public static function isCallable($value, $message = null, string $propertyPath = null): bool 2577 { 2578 if (!\is_callable($value)) { 2579 $message = \sprintf( 2580 static::generateMessage($message ?: 'Provided "%s" is not a callable.'), 2581 static::stringify($value) 2582 ); 2583 2584 throw static::createException($value, $message, static::INVALID_CALLABLE, $propertyPath); 2585 } 2586 2587 return true; 2588 } 2589 2590 /** 2591 * Assert that the provided value is valid according to a callback. 2592 * 2593 * If the callback returns `false` the assertion will fail. 2594 * 2595 * @param mixed $value 2596 * @param callable $callback 2597 * @param string|callable|null $message 2598 * @param string|null $propertyPath 2599 * 2600 * @return bool 2601 * 2602 * @throws AssertionFailedException 2603 */ 2604 public static function satisfy($value, $callback, $message = null, string $propertyPath = null): bool 2605 { 2606 static::isCallable($callback); 2607 2608 if (false === \call_user_func($callback, $value)) { 2609 $message = \sprintf( 2610 static::generateMessage($message ?: 'Provided "%s" is invalid according to custom rule.'), 2611 static::stringify($value) 2612 ); 2613 2614 throw static::createException($value, $message, static::INVALID_SATISFY, $propertyPath); 2615 } 2616 2617 return true; 2618 } 2619 2620 /** 2621 * Assert that value is an IPv4 or IPv6 address 2622 * (using input_filter/FILTER_VALIDATE_IP). 2623 * 2624 * @param string $value 2625 * @param int|null $flag 2626 * @param string|callable|null $message 2627 * @param string|null $propertyPath 2628 * 2629 * @return bool 2630 * 2631 * @throws AssertionFailedException 2632 * 2633 * @see http://php.net/manual/filter.filters.flags.php 2634 */ 2635 public static function ip($value, $flag = null, $message = null, string $propertyPath = null): bool 2636 { 2637 static::string($value, $message, $propertyPath); 2638 if (!\filter_var($value, FILTER_VALIDATE_IP, $flag)) { 2639 $message = \sprintf( 2640 static::generateMessage($message ?: 'Value "%s" was expected to be a valid IP address.'), 2641 static::stringify($value) 2642 ); 2643 throw static::createException($value, $message, static::INVALID_IP, $propertyPath, ['flag' => $flag]); 2644 } 2645 2646 return true; 2647 } 2648 2649 /** 2650 * Assert that value is an IPv4 address 2651 * (using input_filter/FILTER_VALIDATE_IP). 2652 * 2653 * @param string $value 2654 * @param int|null $flag 2655 * @param string|callable|null $message 2656 * @param string|null $propertyPath 2657 * 2658 * @return bool 2659 * 2660 * @throws AssertionFailedException 2661 * 2662 * @see http://php.net/manual/filter.filters.flags.php 2663 */ 2664 public static function ipv4($value, $flag = null, $message = null, string $propertyPath = null): bool 2665 { 2666 static::ip($value, $flag | FILTER_FLAG_IPV4, static::generateMessage($message ?: 'Value "%s" was expected to be a valid IPv4 address.'), $propertyPath); 2667 2668 return true; 2669 } 2670 2671 /** 2672 * Assert that value is an IPv6 address 2673 * (using input_filter/FILTER_VALIDATE_IP). 2674 * 2675 * @param string $value 2676 * @param int|null $flag 2677 * @param string|callable|null $message 2678 * @param string|null $propertyPath 2679 * 2680 * @return bool 2681 * 2682 * @throws AssertionFailedException 2683 * 2684 * @see http://php.net/manual/filter.filters.flags.php 2685 */ 2686 public static function ipv6($value, $flag = null, $message = null, string $propertyPath = null): bool 2687 { 2688 static::ip($value, $flag | FILTER_FLAG_IPV6, static::generateMessage($message ?: 'Value "%s" was expected to be a valid IPv6 address.'), $propertyPath); 2689 2690 return true; 2691 } 2692 2693 /** 2694 * Assert that a constant is defined. 2695 * 2696 * @param mixed $constant 2697 * @param string|callable|null $message 2698 * @param string|null $propertyPath 2699 * 2700 * @return bool 2701 */ 2702 public static function defined($constant, $message = null, string $propertyPath = null): bool 2703 { 2704 if (!\defined($constant)) { 2705 $message = \sprintf(static::generateMessage($message ?: 'Value "%s" expected to be a defined constant.'), $constant); 2706 2707 throw static::createException($constant, $message, static::INVALID_CONSTANT, $propertyPath); 2708 } 2709 2710 return true; 2711 } 2712 2713 /** 2714 * Assert that a constant is defined. 2715 * 2716 * @param string $value 2717 * @param string|callable|null $message 2718 * @param string|null $propertyPath 2719 * 2720 * @return bool 2721 * 2722 * @throws AssertionFailedException 2723 */ 2724 public static function base64($value, $message = null, string $propertyPath = null): bool 2725 { 2726 if (false === \base64_decode($value, true)) { 2727 $message = \sprintf(static::generateMessage($message ?: 'Value "%s" is not a valid base64 string.'), $value); 2728 2729 throw static::createException($value, $message, static::INVALID_BASE64, $propertyPath); 2730 } 2731 2732 return true; 2733 } 2734 2735 /** 2736 * Helper method that handles building the assertion failure exceptions. 2737 * They are returned from this method so that the stack trace still shows 2738 * the assertions method. 2739 * 2740 * @param mixed $value 2741 * @param string|callable|null $message 2742 * @param int $code 2743 * @param string|null $propertyPath 2744 * @param array $constraints 2745 * 2746 * @return mixed 2747 */ 2748 protected static function createException($value, $message, $code, string $propertyPath = null, array $constraints = []) 2749 { 2750 $exceptionClass = static::$exceptionClass; 2751 2752 return new $exceptionClass($message, $code, $propertyPath, $value, $constraints); 2753 } 2754 2755 /** 2756 * Make a string version of a value. 2757 * 2758 * @param mixed $value 2759 * 2760 * @return string 2761 */ 2762 protected static function stringify($value): string 2763 { 2764 $result = \gettype($value); 2765 2766 if (\is_bool($value)) { 2767 $result = $value ? '<TRUE>' : '<FALSE>'; 2768 } elseif (\is_scalar($value)) { 2769 $val = (string)$value; 2770 2771 if (\strlen($val) > 100) { 2772 $val = \substr($val, 0, 97).'...'; 2773 } 2774 2775 $result = $val; 2776 } elseif (\is_array($value)) { 2777 $result = '<ARRAY>'; 2778 } elseif (\is_object($value)) { 2779 $result = \get_class($value); 2780 } elseif (\is_resource($value)) { 2781 $result = \get_resource_type($value); 2782 } elseif (null === $value) { 2783 $result = '<NULL>'; 2784 } 2785 2786 return $result; 2787 } 2788 2789 /** 2790 * Generate the message. 2791 * 2792 * @param string|callable|null $message 2793 * 2794 * @return string 2795 */ 2796 protected static function generateMessage($message): string 2797 { 2798 if (\is_callable($message)) { 2799 $traces = \debug_backtrace(0); 2800 2801 $parameters = []; 2802 2803 try { 2804 $reflection = new ReflectionClass($traces[1]['class']); 2805 $method = $reflection->getMethod($traces[1]['function']); 2806 foreach ($method->getParameters() as $index => $parameter) { 2807 if ('message' !== $parameter->getName()) { 2808 $parameters[$parameter->getName()] = \array_key_exists($index, $traces[1]['args']) 2809 ? $traces[1]['args'][$index] 2810 : $parameter->getDefaultValue(); 2811 } 2812 } 2813 2814 $parameters['::assertion'] = \sprintf('%s%s%s', $traces[1]['class'], $traces[1]['type'], $traces[1]['function']); 2815 2816 $message = \call_user_func_array($message, [$parameters]); 2817 } // @codeCoverageIgnoreStart 2818 catch (Throwable $exception) { 2819 $message = \sprintf('Unable to generate message : %s', $exception->getMessage()); 2820 } // @codeCoverageIgnoreEnd 2821 } 2822 2823 return (string)$message; 2824 } 2825 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body