stubbles / values
Useful classes to ease the work with values.
Installs: 8 383
Dependents: 6
Suggesters: 1
Security: 0
Stars: 1
Watchers: 3
Forks: 1
Open Issues: 2
Requires
- php: ^8.2
- ext-mbstring: *
Requires (Dev)
- bovigo/assert: ^8.0
- bovigo/callmap: ^8.0
- mikey179/vfsstream: ^1.6.11
- phpunit/phpunit: ^10.5
README
Useful classes to ease the work with values.
Build status
Installation
stubbles/values is distributed as Composer package. To install it as a dependency of your package use the following command:
composer require "stubbles/values": "^11.0"
Requirements
stubbles/values requires at least PHP 8.2.
Available classes
stubbles\values\Result
Enables to wrap a return value which might be null
. In other languages or
libraries this is known as an Optional. To create an instance call
Result::of(someCallThatMightReturnNull())
.
isPresent()
Returns true
when result contains a value which is not null
.
isEmpty()
Returns true
when result contains an empty value. Please note that this method
will always return false
in case the value is an integer, even if it is 0.
value()
Returns the actual value.
filter(callable $predicate)
Allows to filter the value. In case the value fulfills the given predicate the
Result
instance is returned. If the value does not fulfill the predicate the
equivalent of Result::of(null)
is returned.
$filter = fn($value) => 303 === $value; echo Result::of(303)->filter($filter)->value(); // displays 303 echo Result::of(313)->filter($filter)->value(); // displays nothing echo Result::of(null)->filter($filter)->value(); // displays nothing
map(callable $mapper)
Maps the value using the given mapper into a different result. In case the value
is null
the return value still is equivalent to Result::of(null)
.
$mapper = fn($value) => 'Roland TB 303'; echo Result::of(303)->map($mapper)->value(); // displays "Roland TB 303" echo Result::of(null)->map($mapper)->value(); // displays nothing
whenNull($other)
Returns the result if value is present, or result of other.
$default = 909; echo Result::of(303)->whenNull($default)->value(); // displays 303 echo Result::of(null)->whenNull($default)->value(); // displays 909
applyWhenNull(callable $other)
Returns the result if value is present, or the result of applied other.
$default = function() { return 909; }; echo Result::of(303)->applyWhenNull($default)->value(); // displays 303 echo Result::of(null)->applyWhenNull($default)->value(); // displays 909
whenEmpty($other)
Returns the result if value is not empty, or result of other.
$default = 'Roland TB 303'; echo Result::of('Roland 909')->whenEmpty($default)->value(); // displays Roland 909 echo Result::of('')->whenEmpty($default)->value(); // displays Roland TB 303
applyWhenEmpty($other)
Returns the result if value is not empty, or result of applied other.
$default = fn() => 'Roland TB 303'; echo Result::of('Roland 909')->applyWhenEmpty($default)->value(); // displays Roland 909 echo Result::of('')->applyWhenEmpty($default)->value(); // displays Roland TB 303
stubbles\values\Secret
Secret provides a reasonable secure storage for security-sensitive lists of characters, such as passwords.
It prevents accidentially revealing them in output, by var_dump()ing, echo()ing, or casting the object to array. All these cases will not show the password, nor the crypt of it.
However, it is not safe to consider this implementation secure in a crypto- graphically sense, because it does not care for a very strong encryption, and it does share the encryption key with all instances of it in a single PHP instance.
When using this class, you must make sure not to extract the secured string and pass it to a place where an exception might occur, as it might be exposed as method argument.
Instances of this class can not be serialized.
Create a secret
To create a secret call Secret::create('my secret value')
.
Please note that you can not use this function to create a secret with value
null
. If you explicitly want to do that use Secret::forNull()
.
isContained(): bool
Checks whether encryption on creation was successful. In case it failed no errors or exception is thrown, so this is the only way to check.
isNull(): bool
Checks if actual secret is null
.
unveil(): string
Unveils the secret and returns it as a string. This should be called at the latest possible moment to avoid unneccessary revealing of the value to be intended stored secure.
substring(int $start, int $length = null): Secret
Creates a substring of the secret value as new Secret
instance.
Please note that this method is deprecated since release 10.0.0 and will be removed with 11.0.0.
length(): int
Returns length of the secret. Allows to check if it would fit a certain place without the need to unveil it first.
stubbles\values\Parse
Provides methods for parsing strings to a target type.
Parse::toInt($value)
Parses integer value from given string.
Parse::toFloat($value)
Parses float value from given string.
Parse::toBool($string)
Parses boolean value from given string. The return value is true if the string value is either "1", "yes", "true" or "on". In any other case the return value will be false.
Parse::toList($string, string $separator = '|')
Parses string to a list of strings.
If the value is empty the return value will be an empty array. If the value is not empty it will be splitted at "|" (or any other separator provided).
Parse::toList("foo|bar|baz"); // results in ['foo', 'bar', 'baz']
Parse::toMap($string)
Parses string to a map.
If the value is empty the return value will be an empty map. If the value is not empty it will be splitted at "|". The resulting list will be splitted at the first ":", the first part becoming the key and the remainer becoming the value in the map. If no ":" is present, the whole value will be appended to the map using a numeric value for the key.
Parse::toMap("foo:bar|baz"); // results in ['foo' => 'bar', 'baz']
Parse::toRange($string)
Parses string to a range.
Ranges can be written as 1..5 which will return an array: [1, 2, 3, 4, 5]. Works also with letters and reverse order a..e, e..a and 5..1.
Parse::toClass($string)
Parses string to a reflection class.
String must have the format fully\qualified\Classname.class. In case the
string can not be parsed the return value is null
.
Parse::toClassname($string)
Parses string as existing class name.
String must have the format fully\qualified\Classname::class. In case the
string can not be parsed or the class does not exist the return value is null
.
stubbles\values\Properties
Provides a convenient way to read property files and make their values accessible. Properties can both be read from a string you might have in memory or from a file:
$properties = Properties::fromString($propertyString); $properties = Properties::fromFile('path/to/properties.ini');
Properties consist of sections, which each has a list of key-value pairs. Suppose the following properties file:
[config] cool.stuff = "Roland TB 303" interesting = "Pink fluffy unicorns dancing on rainbows" [other] the.answer = 42 github = true
Here, the properties consists of the sections config and other, where both have different key-value pairs, cool.stuff and interesting belong to config and the other two to other.
You can get the raw value of a property:
$answer = $properties->getValue('other', 'the.answer'); // $answer now has the value "42" of type string
However, that might not be what you wanted to achieve. Rather, you would like to have a correct type. That's where the parse*() methods come into play:
$answer = $properties->parseInt('other', 'the.answer'); // $answer now has the value 42 of type int
parse(string $section, string $key)->asInt(): ?int
Tries to read the value and convert it to int.
If you want to have a default value in case the section or key is not set, use
parse($section, $key)->defaultingTo(42)->asInt()
. Please note that the given default value must be of type int
.
parse(string $section, string $key)->asFloat(): ?float
Tries to read the value and convert it to float.
If you want to have a default value in case the section or key is not set, use
parse($section, $key)->defaultingTo(3.03)->asFloat()
. Please note that the given default value must be of type float
.
parse(string $section, string $key)->asBool(): ?bool
Tries to read the value and convert it to boolean.
The following value contents will be converted to true
:
- yes
- true
- on
All other values will evaluate to false
.
If you want to have a default value of true
in case the section or key is not set, use
parse($section, $key)->defaultingTo(true)->asBool()
. Please note that the given default value must be of type bool
. It is not required to explicitly specify false
as default value. In case the section or key is not set false
will be the return default value if not specified otherwise.
parse(string $section, string $key)->asList(): ?array
Tries to read the value and convert it to a list (array with integers as key).
If the value is empty the return value will be an empty array. If the value is
not empty it will be splitted at |. So if the value would be key = foo|bar|baz
it gets converted to ['foo', 'bar', 'baz']
.
If you want to have a default value in case the section or key is not set, use
parse($section, $key)->defaultingTo(['foo', 'bar'])->asList()
. Please note that the given default value must be of type array
.
parse(string $section, string $key)->asMap(): ?array
Tries to read the value and convert it to a hashmap.
If the value is empty the return value will be an empty hash. If the value is
not empty it will be splitted at |. The resulting array will be splitted at
the first :, the first part becoming the key and the remaining part becoming
the value in the hash. If no : is present, the whole value will be appended to
the hash using a numeric value. So key = foo:bar|baz results in
['foo' => 'bar', 'baz']
.
If you want to have a default value in case the section or key is not set, use
parse($section, $key)->defaultingTo(['foo' => 'bar'])->asMap()
. Please note that the given default value must be of type array
.
parse(string $section, string $key)->asRange(): ?array
Tries to read the value and convert it to a range.
Ranges in properties should be written as key = 1..5 the resulting value is
[1, 2, 3, 4, 5]
.
This works also with letters and reverse order:
letters = a..e
letter_reverse = e..a
numbers_reverse = 5..1
If you want to have a default value in case the section or key is not set, use
parse($section, $key)->defaultingTo([1, 2, 3])->asRange()
. Please note that the given default value must be of type array
.
parse(string $section, string $key)->asClass(): ?ReflectionClass
Tries to read the value and convert it to an instance of ReflectionClass
for the class name.
Classes in properties should be written as _key = foo\bar\Baz.class.
If you want to have a default value in case the section or key is not set, use
parse($section, $key)->defaultingTo(new ReflectionClass(stdClass::class))->asClass()
. Please note that the given default value must be of type ReflectionClass
.
Passwords
Available since release 4.0.0
Since release 4.0.0, properties with key password
will be stored as an
instance of stubbles|values\Secret
. This will also be the return value when
requesting the value of such a property.
Modifiable properties
Available since release 1.7.0
By default properties are read only. In case you need modifiable properties use
the stubbles\values\ModifiableProperties
class. It provides means to set
property values:
setSection(string $section, array $data)
Sets a complete section with given section name. In case this section already exists it will be replaced.
setValue(string $section, string $name, $value)
Sets a single property value.
setBooleanValue(string $section, string $name, $value)
Sets a single property to a boolean value in a way that it can be read properly
by parseBool()
.
setArrayValue(string $section, string $name, array $value)
Sets an array property to a value in a way that it can be read properly by
parseArray()
.
setHashValue(string $section, string $name, array $hash)
Sets a map property to a value in a way that it can be read properly by
parseHash()
.
setRangeValue(string $section, string $name, array $range)
Sets a range property to a value in a way that it can be read properly by
parseRange()
.
unmodifiable()
Available since release 4.0.0
Returns an unmodifiable instance from the modifiable properties.
stubbles\values\ResourceLoader
Available since release 7.1.0
Description
The stubbles\values\ResourceLoader
allows to load resources from different
locations. It relies on the root path as described below.
In stubbles/values, a resource is defined as any kind of file which is located
in the path src/main/resources
of the current project, or in src/main/resources
of any other Composer package located in vendor
.
open(string $resource, string $withClass = 'stubbles\streams\file\FileInputStream')
Opens the given resource to read its contents using the given $withClass
. This
class must accept the resource path as constructor argument. By default the
class stubbles\streams\file\FileInputStream
will be used, but the package
stubbles/streams which provides
this class must be required in your project.
Resource can either be a complete path to a resource or a local path. In case it
is a local path it is searched within the src/main/resources
folder of the
current project.
It is not possible to open resources outside of the root path by providing a complete path, a complete path must always lead to a resource located within the root path.
load(string $resource)
Loads resource contents. Resource can either be a complete path to a resource or
a local path. In case it is a local path it is searched within the
src/main/resources
folder of the current project.
It is not possible to load resources outside of the root path by providing a complete path, a complete path must always lead to a resource located within the root path.
$props = $resourceLoader->load('some/properties.ini');
loadWith(string $resource, callable $loader)
Loads resource contents. Resource can either be a complete path to a resource or
a local path. In case it is a local path it is searched within the
src/main/resources
folder of the current project.
It is not possible to load resources outside of the root path by providing a complete path, a complete path must always lead to a resource located within the root path.
The given $loader
must accept a path and return the
result from the load operation:
$props = $resourceLoader->loadWith( 'some/properties.ini', fn($path) => Properties::fromFile($path) );
availableResourceUris(string $resourceName): array
Returns a list of all available URIs for a resource. The returned list is sorted alphabetically, meaning that local resources of the current project are always returned as first entry if they exist, and all vendor resources after. Order of vendor resources is also in alphabetical order of vendor/package names.
stubbles\values\Rootpath
Available since release 7.1.0
Description
The root path within a project is represented by stubbles\values\Rootpath
. It
is defined as the path in which the whole application resides. When an instance
is created and no argument is provided, the class will calculate the root path
by checking the following locations:
- In case the application is inside a phar, it's the directory where the phar is stored.
- Try to locate the
vendor/autoload.php
file generated by Composer, and go up one abovevendor/..
.
For unit tests it can be useful to supply the actual root path to be used for the test directly when constructing the class.
to(string ...$path): string
Returns absolute path to given local path. Supports arbitrary lists of arguments,
e.g. $rootpath->to('src', 'main', 'php', 'Example.php')
will return
/absolute/path/to/root/src/main/php/Example.php
.
contains(string $path): bool
Checks if given path is located within root path.
sourcePathes(): array
Returns a list of all source pathes defined for the autoloader. It relies on autoloader files generated by Composer. If no such autoloader is present the list of source pathes will be empty.
Rootpath::default(): string
Available since release 8.1.0
A static method which returns the rootpath directly as string when not instance is required.
stubbles\values\Value
Available since release 7.2.0
Description
Represents a single value, mostly scalar ones, on which certain checks can be done. Some of the checks are built-in, but additional checks can be defined.
Create an instance with Value::of($someValue)
. In case $someValue
is null
a fixed value instance will be used. For all times there is only one instance
of Value::of(null)
- each creation with null
will return the same instance.
To access the stored value call $actualValue = $value->value()
.
contains($needle): bool
Checks if the value contains the needle. In case the value is a string it is
checked whether $needle
is a substring within the value. In case the value is
an array or an instance of \Traversable
the given $needle
must be an element
within the array or traversable.
containsAnyOf(array $elements): bool
Checks if the value contains any of the given elements.
equals($expected): bool
Checks if the value equals the expected value. Expected value must be a non-null
scalar value. Comparison is done using ===
.
isOneOf(array $allowedValues, bool $strict = false): bool
Checks if the value equals one of the allowed values. In case the value itself
is an array this method returns false
if it contains a value which is not in
the list of allowed values.
Sometimes it is necessary that the value type must also be equal. In such cases
the flag $strict
should be set to true
.
isMatchedBy(string $regex): bool
Checks if the value can be matched by the given regular expression.
satisfies(callable $check): bool
Checks if the value satisfies the given callable. The given callable must accept a single value, its return value is returned.
isNull(): bool
Available since release 8.1.0
Checks if the value is null
.
isEmpty(): bool
Available since release 8.1.0
Checks if the value is empty. A value is empty if it is null
, an empty string
or an empty array.
Define additional checks
Additional checks can be defined:
Values::defineCheck('hasPower', function($value) { return 6100 == $value; });
After the definition this check can be used as follows: Value::of($someValue)->hasPower()
Existing PHP functions must not be defined, they are available automatically:
Value::of($someValue)->is_int()
Available functions
stubbles\values\lastErrorMessage(): Result
Returns the message of the native PHP function error_get_last()['message']
as
instance of stubbles\values\Result
.
stubbles\values\typeOf(&$value): string
Returns the correct type of given value.
For objects the actual class name will be returned. In case of resources the
return value will be resource[type_of_resource], e.g. resource[stream]. For
all other types the result is call to PHP's native gettype()
function.
stubbles\values\pattern($pattern): Pattern
Available since release 7.1.0.
Creates a pattern from regular expression which can be used to match other string values.
The pattern uses preg_match() and checks if the value occurs exactly one time. Please make sure that the supplied regular expression contains correct delimiters, they will not be applied automatically. The matches() method throws a \RuntimeException in case the regular expression is invalid.