Skip to content
This repository was archived by the owner on Jan 30, 2020. It is now read-only.

Commit 707e1ca

Browse files
committed
Merge branch 'hotfix/invokables' into develop
Forward port #67
2 parents 386289d + 13b85d8 commit 707e1ca

15 files changed

+637
-242
lines changed

CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,13 @@ All notable changes to this project will be documented in this file, in reverse
2626

2727
- [#60](https://github.com/zendframework/zend-form/pull/60) adds an alias from
2828
`Zend\Form\FormElementManager` to `FormElementManager` in the `ConfigProvider`.
29+
- [#67](https://github.com/zendframework/zend-form/pull/67) adds polyfills for
30+
the `FormElementManager` to vary its definitions based on the major version of
31+
zend-servicemanager in use. `FormElementManagerFactory` was updated to return
32+
the specific polyfill version, and an autoload rule was added to alias the
33+
class to the correct polyfill version. The polyfills were necessary to ensure
34+
that invokable classes are mapped to the new `ElementFactory` introduced in
35+
the 2.7 series, thus ensuring instantiation is performed correctly.
2936

3037
### Deprecated
3138

@@ -42,6 +49,12 @@ All notable changes to this project will be documented in this file, in reverse
4249
`injectFactory()` and `callElementInit()` are registered as the first and last
4350
initializers, respectively, during construction, restoring the pre-2.7
4451
behavior.
52+
- [#67](https://github.com/zendframework/zend-form/pull/67) fixes the behavior
53+
of `Factory::create()` to the pre-2.7.1 behavior of *not* passing creation
54+
options when retrieving an instance from the `FormElementManager`. This
55+
ensures that options are not passed to Element/Fieldset/Form instances
56+
until after they are fully initialized, ensuring that all dependencies are
57+
present.
4558

4659
## 2.8.1 - 2016-04-18
4760

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
/**
3+
* @link http://github.com/zendframework/zend-form for the canonical source repository
4+
* @copyright Copyright (c) 2005-2016 Zend Technologies USA Inc. (http://www.zend.com)
5+
* @license http://framework.zend.com/license/new-bsd New BSD License
6+
*/
7+
8+
use Zend\Form\FormElementManager;
9+
use Zend\ServiceManager\ServiceManager;
10+
11+
call_user_func(function () {
12+
$target = method_exists(ServiceManager::class, 'configure')
13+
? FormElementManager\FormElementManagerV3Polyfill::class
14+
: FormElementManager\FormElementManagerV2Polyfill::class;
15+
16+
class_alias($target, FormElementManager::class);
17+
});

composer.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@
1010
"autoload": {
1111
"psr-4": {
1212
"Zend\\Form\\": "src/"
13-
}
13+
},
14+
"files": [
15+
"autoload/formElementManagerPolyfill.php"
16+
]
1417
},
1518
"require": {
1619
"php": "^5.5 || ^7.0",

src/Annotation/AnnotationBuilderFactory.php

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use Interop\Container\ContainerInterface;
1111
use Zend\EventManager\EventManagerInterface;
1212
use Zend\EventManager\ListenerAggregateInterface;
13+
use Zend\Form\Factory;
1314
use Zend\ServiceManager\Exception\ServiceNotCreatedException;
1415
use Zend\ServiceManager\FactoryInterface;
1516
use Zend\ServiceManager\ServiceLocatorInterface;
@@ -30,8 +31,7 @@ public function __invoke(ContainerInterface $container, $name, array $options =
3031
$eventManager = $container->get('EventManager');
3132
$annotationBuilder->setEventManager($eventManager);
3233

33-
$formElementManager = $container->get('FormElementManager');
34-
$formElementManager->injectFactory($container, $annotationBuilder);
34+
$this->injectFactory($annotationBuilder->getFormFactory(), $container);
3535

3636
$config = $this->marshalConfig($container);
3737
if (isset($config['preserve_defined_order'])) {
@@ -136,4 +136,22 @@ private function injectListeners(array $config, EventManagerInterface $events, C
136136
$listener->attach($events);
137137
}
138138
}
139+
140+
/**
141+
* Inject the annotation builder's factory instance with the FormElementManager.
142+
*
143+
* Also injects the factory with the InputFilterManager if present.
144+
*
145+
* @param Factory $factory
146+
* @param ContainerInterface $container
147+
*/
148+
private function injectFactory(Factory $factory, ContainerInterface $container)
149+
{
150+
$factory->setFormElementManager($container->get('FormElementManager'));
151+
152+
if ($container->has('InputFilterManager')) {
153+
$inputFilters = $container->get('InputFilterManager');
154+
$factory->getInputFilterFactory()->setInputFilterManager($inputFilters);
155+
}
156+
}
139157
}

src/Factory.php

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -108,12 +108,7 @@ public function create($spec)
108108
$spec = $this->validateSpecification($spec, __METHOD__);
109109
$type = isset($spec['type']) ? $spec['type'] : Element::class;
110110

111-
$creationOptions = [];
112-
if (isset($spec['options']) && is_array($spec['options'])) {
113-
$creationOptions = $spec['options'];
114-
}
115-
116-
$element = $this->getFormElementManager()->get($type, $creationOptions);
111+
$element = $this->getFormElementManager()->get($type);
117112

118113
if ($element instanceof FormInterface) {
119114
return $this->configureForm($element, $spec);
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
<?php
2+
/**
3+
* @link http://github.com/zendframework/zend-form for the canonical source repository
4+
* @copyright Copyright (c) 2005-2016 Zend Technologies USA Inc. (http://www.zend.com)
5+
* @license http://framework.zend.com/license/new-bsd New BSD License
6+
*/
7+
8+
namespace Zend\Form\FormElementManager;
9+
10+
use Zend\Form\Exception;
11+
12+
/**
13+
* Trait providing common logic between FormElementManager implementations.
14+
*
15+
* Trait does not define properties, as the properties common between the
16+
* two versions are originally defined in their parent class, causing a
17+
* resolution conflict.
18+
*/
19+
trait FormElementManagerTrait
20+
{
21+
/**
22+
* Retrieve a service from the manager by name
23+
*
24+
* Allows passing an array of options to use when creating the instance.
25+
* createFromInvokable() will use these and pass them to the instance
26+
* constructor if not null and a non-empty array.
27+
*
28+
* @param string $name
29+
* @param string|array $options
30+
* @param bool $usePeeringServiceManagers
31+
* @return object
32+
*/
33+
public function get($name, $options = [], $usePeeringServiceManagers = true)
34+
{
35+
if (is_string($options)) {
36+
$options = ['name' => $options];
37+
}
38+
return parent::get($name, $options, $usePeeringServiceManagers);
39+
}
40+
41+
/**
42+
* Try to pull hydrator from the creation context, or instantiates it from its name
43+
*
44+
* @param string $hydratorName
45+
* @return mixed
46+
* @throws Exception\DomainException
47+
*/
48+
public function getHydratorFromName($hydratorName)
49+
{
50+
$services = isset($this->creationContext)
51+
? $this->creationContext // v3
52+
: $this->serviceLocator; // v2
53+
54+
if ($services && $services->has('HydratorManager')) {
55+
$hydrators = $services->get('HydratorManager');
56+
if ($hydrators->has($hydratorName)) {
57+
return $hydrators->get($hydratorName);
58+
}
59+
}
60+
61+
if ($services && $services->has($hydratorName)) {
62+
return $services->get($hydratorName);
63+
}
64+
65+
if (! class_exists($hydratorName)) {
66+
throw new Exception\DomainException(sprintf(
67+
'Expects string hydrator name to be a valid class name; received "%s"',
68+
$hydratorName
69+
));
70+
}
71+
72+
$hydrator = new $hydratorName;
73+
return $hydrator;
74+
}
75+
76+
/**
77+
* Try to pull factory from the creation context, or instantiates it from its name
78+
*
79+
* @param string $factoryName
80+
* @return mixed
81+
* @throws Exception\DomainException
82+
*/
83+
public function getFactoryFromName($factoryName)
84+
{
85+
$services = isset($this->creationContext)
86+
? $this->creationContext // v3
87+
: $this->serviceLocator; // v2
88+
89+
if ($services && $services->has($factoryName)) {
90+
return $services->get($factoryName);
91+
}
92+
93+
if (! class_exists($factoryName)) {
94+
throw new Exception\DomainException(sprintf(
95+
'Expects string factory name to be a valid class name; received "%s"',
96+
$factoryName
97+
));
98+
}
99+
100+
$factory = new $factoryName;
101+
return $factory;
102+
}
103+
}

0 commit comments

Comments
 (0)