N°5122 - Update libs to new PHP requirements

This commit is contained in:
Molkobain
2022-08-08 14:10:26 +02:00
parent 30021d9236
commit 57c36d0e51
585 changed files with 62279 additions and 20427 deletions

View File

@@ -1,696 +0,0 @@
# Changelog
All notable changes to this project will be documented in this file, in reverse chronological order by release.
## 3.5.2 - 2021-01-17
-----
### Release Notes for [3.5.2](https://github.com/laminas/laminas-servicemanager/milestone/6)
3.5.x bugfix release (patch)
### 3.5.2
- Total issues resolved: **0**
- Total pull requests resolved: **1**
- Total contributors: **1**
#### Bug
- [75: backported testConfigureInvokablesTakePrecedenceOverFactories to 3.5.x](https://github.com/laminas/laminas-servicemanager/pull/75) thanks to @driehle
## 3.5.1 - 2020-12-01
### Release Notes for [3.5.1](https://github.com/laminas/laminas-servicemanager/milestone/4)
This is a full revert of release `3.5.0`.
`3.5.0` contained multiple backwards-incompatible (BC) breakages that were not
supposed to be released in a minor version, and therefore had to be reverted.
Due to unfortunate branch naming issues when migrating from the old `develop`
branch, `develop` was renamed `3.5.x`, but contained multiple BC breaks that
were fundamentally incompatible with the `3.0.0` and newer features.
Due to the quick response time, in order to not break further downstream systems
that yet have to receive the update, the `3.5.0` release was deleted, so that
it does not appear in your system if you accidentally run `composer update`.
Thanks to @fabiang for promptly detecting the issue and reporting it
at https://github.com/laminas/laminas-servicemanager/issues/59
### 3.5.1
- Total issues resolved: **1**
- Total pull requests resolved: **0**
- Total contributors: **1**
#### BC Break,Bug
- [59: `ContainerInterface` reference was changed in a minor release](https://github.com/laminas/laminas-servicemanager/issues/59) thanks to @fabiang
## 3.4.1 - 2020-05-11
### Added
- Nothing.
### Changed
- Nothing.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- [#28](https://github.com/laminas/laminas-servicemanager/pull/28) provides updates to the `ConfigAbstractFactory` to ensure it works correctly under PHP 7.4 when the `config` service is represented by an `ArrayObject` or `ArrayAccess` implementation.
- [#35](https://github.com/laminas/laminas-servicemanager/pull/35) updates two exception messagers from the `ConfigAbstractFactory` to be more clear about what caused them.
## 3.4.0 - 2018-12-22
### Added
- [zendframework/zend-servicemanager#275](https://github.com/zendframework/zend-servicemanager/pull/275) Enables
plugin managers to accept as a creation context PSR Containers not
implementing Interop interface
### Changed
- Nothing.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- [zendframework/zend-servicemanager#268](https://github.com/zendframework/zend-servicemanager/pull/268) Fixes
ReflectionBasedAbstractFactory trying to instantiate classes with private
constructors
## 3.3.2 - 2018-01-29
### Added
- Nothing.
### Changed
- Nothing.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- [zendframework/zend-servicemanager#243](https://github.com/zendframework/zend-servicemanager/pull/243) provides
a fix to the `ReflectionBasedAbstractFactory` to resolve type-hinted arguments
with default values to their default values if no matching type is found in
the container.
- [zendframework/zend-servicemanager#233](https://github.com/zendframework/zend-servicemanager/pull/233) fixes a
number of parameter annotations to reflect the actual types used.
## 3.3.1 - 2017-11-27
### Added
- [zendframework/zend-servicemanager#201](https://github.com/zendframework/zend-servicemanager/pull/201) and
[zendframework/zend-servicemanager#202](https://github.com/zendframework/zend-servicemanager/pull/202) add
support for PHP versions 7.1 and 7.2.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- [zendframework/zend-servicemanager#206](https://github.com/zendframework/zend-servicemanager/pull/206) fixes an
issue where by callables in `Class::method` notation were not being honored
under PHP 5.6.
## 3.3.0 - 2017-03-01
### Added
- [zendframework/zend-servicemanager#180](https://github.com/zendframework/zend-servicemanager/pull/180) adds
explicit support for PSR-11 (ContainerInterface) by requiring
container-interop at a minimum version of 1.2.0, and adding a requirement on
psr/container 1.0. `Laminas\ServiceManager\ServiceLocatorInterface` now
explicitly extends the `ContainerInterface` from both projects.
Factory interfaces still typehint against the container-interop variant, as
changing the typehint would break backwards compatibility. Users can
duck-type most of these interfaces, however, by creating callables or
invokables that typehint against psr/container instead.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- Nothing.
## 3.2.1 - 2017-02-15
### Added
- [zendframework/zend-servicemanager#176](https://github.com/zendframework/zend-servicemanager/pull/176) adds
the options `-i` or `--ignore-unresolved` to the shipped
`generate-deps-for-config-factory` command. This flag allows it to build
configuration for classes resolved by the `ConfigAbstractFactory` that
typehint on interfaces, which was previously unsupported.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- [zendframework/zend-servicemanager#174](https://github.com/zendframework/zend-servicemanager/pull/174) updates
the `ConfigAbstractFactory` to allow the `config` service to be either an
`array` or an `ArrayObject`; previously, only `array` was supported.
## 3.2.0 - 2016-12-19
### Added
- [zendframework/zend-servicemanager#146](https://github.com/zendframework/zend-servicemanager/pull/146) adds
`Laminas\ServiceManager\AbstractFactory\ConfigAbstractFactory`, which enables a
configuration-based approach to providing class dependencies when all
dependencies are services known to the `ServiceManager`. Please see
[the documentation](docs/book/config-abstract-factory.md) for details.
- [zendframework/zend-servicemanager#154](https://github.com/zendframework/zend-servicemanager/pull/154) adds
`Laminas\ServiceManager\Tool\ConfigDumper`, which will introspect a given class
to determine dependencies, and then create configuration for
`Laminas\ServiceManager\AbstractFactory\ConfigAbstractFactory`, merging it with
the provided configuration file. It also adds a vendor binary,
`generate-deps-for-config-factory`, for generating these from the command
line.
- [zendframework/zend-servicemanager#154](https://github.com/zendframework/zend-servicemanager/pull/154) adds
`Laminas\ServiceManager\Tool\FactoryCreator`, which will introspect a given class
and generate a factory for it. It also adds a vendor binary,
`generate-factory-for-class`, for generating these from the command line.
- [zendframework/zend-servicemanager#153](https://github.com/zendframework/zend-servicemanager/pull/153) adds
`Laminas\ServiceManager\AbstractFactory\ReflectionBasedAbstractFactory`. This
class may be used as either a mapped factory or an abstract factory, and will
use reflection in order to determine which dependencies to use from the
container when instantiating the requested service, with the following rules:
- Scalar values are not allowed, unless they have default values associated.
- Values named `$config` type-hinted against `array` will be injected with the
`config` service, if present.
- All other array values will be provided an empty array.
- Class/interface typehints will be pulled from the container.
- [zendframework/zend-servicemanager#150](https://github.com/zendframework/zend-servicemanager/pull/150) adds
a "cookbook" section to the documentation, with an initial document detailing
the pros and cons of abstract factory usage.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- [zendframework/zend-servicemanager#106](https://github.com/zendframework/zend-servicemanager/pull/106) adds
detection of multiple attempts to register the same instance or named abstract
factory, using a previous instance when detected. You may still use multiple
discrete instances, however.
## 3.1.2 - 2016-12-19
### Added
- Nothing.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- [zendframework/zend-servicemanager#167](https://github.com/zendframework/zend-servicemanager/pull/167) fixes
how exception codes are provided to ServiceNotCreatedException. Previously,
the code was provided as-is. However, some PHP internal exception classes,
notably PDOException, can sometimes return other values (such as strings),
which can lead to fatal errors when instantiating the new exception. The
patch provided casts exception codes to integers to prevent these errors.
## 3.1.1 - 2016-07-15
### Added
- Nothing.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- [zendframework/zend-servicemanager#136](https://github.com/zendframework/zend-servicemanager/pull/136) removes
several imports to classes in subnamespaces within the `ServiceManager`
classfile, removing potential name resolution conflicts that occurred in edge
cases when testing.
## 3.1.0 - 2016-06-01
### Added
- [zendframework/zend-servicemanager#103](https://github.com/zendframework/zend-servicemanager/pull/103) Allowing
installation of `ocramius/proxy-manager` `^2.0` together with
`zendframework/zend-servicemanager`.
- [zendframework/zend-servicemanager#103](https://github.com/zendframework/zend-servicemanager/pull/103) Disallowing
test failures when running tests against PHP `7.0.*`.
- [zendframework/zend-servicemanager#113](https://github.com/zendframework/zend-servicemanager/pull/113) Improved performance
when dealing with registering aliases and factories via `ServiceManager#setFactory()` and
`ServiceManager#setAlias()`
- [zendframework/zend-servicemanager#120](https://github.com/zendframework/zend-servicemanager/pull/120) The
`laminas/laminas-servicemanager` component now provides a
`container-interop/container-interop-implementation` implementation
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- [zendframework/zend-servicemanager#97](https://github.com/zendframework/zend-servicemanager/pull/97) Typo corrections
in the delegator factories documentation.
- [zendframework/zend-servicemanager#98](https://github.com/zendframework/zend-servicemanager/pull/98) Using coveralls ^1.0
for tracking test code coverage changes.
## 3.0.3 - 2016-02-02
### Added
- [zendframework/zend-servicemanager#89](https://github.com/zendframework/zend-servicemanager/pull/89) adds
cyclic alias detection to the `ServiceManager`; it now raises a
`Laminas\ServiceManager\Exception\CyclicAliasException` when one is detected,
detailing the cycle detected.
- [zendframework/zend-servicemanager#95](https://github.com/zendframework/zend-servicemanager/pull/95) adds
GitHub Pages publication automation, and moves the documentation to
https://docs.laminas.dev/laminas-servicemanager/
- [zendframework/zend-servicemanager#93](https://github.com/zendframework/zend-servicemanager/pull/93) adds
`Laminas\ServiceManager\Test\CommonPluginManagerTrait`, which can be used to
validate that a plugin manager instance is ready for version 3.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- [zendframework/zend-servicemanager#90](https://github.com/zendframework/zend-servicemanager/pull/90) fixes
several examples in the configuration chapter of the documentation, ensuring
that the signatures are correct.
- [zendframework/zend-servicemanager#92](https://github.com/zendframework/zend-servicemanager/pull/92) ensures
that alias resolution is skipped during configuration if no aliases are
present, and forward-ports the test from [zendframework/zend-servicemanager#81](https://github.com/zendframework/zend-servicemanager/pull/81)
to validate v2/v3 compatibility for plugin managers.
## 3.0.2 - 2016-01-24
### Added
- [zendframework/zend-servicemanager#64](https://github.com/zendframework/zend-servicemanager/pull/64) performance optimizations
when dealing with alias resolution during service manager instantiation
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- [zendframework/zend-servicemanager#62](https://github.com/zendframework/zend-servicemanager/pull/62)
[zendframework/zend-servicemanager#64](https://github.com/zendframework/zend-servicemanager/pull/64) corrected benchmark assets signature
- [zendframework/zend-servicemanager#72](https://github.com/zendframework/zend-servicemanager/pull/72) corrected link to the Proxy Pattern Wikipedia
page in the documentation
- [zendframework/zend-servicemanager#78](https://github.com/zendframework/zend-servicemanager/issues/78)
[zendframework/zend-servicemanager#79](https://github.com/zendframework/zend-servicemanager/pull/79) creation context was not being correctly passed
to abstract factories when using plugin managers
- [zendframework/zend-servicemanager#82](https://github.com/zendframework/zend-servicemanager/pull/82) corrected migration guide in the DocBlock of
the `InitializerInterface`
## 3.0.1 - 2016-01-19
### Added
- Nothing.
### Deprecated
- Nothing.
### Removed
- [zendframework/zend-servicemanager#68](https://github.com/zendframework/zend-servicemanager/pull/68) removes
the dependency on laminas-stdlib by inlining the `ArrayUtils::merge()` routine
as a private method of `Laminas\ServiceManager\Config`.
### Fixed
- Nothing.
## 3.0.0 - 2016-01-11
First stable release of version 3 of laminas-servicemanager.
Documentation is now available at http://laminas-servicemanager.rtfd.org
### Added
- You can now map multiple key names to the same factory. It was previously
possible in Laminas but it was not enforced by the `FactoryInterface` interface.
Now the interface receives the `$requestedName` as the *second* parameter
(previously, it was the third).
Example:
```php
$sm = new \Laminas\ServiceManager\ServiceManager([
'factories' => [
MyClassA::class => MyFactory::class,
MyClassB::class => MyFactory::class,
'MyClassC' => 'MyFactory' // This is equivalent as using ::class
],
]);
$sm->get(MyClassA::class); // MyFactory will receive MyClassA::class as second parameter
```
- Writing a plugin manager has been simplified. If you have simple needs, you no
longer need to implement the complete `validate` method.
In versions 2.x, if your plugin manager only allows creating instances that
implement `Laminas\Validator\ValidatorInterface`, you needed to write the
following code:
```php
class MyPluginManager extends AbstractPluginManager
{
public function validate($instance)
{
if ($instance instanceof \Laminas\Validator\ValidatorInterface) {
return;
}
throw new InvalidServiceException(sprintf(
'Plugin manager "%s" expected an instance of type "%s", but "%s" was received',
__CLASS__,
\Laminas\Validator\ValidatorInterface::class,
is_object($instance) ? get_class($instance) : gettype($instance)
));
}
}
```
In version 3, this becomes:
```php
use Laminas\ServiceManager\AbstractPluginManager;
use Laminas\Validator\ValidatorInterface;
class MyPluginManager extends AbstractPluginManager
{
protected $instanceOf = ValidatorInterface::class;
}
```
Of course, you can still override the `validate` method if your logic is more
complex.
To aid migration, `validate()` will check for a `validatePlugin()` method (which
was required in v2), and proxy to it if found, after emitting an
`E_USER_DEPRECATED` notice prompting you to rename the method.
- A new method, `configure()`, was added, allowing full configuration of the
`ServiceManager` instance at once. Each of the various configuration methods —
`setAlias()`, `setInvokableClass()`, etc. — now proxy to this method.
- A new method, `mapLazyService($name, $class = null)`, was added, to allow
mapping a lazy service, and as an analog to the other various service
definition methods.
### Deprecated
- Nothing
### Removed
- Peering has been removed. It was a complex and rarely used feature that was
misunderstood most of the time.
- Integration with `Laminas\Di` has been removed. It may be re-integrated later.
- `MutableCreationOptionsInterface` has been removed, as options can now be
passed directly through factories.
- `ServiceLocatorAwareInterface` and its associated trait has been removed. It
was an anti-pattern, and you are encouraged to inject your dependencies in
factories instead of injecting the whole service locator.
### Changed/Fixed
v3 of the ServiceManager component is a completely rewritten, more efficient
implementation of the service locator pattern. It includes a number of breaking
changes, outlined in this section.
- You no longer need a `Laminas\ServiceManager\Config` object to configure the
service manager; you can pass the configuration array directly instead.
In version 2.x:
```php
$config = new \Laminas\ServiceManager\Config([
'factories' => [...]
]);
$sm = new \Laminas\ServiceManager\ServiceManager($config);
```
In Laminas 3.x:
```php
$sm = new \Laminas\ServiceManager\ServiceManager([
'factories' => [...]
]);
```
`Config` and `ConfigInterface` still exist, however, but primarily for the
purposes of codifying and aggregating configuration to use.
- `ConfigInterface` has two important changes:
- `configureServiceManager()` now **must** return the updated service manager
instance.
- A new method, `toArray()`, was added, to allow pulling the configuration in
order to pass to a ServiceManager or plugin manager's constructor or
`configure()` method.
- Interfaces for `FactoryInterface`, `DelegatorFactoryInterface` and
`AbstractFactoryInterface` have changed. All are now directly invokable. This
allows a number of performance optimization internally.
Additionally, all signatures that accepted a "canonical name" argument now
remove it.
Most of the time, rewriting a factory to match the new interface implies
replacing the method name by `__invoke`, and removing the canonical name
argument if present.
For instance, here is a simple version 2.x factory:
```php
class MyFactory implements FactoryInterface
{
function createService(ServiceLocatorInterface $sl)
{
// ...
}
}
```
The equivalent version 3 factory:
```php
class MyFactory implements FactoryInterface
{
function __invoke(ServiceLocatorInterface $sl, $requestedName)
{
// ...
}
}
```
Note another change in the above: factories also receive a second parameter,
enforced through the interface, that allows you to easily map multiple service
names to the same factory.
To provide forwards compatibility, the original interfaces have been retained,
but extend the new interfaces (which are under new namespaces). You can implement
the new methods in your existing v2 factories in order to make them forwards
compatible with v3.
- The for `AbstractFactoryInterface` interface renames the method `canCreateServiceWithName()`
to `canCreate()`, and merges the `$name` and `$requestedName` arguments.
- Plugin managers will now receive the parent service locator instead of itself
in factories. In version 2.x, you needed to call the method
`getServiceLocator()` to retrieve the parent (application) service locator.
This was confusing, and not IDE friendly as this method was not enforced
through the interface.
In version 2.x, if a factory was set to a service name defined in a plugin manager:
```php
class MyFactory implements FactoryInterface
{
function createService(ServiceLocatorInterface $sl)
{
// $sl is actually a plugin manager
$parentLocator = $sl->getServiceLocator();
// ...
}
}
```
In version 3:
```php
class MyFactory implements FactoryInterface
{
function __invoke(ServiceLocatorInterface $sl, $requestedName)
{
// $sl is already the main, parent service locator. If you need to
// retrieve the plugin manager again, you can retrieve it through the
// servicelocator:
$pluginManager = $sl->get(MyPluginManager::class);
// ...
}
}
```
In practice, this should reduce code, as dependencies often come from the main
service locator, and not the plugin manager itself.
To assist in migration, the method `getServiceLocator()` was added to `ServiceManager`
to ensure that existing factories continue to work; the method emits an `E_USER_DEPRECATED`
message to signal developers to update their factories.
- `PluginManager` now enforces the need for the main service locator in its
constructor. In v2.x, people often forgot to set the parent locator, which led
to bugs in factories trying to fetch dependencies from the parent locator.
Additionally, plugin managers now pull dependencies from the parent locator by
default; if you need to pull a peer plugin, your factories will now need to
pull the corresponding plugin manager first.
If you omit passing a service locator to the constructor, your plugin manager
will continue to work, but will emit a deprecation notice indicatin you
should update your initialization code.
- It's so fast now that your app will fly!
## 2.7.0 - 2016-01-11
### Added
- [zendframework/zend-servicemanager#60](https://github.com/zendframework/zend-servicemanager/pull/60) adds
forward compatibility features for `AbstractPluingManager` and introduces
`InvokableFactory` to help forward migration to version 3.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- [zendframework/zend-servicemanager#46](https://github.com/zendframework/zend-servicemanager/pull/46) updates
the exception hierarchy to inherit from the container-interop exceptions.
This ensures that all exceptions thrown by the component follow the
recommendations of that project.
- [zendframework/zend-servicemanager#52](https://github.com/zendframework/zend-servicemanager/pull/52) fixes
the exception message thrown by `ServiceManager::setFactory()` to remove
references to abstract factories.
## 2.6.0 - 2015-07-23
### Added
- [zendframework/zend-servicemanager#4](https://github.com/zendframework/zend-servicemanager/pull/4) updates the
`ServiceManager` to [implement the container-interop interface](https://github.com/container-interop/container-interop),
allowing interoperability with applications that consume that interface.
### Deprecated
- Nothing.
### Removed
- Nothing.
### Fixed
- [zendframework/zend-servicemanager#3](https://github.com/zendframework/zend-servicemanager/pull/3) properly updates the
codebase to PHP 5.5, by taking advantage of the default closure binding
(`$this` in a closure is the invoking object when created within a method). It
also removes several `@requires PHP 5.4.0` annotations.

View File

@@ -1,11 +1,23 @@
# laminas-servicemanager
Master:
[![Build Status](https://travis-ci.com/laminas/laminas-servicemanager.svg?branch=master)](https://travis-ci.com/laminas/laminas-servicemanager)
[![Coverage Status](https://coveralls.io/repos/github/laminas/laminas-servicemanager/badge.svg?branch=master)](https://coveralls.io/github/laminas/laminas-servicemanager?branch=master)
Develop:
[![Build Status](https://travis-ci.com/laminas/laminas-servicemanager.svg?branch=develop)](https://travis-ci.com/laminas/laminas-servicemanager)
[![Coverage Status](https://coveralls.io/repos/github/laminas/laminas-servicemanager/badge.svg?branch=develop)](https://coveralls.io/github/laminas/laminas-servicemanager?branch=develop)
[![Build Status](https://github.com/laminas/laminas-servicemanager/actions/workflows/continuous-integration.yml/badge.svg)](https://github.com/laminas/laminas-servicemanager/actions/workflows/continuous-integration.yml)
[![Psalm coverage](https://shepherd.dev/github/laminas/laminas-servicemanager/coverage.svg?)](https://shepherd.dev/github/laminas/laminas-servicemanager)
> ## 🇷🇺 Русским гражданам
>
> Мы, участники Laminas, родились и живем в разных странах. У многих из нас есть друзья, родственники и коллеги как в России, так и в Украине. Некоторые из нас родились в России. Некоторые из нас живут в России. У некоторых бабушки и дедушки сражались с фашистами во Второй мировой войне. Здесь никто не поддерживает фашизм.
>
> У одного из нас есть украинская родственница, которая спаслась из дома вместе с сыном. Поезд задержался из-за бомбежки на дороге впереди. У нас есть друзья, которые прячутся в бомбоубежищах. Мы с тревогой ждем весточки от них после воздушных налетов, которые беспорядочно наносят удары и попадают по больницам, школам, детским садам и домам. Мы не берем это из каких-либо СМИ. Мы наблюдаем это напрямую.
>
> Вы доверяете нам достаточно, чтоб использовать наши программы, и мы просим вас довериться нам вновь. Мы нуждаемся в помощи. Выходите и протестуйте против этой бесполезной войны. Остановите кровопролитие. Скажите "Нет войне!"
>
> ## 🇺🇸 To Citizens of Russia
>
> We at Laminas come from all over the world. Many of us have friends, family and colleagues in both Russia and Ukraine. Some of us were born in Russia. Some of us currently live in Russia. Some have grandparents who fought Nazis in World War II. Nobody here supports fascism.
>
> One team member has a Ukrainian relative who fled her home with her son. The train was delayed due to bombing on the road ahead. We have friends who are hiding in bomb shelters. We anxiously follow up on them after the air raids, which indiscriminately fire at hospitals, schools, kindergartens and houses. We're not taking this from any media. These are our actual experiences.
>
> You trust us enough to use our software. We ask that you trust us to say the truth on this. We need your help. Go out and protest this unnecessary war. Stop the bloodshed. Say "stop the war!"
The Service Locator design pattern is implemented by the `Laminas\ServiceManager`
component. The Service Locator is a service/object locator, tasked with

View File

@@ -1,11 +1,7 @@
#!/usr/bin/env php
<?php
/**
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
*/
declare(strict_types=1);
namespace Laminas\ServiceManager;

View File

@@ -1,11 +1,7 @@
#!/usr/bin/env php
<?php
/**
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
*/
declare(strict_types=1);
namespace Laminas\ServiceManager;

View File

@@ -21,42 +21,56 @@
"forum": "https://discourse.laminas.dev"
},
"config": {
"sort-packages": true
},
"extra": {
"branch-alias": {
"dev-master": "3.3-dev",
"dev-develop": "4.0-dev"
"platform": {
"php": "7.4.99"
},
"sort-packages": true,
"allow-plugins": {
"dealerdirect/phpcodesniffer-composer-installer": true,
"composer/package-versions-deprecated": true,
"laminas/laminas-dependency-plugin": true
}
},
"require": {
"php": "^5.6 || ^7.0",
"container-interop/container-interop": "^1.2",
"php": "~7.4.0 || ~8.0.0 || ~8.1.0",
"laminas/laminas-stdlib": "^3.2.1",
"laminas/laminas-zendframework-bridge": "^1.0",
"psr/container": "^1.0"
},
"require-dev": {
"laminas/laminas-coding-standard": "~1.0.0",
"mikey179/vfsstream": "^1.6.5",
"ocramius/proxy-manager": "^1.0 || ^2.0",
"phpbench/phpbench": "^0.13.0",
"phpunit/phpunit": "^5.7.25 || ^6.4.4"
"composer/package-versions-deprecated": "^1.0",
"laminas/laminas-coding-standard": "~2.3.0",
"laminas/laminas-container-config-test": "^0.7",
"laminas/laminas-dependency-plugin": "^2.1.2",
"mikey179/vfsstream": "^1.6.10@alpha",
"ocramius/proxy-manager": "^2.11",
"phpbench/phpbench": "^1.1",
"phpspec/prophecy-phpunit": "^2.0",
"phpunit/phpunit": "^9.5.5",
"psalm/plugin-phpunit": "^0.17.0",
"vimeo/psalm": "^4.8"
},
"provide": {
"container-interop/container-interop-implementation": "^1.2",
"psr/container-implementation": "^1.0"
},
"conflict": {
"ext-psr": "*",
"laminas/laminas-code": "<3.3.1",
"zendframework/zend-code": "<3.3.1",
"zendframework/zend-servicemanager": "*"
},
"suggest": {
"laminas/laminas-stdlib": "laminas-stdlib ^2.5 if you wish to use the MergeReplaceKey or MergeRemoveKey features in Config instances",
"ocramius/proxy-manager": "ProxyManager 1.* to handle lazy initialization of services"
"ocramius/proxy-manager": "ProxyManager ^2.1.1 to handle lazy initialization of services"
},
"autoload": {
"psr-4": {
"Laminas\\ServiceManager\\": "src/"
}
},
"files": ["src/autoload.php"]
},
"autoload-dev": {
"files": [
"test/autoload.php"
],
"psr-4": {
"LaminasTest\\ServiceManager\\": "test/",
"LaminasBench\\ServiceManager\\": "benchmarks/"
@@ -67,6 +81,7 @@
"bin/generate-factory-for-class"
],
"scripts": {
"benchmark": "phpbench run --revs=2 --iterations=2 --report=aggregate",
"check": [
"@cs-check",
"@test"
@@ -75,9 +90,9 @@
"cs-fix": "phpcbf",
"test": "phpunit --colors=always",
"test-coverage": "phpunit --colors=always --coverage-clover clover.xml",
"upload-coverage": "coveralls -v"
"static-analysis" : "psalm --shepherd --stats"
},
"replace": {
"zendframework/zend-servicemanager": "^3.4.0"
"container-interop/container-interop": "^1.2.0"
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,26 +1,28 @@
<?php
/**
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
*/
declare(strict_types=1);
namespace Laminas\ServiceManager\AbstractFactory;
use ArrayObject;
use Laminas\ServiceManager\Exception\ServiceNotCreatedException;
use Laminas\ServiceManager\Factory\AbstractFactoryInterface;
use Psr\Container\ContainerInterface;
use function array_key_exists;
use function array_map;
use function array_values;
use function is_array;
use function json_encode;
final class ConfigAbstractFactory implements AbstractFactoryInterface
{
/**
* Factory can create the service if there is a key for it in the config
*
* {@inheritdoc}
*/
public function canCreate(\Interop\Container\ContainerInterface $container, $requestedName)
public function canCreate(ContainerInterface $container, $requestedName)
{
if (! $container->has('config')) {
return false;
@@ -37,7 +39,7 @@ final class ConfigAbstractFactory implements AbstractFactoryInterface
/**
* {@inheritDoc}
*/
public function __invoke(\Interop\Container\ContainerInterface $container, $requestedName, array $options = null)
public function __invoke(ContainerInterface $container, $requestedName, ?array $options = null)
{
if (! $container->has('config')) {
throw new ServiceNotCreatedException('Cannot find a config array in the container');
@@ -52,10 +54,10 @@ final class ConfigAbstractFactory implements AbstractFactoryInterface
throw new ServiceNotCreatedException('Cannot find a `' . self::class . '` key in the config array');
}
$dependencies = $config[self::class];
if (! is_array($dependencies)
if (
! is_array($dependencies)
|| ! array_key_exists($requestedName, $dependencies)
|| ! is_array($dependencies[$requestedName])
) {

View File

@@ -1,19 +1,22 @@
<?php
/**
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
*/
declare(strict_types=1);
namespace Laminas\ServiceManager\AbstractFactory;
use Interop\Container\ContainerInterface;
use Laminas\ServiceManager\Exception\ServiceNotFoundException;
use Laminas\ServiceManager\Factory\AbstractFactoryInterface;
use Psr\Container\ContainerInterface;
use ReflectionClass;
use ReflectionNamedType;
use ReflectionParameter;
use function array_map;
use function class_exists;
use function interface_exists;
use function is_string;
use function sprintf;
/**
* Reflection-based factory.
*
@@ -87,8 +90,6 @@ class ReflectionBasedAbstractFactory implements AbstractFactoryInterface
protected $aliases = [];
/**
* Constructor.
*
* Allows overriding the internal list of aliases. These should be of the
* form `class name => well-known service name`; see the documentation for
* the `$aliases` property for details on what is accepted.
@@ -107,7 +108,7 @@ class ReflectionBasedAbstractFactory implements AbstractFactoryInterface
*
* @return DispatchableInterface
*/
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
public function __invoke(ContainerInterface $container, $requestedName, ?array $options = null)
{
$reflectionClass = new ReflectionClass($requestedName);
@@ -138,7 +139,7 @@ class ReflectionBasedAbstractFactory implements AbstractFactoryInterface
return class_exists($requestedName) && $this->canCallConstructor($requestedName);
}
private function canCallConstructor($requestedName)
private function canCallConstructor(string $requestedName): bool
{
$constructor = (new ReflectionClass($requestedName))->getConstructor();
@@ -151,7 +152,6 @@ class ReflectionBasedAbstractFactory implements AbstractFactoryInterface
* Returns a callback for resolving a parameter to a value, but without
* allowing mapping array `$config` arguments to the `config` service.
*
* @param ContainerInterface $container
* @param string $requestedName
* @return callable
*/
@@ -162,10 +162,9 @@ class ReflectionBasedAbstractFactory implements AbstractFactoryInterface
* @return mixed
* @throws ServiceNotFoundException If type-hinted parameter cannot be
* resolved to a service in the container.
* @psalm-suppress MissingClosureReturnType
*/
return function (ReflectionParameter $parameter) use ($container, $requestedName) {
return $this->resolveParameter($parameter, $container, $requestedName);
};
return fn(ReflectionParameter $parameter) => $this->resolveParameter($parameter, $container, $requestedName);
}
/**
@@ -174,7 +173,6 @@ class ReflectionBasedAbstractFactory implements AbstractFactoryInterface
* Unlike resolveParameter(), this version will detect `$config` array
* arguments and have them return the 'config' service.
*
* @param ContainerInterface $container
* @param string $requestedName
* @return callable
*/
@@ -187,8 +185,11 @@ class ReflectionBasedAbstractFactory implements AbstractFactoryInterface
* resolved to a service in the container.
*/
return function (ReflectionParameter $parameter) use ($container, $requestedName) {
if ($parameter->isArray() && $parameter->getName() === 'config') {
return $container->get('config');
if ($parameter->getName() === 'config') {
$type = $parameter->getType();
if ($type instanceof ReflectionNamedType && $type->getName() === 'array') {
return $container->get('config');
}
}
return $this->resolveParameter($parameter, $container, $requestedName);
};
@@ -197,8 +198,6 @@ class ReflectionBasedAbstractFactory implements AbstractFactoryInterface
/**
* Logic common to all parameter resolution.
*
* @param ReflectionParameter $parameter
* @param ContainerInterface $container
* @param string $requestedName
* @return mixed
* @throws ServiceNotFoundException If type-hinted parameter cannot be
@@ -206,11 +205,14 @@ class ReflectionBasedAbstractFactory implements AbstractFactoryInterface
*/
private function resolveParameter(ReflectionParameter $parameter, ContainerInterface $container, $requestedName)
{
if ($parameter->isArray()) {
$type = $parameter->getType();
$type = $type instanceof ReflectionNamedType ? $type->getName() : null;
if ($type === 'array') {
return [];
}
if (! $parameter->getClass()) {
if ($type === null || (is_string($type) && ! class_exists($type) && ! interface_exists($type))) {
if (! $parameter->isDefaultValueAvailable()) {
throw new ServiceNotFoundException(sprintf(
'Unable to create service "%s"; unable to resolve parameter "%s" '
@@ -223,8 +225,7 @@ class ReflectionBasedAbstractFactory implements AbstractFactoryInterface
return $parameter->getDefaultValue();
}
$type = $parameter->getClass()->getName();
$type = isset($this->aliases[$type]) ? $this->aliases[$type] : $type;
$type = $this->aliases[$type] ?? $type;
if ($container->has($type)) {
return $container->get($type);

View File

@@ -1,10 +1,6 @@
<?php
/**
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
*/
declare(strict_types=1);
namespace Laminas\ServiceManager;
@@ -17,11 +13,11 @@ namespace Laminas\ServiceManager;
*
* - rename the method `canCreateServiceWithName()` to `canCreate()`, and:
* - rename the `$serviceLocator` argument to `$container`, and change the
* typehint to `Interop\Container\ContainerInterface`
* typehint to `Psr\Container\ContainerInterface`
* - merge the `$name` and `$requestedName` arguments
* - rename the method `createServiceWithName()` to `__invoke()`, and:
* - rename the `$serviceLocator` argument to `$container`, and change the
* typehint to `Interop\Container\ContainerInterface`
* typehint to `Psr\Container\ContainerInterface`
* - merge the `$name` and `$requestedName` arguments
* - add the optional `array $options = null` argument.
* - create a `canCreateServiceWithName()` method as defined in this interface, and have it
@@ -40,9 +36,8 @@ interface AbstractFactoryInterface extends Factory\AbstractFactoryInterface
/**
* Determine if we can create a service with name
*
* @param ServiceLocatorInterface $serviceLocator
* @param $name
* @param $requestedName
* @param string $name
* @param string $requestedName
* @return bool
*/
public function canCreateServiceWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName);
@@ -50,9 +45,8 @@ interface AbstractFactoryInterface extends Factory\AbstractFactoryInterface
/**
* Create service with name
*
* @param ServiceLocatorInterface $serviceLocator
* @param $name
* @param $requestedName
* @param string $name
* @param string $requestedName
* @return mixed
*/
public function createServiceWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName);

View File

@@ -1,16 +1,22 @@
<?php
/**
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
*/
declare(strict_types=1);
namespace Laminas\ServiceManager;
use Interop\Container\ContainerInterface;
use Laminas\ServiceManager\Exception\ContainerModificationsNotAllowedException;
use Laminas\ServiceManager\Exception\InvalidServiceException;
use Psr\Container\ContainerInterface as PsrContainerInterface;
use Psr\Container\ContainerInterface;
use function class_exists;
use function get_class;
use function gettype;
use function is_object;
use function method_exists;
use function sprintf;
use function trigger_error;
use const E_USER_DEPRECATED;
/**
* Abstract plugin manager.
@@ -25,6 +31,11 @@ use Psr\Container\ContainerInterface as PsrContainerInterface;
*
* The implementation extends `ServiceManager`, thus providing the same set
* of capabilities as found in that implementation.
*
* @template InstanceType
* @implements PluginManagerInterface<InstanceType>
* @psalm-import-type ServiceManagerConfiguration from ServiceManager
* @psalm-suppress PropertyNotSetInConstructor
*/
abstract class AbstractPluginManager extends ServiceManager implements PluginManagerInterface
{
@@ -39,42 +50,33 @@ abstract class AbstractPluginManager extends ServiceManager implements PluginMan
* An object type that the created instance must be instanced of
*
* @var null|string
* @psalm-var null|class-string<InstanceType>
*/
protected $instanceOf = null;
protected $instanceOf;
/**
* Constructor.
*
* Sets the provided $parentLocator as the creation context for all
* factories; for $config, {@see \Laminas\ServiceManager\ServiceManager::configure()}
* for details on its accepted structure.
*
* @param null|ConfigInterface|ContainerInterface|PsrContainerInterface $configInstanceOrParentLocator
* @param null|ConfigInterface|ContainerInterface $configInstanceOrParentLocator
* @param array $config
* @psalm-param ServiceManagerConfiguration $config
*/
public function __construct($configInstanceOrParentLocator = null, array $config = [])
{
if ($configInstanceOrParentLocator instanceof PsrContainerInterface
&& ! $configInstanceOrParentLocator instanceof ContainerInterface
) {
/**
* {@see \Laminas\ServiceManager\Factory\FactoryInterface} typehints
* against interop container and as such cannot accept non-interop
* psr container. Decorate it as interop.
*/
$configInstanceOrParentLocator = new PsrContainerDecorator($configInstanceOrParentLocator);
}
if (null !== $configInstanceOrParentLocator
/** @psalm-suppress DocblockTypeContradiction */
if (
null !== $configInstanceOrParentLocator
&& ! $configInstanceOrParentLocator instanceof ConfigInterface
&& ! $configInstanceOrParentLocator instanceof ContainerInterface
) {
throw new Exception\InvalidArgumentException(sprintf(
'%s expects a ConfigInterface or ContainerInterface instance as the first argument; received %s',
__CLASS__,
(is_object($configInstanceOrParentLocator)
self::class,
is_object($configInstanceOrParentLocator)
? get_class($configInstanceOrParentLocator)
: gettype($configInstanceOrParentLocator)
)
));
}
@@ -82,7 +84,7 @@ abstract class AbstractPluginManager extends ServiceManager implements PluginMan
trigger_error(sprintf(
'Usage of %s as a constructor argument for %s is now deprecated',
ConfigInterface::class,
get_class($this)
static::class
), E_USER_DEPRECATED);
$config = $configInstanceOrParentLocator->toArray();
}
@@ -105,15 +107,18 @@ abstract class AbstractPluginManager extends ServiceManager implements PluginMan
/**
* Override configure() to validate service instances.
*
* If an instance passed in the `services` configuration is invalid for the
* plugin manager, this method will raise an InvalidServiceException.
*
* {@inheritDoc}
* @throws InvalidServiceException
* @param array $config
* @psalm-param ServiceManagerConfiguration $config
* @return self
* @throws InvalidServiceException If an instance passed in the `services` configuration is invalid for the
* plugin manager.
* @throws ContainerModificationsNotAllowedException If the allow override flag has been toggled off, and a
* service instanceexists for a given service.
*/
public function configure(array $config)
{
if (isset($config['services'])) {
/** @psalm-suppress MixedAssignment */
foreach ($config['services'] as $service) {
$this->validate($service);
}
@@ -125,45 +130,60 @@ abstract class AbstractPluginManager extends ServiceManager implements PluginMan
}
/**
* Override setService for additional plugin validation.
*
* {@inheritDoc}
*
* @param string $name Service name of plugin to retrieve.
* @param null|array $options Options to use when creating the instance.
* @param string|class-string<InstanceType> $name
* @param InstanceType $service
*/
public function setService($name, $service)
{
$this->validate($service);
parent::setService($name, $service);
}
/**
* @param class-string<InstanceType>|string $name Service name of plugin to retrieve.
* @param null|array<mixed> $options Options to use when creating the instance.
* @return mixed
* @throws Exception\ServiceNotFoundException if the manager does not have
* @psalm-return ($name is class-string ? InstanceType : mixed)
* @throws Exception\ServiceNotFoundException If the manager does not have
* a service definition for the instance, and the service is not
* auto-invokable.
* @throws InvalidServiceException if the plugin created is invalid for the
* @throws InvalidServiceException If the plugin created is invalid for the
* plugin context.
*/
public function get($name, array $options = null)
public function get($name, ?array $options = null)
{
if (! $this->has($name)) {
if (! $this->autoAddInvokableClass || ! class_exists($name)) {
throw new Exception\ServiceNotFoundException(sprintf(
'A plugin by the name "%s" was not found in the plugin manager %s',
$name,
get_class($this)
static::class
));
}
$this->setFactory($name, Factory\InvokableFactory::class);
}
$instance = empty($options) ? parent::get($name) : $this->build($name, $options);
$instance = ! $options ? parent::get($name) : $this->build($name, $options);
$this->validate($instance);
return $instance;
}
/**
* {@inheritDoc}
*
* @psalm-assert InstanceType $instance
*/
public function validate($instance)
{
if (method_exists($this, 'validatePlugin')) {
trigger_error(sprintf(
'%s::validatePlugin() has been deprecated as of 3.0; please define validate() instead',
get_class($this)
static::class
), E_USER_DEPRECATED);
$this->validatePlugin($instance);
return;
@@ -175,7 +195,7 @@ abstract class AbstractPluginManager extends ServiceManager implements PluginMan
throw new InvalidServiceException(sprintf(
'Plugin manager "%s" expected an instance of type "%s", but "%s" was received',
__CLASS__,
self::class,
$this->instanceOf,
is_object($instance) ? get_class($instance) : gettype($instance)
));
@@ -186,9 +206,9 @@ abstract class AbstractPluginManager extends ServiceManager implements PluginMan
*
* Returns the creation context.
*
* @deprecated 3.0.0. The creation context should be passed during
* @deprecated since 3.0.0. The creation context should be passed during
* instantiation instead.
* @param ContainerInterface $container
*
* @return void
*/
public function setServiceLocator(ContainerInterface $container)

View File

@@ -1,15 +1,12 @@
<?php
/**
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
*/
declare(strict_types=1);
namespace Laminas\ServiceManager;
use Laminas\Stdlib\ArrayUtils\MergeRemoveKey;
use Laminas\Stdlib\ArrayUtils\MergeReplaceKeyInterface;
use Laminas\Stdlib\ArrayUtils;
use function array_keys;
/**
* Object for defining configuration and configuring an existing service manager instance.
@@ -25,26 +22,27 @@ use Laminas\Stdlib\ArrayUtils\MergeReplaceKeyInterface;
*
* These features are advanced, and not typically used. If you wish to use them,
* you will need to require the laminas-stdlib package in your application.
*
* @psalm-import-type ServiceManagerConfigurationType from ConfigInterface
*/
class Config implements ConfigInterface
{
/**
* @var array
*/
private $allowedKeys = [
/** @var array<string,bool> */
private array $allowedKeys = [
'abstract_factories' => true,
'aliases' => true,
'delegators' => true,
'factories' => true,
'initializers' => true,
'invokables' => true,
'lazy_services' => true,
'services' => true,
'shared' => true,
'aliases' => true,
'delegators' => true,
'factories' => true,
'initializers' => true,
'invokables' => true,
'lazy_services' => true,
'services' => true,
'shared' => true,
];
/**
* @var array
* @var array<string,array>
* @psalm-var ServiceManagerConfigurationType
*/
protected $config = [
'abstract_factories' => [],
@@ -59,7 +57,7 @@ class Config implements ConfigInterface
];
/**
* @param array $config
* @psalm-param ServiceManagerConfigurationType $config
*/
public function __construct(array $config = [])
{
@@ -69,11 +67,13 @@ class Config implements ConfigInterface
unset($config[$key]);
}
}
/** @psalm-suppress ArgumentTypeCoercion */
$this->config = $this->merge($this->config, $config);
}
/**
* @inheritdoc
* @inheritDoc
*/
public function configureServiceManager(ServiceManager $serviceManager)
{
@@ -81,7 +81,7 @@ class Config implements ConfigInterface
}
/**
* @inheritdoc
* @inheritDoc
*/
public function toArray()
{
@@ -89,32 +89,14 @@ class Config implements ConfigInterface
}
/**
* Copy paste from https://github.com/laminas/laminas-stdlib/commit/26fcc32a358aa08de35625736095cb2fdaced090
* to keep compatibility with previous version
*
* @link https://github.com/zendframework/zend-servicemanager/pull/68
* @psalm-param ServiceManagerConfigurationType $a
* @psalm-param ServiceManagerConfigurationType $b
* @psalm-return ServiceManagerConfigurationType
* @psalm-suppress MixedReturnTypeCoercion
*/
private function merge(array $a, array $b)
{
foreach ($b as $key => $value) {
if ($value instanceof MergeReplaceKeyInterface) {
$a[$key] = $value->getData();
} elseif (isset($a[$key]) || array_key_exists($key, $a)) {
if ($value instanceof MergeRemoveKey) {
unset($a[$key]);
} elseif (is_int($key)) {
$a[] = $value;
} elseif (is_array($value) && is_array($a[$key])) {
$a[$key] = $this->merge($a[$key], $value);
} else {
$a[$key] = $value;
}
} else {
if (! $value instanceof MergeRemoveKey) {
$a[$key] = $value;
}
}
}
return $a;
/** @psalm-suppress MixedReturnTypeCoercion */
return ArrayUtils::merge($a, $b);
}
}

View File

@@ -1,13 +1,56 @@
<?php
/**
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
*/
declare(strict_types=1);
namespace Laminas\ServiceManager;
use ArrayAccess;
use Psr\Container\ContainerInterface;
/**
* @see ContainerInterface
* @see ArrayAccess
*
* @psalm-type AbstractFactoriesConfigurationType = array<
* array-key,
* (class-string<Factory\AbstractFactoryInterface>|Factory\AbstractFactoryInterface)
* >
* @psalm-type DelegatorsConfigurationType = array<
* string,
* array<
* array-key,
* (class-string<Factory\DelegatorFactoryInterface>|Factory\DelegatorFactoryInterface)
* |callable(ContainerInterface,string,callable():object,array<mixed>|null):object
* >
* >
* @psalm-type FactoriesConfigurationType = array<
* string,
* (class-string<Factory\FactoryInterface>|Factory\FactoryInterface)
* |callable(ContainerInterface,string,array<mixed>|null):object
* >
* @psalm-type InitializersConfigurationType = array<
* array-key,
* (class-string<Initializer\InitializerInterface>|Initializer\InitializerInterface)
* |callable(ContainerInterface,object):void
* >
* @psalm-type LazyServicesConfigurationType = array{
* class_map?:array<string,class-string>,
* proxies_namespace?:non-empty-string,
* proxies_target_dir?:non-empty-string,
* write_proxy_files?:bool
* }
* @psalm-type ServiceManagerConfigurationType = array{
* abstract_factories?: AbstractFactoriesConfigurationType,
* aliases?: array<string,string>,
* delegators?: DelegatorsConfigurationType,
* factories?: FactoriesConfigurationType,
* initializers?: InitializersConfigurationType,
* invokables?: array<string,string>,
* lazy_services?: LazyServicesConfigurationType,
* services?: array<string,object|array>,
* shared?:array<string,bool>
* }
*/
interface ConfigInterface
{
/**
@@ -17,7 +60,6 @@ interface ConfigInterface
* local properties) and pass it to a ServiceManager's withConfig() method,
* returning a new instance.
*
* @param ServiceManager $serviceManager
* @return ServiceManager
*/
public function configureServiceManager(ServiceManager $serviceManager);
@@ -42,6 +84,7 @@ interface ConfigInterface
* a service manager or plugin manager, or pass to its `withConfig()` method.
*
* @return array
* @psalm-return ServiceManagerConfigurationType
*/
public function toArray();
}

View File

@@ -1,10 +1,6 @@
<?php
/**
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
*/
declare(strict_types=1);
namespace Laminas\ServiceManager;
@@ -17,7 +13,7 @@ namespace Laminas\ServiceManager;
*
* - rename the method `createDelegatorWithName()` to `__invoke()`, and:
* - rename the `$serviceLocator` argument to `$container`, and change the
* typehint to `Interop\Container\ContainerInterface`
* typehint to `Psr\Container\ContainerInterface`
* - merge the `$name` and `$requestedName` arguments
* - add the `callable` typehint to the `$callback` argument
* - add the optional `array $options = null` argument as a final argument
@@ -39,7 +35,6 @@ interface DelegatorFactoryInterface extends Factory\DelegatorFactoryInterface
* @param string $name the normalized service name
* @param string $requestedName the requested service name
* @param callable $callback the callback that is responsible for creating the service
*
* @return mixed
*/
public function createDelegatorWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName, $callback);

View File

@@ -1,18 +1,25 @@
<?php
/**
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
*/
declare(strict_types=1);
namespace Laminas\ServiceManager\Exception;
use DomainException;
/**
* @inheritDoc
*/
use function sprintf;
class ContainerModificationsNotAllowedException extends DomainException implements ExceptionInterface
{
/**
* @param string $service Name of service that already exists.
*/
public static function fromExistingService(string $service): self
{
return new self(sprintf(
'The container does not allow replacing or updating a service'
. ' with existing instances; the following service'
. ' already exists in the container: %s',
$service
));
}
}

View File

@@ -1,26 +1,49 @@
<?php
/**
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
*/
declare(strict_types=1);
namespace Laminas\ServiceManager\Exception;
use function array_filter;
use function array_keys;
use function array_map;
use function array_values;
use function implode;
use function reset;
use function serialize;
use function sort;
use function sprintf;
class CyclicAliasException extends InvalidArgumentException
{
/**
* @param string $alias conflicting alias key
* @param string[] $aliases map of referenced services, indexed by alias name (string)
*/
public static function fromCyclicAlias(string $alias, array $aliases): self
{
$cycle = $alias;
$cursor = $alias;
while (isset($aliases[$cursor]) && $aliases[$cursor] !== $alias) {
$cursor = $aliases[$cursor];
$cycle .= ' -> ' . $cursor;
}
$cycle .= ' -> ' . $alias . "\n";
return new self(sprintf(
"A cycle was detected within the aliases definitions:\n%s",
$cycle
));
}
/**
* @param string[] $aliases map of referenced services, indexed by alias name (string)
*
* @return self
*/
public static function fromAliasesMap(array $aliases)
{
$detectedCycles = array_filter(array_map(
function ($alias) use ($aliases) {
return self::getCycleFor($aliases, $alias);
},
static fn($alias) => self::getCycleFor($aliases, $alias),
array_keys($aliases)
));
@@ -44,7 +67,6 @@ class CyclicAliasException extends InvalidArgumentException
*
* @param string[] $aliases
* @param string $alias
*
* @return array|null
*/
private static function getCycleFor(array $aliases, $alias)
@@ -58,8 +80,7 @@ class CyclicAliasException extends InvalidArgumentException
}
$cycleCandidate[$targetName] = true;
$targetName = $aliases[$targetName];
$targetName = $aliases[$targetName];
}
return null;
@@ -67,7 +88,6 @@ class CyclicAliasException extends InvalidArgumentException
/**
* @param string[] $aliases
*
* @return string
*/
private static function printReferencesMap(array $aliases)
@@ -83,18 +103,17 @@ class CyclicAliasException extends InvalidArgumentException
/**
* @param string[][] $detectedCycles
*
* @return string
*/
private static function printCycles(array $detectedCycles)
{
return "[\n" . implode("\n", array_map([__CLASS__, 'printCycle'], $detectedCycles)) . "\n]";
return "[\n" . implode("\n", array_map([self::class, 'printCycle'], $detectedCycles)) . "\n]";
}
/**
* @param string[] $detectedCycle
*
* @return string
* @phpcsSuppress SlevomatCodingStandard.Classes.UnusedPrivateElements.UnusedMethod
*/
private static function printCycle(array $detectedCycle)
{
@@ -104,9 +123,7 @@ class CyclicAliasException extends InvalidArgumentException
return implode(
' => ',
array_map(
function ($cycle) {
return '"' . $cycle . '"';
},
static fn($cycle): string => '"' . $cycle . '"',
$fullCycle
)
);
@@ -114,7 +131,6 @@ class CyclicAliasException extends InvalidArgumentException
/**
* @param bool[][] $detectedCycles
*
* @return bool[][] de-duplicated
*/
private static function deDuplicateDetectedCycles(array $detectedCycles)
@@ -126,11 +142,9 @@ class CyclicAliasException extends InvalidArgumentException
sort($cycleAliases);
$hash = serialize(array_values($cycleAliases));
$hash = serialize($cycleAliases);
$detectedCyclesByHash[$hash] = isset($detectedCyclesByHash[$hash])
? $detectedCyclesByHash[$hash]
: $detectedCycle;
$detectedCyclesByHash[$hash] ??= $detectedCycle;
}
return array_values($detectedCyclesByHash);

View File

@@ -1,18 +1,14 @@
<?php
/**
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
*/
declare(strict_types=1);
namespace Laminas\ServiceManager\Exception;
use Interop\Container\Exception\ContainerException;
use Psr\Container\ContainerExceptionInterface;
/**
* Base exception for all Laminas\ServiceManager exceptions.
*/
interface ExceptionInterface extends ContainerException
interface ExceptionInterface extends ContainerExceptionInterface
{
}

View File

@@ -1,18 +1,46 @@
<?php
/**
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
*/
declare(strict_types=1);
namespace Laminas\ServiceManager\Exception;
use InvalidArgumentException as SplInvalidArgumentException;
use Laminas\ServiceManager\AbstractFactoryInterface;
use Laminas\ServiceManager\Initializer\InitializerInterface;
use function get_class;
use function gettype;
use function is_object;
use function sprintf;
/**
* @inheritDoc
*/
class InvalidArgumentException extends SplInvalidArgumentException implements ExceptionInterface
{
/**
* @param mixed $initializer
*/
public static function fromInvalidInitializer($initializer): self
{
return new self(sprintf(
'An invalid initializer was registered. Expected a callable or an'
. ' instance of "%s"; received "%s"',
InitializerInterface::class,
is_object($initializer) ? get_class($initializer) : gettype($initializer)
));
}
/**
* @param mixed $abstractFactory
*/
public static function fromInvalidAbstractFactory($abstractFactory): self
{
return new self(sprintf(
'An invalid abstract factory was registered. Expected an instance of or a valid'
. ' class name resolving to an implementation of "%s", but "%s" was received.',
AbstractFactoryInterface::class,
is_object($abstractFactory) ? get_class($abstractFactory) : gettype($abstractFactory)
));
}
}

View File

@@ -1,10 +1,6 @@
<?php
/**
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
*/
declare(strict_types=1);
namespace Laminas\ServiceManager\Exception;

View File

@@ -1,14 +1,9 @@
<?php
/**
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
*/
declare(strict_types=1);
namespace Laminas\ServiceManager\Exception;
use Interop\Container\Exception\ContainerException;
use RuntimeException as SplRuntimeException;
/**
@@ -16,7 +11,6 @@ use RuntimeException as SplRuntimeException;
* the service (factory that has an error...)
*/
class ServiceNotCreatedException extends SplRuntimeException implements
ContainerException,
ExceptionInterface
{
}

View File

@@ -1,15 +1,11 @@
<?php
/**
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
*/
declare(strict_types=1);
namespace Laminas\ServiceManager\Exception;
use Interop\Container\Exception\NotFoundException;
use InvalidArgumentException as SplInvalidArgumentException;
use Psr\Container\NotFoundExceptionInterface;
/**
* This exception is thrown when the service locator do not manage to find a
@@ -17,6 +13,6 @@ use InvalidArgumentException as SplInvalidArgumentException;
*/
class ServiceNotFoundException extends SplInvalidArgumentException implements
ExceptionInterface,
NotFoundException
NotFoundExceptionInterface
{
}

View File

@@ -1,14 +1,10 @@
<?php
/**
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
*/
declare(strict_types=1);
namespace Laminas\ServiceManager\Factory;
use Interop\Container\ContainerInterface;
use Psr\Container\ContainerInterface;
/**
* Interface for an abstract factory.
@@ -25,7 +21,6 @@ interface AbstractFactoryInterface extends FactoryInterface
/**
* Can the factory create an instance for the service?
*
* @param ContainerInterface $container
* @param string $requestedName
* @return bool
*/

View File

@@ -1,17 +1,13 @@
<?php
/**
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
*/
declare(strict_types=1);
namespace Laminas\ServiceManager\Factory;
use Interop\Container\ContainerInterface;
use Interop\Container\Exception\ContainerException;
use Laminas\ServiceManager\Exception\ServiceNotCreatedException;
use Laminas\ServiceManager\Exception\ServiceNotFoundException;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\ContainerInterface;
/**
* Delegator factory interface.
@@ -26,15 +22,13 @@ interface DelegatorFactoryInterface
/**
* A factory that creates delegates of a given service
*
* @param ContainerInterface $container
* @param string $name
* @param callable $callback
* @psalm-param callable():mixed $callback
* @param null|array $options
* @return object
* @throws ServiceNotFoundException if unable to resolve the service.
* @throws ServiceNotCreatedException if an exception is raised when
* creating a service.
* @throws ContainerException if any other error occurs
* @throws ServiceNotFoundException If unable to resolve the service.
* @throws ServiceNotCreatedException If an exception is raised when creating a service.
* @throws ContainerExceptionInterface If any other error occurs.
*/
public function __invoke(ContainerInterface $container, $name, callable $callback, array $options = null);
public function __invoke(ContainerInterface $container, $name, callable $callback, ?array $options = null);
}

View File

@@ -1,17 +1,13 @@
<?php
/**
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
*/
declare(strict_types=1);
namespace Laminas\ServiceManager\Factory;
use Interop\Container\ContainerInterface;
use Interop\Container\Exception\ContainerException;
use Laminas\ServiceManager\Exception\ServiceNotCreatedException;
use Laminas\ServiceManager\Exception\ServiceNotFoundException;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\ContainerInterface;
/**
* Interface for a factory
@@ -26,14 +22,12 @@ interface FactoryInterface
/**
* Create an object
*
* @param ContainerInterface $container
* @param string $requestedName
* @param null|array $options
* @param null|array<mixed> $options
* @return object
* @throws ServiceNotFoundException if unable to resolve the service.
* @throws ServiceNotCreatedException if an exception is raised when
* creating a service.
* @throws ContainerException if any other error occurs
* @throws ServiceNotFoundException If unable to resolve the service.
* @throws ServiceNotCreatedException If an exception is raised when creating a service.
* @throws ContainerExceptionInterface If any other error occurs.
*/
public function __invoke(ContainerInterface $container, $requestedName, array $options = null);
public function __invoke(ContainerInterface $container, $requestedName, ?array $options = null);
}

View File

@@ -1,14 +1,10 @@
<?php
/**
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
*/
declare(strict_types=1);
namespace Laminas\ServiceManager\Factory;
use Interop\Container\ContainerInterface;
use Psr\Container\ContainerInterface;
/**
* Factory for instantiating classes with no dependencies or which accept a single array.
@@ -26,8 +22,8 @@ final class InvokableFactory implements FactoryInterface
/**
* {@inheritDoc}
*/
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
public function __invoke(ContainerInterface $container, $requestedName, ?array $options = null)
{
return (null === $options) ? new $requestedName : new $requestedName($options);
return null === $options ? new $requestedName() : new $requestedName($options);
}
}

View File

@@ -1,10 +1,6 @@
<?php
/**
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
*/
declare(strict_types=1);
namespace Laminas\ServiceManager;
@@ -17,7 +13,7 @@ namespace Laminas\ServiceManager;
*
* - rename the method `createService()` to `__invoke()`, and:
* - rename the `$serviceLocator` argument to `$container`, and change the
* typehint to `Interop\Container\ContainerInterface`
* typehint to `Psr\Container\ContainerInterface`
* - add the `$requestedName` as a second argument
* - add the optional `array $options = null` argument as a final argument
* - create a `createService()` method as defined in this interface, and have it
@@ -34,7 +30,6 @@ interface FactoryInterface extends Factory\FactoryInterface
/**
* Create service
*
* @param ServiceLocatorInterface $serviceLocator
* @return mixed
*/
public function createService(ServiceLocatorInterface $serviceLocator);

View File

@@ -1,14 +1,10 @@
<?php
/**
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
*/
declare(strict_types=1);
namespace Laminas\ServiceManager\Initializer;
use Interop\Container\ContainerInterface;
use Psr\Container\ContainerInterface;
/**
* Interface for an initializer
@@ -21,7 +17,6 @@ interface InitializerInterface
/**
* Initialize the given instance
*
* @param ContainerInterface $container
* @param object $instance
* @return void
*/

View File

@@ -1,10 +1,6 @@
<?php
/**
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
*/
declare(strict_types=1);
namespace Laminas\ServiceManager;
@@ -17,7 +13,7 @@ namespace Laminas\ServiceManager;
*
* - rename the method `initialize()` to `__invoke()`, and:
* - rename the `$serviceLocator` argument to `$container`, and change the
* typehint to `Interop\Container\ContainerInterface`
* typehint to `Psr\Container\ContainerInterface`
* - swap the order of the arguments (so that `$instance` comes second)
* - create an `initialize()` method as defined in this interface, and have it
* proxy to `__invoke()`, passing the arguments in the new order.
@@ -33,8 +29,7 @@ interface InitializerInterface extends Initializer\InitializerInterface
/**
* Initialize
*
* @param $instance
* @param ServiceLocatorInterface $serviceLocator
* @param mixed $instance
* @return mixed
*/
public function initialize($instance, ServiceLocatorInterface $serviceLocator);

View File

@@ -1,31 +1,30 @@
<?php
/**
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
*/
declare(strict_types=1);
namespace Laminas\ServiceManager;
use Interop\Container\Exception\ContainerException;
use Laminas\ServiceManager\Exception\InvalidServiceException;
use Psr\Container\ContainerExceptionInterface;
/**
* Interface for a plugin manager
*
* A plugin manager is a specialized service locator used to create homogeneous objects
*
* @template InstanceType
*/
interface PluginManagerInterface extends ServiceLocatorInterface
{
/**
* Validate an instance
*
* @param object $instance
* @param mixed $instance
* @return void
* @throws InvalidServiceException If created instance does not respect the
* constraint on type imposed by the plugin manager
* @throws ContainerException if any other error occurs
* constraint on type imposed by the plugin manager.
* @throws ContainerExceptionInterface If any other error occurs.
* @psalm-assert InstanceType $instance
*/
public function validate($instance);
}

View File

@@ -1,18 +1,17 @@
<?php
/**
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
*/
declare(strict_types=1);
namespace Laminas\ServiceManager\Proxy;
use Interop\Container\ContainerInterface;
use Laminas\ServiceManager\Exception;
use Laminas\ServiceManager\Factory\DelegatorFactoryInterface;
use ProxyManager\Factory\LazyLoadingValueHolderFactory;
use ProxyManager\Proxy\LazyLoadingInterface;
use ProxyManager\Proxy\VirtualProxyInterface;
use Psr\Container\ContainerInterface;
use function sprintf;
/**
* Delegator factory responsible of instantiating lazy loading value holder proxies of
@@ -22,20 +21,14 @@ use ProxyManager\Proxy\LazyLoadingInterface;
*/
final class LazyServiceFactory implements DelegatorFactoryInterface
{
/**
* @var \ProxyManager\Factory\LazyLoadingValueHolderFactory
*/
private $proxyFactory;
private LazyLoadingValueHolderFactory $proxyFactory;
/** @var array<string, class-string> map of service names to class names */
private array $servicesMap;
/**
* @var string[] map of service names to class names
*/
private $servicesMap;
/**
* @param LazyLoadingValueHolderFactory $proxyFactory
* @param string[] $servicesMap a map of service names to class names of their
* respective classes
* @param array<string, class-string> $servicesMap A map of service names to
* class names of their respective classes
*/
public function __construct(LazyLoadingValueHolderFactory $proxyFactory, array $servicesMap)
{
@@ -46,9 +39,10 @@ final class LazyServiceFactory implements DelegatorFactoryInterface
/**
* {@inheritDoc}
*
* @return \ProxyManager\Proxy\VirtualProxyInterface
* @param string $name
* @return VirtualProxyInterface
*/
public function __invoke(ContainerInterface $container, $name, callable $callback, array $options = null)
public function __invoke(ContainerInterface $container, $name, callable $callback, ?array $options = null)
{
if (isset($this->servicesMap[$name])) {
$initializer = function (&$wrappedInstance, LazyLoadingInterface $proxy) use ($callback) {

View File

@@ -1,52 +0,0 @@
<?php
/**
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
*/
namespace Laminas\ServiceManager;
use Interop\Container\ContainerInterface;
use Psr\Container\ContainerInterface as PsrContainerInterface;
/**
* @internal for use in abstract plugin manager
*/
final class PsrContainerDecorator implements ContainerInterface
{
/**
* @var PsrContainerInterface
*/
private $container;
public function __construct(PsrContainerInterface $container)
{
$this->container = $container;
}
/**
* {@inheritdoc}
*/
public function get($id)
{
return $this->container->get($id);
}
/**
* {@inheritdoc}
*/
public function has($id)
{
return $this->container->has($id);
}
/**
* @return PsrContainerInterface
*/
public function getContainer()
{
return $this->container;
}
}

View File

@@ -1,35 +1,30 @@
<?php
/**
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
*/
declare(strict_types=1);
namespace Laminas\ServiceManager;
use Interop\Container\ContainerInterface as InteropContainerInterface;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\ContainerInterface as PsrContainerInterface;
use Psr\Container\ContainerInterface;
/**
* Interface for service locator
*/
interface ServiceLocatorInterface extends
PsrContainerInterface,
InteropContainerInterface
interface ServiceLocatorInterface extends ContainerInterface
{
/**
* Build a service by its name, using optional options (such services are NEVER cached).
*
* @param string $name
* @param null|array $options
* @template T of object
* @param string|class-string<T> $name
* @param null|array<mixed> $options
* @return mixed
* @psalm-return ($name is class-string ? T : mixed)
* @throws Exception\ServiceNotFoundException If no factory/abstract
* factory could be found to create the instance.
* @throws Exception\ServiceNotCreatedException If factory/delegator fails
* to create the instance.
* @throws ContainerExceptionInterface if any other error occurs
* @throws ContainerExceptionInterface If any other error occurs.
*/
public function build($name, array $options = null);
public function build($name, ?array $options = null);
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,23 +1,33 @@
<?php
/**
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
*/
declare(strict_types=1);
namespace Laminas\ServiceManager\Tool;
use Interop\Container\ContainerInterface;
use Laminas\ServiceManager\AbstractFactory\ConfigAbstractFactory;
use Laminas\ServiceManager\Exception\InvalidArgumentException;
use Psr\Container\ContainerInterface;
use ReflectionClass;
use ReflectionParameter;
use Traversable;
use function array_filter;
use function array_key_exists;
use function class_exists;
use function date;
use function gettype;
use function implode;
use function interface_exists;
use function is_array;
use function is_int;
use function is_string;
use function sprintf;
use function str_repeat;
use function var_export;
class ConfigDumper
{
const CONFIG_TEMPLATE = <<<EOC
public const CONFIG_TEMPLATE = <<<EOC
<?php
/**
@@ -28,15 +38,9 @@ class ConfigDumper
return %s;
EOC;
/**
* @var ContainerInterface
*/
private $container;
private ?ContainerInterface $container;
/**
* @param ContainerInterface $container
*/
public function __construct(ContainerInterface $container = null)
public function __construct(?ContainerInterface $container = null)
{
$this->container = $container;
}
@@ -46,7 +50,7 @@ EOC;
* @param string $className
* @param bool $ignoreUnresolved
* @return array
* @throws InvalidArgumentException for invalid $className
* @throws InvalidArgumentException For invalid $className.
*/
public function createDependencyConfig(array $config, $className, $ignoreUnresolved = false)
{
@@ -67,9 +71,7 @@ EOC;
$constructorArguments = $reflectionClass->getConstructor()->getParameters();
$constructorArguments = array_filter(
$constructorArguments,
function (ReflectionParameter $argument) {
return ! $argument->isOptional();
}
static fn(ReflectionParameter $argument): bool => ! $argument->isOptional()
);
// has no required parameters, treat it as an invokable
@@ -80,8 +82,10 @@ EOC;
$classConfig = [];
foreach ($constructorArguments as $constructorArgument) {
$argumentType = $constructorArgument->getClass();
if (is_null($argumentType)) {
$type = $constructorArgument->getType();
$argumentType = null !== $type && ! $type->isBuiltin() ? $type->getName() : null;
if ($argumentType === null) {
if ($ignoreUnresolved) {
// don't throw an exception, just return the previous config
return $config;
@@ -96,9 +100,8 @@ EOC;
$constructorArgument->getName()
));
}
$argumentName = $argumentType->getName();
$config = $this->createDependencyConfig($config, $argumentName, $ignoreUnresolved);
$classConfig[] = $argumentName;
$config = $this->createDependencyConfig($config, $argumentType, $ignoreUnresolved);
$classConfig[] = $argumentType;
}
$config[ConfigAbstractFactory::class][$className] = $classConfig;
@@ -107,8 +110,8 @@ EOC;
}
/**
* @param $className
* @throws InvalidArgumentException if class name is not a string or does
* @param string $className
* @throws InvalidArgumentException If class name is not a string or does
* not exist.
*/
private function validateClassName($className)
@@ -136,7 +139,7 @@ EOC;
/**
* @param array $config
* @return array
* @throws InvalidArgumentException if ConfigAbstractFactory configuration
* @throws InvalidArgumentException If ConfigAbstractFactory configuration
* value is not an array.
*/
public function createFactoryMappingsFromConfig(array $config)
@@ -168,7 +171,8 @@ EOC;
{
$this->validateClassName($className);
if (array_key_exists('service_manager', $config)
if (
array_key_exists('service_manager', $config)
&& array_key_exists('factories', $config['service_manager'])
&& array_key_exists($className, $config['service_manager']['factories'])
) {
@@ -188,7 +192,7 @@ EOC;
$prepared = $this->prepareConfig($config);
return sprintf(
self::CONFIG_TEMPLATE,
get_class($this),
static::class,
date('Y-m-d H:i:s'),
$prepared
);
@@ -201,10 +205,10 @@ EOC;
*/
private function prepareConfig($config, $indentLevel = 1)
{
$indent = str_repeat(' ', $indentLevel * 4);
$indent = str_repeat(' ', $indentLevel * 4);
$entries = [];
foreach ($config as $key => $value) {
$key = $this->createConfigKey($key);
$key = $this->createConfigKey($key);
$entries[] = sprintf(
'%s%s%s,',
$indent,

View File

@@ -1,25 +1,50 @@
<?php
/**
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
*/
declare(strict_types=1);
namespace Laminas\ServiceManager\Tool;
use Laminas\ServiceManager\Exception;
use Laminas\Stdlib\ConsoleHelper;
use function array_shift;
use function class_exists;
use function dirname;
use function file_exists;
use function file_put_contents;
use function in_array;
use function is_array;
use function is_writable;
use function sprintf;
use const STDERR;
use const STDOUT;
/**
* @psalm-type HelpObject = object{
* command: string
* }
* @psalm-type ErrorObject = object{
* command: string,
* message: string
* }
* @psalm-type ArgumentObject = object{
* command: string,
* configFile: string,
* config: array<array-key, mixed>,
* class: string,
* ignoreUnresolved: bool
* }
*/
class ConfigDumperCommand
{
const COMMAND_DUMP = 'dump';
const COMMAND_ERROR = 'error';
const COMMAND_HELP = 'help';
public const COMMAND_DUMP = 'dump';
public const COMMAND_ERROR = 'error';
public const COMMAND_HELP = 'help';
const DEFAULT_SCRIPT_NAME = __CLASS__;
public const DEFAULT_SCRIPT_NAME = self::class;
const HELP_TEMPLATE = <<< EOH
public const HELP_TEMPLATE = <<<EOH
<info>Usage:</info>
%s [-h|--help|help] [-i|--ignore-unresolved] <configFile> <className>
@@ -41,23 +66,17 @@ and injects it with ConfigAbstractFactory dependency configuration for
the provided class name, writing the changes back to the file.
EOH;
/**
* @var ConsoleHelper
*/
private $helper;
private ConsoleHelper $helper;
/**
* @var string
*/
private $scriptName;
private string $scriptName;
/**
* @param string $scriptName
*/
public function __construct($scriptName = self::DEFAULT_SCRIPT_NAME, ConsoleHelper $helper = null)
public function __construct($scriptName = self::DEFAULT_SCRIPT_NAME, ?ConsoleHelper $helper = null)
{
$this->scriptName = $scriptName;
$this->helper = $helper ?: new ConsoleHelper();
$this->helper = $helper ?: new ConsoleHelper();
}
/**
@@ -110,11 +129,11 @@ EOH;
/**
* @param array $args
* @return \stdClass
* @return object
*/
private function parseArgs(array $args)
{
if (! count($args)) {
if (! $args) {
return $this->createHelpArgument();
}
@@ -127,10 +146,10 @@ EOH;
$ignoreUnresolved = false;
if (in_array($arg1, ['-i', '--ignore-unresolved'], true)) {
$ignoreUnresolved = true;
$arg1 = array_shift($args);
$arg1 = array_shift($args);
}
if (! count($args)) {
if (! $args) {
return $this->createErrorArgument('Missing class name');
}
@@ -192,7 +211,7 @@ EOH;
* @param array $config Parsed configuration.
* @param string $class Name of class to reflect.
* @param bool $ignoreUnresolved If to ignore classes with unresolved direct dependencies.
* @return \stdClass
* @return ArgumentObject
*/
private function createArguments($command, $configFile, $config, $class, $ignoreUnresolved)
{
@@ -207,7 +226,7 @@ EOH;
/**
* @param string $message
* @return \stdClass
* @return ErrorObject
*/
private function createErrorArgument($message)
{
@@ -218,7 +237,7 @@ EOH;
}
/**
* @return \stdClass
* @return HelpObject
*/
private function createHelpArgument()
{

View File

@@ -1,43 +1,59 @@
<?php
/**
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
*/
declare(strict_types=1);
namespace Laminas\ServiceManager\Tool;
use Laminas\ServiceManager\Exception\InvalidArgumentException;
use Laminas\ServiceManager\Factory\FactoryInterface;
use Psr\Container\ContainerInterface;
use ReflectionClass;
use ReflectionParameter;
use function array_filter;
use function array_map;
use function array_merge;
use function array_shift;
use function count;
use function implode;
use function preg_replace;
use function sort;
use function sprintf;
use function str_repeat;
use function strrpos;
use function substr;
class FactoryCreator
{
const FACTORY_TEMPLATE = <<<'EOT'
<?php
public const FACTORY_TEMPLATE = <<<'EOT'
<?php
namespace %s;
declare(strict_types=1);
use Interop\Container\ContainerInterface;
use Laminas\ServiceManager\Factory\FactoryInterface;
use %s;
namespace %s;
class %sFactory implements FactoryInterface
{
/**
* @param ContainerInterface $container
* @param string $requestedName
* @param null|array $options
* @return %s
*/
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
return new %s(%s);
}
}
%s
EOT;
class %sFactory implements FactoryInterface
{
/**
* @param ContainerInterface $container
* @param string $requestedName
* @param null|array $options
* @return %s
*/
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
return new %s(%s);
}
}
EOT;
private const IMPORT_ALWAYS = [
FactoryInterface::class,
ContainerInterface::class,
];
/**
* @param string $className
@@ -49,8 +65,8 @@ EOT;
return sprintf(
self::FACTORY_TEMPLATE,
str_replace('\\' . $class, '', $className),
$className,
preg_replace('/\\\\' . $class . '$/', '', $className),
$this->createImportStatements($className),
$class,
$class,
$class,
@@ -58,14 +74,9 @@ EOT;
);
}
/**
* @param $className
* @return string
*/
private function getClassName($className)
private function getClassName(string $className): string
{
$class = substr($className, strrpos($className, '\\') + 1);
return $class;
return substr($className, strrpos($className, '\\') + 1);
}
/**
@@ -76,7 +87,7 @@ EOT;
{
$reflectionClass = new ReflectionClass($className);
if (! $reflectionClass || ! $reflectionClass->getConstructor()) {
if (! $reflectionClass->getConstructor()) {
return [];
}
@@ -88,12 +99,15 @@ EOT;
$constructorParameters = array_filter(
$constructorParameters,
function (ReflectionParameter $argument) {
function (ReflectionParameter $argument): bool {
if ($argument->isOptional()) {
return false;
}
if (null === $argument->getClass()) {
$type = $argument->getType();
$class = null !== $type && ! $type->isBuiltin() ? $type->getName() : null;
if (null === $class) {
throw new InvalidArgumentException(sprintf(
'Cannot identify type for constructor argument "%s"; '
. 'no type hint, or non-class/interface type hint',
@@ -109,8 +123,9 @@ EOT;
return [];
}
return array_map(function (ReflectionParameter $parameter) {
return $parameter->getClass()->getName();
return array_map(function (ReflectionParameter $parameter): ?string {
$type = $parameter->getType();
return null !== $type && ! $type->isBuiltin() ? $type->getName() : null;
}, $constructorParameters);
}
@@ -120,9 +135,8 @@ EOT;
*/
private function createArgumentString($className)
{
$arguments = array_map(function ($dependency) {
return sprintf('$container->get(\\%s::class)', $dependency);
}, $this->getConstructorParameters($className));
$arguments = array_map(fn(string $dependency): string
=> sprintf('$container->get(\\%s::class)', $dependency), $this->getConstructorParameters($className));
switch (count($arguments)) {
case 0:
@@ -131,7 +145,7 @@ EOT;
return array_shift($arguments);
default:
$argumentPad = str_repeat(' ', 12);
$closePad = str_repeat(' ', 8);
$closePad = str_repeat(' ', 8);
return sprintf(
"\n%s%s\n%s",
$argumentPad,
@@ -140,4 +154,11 @@ EOT;
);
}
}
private function createImportStatements(string $className): string
{
$imports = array_merge(self::IMPORT_ALWAYS, [$className]);
sort($imports);
return implode("\n", array_map(static fn(string $import): string => sprintf('use %s;', $import), $imports));
}
}

View File

@@ -1,25 +1,34 @@
<?php
/**
* @see https://github.com/laminas/laminas-servicemanager for the canonical source repository
* @copyright https://github.com/laminas/laminas-servicemanager/blob/master/COPYRIGHT.md
* @license https://github.com/laminas/laminas-servicemanager/blob/master/LICENSE.md New BSD License
*/
declare(strict_types=1);
namespace Laminas\ServiceManager\Tool;
use Laminas\ServiceManager\Exception;
use Laminas\Stdlib\ConsoleHelper;
use function array_shift;
use function assert;
use function class_exists;
use function in_array;
use function is_string;
use function sprintf;
use const STDERR;
use const STDOUT;
/**
* @psalm-type ArgumentObject = object{command:string, class:null|string, message:null|string}
*/
class FactoryCreatorCommand
{
const COMMAND_DUMP = 'dump';
const COMMAND_ERROR = 'error';
const COMMAND_HELP = 'help';
public const COMMAND_DUMP = 'dump';
public const COMMAND_ERROR = 'error';
public const COMMAND_HELP = 'help';
const DEFAULT_SCRIPT_NAME = __CLASS__;
public const DEFAULT_SCRIPT_NAME = self::class;
const HELP_TEMPLATE = <<< EOH
public const HELP_TEMPLATE = <<<EOH
<info>Usage:</info>
%s [-h|--help|help] <className>
@@ -34,24 +43,17 @@ Generates to STDOUT a factory for creating the specified class; this may then
be added to your application, and configured as a factory for the class.
EOH;
/**
* @var ConsoleHelper
*/
private $helper;
private ConsoleHelper $helper;
/**
* @var string
*/
private $scriptName;
private string $scriptName;
/**
* @param string $scriptName
* @param ConsoleHelper $helper
*/
public function __construct($scriptName = self::DEFAULT_SCRIPT_NAME, ConsoleHelper $helper = null)
public function __construct($scriptName = self::DEFAULT_SCRIPT_NAME, ?ConsoleHelper $helper = null)
{
$this->scriptName = $scriptName;
$this->helper = $helper ?: new ConsoleHelper();
$this->helper = $helper ?: new ConsoleHelper();
}
/**
@@ -67,6 +69,7 @@ EOH;
$this->help();
return 0;
case self::COMMAND_ERROR:
assert(is_string($arguments->message));
$this->helper->writeErrorMessage($arguments->message);
$this->help(STDERR);
return 1;
@@ -77,6 +80,7 @@ EOH;
}
$generator = new FactoryCreator();
assert(is_string($arguments->class));
try {
$factory = $generator->createFactory($arguments->class);
} catch (Exception\InvalidArgumentException $e) {
@@ -95,11 +99,11 @@ EOH;
/**
* @param array $args
* @return \stdClass
* @return ArgumentObject
*/
private function parseArgs(array $args)
{
if (! count($args)) {
if (! $args) {
return $this->createArguments(self::COMMAND_HELP);
}
@@ -137,7 +141,7 @@ EOH;
* @param string $command
* @param string|null $class Name of class to reflect.
* @param string|null $error Error message, if any.
* @return \stdClass
* @return ArgumentObject
*/
private function createArguments($command, $class = null, $error = null)
{

View File

@@ -0,0 +1,21 @@
<?php // phpcs:disable WebimpressCodingStandard.PHP.CorrectClassNameCase.Invalid
declare(strict_types=1);
use Interop\Container\Containerinterface as InteropContainerInterface;
use Interop\Container\Exception\ContainerException as InteropContainerException;
use Interop\Container\Exception\NotFoundException as InteropNotFoundException;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\ContainerInterface;
use Psr\Container\NotFoundExceptionInterface;
if (! interface_exists(InteropContainerInterface::class, false)) {
class_alias(ContainerInterface::class, InteropContainerInterface::class);
}
if (! interface_exists(InteropContainerException::class, false)) {
class_alias(ContainerExceptionInterface::class, InteropContainerException::class);
}
if (! interface_exists(InteropNotFoundException::class, false)) {
class_alias(NotFoundExceptionInterface::class, InteropNotFoundException::class);
}