PK g¾zN'kŅ Ņ Autoloader.phpnu W+A¶ _namespacePrefixesToBaseDirectories[$prefix])) {
$this->_namespacePrefixesToBaseDirectories[$prefix] = [];
}
if (true === $prepend) {
array_unshift(
$this->_namespacePrefixesToBaseDirectories[$prefix],
$baseDirectory
);
} else {
array_push(
$this->_namespacePrefixesToBaseDirectories[$prefix],
$baseDirectory
);
}
return;
}
/**
* Try to load the entity file for a given entity name.
*
* @param string $entity Entity name to load.
* @return bool
*/
public function load($entity)
{
$entityPrefix = $entity;
$hasBaseDirectory = false;
while (false !== $pos = strrpos($entityPrefix, '\\')) {
$currentEntityPrefix = substr($entity, 0, $pos + 1);
$entityPrefix = rtrim($currentEntityPrefix, '\\');
$entitySuffix = substr($entity, $pos + 1);
$entitySuffixAsPath = str_replace('\\', '/', $entitySuffix);
if (false === $this->hasBaseDirectory($currentEntityPrefix)) {
continue;
}
$hasBaseDirectory = true;
foreach ($this->getBaseDirectories($currentEntityPrefix) as $baseDirectory) {
$file = $baseDirectory . $entitySuffixAsPath . '.php';
if (false !== $this->requireFile($file)) {
return $file;
}
}
}
if (true === $hasBaseDirectory &&
$entity === Consistency::getEntityShortestName($entity) &&
false !== $pos = strrpos($entity, '\\')) {
return $this->runAutoloaderStack(
$entity . '\\' . substr($entity, $pos + 1)
);
}
return null;
}
/**
* Require a file if exists.
*
* @param string $filename File name.
* @return bool
*/
public function requireFile($filename)
{
if (false === file_exists($filename)) {
return false;
}
require $filename;
return true;
}
/**
* Check whether at least one base directory exists for a namespace prefix.
*
* @param string $namespacePrefix Namespace prefix.
* @return bool
*/
public function hasBaseDirectory($namespacePrefix)
{
return isset($this->_namespacePrefixesToBaseDirectories[$namespacePrefix]);
}
/**
* Get declared base directories for a namespace prefix.
*
* @param string $namespacePrefix Namespace prefix.
* @return array
*/
public function getBaseDirectories($namespacePrefix)
{
if (false === $this->hasBaseDirectory($namespacePrefix)) {
return [];
}
return $this->_namespacePrefixesToBaseDirectories[$namespacePrefix];
}
/**
* Get loaded classes.
*
* @return array
*/
public static function getLoadedClasses()
{
return get_declared_classes();
}
/**
* Run the entire autoloader stack with a specific entity.
*
* @param string $entity Entity name to load.
* @return void
*/
public function runAutoloaderStack($entity)
{
return spl_autoload_call($entity);
}
/**
* Register the autoloader.
*
* @param bool $prepend Prepend this autoloader to the stack or not.
* @return bool
*/
public function register($prepend = false)
{
return spl_autoload_register([$this, 'load'], true, $prepend);
}
/**
* Unregister the autoloader.
*
* @return bool
*/
public function unregister()
{
return spl_autoload_unregister([$this, 'load']);
}
/**
* Get all registered autoloaders (not only from this library).
*
* @return array
*/
public function getRegisteredAutoloaders()
{
return spl_autoload_functions();
}
/**
* Dynamic new, a simple factory.
* It loads and constructs a class, with provided arguments.
*
* @param bool $classname Classname.
* @param array $arguments Arguments for the constructor.
* @return object
*/
public static function dnew($classname, array $arguments = [])
{
$classname = ltrim($classname, '\\');
if (false === Consistency::entityExists($classname, false)) {
spl_autoload_call($classname);
}
$class = new \ReflectionClass($classname);
if (empty($arguments) || false === $class->hasMethod('__construct')) {
return $class->newInstance();
}
return $class->newInstanceArgs($arguments);
}
}
/**
* Autoloader.
*/
$autoloader = new Autoloader();
$autoloader->addNamespace('Hoa', dirname(__DIR__));
$autoloader->register();
PK g¾zNdĒ°ńŹ Ź .travis.ymlnu W+A¶ language: php
matrix:
include:
- php: 5.5
- php: 5.6
- php: 7.0
- php: 7.1
env:
- ENABLE_XDEBUG=true
- php: 7.1
env:
- ENABLE_DEVTOOLS=true
- php: nightly
- php: hhvm-3.12
sudo: required
dist: trusty
group: edge
- php: hhvm
sudo: required
dist: trusty
group: edge
allow_failures:
- php: nightly
- php: hhvm-3.12
- php: hhvm
fast_finish: true
os:
- linux
notifications:
irc: "chat.freenode.net#hoaproject"
sudo: false
env:
global:
- secure: "AAAAB3NzaC1yc2EAAAADAQABAAACAQDIf0Rf76Hhkflz5b9UzWjOjk4UlMU5ySk0VY3B4WdHDLWMMK7fBp1Aj9qXWEDwkuX/NbQP1gB8jQNo7i5uZEOfu7Mn2svPkBBtnmKmaJhk90xypM4lcpcdPi4e8kXUgkriNQLQ2bRe1qZIeF115FkuIvActq7iWKY1TVSZbO54cDKMifDZfH09cf4vpwrZJqwZG6PUnUcCYijgDy99HtfRvzf9xalO4yWm55ZEbJ/VNTHlq1EhK73QLdHC7MO+OQFcd5wEyMbNxBj/bDn/udgb0HsrDijComTg/oTdQJMspYDQYV3ZYvpGozTTCVQrVTYYTP9RCNstgJLHDv9fZZW6yRlw4yNsT7jIQRLs/7awTxOAvRlxqaxk0//ECVNhDgawVtlbEIKrqnM1N7QTm0gjE0HkWEzxE0QbgoZqlLFD6qCp6WVvIT3uGY/i4TkVy78wf3/fzCKbrf72kYSbxIOCxVtptOmrgAblNEpiA/uZ9IofR2p2iwiVY1xF/mzxV2M4zCw6WASrlDhkaL0IncEdRtBuV2WTpixmtjmNkE9h/90kzb5cKExU786gZmvyflYvqlNlcMo3dNsDnROjQCAUXGBw5+risdqTT295BGmlEdZUtcf0c6/zEGhR8B7CktWYLSgOL5mpGMVNEBzyzEwnIiWCvI3pGgoV3Z9UzSJWKQ=="
cache:
directories:
- vendor/
before_script:
- export PATH="$PATH:$HOME/.composer/vendor/bin"
- if [[ ! $ENABLE_XDEBUG ]]; then
phpenv config-rm xdebug.ini || echo "ext-xdebug is not available, cannot remove it.";
fi
script:
- composer install
- vendor/bin/hoa test:run
- if [[ $ENABLE_DEVTOOLS ]]; then
composer global require friendsofphp/php-cs-fixer;
vendor/bin/hoa devtools:cs --diff --dry-run .;
fi
PK g¾zNY`ńi Prelude.phpnu W+A¶
---
Hoa is a modular, extensible and
structured set of PHP libraries.
Moreover, Hoa aims at being a bridge between industrial and research worlds.
# Hoa\Consistency
[![Help on IRC](https://img.shields.io/badge/help-%23hoaproject-ff0066.svg)](https://webchat.freenode.net/?channels=#hoaproject)
[![Help on Gitter](https://img.shields.io/badge/help-gitter-ff0066.svg)](https://gitter.im/hoaproject/central)
[![Documentation](https://img.shields.io/badge/documentation-hack_book-ff0066.svg)](https://central.hoa-project.net/Documentation/Library/Consistency)
[![Board](https://img.shields.io/badge/organisation-board-ff0066.svg)](https://waffle.io/hoaproject/consistency)
This library provides a thin layer between PHP VMs and libraries to ensure
consistency accross VM versions and library versions.
[Learn more](https://central.hoa-project.net/Documentation/Library/Consistency).
## Installation
With [Composer](https://getcomposer.org/), to include this library into
your dependencies, you need to
require [`hoa/consistency`](https://packagist.org/packages/hoa/consistency):
```sh
$ composer require hoa/consistency '~1.0'
```
For more installation procedures, please read [the Source
page](https://hoa-project.net/Source.html).
## Testing
Before running the test suites, the development dependencies must be installed:
```sh
$ composer install
```
Then, to run all the test suites:
```sh
$ vendor/bin/hoa test:run
```
For more information, please read the [contributor
guide](https://hoa-project.net/Literature/Contributor/Guide.html).
## Quick usage
We propose a quick overview of how the consistency API ensures foreward and
backward compatibility, also an overview of the [PSR-4
autoloader](http://www.php-fig.org/psr/psr-4/) and the xcallable API.
### Foreward and backward compatibility
The `Hoa\Consistency\Consistency` class ensures foreward and backward
compatibility.
#### Example with keywords
The `Hoa\Consistency\Consistency::isKeyword` checks whether a specific word is
reserved by PHP or not. Let's say your current PHP version does not support the
`callable` keyword or type declarations such as `int`, `float`, `string` etc.,
the `isKeyword` method will tell you if they are reserved keywords: Not only
for your current PHP version, but maybe in an incoming version.
```php
$isKeyword = Hoa\Consistency\Consistency::isKeyword('yield');
```
It avoids to write algorithms that might break in the future or for your users
living on the edge.
#### Example with identifiers
PHP identifiers are defined by a regular expression. It might change in the
future. To prevent breaking your algorithms, you can use the
`Hoa\Consistency\Consistency::isIdentifier` method to check an identifier is
correct regarding current PHP version:
```php
$isValidIdentifier = Hoa\Consistency\Consistency::isIdentifier('foo');
```
#### Flexible entities
Flexible entities are very simple. If we declare `Foo\Bar\Bar` as a flexible
entity, we will be able to access it with the `Foo\Bar\Bar` name or `Foo\Bar`.
This is very useful if your architecture evolves but you want to keep the
backward compatibility. For instance, it often happens that you create a
`Foo\Bar\Exception` class in the `Foo/Bar/Exception.php` file. But after few
versions, you realise other exceptions need to be introduced, so you need an
`Exception` directory. In this case, `Foo\Bar\Exception` should move as
`Foo\Bar\Exception\Exception`. If this latter is declared as a flexible entity,
backward compatibility will be kept.
```php
Hoa\Consistency\Consistency::flexEntity('Foo\Bar\Exception\Exception');
```
Another example is the āentry-classā (informal naming).
`Hoa\Consistency\Consistency` is a good example. This is more convenient to
write `Hoa\Consistency` instead of `Hoa\Consistency\Consistency`. This is
possible because this is a flexible entity.
#### Throwable & co.
The `Throwable` interface has been introduced to represent a whole new exception
architecture in PHP. Thus, to be compatible with incoming PHP versions, you
might want to use this interface in some cases. Hopefully, the `Throwable`
interface will be created for you if it does not exists.
```php
try {
ā¦
} catch (Throwable $e) {
ā¦
}
```
### Autoloader
`Hoa\Consistency\Autoloader` is a [PSR-4
compatible](http://www.php-fig.org/psr/psr-4/) autoloader. It simply works as
follows:
* `addNamespace` is used to map a namespace prefix to a directory,
* `register` is used to register the autoloader.
The API also provides the `load` method to force the load of an entity,
`unregister` to unregister the autoloader, `getRegisteredAutoloaders` to get
a list of all registered autoloaders etc.
For instance, to map the `Foo\Bar` namespace to the `Source/` directory:
```php
$autoloader = new Hoa\Consistency\Autoloader();
$autoloader->addNamespace('Foo\Bar', 'Source');
$autoloader->register();
$baz = new Foo\Bar\Baz(); // automatically loaded!
```
### Xcallable
Xcallables are āextended callablesā. It is a unified API to invoke callables of
any kinds, and also extends some Hoa's API (like
[`Hoa\Event`](https://central.hoa-project.net/Resource/Library/Event)
or
[`Hoa\Stream`](https://central.hoa-project.net/Resource/Library/Stream)). It
understands the following kinds:
* `'function'` as a string,
* `'class::method'` as a string,
* `'class', 'method'` as 2Ā string arguments,
* `$object, 'method'` as 2Ā arguments,
* `$object, ''` as 2Ā arguments, the āableā is unknown,
* `function (ā¦) { ā¦ }` as a closure,
* `['class', 'method']` as an array of strings,
* `[$object, 'method']` as an array.
To use it, simply instanciate the `Hoa\Consistency\Xcallable` class and use it
as a function:
```php
$xcallable = new Hoa\Consistency\Xcallable('strtoupper');
var_dump($xcallable('foo'));
/**
* Will output:
* string(3) "FOO"
*/
```
The `Hoa\Consistency\Xcallable::distributeArguments` method invokes the callable
but the arguments are passed as an array:
```php
$xcallable->distributeArguments(['foo']);
```
This is also possible to get a unique hash of the callable:
```php
var_dump($xcallable->getHash());
/**
* Will output:
* string(19) "function#strtoupper"
*/
```
Finally, this is possible to get a reflection instance of the current callable
(can be of kind [`ReflectionFunction`](http://php.net/ReflectionFunction),
[`ReflectionClass`](http://php.net/ReflectionClass),
[`ReflectionMethod`](http://php.net/ReflectionMethod) or
[`ReflectionObject`](http://php.net/ReflectionObject)):
```php
var_dump($xcallable->getReflection());
/**
* Will output:
* object(ReflectionFunction)#42 (1) {
* ["name"]=>
* string(10) "strtoupper"
* }
*/
```
When the object is set but not the method, the latter will be deduced if
possible. If the object is of kind
[`Hoa\Stream`](http://central.hoa-project.net/Resource/Library/Stream), then
according to the type of the arguments given to the callable, the
`writeInteger`, `writeString`, `writeArray` etc. method will be used. If the
argument is of kind `Hoa\Event\Bucket`, then the method name will be deduced
based on the data contained inside the event bucket. This is very handy. For
instance, the following example will work seamlessly:
```php
Hoa\Event\Event::getEvent('hoa://Event/Exception')
->attach(new Hoa\File\Write('Exceptions.log'));
```
The `attach` method on `Hoa\Event\Event` transforms its argument as an
xcallable. In this particular case, the method to call is unknown, we only have
an object (of kind `Hoa\File\Write`). However, because this is a stream, the
method will be deduced according to the data contained in the event bucket fired
on the `hoa://Event/Exception` event channel.
## Documentation
The
[hack book of `Hoa\Consistency`](https://central.hoa-project.net/Documentation/Library/Consistency)
contains detailed information about how to use this library and how it works.
To generate the documentation locally, execute the following commands:
```sh
$ composer require --dev hoa/devtools
$ vendor/bin/hoa devtools:documentation --open
```
More documentation can be found on the project's website:
[hoa-project.net](https://hoa-project.net/).
## Getting help
There are mainly two ways to get help:
* On the [`#hoaproject`](https://webchat.freenode.net/?channels=#hoaproject)
IRC channel,
* On the forum at [users.hoa-project.net](https://users.hoa-project.net).
## Contribution
Do you want to contribute? Thanks! A detailed [contributor
guide](https://hoa-project.net/Literature/Contributor/Guide.html) explains
everything you need to know.
## License
Hoa is under the New BSD License (BSD-3-Clause). Please, see
[`LICENSE`](https://hoa-project.net/LICENSE) for details.
PK g¾zN/6bó*&