-
Notifications
You must be signed in to change notification settings - Fork 2.5k
Form abstract factory #4358
Form abstract factory #4358
Changes from 6 commits
094d6c6
dd3e853
c21e51a
808da5f
9e068d0
eaa7874
94908c8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,154 @@ | ||
<?php | ||
/** | ||
* Zend Framework (http://framework.zend.com/) | ||
* | ||
* @link http://github.com/zendframework/zf2 for the canonical source repository | ||
* @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) | ||
* @license http://framework.zend.com/license/new-bsd New BSD License | ||
*/ | ||
|
||
namespace Zend\Form; | ||
|
||
use Zend\InputFilter\InputFilterInterface; | ||
use Zend\ServiceManager\AbstractFactoryInterface; | ||
use Zend\ServiceManager\ServiceLocatorInterface; | ||
|
||
class FormAbstractFactory implements AbstractFactoryInterface | ||
{ | ||
/** | ||
* @var string Top-level configuration key indicating forms configuration | ||
*/ | ||
protected $configKey = 'form_manager'; | ||
|
||
/** | ||
* @var Factory Form factory used to create forms | ||
*/ | ||
protected $factory; | ||
|
||
/** | ||
* @var string Service prefix necessary for abstract factory to trigger | ||
*/ | ||
protected $servicePrefix = 'Form\\'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What's the reason to force the prefix? IMHO this limit us, e. g. if I want to prefix my forms with the module name. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A prefix helps prevent false positive lookups, and naming collisions. We're On Tuesday, April 30, 2013, Josias Duarte Busiquia wrote:
Matthew Weier O'Phinney There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I vote for removing it, and leave the job for developers, good naming conventions can take of that easily. I say that because at first glance I thought about naming my forms like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not true. You'd still be able to name them that; you'd simply alias them: return array(
'form_manager' => array(
'Foo' => array( /* ... */),
),
'service_manager' => array(
'Form\Foo' => 'MyModule\Form\ContactForm',
),
); Note: completely untested. However, I think that That said, if you're using this functionality, you're creating what is at heart a configuration-driven form. It will either be of the generic type There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I came across this issue because my code breaks when using full names like @wryck7 uses @weierophinney I don't see how aliasing is a simple way to do this. I use full names which very clearly show which class I use in the call, furthermore full names prevent accidental usage of duplicate aliases. Now I am forced to use aliases and make up new names that won't collide with other aliases. In my opinion it's overkill, because my naming was already guaranteed unique because of the full name: I don't know if this code is still used, but my code breaks with full names and only aliasing them fixes this... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @Martin-P The prefix was removed before the release so the full name should be working. Open an issue and detail what you're doing and how it is breaking. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I finally figured out what caused the problem. It was a config file return array(
'di' => array(
),
); It took me many hours to find out what huge problems this small file caused. Is this intended behaviour? If not, I will open an issue for this. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you provide a form configuration that demonstrates this? We did a On Saturday, June 1, 2013, Martin-P wrote:
Matthew Weier O'Phinney There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @weierophinney At that moment I thought I was doing something wrong, but issue #6212 (comment) shows the same issue and reminded me of this issue. It does look like a DI issue after all. |
||
|
||
/** | ||
* Can we create the requested service? | ||
* | ||
* @param ServiceLocatorInterface $services | ||
* @param string $name Service name (as resolved by ServiceManager) | ||
* @param string $rName Name by which service was requested | ||
* @return bool | ||
*/ | ||
public function canCreateServiceWithName(ServiceLocatorInterface $services, $name, $rName) | ||
{ | ||
if (!$services->has('Config')) { | ||
return false; | ||
} | ||
|
||
$prefixLength = strlen($this->servicePrefix); | ||
if (strlen($rName) < $prefixLength | ||
|| substr($rName, 0, $prefixLength) !== $this->servicePrefix | ||
) { | ||
return false; | ||
} | ||
|
||
$config = $services->get('Config'); | ||
if (!isset($config[$this->configKey]) | ||
|| !is_array($config[$this->configKey]) | ||
|| empty($config[$this->configKey]) | ||
) { | ||
return false; | ||
} | ||
|
||
$config = $config[$this->configKey]; | ||
|
||
$serviceName = substr($rName, $prefixLength); | ||
if (!isset($config[$serviceName]) | ||
|| !is_array($config[$serviceName]) | ||
|| empty($config[$serviceName]) | ||
) { | ||
return false; | ||
} | ||
|
||
return true; | ||
} | ||
|
||
/** | ||
* Create a form | ||
* | ||
* @param ServiceLocatorInterface $services | ||
* @param string $name Service name (as resolved by ServiceManager) | ||
* @param string $rName Name by which service was requested | ||
* @return Form | ||
*/ | ||
public function createServiceWithName(ServiceLocatorInterface $services, $name, $rName) | ||
{ | ||
$serviceName = substr($rName, strlen($this->servicePrefix)); | ||
$config = $services->get('Config'); | ||
|
||
$config = $config[$this->configKey][$serviceName]; | ||
|
||
$factory = $this->getFormFactory($services); | ||
$this->marshalInputFilter($config, $services, $factory); | ||
|
||
return $factory->createForm($config); | ||
} | ||
|
||
/** | ||
* Retrieve the form factory, creating it if necessary | ||
* | ||
* @param ServiceLocatorInterface $services | ||
* @return Factory | ||
*/ | ||
protected function getFormFactory(ServiceLocatorInterface $services) | ||
{ | ||
if ($this->factory instanceof Factory) { | ||
return $this->factory; | ||
} | ||
|
||
$elements = null; | ||
if ($services->has('FormElementManager')) { | ||
$elements = $services->get('FormElementManager'); | ||
} | ||
|
||
$this->factory = new Factory($elements); | ||
return $this->factory; | ||
} | ||
|
||
/** | ||
* Marshal the input filter into the configuration | ||
* | ||
* If an input filter is specified: | ||
* - if the InputFilterManager is present, checks if it's there; if so, | ||
* retrieves it and resets the specification to the instance. | ||
* - otherwise, pulls the input filter factory from the form factory, and | ||
* attaches the FilterManager and ValidatorManager to it. | ||
* | ||
* @param array $config | ||
* @param ServiceLocatorInterface $services | ||
* @param Factory $formFactory | ||
*/ | ||
protected function marshalInputFilter(array &$config, ServiceLocatorInterface $services, Factory $formFactory) | ||
{ | ||
if (!isset($config['input_filter'])) { | ||
return; | ||
} | ||
|
||
if ($config['input_filter'] instanceof InputFilterInterface) { | ||
return; | ||
} | ||
|
||
if (is_string($config['input_filter']) | ||
&& $services->has('InputFilterManager') | ||
) { | ||
$inputFilters = $services->get('InputFilterManager'); | ||
if ($inputFilters->has($config['input_filter'])) { | ||
$config['input_filter'] = $inputFilters->get($config['input_filter']); | ||
return; | ||
} | ||
} | ||
|
||
$inputFilterFactory = $formFactory->getInputFilterFactory(); | ||
$inputFilterFactory->getDefaultFilterChain()->setPluginManager($services->get('FilterManager')); | ||
$inputFilterFactory->getDefaultValidatorChain()->setPluginManager($services->get('ValidatorManager')); | ||
} | ||
} |
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
forms
wouldn't make more sense here? Since everything that will go under this key are just forms specifications!?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm ambivalent. I went with something that mirrored the idea of
service_manager.
On Tuesday, April 30, 2013, Josias Duarte Busiquia wrote:
Matthew Weier O'Phinney
matthew@weierophinney.net
http://mwop.net/