Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed #288, auto generated form types now have unique service name. #292

Merged
merged 3 commits into from
Jun 2, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions DependencyInjection/AdmingeneratorGeneratorExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,8 @@ private function registerGeneratedFormsAsServices(ContainerBuilder $container)
private function registerFormsServicesFromGenerator(array $generatorParameters, array $builders, ContainerBuilder $container)
{
$modelParts = explode('\\', $generatorParameters['model']);
$model = array_pop($modelParts);
$model = strtolower(array_pop($modelParts)); // @TODO: BC Support, remove it starting from v.3.0.0
$fullQualifiedNormalizedModelName = strtolower(str_replace('\\', '_', ltrim($generatorParameters['model'], '\\')));
$formsBundleNamespace = sprintf(
'%s%s\\Form\\Type\\%s',
$generatorParameters['namespace_prefix'] ? $generatorParameters['namespace_prefix'] . '\\' : '',
Expand All @@ -284,7 +285,8 @@ private function registerFormsServicesFromGenerator(array $generatorParameters,
->addMethodCall('setAuthorizationChecker', array($authorizationCheckerServiceReference))
->addTag('form.type');

$container->setDefinition('admingen_generator_' . strtolower($model) . '_new', $newDefinition);
$container->setDefinition(($id = 'admingen_generator_' . $fullQualifiedNormalizedModelName . '_new'), $newDefinition);
$container->setAlias('admingen_generator_' . $model . '_new', $id);
}

if (in_array('edit', $builders)) {
Expand All @@ -293,7 +295,8 @@ private function registerFormsServicesFromGenerator(array $generatorParameters,
->addMethodCall('setAuthorizationChecker', array($authorizationCheckerServiceReference))
->addTag('form.type');

$container->setDefinition('admingen_generator_' . strtolower($model) . '_edit', $editDefinition);
$container->setDefinition(($id = 'admingen_generator_' . $fullQualifiedNormalizedModelName . '_edit'), $editDefinition);
$container->setAlias('admingen_generator_' . $model . '_edit', $id);
}

if (in_array('list', $builders) || in_array('nested_list', $builders)) {
Expand All @@ -302,7 +305,8 @@ private function registerFormsServicesFromGenerator(array $generatorParameters,
->addMethodCall('setAuthorizationChecker', array($authorizationCheckerServiceReference))
->addTag('form.type');

$container->setDefinition('admingen_generator_' . strtolower($model) . '_filter', $filterDefinition);
$container->setDefinition(($id = 'admingen_generator_' . $fullQualifiedNormalizedModelName . '_filter'), $filterDefinition);
$container->setAlias('admingen_generator_' . $model . '_filter', $id);
}
}

Expand Down
98 changes: 98 additions & 0 deletions Resources/doc/cookbook/inject-services-into-form-types.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# Inject services into form types

Sometimes it will be necessary for you to injecting additional services
into generated form types.

GeneratorBundle registers all generated form types into service container
within bundle extension
(see `\Admingenerator\GeneratorBundle\DependencyInjection\AdmingeneratorGeneratorExtension::registerFormsServicesFromGenerator()`
for implementation details).

Form types service names are generated according to the following pattern:
- For **NewType**: `admingen_generator_[UNDERSCORED_MODEL_FQCN]_new`
- For **EditType**: `admingen_generator_[UNDERSCORED_MODEL_FQCN]_new`
- For **FiltersType**: `admingen_generator_[UNDERSCORED_MODEL_FQCN]_filter`

Illustrative example to understand service name pattern: if model type FQCN
is `\My\Example\Entity`, generated form type service name for new type
would be: `admingen_generator_my_example_entity_new`.

All auto-registered form type services contains proper service tag `form.type`,
as well as setter definition which injects necessary `security.authorization_checker`
service.

**BC NOTE:** *Up to version 2.1.1 service names were generated by using
only class name without namespaces. Considering our previous given example,
generated service name would be `admingen_generator_entity_new`. This was
a bug in previous versions, which was fixed for versions above 2.1.1. However,
in order not to inflict BC break, new service name patterns are aliased
with old service names. From version 3.0.0 this BC support will be removed,
you should use new service name pattern rule for referencing your form types
in service container.*

Now, when you are aware of the method of how generated form types are
registered in service container, you are able to modify those service
definitions, and most common use case scenario is to inject additional
dependencies.

Here are two proposed methods:

## Method 1: Create your own compiler pass and modify generated service definition

In your application bundle, you can register your own compiler pass,
require your form type service definition and inject additional services,
example:

class MyAppCompilerPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
if ($container->hasDefinition('admingen_generator_my_example_entity_new')) {
$container
->getDefinition('admingen_generator_my_example_entity_new')
->setArguments( [ UTILIZING CONSTRUCTOR INJECTION ] )
->addMethodCall( [ UTILIZING SETTER INJECTION ] );
}
}
}

This is most preferable way, however, if you have a lot of forms for which
you have to modify service definitions, this can be time consuming.

## Method 2: "Magic" injection by using `runopencode\traitor-bundle` and traits

You can use third party bundle [`runopencode\traitor-bundle`](https://github.com/RunOpenCode/traitor-bundle)
which allows you to inject additional services to your auto-generated
forms with just `use trait` statement in form type class, and mentioned
bundle will take care of injecting appropriate service, example:

namespace MyBundle\Form\Type\MyModel;

use Admingenerated\MyBundle\Form\MyModelType\NewType as BaseNewType

class NewType extends BaseNewType
{
use \Psr\Log\LoggerAwareTrait;
}

In example given above, bundle will figure out that you are requiring for
a `logger` service, which will be injected via setter injection.

This is very easy and productive way to inject additional services into
form types, you do not have to care about generated service names and you
do not have to create your own compiler pass, nor additionally code injection
logic.

However, it is a *"magic"* injection which breaks Symfony convention of
how service injection should be registered.

It is strongly advised to read fully and carefully documentation of
`runopencode\traitor-bundle` before making decision of its usage, authors
have explained in details how bundle works, and what are *"pros"* and
*"cons"* of its usage, so you can make informed decision and choose approach
which suits your needs best.





2 changes: 2 additions & 0 deletions Resources/doc/documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ we encourage you to update to latest build. If you're getting errors or have tro
- [Multiple entity managers (Doctrine)][cookbook-em]
- [View parameters][cookbook-view-parameters]
- [Modal with fields][modal-with-fields]
- [Inject services into form types][inject-services-into-form-types]
5. Support and contribution
- [Submitting issues][support-issues]
- [Contributing code][support-contributing]
Expand Down Expand Up @@ -92,3 +93,4 @@ Below are some screenshots of our very simple demo project.
[cookbook-menu]: cookbook/knp-menu.md
[cookbook-view-parameters]: cookbook/view-parameters.md
[modal-with-fields]: cookbook/modal-with-fields.md
[inject-services-into-form-types]: cookbook/inject-services-into-form-types.md
7 changes: 7 additions & 0 deletions UPGRADE.MD
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@

This page contains all upgrade notes since the release of the stable 2.0.0 version.

## Current `master` branch

- Fixed [#285](https://github.com/symfony2admingenerator/GeneratorBundle/issues/285): added cookbook entry regarding injection
of additional services in form types. Documented method of registration of auto generated form types in service container.
- Fixed [#288](https://github.com/symfony2admingenerator/GeneratorBundle/issues/288): generated form types now have unique
service name. Old naming is aliased to new service name in order not to have BC break.

## 2.1.0

- Fixed [#245](https://github.com/symfony2admingenerator/GeneratorBundle/issues/245): KnpMenuBundle usage is now optional.
Expand Down